Skip to main content
Version: 0.24
note

Last checked with Wasp 0.24.

This guide depends on external libraries or services, so it may become outdated over time. We do our best to keep it up to date, but make sure to check their documentation for any changes.

Migrating from the Wasp TS Config

The first version of configuring Wasp in TypeScript used a class-based API: you created an App instance with new App(...) and registered declarations with mutating method calls like app.page(...) and app.query(...). We called this the TS Config.

Starting with Wasp 0.24, the TS Config is now retired in favor of the Wasp Spec: a function-based API where you call app({ ... }) once and list everything in a spec property.

Upgrading from Wasp 0.23 to 0.24?

The conversion below is mechanical, so you can let an LLM do the heavy lifting instead. The migration guide has a copyable prompt bundling this guide, the Wasp Spec docs, and the shared migration steps. Once your config is converted, return to the migration guide for the remaining shared steps.

New featuresโ€‹

Reference importsโ€‹

In the TS Config you could only reference your code with import objects ({ import, from }). The Wasp Spec also supports reference imports: import the value with the regular import syntax and pass it directly to a specification constructor.

main.wasp.ts
const mainPage = app.page("MainPage", {
component: { importDefault: "MainPage", from: "@src/MainPage" },
});

app.query("getTasks", {
fn: { import: "getTasks", from: "@src/queries" },
});

Import objects still work through the ref(...) helper, so you can migrate gradually. See the Wasp Spec documentation for the supported patterns and their limitations.

Multiple filesโ€‹

The TS Config required your entire configuration to live in a single main.wasp.ts. The Wasp Spec lets you split it across multiple *.wasp.ts files and import specifications between them, so you can keep large apps organized (for example, a separate auth.wasp.ts or cards.wasp.ts next to the feature it configures).

See the Wasp Spec documentation for details.

Changesโ€‹

Overviewโ€‹

WhatBeforeAfter
Creating an appnew App(name, { ... });app({ name, ..., spec: [...] });
Configuring the appapp.auth(...);
app.server(...);
app.client(...);
app.db(...);
app.emailSender(...);
app.webSocket(...);
app({
auth: ...,
server: ...,
client: ...,
db: ...,
emailSender: ...,
webSocket: ...,
});
Adding app specificationsapp.route(...);
app.query(...);
app.action(...);
etc
app({
spec: [
route(...),
query(...),
action(...),
]
});
Imports{ import, from }import { ... } from "./src/..." with { type: "ref" };
Package namewasp-config@wasp.sh/spec

App and specificationsโ€‹

main.wasp.ts
import { App } from "wasp-config";

const app = new App("todoApp", {
title: "ToDo App",
wasp: { version: "^0.24.0" },
});

const mainPage = app.page("MainPage", {
component: { importDefault: "MainPage", from: "@src/MainPage" },
});
app.route("MainRoute", { path: "/", to: mainPage });

app.query("getTasks", {
fn: { import: "getTasks", from: "@src/queries" },
entities: ["Task"],
});

export default app;

API: httpRoute becomes positional argumentsโ€‹

main.wasp.ts
app.apiNamespace("bar", {
middlewareConfigFn: { import: "barNamespaceMiddlewareFn", from: "@src/apis" },
path: "/bar",
});

app.api("barBaz", {
fn: { import: "barBaz", from: "@src/apis" },
auth: false,
entities: ["Task"],
httpRoute: { method: "GET", route: "/bar/baz" },
});

Jobs: perform is flattenedโ€‹

main.wasp.ts
app.job("mySpecialJob", {
executor: "PgBoss",
perform: {
fn: { import: "foo", from: "@src/jobs/bar" },
executorOptions: { pgBoss: { retryLimit: 1 } },
},
entities: ["Task"],
});

CRUDโ€‹

main.wasp.ts
app.crud("tasks", {
entity: "Task",
operations: {
getAll: {},
create: { overrideFn: { import: "createTask", from: "@src/actions" } },
},
});

Top-level config: auth, server, client, db, emailSender, webSocketโ€‹

These were configured with mutating method calls. They are now keys of the app({ ... }) object.

main.wasp.ts
const app = new App("todoApp", {
title: "ToDo App",
wasp: { version: "^0.24.0" },
});

app.auth({
userEntity: "User",
methods: { google: {} },
onAuthFailedRedirectTo: "/login",
});

app.client({
rootComponent: { importDefault: "App", from: "@src/App" },
});

app.emailSender({
provider: "SMTP",
defaultFrom: { email: "hi@example.com" },
});

export default app;

How to migrateโ€‹

These steps convert an old class-based Wasp TS Config to the new Wasp Spec. Before running wasp install below, make sure your app's Wasp version is ^0.24.0.

After finishing this guide, return to the migration guide if you still need to complete the shared Wasp 0.24 migration steps.

Wasp validates the Wasp Spec support files during migration, including the required package.json entries, tsconfig.wasp.json options, and tsconfig.src.json exclusions.

  1. Update your package.json with the new dependencies:

    package.json
    {
    // ...
    "devDependencies": {
    // ...
    "wasp-config": "file:.wasp/wasp-config"
    }
    }

    Keep your existing dependencies, replace wasp-config with @wasp.sh/spec, and add @types/node. @types/node is required because the Wasp Spec runs in a Node.js environment.

  2. Update your tsconfig.wasp.json and make sure it includes the following settings:

    tsconfig.wasp.json
    {
    "compilerOptions": {
    "target": "ES2022",
    "module": "esnext",
    "moduleResolution": "bundler",
    "jsx": "preserve",
    "strict": true,
    "isolatedModules": true,
    "moduleDetection": "force",
    "skipLibCheck": true,
    "allowJs": true,
    "noEmit": true,
    "lib": ["ES2023"]
    },
    "include": ["**/*.wasp.ts", ".wasp/out/types/spec"]
    }
  3. Make sure your tsconfig.src.json excludes Wasp Spec files:

    tsconfig.src.json
    {
    // ...
    "include": ["src"],
    "exclude": ["**/*.wasp.ts"]
    }
  4. Run wasp install.

  5. Rewrite main.wasp.ts:

    Replace new App(...) and the app.*(...) method calls with a single app({ ... }) call whose spec property holds the specifications (see the mapping above), and update the import:

    main.wasp.ts
    import { App } from "wasp-config";

    const app = new App("myApp", {
    title: "My app",
    wasp: { version: "^0.24.0" },
    });
    note

    While previously we accepted any *.wasp.ts file name, with the Wasp Spec the entry file must be named main.wasp.ts. You can still split the rest of your config across other *.wasp.ts files.

  6. Run your app with wasp start. If everything is correct, your app should behave exactly as before.

note

At some points, when the Spec needs to be regenerated, Wasp will tell you to run wasp install before being able to start the app. Usually, this might happen when upgrading Wasp versions, running wasp clean, or removing the node_modules folder.

See the full Wasp Spec reference for every option. Got stuck? Reach out on our Discord and we'll help.