Skip to content

Commit fe3eab6

Browse files
Convert Prisma sample from v6 to v7 (#355)
This PR updates the Prisma sample from Prisma v6 to Prisma v7. There were major version changes which caused incompatibilities with our previous sample, such that Dependabot was unable to complete the upgrade without manual changes. It tried in #295 and #284. The major change is the replacement of `DATABASE_URL` with a `prisma.config.ts` file. This is quite convenient for DSQL since previously it was awkward for users to generate a token and embed it in the `DATABASE_URL` variable, given the password would expire. Now we can generate a token on the fly as part of the `prisma.config.ts` file like we do in our connector libraries. You will notice that it's now necessary to provide `CLUSTER_ENDPOINT` even when doing things like `npm run build` which doesn't make a lot of sense, but this seems to be a side-effect of the way Prisma requires the configuration file any time a Prisma command is run. We could probably provide a dummy URL or something but that may be confusing in the sample code, and in practice it's easy to define the `CLUSTER_ENDPOINT` env var first and just leave it defined. In practice I think users may hard code their endpoint in the config file anyway, in which case this won't be an issue. By submitting this pull request, I confirm that my contribution is made under the terms of the MIT-0 license.
1 parent 57f2550 commit fe3eab6

11 files changed

Lines changed: 1285 additions & 1502 deletions

File tree

.github/workflows/typescript-prisma-integ-tests.yml

Lines changed: 21 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -77,52 +77,56 @@ jobs:
7777
7878
- name: Build project
7979
working-directory: ./typescript/prisma
80+
env:
81+
CLUSTER_ENDPOINT: ${{ needs.create-cluster.outputs.cluster-endpoint }}
8082
run: |
8183
npm run build
8284
8385
- name: Run validator unit tests
8486
working-directory: ./typescript/prisma
87+
env:
88+
CLUSTER_ENDPOINT: ${{ needs.create-cluster.outputs.cluster-endpoint }}
8589
run: |
8690
npm run test -- --testPathPatterns=validate
8791
8892
- name: Run transformer unit tests
8993
working-directory: ./typescript/prisma
94+
env:
95+
CLUSTER_ENDPOINT: ${{ needs.create-cluster.outputs.cluster-endpoint }}
9096
run: |
9197
npm run test -- --testPathPatterns=transform
9298
9399
- name: Run workflow unit tests
94100
working-directory: ./typescript/prisma
101+
env:
102+
CLUSTER_ENDPOINT: ${{ needs.create-cluster.outputs.cluster-endpoint }}
95103
run: |
96104
npm run test -- --testPathPatterns=workflow
97105
98106
- name: Run CLI integration tests
99107
working-directory: ./typescript/prisma
108+
env:
109+
CLUSTER_ENDPOINT: ${{ needs.create-cluster.outputs.cluster-endpoint }}
100110
run: |
101111
npm run test -- --testPathPatterns=cli-integration
102112
103-
- name: Create auth helper
113+
- name: Create psql auth helper
104114
run: |
105-
cat > /tmp/generate-prisma-url.sh << 'EOF'
106-
configure_credentials() {
115+
cat > /tmp/configure-psql.sh << 'EOF'
116+
configure_psql() {
107117
local user=$1
108118
109119
if [ "$user" = "admin" ]; then
110120
local auth_type="admin-auth"
111-
local schema="public"
112121
else
113122
local auth_type="auth"
114-
local schema="$NON_ADMIN_SCHEMA"
115123
fi
116124
117125
export PGHOST=$CLUSTER_ENDPOINT
118126
export PGPASSWORD=$(aws dsql generate-db-connect-${auth_type}-token --region $REGION --hostname $PGHOST --expires-in 300)
119127
export PGUSER=$user
120128
export PGDATABASE="postgres"
121129
export PGSSLMODE="verify-full"
122-
123-
# URL-encode password for consumption by Prisma.
124-
prisma_pass=$(python -c "from urllib.parse import quote; print(quote('$PGPASSWORD', safe=''))")
125-
export DATABASE_URL="postgresql://$PGUSER:$prisma_pass@$CLUSTER_ENDPOINT:5432/$PGDATABASE?sslmode=$PGSSLMODE&schema=$schema"
126130
}
127131
EOF
128132
@@ -131,11 +135,7 @@ jobs:
131135
env:
132136
CLUSTER_USER: "admin"
133137
CLUSTER_ENDPOINT: ${{ needs.create-cluster.outputs.cluster-endpoint }}
134-
REGION: ${{ needs.create-cluster.outputs.region }}
135138
run: |
136-
source /tmp/generate-prisma-url.sh
137-
configure_credentials $CLUSTER_USER
138-
139139
# Ensure clean state first.
140140
npm run prisma:migrate-down
141141
@@ -148,8 +148,8 @@ jobs:
148148
CLUSTER_ENDPOINT: ${{ needs.create-cluster.outputs.cluster-endpoint }}
149149
REGION: ${{ needs.create-cluster.outputs.region }}
150150
run: |
151-
source /tmp/generate-prisma-url.sh
152-
configure_credentials $CLUSTER_USER
151+
source /tmp/configure-psql.sh
152+
configure_psql $CLUSTER_USER
153153
154154
# Add a new column to the vet model (after the name field)
155155
sed -i '/model vet/,/^}/s/name String @db.VarChar(30)/name String @db.VarChar(30)\n phone String? @db.VarChar(20)/' prisma/veterinary-schema.prisma
@@ -160,9 +160,9 @@ jobs:
160160
# Validate the modified schema first
161161
npm run validate prisma/veterinary-schema.prisma
162162
163-
# Generate incremental migration using --from-url
163+
# Generate incremental migration using --from-config-datasource (reads from prisma.config.ts)
164164
# Use --force because Prisma may generate DROP CONSTRAINT for PKs
165-
npm run dsql-migrate -- prisma/veterinary-schema.prisma -o prisma/migrations/incremental/migration.sql --from-url "$DATABASE_URL" --force
165+
npm run dsql-migrate -- prisma/veterinary-schema.prisma -o prisma/migrations/incremental/migration.sql --from-config-datasource --force
166166
167167
# Show what was generated
168168
cat prisma/migrations/incremental/migration.sql
@@ -190,7 +190,6 @@ jobs:
190190
env:
191191
CLUSTER_USER: "admin"
192192
CLUSTER_ENDPOINT: ${{ needs.create-cluster.outputs.cluster-endpoint }}
193-
REGION: ${{ needs.create-cluster.outputs.region }}
194193
run: |
195194
npm run sample
196195
@@ -199,11 +198,7 @@ jobs:
199198
env:
200199
CLUSTER_USER: "admin"
201200
CLUSTER_ENDPOINT: ${{ needs.create-cluster.outputs.cluster-endpoint }}
202-
REGION: ${{ needs.create-cluster.outputs.region }}
203201
run: |
204-
source /tmp/generate-prisma-url.sh
205-
configure_credentials $CLUSTER_USER
206-
207202
npm run prisma:migrate-down
208203
209204
- name: Create non-admin role
@@ -216,8 +211,8 @@ jobs:
216211
CLUSTER_ENDPOINT: ${{ needs.create-cluster.outputs.cluster-endpoint }}
217212
REGION: ${{ needs.create-cluster.outputs.region }}
218213
run: |
219-
source /tmp/generate-prisma-url.sh
220-
configure_credentials $ADMIN_USER
214+
source /tmp/configure-psql.sh
215+
configure_psql $ADMIN_USER
221216
222217
# Ensure clean state first.
223218
psql -c "REVOKE ALL PRIVILEGES ON SCHEMA \"$NON_ADMIN_SCHEMA\" FROM \"$NON_ADMIN_USER\"" || true
@@ -234,13 +229,8 @@ jobs:
234229
working-directory: ./typescript/prisma
235230
env:
236231
CLUSTER_USER: "myuser"
237-
NON_ADMIN_SCHEMA: "myschema"
238232
CLUSTER_ENDPOINT: ${{ needs.create-cluster.outputs.cluster-endpoint }}
239-
REGION: ${{ needs.create-cluster.outputs.region }}
240233
run: |
241-
source /tmp/generate-prisma-url.sh
242-
configure_credentials $CLUSTER_USER
243-
244234
# Ensure clean state first.
245235
npm run prisma:migrate-down
246236
@@ -251,21 +241,15 @@ jobs:
251241
env:
252242
CLUSTER_USER: "myuser"
253243
CLUSTER_ENDPOINT: ${{ needs.create-cluster.outputs.cluster-endpoint }}
254-
REGION: ${{ needs.create-cluster.outputs.region }}
255244
run: |
256245
npm run sample
257246
258247
- name: Clean non-admin schema
259248
working-directory: ./typescript/prisma
260249
env:
261250
CLUSTER_USER: "myuser"
262-
NON_ADMIN_SCHEMA: "myschema"
263251
CLUSTER_ENDPOINT: ${{ needs.create-cluster.outputs.cluster-endpoint }}
264-
REGION: ${{ needs.create-cluster.outputs.region }}
265252
run: |
266-
source /tmp/generate-prisma-url.sh
267-
configure_credentials $CLUSTER_USER
268-
269253
npm run prisma:migrate-down
270254
271255
- name: Clean non-admin role
@@ -278,8 +262,8 @@ jobs:
278262
CLUSTER_ENDPOINT: ${{ needs.create-cluster.outputs.cluster-endpoint }}
279263
REGION: ${{ needs.create-cluster.outputs.region }}
280264
run: |
281-
source /tmp/generate-prisma-url.sh
282-
configure_credentials $ADMIN_USER
265+
source /tmp/configure-psql.sh
266+
configure_psql $ADMIN_USER
283267
284268
psql -c "REVOKE ALL PRIVILEGES ON SCHEMA \"$NON_ADMIN_SCHEMA\" FROM \"$NON_ADMIN_USER\""
285269
psql -c "DROP SCHEMA \"$NON_ADMIN_SCHEMA\" CASCADE"

typescript/prisma/README.md

Lines changed: 14 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ For more control over each step, you can run the tools separately:
5656
# Generate and transform in one step
5757
npx prisma migrate diff \
5858
--from-empty \
59-
--to-schema-datamodel prisma/schema.prisma \
59+
--to-schema prisma/schema.prisma \
6060
--script | npm run dsql-transform > prisma/migrations/001_init/migration.sql
6161
```
6262
@@ -117,7 +117,7 @@ npm run dsql-transform raw.sql -o migration.sql
117117
# Transform using pipes (recommended)
118118
npx prisma migrate diff \
119119
--from-empty \
120-
--to-schema-datamodel prisma/schema.prisma \
120+
--to-schema prisma/schema.prisma \
121121
--script | npm run dsql-transform > migration.sql
122122
```
123123
@@ -170,15 +170,15 @@ Note: The foreign key constraint is automatically removed since DSQL doesn't sup
170170
171171
## Incremental Migrations
172172
173-
After your initial deployment, when you need to make schema changes (add columns, tables, indexes), use the `--from-url` option to generate a migration that only includes the differences:
173+
After your initial deployment, when you need to make schema changes (add columns, tables, indexes), use the `--from-config-datasource` option to generate a migration that only includes the differences:
174174
175175
```bash
176176
npm run dsql-migrate prisma/schema.prisma \
177177
-o prisma/migrations/002_add_email/migration.sql \
178-
--from-url "$DATABASE_URL"
178+
--from-config-datasource
179179
```
180180
181-
This compares your updated schema against the live database and generates only the necessary changes.
181+
This compares your updated schema against the live database (using credentials from `prisma.config.ts`) and generates only the necessary changes.
182182
183183
### Migration Ordering
184184
@@ -217,7 +217,7 @@ If the primary key isn't actually changing (Prisma is just being cautious), use
217217
```bash
218218
npm run dsql-migrate prisma/schema.prisma \
219219
-o prisma/migrations/002_add_email/migration.sql \
220-
--from-url "$DATABASE_URL" \
220+
--from-config-datasource \
221221
--force
222222
```
223223

@@ -289,7 +289,7 @@ npm install
289289

290290
### Set environment variables
291291

292-
Set environment variables for your cluster details:
292+
Set environment variables for your cluster details. These are required for all Prisma commands:
293293

294294
```bash
295295
# e.g. "admin"
@@ -299,30 +299,18 @@ export CLUSTER_USER="<your user>"
299299
export CLUSTER_ENDPOINT="<your endpoint>"
300300
```
301301

302-
### Database migrations
303-
304-
Before running the example, you need to apply database migrations to create the required tables. Prisma's migration
305-
tool requires a `DATABASE_URL` environment variable with authentication credentials.
302+
### Build the project
306303

307-
Generate an authentication token following the instructions in
308-
the [Aurora DSQL authentication token guide](https://docs.aws.amazon.com/aurora-dsql/latest/userguide/SECTION_authentication-token.html)
309-
and set it as the `CLUSTER_PASSWORD` environment variable, then set up the database URL:
304+
Build the TypeScript code:
310305

311306
```bash
312-
# Set schema based on user type.
313-
if [ "$CLUSTER_USER" = "admin" ]; then
314-
export SCHEMA="public"
315-
else
316-
export SCHEMA="myschema"
317-
fi
318-
319-
# URL-encode password for consumption by Prisma.
320-
export ENCODED_PASSWORD=$(python -c "from urllib.parse import quote; print(quote('$CLUSTER_PASSWORD', safe=''))")
321-
322-
# Set up DATABASE_URL for Prisma migrations.
323-
export DATABASE_URL="postgresql://$CLUSTER_USER:$ENCODED_PASSWORD@$CLUSTER_ENDPOINT:5432/postgres?sslmode=verify-full&schema=$SCHEMA"
307+
npm run build
324308
```
325309

310+
### Database migrations
311+
312+
Before running the example, you need to apply database migrations to create the required tables. The `prisma.config.ts` file handles IAM authentication automatically using your AWS credentials.
313+
326314
Apply the database migrations:
327315

328316
```bash

typescript/prisma/helpers/cli/index.ts

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,11 @@ Examples:
4242
npm run dsql-migrate prisma/schema.prisma -o prisma/migrations/001_init/migration.sql
4343
4444
# Incremental migration (after schema changes)
45-
npm run dsql-migrate prisma/schema.prisma -o prisma/migrations/002_changes/migration.sql --from-url "$DATABASE_URL"
45+
npm run dsql-migrate prisma/schema.prisma -o prisma/migrations/002_changes/migration.sql --from-config-datasource
4646
4747
# Manual workflow
4848
npm run validate prisma/schema.prisma
49-
npx prisma migrate diff --from-empty --to-schema-datamodel prisma/schema.prisma --script | npm run dsql-transform > migration.sql
49+
npx prisma migrate diff --from-empty --to-schema prisma/schema.prisma --script | npm run dsql-transform > migration.sql
5050
`;
5151

5252
async function main(): Promise<void> {
@@ -118,14 +118,15 @@ Examples:
118118
npm run dsql-migrate prisma/schema.prisma -o prisma/migrations/001_init/migration.sql
119119
120120
# Incremental migration (after schema changes)
121-
npm run dsql-migrate prisma/schema.prisma -o prisma/migrations/002_changes/migration.sql --from-url "$DATABASE_URL"
121+
npm run dsql-migrate prisma/schema.prisma -o prisma/migrations/002_changes/migration.sql --from-config-datasource
122122
`);
123123
process.exit(0);
124124
}
125125

126126
let schemaPath: string | null = null;
127127
let outputFile: string | null = null;
128128
let fromUrl: string | null = null;
129+
let fromConfigDatasource = false;
129130
let fromEmpty = false;
130131
let includeHeader = true;
131132
let force = false;
@@ -140,6 +141,8 @@ Examples:
140141
console.error("Error: --from-url requires a URL argument");
141142
process.exit(1);
142143
}
144+
} else if (args[i] === "--from-config-datasource") {
145+
fromConfigDatasource = true;
143146
} else if (args[i] === "--from-empty") {
144147
fromEmpty = true;
145148
} else if (args[i] === "--no-header") {
@@ -168,7 +171,7 @@ Examples:
168171
}
169172

170173
// Default to --from-empty if no --from-* option specified
171-
if (!fromUrl && !fromEmpty) {
174+
if (!fromUrl && !fromConfigDatasource && !fromEmpty) {
172175
fromEmpty = true;
173176
}
174177

@@ -193,11 +196,18 @@ Examples:
193196
}
194197

195198
// Step 2: Generate migration using Prisma
196-
const fromSource = fromUrl ? "database" : "empty";
199+
const fromSource = fromUrl || fromConfigDatasource ? "database" : "empty";
197200
console.log(`\nGenerating migration (from ${fromSource})...`);
198201

199-
const fromArg = fromUrl ? `--from-url "${fromUrl}"` : "--from-empty";
200-
const prismaCmd = `npx prisma migrate diff ${fromArg} --to-schema-datamodel "${schemaPath}" --script`;
202+
let fromArg: string;
203+
if (fromUrl) {
204+
fromArg = `--from-url "${fromUrl}"`;
205+
} else if (fromConfigDatasource) {
206+
fromArg = "--from-config-datasource";
207+
} else {
208+
fromArg = "--from-empty";
209+
}
210+
const prismaCmd = `npx prisma migrate diff ${fromArg} --to-schema "${schemaPath}" --script`;
201211

202212
let rawSql: string;
203213
try {
@@ -282,7 +292,7 @@ Examples:
282292
npm run dsql-transform raw.sql -o migration.sql
283293
284294
# Transform using pipes
285-
npx prisma migrate diff --from-empty --to-schema-datamodel prisma/schema.prisma --script | npm run dsql-transform > migration.sql
295+
npx prisma migrate diff --from-empty --to-schema prisma/schema.prisma --script | npm run dsql-transform > migration.sql
286296
287297
# Without header comment
288298
npm run dsql-transform raw.sql --no-header -o migration.sql

0 commit comments

Comments
 (0)