@prisma-next/cli 0.3.0-dev.45 → 0.3.0-dev.52

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 CHANGED
@@ -66,6 +66,7 @@ The `contract emit` command does not require a `driver` in the config since it d
66
66
 
67
67
  ```typescript
68
68
  import { defineConfig } from '@prisma-next/cli/config-types';
69
+ import { typescriptContract } from '@prisma-next/sql-contract-ts/config-types';
69
70
  import postgresAdapter from '@prisma-next/adapter-postgres/control';
70
71
  import postgres from '@prisma-next/target-postgres/control';
71
72
  import sql from '@prisma-next/family-sql/control';
@@ -76,11 +77,7 @@ export default defineConfig({
76
77
  target: postgres,
77
78
  adapter: postgresAdapter,
78
79
  extensionPacks: [],
79
- contract: {
80
- source: contract,
81
- output: 'src/prisma/contract.json',
82
- types: 'src/prisma/contract.d.ts',
83
- },
80
+ contract: typescriptContract(contract, 'src/prisma/contract.json'),
84
81
  });
85
82
  ```
86
83
 
@@ -145,6 +142,7 @@ The `db verify` command requires a `driver` in the config to connect to the data
145
142
 
146
143
  ```typescript
147
144
  import { defineConfig } from '@prisma-next/cli/config-types';
145
+ import { typescriptContract } from '@prisma-next/sql-contract-ts/config-types';
148
146
  import postgresAdapter from '@prisma-next/adapter-postgres/control';
149
147
  import postgresDriver from '@prisma-next/driver-postgres/control';
150
148
  import postgres from '@prisma-next/target-postgres/control';
@@ -157,11 +155,7 @@ export default defineConfig({
157
155
  adapter: postgresAdapter,
158
156
  driver: postgresDriver,
159
157
  extensionPacks: [],
160
- contract: {
161
- source: contract,
162
- output: 'src/prisma/contract.json',
163
- types: 'src/prisma/contract.d.ts',
164
- },
158
+ contract: typescriptContract(contract, 'src/prisma/contract.json'),
165
159
  db: {
166
160
  connection: process.env.DATABASE_URL, // Optional: can also use --db flag
167
161
  },
@@ -305,6 +299,7 @@ The `db introspect` command requires a `driver` in the config to connect to the
305
299
 
306
300
  ```typescript
307
301
  import { defineConfig } from '@prisma-next/cli/config-types';
302
+ import { typescriptContract } from '@prisma-next/sql-contract-ts/config-types';
308
303
  import postgresAdapter from '@prisma-next/adapter-postgres/control';
309
304
  import postgresDriver from '@prisma-next/driver-postgres/control';
310
305
  import postgres from '@prisma-next/target-postgres/control';
