Migrations
Seed

Seed migration

From 0.76.0 and above

In this version, we are removing the run function from the generate configuration.

Instead, we're introducing a new package called @snaplet/seed.

We extracted the data client into its own package so you can use it everywhere in your codebase!

Seed scripts or tests, data are now one import away! Let's see how to migrate to it.

First, install the new package:

>_ terminal

npm install -D @snaplet/seed

Like the Prisma Client (opens in a new tab), this package is in fact a proxy to the local data client you will generate with Snaplet CLI based on your database schema.

In order to do that, we repurposed the command snaplet generate to generate the data client! You can now run it.

>_ terminal

npx snaplet generate

It will create a folder containing your data client source code under node_modules/.snaplet. This package is then re-exported by @snaplet/seed.

Now, let's edit your snaplet.config.ts and port your run function to a seed script.

Given this configuration.

snaplet.config.ts

/// <reference path=".snaplet/snaplet.d.ts" />
import { defineConfig } from 'snaplet';
export default defineConfig({
generate: {
alias: {
inflection: true,
},
async run(snaplet) {
await snaplet.users((x) => x(3, () => ({
posts: (x) => x(10),
}))),
},
},
});

  • Copy the content of your run function and remove it.
  • Rename the generate key in your config to seed:
snaplet.config.ts

/// <reference path=".snaplet/snaplet.d.ts" />
import { defineConfig } from 'snaplet';
export default defineConfig({
seed: {
alias: {
inflection: true,
},
},
});

Create a new seed.mts file and import the Snaplet data client.

snaplet.config.ts
seed.mts

import { SnapletClient } from '@snaplet/seed';

Create a new snaplet client instance.

If you were relying on snaplet to clear any existing data from your database first, you now do this explicitly with snaplet.$resetDatabase().

snaplet.config.ts
seed.mts

import { SnapletClient } from '@snaplet/seed';
const snaplet = new SnapletClient();
snaplet.$resetDatabase();

Paste what you copied earlier from your run function.

snaplet.config.ts
seed.mts

import { SnapletClient } from '@snaplet/seed';
const snaplet = new SnapletClient();
snaplet.$resetDatabase();
await snaplet.users((x) => x(3, () => ({
posts: (x) => x(10),
})));

Given this configuration.

  • Copy the content of your run function and remove it.
  • Rename the generate key in your config to seed:

Create a new seed.mts file and import the Snaplet data client.

Create a new snaplet client instance.

If you were relying on snaplet to clear any existing data from your database first, you now do this explicitly with snaplet.$resetDatabase().

Paste what you copied earlier from your run function.

snaplet.config.ts

/// <reference path=".snaplet/snaplet.d.ts" />
import { defineConfig } from 'snaplet';
export default defineConfig({
generate: {
alias: {
inflection: true,
},
async run(snaplet) {
await snaplet.users((x) => x(3, () => ({
posts: (x) => x(10),
}))),
},
},
});

The snaplet data client is automatically connected to your target database defined in either your .snaplet/config.json file or your SNAPLET_TARGET_DATABASE_URL environment variable.

You can now run your seed script with any TypeScript runner like tsx (opens in a new tab) or ts-node (opens in a new tab).

>_ terminal

npx tsx seed.mts

If you were relying on the --sql option to generate a SQL file instead of having the data client writing directly to your database, you can now use the dryRun option in the data client.

seed.mts

import { SnapletClient } from '@snaplet/seed';
const snaplet = new SnapletClient({ dryRun: true });
// With the dryRun option, the data client will output all the SQL queries to stdout.
await snaplet.users((x) => x(3, () => ({
posts: (x) => x(10),
})));

To know more about the data client, check out the documentation.

From 0.66.0 and above

The generate API is evolving! After a great number of feedbacks from the community during the alpha, we decided to make it more flexible and powerful.

The new API is still in beta, but we encourage you to try it out and give us feedbacks.

Here is a step-by-step guide to migrate your existing generate plan to the new API.

You can start by regenerating your types by running:

>_ terminal

snaplet config generate

Now, let's edit your snaplet.config.ts file.

This is what we had before version 0.66.0.

snaplet.config.ts

/// <reference path=".snaplet/snaplet.d.ts" />
import { defineConfig } from 'snaplet';
export default defineConfig({
generate: {
plan({ snaplet }) {
return snaplet.User({
count: 3,
data: {
email: ({ seed }) =>
copycat.email(seed),
Post: {
count: 10,
}
}
}),
},
},
});

Rename plan to run, and make it async. You are no longer required to return a plan. Calling await on a plan will automatically run it.

snaplet.config.ts

/// <reference path=".snaplet/snaplet.d.ts" />
import { defineConfig } from 'snaplet';
export default defineConfig({
generate: {
async run({ snaplet }) {
await snaplet.User({
count: 3,
data: {
email: ({ seed }) =>
copycat.email(seed),
Post: {
count: 10,
}
}
}),
},
},
});

We inject directly the snaplet data client in the run function.

The utilities and operators are now available directly on the snaplet object: snaplet.$pipe, snaplet.$merge and snaplet.$createStore.

snaplet.config.ts

/// <reference path=".snaplet/snaplet.d.ts" />
import { defineConfig } from 'snaplet';
export default defineConfig({
generate: {
async run(snaplet) {
await snaplet.User({
count: 3,
data: {
email: ({ seed }) =>
copycat.email(seed),
Post: {
count: 10,
}
}
}),
},
},
});

We no longer need count and data, you can pass the values directly.

snaplet.config.ts

/// <reference path=".snaplet/snaplet.d.ts" />
import { defineConfig } from 'snaplet';
export default defineConfig({
generate: {
async run(snaplet) {
await snaplet.User({
email: ({ seed }) =>
copycat.email(seed),
Post: {}
}),
},
},
});

To create lists of data, you can either pass an array or use our x helper function passed in a callback.

snaplet.config.ts

/// <reference path=".snaplet/snaplet.d.ts" />
import { defineConfig } from 'snaplet';
export default defineConfig({
generate: {
async run(snaplet) {
await snaplet.User((x) => x(3, () => ({
email: ({ seed }) =>
copycat.email(seed),
Post: (x) => x(10),
}))),
},
},
});

Congrats, you are now using the new API!

snaplet.config.ts

/// <reference path=".snaplet/snaplet.d.ts" />
import { defineConfig } from 'snaplet';
export default defineConfig({
generate: {
async run(snaplet) {
await snaplet.User((x) => x(3, () => ({
email: ({ seed }) =>
copycat.email(seed),
Post: (x) => x(10),
}))),
},
},
});

This is what we had before version 0.66.0.

Rename plan to run, and make it async. You are no longer required to return a plan. Calling await on a plan will automatically run it.

We inject directly the snaplet data client in the run function.

The utilities and operators are now available directly on the snaplet object: snaplet.$pipe, snaplet.$merge and snaplet.$createStore.

We no longer need count and data, you can pass the values directly.

To create lists of data, you can either pass an array or use our x helper function passed in a callback.

Congrats, you are now using the new API!

snaplet.config.ts

/// <reference path=".snaplet/snaplet.d.ts" />
import { defineConfig } from 'snaplet';
export default defineConfig({
generate: {
plan({ snaplet }) {
return snaplet.User({
count: 3,
data: {
email: ({ seed }) =>
copycat.email(seed),
Post: {
count: 10,
}
}
}),
},
},
});

To learn more about the new API, check out the documentation.