@prisma-next/target-postgres 0.3.0-dev.40 → 0.3.0-dev.43
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/dist/control.d.mts.map +1 -1
- package/dist/control.mjs +149 -53
- package/dist/control.mjs.map +1 -1
- package/package.json +14 -14
- package/src/core/migrations/planner.ts +80 -10
- package/src/core/migrations/statement-builders.ts +3 -1
package/package.json
CHANGED
|
@@ -1,29 +1,29 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prisma-next/target-postgres",
|
|
3
|
-
"version": "0.3.0-dev.
|
|
3
|
+
"version": "0.3.0-dev.43",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"description": "Postgres target pack for Prisma Next",
|
|
7
7
|
"dependencies": {
|
|
8
8
|
"arktype": "^2.0.0",
|
|
9
|
-
"@prisma-next/cli": "0.3.0-dev.
|
|
10
|
-
"@prisma-next/contract": "0.3.0-dev.
|
|
11
|
-
"@prisma-next/core-control-plane": "0.3.0-dev.
|
|
12
|
-
"@prisma-next/core-execution-plane": "0.3.0-dev.
|
|
13
|
-
"@prisma-next/family-sql": "0.3.0-dev.
|
|
14
|
-
"@prisma-next/sql-
|
|
15
|
-
"@prisma-next/sql-
|
|
16
|
-
"@prisma-next/sql-
|
|
17
|
-
"@prisma-next/sql-
|
|
18
|
-
"@prisma-next/
|
|
19
|
-
"@prisma-next/
|
|
9
|
+
"@prisma-next/cli": "0.3.0-dev.43",
|
|
10
|
+
"@prisma-next/contract": "0.3.0-dev.43",
|
|
11
|
+
"@prisma-next/core-control-plane": "0.3.0-dev.43",
|
|
12
|
+
"@prisma-next/core-execution-plane": "0.3.0-dev.43",
|
|
13
|
+
"@prisma-next/family-sql": "0.3.0-dev.43",
|
|
14
|
+
"@prisma-next/sql-errors": "0.3.0-dev.43",
|
|
15
|
+
"@prisma-next/sql-contract": "0.3.0-dev.43",
|
|
16
|
+
"@prisma-next/sql-relational-core": "0.3.0-dev.43",
|
|
17
|
+
"@prisma-next/sql-schema-ir": "0.3.0-dev.43",
|
|
18
|
+
"@prisma-next/utils": "0.3.0-dev.43",
|
|
19
|
+
"@prisma-next/sql-runtime": "0.3.0-dev.43"
|
|
20
20
|
},
|
|
21
21
|
"devDependencies": {
|
|
22
22
|
"tsdown": "0.18.4",
|
|
23
23
|
"typescript": "5.9.3",
|
|
24
24
|
"vitest": "4.0.17",
|
|
25
|
-
"@prisma-next/adapter-postgres": "0.3.0-dev.
|
|
26
|
-
"@prisma-next/driver-postgres": "0.3.0-dev.
|
|
25
|
+
"@prisma-next/adapter-postgres": "0.3.0-dev.43",
|
|
26
|
+
"@prisma-next/driver-postgres": "0.3.0-dev.43",
|
|
27
27
|
"@prisma-next/test-utils": "0.0.1",
|
|
28
28
|
"@prisma-next/tsconfig": "0.0.0",
|
|
29
29
|
"@prisma-next/tsdown": "0.0.0"
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
parsePostgresDefault,
|
|
6
6
|
quoteIdentifier,
|
|
7
7
|
} from '@prisma-next/adapter-postgres/control';
|
|
8
|
+
import { isTaggedBigInt } from '@prisma-next/contract/types';
|
|
8
9
|
import type { SchemaIssue } from '@prisma-next/core-control-plane/types';
|
|
9
10
|
import type {
|
|
10
11
|
CodecControlHooks,
|
|
@@ -28,6 +29,7 @@ import {
|
|
|
28
29
|
} from '@prisma-next/family-sql/schema-verify';
|
|
29
30
|
import type {
|
|
30
31
|
ForeignKey,
|
|
32
|
+
ReferentialAction,
|
|
31
33
|
SqlContract,
|
|
32
34
|
SqlStorage,
|
|
33
35
|
StorageColumn,
|
|
@@ -634,12 +636,7 @@ UNIQUE (${unique.columns.map(quoteIdentifier).join(', ')})`,
|
|
|
634
636
|
execute: [
|
|
635
637
|
{
|
|
636
638
|
description: `add foreign key "${fkName}"`,
|
|
637
|
-
sql:
|
|
638
|
-
ADD CONSTRAINT ${quoteIdentifier(fkName)}
|
|
639
|
-
FOREIGN KEY (${foreignKey.columns.map(quoteIdentifier).join(', ')})
|
|
640
|
-
REFERENCES ${qualifyTableName(schemaName, foreignKey.references.table)} (${foreignKey.references.columns
|
|
641
|
-
.map(quoteIdentifier)
|
|
642
|
-
.join(', ')})`,
|
|
639
|
+
sql: buildForeignKeySql(schemaName, tableName, fkName, foreignKey),
|
|
643
640
|
},
|
|
644
641
|
],
|
|
645
642
|
postcheck: [
|
|
@@ -781,7 +778,7 @@ function buildCreateTableSql(qualifiedTableName: string, table: StorageTable): s
|
|
|
781
778
|
const parts = [
|
|
782
779
|
quoteIdentifier(columnName),
|
|
783
780
|
buildColumnTypeSql(column),
|
|
784
|
-
buildColumnDefaultSql(column.default),
|
|
781
|
+
buildColumnDefaultSql(column.default, column),
|
|
785
782
|
column.nullable ? '' : 'NOT NULL',
|
|
786
783
|
].filter(Boolean);
|
|
787
784
|
return parts.join(' ');
|
|
@@ -855,14 +852,17 @@ function renderParameterizedTypeSql(column: StorageColumn): string | null {
|
|
|
855
852
|
*
|
|
856
853
|
* Note: autoincrement is handled specially via SERIAL types, so we skip it here.
|
|
857
854
|
*/
|
|
858
|
-
function buildColumnDefaultSql(
|
|
855
|
+
function buildColumnDefaultSql(
|
|
856
|
+
columnDefault: PostgresColumnDefault | undefined,
|
|
857
|
+
column?: StorageColumn,
|
|
858
|
+
): string {
|
|
859
859
|
if (!columnDefault) {
|
|
860
860
|
return '';
|
|
861
861
|
}
|
|
862
862
|
|
|
863
863
|
switch (columnDefault.kind) {
|
|
864
864
|
case 'literal':
|
|
865
|
-
return `DEFAULT ${columnDefault.
|
|
865
|
+
return `DEFAULT ${renderDefaultLiteral(columnDefault.value, column)}`;
|
|
866
866
|
case 'function': {
|
|
867
867
|
// autoincrement is handled by SERIAL type, no explicit DEFAULT needed
|
|
868
868
|
if (columnDefault.expression === 'autoincrement()') {
|
|
@@ -876,6 +876,37 @@ function buildColumnDefaultSql(columnDefault: PostgresColumnDefault | undefined)
|
|
|
876
876
|
}
|
|
877
877
|
}
|
|
878
878
|
|
|
879
|
+
function renderDefaultLiteral(value: unknown, column?: StorageColumn): string {
|
|
880
|
+
const isJsonColumn = column?.nativeType === 'json' || column?.nativeType === 'jsonb';
|
|
881
|
+
|
|
882
|
+
if (value instanceof Date) {
|
|
883
|
+
return `'${escapeLiteral(value.toISOString())}'`;
|
|
884
|
+
}
|
|
885
|
+
if (!isJsonColumn && isTaggedBigInt(value)) {
|
|
886
|
+
if (!/^-?\d+$/.test(value.value)) {
|
|
887
|
+
throw new Error(`Invalid tagged bigint value: "${value.value}" is not a valid integer`);
|
|
888
|
+
}
|
|
889
|
+
return value.value;
|
|
890
|
+
}
|
|
891
|
+
if (typeof value === 'bigint') {
|
|
892
|
+
return value.toString();
|
|
893
|
+
}
|
|
894
|
+
if (typeof value === 'string') {
|
|
895
|
+
return `'${escapeLiteral(value)}'`;
|
|
896
|
+
}
|
|
897
|
+
if (typeof value === 'number' || typeof value === 'boolean') {
|
|
898
|
+
return String(value);
|
|
899
|
+
}
|
|
900
|
+
if (value === null) {
|
|
901
|
+
return 'NULL';
|
|
902
|
+
}
|
|
903
|
+
const json = JSON.stringify(value);
|
|
904
|
+
if (isJsonColumn) {
|
|
905
|
+
return `'${escapeLiteral(json)}'::${column.nativeType}`;
|
|
906
|
+
}
|
|
907
|
+
return `'${escapeLiteral(json)}'`;
|
|
908
|
+
}
|
|
909
|
+
|
|
879
910
|
function qualifyTableName(schema: string, table: string): string {
|
|
880
911
|
return `${quoteIdentifier(schema)}.${quoteIdentifier(table)}`;
|
|
881
912
|
}
|
|
@@ -957,7 +988,7 @@ function buildAddColumnSql(
|
|
|
957
988
|
column: StorageColumn,
|
|
958
989
|
): string {
|
|
959
990
|
const typeSql = buildColumnTypeSql(column);
|
|
960
|
-
const defaultSql = buildColumnDefaultSql(column.default);
|
|
991
|
+
const defaultSql = buildColumnDefaultSql(column.default, column);
|
|
961
992
|
const parts = [
|
|
962
993
|
`ALTER TABLE ${qualifiedTableName}`,
|
|
963
994
|
`ADD COLUMN ${quoteIdentifier(columnName)} ${typeSql}`,
|
|
@@ -1088,3 +1119,42 @@ function compareStrings(a?: string, b?: string): number {
|
|
|
1088
1119
|
}
|
|
1089
1120
|
return a < b ? -1 : 1;
|
|
1090
1121
|
}
|
|
1122
|
+
|
|
1123
|
+
const REFERENTIAL_ACTION_SQL: Record<ReferentialAction, string> = {
|
|
1124
|
+
noAction: 'NO ACTION',
|
|
1125
|
+
restrict: 'RESTRICT',
|
|
1126
|
+
cascade: 'CASCADE',
|
|
1127
|
+
setNull: 'SET NULL',
|
|
1128
|
+
setDefault: 'SET DEFAULT',
|
|
1129
|
+
};
|
|
1130
|
+
|
|
1131
|
+
function buildForeignKeySql(
|
|
1132
|
+
schemaName: string,
|
|
1133
|
+
tableName: string,
|
|
1134
|
+
fkName: string,
|
|
1135
|
+
foreignKey: ForeignKey,
|
|
1136
|
+
): string {
|
|
1137
|
+
let sql = `ALTER TABLE ${qualifyTableName(schemaName, tableName)}
|
|
1138
|
+
ADD CONSTRAINT ${quoteIdentifier(fkName)}
|
|
1139
|
+
FOREIGN KEY (${foreignKey.columns.map(quoteIdentifier).join(', ')})
|
|
1140
|
+
REFERENCES ${qualifyTableName(schemaName, foreignKey.references.table)} (${foreignKey.references.columns
|
|
1141
|
+
.map(quoteIdentifier)
|
|
1142
|
+
.join(', ')})`;
|
|
1143
|
+
|
|
1144
|
+
if (foreignKey.onDelete !== undefined) {
|
|
1145
|
+
const action = REFERENTIAL_ACTION_SQL[foreignKey.onDelete];
|
|
1146
|
+
if (!action) {
|
|
1147
|
+
throw new Error(`Unknown referential action for onDelete: ${String(foreignKey.onDelete)}`);
|
|
1148
|
+
}
|
|
1149
|
+
sql += `\nON DELETE ${action}`;
|
|
1150
|
+
}
|
|
1151
|
+
if (foreignKey.onUpdate !== undefined) {
|
|
1152
|
+
const action = REFERENTIAL_ACTION_SQL[foreignKey.onUpdate];
|
|
1153
|
+
if (!action) {
|
|
1154
|
+
throw new Error(`Unknown referential action for onUpdate: ${String(foreignKey.onUpdate)}`);
|
|
1155
|
+
}
|
|
1156
|
+
sql += `\nON UPDATE ${action}`;
|
|
1157
|
+
}
|
|
1158
|
+
|
|
1159
|
+
return sql;
|
|
1160
|
+
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { bigintJsonReplacer } from '@prisma-next/contract/types';
|
|
2
|
+
|
|
1
3
|
export interface SqlStatement {
|
|
2
4
|
readonly sql: string;
|
|
3
5
|
readonly params: readonly unknown[];
|
|
@@ -140,5 +142,5 @@ export function buildLedgerInsertStatement(input: LedgerInsertInput): SqlStateme
|
|
|
140
142
|
}
|
|
141
143
|
|
|
142
144
|
function jsonParam(value: unknown): string {
|
|
143
|
-
return JSON.stringify(value ?? null);
|
|
145
|
+
return JSON.stringify(value ?? null, bigintJsonReplacer);
|
|
144
146
|
}
|