@prisma-next/config
Advanced tools
| import { AssembledAuthoringContributions, ControlAdapterDescriptor, ControlDriverDescriptor, ControlDriverInstance, ControlExtensionDescriptor, ControlFamilyDescriptor, ControlMutationDefaults, ControlTargetDescriptor } from "@prisma-next/framework-components/control"; | ||
| import { Contract } from "@prisma-next/contract/types"; | ||
| import { CodecLookup } from "@prisma-next/framework-components/codec"; | ||
| import { CapabilityMatrix } from "@prisma-next/framework-components/components"; | ||
| import { Result } from "@prisma-next/utils/result"; | ||
| //#region src/contract-source-types.d.ts | ||
| interface ContractSourceDiagnosticPosition { | ||
| readonly offset: number; | ||
| readonly line: number; | ||
| readonly column: number; | ||
| } | ||
| interface ContractSourceDiagnosticSpan { | ||
| readonly start: ContractSourceDiagnosticPosition; | ||
| readonly end: ContractSourceDiagnosticPosition; | ||
| } | ||
| interface ContractSourceDiagnostic { | ||
| readonly code: string; | ||
| readonly message: string; | ||
| readonly sourceId?: string; | ||
| readonly span?: ContractSourceDiagnosticSpan; | ||
| /** | ||
| * Optional structured payload for machine-readable consumers (agents, | ||
| * IDE extensions, CLI auto-fix). Human-readable prose lives in `message`; | ||
| * `data` carries the extracted facts (e.g. `{ namespace: 'pgvector' }`). | ||
| */ | ||
| readonly data?: Readonly<Record<string, unknown>>; | ||
| } | ||
| interface ContractSourceDiagnostics { | ||
| readonly summary: string; | ||
| readonly diagnostics: readonly ContractSourceDiagnostic[]; | ||
| readonly meta?: Record<string, unknown>; | ||
| } | ||
| interface ContractSourceContext { | ||
| readonly composedExtensions: readonly string[]; | ||
| /** Extension contracts keyed by space ID, required for cross-space FK resolution. */ | ||
| readonly composedExtensionContracts: ReadonlyMap<string, Contract>; | ||
| readonly authoringContributions: AssembledAuthoringContributions; | ||
| readonly codecLookup: CodecLookup; | ||
| readonly controlMutationDefaults: ControlMutationDefaults; | ||
| readonly resolvedInputs: readonly string[]; | ||
| readonly capabilities: CapabilityMatrix; | ||
| } | ||
| /** Lets format-aware tooling avoid file-extension sniffing and opaque loader introspection. */ | ||
| type ContractSourceFormat = 'psl' | 'typescript'; | ||
| interface ContractSourceProviderBase { | ||
| readonly inputs?: readonly string[]; | ||
| readonly load: (context: ContractSourceContext) => Promise<Result<Contract, ContractSourceDiagnostics>>; | ||
| } | ||
| interface PslContractSourceProvider extends ContractSourceProviderBase { | ||
| readonly format: 'psl'; | ||
| } | ||
| interface TypeScriptContractSourceProvider extends ContractSourceProviderBase { | ||
| readonly format: 'typescript'; | ||
| } | ||
| /** | ||
| * Third-party or unspecified source formats. Absent (or unrecognized) | ||
| * `format` means format-aware tooling must leave the source untouched. | ||
| * Narrowing to a known format flows only through capability guards owned by | ||
| * the authoring layer. | ||
| */ | ||
| interface OpaqueContractSourceProvider extends ContractSourceProviderBase { | ||
| readonly format?: string; | ||
| } | ||
| type ContractSourceProvider = PslContractSourceProvider | TypeScriptContractSourceProvider | OpaqueContractSourceProvider; | ||
| //#endregion | ||
| //#region src/config-types.d.ts | ||
| /** | ||
| * Contract configuration specifying source and artifact locations. | ||
| */ | ||
| interface ContractConfig { | ||
| /** | ||
| * Contract source provider. The provider is always async and must return | ||
| * a Result containing either a Contract or structured diagnostics. | ||
| */ | ||
| readonly source: ContractSourceProvider; | ||
| /** | ||
| * Path to contract.json artifact. Providers that know an input path (PSL, | ||
| * `typescriptContractFromPath`) derive an output colocated with that input | ||
| * so this rarely needs to be set explicitly. The `.d.ts` types file is | ||
| * always emitted next to the JSON (e.g., `contract.json` → `contract.d.ts`). | ||
| */ | ||
| readonly output?: string; | ||
| } | ||
| interface FormatterConfig { | ||
| readonly indent?: number | 'tab'; | ||
| readonly newline?: 'LF' | 'CRLF'; | ||
| } | ||
| /** | ||
| * Default *source* directory for the contract file the user authors at `init` | ||
| * time. Output artefacts colocate with source per the same rule path-bearing | ||
| * providers apply. | ||
| */ | ||
| declare const DEFAULT_CONTRACT_SOURCE_DIR = "src/prisma"; | ||
| declare function normalizeContractConfig(contract: ContractConfig): ContractConfig & { | ||
| readonly output: string; | ||
| }; | ||
| /** | ||
| * Configuration for Prisma Next CLI. | ||
| * Uses Control*Descriptor types for type-safe wiring with compile-time compatibility checks. | ||
| * | ||
| * @template TFamilyId - The family ID (e.g., 'sql', 'document') | ||
| * @template TTargetId - The target ID (e.g., 'postgres', 'mysql') | ||
| * @template TConnection - The driver connection input type (defaults to `unknown` for config flexibility) | ||
| */ | ||
| interface PrismaNextConfig<TFamilyId extends string = string, TTargetId extends string = string, TConnection = unknown> { | ||
| readonly family: ControlFamilyDescriptor<TFamilyId>; | ||
| readonly target: ControlTargetDescriptor<TFamilyId, TTargetId>; | ||
| readonly adapter: ControlAdapterDescriptor<TFamilyId, TTargetId>; | ||
| readonly extensions?: readonly ControlExtensionDescriptor<TFamilyId, TTargetId>[]; | ||
| /** | ||
| * Driver descriptor for DB-connected CLI commands. | ||
| * Required for DB-connected commands (e.g., db verify). | ||
| * Optional for commands that don't need database access (e.g., emit). | ||
| * The driver's connection type matches the TConnection config parameter. | ||
| */ | ||
| readonly driver?: ControlDriverDescriptor<TFamilyId, TTargetId, ControlDriverInstance<TFamilyId, TTargetId>, TConnection>; | ||
| /** | ||
| * Database connection configuration. | ||
| * The connection type is driver-specific (e.g., URL string for Postgres). | ||
| */ | ||
| readonly db?: { | ||
| /** | ||
| * Driver-specific connection input. | ||
| * For Postgres: a connection string (URL). | ||
| * For other drivers: may be a structured object. | ||
| */ | ||
| readonly connection?: TConnection; | ||
| }; | ||
| /** | ||
| * Contract configuration. Specifies source and artifact locations. | ||
| * Required for emit command; optional for other commands that only read artifacts. | ||
| */ | ||
| readonly contract?: ContractConfig; | ||
| /** | ||
| * Migration configuration. Controls where on-disk migration packages are stored. | ||
| */ | ||
| readonly migrations?: { | ||
| /** Directory for migration packages, relative to config file. Defaults to 'migrations'. */ | ||
| readonly dir?: string; | ||
| }; | ||
| readonly formatter?: FormatterConfig; | ||
| } | ||
| /** | ||
| * Helper function to define a Prisma Next config. | ||
| * Validates and normalizes the config using Arktype, then returns the normalized IR. | ||
| * | ||
| * Normalization: | ||
| * - contract.output defaults to a path colocated with DEFAULT_CONTRACT_SOURCE_DIR | ||
| * when missing (in-memory-only providers) | ||
| * | ||
| * @param config - Raw config input from user | ||
| * @returns Normalized config IR with defaults applied | ||
| * @throws Error if config structure is invalid | ||
| */ | ||
| declare function defineConfig<TFamilyId extends string = string, TTargetId extends string = string>(config: PrismaNextConfig<TFamilyId, TTargetId>): PrismaNextConfig<TFamilyId, TTargetId>; | ||
| //#endregion | ||
| export { TypeScriptContractSourceProvider as _, defineConfig as a, ContractSourceDiagnostic as c, ContractSourceDiagnostics as d, ContractSourceFormat as f, PslContractSourceProvider as g, OpaqueContractSourceProvider as h, PrismaNextConfig as i, ContractSourceDiagnosticPosition as l, ContractSourceProviderBase as m, DEFAULT_CONTRACT_SOURCE_DIR as n, normalizeContractConfig as o, ContractSourceProvider as p, FormatterConfig as r, ContractSourceContext as s, ContractConfig as t, ContractSourceDiagnosticSpan as u }; | ||
| //# sourceMappingURL=config-types-B1QRy_5L.d.mts.map |
| {"version":3,"file":"config-types-B1QRy_5L.d.mts","names":[],"sources":["../src/contract-source-types.ts","../src/config-types.ts"],"mappings":";;;;;;UASiB;WACN;WACA;WACA;;UAGM;WACN,OAAO;WACP,KAAK;;UAGC;WACN;WACA;WACA;WACA,OAAO;;;;;;WAMP,OAAO,SAAS;;UAGV;WACN;WACA,sBAAsB;WACtB,OAAO;;UAGD;WACN;;WAEA,4BAA4B,oBAAoB;WAChD,wBAAwB;WACxB,aAAa;WACb,yBAAyB;WACzB;WACA,cAAc;;;KAIb;UAEK;WACN;WACA,OACP,SAAS,0BACN,QAAQ,OAAO,UAAU;;UAGf,kCAAkC;WACxC;;UAGM,yCAAyC;WAC/C;;;;;;;;UASM,qCAAqC;WAC3C;;KAGC,yBACR,4BACA,mCACA;;;;;;UC7Da;;;;;WAKN,QAAQ;;;;;;;WAOR;;UAGM;WACN;WACA;;;;;;;cAQE;iBAEG,wBACd,UAAU,iBACT;WAA4B;;;;;;;;;;UAmBd,iBACf,mCACA,mCACA;WAES,QAAQ,wBAAwB;WAChC,QAAQ,wBAAwB,WAAW;WAC3C,SAAS,yBAAyB,WAAW;WAC7C,sBAAsB,2BAA2B,WAAW;;;;;;;WAO5D,SAAS,wBAChB,WACA,WACA,sBAAsB,WAAW,YACjC;;;;;WAMO;;;;;;aAME,aAAa;;;;;;WAMf,WAAW;;;;WAIX;;aAEE;;WAEF,YAAY;;;;;;;;;;;;;;iBAuDP,aAAa,mCAAmC,mCAC9D,QAAQ,iBAAiB,WAAW,aACnC,iBAAiB,WAAW"} |
@@ -1,2 +0,2 @@ | ||
| import { _ as TypeScriptContractSourceProvider, a as defineConfig, c as ContractSourceDiagnostic, d as ContractSourceDiagnostics, f as ContractSourceFormat, g as PslContractSourceProvider, h as OpaqueContractSourceProvider, i as PrismaNextConfig, l as ContractSourceDiagnosticPosition, m as ContractSourceProviderBase, n as DEFAULT_CONTRACT_SOURCE_DIR, o as normalizeContractConfig, p as ContractSourceProvider, r as FormatterConfig, s as ContractSourceContext, t as ContractConfig, u as ContractSourceDiagnosticSpan } from "./config-types-DtsiIT_O.mjs"; | ||
| import { _ as TypeScriptContractSourceProvider, a as defineConfig, c as ContractSourceDiagnostic, d as ContractSourceDiagnostics, f as ContractSourceFormat, g as PslContractSourceProvider, h as OpaqueContractSourceProvider, i as PrismaNextConfig, l as ContractSourceDiagnosticPosition, m as ContractSourceProviderBase, n as DEFAULT_CONTRACT_SOURCE_DIR, o as normalizeContractConfig, p as ContractSourceProvider, r as FormatterConfig, s as ContractSourceContext, t as ContractConfig, u as ContractSourceDiagnosticSpan } from "./config-types-B1QRy_5L.mjs"; | ||
| export { type ContractConfig, type ContractSourceContext, type ContractSourceDiagnostic, type ContractSourceDiagnosticPosition, type ContractSourceDiagnosticSpan, type ContractSourceDiagnostics, type ContractSourceFormat, type ContractSourceProvider, type ContractSourceProviderBase, DEFAULT_CONTRACT_SOURCE_DIR, type FormatterConfig, type OpaqueContractSourceProvider, type PrismaNextConfig, type PslContractSourceProvider, type TypeScriptContractSourceProvider, defineConfig, normalizeContractConfig }; |
@@ -20,3 +20,3 @@ import { type } from "arktype"; | ||
| adapter: "unknown", | ||
| "extensionPacks?": "unknown[]", | ||
| "extensions?": "unknown[]", | ||
| "driver?": "unknown", | ||
@@ -26,3 +26,3 @@ "db?": "unknown", | ||
| source: type({ | ||
| "sourceFormat?": "string", | ||
| "format?": "string", | ||
| "inputs?": type("string").array(), | ||
@@ -29,0 +29,0 @@ load: "Function" |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"config-types.mjs","names":[],"sources":["../src/config-types.ts"],"sourcesContent":["import type {\n ControlAdapterDescriptor,\n ControlDriverDescriptor,\n ControlDriverInstance,\n ControlExtensionDescriptor,\n ControlFamilyDescriptor,\n ControlTargetDescriptor,\n} from '@prisma-next/framework-components/control';\nimport { type } from 'arktype';\nimport type { ContractSourceProvider } from './contract-source-types';\n\n/**\n * Type alias for CLI driver instances.\n * Uses string for both family and target IDs for maximum flexibility.\n */\nexport type CliDriver = ControlDriverInstance<string, string>;\n\n/**\n * Contract configuration specifying source and artifact locations.\n */\nexport interface ContractConfig {\n /**\n * Contract source provider. The provider is always async and must return\n * a Result containing either a Contract or structured diagnostics.\n */\n readonly source: ContractSourceProvider;\n /**\n * Path to contract.json artifact. Providers that know an input path (PSL,\n * `typescriptContractFromPath`) derive an output colocated with that input\n * so this rarely needs to be set explicitly. The `.d.ts` types file is\n * always emitted next to the JSON (e.g., `contract.json` → `contract.d.ts`).\n */\n readonly output?: string;\n}\n\nexport interface FormatterConfig {\n readonly indent?: number | 'tab';\n readonly newline?: 'LF' | 'CRLF';\n}\n\n/**\n * Default *source* directory for the contract file the user authors at `init`\n * time. Output artefacts colocate with source per the same rule path-bearing\n * providers apply.\n */\nexport const DEFAULT_CONTRACT_SOURCE_DIR = 'src/prisma';\n\nexport function normalizeContractConfig(\n contract: ContractConfig,\n): ContractConfig & { readonly output: string } {\n // In-memory-only fallback: `typescriptContract(contract)` has no source path\n // to anchor on, so normalization supplies a default output colocated with\n // the default source directory.\n const inMemoryFallbackOutput = `${DEFAULT_CONTRACT_SOURCE_DIR}/contract.json`;\n return {\n source: contract.source,\n output: contract.output ?? inMemoryFallbackOutput,\n };\n}\n\n/**\n * Configuration for Prisma Next CLI.\n * Uses Control*Descriptor types for type-safe wiring with compile-time compatibility checks.\n *\n * @template TFamilyId - The family ID (e.g., 'sql', 'document')\n * @template TTargetId - The target ID (e.g., 'postgres', 'mysql')\n * @template TConnection - The driver connection input type (defaults to `unknown` for config flexibility)\n */\nexport interface PrismaNextConfig<\n TFamilyId extends string = string,\n TTargetId extends string = string,\n TConnection = unknown,\n> {\n readonly family: ControlFamilyDescriptor<TFamilyId>;\n readonly target: ControlTargetDescriptor<TFamilyId, TTargetId>;\n readonly adapter: ControlAdapterDescriptor<TFamilyId, TTargetId>;\n readonly extensionPacks?: readonly ControlExtensionDescriptor<TFamilyId, TTargetId>[];\n /**\n * Driver descriptor for DB-connected CLI commands.\n * Required for DB-connected commands (e.g., db verify).\n * Optional for commands that don't need database access (e.g., emit).\n * The driver's connection type matches the TConnection config parameter.\n */\n readonly driver?: ControlDriverDescriptor<\n TFamilyId,\n TTargetId,\n ControlDriverInstance<TFamilyId, TTargetId>,\n TConnection\n >;\n /**\n * Database connection configuration.\n * The connection type is driver-specific (e.g., URL string for Postgres).\n */\n readonly db?: {\n /**\n * Driver-specific connection input.\n * For Postgres: a connection string (URL).\n * For other drivers: may be a structured object.\n */\n readonly connection?: TConnection;\n };\n /**\n * Contract configuration. Specifies source and artifact locations.\n * Required for emit command; optional for other commands that only read artifacts.\n */\n readonly contract?: ContractConfig;\n /**\n * Migration configuration. Controls where on-disk migration packages are stored.\n */\n readonly migrations?: {\n /** Directory for migration packages, relative to config file. Defaults to 'migrations'. */\n readonly dir?: string;\n };\n readonly formatter?: FormatterConfig;\n}\n\nconst ContractSourceInputSchema = type('string');\n\nexport const ContractSourceProviderSchema = type({\n 'sourceFormat?': 'string',\n 'inputs?': ContractSourceInputSchema.array(),\n load: 'Function',\n});\n\nexport const ContractConfigSchema = type({\n source: ContractSourceProviderSchema,\n 'output?': 'string',\n});\n\n/**\n * Arktype schema for PrismaNextConfig validation.\n * Note: This validates structure only. Descriptor objects (family, target, adapter) are validated separately.\n */\nconst MigrationsConfigSchema = type({\n 'dir?': 'string',\n});\n\nconst FormatterIndentSchema = type('number.integer >= 1').or(\"'tab'\");\n\nexport const FormatterConfigSchema = type({\n 'indent?': FormatterIndentSchema,\n 'newline?': \"'LF' | 'CRLF'\",\n});\n\nconst PrismaNextConfigSchema = type({\n family: 'unknown', // ControlFamilyDescriptor - validated separately\n target: 'unknown', // ControlTargetDescriptor - validated separately\n adapter: 'unknown', // ControlAdapterDescriptor - validated separately\n 'extensionPacks?': 'unknown[]',\n 'driver?': 'unknown', // ControlDriverDescriptor - validated separately (optional)\n 'db?': 'unknown',\n 'contract?': ContractConfigSchema,\n 'migrations?': MigrationsConfigSchema,\n 'formatter?': FormatterConfigSchema,\n});\n\n/**\n * Helper function to define a Prisma Next config.\n * Validates and normalizes the config using Arktype, then returns the normalized IR.\n *\n * Normalization:\n * - contract.output defaults to a path colocated with DEFAULT_CONTRACT_SOURCE_DIR\n * when missing (in-memory-only providers)\n *\n * @param config - Raw config input from user\n * @returns Normalized config IR with defaults applied\n * @throws Error if config structure is invalid\n */\nexport function defineConfig<TFamilyId extends string = string, TTargetId extends string = string>(\n config: PrismaNextConfig<TFamilyId, TTargetId>,\n): PrismaNextConfig<TFamilyId, TTargetId> {\n // Validate structure using Arktype\n const validated = PrismaNextConfigSchema(config);\n if (validated instanceof type.errors) {\n const messages = validated.map((p: { message: string }) => p.message).join('; ');\n throw new Error(`Config validation failed: ${messages}`);\n }\n\n // Normalize contract config if present\n if (config.contract) {\n // Return normalized config\n return {\n ...config,\n contract: normalizeContractConfig(config.contract),\n };\n }\n\n // Return config as-is if no contract (preserve literal types)\n return config;\n}\n"],"mappings":";;;;;;;AA6CA,MAAa,8BAA8B;AAE3C,SAAgB,wBACd,UAC8C;CAI9C,MAAM,yBAAyB,GAAG,4BAA4B;CAC9D,OAAO;EACL,QAAQ,SAAS;EACjB,QAAQ,SAAS,UAAU;CAC7B;AACF;AAsFA,MAAM,yBAAyB,KAAK;CAClC,QAAQ;CACR,QAAQ;CACR,SAAS;CACT,mBAAmB;CACnB,WAAW;CACX,OAAO;CACP,aA3BkC,KAAK;EACvC,QAP0C,KAAK;GAC/C,iBAAiB;GACjB,WAJgC,KAAK,QAI1B,CAAA,CAA0B,MAAM;GAC3C,MAAM;EACR,CAGU;EACR,WAAW;CACb,CAwBe;CACb,eAnB6B,KAAK,EAClC,QAAQ,SACV,CAiBiB;CACf,cAdmC,KAAK;EACxC,WAH4B,KAAK,qBAAqB,CAAC,CAAC,GAAG,OAGhD;EACX,YAAY;CACd,CAWgB;AAChB,CAAC;;;;;;;;;;;;;AAcD,SAAgB,aACd,QACwC;CAExC,MAAM,YAAY,uBAAuB,MAAM;CAC/C,IAAI,qBAAqB,KAAK,QAAQ;EACpC,MAAM,WAAW,UAAU,KAAK,MAA2B,EAAE,OAAO,CAAC,CAAC,KAAK,IAAI;EAC/E,MAAM,IAAI,MAAM,6BAA6B,UAAU;CACzD;CAGA,IAAI,OAAO,UAET,OAAO;EACL,GAAG;EACH,UAAU,wBAAwB,OAAO,QAAQ;CACnD;CAIF,OAAO;AACT"} | ||
| {"version":3,"file":"config-types.mjs","names":[],"sources":["../src/config-types.ts"],"sourcesContent":["import type {\n ControlAdapterDescriptor,\n ControlDriverDescriptor,\n ControlDriverInstance,\n ControlExtensionDescriptor,\n ControlFamilyDescriptor,\n ControlTargetDescriptor,\n} from '@prisma-next/framework-components/control';\nimport { type } from 'arktype';\nimport type { ContractSourceProvider } from './contract-source-types';\n\n/**\n * Type alias for CLI driver instances.\n * Uses string for both family and target IDs for maximum flexibility.\n */\nexport type CliDriver = ControlDriverInstance<string, string>;\n\n/**\n * Contract configuration specifying source and artifact locations.\n */\nexport interface ContractConfig {\n /**\n * Contract source provider. The provider is always async and must return\n * a Result containing either a Contract or structured diagnostics.\n */\n readonly source: ContractSourceProvider;\n /**\n * Path to contract.json artifact. Providers that know an input path (PSL,\n * `typescriptContractFromPath`) derive an output colocated with that input\n * so this rarely needs to be set explicitly. The `.d.ts` types file is\n * always emitted next to the JSON (e.g., `contract.json` → `contract.d.ts`).\n */\n readonly output?: string;\n}\n\nexport interface FormatterConfig {\n readonly indent?: number | 'tab';\n readonly newline?: 'LF' | 'CRLF';\n}\n\n/**\n * Default *source* directory for the contract file the user authors at `init`\n * time. Output artefacts colocate with source per the same rule path-bearing\n * providers apply.\n */\nexport const DEFAULT_CONTRACT_SOURCE_DIR = 'src/prisma';\n\nexport function normalizeContractConfig(\n contract: ContractConfig,\n): ContractConfig & { readonly output: string } {\n // In-memory-only fallback: `typescriptContract(contract)` has no source path\n // to anchor on, so normalization supplies a default output colocated with\n // the default source directory.\n const inMemoryFallbackOutput = `${DEFAULT_CONTRACT_SOURCE_DIR}/contract.json`;\n return {\n source: contract.source,\n output: contract.output ?? inMemoryFallbackOutput,\n };\n}\n\n/**\n * Configuration for Prisma Next CLI.\n * Uses Control*Descriptor types for type-safe wiring with compile-time compatibility checks.\n *\n * @template TFamilyId - The family ID (e.g., 'sql', 'document')\n * @template TTargetId - The target ID (e.g., 'postgres', 'mysql')\n * @template TConnection - The driver connection input type (defaults to `unknown` for config flexibility)\n */\nexport interface PrismaNextConfig<\n TFamilyId extends string = string,\n TTargetId extends string = string,\n TConnection = unknown,\n> {\n readonly family: ControlFamilyDescriptor<TFamilyId>;\n readonly target: ControlTargetDescriptor<TFamilyId, TTargetId>;\n readonly adapter: ControlAdapterDescriptor<TFamilyId, TTargetId>;\n readonly extensions?: readonly ControlExtensionDescriptor<TFamilyId, TTargetId>[];\n /**\n * Driver descriptor for DB-connected CLI commands.\n * Required for DB-connected commands (e.g., db verify).\n * Optional for commands that don't need database access (e.g., emit).\n * The driver's connection type matches the TConnection config parameter.\n */\n readonly driver?: ControlDriverDescriptor<\n TFamilyId,\n TTargetId,\n ControlDriverInstance<TFamilyId, TTargetId>,\n TConnection\n >;\n /**\n * Database connection configuration.\n * The connection type is driver-specific (e.g., URL string for Postgres).\n */\n readonly db?: {\n /**\n * Driver-specific connection input.\n * For Postgres: a connection string (URL).\n * For other drivers: may be a structured object.\n */\n readonly connection?: TConnection;\n };\n /**\n * Contract configuration. Specifies source and artifact locations.\n * Required for emit command; optional for other commands that only read artifacts.\n */\n readonly contract?: ContractConfig;\n /**\n * Migration configuration. Controls where on-disk migration packages are stored.\n */\n readonly migrations?: {\n /** Directory for migration packages, relative to config file. Defaults to 'migrations'. */\n readonly dir?: string;\n };\n readonly formatter?: FormatterConfig;\n}\n\nconst ContractSourceInputSchema = type('string');\n\nexport const ContractSourceProviderSchema = type({\n 'format?': 'string',\n 'inputs?': ContractSourceInputSchema.array(),\n load: 'Function',\n});\n\nexport const ContractConfigSchema = type({\n source: ContractSourceProviderSchema,\n 'output?': 'string',\n});\n\n/**\n * Arktype schema for PrismaNextConfig validation.\n * Note: This validates structure only. Descriptor objects (family, target, adapter) are validated separately.\n */\nconst MigrationsConfigSchema = type({\n 'dir?': 'string',\n});\n\nconst FormatterIndentSchema = type('number.integer >= 1').or(\"'tab'\");\n\nexport const FormatterConfigSchema = type({\n 'indent?': FormatterIndentSchema,\n 'newline?': \"'LF' | 'CRLF'\",\n});\n\nconst PrismaNextConfigSchema = type({\n family: 'unknown', // ControlFamilyDescriptor - validated separately\n target: 'unknown', // ControlTargetDescriptor - validated separately\n adapter: 'unknown', // ControlAdapterDescriptor - validated separately\n 'extensions?': 'unknown[]',\n 'driver?': 'unknown', // ControlDriverDescriptor - validated separately (optional)\n 'db?': 'unknown',\n 'contract?': ContractConfigSchema,\n 'migrations?': MigrationsConfigSchema,\n 'formatter?': FormatterConfigSchema,\n});\n\n/**\n * Helper function to define a Prisma Next config.\n * Validates and normalizes the config using Arktype, then returns the normalized IR.\n *\n * Normalization:\n * - contract.output defaults to a path colocated with DEFAULT_CONTRACT_SOURCE_DIR\n * when missing (in-memory-only providers)\n *\n * @param config - Raw config input from user\n * @returns Normalized config IR with defaults applied\n * @throws Error if config structure is invalid\n */\nexport function defineConfig<TFamilyId extends string = string, TTargetId extends string = string>(\n config: PrismaNextConfig<TFamilyId, TTargetId>,\n): PrismaNextConfig<TFamilyId, TTargetId> {\n // Validate structure using Arktype\n const validated = PrismaNextConfigSchema(config);\n if (validated instanceof type.errors) {\n const messages = validated.map((p: { message: string }) => p.message).join('; ');\n throw new Error(`Config validation failed: ${messages}`);\n }\n\n // Normalize contract config if present\n if (config.contract) {\n // Return normalized config\n return {\n ...config,\n contract: normalizeContractConfig(config.contract),\n };\n }\n\n // Return config as-is if no contract (preserve literal types)\n return config;\n}\n"],"mappings":";;;;;;;AA6CA,MAAa,8BAA8B;AAE3C,SAAgB,wBACd,UAC8C;CAI9C,MAAM,yBAAyB,GAAG,4BAA4B;CAC9D,OAAO;EACL,QAAQ,SAAS;EACjB,QAAQ,SAAS,UAAU;CAC7B;AACF;AAsFA,MAAM,yBAAyB,KAAK;CAClC,QAAQ;CACR,QAAQ;CACR,SAAS;CACT,eAAe;CACf,WAAW;CACX,OAAO;CACP,aA3BkC,KAAK;EACvC,QAP0C,KAAK;GAC/C,WAAW;GACX,WAJgC,KAAK,QAI1B,CAAA,CAA0B,MAAM;GAC3C,MAAM;EACR,CAGU;EACR,WAAW;CACb,CAwBe;CACb,eAnB6B,KAAK,EAClC,QAAQ,SACV,CAiBiB;CACf,cAdmC,KAAK;EACxC,WAH4B,KAAK,qBAAqB,CAAC,CAAC,GAAG,OAGhD;EACX,YAAY;CACd,CAWgB;AAChB,CAAC;;;;;;;;;;;;;AAcD,SAAgB,aACd,QACwC;CAExC,MAAM,YAAY,uBAAuB,MAAM;CAC/C,IAAI,qBAAqB,KAAK,QAAQ;EACpC,MAAM,WAAW,UAAU,KAAK,MAA2B,EAAE,OAAO,CAAC,CAAC,KAAK,IAAI;EAC/E,MAAM,IAAI,MAAM,6BAA6B,UAAU;CACzD;CAGA,IAAI,OAAO,UAET,OAAO;EACL,GAAG;EACH,UAAU,wBAAwB,OAAO,QAAQ;CACnD;CAIF,OAAO;AACT"} |
@@ -1,2 +0,2 @@ | ||
| import { i as PrismaNextConfig } from "./config-types-DtsiIT_O.mjs"; | ||
| import { i as PrismaNextConfig } from "./config-types-B1QRy_5L.mjs"; | ||
| //#region src/config-validation.d.ts | ||
@@ -3,0 +3,0 @@ /** |
@@ -70,16 +70,16 @@ //#region src/errors.ts | ||
| if (typeof adapter["create"] !== "function") throwValidation("adapter.create", "Config.adapter must have create: function"); | ||
| if (configObj["extensions"] !== void 0) throwValidation("extensions", "Config.extensions is not supported; use Config.extensionPacks"); | ||
| if (configObj["extensionPacks"] !== void 0) { | ||
| if (!Array.isArray(configObj["extensionPacks"])) throwValidation("extensionPacks", "Config.extensionPacks must be an array"); | ||
| for (const ext of configObj["extensionPacks"]) { | ||
| if (!ext || typeof ext !== "object") throwValidation("extensionPacks[]", "Config.extensionPacks must contain ControlExtensionDescriptor objects"); | ||
| if (configObj["extensionPacks"] !== void 0) throwValidation("extensionPacks", "Config.extensionPacks is no longer supported; rename it to Config.extensions"); | ||
| if (configObj["extensions"] !== void 0) { | ||
| if (!Array.isArray(configObj["extensions"])) throwValidation("extensions", "Config.extensions must be an array"); | ||
| for (const ext of configObj["extensions"]) { | ||
| if (!ext || typeof ext !== "object") throwValidation("extensions[]", "Config.extensions must contain ControlExtensionDescriptor objects"); | ||
| const extObj = ext; | ||
| if (extObj["kind"] !== "extension") throwValidation("extensionPacks[].kind", "Config.extensionPacks items must have kind: \"extension\""); | ||
| if (typeof extObj["id"] !== "string") throwValidation("extensionPacks[].id", "Config.extensionPacks items must have id: string"); | ||
| if (typeof extObj["familyId"] !== "string") throwValidation("extensionPacks[].familyId", "Config.extensionPacks items must have familyId: string"); | ||
| if (typeof extObj["version"] !== "string") throwValidation("extensionPacks[].version", "Config.extensionPacks items must have version: string"); | ||
| if (extObj["familyId"] !== familyId) throwValidation("extensionPacks[].familyId", `Config.extensionPacks[].familyId must match Config.family.familyId (expected: ${familyId}, got: ${extObj["familyId"]})`); | ||
| if (typeof extObj["targetId"] !== "string") throwValidation("extensionPacks[].targetId", "Config.extensionPacks items must have targetId: string"); | ||
| if (extObj["targetId"] !== expectedTargetId) throwValidation("extensionPacks[].targetId", `Config.extensionPacks[].targetId must match Config.target.targetId (expected: ${expectedTargetId}, got: ${extObj["targetId"]})`); | ||
| if (typeof extObj["create"] !== "function") throwValidation("extensionPacks[].create", "Config.extensionPacks items must have create: function"); | ||
| if (extObj["kind"] !== "extension") throwValidation("extensions[].kind", "Config.extensions items must have kind: \"extension\""); | ||
| if (typeof extObj["id"] !== "string") throwValidation("extensions[].id", "Config.extensions items must have id: string"); | ||
| if (typeof extObj["familyId"] !== "string") throwValidation("extensions[].familyId", "Config.extensions items must have familyId: string"); | ||
| if (typeof extObj["version"] !== "string") throwValidation("extensions[].version", "Config.extensions items must have version: string"); | ||
| if (extObj["familyId"] !== familyId) throwValidation("extensions[].familyId", `Config.extensions[].familyId must match Config.family.familyId (expected: ${familyId}, got: ${extObj["familyId"]})`); | ||
| if (typeof extObj["targetId"] !== "string") throwValidation("extensions[].targetId", "Config.extensions items must have targetId: string"); | ||
| if (extObj["targetId"] !== expectedTargetId) throwValidation("extensions[].targetId", `Config.extensions[].targetId must match Config.target.targetId (expected: ${expectedTargetId}, got: ${extObj["targetId"]})`); | ||
| if (typeof extObj["create"] !== "function") throwValidation("extensions[].create", "Config.extensions items must have create: function"); | ||
| } | ||
@@ -86,0 +86,0 @@ } |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"config-validation.mjs","names":[],"sources":["../src/errors.ts","../src/config-validation.ts"],"sourcesContent":["export class ConfigValidationError extends Error {\n readonly field: string;\n readonly why: string;\n\n constructor(field: string, why?: string) {\n super(why ?? `Config must have a \"${field}\" field`);\n this.name = 'ConfigValidationError';\n this.field = field;\n this.why = why ?? `Config must have a \"${field}\" field`;\n }\n}\n","import type { PrismaNextConfig } from './config-types';\nimport { ConfigValidationError } from './errors';\n\nfunction throwValidation(field: string, why?: string): never {\n throw new ConfigValidationError(field, why);\n}\n\nfunction validateContractConfig(contract: Record<string, unknown>): void {\n if (!Object.hasOwn(contract, 'source')) {\n throwValidation(\n 'contract.source',\n 'Config.contract.source is required when contract is provided',\n );\n }\n\n const source = contract['source'];\n if (!source || typeof source !== 'object') {\n throwValidation('contract.source', 'Config.contract.source must be a provider object');\n }\n\n const sourceConfig = source as Record<string, unknown>;\n const inputs = Object.hasOwn(sourceConfig, 'inputs') ? sourceConfig['inputs'] : undefined;\n\n if (inputs !== undefined) {\n if (!Array.isArray(inputs)) {\n throwValidation(\n 'contract.source.inputs',\n 'Config.contract.source.inputs must be an array of strings when provided',\n );\n }\n\n for (const input of inputs) {\n if (typeof input !== 'string') {\n throwValidation(\n 'contract.source.inputs[]',\n 'Config.contract.source.inputs must contain only strings',\n );\n }\n }\n }\n\n if (!Object.hasOwn(sourceConfig, 'load') || typeof sourceConfig['load'] !== 'function') {\n throwValidation('contract.source.load', 'Config.contract.source.load must be a function');\n }\n\n const output = Object.hasOwn(contract, 'output') ? contract['output'] : undefined;\n if (output !== undefined && typeof output !== 'string') {\n throwValidation('contract.output', 'Config.contract.output must be a string when provided');\n }\n}\n\n/**\n * Validates that the config has the required structure.\n * This is pure validation logic with no file I/O or CLI awareness.\n *\n * @param config - Config object to validate\n * @throws ConfigValidationError if config structure is invalid\n */\nexport function validateConfig(config: unknown): asserts config is PrismaNextConfig {\n if (!config || typeof config !== 'object') {\n throwValidation('object', 'Config must be an object');\n }\n\n const configObj = config as Record<string, unknown>;\n\n if (!configObj['family']) {\n throwValidation('family');\n }\n\n if (!configObj['target']) {\n throwValidation('target');\n }\n\n if (!configObj['adapter']) {\n throwValidation('adapter');\n }\n\n // Validate family descriptor\n const family = configObj['family'] as Record<string, unknown>;\n if (family['kind'] !== 'family') {\n throwValidation('family.kind', 'Config.family must have kind: \"family\"');\n }\n if (typeof family['id'] !== 'string') {\n throwValidation('family.id', 'Config.family must have id: string');\n }\n if (typeof family['familyId'] !== 'string') {\n throwValidation('family.familyId', 'Config.family must have familyId: string');\n }\n if (typeof family['version'] !== 'string') {\n throwValidation('family.version', 'Config.family must have version: string');\n }\n if (!family['emission'] || typeof family['emission'] !== 'object') {\n throwValidation('family.emission', 'Config.family must have emission: EmissionSpi');\n }\n if (typeof family['create'] !== 'function') {\n throwValidation('family.create', 'Config.family must have create: function');\n }\n\n const familyId = family['familyId'] as string;\n\n // Validate target descriptor\n const target = configObj['target'] as Record<string, unknown>;\n if (target['kind'] !== 'target') {\n throwValidation('target.kind', 'Config.target must have kind: \"target\"');\n }\n if (typeof target['id'] !== 'string') {\n throwValidation('target.id', 'Config.target must have id: string');\n }\n if (typeof target['familyId'] !== 'string') {\n throwValidation('target.familyId', 'Config.target must have familyId: string');\n }\n if (typeof target['version'] !== 'string') {\n throwValidation('target.version', 'Config.target must have version: string');\n }\n if (target['familyId'] !== familyId) {\n throwValidation(\n 'target.familyId',\n `Config.target.familyId must match Config.family.familyId (expected: ${familyId}, got: ${target['familyId']})`,\n );\n }\n if (typeof target['targetId'] !== 'string') {\n throwValidation('target.targetId', 'Config.target must have targetId: string');\n }\n if (typeof target['create'] !== 'function') {\n throwValidation('target.create', 'Config.target must have create: function');\n }\n const expectedTargetId = target['targetId'] as string;\n\n // Validate adapter descriptor\n const adapter = configObj['adapter'] as Record<string, unknown>;\n if (adapter['kind'] !== 'adapter') {\n throwValidation('adapter.kind', 'Config.adapter must have kind: \"adapter\"');\n }\n if (typeof adapter['id'] !== 'string') {\n throwValidation('adapter.id', 'Config.adapter must have id: string');\n }\n if (typeof adapter['familyId'] !== 'string') {\n throwValidation('adapter.familyId', 'Config.adapter must have familyId: string');\n }\n if (typeof adapter['version'] !== 'string') {\n throwValidation('adapter.version', 'Config.adapter must have version: string');\n }\n if (adapter['familyId'] !== familyId) {\n throwValidation(\n 'adapter.familyId',\n `Config.adapter.familyId must match Config.family.familyId (expected: ${familyId}, got: ${adapter['familyId']})`,\n );\n }\n if (typeof adapter['targetId'] !== 'string') {\n throwValidation('adapter.targetId', 'Config.adapter must have targetId: string');\n }\n if (adapter['targetId'] !== expectedTargetId) {\n throwValidation(\n 'adapter.targetId',\n `Config.adapter.targetId must match Config.target.targetId (expected: ${expectedTargetId}, got: ${adapter['targetId']})`,\n );\n }\n if (typeof adapter['create'] !== 'function') {\n throwValidation('adapter.create', 'Config.adapter must have create: function');\n }\n\n if (configObj['extensions'] !== undefined) {\n throwValidation('extensions', 'Config.extensions is not supported; use Config.extensionPacks');\n }\n\n // Validate extensionPacks array if present\n if (configObj['extensionPacks'] !== undefined) {\n if (!Array.isArray(configObj['extensionPacks'])) {\n throwValidation('extensionPacks', 'Config.extensionPacks must be an array');\n }\n for (const ext of configObj['extensionPacks']) {\n if (!ext || typeof ext !== 'object') {\n throwValidation(\n 'extensionPacks[]',\n 'Config.extensionPacks must contain ControlExtensionDescriptor objects',\n );\n }\n const extObj = ext as Record<string, unknown>;\n if (extObj['kind'] !== 'extension') {\n throwValidation(\n 'extensionPacks[].kind',\n 'Config.extensionPacks items must have kind: \"extension\"',\n );\n }\n if (typeof extObj['id'] !== 'string') {\n throwValidation('extensionPacks[].id', 'Config.extensionPacks items must have id: string');\n }\n if (typeof extObj['familyId'] !== 'string') {\n throwValidation(\n 'extensionPacks[].familyId',\n 'Config.extensionPacks items must have familyId: string',\n );\n }\n if (typeof extObj['version'] !== 'string') {\n throwValidation(\n 'extensionPacks[].version',\n 'Config.extensionPacks items must have version: string',\n );\n }\n if (extObj['familyId'] !== familyId) {\n throwValidation(\n 'extensionPacks[].familyId',\n `Config.extensionPacks[].familyId must match Config.family.familyId (expected: ${familyId}, got: ${extObj['familyId']})`,\n );\n }\n if (typeof extObj['targetId'] !== 'string') {\n throwValidation(\n 'extensionPacks[].targetId',\n 'Config.extensionPacks items must have targetId: string',\n );\n }\n if (extObj['targetId'] !== expectedTargetId) {\n throwValidation(\n 'extensionPacks[].targetId',\n `Config.extensionPacks[].targetId must match Config.target.targetId (expected: ${expectedTargetId}, got: ${extObj['targetId']})`,\n );\n }\n if (typeof extObj['create'] !== 'function') {\n throwValidation(\n 'extensionPacks[].create',\n 'Config.extensionPacks items must have create: function',\n );\n }\n }\n }\n\n // Validate driver descriptor if present\n if (configObj['driver'] !== undefined) {\n const driver = configObj['driver'] as Record<string, unknown>;\n if (driver['kind'] !== 'driver') {\n throwValidation('driver.kind', 'Config.driver must have kind: \"driver\"');\n }\n if (typeof driver['id'] !== 'string') {\n throwValidation('driver.id', 'Config.driver must have id: string');\n }\n if (typeof driver['version'] !== 'string') {\n throwValidation('driver.version', 'Config.driver must have version: string');\n }\n if (typeof driver['familyId'] !== 'string') {\n throwValidation('driver.familyId', 'Config.driver must have familyId: string');\n }\n if (driver['familyId'] !== familyId) {\n throwValidation(\n 'driver.familyId',\n `Config.driver.familyId must match Config.family.familyId (expected: ${familyId}, got: ${driver['familyId']})`,\n );\n }\n if (typeof driver['targetId'] !== 'string') {\n throwValidation('driver.targetId', 'Config.driver must have targetId: string');\n }\n if (driver['targetId'] !== expectedTargetId) {\n throwValidation(\n 'driver.targetId',\n `Config.driver.targetId must match Config.target.targetId (expected: ${expectedTargetId}, got: ${driver['targetId']})`,\n );\n }\n if (typeof driver['create'] !== 'function') {\n throwValidation('driver.create', 'Config.driver must have create: function');\n }\n }\n\n // Validate contract config if present (structure validation - defineConfig() handles normalization)\n if (configObj['contract'] !== undefined) {\n const contract = configObj['contract'] as Record<string, unknown>;\n if (!contract || typeof contract !== 'object') {\n throwValidation('contract', 'Config.contract must be an object');\n }\n validateContractConfig(contract);\n }\n}\n"],"mappings":";AAAA,IAAa,wBAAb,cAA2C,MAAM;CAC/C;CACA;CAEA,YAAY,OAAe,KAAc;EACvC,MAAM,OAAO,uBAAuB,MAAM,QAAQ;EAClD,KAAK,OAAO;EACZ,KAAK,QAAQ;EACb,KAAK,MAAM,OAAO,uBAAuB,MAAM;CACjD;AACF;;;ACPA,SAAS,gBAAgB,OAAe,KAAqB;CAC3D,MAAM,IAAI,sBAAsB,OAAO,GAAG;AAC5C;AAEA,SAAS,uBAAuB,UAAyC;CACvE,IAAI,CAAC,OAAO,OAAO,UAAU,QAAQ,GACnC,gBACE,mBACA,8DACF;CAGF,MAAM,SAAS,SAAS;CACxB,IAAI,CAAC,UAAU,OAAO,WAAW,UAC/B,gBAAgB,mBAAmB,kDAAkD;CAGvF,MAAM,eAAe;CACrB,MAAM,SAAS,OAAO,OAAO,cAAc,QAAQ,IAAI,aAAa,YAAY,KAAA;CAEhF,IAAI,WAAW,KAAA,GAAW;EACxB,IAAI,CAAC,MAAM,QAAQ,MAAM,GACvB,gBACE,0BACA,yEACF;EAGF,KAAK,MAAM,SAAS,QAClB,IAAI,OAAO,UAAU,UACnB,gBACE,4BACA,yDACF;CAGN;CAEA,IAAI,CAAC,OAAO,OAAO,cAAc,MAAM,KAAK,OAAO,aAAa,YAAY,YAC1E,gBAAgB,wBAAwB,gDAAgD;CAG1F,MAAM,SAAS,OAAO,OAAO,UAAU,QAAQ,IAAI,SAAS,YAAY,KAAA;CACxE,IAAI,WAAW,KAAA,KAAa,OAAO,WAAW,UAC5C,gBAAgB,mBAAmB,uDAAuD;AAE9F;;;;;;;;AASA,SAAgB,eAAe,QAAqD;CAClF,IAAI,CAAC,UAAU,OAAO,WAAW,UAC/B,gBAAgB,UAAU,0BAA0B;CAGtD,MAAM,YAAY;CAElB,IAAI,CAAC,UAAU,WACb,gBAAgB,QAAQ;CAG1B,IAAI,CAAC,UAAU,WACb,gBAAgB,QAAQ;CAG1B,IAAI,CAAC,UAAU,YACb,gBAAgB,SAAS;CAI3B,MAAM,SAAS,UAAU;CACzB,IAAI,OAAO,YAAY,UACrB,gBAAgB,eAAe,0CAAwC;CAEzE,IAAI,OAAO,OAAO,UAAU,UAC1B,gBAAgB,aAAa,oCAAoC;CAEnE,IAAI,OAAO,OAAO,gBAAgB,UAChC,gBAAgB,mBAAmB,0CAA0C;CAE/E,IAAI,OAAO,OAAO,eAAe,UAC/B,gBAAgB,kBAAkB,yCAAyC;CAE7E,IAAI,CAAC,OAAO,eAAe,OAAO,OAAO,gBAAgB,UACvD,gBAAgB,mBAAmB,+CAA+C;CAEpF,IAAI,OAAO,OAAO,cAAc,YAC9B,gBAAgB,iBAAiB,0CAA0C;CAG7E,MAAM,WAAW,OAAO;CAGxB,MAAM,SAAS,UAAU;CACzB,IAAI,OAAO,YAAY,UACrB,gBAAgB,eAAe,0CAAwC;CAEzE,IAAI,OAAO,OAAO,UAAU,UAC1B,gBAAgB,aAAa,oCAAoC;CAEnE,IAAI,OAAO,OAAO,gBAAgB,UAChC,gBAAgB,mBAAmB,0CAA0C;CAE/E,IAAI,OAAO,OAAO,eAAe,UAC/B,gBAAgB,kBAAkB,yCAAyC;CAE7E,IAAI,OAAO,gBAAgB,UACzB,gBACE,mBACA,uEAAuE,SAAS,SAAS,OAAO,YAAY,EAC9G;CAEF,IAAI,OAAO,OAAO,gBAAgB,UAChC,gBAAgB,mBAAmB,0CAA0C;CAE/E,IAAI,OAAO,OAAO,cAAc,YAC9B,gBAAgB,iBAAiB,0CAA0C;CAE7E,MAAM,mBAAmB,OAAO;CAGhC,MAAM,UAAU,UAAU;CAC1B,IAAI,QAAQ,YAAY,WACtB,gBAAgB,gBAAgB,4CAA0C;CAE5E,IAAI,OAAO,QAAQ,UAAU,UAC3B,gBAAgB,cAAc,qCAAqC;CAErE,IAAI,OAAO,QAAQ,gBAAgB,UACjC,gBAAgB,oBAAoB,2CAA2C;CAEjF,IAAI,OAAO,QAAQ,eAAe,UAChC,gBAAgB,mBAAmB,0CAA0C;CAE/E,IAAI,QAAQ,gBAAgB,UAC1B,gBACE,oBACA,wEAAwE,SAAS,SAAS,QAAQ,YAAY,EAChH;CAEF,IAAI,OAAO,QAAQ,gBAAgB,UACjC,gBAAgB,oBAAoB,2CAA2C;CAEjF,IAAI,QAAQ,gBAAgB,kBAC1B,gBACE,oBACA,wEAAwE,iBAAiB,SAAS,QAAQ,YAAY,EACxH;CAEF,IAAI,OAAO,QAAQ,cAAc,YAC/B,gBAAgB,kBAAkB,2CAA2C;CAG/E,IAAI,UAAU,kBAAkB,KAAA,GAC9B,gBAAgB,cAAc,+DAA+D;CAI/F,IAAI,UAAU,sBAAsB,KAAA,GAAW;EAC7C,IAAI,CAAC,MAAM,QAAQ,UAAU,iBAAiB,GAC5C,gBAAgB,kBAAkB,wCAAwC;EAE5E,KAAK,MAAM,OAAO,UAAU,mBAAmB;GAC7C,IAAI,CAAC,OAAO,OAAO,QAAQ,UACzB,gBACE,oBACA,uEACF;GAEF,MAAM,SAAS;GACf,IAAI,OAAO,YAAY,aACrB,gBACE,yBACA,2DACF;GAEF,IAAI,OAAO,OAAO,UAAU,UAC1B,gBAAgB,uBAAuB,kDAAkD;GAE3F,IAAI,OAAO,OAAO,gBAAgB,UAChC,gBACE,6BACA,wDACF;GAEF,IAAI,OAAO,OAAO,eAAe,UAC/B,gBACE,4BACA,uDACF;GAEF,IAAI,OAAO,gBAAgB,UACzB,gBACE,6BACA,iFAAiF,SAAS,SAAS,OAAO,YAAY,EACxH;GAEF,IAAI,OAAO,OAAO,gBAAgB,UAChC,gBACE,6BACA,wDACF;GAEF,IAAI,OAAO,gBAAgB,kBACzB,gBACE,6BACA,iFAAiF,iBAAiB,SAAS,OAAO,YAAY,EAChI;GAEF,IAAI,OAAO,OAAO,cAAc,YAC9B,gBACE,2BACA,wDACF;EAEJ;CACF;CAGA,IAAI,UAAU,cAAc,KAAA,GAAW;EACrC,MAAM,SAAS,UAAU;EACzB,IAAI,OAAO,YAAY,UACrB,gBAAgB,eAAe,0CAAwC;EAEzE,IAAI,OAAO,OAAO,UAAU,UAC1B,gBAAgB,aAAa,oCAAoC;EAEnE,IAAI,OAAO,OAAO,eAAe,UAC/B,gBAAgB,kBAAkB,yCAAyC;EAE7E,IAAI,OAAO,OAAO,gBAAgB,UAChC,gBAAgB,mBAAmB,0CAA0C;EAE/E,IAAI,OAAO,gBAAgB,UACzB,gBACE,mBACA,uEAAuE,SAAS,SAAS,OAAO,YAAY,EAC9G;EAEF,IAAI,OAAO,OAAO,gBAAgB,UAChC,gBAAgB,mBAAmB,0CAA0C;EAE/E,IAAI,OAAO,gBAAgB,kBACzB,gBACE,mBACA,uEAAuE,iBAAiB,SAAS,OAAO,YAAY,EACtH;EAEF,IAAI,OAAO,OAAO,cAAc,YAC9B,gBAAgB,iBAAiB,0CAA0C;CAE/E;CAGA,IAAI,UAAU,gBAAgB,KAAA,GAAW;EACvC,MAAM,WAAW,UAAU;EAC3B,IAAI,CAAC,YAAY,OAAO,aAAa,UACnC,gBAAgB,YAAY,mCAAmC;EAEjE,uBAAuB,QAAQ;CACjC;AACF"} | ||
| {"version":3,"file":"config-validation.mjs","names":[],"sources":["../src/errors.ts","../src/config-validation.ts"],"sourcesContent":["export class ConfigValidationError extends Error {\n readonly field: string;\n readonly why: string;\n\n constructor(field: string, why?: string) {\n super(why ?? `Config must have a \"${field}\" field`);\n this.name = 'ConfigValidationError';\n this.field = field;\n this.why = why ?? `Config must have a \"${field}\" field`;\n }\n}\n","import type { PrismaNextConfig } from './config-types';\nimport { ConfigValidationError } from './errors';\n\nfunction throwValidation(field: string, why?: string): never {\n throw new ConfigValidationError(field, why);\n}\n\nfunction validateContractConfig(contract: Record<string, unknown>): void {\n if (!Object.hasOwn(contract, 'source')) {\n throwValidation(\n 'contract.source',\n 'Config.contract.source is required when contract is provided',\n );\n }\n\n const source = contract['source'];\n if (!source || typeof source !== 'object') {\n throwValidation('contract.source', 'Config.contract.source must be a provider object');\n }\n\n const sourceConfig = source as Record<string, unknown>;\n const inputs = Object.hasOwn(sourceConfig, 'inputs') ? sourceConfig['inputs'] : undefined;\n\n if (inputs !== undefined) {\n if (!Array.isArray(inputs)) {\n throwValidation(\n 'contract.source.inputs',\n 'Config.contract.source.inputs must be an array of strings when provided',\n );\n }\n\n for (const input of inputs) {\n if (typeof input !== 'string') {\n throwValidation(\n 'contract.source.inputs[]',\n 'Config.contract.source.inputs must contain only strings',\n );\n }\n }\n }\n\n if (!Object.hasOwn(sourceConfig, 'load') || typeof sourceConfig['load'] !== 'function') {\n throwValidation('contract.source.load', 'Config.contract.source.load must be a function');\n }\n\n const output = Object.hasOwn(contract, 'output') ? contract['output'] : undefined;\n if (output !== undefined && typeof output !== 'string') {\n throwValidation('contract.output', 'Config.contract.output must be a string when provided');\n }\n}\n\n/**\n * Validates that the config has the required structure.\n * This is pure validation logic with no file I/O or CLI awareness.\n *\n * @param config - Config object to validate\n * @throws ConfigValidationError if config structure is invalid\n */\nexport function validateConfig(config: unknown): asserts config is PrismaNextConfig {\n if (!config || typeof config !== 'object') {\n throwValidation('object', 'Config must be an object');\n }\n\n const configObj = config as Record<string, unknown>;\n\n if (!configObj['family']) {\n throwValidation('family');\n }\n\n if (!configObj['target']) {\n throwValidation('target');\n }\n\n if (!configObj['adapter']) {\n throwValidation('adapter');\n }\n\n // Validate family descriptor\n const family = configObj['family'] as Record<string, unknown>;\n if (family['kind'] !== 'family') {\n throwValidation('family.kind', 'Config.family must have kind: \"family\"');\n }\n if (typeof family['id'] !== 'string') {\n throwValidation('family.id', 'Config.family must have id: string');\n }\n if (typeof family['familyId'] !== 'string') {\n throwValidation('family.familyId', 'Config.family must have familyId: string');\n }\n if (typeof family['version'] !== 'string') {\n throwValidation('family.version', 'Config.family must have version: string');\n }\n if (!family['emission'] || typeof family['emission'] !== 'object') {\n throwValidation('family.emission', 'Config.family must have emission: EmissionSpi');\n }\n if (typeof family['create'] !== 'function') {\n throwValidation('family.create', 'Config.family must have create: function');\n }\n\n const familyId = family['familyId'] as string;\n\n // Validate target descriptor\n const target = configObj['target'] as Record<string, unknown>;\n if (target['kind'] !== 'target') {\n throwValidation('target.kind', 'Config.target must have kind: \"target\"');\n }\n if (typeof target['id'] !== 'string') {\n throwValidation('target.id', 'Config.target must have id: string');\n }\n if (typeof target['familyId'] !== 'string') {\n throwValidation('target.familyId', 'Config.target must have familyId: string');\n }\n if (typeof target['version'] !== 'string') {\n throwValidation('target.version', 'Config.target must have version: string');\n }\n if (target['familyId'] !== familyId) {\n throwValidation(\n 'target.familyId',\n `Config.target.familyId must match Config.family.familyId (expected: ${familyId}, got: ${target['familyId']})`,\n );\n }\n if (typeof target['targetId'] !== 'string') {\n throwValidation('target.targetId', 'Config.target must have targetId: string');\n }\n if (typeof target['create'] !== 'function') {\n throwValidation('target.create', 'Config.target must have create: function');\n }\n const expectedTargetId = target['targetId'] as string;\n\n // Validate adapter descriptor\n const adapter = configObj['adapter'] as Record<string, unknown>;\n if (adapter['kind'] !== 'adapter') {\n throwValidation('adapter.kind', 'Config.adapter must have kind: \"adapter\"');\n }\n if (typeof adapter['id'] !== 'string') {\n throwValidation('adapter.id', 'Config.adapter must have id: string');\n }\n if (typeof adapter['familyId'] !== 'string') {\n throwValidation('adapter.familyId', 'Config.adapter must have familyId: string');\n }\n if (typeof adapter['version'] !== 'string') {\n throwValidation('adapter.version', 'Config.adapter must have version: string');\n }\n if (adapter['familyId'] !== familyId) {\n throwValidation(\n 'adapter.familyId',\n `Config.adapter.familyId must match Config.family.familyId (expected: ${familyId}, got: ${adapter['familyId']})`,\n );\n }\n if (typeof adapter['targetId'] !== 'string') {\n throwValidation('adapter.targetId', 'Config.adapter must have targetId: string');\n }\n if (adapter['targetId'] !== expectedTargetId) {\n throwValidation(\n 'adapter.targetId',\n `Config.adapter.targetId must match Config.target.targetId (expected: ${expectedTargetId}, got: ${adapter['targetId']})`,\n );\n }\n if (typeof adapter['create'] !== 'function') {\n throwValidation('adapter.create', 'Config.adapter must have create: function');\n }\n\n if (configObj['extensionPacks'] !== undefined) {\n throwValidation(\n 'extensionPacks',\n 'Config.extensionPacks is no longer supported; rename it to Config.extensions',\n );\n }\n\n // Validate extensions array if present\n if (configObj['extensions'] !== undefined) {\n if (!Array.isArray(configObj['extensions'])) {\n throwValidation('extensions', 'Config.extensions must be an array');\n }\n for (const ext of configObj['extensions']) {\n if (!ext || typeof ext !== 'object') {\n throwValidation(\n 'extensions[]',\n 'Config.extensions must contain ControlExtensionDescriptor objects',\n );\n }\n const extObj = ext as Record<string, unknown>;\n if (extObj['kind'] !== 'extension') {\n throwValidation('extensions[].kind', 'Config.extensions items must have kind: \"extension\"');\n }\n if (typeof extObj['id'] !== 'string') {\n throwValidation('extensions[].id', 'Config.extensions items must have id: string');\n }\n if (typeof extObj['familyId'] !== 'string') {\n throwValidation(\n 'extensions[].familyId',\n 'Config.extensions items must have familyId: string',\n );\n }\n if (typeof extObj['version'] !== 'string') {\n throwValidation(\n 'extensions[].version',\n 'Config.extensions items must have version: string',\n );\n }\n if (extObj['familyId'] !== familyId) {\n throwValidation(\n 'extensions[].familyId',\n `Config.extensions[].familyId must match Config.family.familyId (expected: ${familyId}, got: ${extObj['familyId']})`,\n );\n }\n if (typeof extObj['targetId'] !== 'string') {\n throwValidation(\n 'extensions[].targetId',\n 'Config.extensions items must have targetId: string',\n );\n }\n if (extObj['targetId'] !== expectedTargetId) {\n throwValidation(\n 'extensions[].targetId',\n `Config.extensions[].targetId must match Config.target.targetId (expected: ${expectedTargetId}, got: ${extObj['targetId']})`,\n );\n }\n if (typeof extObj['create'] !== 'function') {\n throwValidation(\n 'extensions[].create',\n 'Config.extensions items must have create: function',\n );\n }\n }\n }\n\n // Validate driver descriptor if present\n if (configObj['driver'] !== undefined) {\n const driver = configObj['driver'] as Record<string, unknown>;\n if (driver['kind'] !== 'driver') {\n throwValidation('driver.kind', 'Config.driver must have kind: \"driver\"');\n }\n if (typeof driver['id'] !== 'string') {\n throwValidation('driver.id', 'Config.driver must have id: string');\n }\n if (typeof driver['version'] !== 'string') {\n throwValidation('driver.version', 'Config.driver must have version: string');\n }\n if (typeof driver['familyId'] !== 'string') {\n throwValidation('driver.familyId', 'Config.driver must have familyId: string');\n }\n if (driver['familyId'] !== familyId) {\n throwValidation(\n 'driver.familyId',\n `Config.driver.familyId must match Config.family.familyId (expected: ${familyId}, got: ${driver['familyId']})`,\n );\n }\n if (typeof driver['targetId'] !== 'string') {\n throwValidation('driver.targetId', 'Config.driver must have targetId: string');\n }\n if (driver['targetId'] !== expectedTargetId) {\n throwValidation(\n 'driver.targetId',\n `Config.driver.targetId must match Config.target.targetId (expected: ${expectedTargetId}, got: ${driver['targetId']})`,\n );\n }\n if (typeof driver['create'] !== 'function') {\n throwValidation('driver.create', 'Config.driver must have create: function');\n }\n }\n\n // Validate contract config if present (structure validation - defineConfig() handles normalization)\n if (configObj['contract'] !== undefined) {\n const contract = configObj['contract'] as Record<string, unknown>;\n if (!contract || typeof contract !== 'object') {\n throwValidation('contract', 'Config.contract must be an object');\n }\n validateContractConfig(contract);\n }\n}\n"],"mappings":"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"} |
+6
-6
| { | ||
| "name": "@prisma-next/config", | ||
| "version": "0.16.0-dev.19", | ||
| "version": "0.16.0-dev.21", | ||
| "license": "Apache-2.0", | ||
@@ -9,5 +9,5 @@ "type": "module", | ||
| "dependencies": { | ||
| "@prisma-next/contract": "0.16.0-dev.19", | ||
| "@prisma-next/framework-components": "0.16.0-dev.19", | ||
| "@prisma-next/utils": "0.16.0-dev.19", | ||
| "@prisma-next/contract": "0.16.0-dev.21", | ||
| "@prisma-next/framework-components": "0.16.0-dev.21", | ||
| "@prisma-next/utils": "0.16.0-dev.21", | ||
| "arktype": "^2.2.2", | ||
@@ -17,4 +17,4 @@ "pathe": "^2.0.3" | ||
| "devDependencies": { | ||
| "@prisma-next/tsconfig": "0.16.0-dev.19", | ||
| "@prisma-next/tsdown": "0.16.0-dev.19", | ||
| "@prisma-next/tsconfig": "0.16.0-dev.21", | ||
| "@prisma-next/tsdown": "0.16.0-dev.21", | ||
| "tsdown": "0.22.8", | ||
@@ -21,0 +21,0 @@ "typescript": "5.9.3", |
+1
-1
@@ -21,3 +21,3 @@ # @prisma-next/config | ||
| - Type-safe config composition for `family`, `target`, `adapter`, optional `driver`, and optional `extensionPacks` (`extensions` is rejected at runtime) | ||
| - Type-safe config composition for `family`, `target`, `adapter`, optional `driver`, and optional `extensions` (`extensions` is rejected at runtime) | ||
| - Contract source provider protocol (`contract.source`) and diagnostics shape | ||
@@ -24,0 +24,0 @@ - Tool-agnostic provider input metadata for build integrations via `contract.source.inputs` |
@@ -77,3 +77,3 @@ import type { | ||
| readonly adapter: ControlAdapterDescriptor<TFamilyId, TTargetId>; | ||
| readonly extensionPacks?: readonly ControlExtensionDescriptor<TFamilyId, TTargetId>[]; | ||
| readonly extensions?: readonly ControlExtensionDescriptor<TFamilyId, TTargetId>[]; | ||
| /** | ||
@@ -121,3 +121,3 @@ * Driver descriptor for DB-connected CLI commands. | ||
| export const ContractSourceProviderSchema = type({ | ||
| 'sourceFormat?': 'string', | ||
| 'format?': 'string', | ||
| 'inputs?': ContractSourceInputSchema.array(), | ||
@@ -151,3 +151,3 @@ load: 'Function', | ||
| adapter: 'unknown', // ControlAdapterDescriptor - validated separately | ||
| 'extensionPacks?': 'unknown[]', | ||
| 'extensions?': 'unknown[]', | ||
| 'driver?': 'unknown', // ControlDriverDescriptor - validated separately (optional) | ||
@@ -154,0 +154,0 @@ 'db?': 'unknown', |
+26
-26
@@ -162,16 +162,19 @@ import type { PrismaNextConfig } from './config-types'; | ||
| if (configObj['extensions'] !== undefined) { | ||
| throwValidation('extensions', 'Config.extensions is not supported; use Config.extensionPacks'); | ||
| if (configObj['extensionPacks'] !== undefined) { | ||
| throwValidation( | ||
| 'extensionPacks', | ||
| 'Config.extensionPacks is no longer supported; rename it to Config.extensions', | ||
| ); | ||
| } | ||
| // Validate extensionPacks array if present | ||
| if (configObj['extensionPacks'] !== undefined) { | ||
| if (!Array.isArray(configObj['extensionPacks'])) { | ||
| throwValidation('extensionPacks', 'Config.extensionPacks must be an array'); | ||
| // Validate extensions array if present | ||
| if (configObj['extensions'] !== undefined) { | ||
| if (!Array.isArray(configObj['extensions'])) { | ||
| throwValidation('extensions', 'Config.extensions must be an array'); | ||
| } | ||
| for (const ext of configObj['extensionPacks']) { | ||
| for (const ext of configObj['extensions']) { | ||
| if (!ext || typeof ext !== 'object') { | ||
| throwValidation( | ||
| 'extensionPacks[]', | ||
| 'Config.extensionPacks must contain ControlExtensionDescriptor objects', | ||
| 'extensions[]', | ||
| 'Config.extensions must contain ControlExtensionDescriptor objects', | ||
| ); | ||
@@ -181,14 +184,11 @@ } | ||
| if (extObj['kind'] !== 'extension') { | ||
| throwValidation( | ||
| 'extensionPacks[].kind', | ||
| 'Config.extensionPacks items must have kind: "extension"', | ||
| ); | ||
| throwValidation('extensions[].kind', 'Config.extensions items must have kind: "extension"'); | ||
| } | ||
| if (typeof extObj['id'] !== 'string') { | ||
| throwValidation('extensionPacks[].id', 'Config.extensionPacks items must have id: string'); | ||
| throwValidation('extensions[].id', 'Config.extensions items must have id: string'); | ||
| } | ||
| if (typeof extObj['familyId'] !== 'string') { | ||
| throwValidation( | ||
| 'extensionPacks[].familyId', | ||
| 'Config.extensionPacks items must have familyId: string', | ||
| 'extensions[].familyId', | ||
| 'Config.extensions items must have familyId: string', | ||
| ); | ||
@@ -198,4 +198,4 @@ } | ||
| throwValidation( | ||
| 'extensionPacks[].version', | ||
| 'Config.extensionPacks items must have version: string', | ||
| 'extensions[].version', | ||
| 'Config.extensions items must have version: string', | ||
| ); | ||
@@ -205,4 +205,4 @@ } | ||
| throwValidation( | ||
| 'extensionPacks[].familyId', | ||
| `Config.extensionPacks[].familyId must match Config.family.familyId (expected: ${familyId}, got: ${extObj['familyId']})`, | ||
| 'extensions[].familyId', | ||
| `Config.extensions[].familyId must match Config.family.familyId (expected: ${familyId}, got: ${extObj['familyId']})`, | ||
| ); | ||
@@ -212,4 +212,4 @@ } | ||
| throwValidation( | ||
| 'extensionPacks[].targetId', | ||
| 'Config.extensionPacks items must have targetId: string', | ||
| 'extensions[].targetId', | ||
| 'Config.extensions items must have targetId: string', | ||
| ); | ||
@@ -219,4 +219,4 @@ } | ||
| throwValidation( | ||
| 'extensionPacks[].targetId', | ||
| `Config.extensionPacks[].targetId must match Config.target.targetId (expected: ${expectedTargetId}, got: ${extObj['targetId']})`, | ||
| 'extensions[].targetId', | ||
| `Config.extensions[].targetId must match Config.target.targetId (expected: ${expectedTargetId}, got: ${extObj['targetId']})`, | ||
| ); | ||
@@ -226,4 +226,4 @@ } | ||
| throwValidation( | ||
| 'extensionPacks[].create', | ||
| 'Config.extensionPacks items must have create: function', | ||
| 'extensions[].create', | ||
| 'Config.extensions items must have create: function', | ||
| ); | ||
@@ -230,0 +230,0 @@ } |
@@ -41,3 +41,3 @@ import type { Contract } from '@prisma-next/contract/types'; | ||
| export interface ContractSourceContext { | ||
| readonly composedExtensionPacks: readonly string[]; | ||
| readonly composedExtensions: readonly string[]; | ||
| /** Extension contracts keyed by space ID, required for cross-space FK resolution. */ | ||
@@ -63,7 +63,7 @@ readonly composedExtensionContracts: ReadonlyMap<string, Contract>; | ||
| export interface PslContractSourceProvider extends ContractSourceProviderBase { | ||
| readonly sourceFormat: 'psl'; | ||
| readonly format: 'psl'; | ||
| } | ||
| export interface TypeScriptContractSourceProvider extends ContractSourceProviderBase { | ||
| readonly sourceFormat: 'typescript'; | ||
| readonly format: 'typescript'; | ||
| } | ||
@@ -73,3 +73,3 @@ | ||
| * Third-party or unspecified source formats. Absent (or unrecognized) | ||
| * `sourceFormat` means format-aware tooling must leave the source untouched. | ||
| * `format` means format-aware tooling must leave the source untouched. | ||
| * Narrowing to a known format flows only through capability guards owned by | ||
@@ -79,3 +79,3 @@ * the authoring layer. | ||
| export interface OpaqueContractSourceProvider extends ContractSourceProviderBase { | ||
| readonly sourceFormat?: string; | ||
| readonly format?: string; | ||
| } | ||
@@ -82,0 +82,0 @@ |
| import { AssembledAuthoringContributions, ControlAdapterDescriptor, ControlDriverDescriptor, ControlDriverInstance, ControlExtensionDescriptor, ControlFamilyDescriptor, ControlMutationDefaults, ControlTargetDescriptor } from "@prisma-next/framework-components/control"; | ||
| import { Contract } from "@prisma-next/contract/types"; | ||
| import { CodecLookup } from "@prisma-next/framework-components/codec"; | ||
| import { CapabilityMatrix } from "@prisma-next/framework-components/components"; | ||
| import { Result } from "@prisma-next/utils/result"; | ||
| //#region src/contract-source-types.d.ts | ||
| interface ContractSourceDiagnosticPosition { | ||
| readonly offset: number; | ||
| readonly line: number; | ||
| readonly column: number; | ||
| } | ||
| interface ContractSourceDiagnosticSpan { | ||
| readonly start: ContractSourceDiagnosticPosition; | ||
| readonly end: ContractSourceDiagnosticPosition; | ||
| } | ||
| interface ContractSourceDiagnostic { | ||
| readonly code: string; | ||
| readonly message: string; | ||
| readonly sourceId?: string; | ||
| readonly span?: ContractSourceDiagnosticSpan; | ||
| /** | ||
| * Optional structured payload for machine-readable consumers (agents, | ||
| * IDE extensions, CLI auto-fix). Human-readable prose lives in `message`; | ||
| * `data` carries the extracted facts (e.g. `{ namespace: 'pgvector' }`). | ||
| */ | ||
| readonly data?: Readonly<Record<string, unknown>>; | ||
| } | ||
| interface ContractSourceDiagnostics { | ||
| readonly summary: string; | ||
| readonly diagnostics: readonly ContractSourceDiagnostic[]; | ||
| readonly meta?: Record<string, unknown>; | ||
| } | ||
| interface ContractSourceContext { | ||
| readonly composedExtensionPacks: readonly string[]; | ||
| /** Extension contracts keyed by space ID, required for cross-space FK resolution. */ | ||
| readonly composedExtensionContracts: ReadonlyMap<string, Contract>; | ||
| readonly authoringContributions: AssembledAuthoringContributions; | ||
| readonly codecLookup: CodecLookup; | ||
| readonly controlMutationDefaults: ControlMutationDefaults; | ||
| readonly resolvedInputs: readonly string[]; | ||
| readonly capabilities: CapabilityMatrix; | ||
| } | ||
| /** Lets format-aware tooling avoid file-extension sniffing and opaque loader introspection. */ | ||
| type ContractSourceFormat = 'psl' | 'typescript'; | ||
| interface ContractSourceProviderBase { | ||
| readonly inputs?: readonly string[]; | ||
| readonly load: (context: ContractSourceContext) => Promise<Result<Contract, ContractSourceDiagnostics>>; | ||
| } | ||
| interface PslContractSourceProvider extends ContractSourceProviderBase { | ||
| readonly sourceFormat: 'psl'; | ||
| } | ||
| interface TypeScriptContractSourceProvider extends ContractSourceProviderBase { | ||
| readonly sourceFormat: 'typescript'; | ||
| } | ||
| /** | ||
| * Third-party or unspecified source formats. Absent (or unrecognized) | ||
| * `sourceFormat` means format-aware tooling must leave the source untouched. | ||
| * Narrowing to a known format flows only through capability guards owned by | ||
| * the authoring layer. | ||
| */ | ||
| interface OpaqueContractSourceProvider extends ContractSourceProviderBase { | ||
| readonly sourceFormat?: string; | ||
| } | ||
| type ContractSourceProvider = PslContractSourceProvider | TypeScriptContractSourceProvider | OpaqueContractSourceProvider; | ||
| //#endregion | ||
| //#region src/config-types.d.ts | ||
| /** | ||
| * Contract configuration specifying source and artifact locations. | ||
| */ | ||
| interface ContractConfig { | ||
| /** | ||
| * Contract source provider. The provider is always async and must return | ||
| * a Result containing either a Contract or structured diagnostics. | ||
| */ | ||
| readonly source: ContractSourceProvider; | ||
| /** | ||
| * Path to contract.json artifact. Providers that know an input path (PSL, | ||
| * `typescriptContractFromPath`) derive an output colocated with that input | ||
| * so this rarely needs to be set explicitly. The `.d.ts` types file is | ||
| * always emitted next to the JSON (e.g., `contract.json` → `contract.d.ts`). | ||
| */ | ||
| readonly output?: string; | ||
| } | ||
| interface FormatterConfig { | ||
| readonly indent?: number | 'tab'; | ||
| readonly newline?: 'LF' | 'CRLF'; | ||
| } | ||
| /** | ||
| * Default *source* directory for the contract file the user authors at `init` | ||
| * time. Output artefacts colocate with source per the same rule path-bearing | ||
| * providers apply. | ||
| */ | ||
| declare const DEFAULT_CONTRACT_SOURCE_DIR = "src/prisma"; | ||
| declare function normalizeContractConfig(contract: ContractConfig): ContractConfig & { | ||
| readonly output: string; | ||
| }; | ||
| /** | ||
| * Configuration for Prisma Next CLI. | ||
| * Uses Control*Descriptor types for type-safe wiring with compile-time compatibility checks. | ||
| * | ||
| * @template TFamilyId - The family ID (e.g., 'sql', 'document') | ||
| * @template TTargetId - The target ID (e.g., 'postgres', 'mysql') | ||
| * @template TConnection - The driver connection input type (defaults to `unknown` for config flexibility) | ||
| */ | ||
| interface PrismaNextConfig<TFamilyId extends string = string, TTargetId extends string = string, TConnection = unknown> { | ||
| readonly family: ControlFamilyDescriptor<TFamilyId>; | ||
| readonly target: ControlTargetDescriptor<TFamilyId, TTargetId>; | ||
| readonly adapter: ControlAdapterDescriptor<TFamilyId, TTargetId>; | ||
| readonly extensionPacks?: readonly ControlExtensionDescriptor<TFamilyId, TTargetId>[]; | ||
| /** | ||
| * Driver descriptor for DB-connected CLI commands. | ||
| * Required for DB-connected commands (e.g., db verify). | ||
| * Optional for commands that don't need database access (e.g., emit). | ||
| * The driver's connection type matches the TConnection config parameter. | ||
| */ | ||
| readonly driver?: ControlDriverDescriptor<TFamilyId, TTargetId, ControlDriverInstance<TFamilyId, TTargetId>, TConnection>; | ||
| /** | ||
| * Database connection configuration. | ||
| * The connection type is driver-specific (e.g., URL string for Postgres). | ||
| */ | ||
| readonly db?: { | ||
| /** | ||
| * Driver-specific connection input. | ||
| * For Postgres: a connection string (URL). | ||
| * For other drivers: may be a structured object. | ||
| */ | ||
| readonly connection?: TConnection; | ||
| }; | ||
| /** | ||
| * Contract configuration. Specifies source and artifact locations. | ||
| * Required for emit command; optional for other commands that only read artifacts. | ||
| */ | ||
| readonly contract?: ContractConfig; | ||
| /** | ||
| * Migration configuration. Controls where on-disk migration packages are stored. | ||
| */ | ||
| readonly migrations?: { | ||
| /** Directory for migration packages, relative to config file. Defaults to 'migrations'. */ | ||
| readonly dir?: string; | ||
| }; | ||
| readonly formatter?: FormatterConfig; | ||
| } | ||
| /** | ||
| * Helper function to define a Prisma Next config. | ||
| * Validates and normalizes the config using Arktype, then returns the normalized IR. | ||
| * | ||
| * Normalization: | ||
| * - contract.output defaults to a path colocated with DEFAULT_CONTRACT_SOURCE_DIR | ||
| * when missing (in-memory-only providers) | ||
| * | ||
| * @param config - Raw config input from user | ||
| * @returns Normalized config IR with defaults applied | ||
| * @throws Error if config structure is invalid | ||
| */ | ||
| declare function defineConfig<TFamilyId extends string = string, TTargetId extends string = string>(config: PrismaNextConfig<TFamilyId, TTargetId>): PrismaNextConfig<TFamilyId, TTargetId>; | ||
| //#endregion | ||
| export { TypeScriptContractSourceProvider as _, defineConfig as a, ContractSourceDiagnostic as c, ContractSourceDiagnostics as d, ContractSourceFormat as f, PslContractSourceProvider as g, OpaqueContractSourceProvider as h, PrismaNextConfig as i, ContractSourceDiagnosticPosition as l, ContractSourceProviderBase as m, DEFAULT_CONTRACT_SOURCE_DIR as n, normalizeContractConfig as o, ContractSourceProvider as p, FormatterConfig as r, ContractSourceContext as s, ContractConfig as t, ContractSourceDiagnosticSpan as u }; | ||
| //# sourceMappingURL=config-types-DtsiIT_O.d.mts.map |
| {"version":3,"file":"config-types-DtsiIT_O.d.mts","names":[],"sources":["../src/contract-source-types.ts","../src/config-types.ts"],"mappings":";;;;;;UASiB;WACN;WACA;WACA;;UAGM;WACN,OAAO;WACP,KAAK;;UAGC;WACN;WACA;WACA;WACA,OAAO;;;;;;WAMP,OAAO,SAAS;;UAGV;WACN;WACA,sBAAsB;WACtB,OAAO;;UAGD;WACN;;WAEA,4BAA4B,oBAAoB;WAChD,wBAAwB;WACxB,aAAa;WACb,yBAAyB;WACzB;WACA,cAAc;;;KAIb;UAEK;WACN;WACA,OACP,SAAS,0BACN,QAAQ,OAAO,UAAU;;UAGf,kCAAkC;WACxC;;UAGM,yCAAyC;WAC/C;;;;;;;;UASM,qCAAqC;WAC3C;;KAGC,yBACR,4BACA,mCACA;;;;;;UC7Da;;;;;WAKN,QAAQ;;;;;;;WAOR;;UAGM;WACN;WACA;;;;;;;cAQE;iBAEG,wBACd,UAAU,iBACT;WAA4B;;;;;;;;;;UAmBd,iBACf,mCACA,mCACA;WAES,QAAQ,wBAAwB;WAChC,QAAQ,wBAAwB,WAAW;WAC3C,SAAS,yBAAyB,WAAW;WAC7C,0BAA0B,2BAA2B,WAAW;;;;;;;WAOhE,SAAS,wBAChB,WACA,WACA,sBAAsB,WAAW,YACjC;;;;;WAMO;;;;;;aAME,aAAa;;;;;;WAMf,WAAW;;;;WAIX;;aAEE;;WAEF,YAAY;;;;;;;;;;;;;;iBAuDP,aAAa,mCAAmC,mCAC9D,QAAQ,iBAAiB,WAAW,aACnC,iBAAiB,WAAW"} |
78654
-0.44%+ Added
+ Added
+ Added
+ Added
+ Added
- Removed
- Removed
- Removed
- Removed
- Removed