@prisma-next/cli 0.3.0-dev.13 → 0.3.0-dev.15

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.
Files changed (52) hide show
  1. package/README.md +109 -25
  2. package/dist/{chunk-CVNWLFXO.js → chunk-6EPKRATC.js} +2 -2
  3. package/dist/{chunk-BZMBKEEQ.js → chunk-DIJPT5TZ.js} +3 -33
  4. package/dist/chunk-DIJPT5TZ.js.map +1 -0
  5. package/dist/{chunk-QUPBU4KV.js → chunk-MG7PBERL.js} +2 -2
  6. package/dist/chunk-VI2YETW7.js +38 -0
  7. package/dist/chunk-VI2YETW7.js.map +1 -0
  8. package/dist/cli.js +34 -38
  9. package/dist/cli.js.map +1 -1
  10. package/dist/commands/contract-emit.js +3 -2
  11. package/dist/commands/db-init.d.ts.map +1 -1
  12. package/dist/commands/db-init.js +21 -19
  13. package/dist/commands/db-init.js.map +1 -1
  14. package/dist/commands/db-introspect.d.ts.map +1 -1
  15. package/dist/commands/db-introspect.js +13 -16
  16. package/dist/commands/db-introspect.js.map +1 -1
  17. package/dist/commands/db-schema-verify.d.ts.map +1 -1
  18. package/dist/commands/db-schema-verify.js +8 -7
  19. package/dist/commands/db-schema-verify.js.map +1 -1
  20. package/dist/commands/db-sign.js +8 -7
  21. package/dist/commands/db-sign.js.map +1 -1
  22. package/dist/commands/db-verify.d.ts.map +1 -1
  23. package/dist/commands/db-verify.js +8 -7
  24. package/dist/commands/db-verify.js.map +1 -1
  25. package/dist/control-api/client.d.ts +13 -0
  26. package/dist/control-api/client.d.ts.map +1 -0
  27. package/dist/control-api/operations/db-init.d.ts +27 -0
  28. package/dist/control-api/operations/db-init.d.ts.map +1 -0
  29. package/dist/control-api/types.d.ts +203 -0
  30. package/dist/control-api/types.d.ts.map +1 -0
  31. package/dist/exports/control-api.d.ts +13 -0
  32. package/dist/exports/control-api.d.ts.map +1 -0
  33. package/dist/exports/control-api.js +240 -0
  34. package/dist/exports/control-api.js.map +1 -0
  35. package/dist/exports/index.js +3 -2
  36. package/dist/exports/index.js.map +1 -1
  37. package/dist/utils/cli-errors.d.ts +1 -1
  38. package/dist/utils/cli-errors.d.ts.map +1 -1
  39. package/package.json +15 -11
  40. package/src/commands/db-init.ts +12 -11
  41. package/src/commands/db-introspect.ts +16 -18
  42. package/src/commands/db-schema-verify.ts +6 -7
  43. package/src/commands/db-sign.ts +6 -6
  44. package/src/commands/db-verify.ts +6 -7
  45. package/src/control-api/client.ts +229 -0
  46. package/src/control-api/operations/db-init.ts +167 -0
  47. package/src/control-api/types.ts +251 -0
  48. package/src/exports/control-api.ts +34 -0
  49. package/src/utils/cli-errors.ts +1 -1
  50. package/dist/chunk-BZMBKEEQ.js.map +0 -1
  51. /package/dist/{chunk-CVNWLFXO.js.map → chunk-6EPKRATC.js.map} +0 -0
  52. /package/dist/{chunk-QUPBU4KV.js.map → chunk-MG7PBERL.js.map} +0 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/commands/db-sign.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport { relative, resolve } from 'node:path';\nimport {\n errorDatabaseUrlRequired,\n errorDriverRequired,\n errorFileNotFound,\n errorRuntime,\n errorUnexpected,\n} from '@prisma-next/core-control-plane/errors';\nimport type {\n SignDatabaseResult,\n VerifyDatabaseSchemaResult,\n} from '@prisma-next/core-control-plane/types';\nimport { createControlPlaneStack } from '@prisma-next/core-control-plane/types';\nimport { Command } from 'commander';\nimport { loadConfig } from '../config-loader';\nimport { performAction } from '../utils/action';\nimport { setCommandDescriptions } from '../utils/command-helpers';\nimport {\n assertContractRequirementsSatisfied,\n assertFrameworkComponentsCompatible,\n} from '../utils/framework-components';\nimport { parseGlobalFlags } from '../utils/global-flags';\nimport {\n formatCommandHelp,\n formatSchemaVerifyJson,\n formatSchemaVerifyOutput,\n formatSignJson,\n formatSignOutput,\n formatStyledHeader,\n} from '../utils/output';\nimport { handleResult } from '../utils/result-handler';\nimport { withSpinner } from '../utils/spinner';\n\ninterface DbSignOptions {\n readonly db?: string;\n readonly config?: string;\n readonly json?: string | boolean;\n readonly quiet?: boolean;\n readonly q?: boolean;\n readonly verbose?: boolean;\n readonly v?: boolean;\n readonly vv?: boolean;\n readonly trace?: boolean;\n readonly timestamps?: boolean;\n readonly color?: boolean;\n readonly 'no-color'?: boolean;\n}\n\nexport function createDbSignCommand(): Command {\n const command = new Command('sign');\n setCommandDescriptions(\n command,\n 'Sign the database with your contract so you can safely run queries',\n 'Verifies that your database schema satisfies the emitted contract, and if so, writes or\\n' +\n 'updates the contract marker in the database. This command is idempotent and safe to run\\n' +\n 'in CI/deployment pipelines. The marker records that this database instance is aligned\\n' +\n 'with a specific contract version.',\n );\n command\n .configureHelp({\n formatHelp: (cmd) => {\n const flags = parseGlobalFlags({});\n return formatCommandHelp({ command: cmd, flags });\n },\n })\n .option('--db <url>', 'Database connection string')\n .option('--config <path>', 'Path to prisma-next.config.ts')\n .option('--json [format]', 'Output as JSON (object or ndjson)', false)\n .option('-q, --quiet', 'Quiet mode: errors only')\n .option('-v, --verbose', 'Verbose output: debug info, timings')\n .option('-vv, --trace', 'Trace output: deep internals, stack traces')\n .option('--timestamps', 'Add timestamps to output')\n .option('--color', 'Force color output')\n .option('--no-color', 'Disable color output')\n .action(async (options: DbSignOptions) => {\n const flags = parseGlobalFlags(options);\n\n const result = await performAction(async () => {\n // Load config (file I/O)\n const config = await loadConfig(options.config);\n // Normalize config path for display (match contract path format - no ./ prefix)\n const configPath = options.config\n ? relative(process.cwd(), resolve(options.config))\n : 'prisma-next.config.ts';\n const contractPathAbsolute = config.contract?.output\n ? resolve(config.contract.output)\n : resolve('src/prisma/contract.json');\n // Convert to relative path for display\n const contractPath = relative(process.cwd(), contractPathAbsolute);\n\n // Output header (only for human-readable output)\n if (flags.json !== 'object' && !flags.quiet) {\n const details: Array<{ label: string; value: string }> = [\n { label: 'config', value: configPath },\n { label: 'contract', value: contractPath },\n ];\n if (options.db) {\n details.push({ label: 'database', value: options.db });\n }\n const header = formatStyledHeader({\n command: 'db sign',\n description: 'Sign the database with your contract so you can safely run queries',\n url: 'https://pris.ly/db-sign',\n details,\n flags,\n });\n console.log(header);\n }\n\n // Load contract file (file I/O)\n let contractJsonContent: string;\n try {\n contractJsonContent = await readFile(contractPathAbsolute, 'utf-8');\n } catch (error) {\n if (error instanceof Error && (error as { code?: string }).code === 'ENOENT') {\n throw errorFileNotFound(contractPathAbsolute, {\n why: `Contract file not found at ${contractPathAbsolute}`,\n });\n }\n throw errorUnexpected(error instanceof Error ? error.message : String(error), {\n why: `Failed to read contract file: ${error instanceof Error ? error.message : String(error)}`,\n });\n }\n const contractJson = JSON.parse(contractJsonContent) as Record<string, unknown>;\n\n // Resolve database URL\n const dbUrl = options.db ?? config.db?.url;\n if (!dbUrl) {\n throw errorDatabaseUrlRequired();\n }\n\n // Check for driver\n if (!config.driver) {\n throw errorDriverRequired();\n }\n\n // Store driver descriptor after null check\n const driverDescriptor = config.driver;\n\n // Create family instance (needed for contract validation - no DB connection required)\n const stack = createControlPlaneStack({\n target: config.target,\n adapter: config.adapter,\n driver: driverDescriptor,\n extensionPacks: config.extensionPacks,\n });\n const familyInstance = config.family.create(stack);\n\n // Validate contract using instance validator (fail-fast before DB connection)\n const contractIR = familyInstance.validateContractIR(contractJson);\n assertContractRequirementsSatisfied({ contract: contractIR, stack });\n\n const rawComponents = [config.target, config.adapter, ...(config.extensionPacks ?? [])];\n const frameworkComponents = assertFrameworkComponentsCompatible(\n config.family.familyId,\n config.target.targetId,\n rawComponents,\n );\n\n // Create driver (expensive operation - done after validation)\n const driver = await driverDescriptor.create(dbUrl);\n\n try {\n // Schema verification precondition with spinner\n let schemaVerifyResult: VerifyDatabaseSchemaResult;\n try {\n schemaVerifyResult = await withSpinner(\n () =>\n familyInstance.schemaVerify({\n driver,\n contractIR,\n strict: false,\n contractPath: contractPathAbsolute,\n configPath,\n frameworkComponents,\n }),\n {\n message: 'Verifying database satisfies contract',\n flags,\n },\n );\n } catch (error) {\n // Wrap errors from schemaVerify() in structured error\n throw errorRuntime(error instanceof Error ? error.message : String(error), {\n why: `Failed to verify database schema: ${error instanceof Error ? error.message : String(error)}`,\n });\n }\n\n // If schema verification failed, return both results for handling outside performAction\n if (!schemaVerifyResult.ok) {\n return { schemaVerifyResult, signResult: undefined };\n }\n\n // Schema verification passed - proceed with signing\n let signResult: SignDatabaseResult;\n try {\n signResult = await withSpinner(\n () =>\n familyInstance.sign({\n driver,\n contractIR,\n contractPath: contractPathAbsolute,\n configPath,\n }),\n {\n message: 'Signing database...',\n flags,\n },\n );\n } catch (error) {\n // Wrap errors from sign() in structured error\n throw errorRuntime(error instanceof Error ? error.message : String(error), {\n why: `Failed to sign database: ${error instanceof Error ? error.message : String(error)}`,\n });\n }\n\n // Add blank line after all async operations if spinners were shown\n if (!flags.quiet && flags.json !== 'object' && process.stdout.isTTY) {\n console.log('');\n }\n\n return { schemaVerifyResult: undefined, signResult };\n } finally {\n // Ensure driver connection is closed\n await driver.close();\n }\n });\n\n // Handle result - formats output and returns exit code\n const exitCode = handleResult(result, flags, (value) => {\n const { schemaVerifyResult, signResult } = value;\n\n // If schema verification failed, format and print schema verification output\n if (schemaVerifyResult && !schemaVerifyResult.ok) {\n if (flags.json === 'object') {\n console.log(formatSchemaVerifyJson(schemaVerifyResult));\n } else {\n const output = formatSchemaVerifyOutput(schemaVerifyResult, flags);\n if (output) {\n console.log(output);\n }\n }\n // Don't proceed to sign output formatting\n return;\n }\n\n // Schema verification passed - format sign output\n if (signResult) {\n if (flags.json === 'object') {\n console.log(formatSignJson(signResult));\n } else {\n const output = formatSignOutput(signResult, flags);\n if (output) {\n console.log(output);\n }\n }\n }\n });\n\n // For logical schema mismatches, check if schema verification passed\n // Infra errors already handled by handleResult (returns non-zero exit code)\n if (result.ok && result.value.schemaVerifyResult && !result.value.schemaVerifyResult.ok) {\n // Schema verification failed - exit with code 1\n process.exit(1);\n } else {\n // Success or infra error - use exit code from handleResult\n process.exit(exitCode);\n }\n });\n\n return command;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/commands/db-sign.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport { relative, resolve } from 'node:path';\nimport {\n errorDatabaseConnectionRequired,\n errorDriverRequired,\n errorFileNotFound,\n errorRuntime,\n errorUnexpected,\n} from '@prisma-next/core-control-plane/errors';\nimport type {\n SignDatabaseResult,\n VerifyDatabaseSchemaResult,\n} from '@prisma-next/core-control-plane/types';\nimport { createControlPlaneStack } from '@prisma-next/core-control-plane/types';\nimport { Command } from 'commander';\nimport { loadConfig } from '../config-loader';\nimport { performAction } from '../utils/action';\nimport { setCommandDescriptions } from '../utils/command-helpers';\nimport {\n assertContractRequirementsSatisfied,\n assertFrameworkComponentsCompatible,\n} from '../utils/framework-components';\nimport { parseGlobalFlags } from '../utils/global-flags';\nimport {\n formatCommandHelp,\n formatSchemaVerifyJson,\n formatSchemaVerifyOutput,\n formatSignJson,\n formatSignOutput,\n formatStyledHeader,\n} from '../utils/output';\nimport { handleResult } from '../utils/result-handler';\nimport { withSpinner } from '../utils/spinner';\n\ninterface DbSignOptions {\n readonly db?: string;\n readonly config?: string;\n readonly json?: string | boolean;\n readonly quiet?: boolean;\n readonly q?: boolean;\n readonly verbose?: boolean;\n readonly v?: boolean;\n readonly vv?: boolean;\n readonly trace?: boolean;\n readonly timestamps?: boolean;\n readonly color?: boolean;\n readonly 'no-color'?: boolean;\n}\n\nexport function createDbSignCommand(): Command {\n const command = new Command('sign');\n setCommandDescriptions(\n command,\n 'Sign the database with your contract so you can safely run queries',\n 'Verifies that your database schema satisfies the emitted contract, and if so, writes or\\n' +\n 'updates the contract marker in the database. This command is idempotent and safe to run\\n' +\n 'in CI/deployment pipelines. The marker records that this database instance is aligned\\n' +\n 'with a specific contract version.',\n );\n command\n .configureHelp({\n formatHelp: (cmd) => {\n const flags = parseGlobalFlags({});\n return formatCommandHelp({ command: cmd, flags });\n },\n })\n .option('--db <url>', 'Database connection string')\n .option('--config <path>', 'Path to prisma-next.config.ts')\n .option('--json [format]', 'Output as JSON (object or ndjson)', false)\n .option('-q, --quiet', 'Quiet mode: errors only')\n .option('-v, --verbose', 'Verbose output: debug info, timings')\n .option('-vv, --trace', 'Trace output: deep internals, stack traces')\n .option('--timestamps', 'Add timestamps to output')\n .option('--color', 'Force color output')\n .option('--no-color', 'Disable color output')\n .action(async (options: DbSignOptions) => {\n const flags = parseGlobalFlags(options);\n\n const result = await performAction(async () => {\n // Load config (file I/O)\n const config = await loadConfig(options.config);\n // Normalize config path for display (match contract path format - no ./ prefix)\n const configPath = options.config\n ? relative(process.cwd(), resolve(options.config))\n : 'prisma-next.config.ts';\n const contractPathAbsolute = config.contract?.output\n ? resolve(config.contract.output)\n : resolve('src/prisma/contract.json');\n // Convert to relative path for display\n const contractPath = relative(process.cwd(), contractPathAbsolute);\n\n // Output header (only for human-readable output)\n if (flags.json !== 'object' && !flags.quiet) {\n const details: Array<{ label: string; value: string }> = [\n { label: 'config', value: configPath },\n { label: 'contract', value: contractPath },\n ];\n if (options.db) {\n details.push({ label: 'database', value: options.db });\n }\n const header = formatStyledHeader({\n command: 'db sign',\n description: 'Sign the database with your contract so you can safely run queries',\n url: 'https://pris.ly/db-sign',\n details,\n flags,\n });\n console.log(header);\n }\n\n // Load contract file (file I/O)\n let contractJsonContent: string;\n try {\n contractJsonContent = await readFile(contractPathAbsolute, 'utf-8');\n } catch (error) {\n if (error instanceof Error && (error as { code?: string }).code === 'ENOENT') {\n throw errorFileNotFound(contractPathAbsolute, {\n why: `Contract file not found at ${contractPathAbsolute}`,\n });\n }\n throw errorUnexpected(error instanceof Error ? error.message : String(error), {\n why: `Failed to read contract file: ${error instanceof Error ? error.message : String(error)}`,\n });\n }\n const contractJson = JSON.parse(contractJsonContent) as Record<string, unknown>;\n\n // Resolve database connection (--db flag or config.db.connection)\n const dbConnection = options.db ?? config.db?.connection;\n if (!dbConnection) {\n throw errorDatabaseConnectionRequired();\n }\n\n // Check for driver\n if (!config.driver) {\n throw errorDriverRequired();\n }\n\n // Store driver descriptor after null check\n const driverDescriptor = config.driver;\n\n // Create family instance (needed for contract validation - no DB connection required)\n const stack = createControlPlaneStack({\n target: config.target,\n adapter: config.adapter,\n driver: driverDescriptor,\n extensionPacks: config.extensionPacks,\n });\n const familyInstance = config.family.create(stack);\n\n // Validate contract using instance validator (fail-fast before DB connection)\n const contractIR = familyInstance.validateContractIR(contractJson);\n assertContractRequirementsSatisfied({ contract: contractIR, stack });\n\n const rawComponents = [config.target, config.adapter, ...(config.extensionPacks ?? [])];\n const frameworkComponents = assertFrameworkComponentsCompatible(\n config.family.familyId,\n config.target.targetId,\n rawComponents,\n );\n\n // Create driver (expensive operation - done after validation)\n const driver = await driverDescriptor.create(dbConnection);\n\n try {\n // Schema verification precondition with spinner\n let schemaVerifyResult: VerifyDatabaseSchemaResult;\n try {\n schemaVerifyResult = await withSpinner(\n () =>\n familyInstance.schemaVerify({\n driver,\n contractIR,\n strict: false,\n contractPath: contractPathAbsolute,\n configPath,\n frameworkComponents,\n }),\n {\n message: 'Verifying database satisfies contract',\n flags,\n },\n );\n } catch (error) {\n // Wrap errors from schemaVerify() in structured error\n throw errorRuntime(error instanceof Error ? error.message : String(error), {\n why: `Failed to verify database schema: ${error instanceof Error ? error.message : String(error)}`,\n });\n }\n\n // If schema verification failed, return both results for handling outside performAction\n if (!schemaVerifyResult.ok) {\n return { schemaVerifyResult, signResult: undefined };\n }\n\n // Schema verification passed - proceed with signing\n let signResult: SignDatabaseResult;\n try {\n signResult = await withSpinner(\n () =>\n familyInstance.sign({\n driver,\n contractIR,\n contractPath: contractPathAbsolute,\n configPath,\n }),\n {\n message: 'Signing database...',\n flags,\n },\n );\n } catch (error) {\n // Wrap errors from sign() in structured error\n throw errorRuntime(error instanceof Error ? error.message : String(error), {\n why: `Failed to sign database: ${error instanceof Error ? error.message : String(error)}`,\n });\n }\n\n // Add blank line after all async operations if spinners were shown\n if (!flags.quiet && flags.json !== 'object' && process.stdout.isTTY) {\n console.log('');\n }\n\n return { schemaVerifyResult: undefined, signResult };\n } finally {\n // Ensure driver connection is closed\n await driver.close();\n }\n });\n\n // Handle result - formats output and returns exit code\n const exitCode = handleResult(result, flags, (value) => {\n const { schemaVerifyResult, signResult } = value;\n\n // If schema verification failed, format and print schema verification output\n if (schemaVerifyResult && !schemaVerifyResult.ok) {\n if (flags.json === 'object') {\n console.log(formatSchemaVerifyJson(schemaVerifyResult));\n } else {\n const output = formatSchemaVerifyOutput(schemaVerifyResult, flags);\n if (output) {\n console.log(output);\n }\n }\n // Don't proceed to sign output formatting\n return;\n }\n\n // Schema verification passed - format sign output\n if (signResult) {\n if (flags.json === 'object') {\n console.log(formatSignJson(signResult));\n } else {\n const output = formatSignOutput(signResult, flags);\n if (output) {\n console.log(output);\n }\n }\n }\n });\n\n // For logical schema mismatches, check if schema verification passed\n // Infra errors already handled by handleResult (returns non-zero exit code)\n if (result.ok && result.value.schemaVerifyResult && !result.value.schemaVerifyResult.ok) {\n // Schema verification failed - exit with code 1\n process.exit(1);\n } else {\n // Success or infra error - use exit code from handleResult\n process.exit(exitCode);\n }\n });\n\n return command;\n}\n"],"mappings":"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","names":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"db-verify.d.ts","sourceRoot":"","sources":["../../src/commands/db-verify.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA8BpC,wBAAgB,qBAAqB,IAAI,OAAO,CAuL/C"}
1
+ {"version":3,"file":"db-verify.d.ts","sourceRoot":"","sources":["../../src/commands/db-verify.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA8BpC,wBAAgB,qBAAqB,IAAI,OAAO,CAsL/C"}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  assertContractRequirementsSatisfied
3
- } from "../chunk-CVNWLFXO.js";
3
+ } from "../chunk-6EPKRATC.js";
4
4
  import {
5
5
  formatCommandHelp,
6
6
  formatStyledHeader,
@@ -11,16 +11,17 @@ import {
11
11
  performAction,
12
12
  setCommandDescriptions,
13
13
  withSpinner
14
- } from "../chunk-BZMBKEEQ.js";
14
+ } from "../chunk-DIJPT5TZ.js";
15
15
  import {
16
16
  loadConfig
17
17
  } from "../chunk-HWYQOCAJ.js";
18
+ import "../chunk-VI2YETW7.js";
18
19
 
19
20
  // src/commands/db-verify.ts
20
21
  import { readFile } from "fs/promises";
21
22
  import { relative, resolve } from "path";
22
23
  import {
23
- errorDatabaseUrlRequired,
24
+ errorDatabaseConnectionRequired,
24
25
  errorDriverRequired,
25
26
  errorFileNotFound,
26
27
  errorHashMismatch,
@@ -81,15 +82,15 @@ function createDbVerifyCommand() {
81
82
  });
82
83
  }
83
84
  const contractJson = JSON.parse(contractJsonContent);
84
- const dbUrl = options.db ?? config.db?.url;
85
- if (!dbUrl) {
86
- throw errorDatabaseUrlRequired();
85
+ const dbConnection = options.db ?? config.db?.connection;
86
+ if (!dbConnection) {
87
+ throw errorDatabaseConnectionRequired();
87
88
  }
88
89
  if (!config.driver) {
89
90
  throw errorDriverRequired();
90
91
  }
91
92
  const driverDescriptor = config.driver;
92
- const driver = await withSpinner(() => driverDescriptor.create(dbUrl), {
93
+ const driver = await withSpinner(() => driverDescriptor.create(dbConnection), {
93
94
  message: "Connecting to database...",
94
95
  flags
95
96
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/commands/db-verify.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport { relative, resolve } from 'node:path';\nimport type { ContractIR } from '@prisma-next/contract/ir';\nimport {\n errorDatabaseUrlRequired,\n errorDriverRequired,\n errorFileNotFound,\n errorHashMismatch,\n errorMarkerMissing,\n errorRuntime,\n errorTargetMismatch,\n errorUnexpected,\n} from '@prisma-next/core-control-plane/errors';\nimport type { VerifyDatabaseResult } from '@prisma-next/core-control-plane/types';\nimport { createControlPlaneStack } from '@prisma-next/core-control-plane/types';\nimport { Command } from 'commander';\nimport { loadConfig } from '../config-loader';\nimport { performAction } from '../utils/action';\nimport { setCommandDescriptions } from '../utils/command-helpers';\nimport { assertContractRequirementsSatisfied } from '../utils/framework-components';\nimport { parseGlobalFlags } from '../utils/global-flags';\nimport {\n formatCommandHelp,\n formatStyledHeader,\n formatVerifyJson,\n formatVerifyOutput,\n} from '../utils/output';\nimport { handleResult } from '../utils/result-handler';\nimport { withSpinner } from '../utils/spinner';\n\ninterface DbVerifyOptions {\n readonly db?: string;\n readonly config?: string;\n readonly json?: string | boolean;\n readonly quiet?: boolean;\n readonly q?: boolean;\n readonly verbose?: boolean;\n readonly v?: boolean;\n readonly vv?: boolean;\n readonly trace?: boolean;\n readonly timestamps?: boolean;\n readonly color?: boolean;\n readonly 'no-color'?: boolean;\n}\n\nexport function createDbVerifyCommand(): Command {\n const command = new Command('verify');\n setCommandDescriptions(\n command,\n 'Check whether the database has been signed with your contract',\n 'Verifies that your database schema matches the emitted contract. Checks table structures,\\n' +\n 'column types, constraints, and codec coverage. Reports any mismatches or missing codecs.',\n );\n command\n .configureHelp({\n formatHelp: (cmd) => {\n const flags = parseGlobalFlags({});\n return formatCommandHelp({ command: cmd, flags });\n },\n })\n .option('--db <url>', 'Database connection string')\n .option('--config <path>', 'Path to prisma-next.config.ts')\n .option('--json [format]', 'Output as JSON (object or ndjson)', false)\n .option('-q, --quiet', 'Quiet mode: errors only')\n .option('-v, --verbose', 'Verbose output: debug info, timings')\n .option('-vv, --trace', 'Trace output: deep internals, stack traces')\n .option('--timestamps', 'Add timestamps to output')\n .option('--color', 'Force color output')\n .option('--no-color', 'Disable color output')\n .action(async (options: DbVerifyOptions) => {\n const flags = parseGlobalFlags(options);\n\n const result = await performAction(async () => {\n // Load config (file I/O)\n const config = await loadConfig(options.config);\n // Normalize config path for display (match contract path format - no ./ prefix)\n const configPath = options.config\n ? relative(process.cwd(), resolve(options.config))\n : 'prisma-next.config.ts';\n const contractPathAbsolute = config.contract?.output\n ? resolve(config.contract.output)\n : resolve('src/prisma/contract.json');\n // Convert to relative path for display\n const contractPath = relative(process.cwd(), contractPathAbsolute);\n\n // Output header (only for human-readable output)\n if (flags.json !== 'object' && !flags.quiet) {\n const details: Array<{ label: string; value: string }> = [\n { label: 'config', value: configPath },\n { label: 'contract', value: contractPath },\n ];\n if (options.db) {\n details.push({ label: 'database', value: options.db });\n }\n const header = formatStyledHeader({\n command: 'db verify',\n description: 'Check whether the database has been signed with your contract',\n url: 'https://pris.ly/db-verify',\n details,\n flags,\n });\n console.log(header);\n }\n\n // Load contract file (file I/O)\n let contractJsonContent: string;\n try {\n contractJsonContent = await readFile(contractPathAbsolute, 'utf-8');\n } catch (error) {\n if (error instanceof Error && (error as { code?: string }).code === 'ENOENT') {\n throw errorFileNotFound(contractPathAbsolute, {\n why: `Contract file not found at ${contractPathAbsolute}`,\n });\n }\n throw errorUnexpected(error instanceof Error ? error.message : String(error), {\n why: `Failed to read contract file: ${error instanceof Error ? error.message : String(error)}`,\n });\n }\n const contractJson = JSON.parse(contractJsonContent) as Record<string, unknown>;\n\n // Resolve database URL\n const dbUrl = options.db ?? config.db?.url;\n if (!dbUrl) {\n throw errorDatabaseUrlRequired();\n }\n\n // Check for driver\n if (!config.driver) {\n throw errorDriverRequired();\n }\n\n // Store driver descriptor after null check\n const driverDescriptor = config.driver;\n\n // Create driver\n const driver = await withSpinner(() => driverDescriptor.create(dbUrl), {\n message: 'Connecting to database...',\n flags,\n });\n\n try {\n // Create family instance\n const stack = createControlPlaneStack({\n target: config.target,\n adapter: config.adapter,\n driver: driverDescriptor,\n extensionPacks: config.extensionPacks,\n });\n const familyInstance = config.family.create(stack);\n\n // Validate contract using instance validator\n const contractIR = familyInstance.validateContractIR(contractJson) as ContractIR;\n assertContractRequirementsSatisfied({ contract: contractIR, stack });\n\n // Call family instance verify method\n let verifyResult: VerifyDatabaseResult;\n try {\n verifyResult = await withSpinner(\n () =>\n familyInstance.verify({\n driver,\n contractIR,\n expectedTargetId: config.target.targetId,\n contractPath: contractPathAbsolute,\n configPath,\n }),\n {\n message: 'Verifying database schema...',\n flags,\n },\n );\n } catch (error) {\n // Wrap errors from verify() in structured error\n throw errorUnexpected(error instanceof Error ? error.message : String(error), {\n why: `Failed to verify database: ${error instanceof Error ? error.message : String(error)}`,\n });\n }\n\n // If verification failed, throw structured error\n if (!verifyResult.ok && verifyResult.code) {\n if (verifyResult.code === 'PN-RTM-3001') {\n throw errorMarkerMissing();\n }\n if (verifyResult.code === 'PN-RTM-3002') {\n throw errorHashMismatch({\n expected: verifyResult.contract.coreHash,\n ...(verifyResult.marker?.coreHash ? { actual: verifyResult.marker.coreHash } : {}),\n });\n }\n if (verifyResult.code === 'PN-RTM-3003') {\n throw errorTargetMismatch(\n verifyResult.target.expected,\n verifyResult.target.actual ?? 'unknown',\n );\n }\n throw errorRuntime(verifyResult.summary);\n }\n\n // Add blank line after all async operations if spinners were shown\n if (!flags.quiet && flags.json !== 'object' && process.stdout.isTTY) {\n console.log('');\n }\n\n return verifyResult;\n } finally {\n // Ensure driver connection is closed\n await driver.close();\n }\n });\n\n // Handle result - formats output and returns exit code\n const exitCode = handleResult(result, flags, (verifyResult) => {\n // Output based on flags\n if (flags.json === 'object') {\n // JSON output to stdout\n console.log(formatVerifyJson(verifyResult));\n } else {\n // Human-readable output to stdout\n const output = formatVerifyOutput(verifyResult, flags);\n if (output) {\n console.log(output);\n }\n }\n });\n process.exit(exitCode);\n });\n\n return command;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/commands/db-verify.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport { relative, resolve } from 'node:path';\nimport type { ContractIR } from '@prisma-next/contract/ir';\nimport {\n errorDatabaseConnectionRequired,\n errorDriverRequired,\n errorFileNotFound,\n errorHashMismatch,\n errorMarkerMissing,\n errorRuntime,\n errorTargetMismatch,\n errorUnexpected,\n} from '@prisma-next/core-control-plane/errors';\nimport type { VerifyDatabaseResult } from '@prisma-next/core-control-plane/types';\nimport { createControlPlaneStack } from '@prisma-next/core-control-plane/types';\nimport { Command } from 'commander';\nimport { loadConfig } from '../config-loader';\nimport { performAction } from '../utils/action';\nimport { setCommandDescriptions } from '../utils/command-helpers';\nimport { assertContractRequirementsSatisfied } from '../utils/framework-components';\nimport { parseGlobalFlags } from '../utils/global-flags';\nimport {\n formatCommandHelp,\n formatStyledHeader,\n formatVerifyJson,\n formatVerifyOutput,\n} from '../utils/output';\nimport { handleResult } from '../utils/result-handler';\nimport { withSpinner } from '../utils/spinner';\n\ninterface DbVerifyOptions {\n readonly db?: string;\n readonly config?: string;\n readonly json?: string | boolean;\n readonly quiet?: boolean;\n readonly q?: boolean;\n readonly verbose?: boolean;\n readonly v?: boolean;\n readonly vv?: boolean;\n readonly trace?: boolean;\n readonly timestamps?: boolean;\n readonly color?: boolean;\n readonly 'no-color'?: boolean;\n}\n\nexport function createDbVerifyCommand(): Command {\n const command = new Command('verify');\n setCommandDescriptions(\n command,\n 'Check whether the database has been signed with your contract',\n 'Verifies that your database schema matches the emitted contract. Checks table structures,\\n' +\n 'column types, constraints, and codec coverage. Reports any mismatches or missing codecs.',\n );\n command\n .configureHelp({\n formatHelp: (cmd) => {\n const flags = parseGlobalFlags({});\n return formatCommandHelp({ command: cmd, flags });\n },\n })\n .option('--db <url>', 'Database connection string')\n .option('--config <path>', 'Path to prisma-next.config.ts')\n .option('--json [format]', 'Output as JSON (object or ndjson)', false)\n .option('-q, --quiet', 'Quiet mode: errors only')\n .option('-v, --verbose', 'Verbose output: debug info, timings')\n .option('-vv, --trace', 'Trace output: deep internals, stack traces')\n .option('--timestamps', 'Add timestamps to output')\n .option('--color', 'Force color output')\n .option('--no-color', 'Disable color output')\n .action(async (options: DbVerifyOptions) => {\n const flags = parseGlobalFlags(options);\n\n const result = await performAction(async () => {\n // Load config (file I/O)\n const config = await loadConfig(options.config);\n // Normalize config path for display (match contract path format - no ./ prefix)\n const configPath = options.config\n ? relative(process.cwd(), resolve(options.config))\n : 'prisma-next.config.ts';\n const contractPathAbsolute = config.contract?.output\n ? resolve(config.contract.output)\n : resolve('src/prisma/contract.json');\n // Convert to relative path for display\n const contractPath = relative(process.cwd(), contractPathAbsolute);\n\n // Output header (only for human-readable output)\n if (flags.json !== 'object' && !flags.quiet) {\n const details: Array<{ label: string; value: string }> = [\n { label: 'config', value: configPath },\n { label: 'contract', value: contractPath },\n ];\n if (options.db) {\n details.push({ label: 'database', value: options.db });\n }\n const header = formatStyledHeader({\n command: 'db verify',\n description: 'Check whether the database has been signed with your contract',\n url: 'https://pris.ly/db-verify',\n details,\n flags,\n });\n console.log(header);\n }\n\n // Load contract file (file I/O)\n let contractJsonContent: string;\n try {\n contractJsonContent = await readFile(contractPathAbsolute, 'utf-8');\n } catch (error) {\n if (error instanceof Error && (error as { code?: string }).code === 'ENOENT') {\n throw errorFileNotFound(contractPathAbsolute, {\n why: `Contract file not found at ${contractPathAbsolute}`,\n });\n }\n throw errorUnexpected(error instanceof Error ? error.message : String(error), {\n why: `Failed to read contract file: ${error instanceof Error ? error.message : String(error)}`,\n });\n }\n const contractJson = JSON.parse(contractJsonContent) as Record<string, unknown>;\n\n // Resolve database connection (--db flag or config.db.connection)\n const dbConnection = options.db ?? config.db?.connection;\n if (!dbConnection) {\n throw errorDatabaseConnectionRequired();\n }\n\n // Check for driver\n if (!config.driver) {\n throw errorDriverRequired();\n }\n\n // Store driver descriptor after null check\n const driverDescriptor = config.driver;\n\n const driver = await withSpinner(() => driverDescriptor.create(dbConnection), {\n message: 'Connecting to database...',\n flags,\n });\n\n try {\n // Create family instance\n const stack = createControlPlaneStack({\n target: config.target,\n adapter: config.adapter,\n driver: driverDescriptor,\n extensionPacks: config.extensionPacks,\n });\n const familyInstance = config.family.create(stack);\n\n // Validate contract using instance validator\n const contractIR = familyInstance.validateContractIR(contractJson) as ContractIR;\n assertContractRequirementsSatisfied({ contract: contractIR, stack });\n\n // Call family instance verify method\n let verifyResult: VerifyDatabaseResult;\n try {\n verifyResult = await withSpinner(\n () =>\n familyInstance.verify({\n driver,\n contractIR,\n expectedTargetId: config.target.targetId,\n contractPath: contractPathAbsolute,\n configPath,\n }),\n {\n message: 'Verifying database schema...',\n flags,\n },\n );\n } catch (error) {\n // Wrap errors from verify() in structured error\n throw errorUnexpected(error instanceof Error ? error.message : String(error), {\n why: `Failed to verify database: ${error instanceof Error ? error.message : String(error)}`,\n });\n }\n\n // If verification failed, throw structured error\n if (!verifyResult.ok && verifyResult.code) {\n if (verifyResult.code === 'PN-RTM-3001') {\n throw errorMarkerMissing();\n }\n if (verifyResult.code === 'PN-RTM-3002') {\n throw errorHashMismatch({\n expected: verifyResult.contract.coreHash,\n ...(verifyResult.marker?.coreHash ? { actual: verifyResult.marker.coreHash } : {}),\n });\n }\n if (verifyResult.code === 'PN-RTM-3003') {\n throw errorTargetMismatch(\n verifyResult.target.expected,\n verifyResult.target.actual ?? 'unknown',\n );\n }\n throw errorRuntime(verifyResult.summary);\n }\n\n // Add blank line after all async operations if spinners were shown\n if (!flags.quiet && flags.json !== 'object' && process.stdout.isTTY) {\n console.log('');\n }\n\n return verifyResult;\n } finally {\n // Ensure driver connection is closed\n await driver.close();\n }\n });\n\n // Handle result - formats output and returns exit code\n const exitCode = handleResult(result, flags, (verifyResult) => {\n // Output based on flags\n if (flags.json === 'object') {\n // JSON output to stdout\n console.log(formatVerifyJson(verifyResult));\n } else {\n // Human-readable output to stdout\n const output = formatVerifyOutput(verifyResult, flags);\n if (output) {\n console.log(output);\n }\n }\n });\n process.exit(exitCode);\n });\n\n return command;\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,13 @@
1
+ import type { ControlClient, ControlClientOptions } from './types';
2
+ /**
3
+ * Creates a programmatic control client for Prisma Next operations.
4
+ *
5
+ * The client accepts framework component descriptors at creation time,
6
+ * manages driver lifecycle via connect()/close(), and exposes domain
7
+ * operations that delegate to the existing family instance methods.
8
+ *
9
+ * @see {@link ControlClient} for the client interface
10
+ * @see README.md "Programmatic Control API" section for usage examples
11
+ */
12
+ export declare function createControlClient(options: ControlClientOptions): ControlClient;
13
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/control-api/client.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EACV,aAAa,EACb,oBAAoB,EAOrB,MAAM,SAAS,CAAC;AAEjB;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,oBAAoB,GAAG,aAAa,CAEhF"}
@@ -0,0 +1,27 @@
1
+ import type { TargetBoundComponentDescriptor } from '@prisma-next/contract/framework-components';
2
+ import type { ContractIR } from '@prisma-next/contract/ir';
3
+ import type { ControlDriverInstance, ControlFamilyInstance, TargetMigrationsCapability } from '@prisma-next/core-control-plane/types';
4
+ import type { DbInitResult } from '../types';
5
+ /**
6
+ * Options for executing dbInit operation.
7
+ */
8
+ export interface ExecuteDbInitOptions<TFamilyId extends string, TTargetId extends string> {
9
+ readonly driver: ControlDriverInstance<TFamilyId, TTargetId>;
10
+ readonly familyInstance: ControlFamilyInstance<TFamilyId>;
11
+ readonly contractIR: ContractIR;
12
+ readonly mode: 'plan' | 'apply';
13
+ readonly migrations: TargetMigrationsCapability<TFamilyId, TTargetId, ControlFamilyInstance<TFamilyId>>;
14
+ readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<TFamilyId, TTargetId>>;
15
+ }
16
+ /**
17
+ * Executes the dbInit operation.
18
+ *
19
+ * This is the core logic extracted from the CLI command, without any file I/O,
20
+ * process.exit(), or console output. It uses the Result pattern to return
21
+ * success or failure details.
22
+ *
23
+ * @param options - The options for executing dbInit
24
+ * @returns Result with DbInitSuccess on success, DbInitFailure on failure
25
+ */
26
+ export declare function executeDbInit<TFamilyId extends string, TTargetId extends string>(options: ExecuteDbInitOptions<TFamilyId, TTargetId>): Promise<DbInitResult>;
27
+ //# sourceMappingURL=db-init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db-init.d.ts","sourceRoot":"","sources":["../../../src/control-api/operations/db-init.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,4CAA4C,CAAC;AACjG,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,KAAK,EACV,qBAAqB,EACrB,qBAAqB,EAIrB,0BAA0B,EAC3B,MAAM,uCAAuC,CAAC;AAE/C,OAAO,KAAK,EAAE,YAAY,EAAiB,MAAM,UAAU,CAAC;AAE5D;;GAEG;AACH,MAAM,WAAW,oBAAoB,CAAC,SAAS,SAAS,MAAM,EAAE,SAAS,SAAS,MAAM;IACtF,QAAQ,CAAC,MAAM,EAAE,qBAAqB,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IAC7D,QAAQ,CAAC,cAAc,EAAE,qBAAqB,CAAC,SAAS,CAAC,CAAC;IAC1D,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IAChC,QAAQ,CAAC,UAAU,EAAE,0BAA0B,CAC7C,SAAS,EACT,SAAS,EACT,qBAAqB,CAAC,SAAS,CAAC,CACjC,CAAC;IACF,QAAQ,CAAC,mBAAmB,EAAE,aAAa,CAAC,8BAA8B,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC;CACnG;AAED;;;;;;;;;GASG;AACH,wBAAsB,aAAa,CAAC,SAAS,SAAS,MAAM,EAAE,SAAS,SAAS,MAAM,EACpF,OAAO,EAAE,oBAAoB,CAAC,SAAS,EAAE,SAAS,CAAC,GAClD,OAAO,CAAC,YAAY,CAAC,CA6HvB"}
@@ -0,0 +1,203 @@
1
+ import type { ControlAdapterDescriptor, ControlDriverDescriptor, ControlExtensionDescriptor, ControlFamilyDescriptor, ControlTargetDescriptor, MigrationPlannerConflict, SignDatabaseResult, VerifyDatabaseResult, VerifyDatabaseSchemaResult } from '@prisma-next/core-control-plane/types';
2
+ import type { Result } from '@prisma-next/utils/result';
3
+ /**
4
+ * Options for creating a control client.
5
+ *
6
+ * Note: This is NOT the same as CLI config. There's no `contract` field,
7
+ * no file paths. The client is config-agnostic.
8
+ *
9
+ * The descriptor types use permissive `any` because family-specific descriptors
10
+ * (e.g., SqlFamilyDescriptor) have more specific `create` method signatures that
11
+ * are not compatible with the base ControlFamilyDescriptor type due to TypeScript
12
+ * variance rules. The client implementation casts these internally.
13
+ */
14
+ export interface ControlClientOptions {
15
+ readonly family: ControlFamilyDescriptor<any, any>;
16
+ readonly target: ControlTargetDescriptor<any, any, any, any>;
17
+ readonly adapter: ControlAdapterDescriptor<any, any, any>;
18
+ /** Optional - control client can be created without driver for offline operations */
19
+ readonly driver?: ControlDriverDescriptor<any, any, any, any>;
20
+ readonly extensionPacks?: ReadonlyArray<ControlExtensionDescriptor<any, any, any>>;
21
+ /**
22
+ * Optional default connection for auto-connect.
23
+ * When provided, operations will auto-connect if not already connected.
24
+ * The type is driver-specific (e.g., string URL for Postgres).
25
+ */
26
+ readonly connection?: unknown;
27
+ }
28
+ /**
29
+ * Options for the verify operation.
30
+ */
31
+ export interface VerifyOptions {
32
+ /** Contract IR or unvalidated JSON - validated at runtime via familyInstance.validateContractIR() */
33
+ readonly contractIR: unknown;
34
+ }
35
+ /**
36
+ * Options for the schemaVerify operation.
37
+ */
38
+ export interface SchemaVerifyOptions {
39
+ /** Contract IR or unvalidated JSON - validated at runtime via familyInstance.validateContractIR() */
40
+ readonly contractIR: unknown;
41
+ /**
42
+ * Whether to use strict mode for schema verification.
43
+ * In strict mode, extra tables/columns are reported as issues.
44
+ * Default: false (tolerant mode - allows superset)
45
+ */
46
+ readonly strict?: boolean;
47
+ }
48
+ /**
49
+ * Options for the sign operation.
50
+ */
51
+ export interface SignOptions {
52
+ /** Contract IR or unvalidated JSON - validated at runtime via familyInstance.validateContractIR() */
53
+ readonly contractIR: unknown;
54
+ }
55
+ /**
56
+ * Options for the dbInit operation.
57
+ */
58
+ export interface DbInitOptions {
59
+ /** Contract IR or unvalidated JSON - validated at runtime via familyInstance.validateContractIR() */
60
+ readonly contractIR: unknown;
61
+ /**
62
+ * Mode for the dbInit operation.
63
+ * - 'plan': Returns planned operations without applying
64
+ * - 'apply': Applies operations and writes marker
65
+ */
66
+ readonly mode: 'plan' | 'apply';
67
+ }
68
+ /**
69
+ * Options for the introspect operation.
70
+ */
71
+ export interface IntrospectOptions {
72
+ /**
73
+ * Optional schema name to introspect.
74
+ */
75
+ readonly schema?: string;
76
+ }
77
+ /**
78
+ * Successful dbInit result.
79
+ */
80
+ export interface DbInitSuccess {
81
+ readonly mode: 'plan' | 'apply';
82
+ readonly plan: {
83
+ readonly operations: ReadonlyArray<{
84
+ readonly id: string;
85
+ readonly label: string;
86
+ readonly operationClass: string;
87
+ }>;
88
+ };
89
+ readonly execution?: {
90
+ readonly operationsPlanned: number;
91
+ readonly operationsExecuted: number;
92
+ };
93
+ readonly marker?: {
94
+ readonly coreHash: string;
95
+ readonly profileHash?: string;
96
+ };
97
+ readonly summary: string;
98
+ }
99
+ /**
100
+ * Failure codes for dbInit operation.
101
+ */
102
+ export type DbInitFailureCode = 'PLANNING_FAILED' | 'MARKER_ORIGIN_MISMATCH' | 'RUNNER_FAILED';
103
+ /**
104
+ * Failure details for dbInit operation.
105
+ */
106
+ export interface DbInitFailure {
107
+ readonly code: DbInitFailureCode;
108
+ readonly summary: string;
109
+ readonly conflicts?: ReadonlyArray<MigrationPlannerConflict>;
110
+ readonly marker?: {
111
+ readonly coreHash?: string;
112
+ readonly profileHash?: string;
113
+ };
114
+ readonly destination?: {
115
+ readonly coreHash: string;
116
+ readonly profileHash?: string | undefined;
117
+ };
118
+ }
119
+ /**
120
+ * Result type for dbInit operation.
121
+ * Uses Result pattern: success returns DbInitSuccess, failure returns DbInitFailure.
122
+ */
123
+ export type DbInitResult = Result<DbInitSuccess, DbInitFailure>;
124
+ /**
125
+ * Programmatic control client for Prisma Next operations.
126
+ *
127
+ * Lifecycle: `connect(connection)` before operations, `close()` when done.
128
+ * Both `init()` and `connect()` are auto-called by operations if needed,
129
+ * but `connect()` requires a connection so must be called explicitly first
130
+ * unless a default connection was provided in options.
131
+ *
132
+ * @see README.md "Programmatic Control API" section for usage examples
133
+ */
134
+ export interface ControlClient {
135
+ /**
136
+ * Initializes the client by creating the control plane stack,
137
+ * family instance, and validating framework components.
138
+ *
139
+ * Idempotent (safe to call multiple times).
140
+ * Called automatically by `connect()` if not already initialized.
141
+ */
142
+ init(): void;
143
+ /**
144
+ * Establishes a database connection.
145
+ * Auto-calls `init()` if not already initialized.
146
+ * Must be called before any database operations unless a default connection
147
+ * was provided in options.
148
+ *
149
+ * @param connection - Driver-specific connection input (e.g., URL string for Postgres).
150
+ * If omitted, uses the default connection from options (if provided).
151
+ * @throws If connection fails, already connected, driver is not configured,
152
+ * or no connection provided and no default connection in options.
153
+ */
154
+ connect(connection?: unknown): Promise<void>;
155
+ /**
156
+ * Closes the database connection.
157
+ * Idempotent (safe to call multiple times).
158
+ * After close(), can call `connect()` again with same or different URL.
159
+ */
160
+ close(): Promise<void>;
161
+ /**
162
+ * Verifies database marker matches the contract.
163
+ * Compares coreHash and profileHash.
164
+ *
165
+ * @returns Structured result (ok: false for mismatch, not throwing)
166
+ * @throws If not connected or infrastructure failure
167
+ */
168
+ verify(options: VerifyOptions): Promise<VerifyDatabaseResult>;
169
+ /**
170
+ * Verifies database schema satisfies the contract requirements.
171
+ *
172
+ * @param options.strict - If true, extra tables/columns are issues. Default: false
173
+ * @returns Structured result with schema issues
174
+ * @throws If not connected or infrastructure failure
175
+ */
176
+ schemaVerify(options: SchemaVerifyOptions): Promise<VerifyDatabaseSchemaResult>;
177
+ /**
178
+ * Signs the database with a contract marker.
179
+ * Writes or updates the contract marker if schema verification passes.
180
+ * Idempotent (no-op if marker already matches).
181
+ *
182
+ * @returns Structured result
183
+ * @throws If not connected or infrastructure failure
184
+ */
185
+ sign(options: SignOptions): Promise<SignDatabaseResult>;
186
+ /**
187
+ * Initializes database schema from contract.
188
+ * Uses additive-only policy (no destructive changes).
189
+ *
190
+ * @param options.mode - 'plan' to preview, 'apply' to execute
191
+ * @returns Result pattern: Ok with planned/executed operations, NotOk with failure details
192
+ * @throws If not connected, target doesn't support migrations, or infrastructure failure
193
+ */
194
+ dbInit(options: DbInitOptions): Promise<DbInitResult>;
195
+ /**
196
+ * Introspects the database schema.
197
+ *
198
+ * @returns Raw schema IR
199
+ * @throws If not connected or infrastructure failure
200
+ */
201
+ introspect(options?: IntrospectOptions): Promise<unknown>;
202
+ }
203
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/control-api/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Programmatic Control API for Prisma Next.
3
+ *
4
+ * This module exports the control client factory and types for programmatic
5
+ * access to control-plane operations without using the CLI.
6
+ *
7
+ * @see README.md "Programmatic Control API" section for usage examples
8
+ * @module
9
+ */
10
+ export type { ControlPlaneStack, SignDatabaseResult, VerifyDatabaseResult, VerifyDatabaseSchemaResult, } from '@prisma-next/core-control-plane/types';
11
+ export { createControlClient } from '../control-api/client';
12
+ export type { ControlClient, ControlClientOptions, DbInitFailure, DbInitFailureCode, DbInitOptions, DbInitResult, DbInitSuccess, IntrospectOptions, SchemaVerifyOptions, SignOptions, VerifyOptions, } from '../control-api/types';
13
+ //# sourceMappingURL=control-api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"control-api.d.ts","sourceRoot":"","sources":["../../src/exports/control-api.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,YAAY,EACV,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,EACpB,0BAA0B,GAC3B,MAAM,uCAAuC,CAAC;AAE/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAG5D,YAAY,EACV,aAAa,EACb,oBAAoB,EACpB,aAAa,EACb,iBAAiB,EACjB,aAAa,EACb,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,mBAAmB,EACnB,WAAW,EACX,aAAa,GACd,MAAM,sBAAsB,CAAC"}