@prisma-next/cli 0.3.0-dev.16 → 0.3.0-dev.163
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/LICENSE +201 -0
- package/README.md +381 -128
- package/dist/cli-errors-BDCYR5ap.mjs +4 -0
- package/dist/cli-errors-Dzs7Oxz7.d.mts +3 -0
- package/dist/cli.d.mts +1 -0
- package/dist/cli.js +1 -2671
- package/dist/cli.mjs +238 -0
- package/dist/cli.mjs.map +1 -0
- package/dist/client-yYtotiSX.mjs +1063 -0
- package/dist/client-yYtotiSX.mjs.map +1 -0
- package/dist/commands/contract-emit.d.mts +7 -0
- package/dist/commands/contract-emit.d.mts.map +1 -0
- package/dist/commands/contract-emit.mjs +4 -0
- package/dist/commands/contract-infer.d.mts +7 -0
- package/dist/commands/contract-infer.d.mts.map +1 -0
- package/dist/commands/contract-infer.mjs +4 -0
- package/dist/commands/db-init.d.mts +7 -0
- package/dist/commands/db-init.d.mts.map +1 -0
- package/dist/commands/db-init.mjs +124 -0
- package/dist/commands/db-init.mjs.map +1 -0
- package/dist/commands/db-schema.d.mts +7 -0
- package/dist/commands/db-schema.d.mts.map +1 -0
- package/dist/commands/db-schema.mjs +52 -0
- package/dist/commands/db-schema.mjs.map +1 -0
- package/dist/commands/db-sign.d.mts +7 -0
- package/dist/commands/db-sign.d.mts.map +1 -0
- package/dist/commands/db-sign.mjs +135 -0
- package/dist/commands/db-sign.mjs.map +1 -0
- package/dist/commands/db-update.d.mts +7 -0
- package/dist/commands/db-update.d.mts.map +1 -0
- package/dist/commands/db-update.mjs +121 -0
- package/dist/commands/db-update.mjs.map +1 -0
- package/dist/commands/db-verify.d.mts +7 -0
- package/dist/commands/db-verify.d.mts.map +1 -0
- package/dist/commands/db-verify.mjs +321 -0
- package/dist/commands/db-verify.mjs.map +1 -0
- package/dist/commands/migration-apply.d.mts +36 -0
- package/dist/commands/migration-apply.d.mts.map +1 -0
- package/dist/commands/migration-apply.mjs +243 -0
- package/dist/commands/migration-apply.mjs.map +1 -0
- package/dist/commands/migration-new.d.mts +8 -0
- package/dist/commands/migration-new.d.mts.map +1 -0
- package/dist/commands/migration-new.mjs +151 -0
- package/dist/commands/migration-new.mjs.map +1 -0
- package/dist/commands/migration-plan.d.mts +47 -0
- package/dist/commands/migration-plan.d.mts.map +1 -0
- package/dist/commands/migration-plan.mjs +312 -0
- package/dist/commands/migration-plan.mjs.map +1 -0
- package/dist/commands/migration-ref.d.mts +43 -0
- package/dist/commands/migration-ref.d.mts.map +1 -0
- package/dist/commands/migration-ref.mjs +194 -0
- package/dist/commands/migration-ref.mjs.map +1 -0
- package/dist/commands/migration-show.d.mts +28 -0
- package/dist/commands/migration-show.d.mts.map +1 -0
- package/dist/commands/migration-show.mjs +139 -0
- package/dist/commands/migration-show.mjs.map +1 -0
- package/dist/commands/migration-status.d.mts +86 -0
- package/dist/commands/migration-status.d.mts.map +1 -0
- package/dist/commands/migration-status.mjs +4 -0
- package/dist/commands/migration-verify.d.mts +16 -0
- package/dist/commands/migration-verify.d.mts.map +1 -0
- package/dist/commands/migration-verify.mjs +109 -0
- package/dist/commands/migration-verify.mjs.map +1 -0
- package/dist/config-loader-C4VXKl8f.mjs +43 -0
- package/dist/config-loader-C4VXKl8f.mjs.map +1 -0
- package/dist/{config-loader.d.ts → config-loader.d.mts} +8 -3
- package/dist/config-loader.d.mts.map +1 -0
- package/dist/config-loader.mjs +3 -0
- package/dist/contract-emit-Bk_eEDKu.mjs +187 -0
- package/dist/contract-emit-Bk_eEDKu.mjs.map +1 -0
- package/dist/contract-infer-suMDmFSG.mjs +89 -0
- package/dist/contract-infer-suMDmFSG.mjs.map +1 -0
- package/dist/exports/config-types.d.mts +2 -0
- package/dist/exports/config-types.mjs +3 -0
- package/dist/exports/control-api.d.mts +624 -0
- package/dist/exports/control-api.d.mts.map +1 -0
- package/dist/exports/control-api.mjs +109 -0
- package/dist/exports/control-api.mjs.map +1 -0
- package/dist/{load-ts-contract.d.ts → exports/index.d.mts} +12 -7
- package/dist/exports/index.d.mts.map +1 -0
- package/dist/exports/index.mjs +137 -0
- package/dist/exports/index.mjs.map +1 -0
- package/dist/extract-operation-statements-BVlb3jxp.mjs +13 -0
- package/dist/extract-operation-statements-BVlb3jxp.mjs.map +1 -0
- package/dist/extract-sql-ddl-6EVSOThm.mjs +26 -0
- package/dist/extract-sql-ddl-6EVSOThm.mjs.map +1 -0
- package/dist/framework-components-BAsliT4V.mjs +59 -0
- package/dist/framework-components-BAsliT4V.mjs.map +1 -0
- package/dist/inspect-live-schema-HMutsJYh.mjs +91 -0
- package/dist/inspect-live-schema-HMutsJYh.mjs.map +1 -0
- package/dist/migration-command-scaffold-Dg7CKKCg.mjs +105 -0
- package/dist/migration-command-scaffold-Dg7CKKCg.mjs.map +1 -0
- package/dist/migration-status-BqfVmC0w.mjs +1582 -0
- package/dist/migration-status-BqfVmC0w.mjs.map +1 -0
- package/dist/migrations-Bv8oeiY_.mjs +173 -0
- package/dist/migrations-Bv8oeiY_.mjs.map +1 -0
- package/dist/progress-adapter-D4x8SbJa.mjs +43 -0
- package/dist/progress-adapter-D4x8SbJa.mjs.map +1 -0
- package/dist/terminal-ui-N5tR-ob5.mjs +967 -0
- package/dist/terminal-ui-N5tR-ob5.mjs.map +1 -0
- package/dist/verify-WARh5TjK.mjs +385 -0
- package/dist/verify-WARh5TjK.mjs.map +1 -0
- package/package.json +88 -42
- package/src/cli.ts +113 -58
- package/src/commands/contract-emit.ts +237 -144
- package/src/commands/contract-infer-paths.ts +32 -0
- package/src/commands/contract-infer.ts +143 -0
- package/src/commands/db-init.ts +97 -219
- package/src/commands/db-schema.ts +77 -0
- package/src/commands/db-sign.ts +208 -229
- package/src/commands/db-update.ts +236 -0
- package/src/commands/db-verify.ts +504 -184
- package/src/commands/inspect-live-schema.ts +170 -0
- package/src/commands/migration-apply.ts +427 -0
- package/src/commands/migration-new.ts +260 -0
- package/src/commands/migration-plan.ts +519 -0
- package/src/commands/migration-ref.ts +305 -0
- package/src/commands/migration-show.ts +246 -0
- package/src/commands/migration-status.ts +864 -0
- package/src/commands/migration-verify.ts +180 -0
- package/src/config-loader.ts +13 -3
- package/src/control-api/client.ts +424 -72
- package/src/control-api/contract-enrichment.ts +119 -0
- package/src/control-api/errors.ts +9 -0
- package/src/control-api/operations/contract-emit.ts +174 -0
- package/src/control-api/operations/db-init.ts +53 -49
- package/src/control-api/operations/db-update.ts +220 -0
- package/src/control-api/operations/extract-operation-statements.ts +14 -0
- package/src/control-api/operations/extract-sql-ddl.ts +47 -0
- package/src/control-api/operations/migration-apply.ts +191 -0
- package/src/control-api/operations/migration-helpers.ts +49 -0
- package/src/control-api/types.ts +388 -18
- package/src/exports/config-types.ts +4 -3
- package/src/exports/control-api.ts +21 -2
- package/src/load-ts-contract.ts +30 -19
- package/src/utils/cli-errors.ts +14 -8
- package/src/utils/command-helpers.ts +302 -3
- package/src/utils/formatters/emit.ts +67 -0
- package/src/utils/formatters/errors.ts +82 -0
- package/src/utils/formatters/graph-migration-mapper.ts +240 -0
- package/src/utils/formatters/graph-render.ts +1323 -0
- package/src/utils/formatters/graph-types.ts +120 -0
- package/src/utils/formatters/help.ts +380 -0
- package/src/utils/formatters/helpers.ts +28 -0
- package/src/utils/formatters/migrations.ts +346 -0
- package/src/utils/formatters/styled.ts +212 -0
- package/src/utils/formatters/verify.ts +621 -0
- package/src/utils/framework-components.ts +13 -10
- package/src/utils/global-flags.ts +41 -23
- package/src/utils/migration-command-scaffold.ts +184 -0
- package/src/utils/migration-types.ts +12 -0
- package/src/utils/progress-adapter.ts +18 -29
- package/src/utils/result-handler.ts +12 -13
- package/src/utils/shutdown.ts +92 -0
- package/src/utils/suggest-command.ts +31 -0
- package/src/utils/terminal-ui.ts +276 -0
- package/dist/chunk-5MPKZYVI.js +0 -47
- package/dist/chunk-5MPKZYVI.js.map +0 -1
- package/dist/chunk-6EPKRATC.js +0 -91
- package/dist/chunk-6EPKRATC.js.map +0 -1
- package/dist/chunk-74IELXRA.js +0 -371
- package/dist/chunk-74IELXRA.js.map +0 -1
- package/dist/chunk-HWYQOCAJ.js +0 -47
- package/dist/chunk-HWYQOCAJ.js.map +0 -1
- package/dist/chunk-U6QI3AZ3.js +0 -133
- package/dist/chunk-U6QI3AZ3.js.map +0 -1
- package/dist/chunk-VI2YETW7.js +0 -38
- package/dist/chunk-VI2YETW7.js.map +0 -1
- package/dist/chunk-ZG5T6OB5.js +0 -923
- package/dist/chunk-ZG5T6OB5.js.map +0 -1
- package/dist/cli.d.ts +0 -2
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/commands/contract-emit.d.ts +0 -3
- package/dist/commands/contract-emit.d.ts.map +0 -1
- package/dist/commands/contract-emit.js +0 -11
- package/dist/commands/contract-emit.js.map +0 -1
- package/dist/commands/db-init.d.ts +0 -3
- package/dist/commands/db-init.d.ts.map +0 -1
- package/dist/commands/db-init.js +0 -302
- package/dist/commands/db-init.js.map +0 -1
- package/dist/commands/db-introspect.d.ts +0 -3
- package/dist/commands/db-introspect.d.ts.map +0 -1
- package/dist/commands/db-introspect.js +0 -185
- package/dist/commands/db-introspect.js.map +0 -1
- package/dist/commands/db-schema-verify.d.ts +0 -3
- package/dist/commands/db-schema-verify.d.ts.map +0 -1
- package/dist/commands/db-schema-verify.js +0 -163
- package/dist/commands/db-schema-verify.js.map +0 -1
- package/dist/commands/db-sign.d.ts +0 -3
- package/dist/commands/db-sign.d.ts.map +0 -1
- package/dist/commands/db-sign.js +0 -198
- package/dist/commands/db-sign.js.map +0 -1
- package/dist/commands/db-verify.d.ts +0 -3
- package/dist/commands/db-verify.d.ts.map +0 -1
- package/dist/commands/db-verify.js +0 -172
- package/dist/commands/db-verify.js.map +0 -1
- package/dist/config-loader.d.ts.map +0 -1
- package/dist/config-loader.js +0 -7
- package/dist/config-loader.js.map +0 -1
- package/dist/control-api/client.d.ts +0 -13
- package/dist/control-api/client.d.ts.map +0 -1
- package/dist/control-api/operations/db-init.d.ts +0 -29
- package/dist/control-api/operations/db-init.d.ts.map +0 -1
- package/dist/control-api/types.d.ts +0 -256
- package/dist/control-api/types.d.ts.map +0 -1
- package/dist/exports/config-types.d.ts +0 -3
- package/dist/exports/config-types.d.ts.map +0 -1
- package/dist/exports/config-types.js +0 -6
- package/dist/exports/config-types.js.map +0 -1
- package/dist/exports/control-api.d.ts +0 -13
- package/dist/exports/control-api.d.ts.map +0 -1
- package/dist/exports/control-api.js +0 -9
- package/dist/exports/control-api.js.map +0 -1
- package/dist/exports/index.d.ts +0 -4
- package/dist/exports/index.d.ts.map +0 -1
- package/dist/exports/index.js +0 -177
- package/dist/exports/index.js.map +0 -1
- package/dist/load-ts-contract.d.ts.map +0 -1
- package/dist/utils/action.d.ts +0 -16
- package/dist/utils/action.d.ts.map +0 -1
- package/dist/utils/cli-errors.d.ts +0 -7
- package/dist/utils/cli-errors.d.ts.map +0 -1
- package/dist/utils/command-helpers.d.ts +0 -12
- package/dist/utils/command-helpers.d.ts.map +0 -1
- package/dist/utils/framework-components.d.ts +0 -70
- package/dist/utils/framework-components.d.ts.map +0 -1
- package/dist/utils/global-flags.d.ts +0 -25
- package/dist/utils/global-flags.d.ts.map +0 -1
- package/dist/utils/output.d.ts +0 -142
- package/dist/utils/output.d.ts.map +0 -1
- package/dist/utils/progress-adapter.d.ts +0 -26
- package/dist/utils/progress-adapter.d.ts.map +0 -1
- package/dist/utils/result-handler.d.ts +0 -15
- package/dist/utils/result-handler.d.ts.map +0 -1
- package/dist/utils/spinner.d.ts +0 -29
- package/dist/utils/spinner.d.ts.map +0 -1
- package/src/commands/db-introspect.ts +0 -254
- package/src/commands/db-schema-verify.ts +0 -231
- package/src/utils/action.ts +0 -43
- package/src/utils/output.ts +0 -1471
- package/src/utils/spinner.ts +0 -67
|
@@ -1,21 +1,42 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import {
|
|
1
|
+
import type { Contract, ContractMarkerRecord } from '@prisma-next/contract/types';
|
|
2
|
+
import { emit as emitContractArtifacts } from '@prisma-next/emitter';
|
|
3
|
+
import type { TargetBoundComponentDescriptor } from '@prisma-next/framework-components/components';
|
|
3
4
|
import type {
|
|
4
5
|
ControlDriverInstance,
|
|
5
6
|
ControlFamilyInstance,
|
|
6
|
-
|
|
7
|
+
ControlStack,
|
|
8
|
+
CoreSchemaView,
|
|
7
9
|
SignDatabaseResult,
|
|
8
10
|
VerifyDatabaseResult,
|
|
9
11
|
VerifyDatabaseSchemaResult,
|
|
10
|
-
} from '@prisma-next/
|
|
12
|
+
} from '@prisma-next/framework-components/control';
|
|
13
|
+
import {
|
|
14
|
+
createControlStack,
|
|
15
|
+
hasMigrations,
|
|
16
|
+
hasSchemaView,
|
|
17
|
+
} from '@prisma-next/framework-components/control';
|
|
18
|
+
import { ifDefined } from '@prisma-next/utils/defined';
|
|
19
|
+
import { notOk, ok } from '@prisma-next/utils/result';
|
|
11
20
|
import { assertFrameworkComponentsCompatible } from '../utils/framework-components';
|
|
21
|
+
import { enrichContract } from './contract-enrichment';
|
|
22
|
+
import { ContractValidationError } from './errors';
|
|
12
23
|
import { executeDbInit } from './operations/db-init';
|
|
24
|
+
import { executeDbUpdate } from './operations/db-update';
|
|
25
|
+
import { executeMigrationApply } from './operations/migration-apply';
|
|
13
26
|
import type {
|
|
27
|
+
ControlActionName,
|
|
14
28
|
ControlClient,
|
|
15
29
|
ControlClientOptions,
|
|
16
30
|
DbInitOptions,
|
|
17
31
|
DbInitResult,
|
|
32
|
+
DbUpdateOptions,
|
|
33
|
+
DbUpdateResult,
|
|
34
|
+
EmitOptions,
|
|
35
|
+
EmitResult,
|
|
18
36
|
IntrospectOptions,
|
|
37
|
+
MigrationApplyOptions,
|
|
38
|
+
MigrationApplyResult,
|
|
39
|
+
OnControlProgress,
|
|
19
40
|
SchemaVerifyOptions,
|
|
20
41
|
SignOptions,
|
|
21
42
|
VerifyOptions,
|
|
@@ -41,9 +62,9 @@ export function createControlClient(options: ControlClientOptions): ControlClien
|
|
|
41
62
|
*/
|
|
42
63
|
class ControlClientImpl implements ControlClient {
|
|
43
64
|
private readonly options: ControlClientOptions;
|
|
44
|
-
private stack:
|
|
65
|
+
private stack: ControlStack | null = null;
|
|
45
66
|
private driver: ControlDriverInstance<string, string> | null = null;
|
|
46
|
-
private familyInstance: ControlFamilyInstance<string> | null = null;
|
|
67
|
+
private familyInstance: ControlFamilyInstance<string, unknown> | null = null;
|
|
47
68
|
private frameworkComponents: ReadonlyArray<
|
|
48
69
|
TargetBoundComponentDescriptor<string, string>
|
|
49
70
|
> | null = null;
|
|
@@ -60,15 +81,14 @@ class ControlClientImpl implements ControlClient {
|
|
|
60
81
|
return; // Idempotent
|
|
61
82
|
}
|
|
62
83
|
|
|
63
|
-
|
|
64
|
-
|
|
84
|
+
this.stack = createControlStack({
|
|
85
|
+
family: this.options.family,
|
|
65
86
|
target: this.options.target,
|
|
66
87
|
adapter: this.options.adapter,
|
|
67
88
|
driver: this.options.driver,
|
|
68
89
|
extensionPacks: this.options.extensionPacks,
|
|
69
90
|
});
|
|
70
91
|
|
|
71
|
-
// Create family instance using the stack
|
|
72
92
|
this.familyInstance = this.options.family.create(this.stack);
|
|
73
93
|
|
|
74
94
|
// Validate and type-narrow framework components
|
|
@@ -109,12 +129,8 @@ class ControlClientImpl implements ControlClient {
|
|
|
109
129
|
);
|
|
110
130
|
}
|
|
111
131
|
|
|
112
|
-
// Create driver instance
|
|
113
|
-
// Cast through any since connection type is driver-specific at runtime.
|
|
114
|
-
// The driver descriptor is typed with any for TConnection in ControlClientOptions,
|
|
115
|
-
// but createControlPlaneStack defaults it to string. We bridge this at runtime.
|
|
116
132
|
// biome-ignore lint/suspicious/noExplicitAny: required for runtime connection type flexibility
|
|
117
|
-
this.driver = await this.stack
|
|
133
|
+
this.driver = await this.stack.driver.create(resolvedConnection as any);
|
|
118
134
|
}
|
|
119
135
|
|
|
120
136
|
async close(): Promise<void> {
|
|
@@ -126,7 +142,7 @@ class ControlClientImpl implements ControlClient {
|
|
|
126
142
|
|
|
127
143
|
private async ensureConnected(): Promise<{
|
|
128
144
|
driver: ControlDriverInstance<string, string>;
|
|
129
|
-
familyInstance: ControlFamilyInstance<string>;
|
|
145
|
+
familyInstance: ControlFamilyInstance<string, unknown>;
|
|
130
146
|
frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<string, string>>;
|
|
131
147
|
}> {
|
|
132
148
|
// Auto-init if needed
|
|
@@ -147,113 +163,449 @@ class ControlClientImpl implements ControlClient {
|
|
|
147
163
|
};
|
|
148
164
|
}
|
|
149
165
|
|
|
166
|
+
private async connectWithProgress(
|
|
167
|
+
connection: unknown | undefined,
|
|
168
|
+
action: ControlActionName,
|
|
169
|
+
onProgress?: OnControlProgress,
|
|
170
|
+
): Promise<void> {
|
|
171
|
+
if (connection === undefined) return;
|
|
172
|
+
onProgress?.({
|
|
173
|
+
action,
|
|
174
|
+
kind: 'spanStart',
|
|
175
|
+
spanId: 'connect',
|
|
176
|
+
label: 'Connecting to database...',
|
|
177
|
+
});
|
|
178
|
+
try {
|
|
179
|
+
await this.connect(connection);
|
|
180
|
+
onProgress?.({ action, kind: 'spanEnd', spanId: 'connect', outcome: 'ok' });
|
|
181
|
+
} catch (error) {
|
|
182
|
+
onProgress?.({ action, kind: 'spanEnd', spanId: 'connect', outcome: 'error' });
|
|
183
|
+
throw error;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
150
187
|
async verify(options: VerifyOptions): Promise<VerifyDatabaseResult> {
|
|
188
|
+
const { onProgress } = options;
|
|
189
|
+
await this.connectWithProgress(options.connection, 'verify', onProgress);
|
|
151
190
|
const { driver, familyInstance } = await this.ensureConnected();
|
|
152
191
|
|
|
153
192
|
// Validate contract using family instance
|
|
154
|
-
|
|
193
|
+
let contract: Contract;
|
|
194
|
+
try {
|
|
195
|
+
contract = familyInstance.validateContract(options.contract);
|
|
196
|
+
} catch (error) {
|
|
197
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
198
|
+
throw new ContractValidationError(message, error);
|
|
199
|
+
}
|
|
155
200
|
|
|
156
|
-
//
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
contractIR,
|
|
163
|
-
expectedTargetId: this.options.target.targetId,
|
|
164
|
-
contractPath: '',
|
|
201
|
+
// Emit verify span
|
|
202
|
+
onProgress?.({
|
|
203
|
+
action: 'verify',
|
|
204
|
+
kind: 'spanStart',
|
|
205
|
+
spanId: 'verify',
|
|
206
|
+
label: 'Verifying database marker...',
|
|
165
207
|
});
|
|
208
|
+
|
|
209
|
+
try {
|
|
210
|
+
// Delegate to family instance verify method
|
|
211
|
+
// Note: We pass empty strings for contractPath/configPath since the programmatic
|
|
212
|
+
// API doesn't deal with file paths. The family instance accepts these as optional
|
|
213
|
+
// metadata for error reporting.
|
|
214
|
+
const result = await familyInstance.verify({
|
|
215
|
+
driver,
|
|
216
|
+
contract,
|
|
217
|
+
expectedTargetId: this.options.target.targetId,
|
|
218
|
+
contractPath: '',
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
onProgress?.({
|
|
222
|
+
action: 'verify',
|
|
223
|
+
kind: 'spanEnd',
|
|
224
|
+
spanId: 'verify',
|
|
225
|
+
outcome: result.ok ? 'ok' : 'error',
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
return result;
|
|
229
|
+
} catch (error) {
|
|
230
|
+
onProgress?.({
|
|
231
|
+
action: 'verify',
|
|
232
|
+
kind: 'spanEnd',
|
|
233
|
+
spanId: 'verify',
|
|
234
|
+
outcome: 'error',
|
|
235
|
+
});
|
|
236
|
+
throw error;
|
|
237
|
+
}
|
|
166
238
|
}
|
|
167
239
|
|
|
168
240
|
async schemaVerify(options: SchemaVerifyOptions): Promise<VerifyDatabaseSchemaResult> {
|
|
241
|
+
const { onProgress } = options;
|
|
242
|
+
await this.connectWithProgress(options.connection, 'schemaVerify', onProgress);
|
|
169
243
|
const { driver, familyInstance, frameworkComponents } = await this.ensureConnected();
|
|
170
244
|
|
|
171
245
|
// Validate contract using family instance
|
|
172
|
-
|
|
246
|
+
let contract: Contract;
|
|
247
|
+
try {
|
|
248
|
+
contract = familyInstance.validateContract(options.contract);
|
|
249
|
+
} catch (error) {
|
|
250
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
251
|
+
throw new ContractValidationError(message, error);
|
|
252
|
+
}
|
|
173
253
|
|
|
174
|
-
//
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
frameworkComponents,
|
|
254
|
+
// Emit schemaVerify span
|
|
255
|
+
onProgress?.({
|
|
256
|
+
action: 'schemaVerify',
|
|
257
|
+
kind: 'spanStart',
|
|
258
|
+
spanId: 'schemaVerify',
|
|
259
|
+
label: 'Verifying database schema...',
|
|
181
260
|
});
|
|
261
|
+
|
|
262
|
+
try {
|
|
263
|
+
// Delegate to family instance schemaVerify method
|
|
264
|
+
const result = await familyInstance.schemaVerify({
|
|
265
|
+
driver,
|
|
266
|
+
contract,
|
|
267
|
+
strict: options.strict ?? false,
|
|
268
|
+
contractPath: '',
|
|
269
|
+
frameworkComponents,
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
onProgress?.({
|
|
273
|
+
action: 'schemaVerify',
|
|
274
|
+
kind: 'spanEnd',
|
|
275
|
+
spanId: 'schemaVerify',
|
|
276
|
+
outcome: result.ok ? 'ok' : 'error',
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
return result;
|
|
280
|
+
} catch (error) {
|
|
281
|
+
onProgress?.({
|
|
282
|
+
action: 'schemaVerify',
|
|
283
|
+
kind: 'spanEnd',
|
|
284
|
+
spanId: 'schemaVerify',
|
|
285
|
+
outcome: 'error',
|
|
286
|
+
});
|
|
287
|
+
throw error;
|
|
288
|
+
}
|
|
182
289
|
}
|
|
183
290
|
|
|
184
291
|
async sign(options: SignOptions): Promise<SignDatabaseResult> {
|
|
292
|
+
const { onProgress } = options;
|
|
293
|
+
await this.connectWithProgress(options.connection, 'sign', onProgress);
|
|
185
294
|
const { driver, familyInstance } = await this.ensureConnected();
|
|
186
295
|
|
|
187
296
|
// Validate contract using family instance
|
|
188
|
-
|
|
297
|
+
let contract: Contract;
|
|
298
|
+
try {
|
|
299
|
+
contract = familyInstance.validateContract(options.contract);
|
|
300
|
+
} catch (error) {
|
|
301
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
302
|
+
throw new ContractValidationError(message, error);
|
|
303
|
+
}
|
|
189
304
|
|
|
190
|
-
//
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
305
|
+
// Emit sign span
|
|
306
|
+
onProgress?.({
|
|
307
|
+
action: 'sign',
|
|
308
|
+
kind: 'spanStart',
|
|
309
|
+
spanId: 'sign',
|
|
310
|
+
label: 'Signing database...',
|
|
195
311
|
});
|
|
196
|
-
}
|
|
197
312
|
|
|
198
|
-
|
|
199
|
-
|
|
313
|
+
try {
|
|
314
|
+
// Delegate to family instance sign method
|
|
315
|
+
const result = await familyInstance.sign({
|
|
316
|
+
driver,
|
|
317
|
+
contract,
|
|
318
|
+
contractPath: options.contractPath ?? '',
|
|
319
|
+
...ifDefined('configPath', options.configPath),
|
|
320
|
+
});
|
|
200
321
|
|
|
201
|
-
// Connect with progress span if connection provided
|
|
202
|
-
if (options.connection !== undefined) {
|
|
203
322
|
onProgress?.({
|
|
204
|
-
action: '
|
|
205
|
-
kind: '
|
|
206
|
-
spanId: '
|
|
207
|
-
|
|
323
|
+
action: 'sign',
|
|
324
|
+
kind: 'spanEnd',
|
|
325
|
+
spanId: 'sign',
|
|
326
|
+
outcome: 'ok',
|
|
208
327
|
});
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
action: 'dbInit',
|
|
220
|
-
kind: 'spanEnd',
|
|
221
|
-
spanId: 'connect',
|
|
222
|
-
outcome: 'error',
|
|
223
|
-
});
|
|
224
|
-
throw error;
|
|
225
|
-
}
|
|
328
|
+
|
|
329
|
+
return result;
|
|
330
|
+
} catch (error) {
|
|
331
|
+
onProgress?.({
|
|
332
|
+
action: 'sign',
|
|
333
|
+
kind: 'spanEnd',
|
|
334
|
+
spanId: 'sign',
|
|
335
|
+
outcome: 'error',
|
|
336
|
+
});
|
|
337
|
+
throw error;
|
|
226
338
|
}
|
|
339
|
+
}
|
|
227
340
|
|
|
341
|
+
async dbInit(options: DbInitOptions): Promise<DbInitResult> {
|
|
342
|
+
const { onProgress } = options;
|
|
343
|
+
await this.connectWithProgress(options.connection, 'dbInit', onProgress);
|
|
228
344
|
const { driver, familyInstance, frameworkComponents } = await this.ensureConnected();
|
|
229
345
|
|
|
230
|
-
|
|
231
|
-
if (!this.options.target.migrations) {
|
|
346
|
+
if (!hasMigrations(this.options.target)) {
|
|
232
347
|
throw new Error(`Target "${this.options.target.targetId}" does not support migrations`);
|
|
233
348
|
}
|
|
234
349
|
|
|
235
|
-
|
|
236
|
-
|
|
350
|
+
let contract: Contract;
|
|
351
|
+
try {
|
|
352
|
+
contract = familyInstance.validateContract(options.contract);
|
|
353
|
+
} catch (error) {
|
|
354
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
355
|
+
throw new ContractValidationError(message, error);
|
|
356
|
+
}
|
|
237
357
|
|
|
238
|
-
// Delegate to extracted dbInit operation
|
|
239
358
|
return executeDbInit({
|
|
240
359
|
driver,
|
|
241
360
|
familyInstance,
|
|
242
|
-
|
|
361
|
+
contract,
|
|
243
362
|
mode: options.mode,
|
|
244
363
|
migrations: this.options.target.migrations,
|
|
245
364
|
frameworkComponents,
|
|
365
|
+
...ifDefined('onProgress', onProgress),
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
async dbUpdate(options: DbUpdateOptions): Promise<DbUpdateResult> {
|
|
370
|
+
const { onProgress } = options;
|
|
371
|
+
await this.connectWithProgress(options.connection, 'dbUpdate', onProgress);
|
|
372
|
+
const { driver, familyInstance, frameworkComponents } = await this.ensureConnected();
|
|
373
|
+
|
|
374
|
+
if (!hasMigrations(this.options.target)) {
|
|
375
|
+
throw new Error(`Target "${this.options.target.targetId}" does not support migrations`);
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
let contract: Contract;
|
|
379
|
+
try {
|
|
380
|
+
contract = familyInstance.validateContract(options.contract);
|
|
381
|
+
} catch (error) {
|
|
382
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
383
|
+
throw new ContractValidationError(message, error);
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
return executeDbUpdate({
|
|
387
|
+
driver,
|
|
388
|
+
familyInstance,
|
|
389
|
+
contract,
|
|
390
|
+
mode: options.mode,
|
|
391
|
+
migrations: this.options.target.migrations,
|
|
392
|
+
frameworkComponents,
|
|
393
|
+
...ifDefined('acceptDataLoss', options.acceptDataLoss),
|
|
394
|
+
...ifDefined('onProgress', onProgress),
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
async readMarker(): Promise<ContractMarkerRecord | null> {
|
|
399
|
+
const { driver, familyInstance } = await this.ensureConnected();
|
|
400
|
+
return familyInstance.readMarker({ driver });
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
async migrationApply(options: MigrationApplyOptions): Promise<MigrationApplyResult> {
|
|
404
|
+
const { onProgress } = options;
|
|
405
|
+
await this.connectWithProgress(options.connection, 'migrationApply', onProgress);
|
|
406
|
+
const { driver, familyInstance, frameworkComponents } = await this.ensureConnected();
|
|
407
|
+
|
|
408
|
+
if (!hasMigrations(this.options.target)) {
|
|
409
|
+
throw new Error(`Target "${this.options.target.targetId}" does not support migrations`);
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
return executeMigrationApply({
|
|
413
|
+
driver,
|
|
414
|
+
familyInstance,
|
|
415
|
+
originHash: options.originHash,
|
|
416
|
+
destinationHash: options.destinationHash,
|
|
417
|
+
pendingMigrations: options.pendingMigrations,
|
|
418
|
+
migrations: this.options.target.migrations,
|
|
419
|
+
frameworkComponents,
|
|
420
|
+
targetId: this.options.target.targetId,
|
|
246
421
|
...(onProgress ? { onProgress } : {}),
|
|
247
422
|
});
|
|
248
423
|
}
|
|
249
424
|
|
|
250
425
|
async introspect(options?: IntrospectOptions): Promise<unknown> {
|
|
426
|
+
const onProgress = options?.onProgress;
|
|
427
|
+
await this.connectWithProgress(options?.connection, 'introspect', onProgress);
|
|
251
428
|
const { driver, familyInstance } = await this.ensureConnected();
|
|
252
429
|
|
|
253
430
|
// TODO: Pass schema option to familyInstance.introspect when schema filtering is implemented
|
|
254
431
|
const _schema = options?.schema;
|
|
255
432
|
void _schema;
|
|
256
433
|
|
|
257
|
-
|
|
434
|
+
// Emit introspect span
|
|
435
|
+
onProgress?.({
|
|
436
|
+
action: 'introspect',
|
|
437
|
+
kind: 'spanStart',
|
|
438
|
+
spanId: 'introspect',
|
|
439
|
+
label: 'Introspecting database schema...',
|
|
440
|
+
});
|
|
441
|
+
|
|
442
|
+
try {
|
|
443
|
+
const result = await familyInstance.introspect({ driver });
|
|
444
|
+
|
|
445
|
+
onProgress?.({
|
|
446
|
+
action: 'introspect',
|
|
447
|
+
kind: 'spanEnd',
|
|
448
|
+
spanId: 'introspect',
|
|
449
|
+
outcome: 'ok',
|
|
450
|
+
});
|
|
451
|
+
|
|
452
|
+
return result;
|
|
453
|
+
} catch (error) {
|
|
454
|
+
onProgress?.({
|
|
455
|
+
action: 'introspect',
|
|
456
|
+
kind: 'spanEnd',
|
|
457
|
+
spanId: 'introspect',
|
|
458
|
+
outcome: 'error',
|
|
459
|
+
});
|
|
460
|
+
throw error;
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
toSchemaView(schemaIR: unknown): CoreSchemaView | undefined {
|
|
465
|
+
this.init();
|
|
466
|
+
if (this.familyInstance && hasSchemaView(this.familyInstance)) {
|
|
467
|
+
return this.familyInstance.toSchemaView(schemaIR);
|
|
468
|
+
}
|
|
469
|
+
return undefined;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
async emit(options: EmitOptions): Promise<EmitResult> {
|
|
473
|
+
const { onProgress, contractConfig } = options;
|
|
474
|
+
|
|
475
|
+
// Ensure initialized (creates stack and family instance)
|
|
476
|
+
// emit() does NOT require a database connection
|
|
477
|
+
this.init();
|
|
478
|
+
|
|
479
|
+
if (!this.familyInstance) {
|
|
480
|
+
throw new Error('Family instance was not initialized. This is a bug.');
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
let contractRaw: unknown;
|
|
484
|
+
onProgress?.({
|
|
485
|
+
action: 'emit',
|
|
486
|
+
kind: 'spanStart',
|
|
487
|
+
spanId: 'resolveSource',
|
|
488
|
+
label: 'Resolving contract source...',
|
|
489
|
+
});
|
|
490
|
+
|
|
491
|
+
try {
|
|
492
|
+
const sourceContext = {
|
|
493
|
+
composedExtensionPacks: (this.options.extensionPacks ?? []).map((p) => p.id),
|
|
494
|
+
};
|
|
495
|
+
const providerResult = await contractConfig.sourceProvider(sourceContext);
|
|
496
|
+
if (!providerResult.ok) {
|
|
497
|
+
onProgress?.({
|
|
498
|
+
action: 'emit',
|
|
499
|
+
kind: 'spanEnd',
|
|
500
|
+
spanId: 'resolveSource',
|
|
501
|
+
outcome: 'error',
|
|
502
|
+
});
|
|
503
|
+
|
|
504
|
+
return notOk({
|
|
505
|
+
code: 'CONTRACT_SOURCE_INVALID',
|
|
506
|
+
summary: providerResult.failure.summary,
|
|
507
|
+
why: providerResult.failure.summary,
|
|
508
|
+
meta: providerResult.failure.meta,
|
|
509
|
+
diagnostics: providerResult.failure,
|
|
510
|
+
});
|
|
511
|
+
}
|
|
512
|
+
contractRaw = providerResult.value;
|
|
513
|
+
|
|
514
|
+
onProgress?.({
|
|
515
|
+
action: 'emit',
|
|
516
|
+
kind: 'spanEnd',
|
|
517
|
+
spanId: 'resolveSource',
|
|
518
|
+
outcome: 'ok',
|
|
519
|
+
});
|
|
520
|
+
} catch (error) {
|
|
521
|
+
onProgress?.({
|
|
522
|
+
action: 'emit',
|
|
523
|
+
kind: 'spanEnd',
|
|
524
|
+
spanId: 'resolveSource',
|
|
525
|
+
outcome: 'error',
|
|
526
|
+
});
|
|
527
|
+
|
|
528
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
529
|
+
return notOk({
|
|
530
|
+
code: 'CONTRACT_SOURCE_INVALID',
|
|
531
|
+
summary: 'Failed to resolve contract source',
|
|
532
|
+
why: message,
|
|
533
|
+
diagnostics: {
|
|
534
|
+
summary: 'Contract source provider threw an exception',
|
|
535
|
+
diagnostics: [
|
|
536
|
+
{
|
|
537
|
+
code: 'PROVIDER_THROW',
|
|
538
|
+
message,
|
|
539
|
+
},
|
|
540
|
+
],
|
|
541
|
+
},
|
|
542
|
+
meta: undefined,
|
|
543
|
+
});
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
// Emit contract
|
|
547
|
+
onProgress?.({
|
|
548
|
+
action: 'emit',
|
|
549
|
+
kind: 'spanStart',
|
|
550
|
+
spanId: 'emit',
|
|
551
|
+
label: 'Emitting contract...',
|
|
552
|
+
});
|
|
553
|
+
|
|
554
|
+
try {
|
|
555
|
+
const enrichedIR = enrichContract(contractRaw as Contract, this.frameworkComponents ?? []);
|
|
556
|
+
|
|
557
|
+
try {
|
|
558
|
+
this.familyInstance.validateContract(enrichedIR);
|
|
559
|
+
} catch (error) {
|
|
560
|
+
onProgress?.({
|
|
561
|
+
action: 'emit',
|
|
562
|
+
kind: 'spanEnd',
|
|
563
|
+
spanId: 'emit',
|
|
564
|
+
outcome: 'error',
|
|
565
|
+
});
|
|
566
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
567
|
+
return notOk({
|
|
568
|
+
code: 'CONTRACT_VALIDATION_FAILED',
|
|
569
|
+
summary: 'Contract validation failed',
|
|
570
|
+
why: message,
|
|
571
|
+
meta: undefined,
|
|
572
|
+
});
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
const result = await emitContractArtifacts(
|
|
576
|
+
enrichedIR,
|
|
577
|
+
this.stack!,
|
|
578
|
+
this.options.family.emission,
|
|
579
|
+
);
|
|
580
|
+
|
|
581
|
+
onProgress?.({
|
|
582
|
+
action: 'emit',
|
|
583
|
+
kind: 'spanEnd',
|
|
584
|
+
spanId: 'emit',
|
|
585
|
+
outcome: 'ok',
|
|
586
|
+
});
|
|
587
|
+
|
|
588
|
+
return ok({
|
|
589
|
+
storageHash: result.storageHash,
|
|
590
|
+
...ifDefined('executionHash', result.executionHash),
|
|
591
|
+
profileHash: result.profileHash,
|
|
592
|
+
contractJson: result.contractJson,
|
|
593
|
+
contractDts: result.contractDts,
|
|
594
|
+
});
|
|
595
|
+
} catch (error) {
|
|
596
|
+
onProgress?.({
|
|
597
|
+
action: 'emit',
|
|
598
|
+
kind: 'spanEnd',
|
|
599
|
+
spanId: 'emit',
|
|
600
|
+
outcome: 'error',
|
|
601
|
+
});
|
|
602
|
+
|
|
603
|
+
return notOk({
|
|
604
|
+
code: 'EMIT_FAILED',
|
|
605
|
+
summary: 'Failed to emit contract',
|
|
606
|
+
why: error instanceof Error ? error.message : String(error),
|
|
607
|
+
meta: undefined,
|
|
608
|
+
});
|
|
609
|
+
}
|
|
258
610
|
}
|
|
259
611
|
}
|