Skip to main content
Version: Next
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 parts with mutating method calls like app.page(...) and app.query(...). We called this the TS Config.

Start 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 parts array.

Let an LLM do the heavy lifting

The mapping below is mechanical. You can give the Wasp Spec reference and your old main.wasp.ts to the LLM of your choice and ask it to rewrite it following that reference.

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 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, 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 parts between them, so you can keep large configs 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, ..., parts: [] })
Configuring the appapp.auth(...)
app.server(...)
app.client(...)
app.db(...)
app.emailSender(...)
app.webSocket(...)
app({
auth: ...,
server: ...,
client: ...,
db: ...,
emailSender: ...,
webSocket: ...,
})
Adding app declarationsapp.route(...)
app.query(...)
app.action(...)
etc
app({
parts: [
route(...),
query(...),
action(...),
]
})
Imports{ import, from }import { ... } from "./src/..." with { type: "ref" }
Package namewasp-config@wasp.sh/spec

App and parts

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 assume your project is already on Wasp ^0.24.0. If it isn't, follow the migration guide first.

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": ["main.wasp.ts", "**/*.wasp.ts"]
    }
  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 parts array holds the constructors (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' },
    })
  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.