@prisma-next/target-postgres 0.4.0-dev.6 → 0.4.0-dev.7

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/dist/control.mjs CHANGED
@@ -4,13 +4,15 @@ import { LiteralExpr, SQL_CHAR_CODEC_ID, SQL_FLOAT_CODEC_ID, SQL_INT_CODEC_ID, S
4
4
  import { ifDefined } from "@prisma-next/utils/defined";
5
5
  import { type } from "arktype";
6
6
  import { arraysEqual, verifySqlSchema } from "@prisma-next/family-sql/schema-verify";
7
- import { collectInitDependencies, contractToSchemaIR, createMigrationPlan, extractCodecControlHooks, plannerFailure, plannerSuccess, runnerFailure, runnerSuccess } from "@prisma-next/family-sql/control";
7
+ import { collectInitDependencies, contractToSchemaIR, createMigrationPlan, extractCodecControlHooks, plannerFailure, runnerFailure, runnerSuccess } from "@prisma-next/family-sql/control";
8
8
  import { MigrationDescriptorArraySchema } from "@prisma-next/family-sql/operation-descriptors";
9
9
  import { sql } from "@prisma-next/sql-builder/runtime";
10
10
  import { notOk, ok, okVoid } from "@prisma-next/utils/result";
11
11
  import { lowerSqlPlan } from "@prisma-next/sql-runtime";
12
+ import { errorPlanDoesNotSupportAuthoringSurface } from "@prisma-next/errors/migration";
12
13
  import { defaultIndexName } from "@prisma-next/sql-schema-ir/naming";
13
14
  import { invariant } from "@prisma-next/utils/assertions";
15
+ import { relative } from "pathe";
14
16
  import { readMarker } from "@prisma-next/family-sql/verify";
15
17
  import { SqlQueryError } from "@prisma-next/sql-errors";
16
18
 
@@ -4299,6 +4301,94 @@ function hasForeignKey(lookup, fk) {
4299
4301
  return lookup.fkKeys.has(`${fk.columns.join(",")}|${fk.references.table}|${fk.references.columns.join(",")}`);
4300
4302
  }
4301
4303
 
4304
+ //#endregion
4305
+ //#region src/core/migrations/scaffolding.ts
4306
+ function serializeQueryInput(input) {
4307
+ if (typeof input === "boolean") return String(input);
4308
+ if (typeof input === "symbol") return "TODO /* fill in using db.sql.from(...) */";
4309
+ if (input === null || input === void 0) return "null";
4310
+ if (Array.isArray(input)) {
4311
+ if (input.length === 0) return "[]";
4312
+ if (input.every((item) => typeof item === "symbol")) return "[TODO /* fill in using db.sql.from(...) */]";
4313
+ return `[${input.map(serializeQueryInput).join(", ")}]`;
4314
+ }
4315
+ return JSON.stringify(input);
4316
+ }
4317
+ function renderDescriptor(desc) {
4318
+ switch (desc.kind) {
4319
+ case "createTable": return `createTable(${JSON.stringify(desc["table"])})`;
4320
+ case "dropTable": return `dropTable(${JSON.stringify(desc["table"])})`;
4321
+ case "addColumn": {
4322
+ const args = [JSON.stringify(desc["table"]), JSON.stringify(desc["column"])];
4323
+ if (desc["overrides"]) args.push(JSON.stringify(desc["overrides"]));
4324
+ return `addColumn(${args.join(", ")})`;
4325
+ }
4326
+ case "dropColumn": return `dropColumn(${JSON.stringify(desc["table"])}, ${JSON.stringify(desc["column"])})`;
4327
+ case "alterColumnType": {
4328
+ const opts = {};
4329
+ if (desc["using"]) opts["using"] = desc["using"];
4330
+ if (desc["toType"]) opts["toType"] = desc["toType"];
4331
+ return Object.keys(opts).length > 0 ? `alterColumnType(${JSON.stringify(desc["table"])}, ${JSON.stringify(desc["column"])}, ${JSON.stringify(opts)})` : `alterColumnType(${JSON.stringify(desc["table"])}, ${JSON.stringify(desc["column"])})`;
4332
+ }
4333
+ case "setNotNull": return `setNotNull(${JSON.stringify(desc["table"])}, ${JSON.stringify(desc["column"])})`;
4334
+ case "dropNotNull": return `dropNotNull(${JSON.stringify(desc["table"])}, ${JSON.stringify(desc["column"])})`;
4335
+ case "setDefault": return `setDefault(${JSON.stringify(desc["table"])}, ${JSON.stringify(desc["column"])})`;
4336
+ case "dropDefault": return `dropDefault(${JSON.stringify(desc["table"])}, ${JSON.stringify(desc["column"])})`;
4337
+ case "addPrimaryKey": return `addPrimaryKey(${JSON.stringify(desc["table"])})`;
4338
+ case "addUnique": return `addUnique(${JSON.stringify(desc["table"])}, ${JSON.stringify(desc["columns"])})`;
4339
+ case "addForeignKey": return `addForeignKey(${JSON.stringify(desc["table"])}, ${JSON.stringify(desc["columns"])})`;
4340
+ case "dropConstraint": return `dropConstraint(${JSON.stringify(desc["table"])}, ${JSON.stringify(desc["constraintName"])})`;
4341
+ case "createIndex": return `createIndex(${JSON.stringify(desc["table"])}, ${JSON.stringify(desc["columns"])})`;
4342
+ case "dropIndex": return `dropIndex(${JSON.stringify(desc["table"])}, ${JSON.stringify(desc["indexName"])})`;
4343
+ case "createEnumType": return desc["values"] ? `createEnumType(${JSON.stringify(desc["typeName"])}, ${JSON.stringify(desc["values"])})` : `createEnumType(${JSON.stringify(desc["typeName"])})`;
4344
+ case "addEnumValues": return `addEnumValues(${JSON.stringify(desc["typeName"])}, ${JSON.stringify(desc["values"])})`;
4345
+ case "dropEnumType": return `dropEnumType(${JSON.stringify(desc["typeName"])})`;
4346
+ case "renameType": return `renameType(${JSON.stringify(desc["fromName"])}, ${JSON.stringify(desc["toName"])})`;
4347
+ case "createDependency": return `createDependency(${JSON.stringify(desc["dependencyId"])})`;
4348
+ case "dataTransform": return `dataTransform(${JSON.stringify(desc["name"])}, {\n check: ${serializeQueryInput(desc["check"])},\n run: ${serializeQueryInput(desc["run"])},\n })`;
4349
+ default: throw new Error(`Unknown Postgres descriptor kind: ${desc.kind}`);
4350
+ }
4351
+ }
4352
+ function renderPreamble(plan, context) {
4353
+ const hasDataTransform = plan.some((d) => d.kind === "dataTransform");
4354
+ if (hasDataTransform && context.contractJsonPath) {
4355
+ const relativeContractDts = relative(context.packageDir, context.contractJsonPath).replace(/\.json$/, ".d");
4356
+ const importList$1 = [...new Set(plan.map((d) => d.kind))];
4357
+ importList$1.push("TODO");
4358
+ return [
4359
+ `import type { Contract } from "${relativeContractDts}"`,
4360
+ `import { createBuilders } from "@prisma-next/target-postgres/migration-builders"`,
4361
+ "",
4362
+ `const { ${importList$1.join(", ")} } = createBuilders<Contract>()`
4363
+ ];
4364
+ }
4365
+ const importList = [...new Set(plan.map((d) => d.kind))];
4366
+ if (importList.length === 0) importList.push("createTable");
4367
+ if (hasDataTransform) importList.push("TODO");
4368
+ return [`import { ${importList.join(", ")} } from "@prisma-next/target-postgres/migration-builders"`];
4369
+ }
4370
+ /**
4371
+ * Render a Postgres descriptor list to a `migration.ts` source string.
4372
+ *
4373
+ * Internal to the Postgres target — no longer part of the framework SPI.
4374
+ * Invoked from two paths:
4375
+ * - the migrations capability's `renderDescriptorTypeScript` hook (called by
4376
+ * the CLI after `planWithDescriptors` to seed an editable authoring
4377
+ * surface, and by `emptyMigration()` to produce the `migration new` stub);
4378
+ * - directly by this package's unit tests.
4379
+ */
4380
+ function renderDescriptorTypeScript(descriptors, context) {
4381
+ const preamble = renderPreamble(descriptors, context);
4382
+ const calls = descriptors.map((d) => ` ${renderDescriptor(d)},`);
4383
+ const body = calls.length > 0 ? `\n${calls.join("\n")}\n` : "";
4384
+ return [
4385
+ ...preamble,
4386
+ "",
4387
+ `export default () => [${body}]`,
4388
+ ""
4389
+ ].join("\n");
4390
+ }
4391
+
4302
4392
  //#endregion
4303
4393
  //#region src/core/migrations/planner.ts
4304
4394
  const DEFAULT_PLANNER_CONFIG = { defaultSchema: "public" };
@@ -4308,11 +4398,43 @@ function createPostgresMigrationPlanner(config = {}) {
4308
4398
  ...config
4309
4399
  });