@@ -468,11 +463,7 @@ export default defineConfig({
468
463
  adapter: postgresAdapter,
469
464
  driver: postgresDriver,
470
465
  extensionPacks: [],
471
- contract: {
472
- source: contract,
473
- output: 'src/prisma/contract.json',
474
- types: 'src/prisma/contract.d.ts',
475
- },
466
+ contract: typescriptContract(contract, 'src/prisma/contract.json'),
476
467
  db: {
477
468
  connection: process.env.DATABASE_URL, // Optional: can also use --db flag
478
469
  },
@@ -667,6 +658,7 @@ The `db init` command requires a `driver` in the config to connect to the databa
667
658
 
668
659
  ```typescript
669
660
  import { defineConfig } from '@prisma-next/cli/config-types';
661
+ import { typescriptContract } from '@prisma-next/sql-contract-ts/config-types';
670
662
  import postgresAdapter from '@prisma-next/adapter-postgres/control';
671
663
  import postgresDriver from '@prisma-next/driver-postgres/control';
672
664
  import postgres from '@prisma-next/target-postgres/control';
@@ -679,11 +671,7 @@ export default defineConfig({
679
671
  adapter: postgresAdapter,
680
672
  driver: postgresDriver,
681
673
  extensionPacks: [],
682
- contract: {
683
- source: contract,
684
- output: 'src/prisma/contract.json',
685
- types: 'src/prisma/contract.d.ts',
686
- },
674
+ contract: typescriptContract(contract, 'src/prisma/contract.json'),
687
675
  db: {
688
676
  connection: process.env.DATABASE_URL, // Optional: can also use --db flag
689
677
  },
@@ -802,6 +790,7 @@ The CLI uses a config file to specify the target family, target, adapter, extens
802
790
 
803
791
  ```typescript
804
792
  import { defineConfig } from '@prisma-next/cli/config-types';
793
+ import { typescriptContract } from '@prisma-next/sql-contract-ts/config-types';
805
794
  import postgresAdapter from '@prisma-next/adapter-postgres/control';
806
795
  import postgres from '@prisma-next/target-postgres/control';
807
796
  import sql from '@prisma-next/family-sql/control';
@@ -812,22 +801,18 @@ export default defineConfig({
812
801
  target: postgres,
813
802
  adapter: postgresAdapter,
814
803
  extensionPacks: [],
815
- contract: {
816
- source: contract, // Can be a value or a function: () => import('./contract').then(m => m.contract)
817
- output: 'src/prisma/contract.json', // Optional: defaults to 'src/prisma/contract.json'
818
- types: 'src/prisma/contract.d.ts', // Optional: defaults to output with .d.ts extension
819
- },
804
+ contract: typescriptContract(contract, 'src/prisma/contract.json'),
820
805
  });
821
806
  ```
822
807
 
823
- The `contract.source` field can be:
824
- - A direct value: `source: contract`
825
- - A synchronous function: `source: () => contract`
826
- - An asynchronous function: `source: () => import('./contract').then(m => m.contract)`
808
+ Prefer helper utilities for authoring mode selection:
809
+ - `typescriptContract(contractIR, outputPath?)` from `@prisma-next/sql-contract-ts/config-types` for TS-authored contracts
810
+ - `prismaContract(schemaPath, { output?, target? })` from `@prisma-next/sql-contract-psl/provider` for PSL-authored providers
811
+ - Provider failures are returned as structured diagnostics for CLI rendering
827
812
 
828
813
  The `contract.output` field specifies the path to `contract.json`. This is the canonical location where other CLI commands can find the contract JSON artifact. Defaults to `'src/prisma/contract.json'` if not specified.
829
814
 
830
- The `contract.types` field specifies the path to `contract.d.ts`. Defaults to `output` with `.d.ts` extension (replaces `.json` with `.d.ts` if output ends with `.json`, otherwise appends `contract.d.ts` to the directory containing output).
815
+ `contract.d.ts` is always colocated with `contract.json` and derived from `contract.output` (`contract.json` `contract.d.ts`).
831
816
 
832
817
  **Output:**
833
818
  - `contract.json`: Includes `_generated` metadata field indicating it's a generated artifact (excluded from canonicalization/hashing)
@@ -877,11 +862,12 @@ See `.cursor/rules/config-validation-and-normalization.mdc` for detailed pattern
877
862
  - Supports global flags (JSON, verbosity, color, timestamps)
878
863
  - **Error Handling**: Uses structured errors (`CliStructuredError`), Result pattern (`performAction`), and `process.exit()`. Commands wrap logic in `performAction()`, process results with `handleResult()`, and call `process.exit(exitCode)` directly. See `.cursor/rules/cli-error-handling.mdc` for details.
879
864
  - Loads the user's config module (`prisma-next.config.ts`)
880
- - Resolves contract from config:
881
- - Uses `config.contract.source` (supports sync and async functions)
882
- - User's config is responsible for loading the contract (can use `loadContractFromTs` or any other method)
865
+ - Resolves contract from provider:
866
+ - Calls `config.contract.source()` and expects `Result<ContractIR, Diagnostics>`
867
+ - Source-specific parsing/loading stays inside providers
868
+ - Provider diagnostics are surfaced as actionable CLI failures
883
869
  - Throws error if `config.contract` is missing
884
- - Uses artifact paths from `config.contract.output/types` (already normalized by `defineConfig()` with defaults applied)
870
+ - Uses artifact path from `config.contract.output` (already normalized by `defineConfig()` with defaults applied)
885
871
  - Creates family instance via `config.family.create()` (assembles operation registry, type imports, extension IDs)
886
872
  - Calls `familyInstance.emitContract()` with raw contract (instance handles stripping mappings and validation internally)
887
873
  - Outputs human-readable or JSON format based on flags
package/dist/cli.mjs CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import "./config-loader-CnnWuluc.mjs";
3
+ import "./config-loader-BJ8HsEdA.mjs";
4
+ import "./client-BSZKpZTF.mjs";
4
5
  import { b as parseGlobalFlags, d as formatRootHelp, r as formatCommandHelp, x as setCommandDescriptions } from "./result-handler-BZPY7HX4.mjs";
5
6
  import { createContractEmitCommand } from "./commands/contract-emit.mjs";
6
7
  import { createDbInitCommand } from "./commands/db-init.mjs";
package/dist/cli.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.mjs","names":[],"sources":["../src/cli.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { createContractEmitCommand } from './commands/contract-emit';\nimport { createDbInitCommand } from './commands/db-init';\nimport { createDbIntrospectCommand } from './commands/db-introspect';\nimport { createDbSchemaVerifyCommand } from './commands/db-schema-verify';\nimport { createDbSignCommand } from './commands/db-sign';\nimport { createDbVerifyCommand } from './commands/db-verify';\nimport { setCommandDescriptions } from './utils/command-helpers';\nimport { parseGlobalFlags } from './utils/global-flags';\nimport { formatCommandHelp, formatRootHelp } from './utils/output';\n\nconst program = new Command();\n\nprogram.name('prisma-next').description('Prisma Next CLI').version('0.0.1');\n\n// Override version option description to match capitalization style\nconst versionOption = program.options.find((opt) => opt.flags.includes('--version'));\nif (versionOption) {\n versionOption.description = 'Output the version number';\n}\n\nprogram.configureOutput({\n writeErr: () => {\n // Suppress all default error output - we handle errors in exitOverride\n },\n writeOut: () => {\n // Suppress all default output - our custom formatters handle everything\n },\n});\n\n// Customize root help output to use our styled format\nconst rootHelpFormatter = (cmd: Command) => {\n const flags = parseGlobalFlags({});\n return formatRootHelp({ program: cmd, flags });\n};\n\nprogram.configureHelp({\n formatHelp: rootHelpFormatter,\n subcommandDescription: () => '',\n});\n\n// Override exit to handle unhandled errors (fail fast cases)\n// Commands handle structured errors themselves via process.exit()\nprogram.exitOverride((err) => {\n if (err) {\n // Help requests are not errors - allow Commander to output help and exit normally\n // Commander throws errors with codes like 'commander.help', 'commander.helpDisplayed', or 'outputHelp'\n const errorCode = (err as { code?: string }).code;\n const errorMessage = String(err.message ?? '');\n const errorName = err.name ?? '';\n\n // Check for unknown command errors first (before other checks)\n // Commander.js uses code 'commander.unknownCommand' or error message contains 'unknown command'\n const isUnknownCommandError =\n errorCode === 'commander.unknownCommand' ||\n errorCode === 'commander.unknownArgument' ||\n (errorName === 'CommanderError' &&\n (errorMessage.includes('unknown command') || errorMessage.includes('unknown argument')));\n if (isUnknownCommandError) {\n const flags = parseGlobalFlags({});\n // Extract the command/subcommand name from the error message\n // Error message format: \"unknown command 'command-name'\"\n const match = errorMessage.match(/unknown command ['\"]([^'\"]+)['\"]/);\n const commandName = match ? match[1] : process.argv[3] || process.argv[2] || 'unknown';\n\n // Determine which command context we're in\n // Check if the first argument is a recognized parent command\n const firstArg = process.argv[2];\n const parentCommand = firstArg\n ? program.commands.find((cmd) => cmd.name() === firstArg)\n : undefined;\n\n if (parentCommand && commandName !== firstArg) {\n // Unrecognized subcommand - show parent command help\n // eslint-disable-next-line no-console\n console.error(`Unknown command: ${commandName}`);\n // eslint-disable-next-line no-console\n console.error('');\n const helpText = formatCommandHelp({ command: parentCommand, flags });\n // eslint-disable-next-line no-console\n console.log(helpText);\n } else {\n // Unrecognized top-level command - show root help\n // eslint-disable-next-line no-console\n console.error(`Unknown command: ${commandName}`);\n // eslint-disable-next-line no-console\n console.error('');\n const helpText = formatRootHelp({ program, flags });\n // eslint-disable-next-line no-console\n console.log(helpText);\n }\n process.exit(1);\n return;\n }\n const isHelpError =\n errorCode === 'commander.help' ||\n errorCode === 'commander.helpDisplayed' ||\n errorCode === 'outputHelp' ||\n errorMessage === '(outputHelp)' ||\n errorMessage.includes('outputHelp') ||\n (errorName === 'CommanderError' && errorMessage.includes('outputHelp'));\n if (isHelpError) {\n process.exit(0);\n return;\n }\n // Missing required arguments/subcommands - show help and exit with 0\n // Commander throws errors with code 'commander.missingArgument' or 'commander.missingMandatoryOptionValue'\n // or when a command with subcommands is called without a subcommand\n const isMissingArgumentError =\n errorCode === 'commander.missingArgument' ||\n errorCode === 'commander.missingMandatoryOptionValue' ||\n (errorName === 'CommanderError' &&\n (errorMessage.includes('missing') || errorMessage.includes('required')));\n if (isMissingArgumentError) {\n // Help was already displayed by Commander.js, just exit with 0\n process.exit(0);\n return;\n }\n // Unhandled error - fail fast with exit code 1\n // eslint-disable-next-line no-console\n console.error(`Unhandled error: ${err.message}`);\n if (err.stack) {\n // eslint-disable-next-line no-console\n console.error(err.stack);\n }\n process.exit(1);\n }\n process.exit(0);\n});\n\n// Register contract subcommand\nconst contractCommand = new Command('contract');\nsetCommandDescriptions(\n contractCommand,\n 'Contract management commands',\n 'Define and emit your application data contract. The contract describes your schema as a\\n' +\n 'declarative data structure that can be signed and verified against your database.',\n);\ncontractCommand.configureHelp({\n formatHelp: (cmd) => {\n const flags = parseGlobalFlags({});\n return formatCommandHelp({ command: cmd, flags });\n },\n subcommandDescription: () => '',\n});\n\n// Add emit subcommand to contract\nconst contractEmitCommand = createContractEmitCommand();\ncontractCommand.addCommand(contractEmitCommand);\n\n// Register contract command\nprogram.addCommand(contractCommand);\n\n// Register db subcommand\nconst dbCommand = new Command('db');\nsetCommandDescriptions(\n dbCommand,\n 'Database management commands',\n 'Verify and sign your database with your contract. Ensure your database schema matches\\n' +\n 'your contract, and sign it to record the contract hash for future verification.',\n);\ndbCommand.configureHelp({\n formatHelp: (cmd) => {\n const flags = parseGlobalFlags({});\n return formatCommandHelp({ command: cmd, flags });\n },\n subcommandDescription: () => '',\n});\n\n// Add verify subcommand to db\nconst dbVerifyCommand = createDbVerifyCommand();\ndbCommand.addCommand(dbVerifyCommand);\n\n// Add init subcommand to db\nconst dbInitCommand = createDbInitCommand();\ndbCommand.addCommand(dbInitCommand);\n\n// Add introspect subcommand to db\nconst dbIntrospectCommand = createDbIntrospectCommand();\ndbCommand.addCommand(dbIntrospectCommand);\n\n// Add schema-verify subcommand to db\nconst dbSchemaVerifyCommand = createDbSchemaVerifyCommand();\ndbCommand.addCommand(dbSchemaVerifyCommand);\n\n// Add sign subcommand to db\nconst dbSignCommand = createDbSignCommand();\ndbCommand.addCommand(dbSignCommand);\n\n// Register db command\nprogram.addCommand(dbCommand);\n\n// Create help command\nconst helpCommand = new Command('help')\n .description('Show usage instructions')\n .configureHelp({\n formatHelp: (cmd) => {\n const flags = parseGlobalFlags({});\n return formatCommandHelp({ command: cmd, flags });\n },\n })\n .action(() => {\n const flags = parseGlobalFlags({});\n const helpText = formatRootHelp({ program, flags });\n // eslint-disable-next-line no-console\n console.log(helpText);\n process.exit(0);\n });\n\nprogram.addCommand(helpCommand);\n\n// Set help as the default action when no command is provided\nprogram.action(() => {\n const flags = parseGlobalFlags({});\n const helpText = formatRootHelp({ program, flags });\n // eslint-disable-next-line no-console\n console.log(helpText);\n process.exit(0);\n});\n\n// Check if a command was invoked with no arguments (just the command name)\n// or if an unrecognized command was provided\nconst args = process.argv.slice(2);\nif (args.length > 0) {\n const commandName = args[0];\n // Handle version option explicitly since we suppress default output\n if (commandName === '--version' || commandName === '-V') {\n // eslint-disable-next-line no-console\n console.log(program.version());\n process.exit(0);\n }\n // Skip command check for global options like --help, -h\n const isGlobalOption = commandName === '--help' || commandName === '-h';\n if (!isGlobalOption) {\n // Check if this is a recognized command\n const command = program.commands.find((cmd) => cmd.name() === commandName);\n\n if (!command) {\n // Unrecognized command - show error message and usage\n const flags = parseGlobalFlags({});\n // eslint-disable-next-line no-console\n console.error(`Unknown command: ${commandName}`);\n // eslint-disable-next-line no-console\n console.error('');\n const helpText = formatRootHelp({ program, flags });\n // eslint-disable-next-line no-console\n console.log(helpText);\n process.exit(1);\n } else if (command.commands.length > 0 && args.length === 1) {\n // Parent command called with no subcommand - show help and exit with 0\n const flags = parseGlobalFlags({});\n const helpText = formatCommandHelp({ command, flags });\n // eslint-disable-next-line no-console\n console.log(helpText);\n process.exit(0);\n }\n }\n}\n\nprogram.parse();\n"],"mappings":"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"}
1
+ {"version":3,"file":"cli.mjs","names":[],"sources":["../src/cli.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { createContractEmitCommand } from './commands/contract-emit';\nimport { createDbInitCommand } from './commands/db-init';\nimport { createDbIntrospectCommand } from './commands/db-introspect';\nimport { createDbSchemaVerifyCommand } from './commands/db-schema-verify';\nimport { createDbSignCommand } from './commands/db-sign';\nimport { createDbVerifyCommand } from './commands/db-verify';\nimport { setCommandDescriptions } from './utils/command-helpers';\nimport { parseGlobalFlags } from './utils/global-flags';\nimport { formatCommandHelp, formatRootHelp } from './utils/output';\n\nconst program = new Command();\n\nprogram.name('prisma-next').description('Prisma Next CLI').version('0.0.1');\n\n// Override version option description to match capitalization style\nconst versionOption = program.options.find((opt) => opt.flags.includes('--version'));\nif (versionOption) {\n versionOption.description = 'Output the version number';\n}\n\nprogram.configureOutput({\n writeErr: () => {\n // Suppress all default error output - we handle errors in exitOverride\n },\n writeOut: () => {\n // Suppress all default output - our custom formatters handle everything\n },\n});\n\n// Customize root help output to use our styled format\nconst rootHelpFormatter = (cmd: Command) => {\n const flags = parseGlobalFlags({});\n return formatRootHelp({ program: cmd, flags });\n};\n\nprogram.configureHelp({\n formatHelp: rootHelpFormatter,\n subcommandDescription: () => '',\n});\n\n// Override exit to handle unhandled errors (fail fast cases)\n// Commands handle structured errors themselves via process.exit()\nprogram.exitOverride((err) => {\n if (err) {\n // Help requests are not errors - allow Commander to output help and exit normally\n // Commander throws errors with codes like 'commander.help', 'commander.helpDisplayed', or 'outputHelp'\n const errorCode = (err as { code?: string }).code;\n const errorMessage = String(err.message ?? '');\n const errorName = err.name ?? '';\n\n // Check for unknown command errors first (before other checks)\n // Commander.js uses code 'commander.unknownCommand' or error message contains 'unknown command'\n const isUnknownCommandError =\n errorCode === 'commander.unknownCommand' ||\n errorCode === 'commander.unknownArgument' ||\n (errorName === 'CommanderError' &&\n (errorMessage.includes('unknown command') || errorMessage.includes('unknown argument')));\n if (isUnknownCommandError) {\n const flags = parseGlobalFlags({});\n // Extract the command/subcommand name from the error message\n // Error message format: \"unknown command 'command-name'\"\n const match = errorMessage.match(/unknown command ['\"]([^'\"]+)['\"]/);\n const commandName = match ? match[1] : process.argv[3] || process.argv[2] || 'unknown';\n\n // Determine which command context we're in\n // Check if the first argument is a recognized parent command\n const firstArg = process.argv[2];\n const parentCommand = firstArg\n ? program.commands.find((cmd) => cmd.name() === firstArg)\n : undefined;\n\n if (parentCommand && commandName !== firstArg) {\n // Unrecognized subcommand - show parent command help\n // eslint-disable-next-line no-console\n console.error(`Unknown command: ${commandName}`);\n // eslint-disable-next-line no-console\n console.error('');\n const helpText = formatCommandHelp({ command: parentCommand, flags });\n // eslint-disable-next-line no-console\n console.log(helpText);\n } else {\n // Unrecognized top-level command - show root help\n // eslint-disable-next-line no-console\n console.error(`Unknown command: ${commandName}`);\n // eslint-disable-next-line no-console\n console.error('');\n const helpText = formatRootHelp({ program, flags });\n // eslint-disable-next-line no-console\n console.log(helpText);\n }\n process.exit(1);\n return;\n }\n const isHelpError =\n errorCode === 'commander.help' ||\n errorCode === 'commander.helpDisplayed' ||\n errorCode === 'outputHelp' ||\n errorMessage === '(outputHelp)' ||\n errorMessage.includes('outputHelp') ||\n (errorName === 'CommanderError' && errorMessage.includes('outputHelp'));\n if (isHelpError) {\n process.exit(0);\n return;\n }\n // Missing required arguments/subcommands - show help and exit with 0\n // Commander throws errors with code 'commander.missingArgument' or 'commander.missingMandatoryOptionValue'\n // or when a command with subcommands is called without a subcommand\n const isMissingArgumentError =\n errorCode === 'commander.missingArgument' ||\n errorCode === 'commander.missingMandatoryOptionValue' ||\n (errorName === 'CommanderError' &&\n (errorMessage.includes('missing') || errorMessage.includes('required')));\n if (isMissingArgumentError) {\n // Help was already displayed by Commander.js, just exit with 0\n process.exit(0);\n return;\n }\n // Unhandled error - fail fast with exit code 1\n // eslint-disable-next-line no-console\n console.error(`Unhandled error: ${err.message}`);\n if (err.stack) {\n // eslint-disable-next-line no-console\n console.error(err.stack);\n }\n process.exit(1);\n }\n process.exit(0);\n});\n\n// Register contract subcommand\nconst contractCommand = new Command('contract');\nsetCommandDescriptions(\n contractCommand,\n 'Contract management commands',\n 'Define and emit your application data contract. The contract describes your schema as a\\n' +\n 'declarative data structure that can be signed and verified against your database.',\n);\ncontractCommand.configureHelp({\n formatHelp: (cmd) => {\n const flags = parseGlobalFlags({});\n return formatCommandHelp({ command: cmd, flags });\n },\n subcommandDescription: () => '',\n});\n\n// Add emit subcommand to contract\nconst contractEmitCommand = createContractEmitCommand();\ncontractCommand.addCommand(contractEmitCommand);\n\n// Register contract command\nprogram.addCommand(contractCommand);\n\n// Register db subcommand\nconst dbCommand = new Command('db');\nsetCommandDescriptions(\n dbCommand,\n 'Database management commands',\n 'Verify and sign your database with your contract. Ensure your database schema matches\\n' +\n 'your contract, and sign it to record the contract hash for future verification.',\n);\ndbCommand.configureHelp({\n formatHelp: (cmd) => {\n const flags = parseGlobalFlags({});\n return formatCommandHelp({ command: cmd, flags });\n },\n subcommandDescription: () => '',\n});\n\n// Add verify subcommand to db\nconst dbVerifyCommand = createDbVerifyCommand();\ndbCommand.addCommand(dbVerifyCommand);\n\n// Add init subcommand to db\nconst dbInitCommand = createDbInitCommand();\ndbCommand.addCommand(dbInitCommand);\n\n// Add introspect subcommand to db\nconst dbIntrospectCommand = createDbIntrospectCommand();\ndbCommand.addCommand(dbIntrospectCommand);\n\n// Add schema-verify subcommand to db\nconst dbSchemaVerifyCommand = createDbSchemaVerifyCommand();\ndbCommand.addCommand(dbSchemaVerifyCommand);\n\n// Add sign subcommand to db\nconst dbSignCommand = createDbSignCommand();\ndbCommand.addCommand(dbSignCommand);\n\n// Register db command\nprogram.addCommand(dbCommand);\n\n// Create help command\nconst helpCommand = new Command('help')\n .description('Show usage instructions')\n .configureHelp({\n formatHelp: (cmd) => {\n const flags = parseGlobalFlags({});\n return formatCommandHelp({ command: cmd, flags });\n },\n })\n .action(() => {\n const flags = parseGlobalFlags({});\n const helpText = formatRootHelp({ program, flags });\n // eslint-disable-next-line no-console\n console.log(helpText);\n process.exit(0);\n });\n\nprogram.addCommand(helpCommand);\n\n// Set help as the default action when no command is provided\nprogram.action(() => {\n const flags = parseGlobalFlags({});\n const helpText = formatRootHelp({ program, flags });\n // eslint-disable-next-line no-console\n console.log(helpText);\n process.exit(0);\n});\n\n// Check if a command was invoked with no arguments (just the command name)\n// or if an unrecognized command was provided\nconst args = process.argv.slice(2);\nif (args.length > 0) {\n const commandName = args[0];\n // Handle version option explicitly since we suppress default output\n if (commandName === '--version' || commandName === '-V') {\n // eslint-disable-next-line no-console\n console.log(program.version());\n process.exit(0);\n }\n // Skip command check for global options like --help, -h\n const isGlobalOption = commandName === '--help' || commandName === '-h';\n if (!isGlobalOption) {\n // Check if this is a recognized command\n const command = program.commands.find((cmd) => cmd.name() === commandName);\n\n if (!command) {\n // Unrecognized command - show error message and usage\n const flags = parseGlobalFlags({});\n // eslint-disable-next-line no-console\n console.error(`Unknown command: ${commandName}`);\n // eslint-disable-next-line no-console\n console.error('');\n const helpText = formatRootHelp({ program, flags });\n // eslint-disable-next-line no-console\n console.log(helpText);\n process.exit(1);\n } else if (command.commands.length > 0 && args.length === 1) {\n // Parent command called with no subcommand - show help and exit with 0\n const flags = parseGlobalFlags({});\n const helpText = formatCommandHelp({ command, flags });\n // eslint-disable-next-line no-console\n console.log(helpText);\n process.exit(0);\n }\n }\n}\n\nprogram.parse();\n"],"mappings":"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"}
@@ -623,14 +623,23 @@ var ControlClientImpl = class {
623
623
  label: "Resolving contract source..."
624
624
  });
625
625
  try {
626
- switch (contractConfig.source.kind) {
627
- case "loader":
628
- contractRaw = await contractConfig.source.load();
629
- break;
630
- case "value":
631
- contractRaw = contractConfig.source.value;
632
- break;
626
+ const providerResult = await contractConfig.sourceProvider();
627
+ if (!providerResult.ok) {
628
+ onProgress?.({
629
+ action: "emit",
630
+ kind: "spanEnd",
631
+ spanId: "resolveSource",
632
+ outcome: "error"
633
+ });
634
+ return notOk({
635
+ code: "CONTRACT_SOURCE_INVALID",
636
+ summary: providerResult.failure.summary,
637
+ why: providerResult.failure.summary,
638
+ meta: providerResult.failure.meta,
639
+ diagnostics: providerResult.failure
640
+ });
633
641
  }
642
+ contractRaw = providerResult.value;
634
643
  onProgress?.({
635
644
  action: "emit",
636
645
  kind: "spanEnd",
@@ -644,10 +653,18 @@ var ControlClientImpl = class {
644
653
  spanId: "resolveSource",
645
654
  outcome: "error"
646
655
  });
656
+ const message = error instanceof Error ? error.message : String(error);
647
657
  return notOk({
648
658
  code: "CONTRACT_SOURCE_INVALID",
649
659
  summary: "Failed to resolve contract source",
650
- why: error instanceof Error ? error.message : String(error),
660
+ why: message,
661
+ diagnostics: {
662
+ summary: "Contract source provider threw an exception",
663
+ diagnostics: [{
664
+ code: "PROVIDER_THROW",
665
+ message
666
+ }]
667
+ },
651
668
  meta: void 0
652
669
  });
653
670
  }
@@ -691,4 +708,4 @@ var ControlClientImpl = class {
691
708
 
692
709
  //#endregion
693
710
  export { errorDatabaseConnectionRequired as a, errorHashMismatch as c, errorMigrationPlanningFailed as d, errorRuntime as f, errorUnexpected$1 as h, errorContractValidationFailed as i, errorJsonFormatNotSupported as l, errorTargetMismatch as m, CliStructuredError as n, errorDriverRequired as o, errorTargetMigrationNotSupported as p, errorContractConfigMissing$1 as r, errorFileNotFound as s, createControlClient as t, errorMarkerMissing as u };
694
- //# sourceMappingURL=client-Lm9Q6aQM.mjs.map
711
+ //# sourceMappingURL=client-BSZKpZTF.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"client-Lm9Q6aQM.mjs","names":["plannerResult: MigrationPlannerResult","migrationPlan: MigrationPlan","runnerResult: MigrationRunnerResult","contractRaw: unknown"],"sources":["../src/utils/framework-components.ts","../src/control-api/operations/db-init.ts","../src/control-api/client.ts"],"sourcesContent":["import {\n checkContractComponentRequirements,\n type TargetBoundComponentDescriptor,\n} from '@prisma-next/contract/framework-components';\nimport type { ContractIR } from '@prisma-next/contract/ir';\nimport type { ControlPlaneStack } from '@prisma-next/core-control-plane/types';\nimport { errorConfigValidation, errorContractMissingExtensionPacks } from './cli-errors';\n\n/**\n * Asserts that all framework components are compatible with the expected family and target.\n *\n * This function validates that each component in the framework components array:\n * - Has kind 'target', 'adapter', 'extension', or 'driver'\n * - Has familyId matching expectedFamilyId\n * - Has targetId matching expectedTargetId\n *\n * This validation happens at the CLI composition boundary, before passing components\n * to typed planner/runner instances. It fills the gap between runtime validation\n * (via `validateConfig()`) and compile-time type enforcement.\n *\n * @param expectedFamilyId - The expected family ID (e.g., 'sql')\n * @param expectedTargetId - The expected target ID (e.g., 'postgres')\n * @param frameworkComponents - Array of framework components to validate\n * @returns The same array typed as TargetBoundComponentDescriptor\n * @throws CliStructuredError if any component is incompatible\n *\n * @example\n * ```ts\n * const config = await loadConfig();\n * const frameworkComponents = [config.target, config.adapter, ...(config.extensionPacks ?? [])];\n *\n * // Validate and type-narrow components before passing to planner\n * const typedComponents = assertFrameworkComponentsCompatible(\n * config.family.familyId,\n * config.target.targetId,\n * frameworkComponents\n * );\n *\n * const planner = target.migrations.createPlanner(familyInstance);\n * planner.plan({ contract, schema, policy, frameworkComponents: typedComponents });\n * ```\n */\nexport function assertFrameworkComponentsCompatible<\n TFamilyId extends string,\n TTargetId extends string,\n>(\n expectedFamilyId: TFamilyId,\n expectedTargetId: TTargetId,\n frameworkComponents: ReadonlyArray<unknown>,\n): ReadonlyArray<TargetBoundComponentDescriptor<TFamilyId, TTargetId>> {\n for (let i = 0; i < frameworkComponents.length; i++) {\n const component = frameworkComponents[i];\n\n // Check that component is an object\n if (typeof component !== 'object' || component === null) {\n throw errorConfigValidation('frameworkComponents[]', {\n why: `Framework component at index ${i} must be an object`,\n });\n }\n\n const record = component as Record<string, unknown>;\n\n // Check kind\n if (!Object.hasOwn(record, 'kind')) {\n throw errorConfigValidation('frameworkComponents[].kind', {\n why: `Framework component at index ${i} must have 'kind' property`,\n });\n }\n\n const kind = record['kind'];\n if (kind !== 'target' && kind !== 'adapter' && kind !== 'extension' && kind !== 'driver') {\n throw errorConfigValidation('frameworkComponents[].kind', {\n why: `Framework component at index ${i} has invalid kind '${String(kind)}' (must be 'target', 'adapter', 'extension', or 'driver')`,\n });\n }\n\n // Check familyId\n if (!Object.hasOwn(record, 'familyId')) {\n throw errorConfigValidation('frameworkComponents[].familyId', {\n why: `Framework component at index ${i} (kind: ${String(kind)}) must have 'familyId' property`,\n });\n }\n\n const familyId = record['familyId'];\n if (familyId !== expectedFamilyId) {\n throw errorConfigValidation('frameworkComponents[].familyId', {\n why: `Framework component at index ${i} (kind: ${String(kind)}) has familyId '${String(familyId)}' but expected '${expectedFamilyId}'`,\n });\n }\n\n // Check targetId\n if (!Object.hasOwn(record, 'targetId')) {\n throw errorConfigValidation('frameworkComponents[].targetId', {\n why: `Framework component at index ${i} (kind: ${String(kind)}) must have 'targetId' property`,\n });\n }\n\n const targetId = record['targetId'];\n if (targetId !== expectedTargetId) {\n throw errorConfigValidation('frameworkComponents[].targetId', {\n why: `Framework component at index ${i} (kind: ${String(kind)}) has targetId '${String(targetId)}' but expected '${expectedTargetId}'`,\n });\n }\n }\n\n // Type assertion is safe because we've validated all components above\n return frameworkComponents as ReadonlyArray<TargetBoundComponentDescriptor<TFamilyId, TTargetId>>;\n}\n\n/**\n * Validates that a contract is compatible with the configured target, adapter,\n * and extension packs. Throws on family/target mismatches or missing extension packs.\n *\n * This check ensures the emitted contract matches the CLI config before running\n * commands that depend on the contract (e.g., db verify, db sign).\n *\n * @param contract - The contract IR to validate (must include targetFamily, target, extensionPacks).\n * @param stack - The control plane stack (target, adapter, driver, extensionPacks).\n *\n * @throws {CliStructuredError} errorConfigValidation when contract.targetFamily or contract.target\n * doesn't match the configured family/target.\n * @throws {CliStructuredError} errorContractMissingExtensionPacks when the contract requires\n * extension packs that are not provided in the config (includes all missing packs in error.meta).\n *\n * @example\n * ```ts\n * import { assertContractRequirementsSatisfied } from './framework-components';\n *\n * const config = await loadConfig();\n * const contractIR = await loadContractJson(config.contract.output);\n * const stack = createControlPlaneStack({ target: config.target, adapter: config.adapter, ... });\n *\n * // Throws if contract is incompatible with config\n * assertContractRequirementsSatisfied({ contract: contractIR, stack });\n * ```\n */\nexport function assertContractRequirementsSatisfied<\n TFamilyId extends string,\n TTargetId extends string,\n>({\n contract,\n stack,\n}: {\n readonly contract: Pick<ContractIR, 'targetFamily' | 'target' | 'extensionPacks'>;\n readonly stack: ControlPlaneStack<TFamilyId, TTargetId>;\n}): void {\n const providedComponentIds = new Set<string>([stack.target.id, stack.adapter.id]);\n for (const extension of stack.extensionPacks) {\n providedComponentIds.add(extension.id);\n }\n\n const result = checkContractComponentRequirements({\n contract,\n expectedTargetFamily: stack.target.familyId,\n expectedTargetId: stack.target.targetId,\n providedComponentIds,\n });\n\n if (result.familyMismatch) {\n throw errorConfigValidation('contract.targetFamily', {\n why: `Contract was emitted for family '${result.familyMismatch.actual}' but CLI config is wired to '${result.familyMismatch.expected}'.`,\n });\n }\n\n if (result.targetMismatch) {\n throw errorConfigValidation('contract.target', {\n why: `Contract target '${result.targetMismatch.actual}' does not match CLI target '${result.targetMismatch.expected}'.`,\n });\n }\n\n if (result.missingExtensionPackIds.length > 0) {\n throw errorContractMissingExtensionPacks({\n missingExtensionPacks: result.missingExtensionPackIds,\n providedComponentIds: [...providedComponentIds],\n });\n }\n}\n","import type { TargetBoundComponentDescriptor } from '@prisma-next/contract/framework-components';\nimport type { ContractIR } from '@prisma-next/contract/ir';\nimport type {\n ControlDriverInstance,\n ControlFamilyInstance,\n MigrationPlan,\n MigrationPlannerResult,\n MigrationPlanOperation,\n MigrationRunnerResult,\n TargetMigrationsCapability,\n} from '@prisma-next/core-control-plane/types';\nimport { notOk, ok } from '@prisma-next/utils/result';\nimport type { DbInitResult, DbInitSuccess, OnControlProgress } from '../types';\n\n/**\n * Options for executing dbInit operation.\n */\nexport interface ExecuteDbInitOptions<TFamilyId extends string, TTargetId extends string> {\n readonly driver: ControlDriverInstance<TFamilyId, TTargetId>;\n readonly familyInstance: ControlFamilyInstance<TFamilyId>;\n readonly contractIR: ContractIR;\n readonly mode: 'plan' | 'apply';\n readonly migrations: TargetMigrationsCapability<\n TFamilyId,\n TTargetId,\n ControlFamilyInstance<TFamilyId>\n >;\n readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<TFamilyId, TTargetId>>;\n /** Optional progress callback for observing operation progress */\n readonly onProgress?: OnControlProgress;\n}\n\n/**\n * Executes the dbInit operation.\n *\n * This is the core logic extracted from the CLI command, without any file I/O,\n * process.exit(), or console output. It uses the Result pattern to return\n * success or failure details.\n *\n * @param options - The options for executing dbInit\n * @returns Result with DbInitSuccess on success, DbInitFailure on failure\n */\nexport async function executeDbInit<TFamilyId extends string, TTargetId extends string>(\n options: ExecuteDbInitOptions<TFamilyId, TTargetId>,\n): Promise<DbInitResult> {\n const { driver, familyInstance, contractIR, mode, migrations, frameworkComponents, onProgress } =\n options;\n\n // Create planner and runner from target migrations capability\n const planner = migrations.createPlanner(familyInstance);\n const runner = migrations.createRunner(familyInstance);\n\n // Introspect live schema\n const introspectSpanId = 'introspect';\n onProgress?.({\n action: 'dbInit',\n kind: 'spanStart',\n spanId: introspectSpanId,\n label: 'Introspecting database schema',\n });\n const schemaIR = await familyInstance.introspect({ driver });\n onProgress?.({\n action: 'dbInit',\n kind: 'spanEnd',\n spanId: introspectSpanId,\n outcome: 'ok',\n });\n\n // Policy for init mode (additive only)\n const policy = { allowedOperationClasses: ['additive'] as const };\n\n // Plan migration\n const planSpanId = 'plan';\n onProgress?.({\n action: 'dbInit',\n kind: 'spanStart',\n spanId: planSpanId,\n label: 'Planning migration',\n });\n const plannerResult: MigrationPlannerResult = await planner.plan({\n contract: contractIR,\n schema: schemaIR,\n policy,\n frameworkComponents,\n });\n\n if (plannerResult.kind === 'failure') {\n onProgress?.({\n action: 'dbInit',\n kind: 'spanEnd',\n spanId: planSpanId,\n outcome: 'error',\n });\n return notOk({\n code: 'PLANNING_FAILED' as const,\n summary: 'Migration planning failed due to conflicts',\n conflicts: plannerResult.conflicts,\n why: undefined,\n meta: undefined,\n });\n }\n\n const migrationPlan: MigrationPlan = plannerResult.plan;\n onProgress?.({\n action: 'dbInit',\n kind: 'spanEnd',\n spanId: planSpanId,\n outcome: 'ok',\n });\n\n // Check for existing marker - handle idempotency and mismatch errors\n const checkMarkerSpanId = 'checkMarker';\n onProgress?.({\n action: 'dbInit',\n kind: 'spanStart',\n spanId: checkMarkerSpanId,\n label: 'Checking contract marker',\n });\n const existingMarker = await familyInstance.readMarker({ driver });\n if (existingMarker) {\n const markerMatchesDestination =\n existingMarker.storageHash === migrationPlan.destination.storageHash &&\n (!migrationPlan.destination.profileHash ||\n existingMarker.profileHash === migrationPlan.destination.profileHash);\n\n if (markerMatchesDestination) {\n // Already at destination - return success with no operations\n onProgress?.({\n action: 'dbInit',\n kind: 'spanEnd',\n spanId: checkMarkerSpanId,\n outcome: 'skipped',\n });\n const result: DbInitSuccess = {\n mode,\n plan: { operations: [] },\n ...(mode === 'apply'\n ? {\n execution: { operationsPlanned: 0, operationsExecuted: 0 },\n marker: {\n storageHash: existingMarker.storageHash,\n profileHash: existingMarker.profileHash,\n },\n }\n : {}),\n summary: 'Database already at target contract state',\n };\n return ok(result);\n }\n\n // Marker exists but doesn't match destination - fail\n onProgress?.({\n action: 'dbInit',\n kind: 'spanEnd',\n spanId: checkMarkerSpanId,\n outcome: 'error',\n });\n return notOk({\n code: 'MARKER_ORIGIN_MISMATCH' as const,\n summary: 'Existing contract marker does not match plan destination',\n marker: {\n storageHash: existingMarker.storageHash,\n profileHash: existingMarker.profileHash,\n },\n destination: {\n storageHash: migrationPlan.destination.storageHash,\n profileHash: migrationPlan.destination.profileHash,\n },\n why: undefined,\n conflicts: undefined,\n meta: undefined,\n });\n }\n\n onProgress?.({\n action: 'dbInit',\n kind: 'spanEnd',\n spanId: checkMarkerSpanId,\n outcome: 'ok',\n });\n\n // Plan mode - don't execute\n if (mode === 'plan') {\n const result: DbInitSuccess = {\n mode: 'plan',\n plan: { operations: migrationPlan.operations },\n summary: `Planned ${migrationPlan.operations.length} operation(s)`,\n };\n return ok(result);\n }\n\n // Apply mode - execute runner\n const applySpanId = 'apply';\n onProgress?.({\n action: 'dbInit',\n kind: 'spanStart',\n spanId: applySpanId,\n label: 'Applying migration plan',\n });\n\n const callbacks = onProgress\n ? {\n onOperationStart: (op: MigrationPlanOperation) => {\n onProgress({\n action: 'dbInit',\n kind: 'spanStart',\n spanId: `operation:${op.id}`,\n parentSpanId: applySpanId,\n label: op.label,\n });\n },\n onOperationComplete: (op: MigrationPlanOperation) => {\n onProgress({\n action: 'dbInit',\n kind: 'spanEnd',\n spanId: `operation:${op.id}`,\n outcome: 'ok',\n });\n },\n }\n : undefined;\n\n const runnerResult: MigrationRunnerResult = await runner.execute({\n plan: migrationPlan,\n driver,\n destinationContract: contractIR,\n policy,\n ...(callbacks ? { callbacks } : {}),\n // db init plans and applies back-to-back from a fresh introspection, so per-operation\n // pre/postchecks and the idempotency probe are usually redundant overhead. We still\n // enforce marker/origin compatibility and a full schema verification after apply.\n executionChecks: {\n prechecks: false,\n postchecks: false,\n idempotencyChecks: false,\n },\n frameworkComponents,\n });\n\n if (!runnerResult.ok) {\n onProgress?.({\n action: 'dbInit',\n kind: 'spanEnd',\n spanId: applySpanId,\n outcome: 'error',\n });\n return notOk({\n code: 'RUNNER_FAILED' as const,\n summary: runnerResult.failure.summary,\n why: runnerResult.failure.why,\n meta: runnerResult.failure.meta,\n conflicts: undefined,\n });\n }\n\n const execution = runnerResult.value;\n\n onProgress?.({\n action: 'dbInit',\n kind: 'spanEnd',\n spanId: applySpanId,\n outcome: 'ok',\n });\n\n const result: DbInitSuccess = {\n mode: 'apply',\n plan: { operations: migrationPlan.operations },\n execution: {\n operationsPlanned: execution.operationsPlanned,\n operationsExecuted: execution.operationsExecuted,\n },\n marker: migrationPlan.destination.profileHash\n ? {\n storageHash: migrationPlan.destination.storageHash,\n profileHash: migrationPlan.destination.profileHash,\n }\n : { storageHash: migrationPlan.destination.storageHash },\n summary: `Applied ${execution.operationsExecuted} operation(s), marker written`,\n };\n return ok(result);\n}\n","import type { TargetBoundComponentDescriptor } from '@prisma-next/contract/framework-components';\nimport type { CoreSchemaView } from '@prisma-next/core-control-plane/schema-view';\nimport { createControlPlaneStack } from '@prisma-next/core-control-plane/stack';\nimport type {\n ControlDriverInstance,\n ControlFamilyInstance,\n ControlPlaneStack,\n SignDatabaseResult,\n VerifyDatabaseResult,\n VerifyDatabaseSchemaResult,\n} from '@prisma-next/core-control-plane/types';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport { notOk, ok } from '@prisma-next/utils/result';\nimport { assertFrameworkComponentsCompatible } from '../utils/framework-components';\nimport { executeDbInit } from './operations/db-init';\nimport type {\n ControlClient,\n ControlClientOptions,\n DbInitOptions,\n DbInitResult,\n EmitOptions,\n EmitResult,\n IntrospectOptions,\n SchemaVerifyOptions,\n SignOptions,\n VerifyOptions,\n} from './types';\n\n/**\n * Creates a programmatic control client for Prisma Next operations.\n *\n * The client accepts framework component descriptors at creation time,\n * manages driver lifecycle via connect()/close(), and exposes domain\n * operations that delegate to the existing family instance methods.\n *\n * @see {@link ControlClient} for the client interface\n * @see README.md \"Programmatic Control API\" section for usage examples\n */\nexport function createControlClient(options: ControlClientOptions): ControlClient {\n return new ControlClientImpl(options);\n}\n\n/**\n * Implementation of ControlClient.\n * Manages initialization and connection state, delegates operations to family instance.\n */\nclass ControlClientImpl implements ControlClient {\n private readonly options: ControlClientOptions;\n private stack: ControlPlaneStack<string, string> | null = null;\n private driver: ControlDriverInstance<string, string> | null = null;\n private familyInstance: ControlFamilyInstance<string> | null = null;\n private frameworkComponents: ReadonlyArray<\n TargetBoundComponentDescriptor<string, string>\n > | null = null;\n private initialized = false;\n private readonly defaultConnection: unknown;\n\n constructor(options: ControlClientOptions) {\n this.options = options;\n this.defaultConnection = options.connection;\n }\n\n init(): void {\n if (this.initialized) {\n return; // Idempotent\n }\n\n // Create the control plane stack\n this.stack = createControlPlaneStack({\n target: this.options.target,\n adapter: this.options.adapter,\n driver: this.options.driver,\n extensionPacks: this.options.extensionPacks,\n });\n\n // Create family instance using the stack\n this.familyInstance = this.options.family.create(this.stack);\n\n // Validate and type-narrow framework components\n const rawComponents = [\n this.options.target,\n this.options.adapter,\n ...(this.options.extensionPacks ?? []),\n ];\n this.frameworkComponents = assertFrameworkComponentsCompatible(\n this.options.family.familyId,\n this.options.target.targetId,\n rawComponents,\n );\n\n this.initialized = true;\n }\n\n async connect(connection?: unknown): Promise<void> {\n // Auto-init if needed\n this.init();\n\n if (this.driver) {\n throw new Error('Already connected. Call close() before reconnecting.');\n }\n\n // Resolve connection: argument > default from options\n const resolvedConnection = connection ?? this.defaultConnection;\n if (resolvedConnection === undefined) {\n throw new Error(\n 'No connection provided. Pass a connection to connect() or provide a default connection when creating the client.',\n );\n }\n\n // Check for driver descriptor\n if (!this.stack?.driver) {\n throw new Error(\n 'Driver is not configured. Pass a driver descriptor when creating the control client to enable database operations.',\n );\n }\n\n // Create driver instance\n // Cast through any since connection type is driver-specific at runtime.\n // The driver descriptor is typed with any for TConnection in ControlClientOptions,\n // but createControlPlaneStack defaults it to string. We bridge this at runtime.\n // biome-ignore lint/suspicious/noExplicitAny: required for runtime connection type flexibility\n this.driver = await this.stack?.driver.create(resolvedConnection as any);\n }\n\n async close(): Promise<void> {\n if (this.driver) {\n await this.driver.close();\n this.driver = null;\n }\n }\n\n private async ensureConnected(): Promise<{\n driver: ControlDriverInstance<string, string>;\n familyInstance: ControlFamilyInstance<string>;\n frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<string, string>>;\n }> {\n // Auto-init if needed\n this.init();\n\n // Auto-connect if not connected and default connection is available\n if (!this.driver && this.defaultConnection !== undefined) {\n await this.connect(this.defaultConnection);\n }\n\n if (!this.driver || !this.familyInstance || !this.frameworkComponents) {\n throw new Error('Not connected. Call connect(connection) first.');\n }\n return {\n driver: this.driver,\n familyInstance: this.familyInstance,\n frameworkComponents: this.frameworkComponents,\n };\n }\n\n async verify(options: VerifyOptions): Promise<VerifyDatabaseResult> {\n const { onProgress } = options;\n\n // Connect with progress span if connection provided\n if (options.connection !== undefined) {\n onProgress?.({\n action: 'verify',\n kind: 'spanStart',\n spanId: 'connect',\n label: 'Connecting to database...',\n });\n try {\n await this.connect(options.connection);\n onProgress?.({\n action: 'verify',\n kind: 'spanEnd',\n spanId: 'connect',\n outcome: 'ok',\n });\n } catch (error) {\n onProgress?.({\n action: 'verify',\n kind: 'spanEnd',\n spanId: 'connect',\n outcome: 'error',\n });\n throw error;\n }\n }\n\n const { driver, familyInstance } = await this.ensureConnected();\n\n // Validate contract using family instance\n const contractIR = familyInstance.validateContractIR(options.contractIR);\n\n // Emit verify span\n onProgress?.({\n action: 'verify',\n kind: 'spanStart',\n spanId: 'verify',\n label: 'Verifying contract marker...',\n });\n\n try {\n // Delegate to family instance verify method\n // Note: We pass empty strings for contractPath/configPath since the programmatic\n // API doesn't deal with file paths. The family instance accepts these as optional\n // metadata for error reporting.\n const result = await familyInstance.verify({\n driver,\n contractIR,\n expectedTargetId: this.options.target.targetId,\n contractPath: '',\n });\n\n onProgress?.({\n action: 'verify',\n kind: 'spanEnd',\n spanId: 'verify',\n outcome: result.ok ? 'ok' : 'error',\n });\n\n return result;\n } catch (error) {\n onProgress?.({\n action: 'verify',\n kind: 'spanEnd',\n spanId: 'verify',\n outcome: 'error',\n });\n throw error;\n }\n }\n\n async schemaVerify(options: SchemaVerifyOptions): Promise<VerifyDatabaseSchemaResult> {\n const { onProgress } = options;\n\n // Connect with progress span if connection provided\n if (options.connection !== undefined) {\n onProgress?.({\n action: 'schemaVerify',\n kind: 'spanStart',\n spanId: 'connect',\n label: 'Connecting to database...',\n });\n try {\n await this.connect(options.connection);\n onProgress?.({\n action: 'schemaVerify',\n kind: 'spanEnd',\n spanId: 'connect',\n outcome: 'ok',\n });\n } catch (error) {\n onProgress?.({\n action: 'schemaVerify',\n kind: 'spanEnd',\n spanId: 'connect',\n outcome: 'error',\n });\n throw error;\n }\n }\n\n const { driver, familyInstance, frameworkComponents } = await this.ensureConnected();\n\n // Validate contract using family instance\n const contractIR = familyInstance.validateContractIR(options.contractIR);\n\n // Emit schemaVerify span\n onProgress?.({\n action: 'schemaVerify',\n kind: 'spanStart',\n spanId: 'schemaVerify',\n label: 'Verifying database schema...',\n });\n\n try {\n // Delegate to family instance schemaVerify method\n const result = await familyInstance.schemaVerify({\n driver,\n contractIR,\n strict: options.strict ?? false,\n contractPath: '',\n frameworkComponents,\n });\n\n onProgress?.({\n action: 'schemaVerify',\n kind: 'spanEnd',\n spanId: 'schemaVerify',\n outcome: result.ok ? 'ok' : 'error',\n });\n\n return result;\n } catch (error) {\n onProgress?.({\n action: 'schemaVerify',\n kind: 'spanEnd',\n spanId: 'schemaVerify',\n outcome: 'error',\n });\n throw error;\n }\n }\n\n async sign(options: SignOptions): Promise<SignDatabaseResult> {\n const { onProgress } = options;\n\n // Connect with progress span if connection provided\n if (options.connection !== undefined) {\n onProgress?.({\n action: 'sign',\n kind: 'spanStart',\n spanId: 'connect',\n label: 'Connecting to database...',\n });\n try {\n await this.connect(options.connection);\n onProgress?.({\n action: 'sign',\n kind: 'spanEnd',\n spanId: 'connect',\n outcome: 'ok',\n });\n } catch (error) {\n onProgress?.({\n action: 'sign',\n kind: 'spanEnd',\n spanId: 'connect',\n outcome: 'error',\n });\n throw error;\n }\n }\n\n const { driver, familyInstance } = await this.ensureConnected();\n\n // Validate contract using family instance\n const contractIR = familyInstance.validateContractIR(options.contractIR);\n\n // Emit sign span\n onProgress?.({\n action: 'sign',\n kind: 'spanStart',\n spanId: 'sign',\n label: 'Signing database...',\n });\n\n try {\n // Delegate to family instance sign method\n const result = await familyInstance.sign({\n driver,\n contractIR,\n contractPath: options.contractPath ?? '',\n ...ifDefined('configPath', options.configPath),\n });\n\n onProgress?.({\n action: 'sign',\n kind: 'spanEnd',\n spanId: 'sign',\n outcome: 'ok',\n });\n\n return result;\n } catch (error) {\n onProgress?.({\n action: 'sign',\n kind: 'spanEnd',\n spanId: 'sign',\n outcome: 'error',\n });\n throw error;\n }\n }\n\n async dbInit(options: DbInitOptions): Promise<DbInitResult> {\n const { onProgress } = options;\n\n // Connect with progress span if connection provided\n if (options.connection !== undefined) {\n onProgress?.({\n action: 'dbInit',\n kind: 'spanStart',\n spanId: 'connect',\n label: 'Connecting to database...',\n });\n try {\n await this.connect(options.connection);\n onProgress?.({\n action: 'dbInit',\n kind: 'spanEnd',\n spanId: 'connect',\n outcome: 'ok',\n });\n } catch (error) {\n onProgress?.({\n action: 'dbInit',\n kind: 'spanEnd',\n spanId: 'connect',\n outcome: 'error',\n });\n throw error;\n }\n }\n\n const { driver, familyInstance, frameworkComponents } = await this.ensureConnected();\n\n // Check target supports migrations\n if (!this.options.target.migrations) {\n throw new Error(`Target \"${this.options.target.targetId}\" does not support migrations`);\n }\n\n // Validate contract using family instance\n const contractIR = familyInstance.validateContractIR(options.contractIR);\n\n // Delegate to extracted dbInit operation\n return executeDbInit({\n driver,\n familyInstance,\n contractIR,\n mode: options.mode,\n migrations: this.options.target.migrations,\n frameworkComponents,\n ...(onProgress ? { onProgress } : {}),\n });\n }\n\n async introspect(options?: IntrospectOptions): Promise<unknown> {\n const onProgress = options?.onProgress;\n\n // Connect with progress span if connection provided\n if (options?.connection !== undefined) {\n onProgress?.({\n action: 'introspect',\n kind: 'spanStart',\n spanId: 'connect',\n label: 'Connecting to database...',\n });\n try {\n await this.connect(options.connection);\n onProgress?.({\n action: 'introspect',\n kind: 'spanEnd',\n spanId: 'connect',\n outcome: 'ok',\n });\n } catch (error) {\n onProgress?.({\n action: 'introspect',\n kind: 'spanEnd',\n spanId: 'connect',\n outcome: 'error',\n });\n throw error;\n }\n }\n\n const { driver, familyInstance } = await this.ensureConnected();\n\n // TODO: Pass schema option to familyInstance.introspect when schema filtering is implemented\n const _schema = options?.schema;\n void _schema;\n\n // Emit introspect span\n onProgress?.({\n action: 'introspect',\n kind: 'spanStart',\n spanId: 'introspect',\n label: 'Introspecting database schema...',\n });\n\n try {\n const result = await familyInstance.introspect({ driver });\n\n onProgress?.({\n action: 'introspect',\n kind: 'spanEnd',\n spanId: 'introspect',\n outcome: 'ok',\n });\n\n return result;\n } catch (error) {\n onProgress?.({\n action: 'introspect',\n kind: 'spanEnd',\n spanId: 'introspect',\n outcome: 'error',\n });\n throw error;\n }\n }\n\n toSchemaView(schemaIR: unknown): CoreSchemaView | undefined {\n this.init();\n if (this.familyInstance?.toSchemaView) {\n return this.familyInstance.toSchemaView(schemaIR);\n }\n return undefined;\n }\n\n async emit(options: EmitOptions): Promise<EmitResult> {\n const { onProgress, contractConfig } = options;\n\n // Ensure initialized (creates stack and family instance)\n // emit() does NOT require a database connection\n this.init();\n\n if (!this.familyInstance) {\n throw new Error('Family instance was not initialized. This is a bug.');\n }\n\n // Resolve contract source\n let contractRaw: unknown;\n onProgress?.({\n action: 'emit',\n kind: 'spanStart',\n spanId: 'resolveSource',\n label: 'Resolving contract source...',\n });\n\n try {\n switch (contractConfig.source.kind) {\n case 'loader':\n contractRaw = await contractConfig.source.load();\n break;\n case 'value':\n contractRaw = contractConfig.source.value;\n break;\n }\n\n onProgress?.({\n action: 'emit',\n kind: 'spanEnd',\n spanId: 'resolveSource',\n outcome: 'ok',\n });\n } catch (error) {\n onProgress?.({\n action: 'emit',\n kind: 'spanEnd',\n spanId: 'resolveSource',\n outcome: 'error',\n });\n\n return notOk({\n code: 'CONTRACT_SOURCE_INVALID',\n summary: 'Failed to resolve contract source',\n why: error instanceof Error ? error.message : String(error),\n meta: undefined,\n });\n }\n\n // Emit contract\n onProgress?.({\n action: 'emit',\n kind: 'spanStart',\n spanId: 'emit',\n label: 'Emitting contract...',\n });\n\n try {\n const emitResult = await this.familyInstance.emitContract({ contractIR: contractRaw });\n\n onProgress?.({\n action: 'emit',\n kind: 'spanEnd',\n spanId: 'emit',\n outcome: 'ok',\n });\n\n return ok({\n storageHash: emitResult.storageHash,\n ...ifDefined('executionHash', emitResult.executionHash),\n profileHash: emitResult.profileHash,\n contractJson: emitResult.contractJson,\n contractDts: emitResult.contractDts,\n });\n } catch (error) {\n onProgress?.({\n action: 'emit',\n kind: 'spanEnd',\n spanId: 'emit',\n outcome: 'error',\n });\n\n return notOk({\n code: 'EMIT_FAILED',\n summary: 'Failed to emit contract',\n why: error instanceof Error ? error.message : String(error),\n meta: undefined,\n });\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"client-BSZKpZTF.mjs","names":["plannerResult: MigrationPlannerResult","migrationPlan: MigrationPlan","runnerResult: MigrationRunnerResult","contractRaw: unknown"],"sources":["../src/utils/framework-components.ts","../src/control-api/operations/db-init.ts","../src/control-api/client.ts"],"sourcesContent":["import {\n checkContractComponentRequirements,\n type TargetBoundComponentDescriptor,\n} from '@prisma-next/contract/framework-components';\nimport type { ContractIR } from '@prisma-next/contract/ir';\nimport type { ControlPlaneStack } from '@prisma-next/core-control-plane/types';\nimport { errorConfigValidation, errorContractMissingExtensionPacks } from './cli-errors';\n\n/**\n * Asserts that all framework components are compatible with the expected family and target.\n *\n * This function validates that each component in the framework components array:\n * - Has kind 'target', 'adapter', 'extension', or 'driver'\n * - Has familyId matching expectedFamilyId\n * - Has targetId matching expectedTargetId\n *\n * This validation happens at the CLI composition boundary, before passing components\n * to typed planner/runner instances. It fills the gap between runtime validation\n * (via `validateConfig()`) and compile-time type enforcement.\n *\n * @param expectedFamilyId - The expected family ID (e.g., 'sql')\n * @param expectedTargetId - The expected target ID (e.g., 'postgres')\n * @param frameworkComponents - Array of framework components to validate\n * @returns The same array typed as TargetBoundComponentDescriptor\n * @throws CliStructuredError if any component is incompatible\n *\n * @example\n * ```ts\n * const config = await loadConfig();\n * const frameworkComponents = [config.target, config.adapter, ...(config.extensionPacks ?? [])];\n *\n * // Validate and type-narrow components before passing to planner\n * const typedComponents = assertFrameworkComponentsCompatible(\n * config.family.familyId,\n * config.target.targetId,\n * frameworkComponents\n * );\n *\n * const planner = target.migrations.createPlanner(familyInstance);\n * planner.plan({ contract, schema, policy, frameworkComponents: typedComponents });\n * ```\n */\nexport function assertFrameworkComponentsCompatible<\n TFamilyId extends string,\n TTargetId extends string,\n>(\n expectedFamilyId: TFamilyId,\n expectedTargetId: TTargetId,\n frameworkComponents: ReadonlyArray<unknown>,\n): ReadonlyArray<TargetBoundComponentDescriptor<TFamilyId, TTargetId>> {\n for (let i = 0; i < frameworkComponents.length; i++) {\n const component = frameworkComponents[i];\n\n // Check that component is an object\n if (typeof component !== 'object' || component === null) {\n throw errorConfigValidation('frameworkComponents[]', {\n why: `Framework component at index ${i} must be an object`,\n });\n }\n\n const record = component as Record<string, unknown>;\n\n // Check kind\n if (!Object.hasOwn(record, 'kind')) {\n throw errorConfigValidation('frameworkComponents[].kind', {\n why: `Framework component at index ${i} must have 'kind' property`,\n });\n }\n\n const kind = record['kind'];\n if (kind !== 'target' && kind !== 'adapter' && kind !== 'extension' && kind !== 'driver') {\n throw errorConfigValidation('frameworkComponents[].kind', {\n why: `Framework component at index ${i} has invalid kind '${String(kind)}' (must be 'target', 'adapter', 'extension', or 'driver')`,\n });\n }\n\n // Check familyId\n if (!Object.hasOwn(record, 'familyId')) {\n throw errorConfigValidation('frameworkComponents[].familyId', {\n why: `Framework component at index ${i} (kind: ${String(kind)}) must have 'familyId' property`,\n });\n }\n\n const familyId = record['familyId'];\n if (familyId !== expectedFamilyId) {\n throw errorConfigValidation('frameworkComponents[].familyId', {\n why: `Framework component at index ${i} (kind: ${String(kind)}) has familyId '${String(familyId)}' but expected '${expectedFamilyId}'`,\n });\n }\n\n // Check targetId\n if (!Object.hasOwn(record, 'targetId')) {\n throw errorConfigValidation('frameworkComponents[].targetId', {\n why: `Framework component at index ${i} (kind: ${String(kind)}) must have 'targetId' property`,\n });\n }\n\n const targetId = record['targetId'];\n if (targetId !== expectedTargetId) {\n throw errorConfigValidation('frameworkComponents[].targetId', {\n why: `Framework component at index ${i} (kind: ${String(kind)}) has targetId '${String(targetId)}' but expected '${expectedTargetId}'`,\n });\n }\n }\n\n // Type assertion is safe because we've validated all components above\n return frameworkComponents as ReadonlyArray<TargetBoundComponentDescriptor<TFamilyId, TTargetId>>;\n}\n\n/**\n * Validates that a contract is compatible with the configured target, adapter,\n * and extension packs. Throws on family/target mismatches or missing extension packs.\n *\n * This check ensures the emitted contract matches the CLI config before running\n * commands that depend on the contract (e.g., db verify, db sign).\n *\n * @param contract - The contract IR to validate (must include targetFamily, target, extensionPacks).\n * @param stack - The control plane stack (target, adapter, driver, extensionPacks).\n *\n * @throws {CliStructuredError} errorConfigValidation when contract.targetFamily or contract.target\n * doesn't match the configured family/target.\n * @throws {CliStructuredError} errorContractMissingExtensionPacks when the contract requires\n * extension packs that are not provided in the config (includes all missing packs in error.meta).\n *\n * @example\n * ```ts\n * import { assertContractRequirementsSatisfied } from './framework-components';\n *\n * const config = await loadConfig();\n * const contractIR = await loadContractJson(config.contract.output);\n * const stack = createControlPlaneStack({ target: config.target, adapter: config.adapter, ... });\n *\n * // Throws if contract is incompatible with config\n * assertContractRequirementsSatisfied({ contract: contractIR, stack });\n * ```\n */\nexport function assertContractRequirementsSatisfied<\n TFamilyId extends string,\n TTargetId extends string,\n>({\n contract,\n stack,\n}: {\n readonly contract: Pick<ContractIR, 'targetFamily' | 'target' | 'extensionPacks'>;\n readonly stack: ControlPlaneStack<TFamilyId, TTargetId>;\n}): void {\n const providedComponentIds = new Set<string>([stack.target.id, stack.adapter.id]);\n for (const extension of stack.extensionPacks) {\n providedComponentIds.add(extension.id);\n }\n\n const result = checkContractComponentRequirements({\n contract,\n expectedTargetFamily: stack.target.familyId,\n expectedTargetId: stack.target.targetId,\n providedComponentIds,\n });\n\n if (result.familyMismatch) {\n throw errorConfigValidation('contract.targetFamily', {\n why: `Contract was emitted for family '${result.familyMismatch.actual}' but CLI config is wired to '${result.familyMismatch.expected}'.`,\n });\n }\n\n if (result.targetMismatch) {\n throw errorConfigValidation('contract.target', {\n why: `Contract target '${result.targetMismatch.actual}' does not match CLI target '${result.targetMismatch.expected}'.`,\n });\n }\n\n if (result.missingExtensionPackIds.length > 0) {\n throw errorContractMissingExtensionPacks({\n missingExtensionPacks: result.missingExtensionPackIds,\n providedComponentIds: [...providedComponentIds],\n });\n }\n}\n","import type { TargetBoundComponentDescriptor } from '@prisma-next/contract/framework-components';\nimport type { ContractIR } from '@prisma-next/contract/ir';\nimport type {\n ControlDriverInstance,\n ControlFamilyInstance,\n MigrationPlan,\n MigrationPlannerResult,\n MigrationPlanOperation,\n MigrationRunnerResult,\n TargetMigrationsCapability,\n} from '@prisma-next/core-control-plane/types';\nimport { notOk, ok } from '@prisma-next/utils/result';\nimport type { DbInitResult, DbInitSuccess, OnControlProgress } from '../types';\n\n/**\n * Options for executing dbInit operation.\n */\nexport interface ExecuteDbInitOptions<TFamilyId extends string, TTargetId extends string> {\n readonly driver: ControlDriverInstance<TFamilyId, TTargetId>;\n readonly familyInstance: ControlFamilyInstance<TFamilyId>;\n readonly contractIR: ContractIR;\n readonly mode: 'plan' | 'apply';\n readonly migrations: TargetMigrationsCapability<\n TFamilyId,\n TTargetId,\n ControlFamilyInstance<TFamilyId>\n >;\n readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<TFamilyId, TTargetId>>;\n /** Optional progress callback for observing operation progress */\n readonly onProgress?: OnControlProgress;\n}\n\n/**\n * Executes the dbInit operation.\n *\n * This is the core logic extracted from the CLI command, without any file I/O,\n * process.exit(), or console output. It uses the Result pattern to return\n * success or failure details.\n *\n * @param options - The options for executing dbInit\n * @returns Result with DbInitSuccess on success, DbInitFailure on failure\n */\nexport async function executeDbInit<TFamilyId extends string, TTargetId extends string>(\n options: ExecuteDbInitOptions<TFamilyId, TTargetId>,\n): Promise<DbInitResult> {\n const { driver, familyInstance, contractIR, mode, migrations, frameworkComponents, onProgress } =\n options;\n\n // Create planner and runner from target migrations capability\n const planner = migrations.createPlanner(familyInstance);\n const runner = migrations.createRunner(familyInstance);\n\n // Introspect live schema\n const introspectSpanId = 'introspect';\n onProgress?.({\n action: 'dbInit',\n kind: 'spanStart',\n spanId: introspectSpanId,\n label: 'Introspecting database schema',\n });\n const schemaIR = await familyInstance.introspect({ driver });\n onProgress?.({\n action: 'dbInit',\n kind: 'spanEnd',\n spanId: introspectSpanId,\n outcome: 'ok',\n });\n\n // Policy for init mode (additive only)\n const policy = { allowedOperationClasses: ['additive'] as const };\n\n // Plan migration\n const planSpanId = 'plan';\n onProgress?.({\n action: 'dbInit',\n kind: 'spanStart',\n spanId: planSpanId,\n label: 'Planning migration',\n });\n const plannerResult: MigrationPlannerResult = await planner.plan({\n contract: contractIR,\n schema: schemaIR,\n policy,\n frameworkComponents,\n });\n\n if (plannerResult.kind === 'failure') {\n onProgress?.({\n action: 'dbInit',\n kind: 'spanEnd',\n spanId: planSpanId,\n outcome: 'error',\n });\n return notOk({\n code: 'PLANNING_FAILED' as const,\n summary: 'Migration planning failed due to conflicts',\n conflicts: plannerResult.conflicts,\n why: undefined,\n meta: undefined,\n });\n }\n\n const migrationPlan: MigrationPlan = plannerResult.plan;\n onProgress?.({\n action: 'dbInit',\n kind: 'spanEnd',\n spanId: planSpanId,\n outcome: 'ok',\n });\n\n // Check for existing marker - handle idempotency and mismatch errors\n const checkMarkerSpanId = 'checkMarker';\n onProgress?.({\n action: 'dbInit',\n kind: 'spanStart',\n spanId: checkMarkerSpanId,\n label: 'Checking contract marker',\n });\n const existingMarker = await familyInstance.readMarker({ driver });\n if (existingMarker) {\n const markerMatchesDestination =\n existingMarker.storageHash === migrationPlan.destination.storageHash &&\n (!migrationPlan.destination.profileHash ||\n existingMarker.profileHash === migrationPlan.destination.profileHash);\n\n if (markerMatchesDestination) {\n // Already at destination - return success with no operations\n onProgress?.({\n action: 'dbInit',\n kind: 'spanEnd',\n spanId: checkMarkerSpanId,\n outcome: 'skipped',\n });\n const result: DbInitSuccess = {\n mode,\n plan: { operations: [] },\n ...(mode === 'apply'\n ? {\n execution: { operationsPlanned: 0, operationsExecuted: 0 },\n marker: {\n storageHash: existingMarker.storageHash,\n profileHash: existingMarker.profileHash,\n },\n }\n : {}),\n summary: 'Database already at target contract state',\n };\n return ok(result);\n }\n\n // Marker exists but doesn't match destination - fail\n onProgress?.({\n action: 'dbInit',\n kind: 'spanEnd',\n spanId: checkMarkerSpanId,\n outcome: 'error',\n });\n return notOk({\n code: 'MARKER_ORIGIN_MISMATCH' as const,\n summary: 'Existing contract marker does not match plan destination',\n marker: {\n storageHash: existingMarker.storageHash,\n profileHash: existingMarker.profileHash,\n },\n destination: {\n storageHash: migrationPlan.destination.storageHash,\n profileHash: migrationPlan.destination.profileHash,\n },\n why: undefined,\n conflicts: undefined,\n meta: undefined,\n });\n }\n\n onProgress?.({\n action: 'dbInit',\n kind: 'spanEnd',\n spanId: checkMarkerSpanId,\n outcome: 'ok',\n });\n\n // Plan mode - don't execute\n if (mode === 'plan') {\n const result: DbInitSuccess = {\n mode: 'plan',\n plan: { operations: migrationPlan.operations },\n summary: `Planned ${migrationPlan.operations.length} operation(s)`,\n };\n return ok(result);\n }\n\n // Apply mode - execute runner\n const applySpanId = 'apply';\n onProgress?.({\n action: 'dbInit',\n kind: 'spanStart',\n spanId: applySpanId,\n label: 'Applying migration plan',\n });\n\n const callbacks = onProgress\n ? {\n onOperationStart: (op: MigrationPlanOperation) => {\n onProgress({\n action: 'dbInit',\n kind: 'spanStart',\n spanId: `operation:${op.id}`,\n parentSpanId: applySpanId,\n label: op.label,\n });\n },\n onOperationComplete: (op: MigrationPlanOperation) => {\n onProgress({\n action: 'dbInit',\n kind: 'spanEnd',\n spanId: `operation:${op.id}`,\n outcome: 'ok',\n });\n },\n }\n : undefined;\n\n const runnerResult: MigrationRunnerResult = await runner.execute({\n plan: migrationPlan,\n driver,\n destinationContract: contractIR,\n policy,\n ...(callbacks ? { callbacks } : {}),\n // db init plans and applies back-to-back from a fresh introspection, so per-operation\n // pre/postchecks and the idempotency probe are usually redundant overhead. We still\n // enforce marker/origin compatibility and a full schema verification after apply.\n executionChecks: {\n prechecks: false,\n postchecks: false,\n idempotencyChecks: false,\n },\n frameworkComponents,\n });\n\n if (!runnerResult.ok) {\n onProgress?.({\n action: 'dbInit',\n kind: 'spanEnd',\n spanId: applySpanId,\n outcome: 'error',\n });\n return notOk({\n code: 'RUNNER_FAILED' as const,\n summary: runnerResult.failure.summary,\n why: runnerResult.failure.why,\n meta: runnerResult.failure.meta,\n conflicts: undefined,\n });\n }\n\n const execution = runnerResult.value;\n\n onProgress?.({\n action: 'dbInit',\n kind: 'spanEnd',\n spanId: applySpanId,\n outcome: 'ok',\n });\n\n const result: DbInitSuccess = {\n mode: 'apply',\n plan: { operations: migrationPlan.operations },\n execution: {\n operationsPlanned: execution.operationsPlanned,\n operationsExecuted: execution.operationsExecuted,\n },\n marker: migrationPlan.destination.profileHash\n ? {\n storageHash: migrationPlan.destination.storageHash,\n profileHash: migrationPlan.destination.profileHash,\n }\n : { storageHash: migrationPlan.destination.storageHash },\n summary: `Applied ${execution.operationsExecuted} operation(s), marker written`,\n };\n return ok(result);\n}\n","import type { TargetBoundComponentDescriptor } from '@prisma-next/contract/framework-components';\nimport type { CoreSchemaView } from '@prisma-next/core-control-plane/schema-view';\nimport { createControlPlaneStack } from '@prisma-next/core-control-plane/stack';\nimport type {\n ControlDriverInstance,\n ControlFamilyInstance,\n ControlPlaneStack,\n SignDatabaseResult,\n VerifyDatabaseResult,\n VerifyDatabaseSchemaResult,\n} from '@prisma-next/core-control-plane/types';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport { notOk, ok } from '@prisma-next/utils/result';\nimport { assertFrameworkComponentsCompatible } from '../utils/framework-components';\nimport { executeDbInit } from './operations/db-init';\nimport type {\n ControlClient,\n ControlClientOptions,\n DbInitOptions,\n DbInitResult,\n EmitOptions,\n EmitResult,\n IntrospectOptions,\n SchemaVerifyOptions,\n SignOptions,\n VerifyOptions,\n} from './types';\n\n/**\n * Creates a programmatic control client for Prisma Next operations.\n *\n * The client accepts framework component descriptors at creation time,\n * manages driver lifecycle via connect()/close(), and exposes domain\n * operations that delegate to the existing family instance methods.\n *\n * @see {@link ControlClient} for the client interface\n * @see README.md \"Programmatic Control API\" section for usage examples\n */\nexport function createControlClient(options: ControlClientOptions): ControlClient {\n return new ControlClientImpl(options);\n}\n\n/**\n * Implementation of ControlClient.\n * Manages initialization and connection state, delegates operations to family instance.\n */\nclass ControlClientImpl implements ControlClient {\n private readonly options: ControlClientOptions;\n private stack: ControlPlaneStack<string, string> | null = null;\n private driver: ControlDriverInstance<string, string> | null = null;\n private familyInstance: ControlFamilyInstance<string> | null = null;\n private frameworkComponents: ReadonlyArray<\n TargetBoundComponentDescriptor<string, string>\n > | null = null;\n private initialized = false;\n private readonly defaultConnection: unknown;\n\n constructor(options: ControlClientOptions) {\n this.options = options;\n this.defaultConnection = options.connection;\n }\n\n init(): void {\n if (this.initialized) {\n return; // Idempotent\n }\n\n // Create the control plane stack\n this.stack = createControlPlaneStack({\n target: this.options.target,\n adapter: this.options.adapter,\n driver: this.options.driver,\n extensionPacks: this.options.extensionPacks,\n });\n\n // Create family instance using the stack\n this.familyInstance = this.options.family.create(this.stack);\n\n // Validate and type-narrow framework components\n const rawComponents = [\n this.options.target,\n this.options.adapter,\n ...(this.options.extensionPacks ?? []),\n ];\n this.frameworkComponents = assertFrameworkComponentsCompatible(\n this.options.family.familyId,\n this.options.target.targetId,\n rawComponents,\n );\n\n this.initialized = true;\n }\n\n async connect(connection?: unknown): Promise<void> {\n // Auto-init if needed\n this.init();\n\n if (this.driver) {\n throw new Error('Already connected. Call close() before reconnecting.');\n }\n\n // Resolve connection: argument > default from options\n const resolvedConnection = connection ?? this.defaultConnection;\n if (resolvedConnection === undefined) {\n throw new Error(\n 'No connection provided. Pass a connection to connect() or provide a default connection when creating the client.',\n );\n }\n\n // Check for driver descriptor\n if (!this.stack?.driver) {\n throw new Error(\n 'Driver is not configured. Pass a driver descriptor when creating the control client to enable database operations.',\n );\n }\n\n // Create driver instance\n // Cast through any since connection type is driver-specific at runtime.\n // The driver descriptor is typed with any for TConnection in ControlClientOptions,\n // but createControlPlaneStack defaults it to string. We bridge this at runtime.\n // biome-ignore lint/suspicious/noExplicitAny: required for runtime connection type flexibility\n this.driver = await this.stack?.driver.create(resolvedConnection as any);\n }\n\n async close(): Promise<void> {\n if (this.driver) {\n await this.driver.close();\n this.driver = null;\n }\n }\n\n private async ensureConnected(): Promise<{\n driver: ControlDriverInstance<string, string>;\n familyInstance: ControlFamilyInstance<string>;\n frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<string, string>>;\n }> {\n // Auto-init if needed\n this.init();\n\n // Auto-connect if not connected and default connection is available\n if (!this.driver && this.defaultConnection !== undefined) {\n await this.connect(this.defaultConnection);\n }\n\n if (!this.driver || !this.familyInstance || !this.frameworkComponents) {\n throw new Error('Not connected. Call connect(connection) first.');\n }\n return {\n driver: this.driver,\n familyInstance: this.familyInstance,\n frameworkComponents: this.frameworkComponents,\n };\n }\n\n async verify(options: VerifyOptions): Promise<VerifyDatabaseResult> {\n const { onProgress } = options;\n\n // Connect with progress span if connection provided\n if (options.connection !== undefined) {\n onProgress?.({\n action: 'verify',\n kind: 'spanStart',\n spanId: 'connect',\n label: 'Connecting to database...',\n });\n try {\n await this.connect(options.connection);\n onProgress?.({\n action: 'verify',\n kind: 'spanEnd',\n spanId: 'connect',\n outcome: 'ok',\n });\n } catch (error) {\n onProgress?.({\n action: 'verify',\n kind: 'spanEnd',\n spanId: 'connect',\n outcome: 'error',\n });\n throw error;\n }\n }\n\n const { driver, familyInstance } = await this.ensureConnected();\n\n // Validate contract using family instance\n const contractIR = familyInstance.validateContractIR(options.contractIR);\n\n // Emit verify span\n onProgress?.({\n action: 'verify',\n kind: 'spanStart',\n spanId: 'verify',\n label: 'Verifying contract marker...',\n });\n\n try {\n // Delegate to family instance verify method\n // Note: We pass empty strings for contractPath/configPath since the programmatic\n // API doesn't deal with file paths. The family instance accepts these as optional\n // metadata for error reporting.\n const result = await familyInstance.verify({\n driver,\n contractIR,\n expectedTargetId: this.options.target.targetId,\n contractPath: '',\n });\n\n onProgress?.({\n action: 'verify',\n kind: 'spanEnd',\n spanId: 'verify',\n outcome: result.ok ? 'ok' : 'error',\n });\n\n return result;\n } catch (error) {\n onProgress?.({\n action: 'verify',\n kind: 'spanEnd',\n spanId: 'verify',\n outcome: 'error',\n });\n throw error;\n }\n }\n\n async schemaVerify(options: SchemaVerifyOptions): Promise<VerifyDatabaseSchemaResult> {\n const { onProgress } = options;\n\n // Connect with progress span if connection provided\n if (options.connection !== undefined) {\n onProgress?.({\n action: 'schemaVerify',\n kind: 'spanStart',\n spanId: 'connect',\n label: 'Connecting to database...',\n });\n try {\n await this.connect(options.connection);\n onProgress?.({\n action: 'schemaVerify',\n kind: 'spanEnd',\n spanId: 'connect',\n outcome: 'ok',\n });\n } catch (error) {\n onProgress?.({\n action: 'schemaVerify',\n kind: 'spanEnd',\n spanId: 'connect',\n outcome: 'error',\n });\n throw error;\n }\n }\n\n const { driver, familyInstance, frameworkComponents } = await this.ensureConnected();\n\n // Validate contract using family instance\n const contractIR = familyInstance.validateContractIR(options.contractIR);\n\n // Emit schemaVerify span\n onProgress?.({\n action: 'schemaVerify',\n kind: 'spanStart',\n spanId: 'schemaVerify',\n label: 'Verifying database schema...',\n });\n\n try {\n // Delegate to family instance schemaVerify method\n const result = await familyInstance.schemaVerify({\n driver,\n contractIR,\n strict: options.strict ?? false,\n contractPath: '',\n frameworkComponents,\n });\n\n onProgress?.({\n action: 'schemaVerify',\n kind: 'spanEnd',\n spanId: 'schemaVerify',\n outcome: result.ok ? 'ok' : 'error',\n });\n\n return result;\n } catch (error) {\n onProgress?.({\n action: 'schemaVerify',\n kind: 'spanEnd',\n spanId: 'schemaVerify',\n outcome: 'error',\n });\n throw error;\n }\n }\n\n async sign(options: SignOptions): Promise<SignDatabaseResult> {\n const { onProgress } = options;\n\n // Connect with progress span if connection provided\n if (options.connection !== undefined) {\n onProgress?.({\n action: 'sign',\n kind: 'spanStart',\n spanId: 'connect',\n label: 'Connecting to database...',\n });\n try {\n await this.connect(options.connection);\n onProgress?.({\n action: 'sign',\n kind: 'spanEnd',\n spanId: 'connect',\n outcome: 'ok',\n });\n } catch (error) {\n onProgress?.({\n action: 'sign',\n kind: 'spanEnd',\n spanId: 'connect',\n outcome: 'error',\n });\n throw error;\n }\n }\n\n const { driver, familyInstance } = await this.ensureConnected();\n\n // Validate contract using family instance\n const contractIR = familyInstance.validateContractIR(options.contractIR);\n\n // Emit sign span\n onProgress?.({\n action: 'sign',\n kind: 'spanStart',\n spanId: 'sign',\n label: 'Signing database...',\n });\n\n try {\n // Delegate to family instance sign method\n const result = await familyInstance.sign({\n driver,\n contractIR,\n contractPath: options.contractPath ?? '',\n ...ifDefined('configPath', options.configPath),\n });\n\n onProgress?.({\n action: 'sign',\n kind: 'spanEnd',\n spanId: 'sign',\n outcome: 'ok',\n });\n\n return result;\n } catch (error) {\n onProgress?.({\n action: 'sign',\n kind: 'spanEnd',\n spanId: 'sign',\n outcome: 'error',\n });\n throw error;\n }\n }\n\n async dbInit(options: DbInitOptions): Promise<DbInitResult> {\n const { onProgress } = options;\n\n // Connect with progress span if connection provided\n if (options.connection !== undefined) {\n onProgress?.({\n action: 'dbInit',\n kind: 'spanStart',\n spanId: 'connect',\n label: 'Connecting to database...',\n });\n try {\n await this.connect(options.connection);\n onProgress?.({\n action: 'dbInit',\n kind: 'spanEnd',\n spanId: 'connect',\n outcome: 'ok',\n });\n } catch (error) {\n onProgress?.({\n action: 'dbInit',\n kind: 'spanEnd',\n spanId: 'connect',\n outcome: 'error',\n });\n throw error;\n }\n }\n\n const { driver, familyInstance, frameworkComponents } = await this.ensureConnected();\n\n // Check target supports migrations\n if (!this.options.target.migrations) {\n throw new Error(`Target \"${this.options.target.targetId}\" does not support migrations`);\n }\n\n // Validate contract using family instance\n const contractIR = familyInstance.validateContractIR(options.contractIR);\n\n // Delegate to extracted dbInit operation\n return executeDbInit({\n driver,\n familyInstance,\n contractIR,\n mode: options.mode,\n migrations: this.options.target.migrations,\n frameworkComponents,\n ...(onProgress ? { onProgress } : {}),\n });\n }\n\n async introspect(options?: IntrospectOptions): Promise<unknown> {\n const onProgress = options?.onProgress;\n\n // Connect with progress span if connection provided\n if (options?.connection !== undefined) {\n onProgress?.({\n action: 'introspect',\n kind: 'spanStart',\n spanId: 'connect',\n label: 'Connecting to database...',\n });\n try {\n await this.connect(options.connection);\n onProgress?.({\n action: 'introspect',\n kind: 'spanEnd',\n spanId: 'connect',\n outcome: 'ok',\n });\n } catch (error) {\n onProgress?.({\n action: 'introspect',\n kind: 'spanEnd',\n spanId: 'connect',\n outcome: 'error',\n });\n throw error;\n }\n }\n\n const { driver, familyInstance } = await this.ensureConnected();\n\n // TODO: Pass schema option to familyInstance.introspect when schema filtering is implemented\n const _schema = options?.schema;\n void _schema;\n\n // Emit introspect span\n onProgress?.({\n action: 'introspect',\n kind: 'spanStart',\n spanId: 'introspect',\n label: 'Introspecting database schema...',\n });\n\n try {\n const result = await familyInstance.introspect({ driver });\n\n onProgress?.({\n action: 'introspect',\n kind: 'spanEnd',\n spanId: 'introspect',\n outcome: 'ok',\n });\n\n return result;\n } catch (error) {\n onProgress?.({\n action: 'introspect',\n kind: 'spanEnd',\n spanId: 'introspect',\n outcome: 'error',\n });\n throw error;\n }\n }\n\n toSchemaView(schemaIR: unknown): CoreSchemaView | undefined {\n this.init();\n if (this.familyInstance?.toSchemaView) {\n return this.familyInstance.toSchemaView(schemaIR);\n }\n return undefined;\n }\n\n async emit(options: EmitOptions): Promise<EmitResult> {\n const { onProgress, contractConfig } = options;\n\n // Ensure initialized (creates stack and family instance)\n // emit() does NOT require a database connection\n this.init();\n\n if (!this.familyInstance) {\n throw new Error('Family instance was not initialized. This is a bug.');\n }\n\n let contractRaw: unknown;\n onProgress?.({\n action: 'emit',\n kind: 'spanStart',\n spanId: 'resolveSource',\n label: 'Resolving contract source...',\n });\n\n try {\n const providerResult = await contractConfig.sourceProvider();\n if (!providerResult.ok) {\n onProgress?.({\n action: 'emit',\n kind: 'spanEnd',\n spanId: 'resolveSource',\n outcome: 'error',\n });\n\n return notOk({\n code: 'CONTRACT_SOURCE_INVALID',\n summary: providerResult.failure.summary,\n why: providerResult.failure.summary,\n meta: providerResult.failure.meta,\n diagnostics: providerResult.failure,\n });\n }\n contractRaw = providerResult.value;\n\n onProgress?.({\n action: 'emit',\n kind: 'spanEnd',\n spanId: 'resolveSource',\n outcome: 'ok',\n });\n } catch (error) {\n onProgress?.({\n action: 'emit',\n kind: 'spanEnd',\n spanId: 'resolveSource',\n outcome: 'error',\n });\n\n const message = error instanceof Error ? error.message : String(error);\n return notOk({\n code: 'CONTRACT_SOURCE_INVALID',\n summary: 'Failed to resolve contract source',\n why: message,\n diagnostics: {\n summary: 'Contract source provider threw an exception',\n diagnostics: [\n {\n code: 'PROVIDER_THROW',\n message,\n },\n ],\n },\n meta: undefined,\n });\n }\n\n // Emit contract\n onProgress?.({\n action: 'emit',\n kind: 'spanStart',\n spanId: 'emit',\n label: 'Emitting contract...',\n });\n\n try {\n const emitResult = await this.familyInstance.emitContract({ contractIR: contractRaw });\n\n onProgress?.({\n action: 'emit',\n kind: 'spanEnd',\n spanId: 'emit',\n outcome: 'ok',\n });\n\n return ok({\n storageHash: emitResult.storageHash,\n ...ifDefined('executionHash', emitResult.executionHash),\n profileHash: emitResult.profileHash,\n contractJson: emitResult.contractJson,\n contractDts: emitResult.contractDts,\n });\n } catch (error) {\n onProgress?.({\n action: 'emit',\n kind: 'spanEnd',\n spanId: 'emit',\n outcome: 'error',\n });\n\n return notOk({\n code: 'EMIT_FAILED',\n summary: 'Failed to emit contract',\n why: error instanceof Error ? error.message : String(error),\n meta: undefined,\n });\n }\n }\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"contract-emit.d.mts","names":[],"sources":["../../src/commands/contract-emit.ts"],"sourcesContent":[],"mappings":";;;iBAsNgB,yBAAA,CAAA,GAA6B"}
1
+ {"version":3,"file":"contract-emit.d.mts","names":[],"sources":["../../src/commands/contract-emit.ts"],"sourcesContent":[],"mappings":";;;iBAsOgB,yBAAA,CAAA,GAA6B"}
@@ -1,21 +1,34 @@
1
- import { t as loadConfig } from "../config-loader-CnnWuluc.mjs";
2
- import { f as errorRuntime, h as errorUnexpected$1, n as CliStructuredError, t as createControlClient } from "../client-Lm9Q6aQM.mjs";
1
+ import { t as loadConfig } from "../config-loader-BJ8HsEdA.mjs";
2
+ import { f as errorRuntime, h as errorUnexpected$1, n as CliStructuredError, t as createControlClient } from "../client-BSZKpZTF.mjs";
3
3
  import { _ as formatSuccessMessage, b as parseGlobalFlags, c as formatEmitOutput, g as formatStyledHeader, n as createProgressAdapter, r as formatCommandHelp, s as formatEmitJson, t as handleResult, x as setCommandDescriptions } from "../result-handler-BZPY7HX4.mjs";
4
4
  import { Command } from "commander";
5
5
  import { mkdirSync, writeFileSync } from "node:fs";
6
- import { dirname, relative, resolve } from "node:path";
7
6
  import { errorContractConfigMissing } from "@prisma-next/core-control-plane/errors";
8
7
  import { notOk, ok } from "@prisma-next/utils/result";
8
+ import { dirname, isAbsolute, join, relative, resolve } from "pathe";
9
9
 
10
10
  //#region src/commands/contract-emit.ts
11
+ function mapDiagnosticsToIssues(failure) {
12
+ return (failure.diagnostics?.diagnostics ?? []).map((diagnostic) => {
13
+ const location = diagnostic.sourceId && diagnostic.span ? ` (${diagnostic.sourceId}:${diagnostic.span.start.line}:${diagnostic.span.start.column})` : diagnostic.sourceId ? ` (${diagnostic.sourceId})` : "";
14
+ return {
15
+ kind: diagnostic.code,
16
+ message: `${diagnostic.message}${location}`
17
+ };
18
+ });
19
+ }
11
20
  /**
12
21
  * Maps an EmitFailure to a CliStructuredError for consistent error handling.
13
22
  */
14
23
  function mapEmitFailure(failure) {
15
- if (failure.code === "CONTRACT_SOURCE_INVALID") return errorRuntime(failure.summary, {
16
- why: failure.why ?? "Contract source is invalid",
17
- fix: "Check your contract source configuration in prisma-next.config.ts"
18
- });
24
+ if (failure.code === "CONTRACT_SOURCE_INVALID") {
25
+ const issues = mapDiagnosticsToIssues(failure);
26
+ return errorRuntime(failure.summary, {
27
+ why: failure.why ?? "Contract source provider failed",
28
+ fix: "Check your contract source provider in prisma-next.config.ts and ensure it returns Result<ContractIR, Diagnostics>",
29
+ ...issues.length > 0 ? { meta: { issues } } : {}
30
+ });
31
+ }
19
32
  if (failure.code === "EMIT_FAILED") return errorRuntime(failure.summary, {
20
33
  why: failure.why ?? "Failed to emit contract",
21
34
  fix: "Check your contract configuration and ensure the source is valid"
@@ -34,11 +47,12 @@ async function executeContractEmitCommand(options, flags, startTime) {
34
47
  if (error instanceof CliStructuredError) return notOk(error);
35
48
  return notOk(errorUnexpected$1(error instanceof Error ? error.message : String(error), { why: "Failed to load config" }));
36
49
  }
37
- if (!config.contract) return notOk(errorContractConfigMissing({ why: "Config.contract is required for emit. Define it in your config: contract: { source: ..., output: ..., types: ... }" }));
50
+ if (!config.contract) return notOk(errorContractConfigMissing({ why: "Config.contract is required for emit. Define it in your config: contract: { source: ..., output: ... }" }));
38
51
  const contractConfig = config.contract;
39
52
  if (!contractConfig.output) return notOk(errorContractConfigMissing({ why: "Contract config must have output path. This should not happen if defineConfig() was used." }));
40
53
  if (!contractConfig.output.endsWith(".json")) return notOk(errorContractConfigMissing({ why: "Contract config output path must end with .json (e.g., \"src/prisma/contract.json\")" }));
41
- const outputJsonPath = resolve(contractConfig.output);
54
+ const configDir = options.config ? dirname(resolve(options.config)) : process.cwd();
55
+ const outputJsonPath = isAbsolute(contractConfig.output) ? contractConfig.output : join(configDir, contractConfig.output);
42
56
  const outputDtsPath = `${outputJsonPath.slice(0, -5)}.d.ts`;
43
57
  if (flags.json !== "object" && !flags.quiet) {
44
58
  const configPath = options.config ? relative(process.cwd(), resolve(options.config)) : "prisma-next.config.ts";
@@ -46,7 +60,7 @@ async function executeContractEmitCommand(options, flags, startTime) {
46
60
  const typesPath = relative(process.cwd(), outputDtsPath);
47
61
  const header = formatStyledHeader({
48
62
  command: "contract emit",
49
- description: "Write your contract to JSON and sign it",
63
+ description: "Emit your contract artifacts",
50
64
  url: "https://pris.ly/contract-emit",
51
65
  details: [
52
66
  {
@@ -74,16 +88,9 @@ async function executeContractEmitCommand(options, flags, startTime) {
74
88
  });
75
89
  const onProgress = createProgressAdapter({ flags });
76
90
  try {
77
- const source = typeof contractConfig.source === "function" ? {
78
- kind: "loader",
79
- load: contractConfig.source
80
- } : {
81
- kind: "value",
82
- value: contractConfig.source
83
- };
84
91
  const result = await client.emit({
85
92
  contractConfig: {
86
- source,
93
+ sourceProvider: contractConfig.source,
87
94
  output: outputJsonPath
88
95
  },
89
96
  onProgress
@@ -114,7 +121,7 @@ async function executeContractEmitCommand(options, flags, startTime) {
114
121
  }
115
122
  function createContractEmitCommand() {
116
123
  const command = new Command("emit");
117
- setCommandDescriptions(command, "Write your contract to JSON and sign it", "Reads your contract source (TypeScript or Prisma schema) and emits contract.json and\ncontract.d.ts. The contract.json contains the canonical contract structure, and\ncontract.d.ts provides TypeScript types for type-safe query building.");
124
+ setCommandDescriptions(command, "Emit your contract artifacts", "Reads your contract source (TypeScript or Prisma schema) and emits contract.json and\ncontract.d.ts. The contract.json contains the canonical contract structure, and\ncontract.d.ts provides TypeScript types for type-safe query building.");
118
125
  command.configureHelp({ formatHelp: (cmd) => {
119
126
  return formatCommandHelp({
120
127
  command: cmd,