prisma-data-migrate-cli
v1.1.0
Published
A CLI wrapper around prisma migrate commands for supporting TypeScript data-migrations.
Downloads
107
Readme
prisma-data-migrate-cli
This CLI exposes the processes described in the Data migrations article from Prisma as a wrapper CLI around Prisma.
Table of Contents
Installation
npm i prisma-data-migrate-cli
or
yarn add prisma-data-migrate-cli
Commands
apply
This is the core command provided by this CLI. This should be a drop-in-replacement for prisma migrate deploy
. This command applies migrations one-by-one to your database schema, but in between each migration, it will check for the existence of a data-migration.ts
file and run that script. This allows you to add data-migrations to your CI/CD pipeline.
Syntax
prisma-data-migrate-cli apply
create
This is an optional helper command, meant to create a data-migration.ts
file stub inside the directory for the latest migration.
Syntax
prisma-data-migrate-cli create [options]
Options
--snapshot
,--s
: Declare if you would like asnapshot.prisma
file added to represent your schema types. If you do not use this option, then your transaction client will be limited to the commands$queryRaw
&$updateRaw
. Defaults to false.
client-rewind
This is optional helper command, meant to roll-back the generated types for your prisma/client
package to that of a snapshot.prisma
file.
Syntax
prisma-data-migrate-cli client-rewind [options]
Options
--name
,--n
: The name of a migration with asnapshot.prisma
file that you would like to rewind your generated database client types back to. Defaults to the latest migration with asnapshot.prisma
file.
Usage
Integrating this CLI into your application requires a few steps. First, this expects that you use the expand and contract pattern for your migrations. So you would make a standard Prisma migration expanding your database model to include new fields. And then you would append a data-migration (using this CLI) on to that migration. Finally, you would make a new migration to contract your data models to remove fields that are no longer necessary.
Usage example
For instance, imagine you had a Prisma schema with this model.
model User {
id Int @id @default(autoincrement())
name String
}
But you want to update the User
table to have separate firstName
& lastName
columns.
First, create your schema expansion by adding the new fields.
model User {
id Int @id @default(autoincrement())
name String
+ firstName String
+ lastName String
}
Now generate your standard migration with prisma migrate dev --create-only --name expand-user-names
. Next, add a data-migration onto that migration by running prisma-data-migrate-cli-create --snapshot
. That will add a snapshot.prisma
and template data-migration.ts
file alongside the existing migration.sql
file.
The data-migration.ts
file is just a single function that represents a database transaction. Update that file to look like this.
import type { PrismaClient } from "@prisma/client";
// Do not change the function signature
export default async (tx: PrismaClient) => {
const users = await tx.user.findMany();
for (const user of users) {
const [firstName, ...lastName] = user.name.split(" ");
await tx.user.update({
data: {
firstName,
lastName: lastName.join(" "),
},
where: { id: user.id },
});
}
};
Now, you can perform your model contraction by updating your Prisma schema to remove the name
property.
model User {
id Int @id @default(autoincrement())
- name String
firstName String
lastName String
}
Once you are satisfied with your data migration, you can run prisma-data-migrate-cli apply
to apply each migration.sql
file and then their data-migration.ts
file in order.
Have caution continuing onto the final step
Finally, you may run prisma migrate dev --create-only --name contract-user-name
. But be WARNED Due to odd behavior in the existing Prisma CLI, running prisma migrate dev --create-only
will only create a new migration without running it. HOWEVER, any migrations in your repository which have not been run will be run when this command is executed. This means that if you chose to not yet run prisma-data-migrate-cli apply
, then the prisma migrate
process will run for the expansion migration (expand-user-names
), but will not run your data-migration.ts
file because that process exists outside of Prisma's CLI. If you try to run prisma-data-migrate-cli apply
after a migration has been marked by Prisma as applied, the data-migration.ts
file will not run. The logic this CLI uses to determine if a migration needs to be run or not when the apply
command is invoked relies on the _prisma_migrations
table created and utilized by Prisma itself.
Usage recommendations
It is heavily recommend that dependents of this CLI utilize package-scripts to organize these commands into a series of sensible defaults for developers of their application. It is recommended that you only interface with your database schema via these commands.
It is also recommended that you update your tsconfig.json
file to add an exclude path equal to "prisma/migrations"
. That way type errors coming from your data-model contractions don't flag in your CI/CD.
Example
"scripts": {
"db:migrate:create": "prisma format && prisma migrate dev --create-only",
"db:migrate:create:with-data": "prisma format && prisma migrate dev --create-only && prisma-data-migrate-cli create --snapshot",
"db:migrate:apply": "prisma-data-migrate-cli apply",
"db:client:rewind": "prisma-data-migrate-cli client-rewind",
}
Caveats
- Currently there is no command to run only a specific data-migration if your migration history has become out of sync by running the wrong
prisma migrate
command directly. - There is not yet support for multi-file schemas
- If you are using SQLite and your database file is identified with a relative path, you must either change it to be an absolute path or not use snapshots.
License
BSD 3-Clause License
Copyright (c) 2022, Alliance for Sustainable Energy LLC, All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.