4310
4400
  }
4401
+ /**
4402
+ * Postgres migration planner.
4403
+ *
4404
+ * Implements the framework's `MigrationPlanner<'sql', 'postgres'>` directly
4405
+ * — meaning it owns `emptyMigration()` and attaches the `renderTypeScript()`
4406
+ * stub to success plans (Postgres uses descriptor-flow authoring, so
4407
+ * `renderTypeScript()` throws on planner-produced plans). No external wrapper
4408
+ * is required at the descriptor level.
4409
+ *
4410
+ * `plan()` accepts the framework's option shape (with `contract`/`schema`
4411
+ * typed as `unknown`); SQL-typed callers may pass the more specific
4412
+ * `SqlMigrationPlannerPlanOptions`, since those structurally satisfy the
4413
+ * looser framework contract. Internally we treat options as the SQL-typed
4414
+ * superset so the existing planner logic stays identical.
4415
+ *
4416
+ * `fromHash` is accepted but ignored: Postgres is descriptor-flow and never
4417
+ * needs it (only class-flow planners like Mongo populate `describe()` from
4418
+ * `fromHash`).
4419
+ */
4311
4420
  var PostgresMigrationPlanner = class {
4312
4421
  constructor(config) {
4313
4422
  this.config = config;
4314
4423
  }
4315
4424
  plan(options) {
4425
+ return this.planSql(options);
4426
+ }
4427
+ emptyMigration(context) {
4428
+ return {
4429
+ targetId: "postgres",
4430
+ destination: { storageHash: context.toHash },
4431
+ operations: [],
4432
+ renderTypeScript() {
4433
+ return renderDescriptorTypeScript([], context);
4434
+ }
4435
+ };
4436
+ }
4437
+ planSql(options) {
4316
4438
  const schemaName = options.schemaName ?? this.config.defaultSchema;
4317
4439
  const policyResult = this.ensureAdditivePolicy(options.policy);
4318
4440
  if (policyResult) return policyResult;
@@ -4335,7 +4457,7 @@ var PostgresMigrationPlanner = class {
4335
4457
  const sortedTables = sortedEntries(options.contract.storage.tables);
4336
4458
  const schemaLookups = buildSchemaLookupMap(options.schema);
4337
4459
  operations.push(...this.buildDatabaseDependencyOperations(options), ...storageTypePlan.operations, ...reconciliationPlan.operations, ...this.buildTableOperations(sortedTables, options.schema, schemaName, codecHooks, storageTypes), ...this.buildColumnOperations(sortedTables, options.schema, schemaLookups, schemaName, codecHooks, storageTypes), ...this.buildPrimaryKeyOperations(sortedTables, options.schema, schemaName), ...this.buildUniqueOperations(sortedTables, schemaLookups, schemaName), ...this.buildIndexOperations(sortedTables, schemaLookups, schemaName), ...this.buildFkBackingIndexOperations(sortedTables, schemaLookups, schemaName), ...this.buildForeignKeyOperations(sortedTables, schemaLookups, schemaName));
4338
- return plannerSuccess(createMigrationPlan({
4460
+ const plan = createMigrationPlan({
4339
4461
  targetId: "postgres",
4340
4462
  origin: null,
4341
4463
  destination: {
@@ -4343,7 +4465,16 @@ var PostgresMigrationPlanner = class {
4343
4465
  ...ifDefined("profileHash", options.contract.profileHash)
4344
4466
  },
4345
4467
  operations
4346
- }));
4468
+ });
4469
+ return Object.freeze({
4470
+ kind: "success",
4471
+ plan: Object.freeze({
4472
+ ...plan,
4473
+ renderTypeScript() {
4474
+ throw errorPlanDoesNotSupportAuthoringSurface({ targetId: "postgres" });
4475
+ }
4476
+ })
4477
+ });
4347
4478
  }
4348
4479
  ensureAdditivePolicy(policy) {
4349
4480
  if (!policy.allowedOperationClasses.includes("additive")) return plannerFailure([{
@@ -5328,6 +5459,9 @@ const postgresTargetDescriptor = {
5328
5459
  dependencies,
5329
5460
  db
5330
5461
  });
5462
+ },
5463
+ renderDescriptorTypeScript(descriptors, context) {
5464
+ return renderDescriptorTypeScript(descriptors, context);
5331
5465
  }
5332
5466
  },
5333
5467
  create() {