@prisma-next/cli 0.1.0-dev.2 → 0.1.0-dev.21
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 +172 -20
- package/dist/{chunk-4Q3MO4TK.js → chunk-VWAVGWUP.js} +2 -2
- package/dist/chunk-VWAVGWUP.js.map +1 -0
- package/dist/chunk-YDE4ILKH.js +55 -0
- package/dist/chunk-YDE4ILKH.js.map +1 -0
- package/dist/{chunk-3EODSNGS.js → chunk-ZKEJZ3NU.js} +94 -32
- package/dist/chunk-ZKEJZ3NU.js.map +1 -0
- package/dist/cli.js +469 -99
- package/dist/cli.js.map +1 -1
- package/dist/commands/contract-emit.js +2 -2
- package/dist/commands/db-init.d.ts +5 -0
- package/dist/commands/db-init.js +292 -0
- package/dist/commands/db-init.js.map +1 -0
- package/dist/commands/db-introspect.js +6 -8
- package/dist/commands/db-introspect.js.map +1 -1
- package/dist/commands/db-schema-verify.js +14 -5
- package/dist/commands/db-schema-verify.js.map +1 -1
- package/dist/commands/db-sign.js +25 -20
- package/dist/commands/db-sign.js.map +1 -1
- package/dist/commands/db-verify.js +3 -4
- package/dist/commands/db-verify.js.map +1 -1
- package/dist/index.js +4 -4
- package/package.json +18 -11
- package/dist/chunk-3EODSNGS.js.map +0 -1
- package/dist/chunk-4Q3MO4TK.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/cli.ts
|
|
4
|
-
import { Command as
|
|
4
|
+
import { Command as Command7 } from "commander";
|
|
5
5
|
|
|
6
6
|
// src/commands/contract-emit.ts
|
|
7
7
|
import { mkdirSync, writeFileSync } from "fs";
|
|
@@ -165,6 +165,15 @@ function formatErrorOutput(error, flags) {
|
|
|
165
165
|
const whereLine = error.where.line ? `${error.where.path}:${error.where.line}` : error.where.path;
|
|
166
166
|
lines.push(`${prefix}${formatDimText(` Where: ${whereLine}`)}`);
|
|
167
167
|
}
|
|
168
|
+
if (isVerbose(flags, 1) && error.meta?.["conflicts"]) {
|
|
169
|
+
const conflicts = error.meta["conflicts"];
|
|
170
|
+
if (conflicts.length > 0) {
|
|
171
|
+
lines.push(`${prefix}${formatDimText(" Conflicts:")}`);
|
|
172
|
+
for (const conflict of conflicts) {
|
|
173
|
+
lines.push(`${prefix}${formatDimText(` - [${conflict.kind}] ${conflict.summary}`)}`);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
168
177
|
if (error.docsUrl && isVerbose(flags, 1)) {
|
|
169
178
|
lines.push(formatDimText(error.docsUrl));
|
|
170
179
|
}
|
|
@@ -598,6 +607,69 @@ function formatSignOutput(result, flags) {
|
|
|
598
607
|
function formatSignJson(result) {
|
|
599
608
|
return JSON.stringify(result, null, 2);
|
|
600
609
|
}
|
|
610
|
+
function formatDbInitPlanOutput(result, flags) {
|
|
611
|
+
if (flags.quiet) {
|
|
612
|
+
return "";
|
|
613
|
+
}
|
|
614
|
+
const lines = [];
|
|
615
|
+
const prefix = createPrefix(flags);
|
|
616
|
+
const useColor = flags.color !== false;
|
|
617
|
+
const formatGreen = createColorFormatter(useColor, green);
|
|
618
|
+
const formatDimText = (text) => formatDim(useColor, text);
|
|
619
|
+
const operationCount = result.plan?.operations.length ?? 0;
|
|
620
|
+
lines.push(`${prefix}${formatGreen("\u2714")} Planned ${operationCount} operation(s)`);
|
|
621
|
+
if (result.plan?.operations && result.plan.operations.length > 0) {
|
|
622
|
+
lines.push(`${prefix}${formatDimText("\u2502")}`);
|
|
623
|
+
for (let i = 0; i < result.plan.operations.length; i++) {
|
|
624
|
+
const op = result.plan.operations[i];
|
|
625
|
+
if (!op) continue;
|
|
626
|
+
const isLast = i === result.plan.operations.length - 1;
|
|
627
|
+
const treeChar = isLast ? "\u2514" : "\u251C";
|
|
628
|
+
const opClass = formatDimText(`[${op.operationClass}]`);
|
|
629
|
+
lines.push(`${prefix}${formatDimText(treeChar)}\u2500 ${op.label} ${opClass}`);
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
if (result.plan?.destination) {
|
|
633
|
+
lines.push(`${prefix}`);
|
|
634
|
+
lines.push(
|
|
635
|
+
`${prefix}${formatDimText(`Destination hash: ${result.plan.destination.coreHash}`)}`
|
|
636
|
+
);
|
|
637
|
+
}
|
|
638
|
+
if (isVerbose(flags, 1)) {
|
|
639
|
+
lines.push(`${prefix}${formatDimText(`Total time: ${result.timings.total}ms`)}`);
|
|
640
|
+
}
|
|
641
|
+
lines.push(`${prefix}`);
|
|
642
|
+
lines.push(`${prefix}${formatDimText("This is a dry run. No changes were applied.")}`);
|
|
643
|
+
lines.push(`${prefix}${formatDimText("Run without --plan to apply changes.")}`);
|
|
644
|
+
return lines.join("\n");
|
|
645
|
+
}
|
|
646
|
+
function formatDbInitApplyOutput(result, flags) {
|
|
647
|
+
if (flags.quiet) {
|
|
648
|
+
return "";
|
|
649
|
+
}
|
|
650
|
+
const lines = [];
|
|
651
|
+
const prefix = createPrefix(flags);
|
|
652
|
+
const useColor = flags.color !== false;
|
|
653
|
+
const formatGreen = createColorFormatter(useColor, green);
|
|
654
|
+
const formatDimText = (text) => formatDim(useColor, text);
|
|
655
|
+
if (result.ok) {
|
|
656
|
+
const executed = result.execution?.operationsExecuted ?? 0;
|
|
657
|
+
lines.push(`${prefix}${formatGreen("\u2714")} Applied ${executed} operation(s)`);
|
|
658
|
+
if (result.marker) {
|
|
659
|
+
lines.push(`${prefix}${formatDimText(` Marker written: ${result.marker.coreHash}`)}`);
|
|
660
|
+
if (result.marker.profileHash) {
|
|
661
|
+
lines.push(`${prefix}${formatDimText(` Profile hash: ${result.marker.profileHash}`)}`);
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
if (isVerbose(flags, 1)) {
|
|
665
|
+
lines.push(`${prefix}${formatDimText(` Total time: ${result.timings.total}ms`)}`);
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
return lines.join("\n");
|
|
669
|
+
}
|
|
670
|
+
function formatDbInitJson(result) {
|
|
671
|
+
return JSON.stringify(result, null, 2);
|
|
672
|
+
}
|
|
601
673
|
var LEFT_COLUMN_WIDTH = 20;
|
|
602
674
|
var RIGHT_COLUMN_MIN_WIDTH = 40;
|
|
603
675
|
var RIGHT_COLUMN_MAX_WIDTH = 90;
|
|
@@ -921,8 +993,10 @@ import {
|
|
|
921
993
|
errorFileNotFound,
|
|
922
994
|
errorHashMismatch,
|
|
923
995
|
errorMarkerMissing,
|
|
996
|
+
errorMigrationPlanningFailed,
|
|
924
997
|
errorQueryRunnerFactoryRequired,
|
|
925
998
|
errorRuntime,
|
|
999
|
+
errorTargetMigrationNotSupported,
|
|
926
1000
|
errorTargetMismatch,
|
|
927
1001
|
errorUnexpected as errorUnexpected2
|
|
928
1002
|
} from "@prisma-next/core-control-plane/errors";
|
|
@@ -967,46 +1041,23 @@ function handleResult(result, flags, onSuccess) {
|
|
|
967
1041
|
// src/utils/spinner.ts
|
|
968
1042
|
import ora from "ora";
|
|
969
1043
|
async function withSpinner(operation, options) {
|
|
970
|
-
const { message, flags
|
|
1044
|
+
const { message, flags } = options;
|
|
971
1045
|
const shouldShowSpinner = !flags.quiet && flags.json !== "object" && process.stdout.isTTY;
|
|
972
1046
|
if (!shouldShowSpinner) {
|
|
973
1047
|
return operation();
|
|
974
1048
|
}
|
|
975
1049
|
const startTime = Date.now();
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
if (!operationCompleted) {
|
|
981
|
-
spinner = ora({
|
|
982
|
-
text: message,
|
|
983
|
-
color: flags.color !== false ? "cyan" : false
|
|
984
|
-
}).start();
|
|
985
|
-
}
|
|
986
|
-
}, delayThreshold);
|
|
1050
|
+
const spinner = ora({
|
|
1051
|
+
text: message,
|
|
1052
|
+
color: flags.color !== false ? "cyan" : false
|
|
1053
|
+
}).start();
|
|
987
1054
|
try {
|
|
988
1055
|
const result = await operation();
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
clearTimeout(timeoutId);
|
|
992
|
-
timeoutId = null;
|
|
993
|
-
}
|
|
994
|
-
if (spinner !== null) {
|
|
995
|
-
const elapsed = Date.now() - startTime;
|
|
996
|
-
spinner.succeed(`${message} (${elapsed}ms)`);
|
|
997
|
-
}
|
|
1056
|
+
const elapsed = Date.now() - startTime;
|
|
1057
|
+
spinner.succeed(`${message} (${elapsed}ms)`);
|
|
998
1058
|
return result;
|
|
999
1059
|
} catch (error) {
|
|
1000
|
-
|
|
1001
|
-
if (timeoutId) {
|
|
1002
|
-
clearTimeout(timeoutId);
|
|
1003
|
-
timeoutId = null;
|
|
1004
|
-
}
|
|
1005
|
-
if (spinner !== null) {
|
|
1006
|
-
spinner.fail(
|
|
1007
|
-
`${message} failed: ${error instanceof Error ? error.message : String(error)}`
|
|
1008
|
-
);
|
|
1009
|
-
}
|
|
1060
|
+
spinner.fail(`${message} failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
1010
1061
|
throw error;
|
|
1011
1062
|
}
|
|
1012
1063
|
}
|
|
@@ -1121,18 +1172,330 @@ function createContractEmitCommand() {
|
|
|
1121
1172
|
return command;
|
|
1122
1173
|
}
|
|
1123
1174
|
|
|
1124
|
-
// src/commands/db-
|
|
1175
|
+
// src/commands/db-init.ts
|
|
1125
1176
|
import { readFile } from "fs/promises";
|
|
1126
1177
|
import { relative as relative3, resolve as resolve3 } from "path";
|
|
1178
|
+
import { Command as Command2 } from "commander";
|
|
1179
|
+
|
|
1180
|
+
// src/utils/framework-components.ts
|
|
1181
|
+
function assertFrameworkComponentsCompatible(expectedFamilyId, expectedTargetId, frameworkComponents) {
|
|
1182
|
+
for (let i = 0; i < frameworkComponents.length; i++) {
|
|
1183
|
+
const component = frameworkComponents[i];
|
|
1184
|
+
if (typeof component !== "object" || component === null) {
|
|
1185
|
+
throw errorConfigValidation("frameworkComponents[]", {
|
|
1186
|
+
why: `Framework component at index ${i} must be an object`
|
|
1187
|
+
});
|
|
1188
|
+
}
|
|
1189
|
+
const record = component;
|
|
1190
|
+
if (!Object.hasOwn(record, "kind")) {
|
|
1191
|
+
throw errorConfigValidation("frameworkComponents[].kind", {
|
|
1192
|
+
why: `Framework component at index ${i} must have 'kind' property`
|
|
1193
|
+
});
|
|
1194
|
+
}
|
|
1195
|
+
const kind = record["kind"];
|
|
1196
|
+
if (kind !== "target" && kind !== "adapter" && kind !== "extension" && kind !== "driver") {
|
|
1197
|
+
throw errorConfigValidation("frameworkComponents[].kind", {
|
|
1198
|
+
why: `Framework component at index ${i} has invalid kind '${String(kind)}' (must be 'target', 'adapter', 'extension', or 'driver')`
|
|
1199
|
+
});
|
|
1200
|
+
}
|
|
1201
|
+
if (!Object.hasOwn(record, "familyId")) {
|
|
1202
|
+
throw errorConfigValidation("frameworkComponents[].familyId", {
|
|
1203
|
+
why: `Framework component at index ${i} (kind: ${String(kind)}) must have 'familyId' property`
|
|
1204
|
+
});
|
|
1205
|
+
}
|
|
1206
|
+
const familyId = record["familyId"];
|
|
1207
|
+
if (familyId !== expectedFamilyId) {
|
|
1208
|
+
throw errorConfigValidation("frameworkComponents[].familyId", {
|
|
1209
|
+
why: `Framework component at index ${i} (kind: ${String(kind)}) has familyId '${String(familyId)}' but expected '${expectedFamilyId}'`
|
|
1210
|
+
});
|
|
1211
|
+
}
|
|
1212
|
+
if (!Object.hasOwn(record, "targetId")) {
|
|
1213
|
+
throw errorConfigValidation("frameworkComponents[].targetId", {
|
|
1214
|
+
why: `Framework component at index ${i} (kind: ${String(kind)}) must have 'targetId' property`
|
|
1215
|
+
});
|
|
1216
|
+
}
|
|
1217
|
+
const targetId = record["targetId"];
|
|
1218
|
+
if (targetId !== expectedTargetId) {
|
|
1219
|
+
throw errorConfigValidation("frameworkComponents[].targetId", {
|
|
1220
|
+
why: `Framework component at index ${i} (kind: ${String(kind)}) has targetId '${String(targetId)}' but expected '${expectedTargetId}'`
|
|
1221
|
+
});
|
|
1222
|
+
}
|
|
1223
|
+
}
|
|
1224
|
+
return frameworkComponents;
|
|
1225
|
+
}
|
|
1226
|
+
|
|
1227
|
+
// src/commands/db-init.ts
|
|
1228
|
+
function createDbInitCommand() {
|
|
1229
|
+
const command = new Command2("init");
|
|
1230
|
+
setCommandDescriptions(
|
|
1231
|
+
command,
|
|
1232
|
+
"Bootstrap a database to match the current contract and write the contract marker",
|
|
1233
|
+
"Initializes a database to match your emitted contract using additive-only operations.\nCreates any missing tables, columns, indexes, and constraints defined in your contract.\nLeaves existing compatible structures in place, surfaces conflicts when destructive changes\nwould be required, and writes a contract marker to track the database state. Use --plan to\npreview changes without applying."
|
|
1234
|
+
);
|
|
1235
|
+
command.configureHelp({
|
|
1236
|
+
formatHelp: (cmd) => {
|
|
1237
|
+
const flags = parseGlobalFlags({});
|
|
1238
|
+
return formatCommandHelp({ command: cmd, flags });
|
|
1239
|
+
}
|
|
1240
|
+
}).option("--db <url>", "Database connection string").option("--config <path>", "Path to prisma-next.config.ts").option("--plan", "Preview planned operations without applying", false).option("--json [format]", "Output as JSON (object or ndjson)", false).option("-q, --quiet", "Quiet mode: errors only").option("-v, --verbose", "Verbose output: debug info, timings").option("-vv, --trace", "Trace output: deep internals, stack traces").option("--timestamps", "Add timestamps to output").option("--color", "Force color output").option("--no-color", "Disable color output").action(async (options) => {
|
|
1241
|
+
const flags = parseGlobalFlags(options);
|
|
1242
|
+
const startTime = Date.now();
|
|
1243
|
+
const result = await performAction(async () => {
|
|
1244
|
+
const config = await loadConfig(options.config);
|
|
1245
|
+
const configPath = options.config ? relative3(process.cwd(), resolve3(options.config)) : "prisma-next.config.ts";
|
|
1246
|
+
const contractPathAbsolute = config.contract?.output ? resolve3(config.contract.output) : resolve3("src/prisma/contract.json");
|
|
1247
|
+
const contractPath = relative3(process.cwd(), contractPathAbsolute);
|
|
1248
|
+
if (flags.json !== "object" && !flags.quiet) {
|
|
1249
|
+
const details = [
|
|
1250
|
+
{ label: "config", value: configPath },
|
|
1251
|
+
{ label: "contract", value: contractPath }
|
|
1252
|
+
];
|
|
1253
|
+
if (options.db) {
|
|
1254
|
+
details.push({ label: "database", value: options.db });
|
|
1255
|
+
}
|
|
1256
|
+
if (options.plan) {
|
|
1257
|
+
details.push({ label: "mode", value: "plan (dry run)" });
|
|
1258
|
+
}
|
|
1259
|
+
const header = formatStyledHeader({
|
|
1260
|
+
command: "db init",
|
|
1261
|
+
description: "Bootstrap a database to match the current contract",
|
|
1262
|
+
url: "https://pris.ly/db-init",
|
|
1263
|
+
details,
|
|
1264
|
+
flags
|
|
1265
|
+
});
|
|
1266
|
+
console.log(header);
|
|
1267
|
+
}
|
|
1268
|
+
let contractJsonContent;
|
|
1269
|
+
try {
|
|
1270
|
+
contractJsonContent = await readFile(contractPathAbsolute, "utf-8");
|
|
1271
|
+
} catch (error) {
|
|
1272
|
+
if (error instanceof Error && error.code === "ENOENT") {
|
|
1273
|
+
throw errorFileNotFound(contractPathAbsolute, {
|
|
1274
|
+
why: `Contract file not found at ${contractPathAbsolute}`
|
|
1275
|
+
});
|
|
1276
|
+
}
|
|
1277
|
+
throw errorUnexpected2(error instanceof Error ? error.message : String(error), {
|
|
1278
|
+
why: `Failed to read contract file: ${error instanceof Error ? error.message : String(error)}`
|
|
1279
|
+
});
|
|
1280
|
+
}
|
|
1281
|
+
let contractJson;
|
|
1282
|
+
try {
|
|
1283
|
+
contractJson = JSON.parse(contractJsonContent);
|
|
1284
|
+
} catch (error) {
|
|
1285
|
+
throw errorUnexpected2(error instanceof Error ? error.message : String(error), {
|
|
1286
|
+
why: `Failed to parse contract JSON at ${contractPathAbsolute}: ${error instanceof Error ? error.message : String(error)}`
|
|
1287
|
+
});
|
|
1288
|
+
}
|
|
1289
|
+
const dbUrl = options.db ?? config.db?.url;
|
|
1290
|
+
if (!dbUrl) {
|
|
1291
|
+
throw errorDatabaseUrlRequired({ why: "Database URL is required for db init" });
|
|
1292
|
+
}
|
|
1293
|
+
if (!config.driver) {
|
|
1294
|
+
throw errorDriverRequired({ why: "Config.driver is required for db init" });
|
|
1295
|
+
}
|
|
1296
|
+
const driverDescriptor = config.driver;
|
|
1297
|
+
if (!config.target.migrations) {
|
|
1298
|
+
throw errorTargetMigrationNotSupported({
|
|
1299
|
+
why: `Target "${config.target.id}" does not support migrations`
|
|
1300
|
+
});
|
|
1301
|
+
}
|
|
1302
|
+
const migrations = config.target.migrations;
|
|
1303
|
+
const driver = await withSpinner(() => driverDescriptor.create(dbUrl), {
|
|
1304
|
+
message: "Connecting to database...",
|
|
1305
|
+
flags
|
|
1306
|
+
});
|
|
1307
|
+
try {
|
|
1308
|
+
const familyInstance = config.family.create({
|
|
1309
|
+
target: config.target,
|
|
1310
|
+
adapter: config.adapter,
|
|
1311
|
+
driver: driverDescriptor,
|
|
1312
|
+
extensions: config.extensions ?? []
|
|
1313
|
+
});
|
|
1314
|
+
const rawComponents = [config.target, config.adapter, ...config.extensions ?? []];
|
|
1315
|
+
const frameworkComponents = assertFrameworkComponentsCompatible(
|
|
1316
|
+
config.family.familyId,
|
|
1317
|
+
config.target.targetId,
|
|
1318
|
+
rawComponents
|
|
1319
|
+
);
|
|
1320
|
+
const contractIR = familyInstance.validateContractIR(contractJson);
|
|
1321
|
+
const planner = migrations.createPlanner(familyInstance);
|
|
1322
|
+
const runner = migrations.createRunner(familyInstance);
|
|
1323
|
+
const schemaIR = await withSpinner(() => familyInstance.introspect({ driver }), {
|
|
1324
|
+
message: "Introspecting database schema...",
|
|
1325
|
+
flags
|
|
1326
|
+
});
|
|
1327
|
+
const policy = { allowedOperationClasses: ["additive"] };
|
|
1328
|
+
const plannerResult = await withSpinner(
|
|
1329
|
+
async () => planner.plan({
|
|
1330
|
+
contract: contractIR,
|
|
1331
|
+
schema: schemaIR,
|
|
1332
|
+
policy,
|
|
1333
|
+
frameworkComponents
|
|
1334
|
+
}),
|
|
1335
|
+
{
|
|
1336
|
+
message: "Planning migration...",
|
|
1337
|
+
flags
|
|
1338
|
+
}
|
|
1339
|
+
);
|
|
1340
|
+
if (plannerResult.kind === "failure") {
|
|
1341
|
+
throw errorMigrationPlanningFailed({ conflicts: plannerResult.conflicts });
|
|
1342
|
+
}
|
|
1343
|
+
const migrationPlan = plannerResult.plan;
|
|
1344
|
+
const existingMarker = await familyInstance.readMarker({ driver });
|
|
1345
|
+
if (existingMarker) {
|
|
1346
|
+
const markerMatchesDestination = existingMarker.coreHash === migrationPlan.destination.coreHash && (!migrationPlan.destination.profileHash || existingMarker.profileHash === migrationPlan.destination.profileHash);
|
|
1347
|
+
if (markerMatchesDestination) {
|
|
1348
|
+
const dbInitResult2 = {
|
|
1349
|
+
ok: true,
|
|
1350
|
+
mode: options.plan ? "plan" : "apply",
|
|
1351
|
+
plan: {
|
|
1352
|
+
targetId: migrationPlan.targetId,
|
|
1353
|
+
destination: migrationPlan.destination,
|
|
1354
|
+
operations: []
|
|
1355
|
+
},
|
|
1356
|
+
...options.plan ? {} : {
|
|
1357
|
+
execution: { operationsPlanned: 0, operationsExecuted: 0 },
|
|
1358
|
+
marker: {
|
|
1359
|
+
coreHash: existingMarker.coreHash,
|
|
1360
|
+
profileHash: existingMarker.profileHash
|
|
1361
|
+
}
|
|
1362
|
+
},
|
|
1363
|
+
summary: "Database already at target contract state",
|
|
1364
|
+
timings: { total: Date.now() - startTime }
|
|
1365
|
+
};
|
|
1366
|
+
return dbInitResult2;
|
|
1367
|
+
}
|
|
1368
|
+
const coreHashMismatch = existingMarker.coreHash !== migrationPlan.destination.coreHash;
|
|
1369
|
+
const profileHashMismatch = migrationPlan.destination.profileHash && existingMarker.profileHash !== migrationPlan.destination.profileHash;
|
|
1370
|
+
const mismatchParts = [];
|
|
1371
|
+
if (coreHashMismatch) {
|
|
1372
|
+
mismatchParts.push(
|
|
1373
|
+
`coreHash (marker: ${existingMarker.coreHash}, destination: ${migrationPlan.destination.coreHash})`
|
|
1374
|
+
);
|
|
1375
|
+
}
|
|
1376
|
+
if (profileHashMismatch) {
|
|
1377
|
+
mismatchParts.push(
|
|
1378
|
+
`profileHash (marker: ${existingMarker.profileHash}, destination: ${migrationPlan.destination.profileHash})`
|
|
1379
|
+
);
|
|
1380
|
+
}
|
|
1381
|
+
throw errorRuntime(
|
|
1382
|
+
`Existing contract marker does not match plan destination. Mismatch in ${mismatchParts.join(" and ")}.`,
|
|
1383
|
+
{
|
|
1384
|
+
why: "Database has an existing contract marker that does not match the target contract",
|
|
1385
|
+
fix: "Use `prisma-next db migrate` to migrate from the existing contract, or drop the database and re-run `db init`",
|
|
1386
|
+
meta: {
|
|
1387
|
+
code: "MARKER_ORIGIN_MISMATCH",
|
|
1388
|
+
markerCoreHash: existingMarker.coreHash,
|
|
1389
|
+
destinationCoreHash: migrationPlan.destination.coreHash,
|
|
1390
|
+
...existingMarker.profileHash ? { markerProfileHash: existingMarker.profileHash } : {},
|
|
1391
|
+
...migrationPlan.destination.profileHash ? { destinationProfileHash: migrationPlan.destination.profileHash } : {}
|
|
1392
|
+
}
|
|
1393
|
+
}
|
|
1394
|
+
);
|
|
1395
|
+
}
|
|
1396
|
+
if (options.plan) {
|
|
1397
|
+
const dbInitResult2 = {
|
|
1398
|
+
ok: true,
|
|
1399
|
+
mode: "plan",
|
|
1400
|
+
plan: {
|
|
1401
|
+
targetId: migrationPlan.targetId,
|
|
1402
|
+
destination: migrationPlan.destination,
|
|
1403
|
+
operations: migrationPlan.operations.map((op) => ({
|
|
1404
|
+
id: op.id,
|
|
1405
|
+
label: op.label,
|
|
1406
|
+
operationClass: op.operationClass
|
|
1407
|
+
}))
|
|
1408
|
+
},
|
|
1409
|
+
summary: `Planned ${migrationPlan.operations.length} operation(s)`,
|
|
1410
|
+
timings: { total: Date.now() - startTime }
|
|
1411
|
+
};
|
|
1412
|
+
return dbInitResult2;
|
|
1413
|
+
}
|
|
1414
|
+
const callbacks = {
|
|
1415
|
+
onOperationStart: (op) => {
|
|
1416
|
+
if (!flags.quiet && flags.json !== "object") {
|
|
1417
|
+
console.log(` \u2192 ${op.label}...`);
|
|
1418
|
+
}
|
|
1419
|
+
},
|
|
1420
|
+
onOperationComplete: (_op) => {
|
|
1421
|
+
}
|
|
1422
|
+
};
|
|
1423
|
+
const runnerResult = await withSpinner(
|
|
1424
|
+
() => runner.execute({
|
|
1425
|
+
plan: migrationPlan,
|
|
1426
|
+
driver,
|
|
1427
|
+
destinationContract: contractIR,
|
|
1428
|
+
policy,
|
|
1429
|
+
callbacks,
|
|
1430
|
+
frameworkComponents
|
|
1431
|
+
}),
|
|
1432
|
+
{
|
|
1433
|
+
message: "Applying migration plan...",
|
|
1434
|
+
flags
|
|
1435
|
+
}
|
|
1436
|
+
);
|
|
1437
|
+
if (!runnerResult.ok) {
|
|
1438
|
+
throw errorRuntime(runnerResult.failure.summary, {
|
|
1439
|
+
why: runnerResult.failure.why ?? `Migration runner failed: ${runnerResult.failure.code}`,
|
|
1440
|
+
meta: { code: runnerResult.failure.code }
|
|
1441
|
+
});
|
|
1442
|
+
}
|
|
1443
|
+
const execution = runnerResult.value;
|
|
1444
|
+
const dbInitResult = {
|
|
1445
|
+
ok: true,
|
|
1446
|
+
mode: "apply",
|
|
1447
|
+
plan: {
|
|
1448
|
+
targetId: migrationPlan.targetId,
|
|
1449
|
+
destination: migrationPlan.destination,
|
|
1450
|
+
operations: migrationPlan.operations.map((op) => ({
|
|
1451
|
+
id: op.id,
|
|
1452
|
+
label: op.label,
|
|
1453
|
+
operationClass: op.operationClass
|
|
1454
|
+
}))
|
|
1455
|
+
},
|
|
1456
|
+
execution: {
|
|
1457
|
+
operationsPlanned: execution.operationsPlanned,
|
|
1458
|
+
operationsExecuted: execution.operationsExecuted
|
|
1459
|
+
},
|
|
1460
|
+
marker: migrationPlan.destination.profileHash ? {
|
|
1461
|
+
coreHash: migrationPlan.destination.coreHash,
|
|
1462
|
+
profileHash: migrationPlan.destination.profileHash
|
|
1463
|
+
} : { coreHash: migrationPlan.destination.coreHash },
|
|
1464
|
+
summary: `Applied ${execution.operationsExecuted} operation(s), marker written`,
|
|
1465
|
+
timings: { total: Date.now() - startTime }
|
|
1466
|
+
};
|
|
1467
|
+
return dbInitResult;
|
|
1468
|
+
} finally {
|
|
1469
|
+
await driver.close();
|
|
1470
|
+
}
|
|
1471
|
+
});
|
|
1472
|
+
const exitCode = handleResult(result, flags, (dbInitResult) => {
|
|
1473
|
+
if (flags.json === "object") {
|
|
1474
|
+
console.log(formatDbInitJson(dbInitResult));
|
|
1475
|
+
} else {
|
|
1476
|
+
const output = dbInitResult.mode === "plan" ? formatDbInitPlanOutput(dbInitResult, flags) : formatDbInitApplyOutput(dbInitResult, flags);
|
|
1477
|
+
if (output) {
|
|
1478
|
+
console.log(output);
|
|
1479
|
+
}
|
|
1480
|
+
}
|
|
1481
|
+
});
|
|
1482
|
+
process.exit(exitCode);
|
|
1483
|
+
});
|
|
1484
|
+
return command;
|
|
1485
|
+
}
|
|
1486
|
+
|
|
1487
|
+
// src/commands/db-introspect.ts
|
|
1488
|
+
import { readFile as readFile2 } from "fs/promises";
|
|
1489
|
+
import { relative as relative4, resolve as resolve4 } from "path";
|
|
1127
1490
|
import {
|
|
1128
1491
|
errorDatabaseUrlRequired as errorDatabaseUrlRequired2,
|
|
1129
1492
|
errorDriverRequired as errorDriverRequired2,
|
|
1130
1493
|
errorRuntime as errorRuntime2,
|
|
1131
1494
|
errorUnexpected as errorUnexpected3
|
|
1132
1495
|
} from "@prisma-next/core-control-plane/errors";
|
|
1133
|
-
import { Command as
|
|
1496
|
+
import { Command as Command3 } from "commander";
|
|
1134
1497
|
function createDbIntrospectCommand() {
|
|
1135
|
-
const command = new
|
|
1498
|
+
const command = new Command3("introspect");
|
|
1136
1499
|
setCommandDescriptions(
|
|
1137
1500
|
command,
|
|
1138
1501
|
"Inspect the database schema",
|
|
@@ -1148,14 +1511,13 @@ function createDbIntrospectCommand() {
|
|
|
1148
1511
|
const result = await performAction(async () => {
|
|
1149
1512
|
const startTime = Date.now();
|
|
1150
1513
|
const config = await loadConfig(options.config);
|
|
1151
|
-
const configPath = options.config ?
|
|
1514
|
+
const configPath = options.config ? relative4(process.cwd(), resolve4(options.config)) : "prisma-next.config.ts";
|
|
1152
1515
|
let contractIR;
|
|
1153
1516
|
if (config.contract?.output) {
|
|
1154
|
-
const contractPath =
|
|
1517
|
+
const contractPath = resolve4(config.contract.output);
|
|
1155
1518
|
try {
|
|
1156
|
-
const contractJsonContent = await
|
|
1157
|
-
|
|
1158
|
-
contractIR = contractJson;
|
|
1519
|
+
const contractJsonContent = await readFile2(contractPath, "utf-8");
|
|
1520
|
+
contractIR = JSON.parse(contractJsonContent);
|
|
1159
1521
|
} catch (error) {
|
|
1160
1522
|
if (error instanceof Error && error.code !== "ENOENT") {
|
|
1161
1523
|
throw errorUnexpected3(error.message, {
|
|
@@ -1203,14 +1565,13 @@ function createDbIntrospectCommand() {
|
|
|
1203
1565
|
driver: driverDescriptor,
|
|
1204
1566
|
extensions: config.extensions ?? []
|
|
1205
1567
|
});
|
|
1206
|
-
const typedFamilyInstance = familyInstance;
|
|
1207
1568
|
if (contractIR) {
|
|
1208
|
-
contractIR =
|
|
1569
|
+
contractIR = familyInstance.validateContractIR(contractIR);
|
|
1209
1570
|
}
|
|
1210
1571
|
let schemaIR;
|
|
1211
1572
|
try {
|
|
1212
1573
|
schemaIR = await withSpinner(
|
|
1213
|
-
() =>
|
|
1574
|
+
() => familyInstance.introspect({
|
|
1214
1575
|
driver,
|
|
1215
1576
|
contractIR
|
|
1216
1577
|
}),
|
|
@@ -1225,9 +1586,9 @@ function createDbIntrospectCommand() {
|
|
|
1225
1586
|
});
|
|
1226
1587
|
}
|
|
1227
1588
|
let schemaView;
|
|
1228
|
-
if (
|
|
1589
|
+
if (familyInstance.toSchemaView) {
|
|
1229
1590
|
try {
|
|
1230
|
-
schemaView =
|
|
1591
|
+
schemaView = familyInstance.toSchemaView(schemaIR);
|
|
1231
1592
|
} catch (error) {
|
|
1232
1593
|
if (flags.verbose) {
|
|
1233
1594
|
console.error(
|
|
@@ -1285,8 +1646,8 @@ function createDbIntrospectCommand() {
|
|
|
1285
1646
|
}
|
|
1286
1647
|
|
|
1287
1648
|
// src/commands/db-schema-verify.ts
|
|
1288
|
-
import { readFile as
|
|
1289
|
-
import { relative as
|
|
1649
|
+
import { readFile as readFile3 } from "fs/promises";
|
|
1650
|
+
import { relative as relative5, resolve as resolve5 } from "path";
|
|
1290
1651
|
import {
|
|
1291
1652
|
errorDatabaseUrlRequired as errorDatabaseUrlRequired3,
|
|
1292
1653
|
errorDriverRequired as errorDriverRequired3,
|
|
@@ -1294,9 +1655,9 @@ import {
|
|
|
1294
1655
|
errorRuntime as errorRuntime3,
|
|
1295
1656
|
errorUnexpected as errorUnexpected4
|
|
1296
1657
|
} from "@prisma-next/core-control-plane/errors";
|
|
1297
|
-
import { Command as
|
|
1658
|
+
import { Command as Command4 } from "commander";
|
|
1298
1659
|
function createDbSchemaVerifyCommand() {
|
|
1299
|
-
const command = new
|
|
1660
|
+
const command = new Command4("schema-verify");
|
|
1300
1661
|
setCommandDescriptions(
|
|
1301
1662
|
command,
|
|
1302
1663
|
"Check whether the database schema satisfies your contract",
|
|
@@ -1311,9 +1672,9 @@ function createDbSchemaVerifyCommand() {
|
|
|
1311
1672
|
const flags = parseGlobalFlags(options);
|
|
1312
1673
|
const result = await performAction(async () => {
|
|
1313
1674
|
const config = await loadConfig(options.config);
|
|
1314
|
-
const configPath = options.config ?
|
|
1315
|
-
const contractPathAbsolute = config.contract?.output ?
|
|
1316
|
-
const contractPath =
|
|
1675
|
+
const configPath = options.config ? relative5(process.cwd(), resolve5(options.config)) : "prisma-next.config.ts";
|
|
1676
|
+
const contractPathAbsolute = config.contract?.output ? resolve5(config.contract.output) : resolve5("src/prisma/contract.json");
|
|
1677
|
+
const contractPath = relative5(process.cwd(), contractPathAbsolute);
|
|
1317
1678
|
if (flags.json !== "object" && !flags.quiet) {
|
|
1318
1679
|
const details = [
|
|
1319
1680
|
{ label: "config", value: configPath },
|
|
@@ -1333,7 +1694,7 @@ function createDbSchemaVerifyCommand() {
|
|
|
1333
1694
|
}
|
|
1334
1695
|
let contractJsonContent;
|
|
1335
1696
|
try {
|
|
1336
|
-
contractJsonContent = await
|
|
1697
|
+
contractJsonContent = await readFile3(contractPathAbsolute, "utf-8");
|
|
1337
1698
|
} catch (error) {
|
|
1338
1699
|
if (error instanceof Error && error.code === "ENOENT") {
|
|
1339
1700
|
throw errorFileNotFound2(contractPathAbsolute, {
|
|
@@ -1364,17 +1725,23 @@ function createDbSchemaVerifyCommand() {
|
|
|
1364
1725
|
driver: driverDescriptor,
|
|
1365
1726
|
extensions: config.extensions ?? []
|
|
1366
1727
|
});
|
|
1367
|
-
const
|
|
1368
|
-
const
|
|
1728
|
+
const rawComponents = [config.target, config.adapter, ...config.extensions ?? []];
|
|
1729
|
+
const frameworkComponents = assertFrameworkComponentsCompatible(
|
|
1730
|
+
config.family.familyId,
|
|
1731
|
+
config.target.targetId,
|
|
1732
|
+
rawComponents
|
|
1733
|
+
);
|
|
1734
|
+
const contractIR = familyInstance.validateContractIR(contractJson);
|
|
1369
1735
|
let schemaVerifyResult;
|
|
1370
1736
|
try {
|
|
1371
1737
|
schemaVerifyResult = await withSpinner(
|
|
1372
|
-
() =>
|
|
1738
|
+
() => familyInstance.schemaVerify({
|
|
1373
1739
|
driver,
|
|
1374
1740
|
contractIR,
|
|
1375
1741
|
strict: options.strict ?? false,
|
|
1376
1742
|
contractPath: contractPathAbsolute,
|
|
1377
|
-
configPath
|
|
1743
|
+
configPath,
|
|
1744
|
+
frameworkComponents
|
|
1378
1745
|
}),
|
|
1379
1746
|
{
|
|
1380
1747
|
message: "Verifying database schema...",
|
|
@@ -1414,8 +1781,8 @@ function createDbSchemaVerifyCommand() {
|
|
|
1414
1781
|
}
|
|
1415
1782
|
|
|
1416
1783
|
// src/commands/db-sign.ts
|
|
1417
|
-
import { readFile as
|
|
1418
|
-
import { relative as
|
|
1784
|
+
import { readFile as readFile4 } from "fs/promises";
|
|
1785
|
+
import { relative as relative6, resolve as resolve6 } from "path";
|
|
1419
1786
|
import {
|
|
1420
1787
|
errorDatabaseUrlRequired as errorDatabaseUrlRequired4,
|
|
1421
1788
|
errorDriverRequired as errorDriverRequired4,
|
|
@@ -1423,9 +1790,9 @@ import {
|
|
|
1423
1790
|
errorRuntime as errorRuntime4,
|
|
1424
1791
|
errorUnexpected as errorUnexpected5
|
|
1425
1792
|
} from "@prisma-next/core-control-plane/errors";
|
|
1426
|
-
import { Command as
|
|
1793
|
+
import { Command as Command5 } from "commander";
|
|
1427
1794
|
function createDbSignCommand() {
|
|
1428
|
-
const command = new
|
|
1795
|
+
const command = new Command5("sign");
|
|
1429
1796
|
setCommandDescriptions(
|
|
1430
1797
|
command,
|
|
1431
1798
|
"Sign the database with your contract so you can safely run queries",
|
|
@@ -1440,9 +1807,9 @@ function createDbSignCommand() {
|
|
|
1440
1807
|
const flags = parseGlobalFlags(options);
|
|
1441
1808
|
const result = await performAction(async () => {
|
|
1442
1809
|
const config = await loadConfig(options.config);
|
|
1443
|
-
const configPath = options.config ?
|
|
1444
|
-
const contractPathAbsolute = config.contract?.output ?
|
|
1445
|
-
const contractPath =
|
|
1810
|
+
const configPath = options.config ? relative6(process.cwd(), resolve6(options.config)) : "prisma-next.config.ts";
|
|
1811
|
+
const contractPathAbsolute = config.contract?.output ? resolve6(config.contract.output) : resolve6("src/prisma/contract.json");
|
|
1812
|
+
const contractPath = relative6(process.cwd(), contractPathAbsolute);
|
|
1446
1813
|
if (flags.json !== "object" && !flags.quiet) {
|
|
1447
1814
|
const details = [
|
|
1448
1815
|
{ label: "config", value: configPath },
|
|
@@ -1462,7 +1829,7 @@ function createDbSignCommand() {
|
|
|
1462
1829
|
}
|
|
1463
1830
|
let contractJsonContent;
|
|
1464
1831
|
try {
|
|
1465
|
-
contractJsonContent = await
|
|
1832
|
+
contractJsonContent = await readFile4(contractPathAbsolute, "utf-8");
|
|
1466
1833
|
} catch (error) {
|
|
1467
1834
|
if (error instanceof Error && error.code === "ENOENT") {
|
|
1468
1835
|
throw errorFileNotFound3(contractPathAbsolute, {
|
|
@@ -1490,20 +1857,24 @@ function createDbSignCommand() {
|
|
|
1490
1857
|
driver: driverDescriptor,
|
|
1491
1858
|
extensions: config.extensions ?? []
|
|
1492
1859
|
});
|
|
1493
|
-
const
|
|
1494
|
-
const
|
|
1860
|
+
const rawComponents = [config.target, config.adapter, ...config.extensions ?? []];
|
|
1861
|
+
const frameworkComponents = assertFrameworkComponentsCompatible(
|
|
1862
|
+
config.family.familyId,
|
|
1863
|
+
config.target.targetId,
|
|
1864
|
+
rawComponents
|
|
1865
|
+
);
|
|
1866
|
+
const contractIR = familyInstance.validateContractIR(contractJson);
|
|
1495
1867
|
let schemaVerifyResult;
|
|
1496
1868
|
try {
|
|
1497
1869
|
schemaVerifyResult = await withSpinner(
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
},
|
|
1870
|
+
() => familyInstance.schemaVerify({
|
|
1871
|
+
driver,
|
|
1872
|
+
contractIR,
|
|
1873
|
+
strict: false,
|
|
1874
|
+
contractPath: contractPathAbsolute,
|
|
1875
|
+
configPath,
|
|
1876
|
+
frameworkComponents
|
|
1877
|
+
}),
|
|
1507
1878
|
{
|
|
1508
1879
|
message: "Verifying database satisfies contract",
|
|
1509
1880
|
flags
|
|
@@ -1520,14 +1891,12 @@ function createDbSignCommand() {
|
|
|
1520
1891
|
let signResult;
|
|
1521
1892
|
try {
|
|
1522
1893
|
signResult = await withSpinner(
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
});
|
|
1530
|
-
},
|
|
1894
|
+
() => familyInstance.sign({
|
|
1895
|
+
driver,
|
|
1896
|
+
contractIR,
|
|
1897
|
+
contractPath: contractPathAbsolute,
|
|
1898
|
+
configPath
|
|
1899
|
+
}),
|
|
1531
1900
|
{
|
|
1532
1901
|
message: "Signing database...",
|
|
1533
1902
|
flags
|
|
@@ -1580,8 +1949,8 @@ function createDbSignCommand() {
|
|
|
1580
1949
|
}
|
|
1581
1950
|
|
|
1582
1951
|
// src/commands/db-verify.ts
|
|
1583
|
-
import { readFile as
|
|
1584
|
-
import { relative as
|
|
1952
|
+
import { readFile as readFile5 } from "fs/promises";
|
|
1953
|
+
import { relative as relative7, resolve as resolve7 } from "path";
|
|
1585
1954
|
import {
|
|
1586
1955
|
errorDatabaseUrlRequired as errorDatabaseUrlRequired5,
|
|
1587
1956
|
errorDriverRequired as errorDriverRequired5,
|
|
@@ -1592,9 +1961,9 @@ import {
|
|
|
1592
1961
|
errorTargetMismatch as errorTargetMismatch2,
|
|
1593
1962
|
errorUnexpected as errorUnexpected6
|
|
1594
1963
|
} from "@prisma-next/core-control-plane/errors";
|
|
1595
|
-
import { Command as
|
|
1964
|
+
import { Command as Command6 } from "commander";
|
|
1596
1965
|
function createDbVerifyCommand() {
|
|
1597
|
-
const command = new
|
|
1966
|
+
const command = new Command6("verify");
|
|
1598
1967
|
setCommandDescriptions(
|
|
1599
1968
|
command,
|
|
1600
1969
|
"Check whether the database has been signed with your contract",
|
|
@@ -1609,9 +1978,9 @@ function createDbVerifyCommand() {
|
|
|
1609
1978
|
const flags = parseGlobalFlags(options);
|
|
1610
1979
|
const result = await performAction(async () => {
|
|
1611
1980
|
const config = await loadConfig(options.config);
|
|
1612
|
-
const configPath = options.config ?
|
|
1613
|
-
const contractPathAbsolute = config.contract?.output ?
|
|
1614
|
-
const contractPath =
|
|
1981
|
+
const configPath = options.config ? relative7(process.cwd(), resolve7(options.config)) : "prisma-next.config.ts";
|
|
1982
|
+
const contractPathAbsolute = config.contract?.output ? resolve7(config.contract.output) : resolve7("src/prisma/contract.json");
|
|
1983
|
+
const contractPath = relative7(process.cwd(), contractPathAbsolute);
|
|
1615
1984
|
if (flags.json !== "object" && !flags.quiet) {
|
|
1616
1985
|
const details = [
|
|
1617
1986
|
{ label: "config", value: configPath },
|
|
@@ -1631,7 +2000,7 @@ function createDbVerifyCommand() {
|
|
|
1631
2000
|
}
|
|
1632
2001
|
let contractJsonContent;
|
|
1633
2002
|
try {
|
|
1634
|
-
contractJsonContent = await
|
|
2003
|
+
contractJsonContent = await readFile5(contractPathAbsolute, "utf-8");
|
|
1635
2004
|
} catch (error) {
|
|
1636
2005
|
if (error instanceof Error && error.code === "ENOENT") {
|
|
1637
2006
|
throw errorFileNotFound4(contractPathAbsolute, {
|
|
@@ -1662,12 +2031,11 @@ function createDbVerifyCommand() {
|
|
|
1662
2031
|
driver: driverDescriptor,
|
|
1663
2032
|
extensions: config.extensions ?? []
|
|
1664
2033
|
});
|
|
1665
|
-
const
|
|
1666
|
-
const contractIR = typedFamilyInstance.validateContractIR(contractJson);
|
|
2034
|
+
const contractIR = familyInstance.validateContractIR(contractJson);
|
|
1667
2035
|
let verifyResult;
|
|
1668
2036
|
try {
|
|
1669
2037
|
verifyResult = await withSpinner(
|
|
1670
|
-
() =>
|
|
2038
|
+
() => familyInstance.verify({
|
|
1671
2039
|
driver,
|
|
1672
2040
|
contractIR,
|
|
1673
2041
|
expectedTargetId: config.target.targetId,
|
|
@@ -1726,7 +2094,7 @@ function createDbVerifyCommand() {
|
|
|
1726
2094
|
}
|
|
1727
2095
|
|
|
1728
2096
|
// src/cli.ts
|
|
1729
|
-
var program = new
|
|
2097
|
+
var program = new Command7();
|
|
1730
2098
|
program.name("prisma-next").description("Prisma Next CLI").version("0.0.1");
|
|
1731
2099
|
var versionOption = program.options.find((opt) => opt.flags.includes("--version"));
|
|
1732
2100
|
if (versionOption) {
|
|
@@ -1790,7 +2158,7 @@ program.exitOverride((err2) => {
|
|
|
1790
2158
|
}
|
|
1791
2159
|
process.exit(0);
|
|
1792
2160
|
});
|
|
1793
|
-
var contractCommand = new
|
|
2161
|
+
var contractCommand = new Command7("contract");
|
|
1794
2162
|
setCommandDescriptions(
|
|
1795
2163
|
contractCommand,
|
|
1796
2164
|
"Contract management commands",
|
|
@@ -1806,7 +2174,7 @@ contractCommand.configureHelp({
|
|
|
1806
2174
|
var contractEmitCommand = createContractEmitCommand();
|
|
1807
2175
|
contractCommand.addCommand(contractEmitCommand);
|
|
1808
2176
|
program.addCommand(contractCommand);
|
|
1809
|
-
var dbCommand = new
|
|
2177
|
+
var dbCommand = new Command7("db");
|
|
1810
2178
|
setCommandDescriptions(
|
|
1811
2179
|
dbCommand,
|
|
1812
2180
|
"Database management commands",
|
|
@@ -1821,6 +2189,8 @@ dbCommand.configureHelp({
|
|
|
1821
2189
|
});
|
|
1822
2190
|
var dbVerifyCommand = createDbVerifyCommand();
|
|
1823
2191
|
dbCommand.addCommand(dbVerifyCommand);
|
|
2192
|
+
var dbInitCommand = createDbInitCommand();
|
|
2193
|
+
dbCommand.addCommand(dbInitCommand);
|
|
1824
2194
|
var dbIntrospectCommand = createDbIntrospectCommand();
|
|
1825
2195
|
dbCommand.addCommand(dbIntrospectCommand);
|
|
1826
2196
|
var dbSchemaVerifyCommand = createDbSchemaVerifyCommand();
|
|
@@ -1828,7 +2198,7 @@ dbCommand.addCommand(dbSchemaVerifyCommand);
|
|
|
1828
2198
|
var dbSignCommand = createDbSignCommand();
|
|
1829
2199
|
dbCommand.addCommand(dbSignCommand);
|
|
1830
2200
|
program.addCommand(dbCommand);
|
|
1831
|
-
var helpCommand = new
|
|
2201
|
+
var helpCommand = new Command7("help").description("Show usage instructions").configureHelp({
|
|
1832
2202
|
formatHelp: (cmd) => {
|
|
1833
2203
|
const flags = parseGlobalFlags({});
|
|
1834
2204
|
return formatCommandHelp({ command: cmd, flags });
|