@prisma-next/family-sql 0.1.0-dev.2 → 0.1.0-dev.20
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 +42 -0
- package/dist/exports/{chunk-3HYKCN35.js → chunk-2L5DCW2L.js} +1 -1
- package/dist/exports/chunk-2L5DCW2L.js.map +1 -0
- package/dist/exports/chunk-6AMLAAA2.js +771 -0
- package/dist/exports/chunk-6AMLAAA2.js.map +1 -0
- package/dist/exports/chunk-NUALBK4N.js +606 -0
- package/dist/exports/chunk-NUALBK4N.js.map +1 -0
- package/dist/exports/control-adapter.d.ts +1 -1
- package/dist/exports/control.d.ts +40 -113
- package/dist/exports/control.js +126 -1349
- package/dist/exports/control.js.map +1 -1
- package/dist/exports/instance-BDpyIYu5.d.ts +384 -0
- package/dist/exports/runtime.d.ts +13 -3
- package/dist/exports/runtime.js +2 -3
- package/dist/exports/runtime.js.map +1 -1
- package/dist/exports/schema-verify.d.ts +68 -0
- package/dist/exports/schema-verify.js +9 -0
- package/dist/exports/schema-verify.js.map +1 -0
- package/dist/exports/test-utils.d.ts +34 -0
- package/dist/exports/test-utils.js +15 -0
- package/dist/exports/test-utils.js.map +1 -0
- package/dist/exports/verify.d.ts +1 -1
- package/dist/exports/verify.js +1 -1
- package/package.json +29 -21
- package/dist/exports/chunk-3HYKCN35.js.map +0 -1
package/README.md
CHANGED
|
@@ -12,8 +12,10 @@ Provides the SQL family descriptor (`ControlFamilyDescriptor`) that includes:
|
|
|
12
12
|
|
|
13
13
|
- **Family Descriptor Export**: Exports the SQL `ControlFamilyDescriptor` for use in CLI configuration files
|
|
14
14
|
- **Family Instance Creation**: Creates `SqlFamilyInstance` objects that implement control-plane domain actions (`verify`, `schemaVerify`, `introspect`, `emitContract`, `validateContractIR`)
|
|
15
|
+
- **Planner & Runner SPI**: Owns the `MigrationPlanner` / `MigrationRunner` interfaces plus the `SqlControlTargetDescriptor` helper so targets can expose planners and runners (e.g., Postgres init planner/runner)
|
|
15
16
|
- **Family Hook Integration**: Integrates the SQL target family hook (`sqlTargetFamilyHook`) from `@prisma-next/sql-contract-emitter`
|
|
16
17
|
- **Control Plane Entry Point**: Serves as the control plane entry point for the SQL family, enabling the CLI to select the family hook and create family instances
|
|
18
|
+
- **Component Database Dependencies**: Consumes database dependencies declared by framework components (target/adapter/extensions). Callers pass the active `frameworkComponents` list into planning/execution/verification; SQL layers structurally narrow to components that declare `databaseDependencies` and use their pure verification hooks (no fuzzy matching against `contract.extensions`).
|
|
17
19
|
|
|
18
20
|
## Usage
|
|
19
21
|
|
|
@@ -39,6 +41,33 @@ const familyInstance = sql.create({
|
|
|
39
41
|
const contractIR = familyInstance.validateContractIR(contractJson);
|
|
40
42
|
const verifyResult = await familyInstance.verify({ driver, contractIR, ... });
|
|
41
43
|
const emitResult = await familyInstance.emitContract({ contractIR: rawContract }); // Handles stripping mappings and validation internally
|
|
44
|
+
|
|
45
|
+
// Targets that implement SqlControlTargetDescriptor can build planners
|
|
46
|
+
const planner = postgresTargetDescriptor.createPlanner(familyInstance);
|
|
47
|
+
// frameworkComponents should include the active target, adapter, and any extension descriptors so
|
|
48
|
+
// planner/runner can resolve database dependencies declared by those components.
|
|
49
|
+
const planResult = planner.plan({
|
|
50
|
+
contract: sqlContract,
|
|
51
|
+
schema,
|
|
52
|
+
policy,
|
|
53
|
+
frameworkComponents: [postgresTargetDescriptor, postgresAdapterDescriptor, pgVectorExtensionDescriptor],
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
// Targets also provide runners for executing plans
|
|
57
|
+
const runner = postgresTargetDescriptor.createRunner(familyInstance);
|
|
58
|
+
const executeResult = await runner.execute({
|
|
59
|
+
plan: planResult.plan,
|
|
60
|
+
driver,
|
|
61
|
+
destinationContract: sqlContract,
|
|
62
|
+
frameworkComponents: [postgresTargetDescriptor, postgresAdapterDescriptor, pgVectorExtensionDescriptor],
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
// executeResult is a Result<MigrationRunnerSuccessValue, MigrationRunnerFailure>
|
|
66
|
+
if (executeResult.ok) {
|
|
67
|
+
console.log(`Executed ${executeResult.value.operationsExecuted} operations`);
|
|
68
|
+
} else {
|
|
69
|
+
console.error(`Migration failed: ${executeResult.failure.code} - ${executeResult.failure.summary}`);
|
|
70
|
+
}
|
|
42
71
|
```
|
|
43
72
|
|
|
44
73
|
## Architecture
|
|
@@ -68,6 +97,19 @@ The descriptor is "pure data + factory" - it only provides the hook and factory
|
|
|
68
97
|
- **`src/core/assembly.ts`**: Assembly helpers for building operation registries and extracting type imports from descriptors. Test utilities import `convertOperationManifest` from the same package via relative path.
|
|
69
98
|
- **`src/core/verify.ts`**: Verification helpers (`readMarker`, `collectSupportedCodecTypeIds`)
|
|
70
99
|
- **`src/core/control-adapter.ts`**: SQL control adapter interface (`SqlControlAdapter`) for control-plane operations
|
|
100
|
+
- **`src/core/migrations/`**: Migration IR helpers plus planner and runner SPI types (`MigrationPlanner`, `MigrationRunner`, `SqlControlTargetDescriptor`). Runners return `MigrationRunnerResult` which is a union of success/failure.
|
|
101
|
+
|
|
102
|
+
### Migration Runner Error Codes
|
|
103
|
+
|
|
104
|
+
The runner returns structured errors with the following codes:
|
|
105
|
+
|
|
106
|
+
- **`DESTINATION_CONTRACT_MISMATCH`**: Plan destination hash doesn't match provided contract hash
|
|
107
|
+
- **`MARKER_ORIGIN_MISMATCH`**: Existing marker doesn't match plan's expected origin
|
|
108
|
+
- **`POLICY_VIOLATION`**: Operation class is not allowed by the plan's policy
|
|
109
|
+
- **`PRECHECK_FAILED`**: Operation precheck returned false
|
|
110
|
+
- **`POSTCHECK_FAILED`**: Operation postcheck returned false after execution
|
|
111
|
+
- **`SCHEMA_VERIFY_FAILED`**: Resulting schema doesn't satisfy the destination contract
|
|
112
|
+
- **`EXECUTION_FAILED`**: SQL execution error during operation execution
|
|
71
113
|
- **`src/exports/control.ts`**: Control plane entry point (exports `SqlFamilyDescriptor` instance)
|
|
72
114
|
- **`src/exports/runtime.ts`**: Runtime entry point (placeholder for future functionality)
|
|
73
115
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/core/verify.ts"],"sourcesContent":["import type { ContractMarkerRecord } from '@prisma-next/contract/types';\nimport type {\n ControlAdapterDescriptor,\n ControlDriverInstance,\n ControlExtensionDescriptor,\n ControlTargetDescriptor,\n} from '@prisma-next/core-control-plane/types';\nimport { type } from 'arktype';\n\nconst MetaSchema = type({ '[string]': 'unknown' });\n\nfunction parseMeta(meta: unknown): Record<string, unknown> {\n if (meta === null || meta === undefined) {\n return {};\n }\n\n let parsed: unknown;\n if (typeof meta === 'string') {\n try {\n parsed = JSON.parse(meta);\n } catch {\n return {};\n }\n } else {\n parsed = meta;\n }\n\n const result = MetaSchema(parsed);\n if (result instanceof type.errors) {\n return {};\n }\n\n return result as Record<string, unknown>;\n}\n\nconst ContractMarkerRowSchema = type({\n core_hash: 'string',\n profile_hash: 'string',\n 'contract_json?': 'unknown | null',\n 'canonical_version?': 'number | null',\n 'updated_at?': 'Date | string',\n 'app_tag?': 'string | null',\n 'meta?': 'unknown | null',\n});\n\n/**\n * Parses a contract marker row from database query result.\n * This is SQL-specific parsing logic (handles SQL row structure with snake_case columns).\n */\nexport function parseContractMarkerRow(row: unknown): ContractMarkerRecord {\n const result = ContractMarkerRowSchema(row);\n if (result instanceof type.errors) {\n const messages = result.map((p: { message: string }) => p.message).join('; ');\n throw new Error(`Invalid contract marker row: ${messages}`);\n }\n\n const validatedRow = result as {\n core_hash: string;\n profile_hash: string;\n contract_json?: unknown | null;\n canonical_version?: number | null;\n updated_at?: Date | string;\n app_tag?: string | null;\n meta?: unknown | null;\n };\n\n const updatedAt = validatedRow.updated_at\n ? validatedRow.updated_at instanceof Date\n ? validatedRow.updated_at\n : new Date(validatedRow.updated_at)\n : new Date();\n\n return {\n coreHash: validatedRow.core_hash,\n profileHash: validatedRow.profile_hash,\n contractJson: validatedRow.contract_json ?? null,\n canonicalVersion: validatedRow.canonical_version ?? null,\n updatedAt,\n appTag: validatedRow.app_tag ?? null,\n meta: parseMeta(validatedRow.meta),\n };\n}\n\n/**\n * Returns the SQL statement to read the contract marker.\n * This is a migration-plane helper (no runtime imports).\n * @internal - Used internally by readMarker(). Prefer readMarker() for Control Plane usage.\n */\nexport function readMarkerSql(): { readonly sql: string; readonly params: readonly unknown[] } {\n return {\n sql: `select\n core_hash,\n profile_hash,\n contract_json,\n canonical_version,\n updated_at,\n app_tag,\n meta\n from prisma_contract.marker\n where id = $1`,\n params: [1],\n };\n}\n\n/**\n * Reads the contract marker from the database using the provided driver.\n * Returns the parsed marker record or null if no marker is found.\n * This abstracts SQL-specific details from the Control Plane.\n *\n * @param driver - ControlDriverInstance instance for executing queries\n * @returns Promise resolving to ContractMarkerRecord or null if marker not found\n */\nexport async function readMarker(\n driver: ControlDriverInstance<'sql', string>,\n): Promise<ContractMarkerRecord | null> {\n const markerStatement = readMarkerSql();\n const queryResult = await driver.query<{\n core_hash: string;\n profile_hash: string;\n contract_json: unknown | null;\n canonical_version: number | null;\n updated_at: Date | string;\n app_tag: string | null;\n meta: unknown | null;\n }>(markerStatement.sql, markerStatement.params);\n\n if (queryResult.rows.length === 0) {\n return null;\n }\n\n const markerRow = queryResult.rows[0];\n if (!markerRow) {\n // If rows array has length > 0 but first element is undefined, this is an unexpected result structure\n throw new Error('Database query returned unexpected result structure');\n }\n\n return parseContractMarkerRow(markerRow);\n}\n\n/**\n * Collects supported codec type IDs from adapter and extension manifests.\n * Returns a sorted, unique array of type IDs that are declared in the manifests.\n * This enables coverage checks by comparing contract column types against supported types.\n *\n * Note: This extracts type IDs from manifest type imports, not from runtime codec registries.\n * The manifests declare which codec types are available, but the actual type IDs\n * are defined in the codec-types TypeScript modules that are imported.\n *\n * For MVP, we return an empty array since extracting type IDs from TypeScript modules\n * would require runtime evaluation or static analysis. This can be enhanced later.\n */\nexport function collectSupportedCodecTypeIds<TFamilyId extends string, TTargetId extends string>(\n descriptors: ReadonlyArray<\n | ControlTargetDescriptor<TFamilyId, TTargetId>\n | ControlAdapterDescriptor<TFamilyId, TTargetId>\n | ControlExtensionDescriptor<TFamilyId, TTargetId>\n >,\n): readonly string[] {\n // For MVP, return empty array\n // Future enhancement: Extract type IDs from codec-types modules via static analysis\n // or require manifests to explicitly list supported type IDs\n void descriptors;\n return [];\n}\n"],"mappings":";AAOA,SAAS,YAAY;AAErB,IAAM,aAAa,KAAK,EAAE,YAAY,UAAU,CAAC;AAEjD,SAAS,UAAU,MAAwC;AACzD,MAAI,SAAS,QAAQ,SAAS,QAAW;AACvC,WAAO,CAAC;AAAA,EACV;AAEA,MAAI;AACJ,MAAI,OAAO,SAAS,UAAU;AAC5B,QAAI;AACF,eAAS,KAAK,MAAM,IAAI;AAAA,IAC1B,QAAQ;AACN,aAAO,CAAC;AAAA,IACV;AAAA,EACF,OAAO;AACL,aAAS;AAAA,EACX;AAEA,QAAM,SAAS,WAAW,MAAM;AAChC,MAAI,kBAAkB,KAAK,QAAQ;AACjC,WAAO,CAAC;AAAA,EACV;AAEA,SAAO;AACT;AAEA,IAAM,0BAA0B,KAAK;AAAA,EACnC,WAAW;AAAA,EACX,cAAc;AAAA,EACd,kBAAkB;AAAA,EAClB,sBAAsB;AAAA,EACtB,eAAe;AAAA,EACf,YAAY;AAAA,EACZ,SAAS;AACX,CAAC;AAMM,SAAS,uBAAuB,KAAoC;AACzE,QAAM,SAAS,wBAAwB,GAAG;AAC1C,MAAI,kBAAkB,KAAK,QAAQ;AACjC,UAAM,WAAW,OAAO,IAAI,CAAC,MAA2B,EAAE,OAAO,EAAE,KAAK,IAAI;AAC5E,UAAM,IAAI,MAAM,gCAAgC,QAAQ,EAAE;AAAA,EAC5D;AAEA,QAAM,eAAe;AAUrB,QAAM,YAAY,aAAa,aAC3B,aAAa,sBAAsB,OACjC,aAAa,aACb,IAAI,KAAK,aAAa,UAAU,IAClC,oBAAI,KAAK;AAEb,SAAO;AAAA,IACL,UAAU,aAAa;AAAA,IACvB,aAAa,aAAa;AAAA,IAC1B,cAAc,aAAa,iBAAiB;AAAA,IAC5C,kBAAkB,aAAa,qBAAqB;AAAA,IACpD;AAAA,IACA,QAAQ,aAAa,WAAW;AAAA,IAChC,MAAM,UAAU,aAAa,IAAI;AAAA,EACnC;AACF;AAOO,SAAS,gBAA+E;AAC7F,SAAO;AAAA,IACL,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAUL,QAAQ,CAAC,CAAC;AAAA,EACZ;AACF;AAUA,eAAsB,WACpB,QACsC;AACtC,QAAM,kBAAkB,cAAc;AACtC,QAAM,cAAc,MAAM,OAAO,MAQ9B,gBAAgB,KAAK,gBAAgB,MAAM;AAE9C,MAAI,YAAY,KAAK,WAAW,GAAG;AACjC,WAAO;AAAA,EACT;AAEA,QAAM,YAAY,YAAY,KAAK,CAAC;AACpC,MAAI,CAAC,WAAW;AAEd,UAAM,IAAI,MAAM,qDAAqD;AAAA,EACvE;AAEA,SAAO,uBAAuB,SAAS;AACzC;AAcO,SAAS,6BACd,aAKmB;AAInB,OAAK;AACL,SAAO,CAAC;AACV;","names":[]}
|