Release notes
The latest Snaplet product updates from the Snaplet team.
Snaplet Release Notes
17 April 2024 - v0.91.0
Bug fixes
- Adds type definitions for
subset.traversalMode
option introduced inv0.91.0
16 April 2024 - v0.91.0
Improvements
- Adds a new
subset.traversalMode
option
8 April 2024 - v0.90.1
Bug Fix: Subsetting for the case of multiple targets
that have the same table.
Previously, if the same table was specified multiple times in subset.targets
, Snaplet would only copy data for relations matching the first target.
Note: Fixing this involved a change to the subsetting algorithm - we now arrange the steps such that each target in the targets
configuration will have its own steps completed before the next
target's steps are run. This might cause the subsetting algorithm to end up picking different rows to what it previously did.
8 April 2024 - v0.90.2
Bug fixes
- The bug fix introduced in v0.90.1 has been reverted - it introduced a regression which caused subsetted datasets to grow considerably. We're working on solving the original issue (subsetting for the
case of multiple
targets
that have the same table - but with avoiding this regression in mind)
8 April 2024 - v0.90.1
Bug Fix: Subsetting for the case of multiple targets
that have the same table.
Previously, if the same table was specified multiple times in subset.targets
, Snaplet would only copy data for relations matching the first target.
Note: Fixing this involved a change to the subsetting algorithm - we now arrange the steps such that each target in the targets
configuration will have its own steps completed before the next
target's steps are run. This might cause the subsetting algorithm to end up picking different rows to what it previously did.
4 April 2024 - v0.90.0
Removed @snaplet/seed
parts from the CLI
@snaplet/seed
now has its own CLI, so npx snaplet setup
now only sets up a project for using Snapshots and not @snaplet/seed
, and npx snaplet generate
has been replaced with npx @snaplet/seed sync
. For more, check out the release notes for @snaplet/seed
Improved snaplet auth login
snaplet auth login
will now authenticate you without you needing to do any manual steps in-between.
Bug Fixes
- We automatically restore snapshots of Supabase databases using
--no-reset
to avoid losing permissions that supabase adds for schemas and their tables. However, we were previously not detecting whether a database is a Supabase database when capturing the snapshots.
28 March 2024 - v0.89.6
Bug fixes
- We were double-encoding special characters in connection strings in
snaplet restore
, causing restores to fail at the database connection test step for connection strings with special characters in them
27 March 2024 - v0.89.5
Bug fixes
- Improvements to debugging information for
DEBUG=snaplet:subset:*
to help understand whichtargets
caused which rows to be added - Avoid
@snaplet/seed
-related validation onsnaplet config pull
(since this command is specific to snapshots on Snaplet Cloud) - Allow overriding for alias conflicts: we were detecting if there were conflicts avoiding us from automatically applying inflection (opens in a new tab), but we
were not allowing
override
s from being applied if there were any conflicts
27 Febuary 2024 - v0.89.4
Bug Fixes
- Reverts the change made in 0.89.1 to keep preview database tasks alive longer - we suspect it might have introduced new issues. For the time being, this means preview database snapshots will be back to having a 20 minute time limit to complete for Snaplet Cloud
27 Febuary 2024 - v0.89.1
Bug Fixes
Snaplet Cloud: Keep preview database restore tasks alive longer
Previously, when restoring snapshots to preview database on app.snaplet.dev, we would terminate restore tasks that took longer than 20 minutes. When deciding whether to terminate a restore, we now give each step in the restore flow 20 minutes to complete, and the entire restore 2 hours to complete.
26 Febuary 2024 - v0.89.0
π¨ @snaplet/copycat
BREAKING CHANGE
We have upgraded to @snaplet/copycat v5.0.0. Fixes someOf()
when range tuple (e.g. copycat.someOf(seed, [1, 2], ['a','b','c'])
) is given for range
parameter instead of number (e.g. copycat.someOf(seed, 2, ['a','b','c'])
). Previously this case would have always (incorrectly) returned an empty array ([]
).
If copycat.someOf()
is currently being given a range tuple (e.g. copycat.someOf(seed, [1, 2], ['a','b','c'])
), results for the same input would change from (incorrectly) being an empty array ([]
), to (correctly) being an array of items of a size within the given range.
13 Febuary 2024 - v0.88.2
Bug Fixes
Avoid unnecessary limit: null
in generated copycat code
We generate code with calls to copycat (e.g. copycat.email(seed)
) in two cases:
@snaplet/seed
: for each database field that we generate data for, we use this generated code as the default value for the field- For snapshots, when generating example transform configs
In both cases, in 0.88.0
we made a change that caused us to add limit: null
for string fields
that did not have a char limit (e.g. text
columns in a database), for example:
copycat.email(seed, { limit: null })
If there is not char limit for the field, we now avoid this unnecessary limit: null
fluff:
copycat.email(seed)
Avoid .toString()
for integer and float field types
In the case of database integer and float database fields, when generated code with calls to copycat
(the same code as mentioned above), we were in some cases incorrectly adding a .toString()
to
this code.
Avoid copycat.scramble()
for generated copycat code for @snaplet/seed
In the case of @snaplet/seed
, for generated code with calls to copycat (the same code as
mentioned above), we were in some cases incorrectly using copycat.scramble()
, which does not make
much sense for @snaplet/seed
, where the input values to copycat would be seed values to determine
what value is generated, rather than actual database values.
13 Febuary 2024 - v0.88.0
π¨ BREAKING CHANGES in @snaplet/seed
We've made improvements to how we generate fake data for each database field.
This means that when running snaplet generate
, the same field (column in a table) might now have a different default value generated for it compared to before snaplet generate
was run.
After upgrading, subsequent runs of snaplet generate
afterwards will not cause different values to be generated though - just the first snaplet generate
after the upgrade.
In this context, a default value means a value that was not explicitly given to @snaplet/seed
for a field (column in a table).
For example:
// name given explicitlyawait snaplet.users({ name: 'Garnet Harley' })// name not given explicitly// => the generated value might have now changed// (after the first `snaplet generate` after upgrading)await snaplet.users({})
Bug Fixes:
Index dropping for snapshots
When we restore database snapshots, we first drop constraints and indices relevant to the snapshot, then insert data from the snapshot, then bring back any constraints we previously dropped. In some cases however, forgein key constraints did not properly drop before dependant index keys were dropped, causing the index drop to fail.
Account for Supavisor URLs when detecting Supabase DBs
We currently automatically add --no-reset
flag if we detect a Supabase database. We detect the supabase database by looking at database connection string. However, we weren't including Supavisor URLs in this check.
Add types for async field functions
At the moment we support promise-returning field generate functions, but npx snaplet generate
did not generate types to show that it is supported:
snaplet.users([{ name: async () => { return await Promise.resolve('Foo Bar') } }])
Make type output deterministic
In some cases, npx snaplet generate
would generate types in a different order than in previous runs.
13 Febuary 2024 - v0.87.3
- Bug Fixes: Resolved an issue where an unhandled error occurred when a package manager was not found in the CLI. This fix improves the stability and reliability of the CLI interface.
February 12, 2024 - v0.87.2
Bug Fixes
- PNPM Workspaces Support: Enhanced
snaplet setup
to properly support pnpm workspaces, facilitating smoother project configurations for users leveraging this package manager.
February 8, 2024 - v0.87.1
Bug Fixes:
- First Name Transformations: Addressed a bug that led to incorrect automatic transformations for
firstName
fields, ensuring data integrity and consistency. - Empty Database Setup: Fixed an issue where users would encounter a deadlock if the target database was empty during the setup process, improving the setup flow's resilience.
8 Febuary 2024 - v0.87.0
π¨ @snaplet/copycat
BREAKING CHANGE
We have upgraded to @snaplet/copycat v4.0.0.
Changes to copycat.phoneNumber()
:
- In the cases where the
prefixes
option is provided, copycat will now return a different output for the same input - The
min
andmax
options have been removed in favour oflength: number | { min: number, max: number }
// beforecopycat.phoneNumber(input, { min: 100000, max: 999999999 })copycat.phoneNumber(input, { min: 100000000, max: 999999999 })// aftercopycat.phoneNumber(input, { length: { min: 6, max: 9 } })copycat.phoneNumber(input, { length: 9 })
Who will be affected? You might be impacted by this change if:
- You use snapshots, and provide options to
copycat.phoneNumber()
in yourtransform
configuration: https://docs.snaplet.dev/core-concepts/capture#transform-data (opens in a new tab) - You use
@snaplet/seed
, and provide options tocopycat.phoneNumber()
π¨ @snaplet/seed
BREAKING CHANGE
@snaplet/seed
now has @snaplet/copycat
as a peer dependency rather than a dependency.
This means you'll also need to have @snaplet/copycat
installed in your project when using @snaplet/seed
.
While this technically is a breaking change, npx snaplet setup
would have installed @snaplet/copycat
for you when setting up @snaplet/seed
. This change would only affect you if you have since removed @snaplet/copycat
from your dependencies.
1 Febuary 2024 - v0.86.2
Fix for unique constraint checking and default database values in Seed π±
We had a bug where we attempted to check uniqueness for columns we don't handle. Indeed, if you have a DEFAULT column in your database, Seed won't generate a value and will let the database do the work unless you specify an explicit value.
Unique constraints checks are now skipped for these columns if they're undefined. β
1 Febuary 2024 - v0.86.1
Handle model name conflicts after inflection applied
As part of the inflection that @snaplet/seed
does, we pluralise the table names. For example, a User
table name would be exposed as seed.users()
.
This caused conflicts in cases where there was one table with the singular form, and one with the plural form. For example, public.user
(note the singular form) and public.users
(not the plural form) would both get the name "users". As a result, the one table ends up getting "lost".
In cases where the schemas differ, we can account for the name conflict by instead qualifying both names with the schema name. For example, for tables public.user
and auth.users
, we would end up with "publicUsers" and "authUsers".
However, if the tables are from the same schema (e.g. public.user
and public.users
), we do not have a way to resolve the conflict, and need you to resolve the conflict by specifying overrides
for this in snaplet.config.ts
. For example:
/// <reference path=".snaplet/snaplet.d.ts" />import { defineConfig } from 'snaplet';export default defineConfig({ seed: { alias: { override: { user: { // e.g. seed.users(x => x(2)) name: 'users', }, users: { // e.g. seed.allUsers(x => x(2)) name: 'allUsers', }, }, }, },});
In this release, we detect if such conflicts exist when you run npx snaplet generate
, and log a message to the console showing which table names conflict.
For more, check out our docs on alias override
s: https://docs.snaplet.dev/core-concepts/seed#override (opens in a new tab)
1 Febuary 2024 - v0.86.0
Unique constraints support in seed π±
Seed is becoming more resilient! By leveraging your database's unique constraints, we are now able to greatly mitigate collisions that could happen when auto connecting models or when generating scalar values.
If you still encounter a unique constraint conflict, you will have a clear error giving you all the context you need to fix the issue. β
It's technically a π¨ breaking change π¨ as it can influence the output of a given plan, but the plan wouldn't work in previous versions.
More resilient AI prediction job π€
We fixed issues around our workflow for predicting your data shapes using AI.
31 January 2024 - v0.85.2
Handle model name conflicts after inflection applied
As part of the inflection that @snaplet/seed
does, we pluralise the table names. For example, a "User" table name would be exposed as seed.users()
.
This caused conflicts in cases where there was one table with the singular form, and one with the plural form. For example, public.user (note the singular form) and auth.users (not the plural form) would both get the name "users". As a result, the one table ends up getting "lost".
In this release, we now account for the name conflict by instead qualifying both names with the schema name. For the example above, we would end up with "publicUsers" and "authUsers".
We do not yet handle the case where the name conflict is in a single schema (e.g. public.user and public.users) - we plan to do this soon!
Fix support for reading fingerprint
from snaplet.config.ts
We previously exposed types for providing fingerprint
in snaplet.config.ts
, but did not actually read this from the config in @snaplet/seed
.
Account for aliasing when generating fingerprint
snaplet fingerprint
did not account for inflection or model aliasing (which is now enabled default from 0.85.0 onwards).
note snaplet fingerprint
is still an experimental feature - docs, improvements and much more coming soon!
Avoid showing preview database url on snaplet preview-database create
snaplet preview-database create
now shares an example of a command to run to obtain the url of a preview database, rather than the url itself.
29 January 2024 - v0.85.0
π¨ Breaking changes ahead π¨
We're refining the API and getting closer to a stable v1 release. π
Model callback API
We are introducing a new way of definining models with functions, for example:
await seed.authors([(ctx) => { const createdAt = new Date(copycat.dateString(ctx.seed)) const day = 1000 * 60 * 60 * 24 const updatedAt = new Date(createdAt.getTime() + day) return { createdAt, updatedAt, }}])
For a complete list of the changes, check out the migration guide
Creating a client is now async
We've changed the way in which the client is instantiated:
import { createSeedClient } from '@snaplet/seed'const seed = await createSeedClient({ /* options */ })
Better compatibility with non-empty databases
@snaplet/seed
now works better with tables that already have existing data in them. For tables with sequences, if you have existing data in them when using @snaplet/seed
,
any new rows generated by @snaplet/seed
will start off the sequences where the existing data left off.
Fix the seed
value for parent fields
We were injecting the model's seed for all parent fields in a model. We're now injecting a per-parent field seed to have more variety in connected data.
Inflection is now turned on by default
You no longer need a snaplet.config.ts
file to enable inflection. It's now turned on by default.
For more on what has changed and how to upgrade, check out the migration guide.
23 January 2024 - v0.84.0
π¨ @snaplet/copycat
BREAKING CHANGE
We have upgraded to @snaplet/copycat v2.0.0. Inputs for copycat.float()
will now map to a different output. It is still deterministic - the same input will always map to the same output. It is just that after the upgrade the corresponding output for each input will have changed.
Who will be affected? You might be impacted by this change if:
- If you use snapshots, and you used
copycat.float()
in yourtransform
configuration: https://docs.snaplet.dev/core-concepts/capture#transform-data (opens in a new tab) - If you use
@snaplet/seed
, and you have floating-point column types (e.g.float4
) in a table for which you use@snaplet/seed
to generate data
Why is it changing?
Previously, output values for copycat.float()
would stay close to the min
value given. With this release, output values will distribute more evenly across the (min, max) range of values.
23 January 2024 - v0.83.2
Improvements
Support Date
s in @snaplet/seed
We now allow date values to be given to @snaplet/seed
.
snaplet.users({ createdAt: () => new Date(23)})
Bug Fixes
Filter out keys when generating fingerprint.json
We now filter out primary and foreign keys from the fields we inspect when creating a fingerprint of your database. For a bit more on what snaplet fingerprint
is, check out the release notes for the initial alpha release of this feature: https://docs.snaplet.dev/release-notes#alpha-release-of-snaplet-fingerprint (opens in a new tab). Docs, improvements and much more coming soon!
19 January 2024 - v0.83.1
Bug Fixes
Addressed an issue with row estimates in partitioned tables. Previously, Snaplet incorrectly estimated total rows to copy as 0 for partitioned tables with data. This fix ensures accurate handling and data management for such tables, particularly when not using subsetting.
17 January 2024 - v0.83.0
Improvement: data
parameter for generate function
We now provide a way to access data already generated for a particular model with the data
parameter:
await snaplet.users([{ email: ({ data }) => `${data.first_name}${data.last_name}@example.org`.toLowerCase()}])
For more, check out our docs.
Improvement: store
and $store
parameters for generate and connect functions
For both generating fields, as well as connecting up relations, we now provide:
store
: The store containing models already created in this plan$store
: The global store containing all models created in thissnaplet
instance so far.
// generate functionawait snaplet.customers([{ email: ({ store, $store }) => /* ... */}])// connect functionawait snaplet.reservations([{ customer: ({ store, $store }) => /* ... */,}]);
For more, check out our docs:
Improvement: Further future-proofing for usage with jest
0.82.1
solved some issues for using @snaplet/seed
with jest, this release adds further such improvements to help prevent these same issues appearing in the future
π¨ BREAKING CHANGES in @snaplet/seed
We've removed the modelSeed
parameter that we pass to generate functions in favor of the new data
mentioned above.
Previously, if you had a field with a value that depended on another field, modelSeed
provided a way to accomplish this:
// **before**await snaplet.users([{ createdAt: ({ modelSeed }) => copycat.dateString(modelSeed), updateAt: ({ modelSeed }) => { const createdAt = copycat.dateString(modelSeed) const updatedAtMs = Number(new Date(createdAt)) + 60_000 return new Date(updatedAtMs).toISOString() }}])
Since we now have the data
parameter, we have a more natural way of obtaining the value generated for previous values:
// **after**await snaplet.users([{ createdAt: ({ seed }) => copycat.dateString(seed), updateAt: ({ data }) => { const updatedAtMs = Number(new Date(data.createdAt)) + 60_000 return new Date(updatedAtMs).toISOString() }}])
16 January 2024 - v0.82.1
Changes and Improvements
-
Improved Restore Functionality for Supabase Users
- Fix: We've resolved an issue where automatic resets were not properly applied when restoring to
127.0.0.1
. Supabase users can now experience a smoother and more reliable restoration process.
- Fix: We've resolved an issue where automatic resets were not properly applied when restoring to
-
Enhanced CLI Transformations
- Enhancement: Our CLI has been refined to provide better automatic transformations for fields such as AGE, RATING, and ROLE. This enhancement aims to streamline your data handling and improve overall workflow efficiency.
-
Jest Environment Compatibility
- Fix: The use of SnapletClient within the Jest testing environment has been fixed. This update ensures a more seamless integration and compatibility, enhancing your development and testing processes.
Stay tuned for more updates!
15 January 2024 - v0.82.0
π¨ BREAKING CHANGES in @snaplet/seed
We've made improvements to our AI model to improve some the data we generate to more closely match your production database.
This means that when running snaplet generate
, the same field (column in a table) might now have a different default value generated for it compared to before snaplet generate
was run.
After upgrading, subsequent runs of snaplet generate
afterwards will not cause different values to be generated though - just the first snaplet generate
after the upgrade.
In this context, a default value means a value that was not explicitly given to @snaplet/seed
for a field (column in a table).
For example:
// name given explicitlyawait snaplet.users({ name: 'Garnet Harley' })// name not given explicitly// => the generated value might have now changed// (after the first `snaplet generate` after upgrading)await snaplet.users({})
11 January 2024 - v0.81.0
This is a big one for @snaplet/seed
! π±
π¨ Breaking Changes
1. Stateful data client
The SnapletClient
is now stateful, meaning that it holds global seeds so you can execute multiple plans generating different data.
This now works:
await snaplet.users((x) => x(2));await snaplet.users((x) => x(2));
You can clear the state of the client using the new snaplet.$reset
function.
2. Global and local stores
Stores are now first class citizens!
Each plan executed returns the data it produced as a local store.
const usersStore = await snaplet.users((x) => x(2))// { users: [user, user]Β }console.log(usersStore)
A new global store is introduced as part of the client's state, accessible at snaplet.$store
. This store contains all the data generated so far. You can reset its state as part of snaplet.$reset()
.
3. Fine-grained auto connections
We reworked the autoConnect
feature. The option is renamed to simply connect
and accepts either true
or a store. When using true
, it will connect the plan to what was already generated in the global store.
Before:
await snaplet.$pipe([ snaplet.organizations(x => x(2)), snaplet.users(x => x(10), { autoConnect: true })]);
Now:
await snaplet.organizations(x => x(2));// the 10 users will be automatically connected to one of the 2 previously generated organizations contained in snaplet.$storesnaplet.users(x => x(10), { connect: true });
You can also pass a store:
const externalStore = { users: [{ id: 42 }, { id: 5432 }]} };await snaplet.posts(x => x(3), { connect: externalStore });
4. Operators pipe
and merge
are gone π«‘
Due to the changes above, the operators are now obsolete and gone. π
Full migration docs: https://docs.snaplet.dev/migrations/seed#from-0810-and-above (opens in a new tab)
11 January 2024 - v0.80.0
Bugfixes
Import @snaplet/copycat
in seed.mts
example
In the case of@snaplet/seed
, npx snaplet setup
now also adds @snaplet/copycat
as a dependency to your project. The example seed.mts
file we generate as part of npx snaplet setup
now also includes an import to @snaplet/copycat
. Since @snaplet/copycat
is typically used as part of writing a seed script with @snaplet/seed
, this change saves you needing to jump through these unnecessary hoops.
Improvements
Handle invalid system-manifest.json
files gracefully
We keep some internal state in a file called system-manifest.json
. For different reasons, this file might be corrupt. This shouldn't prevent you from using Snaplet though, so we now recover from this case gracefully.
5 January 2024 - v0.78.3
Fix Missing semicolon
error in snaplet setup
and snaplet generate
For some databases, we had an issue preventing generating the assets needed by @snaplet/seed
.
4 January 2024 - v0.78.1
@snaplet/copycat
BREAKING CHANGE NOTICE
What is changing?
Inputs for copycat.float()
will now map to a different output. It is still deterministic - the same input will always map to the same output. It is just that after the upgrade the corresponding output for each input will have changed.
When will the change happen? We are planning on releasing the change on 23 January 2024 at 12:00pm (noon) UTC
Who will be affected? You might be impacted by this change if:
- If you use snapshots, and you used
copycat.float()
in yourtransform
configuration: https://docs.snaplet.dev/core-concepts/capture#transform-data (opens in a new tab) - If you use
@snaplet/seed
, and you have floating-point column types (e.g.float4
) in a table for which you use@snaplet/seed
to generate data
Why is it changing?
Previously, output values for copycat.float()
would stay close to the min
value given. With this release, output values will distribute more evenly across the (min, max) range of values.
How to prepare:
To preview the impact of this change, you can modify your copycat
import in your configuration.
From: import { copycat } from '@snaplet/copycat'
To: import { copycat } from '@snaplet/copycat/next'
.
If you are using @snaplet/seed
, you'll also need to first update your snaplet dependencies:
yarn up snaplet @snaplet/seed
Then use the --copycat-next
flag when regenerating assets:
# to switch to `@snaplet/copycat/next`npx snaplet generate --copycat-next# to switch back to `@snaplet/copycat`npx snaplet generate
Need More Time? If the scheduled update time doesnβt suit your schedule, please let us know. We are sorry for any inconvenience this may cause and are here to assist with a smoother transition. Thank you for your attention to this matter.
4 January 2024 - v0.78.0
Alpha release of snaplet fingerprint
This release adds some of the basics for a feature we're working on called snaplet fingerprint
.
A new command has been added:
snaplet fingerprint <database-url>
When run, snaplet fingerprint
will inspect the database url given (typically this would be a production database url), collect some statistical details from a sample of data in your database, and store them in a .snaplet/fingerprint.json
file. When running a seed script (e.g. npx tsx seed.mts
), @snaplet/seed
will try read from this file - if it exists, it will use it to generate data that is more closely matching the kind of data you have in your production database.
The data it generates is still entirely fake - it will just now be closer to how your production data looks. For example, if a date column, snaplet fingerprint
would find the minimum and maximum values from a sample of the data, which in turn allows @snaplet/seed
to generate data within this same date range.
note This still is an experimental feature - docs, improvements and much more coming soon!
4 January 2024 - v0.77.4
Allow using @snaplet/copycat/next
with @snaplet/seed
**
We preview upcoming breaking changes in copycat by exporting the latest change for the upcoming copycat release as @snaplet/copycat/next
.
If you are using @snaplet/seed
, you can now pass a --copycat-next
flag when regenerating assets so that these generated assets use @snaplet/copycat/next
:
# to switch to `@snaplet/copycat/next`npx snaplet generate --copycat-next# to switch back to `@snaplet/copycat`npx snaplet generate
31 December 2023 - v0.77.3
Fix faker is not defined
When generating the assets required for @snaplet/seed
(which we do as part of b oth snaplet setup
and snaplet generate
), we were accidentally referencing faker
when generating the default value for fields that we detected as being having the shape of a URL or a MAC address.
We now replaced these cases with the copycat equivalent to avoid referencing faker.
14 December 2023 - v0.77.0
π¨ BREAKING CHANGES in @snaplet/seed
We've made improvements to some of the default values we generate for each field (column). We regenerate these defaults each time snaplet setup
or snaplet generate
is run.
This means that after upgrading, when running snaplet generate
, the same field (column in a table) might now have a different default value generated for it compared to before snaplet generate
was run. Subsequent runs of snaplet generate
afterwards will not cause different values to be generated though - just the first snaplet generate
after the upgrade.
In this context, a default value means a value that was not explicitly given to @snaplet/seed
for a field (column in a table).
For example:
// name given explicitlysnaplet.users({ name: 'Garnet Harley' })// name not given explicitly// => the generated value might have now changed// (after the first `snaplet generate` after upgrading)snaplet.users({})
π Bug fixes
process
types in seed.mts
At the moment, the seed.mts
example generated by snaplet setup
references process
. If the projects does not have @types/node
as a dependency, vscode will show that it does not know about any types for process
. This releases fixes this by having @snaplet/seed
now depends on and references @types/node
for type definitions. This means that any new projects will get all the type definitions needed for the generated seed.mts
example, even if they do not have @types/node
as a dependency**.**
snaplet.$resetDatabase()
now respects select
in snaplet.config.ts
If you chose to exclude some schemas or tables in snaplet.config.ts
with select
, snaplet.$resetDatabase()
will now exclude them, and truncate all the remaining tables of the remaining schemas in your database:
// snaplet.config.tsimport { defineConfig } from 'snaplet'export default defineConfig({ select: { public: { $default: true, _prisma_migrations: false } }})
// seed.mtsimport { SnapletClient } from '@snaplet/seed'const snaplet = new SnapletClient()// `_prisma_migrations` table will be left as-is and not be truncatedawait snaplet.$resetDatabase()
Fix Unhandled error: column "<name>" does not exist
During snaplet setup
or snaplet generate
, we collect information from your database in order to generate the assets needed for @snaplet/seed
. There was a bug in these flows that was sometimes causing us to look up the incorrect column name.
30 November 2023 - v0.76.0
π New Features
Snaplet Generate becomes @snaplet/seed
: You can now use the full power of Snaplet Seed everywhere in your codebase! Here is a sneak peek:
// seed.mtsimport { SnapletClient } from "@snaplet/seed";const snaplet = new SnapletClient();await snaplet.users(x => x(3, () => ({ posts: (x) => x(10)})));
To know more about @snaplet/seed
, read our quick start guide (opens in a new tab).
π¨ Breaking change in 'snaplet generate'
With the publishing of @snaplet/seed
, there is no more generate.run
function in the Snaplet configuration file.
The snaplet generate
command is repurposed to generate the code needed to use @snaplet/seed
.
You can follow this migration guide: https://docs.snaplet.dev/migrations/seed#from-0760-and-above (opens in a new tab)
Thank you for being a part of our journey! π
7 November 2023 - v0.74.0
π¨ Breaking change: Preview databases
Preview Database Handling Overhaul. We've revamped how we handle preview databases. It's crucial that if you're using preview databases that you upgrade your Snaplet CLI to the latest version to ensure compatibility. Run snaplet upgrade
to upgrade.
7 November 2023 - v0.73.1
π οΈ CLI improvements
This version introduces several fixes to enhance your command-line interface experience.
Restoration Behavior on Interruption: If you press Ctrl+C during a restoration prompt, it defaults to a 'no' response to continue the restoration process without interruption.
Integer Collision Generation: The generate
command has been improved to produce a larger number of values with very low conflict probabilities.
Snapshot Support in PDB Creation: We've made it easier to identify early on if a snapshot won't restore successfully into a preview database by marking unsupported snapshots during PDB creation.
2 November 2023 - v0.73.0
π¨ Generate seeds breaking change
We've made a change to the way Snaplet generates seeds, which breaks previous data generations. We previously introduced a hash based on the plan's inputs to our seeding mechanism, but after user feedback, it's clear that it's not the right approach. The issue with this approach is that if you alter your plan, the modification will impact all the models involved in the plan. As such, we've decided to roll it back.
If you're interested in the specifics, read on.
Let's take this example:
await snaplet.users([ { name: 'John' }, // user id will be 42 { name: 'Jane' }, // user id will be 59 { name: 'Bob' }, // user id will be 14])
If you add an email to Bob
, the user ids will change for all the users:
await snaplet.users([ { name: 'John' }, // user id will be 98 { name: 'Jane' }, // user id will be 35 { name: 'Bob', email: 'bob@acme.com' }, // user id will be 74])
This is because the seeds injected to each field generate functions which were constructed like this:
<hash of the plan inputs>/0/users/0/id
Now that we removed the hash, a field's value is entirely dependent on the model's location in the plan (basically its path):
0/users/0/id
So altering your plans will no longer impact the other models and fields ouputs.
It unfortunately means that your generated data output will change with this release.
π¨ Alias strategy is now opt-in
We recently introduced aliases to customize the data client.
At the time we shipped this feature, we also decided to apply a default alias strategy to the data client. Based on feedback we've decided to revert this change and make it opt-in instead so it's more predictable for you. This is also a breaking change.
To opt-in, you now need to set the inflection
option to true
:
defineConfig({ generate: { alias: { inflection: true, }, },});
31 October 2023 - v0.72.0
π οΈ Copycat improvements
You can't scramble an omlette without breaking some eggs π³. We've made improvements to @snaplet/copycat (opens in a new tab) that introduce breaking changes with how Copycat "scrambles" data during transformation:
- For the same input column value from your database, new snapshots will now be have different resulting values compared to what they used to be in previous snapshots.
- Snaplet generate will generate values that are different to what they used to be.
What this means is that if your tests were expecting to see deterministic values from your Copycat changes, these tests may break, as Copycat generates new deterministic values for all transformations. As such, this new improvement gets a π¨ breaking change π¨ flag.
We've made this change in part to improvement the performace of Copycat, and so, the good news is if you've experienced slow snapshot captures in the past when capturing large column values, you may see an improvement in the time it now takes for your snapshots to capture.
Capturing snapshots or generating with Snaplet will still be deterministic though! The data will only change with the next snapshot you capture or the next time you generate data - after which point it will remain the same across as long as the inputs do not change.
If you rely on Snaplet generating data or transforming data that does not change if the inputs do not change, this release might affect you. More specifically, this change will affect you if you are:
- Using "auto"-transform mode (if you have transform:
{ $mode: 'auto' }
in your Snaplet configuration as shown in the Data Editor on app.snaplet.dev). - Using Copycat in your Snaplet configuration to generate data or transform data when capturing snapshots.
- Using our generate feature.
October 30 2023 - v0.71.0
π Snapshot capture bug fix
We squashed a long-standing bug π which impacts the snapshot files format for users using older versions of the Snaplet CLI.
If you captured a snapshot with a version of Snaplet CLI prior to 0.71.0, you can either:
Capture a new snapshot, which will save it to the new fixed format (recommended):
npx snaplet@latest snapshot capture
Or run the restore command with the last version of Snaplet CLI before the fix:
npx snaplet@0.70.1 snapshot restore
As this is a π¨ breaking change π¨ we added a notice in the console when running snaplet snapshot restore
pointing to this migration note (opens in a new tab).
If you're having trouble with this change, come ask us for help on Discord (opens in a new tab).
25 October 2023 - v0.70.0
π§Ή Removing deprecated commands
Out with the old! In this release we wave goodbye to the following deprecated commands:
π snaplet snapshot subset
π snaplet subset command
π snaplet config setup
Note that the removal of the above commands is is a π¨ breaking change.
π New feature - JSDoc comments
We added JSDoc comments everywhere in the data client so it's easier to discover its API and understand the options and your database schema.
23 October 2023 - v0.69.0
π New feature - Introducing aliases
We are super excited to introduce a new configuration option for Generate called alias
, which allows you to take full control over how your models, fields and relationships are named. We shipped a sensible default implementation which should cover the majority of the use cases but if you need more customization, you can!
The default rules for the aliases:
- Model names: pluralized and camelCased.
- Scalar field names: camelCased.
- Parent field names (one to one relationships): singularized and camelCased.
- Child field names (one to many relationships): pluralized and camelCased.
Don't forget to update your types after you have updated the CLI by running:
snaplet config generate
π οΈ Aliases strategy applied by default
With the introduction of alias above, and we will apply a default strategy so the client's code looks better and is easier to reason about.
If you want to opt-out, you can by setting the new inflection option to false
:
/// <reference path=".snaplet/snaplet.d.ts" />import { defineConfig } from 'snaplet';export default defineConfig({ generate: { alias: { inflection: false, }, async run(snaplet) { await snaplet.User((x) => x(3)) }, },});
π§Ή Removal of the object form shortcut for one-to-many relationships -
We've changed the signature for one-to-many relationship, we removed the object form when you only want to generate 1 element. It was confusing to be able to use both object and array.
// previously// create a single usersnaplet.User({})// create a user with a postsnaplet.User({ Post: {}})// from 0.69.0 onwards// create a single usersnaplet.User([{}])// create a user with a postsnaplet.User([{ Post: [{}]}])
Note that this is a π¨ breaking change and you'll need to use aliases going forward.
Questions? Come ask us for help on Discord (opens in a new tab).*
18 October 2023 - v0.68.0
π¨ Breaking Change: pipe
and merge
We've changed the signature for the pipe
and merge
operators to take in an array of plans instead of using variadic arguments for plans:
// previouslysnaplet.$pipe(snaplet.User({}), snaplet.Post({}))snaplet.$merge(snaplet.User({}), snaplet.Post({}))snaplet.User({}).pipe(snaplet.Post({}))snaplet.User({}).merge(snaplet.Post({}))// from 0.68.1 onwardssnaplet.$pipe([snaplet.User({}), snaplet.Post({})])snaplet.$merge([snaplet.User({}), snaplet.Post({}))snaplet.User({}).pipe([snaplet.Post({})])snaplet.User({}).merge([snaplet.Post({})])
π New Feature: options supported for pipe
and merge
operators
As you may expect, with this change, we now also support options to be provided for these operators in our Generate API.
snaplet.$merge([/* ... plans */], { models: { Post: { data: { // This title will be used for all plans // being combined by this merge title: 'A title for posts in the merged plans' } } }})
Options given to these operators will be passed down to the plans they are combining. If these plans provide their own options, they will take precedence over the corresponding pipe/merge options.
π Bug fixes - Generate
We were were not detecting identity columns correctly, and generate
was not able to generate and insert rows for tables with identity columns. Snaplet generate
is now able to correctly detect if it is dealing with an identity column, and uses OVERRIDING SYSTEM VALUE
when outputting INSERT
statements in order to work with these columns.
16 October 2023 - v0.67.0
π¨ Breaking Change: Better seeding values
For Snaplet generate
we've modified the seed
values generated to be more logically consistent and aligned with users' expectations.
By way of demonstration, before this release, the same id would be returned for these two users:
await snaplet.User({ email: 'alice@acme.com' })await snaplet.User({ email: 'bob@acme.com' })
Doen't make much sense, right? This was because the seed value injected per column was only relying on your plan's paths (here the seed for the User's id would be 0/User/id
).
We produce a hash based on the inputs you provide to snaplet.<modelName>(inputs)
so the output will always depends on the inputs. It's the same behaviour as Snaplet Copycat (opens in a new tab), and we think it's more predictable and logical that way.
π New Features: generate
improvements
We've added the --output
option to generate
so you can safely write the SQL statement to a file without being bothered by eventual other messages logged to stdout (like our auto upgrade message). Read more (opens in a new tab).
We've also added more ways of handling tags
attached to a snapshot to the CLI. Read more (opens in a new tab).
12 October 2023 - v0.66.0
β
Generate
in Beta
A major milestone for our generate
feature, which officially enters beta status!
With this release, we have totally reworked the generate
API so it can be both more powerful and flexible. It goes from alpha to beta status, and we'd love to hear your feedback!
If you've been using generate
you'll need to migrate to use the latest version. We have a migration guide here (opens in a new tab).
Just getting started? If you want to know more about how to generate data you can refer to our quick start guide (opens in a new tab) or our generate
core concept (opens in a new tab) page where we dig deeper into generate
and its options.
Happy generating!