@prisma-next/cli 0.3.0-pr.99.6 → 0.4.0-dev.1
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/agent-skill-mongo.md +106 -0
- package/dist/agent-skill-postgres.md +106 -0
- package/dist/cli-errors-BDCYR5ap.mjs +4 -0
- package/dist/cli-errors-DStABy9d.d.mts +3 -0
- package/dist/cli.d.mts +1 -0
- package/dist/cli.js +1 -2910
- package/dist/cli.mjs +254 -0
- package/dist/cli.mjs.map +1 -0
- package/dist/client-DiUkJAeN.mjs +987 -0
- package/dist/client-DiUkJAeN.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 +125 -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 +53 -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 +136 -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 +122 -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 +322 -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 +244 -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 +152 -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 +313 -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 +195 -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 +140 -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 +110 -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-D2wDXfyo.mjs +191 -0
- package/dist/contract-emit-D2wDXfyo.mjs.map +1 -0
- package/dist/contract-emit-D9WOShFz.mjs +4 -0
- package/dist/contract-emit-Zm_sd1wQ.mjs +112 -0
- package/dist/contract-emit-Zm_sd1wQ.mjs.map +1 -0
- package/dist/contract-enrichment-CGW6mm-E.mjs +79 -0
- package/dist/contract-enrichment-CGW6mm-E.mjs.map +1 -0
- package/dist/contract-infer-DozZT511.mjs +90 -0
- package/dist/contract-infer-DozZT511.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 +6 -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-DZUJNmL3.mjs +13 -0
- package/dist/extract-operation-statements-DZUJNmL3.mjs.map +1 -0
- package/dist/extract-sql-ddl-DDMX-9mz.mjs +26 -0
- package/dist/extract-sql-ddl-DDMX-9mz.mjs.map +1 -0
- package/dist/framework-components-BAsliT4V.mjs +59 -0
- package/dist/framework-components-BAsliT4V.mjs.map +1 -0
- package/dist/init-DQ8auNB4.mjs +430 -0
- package/dist/init-DQ8auNB4.mjs.map +1 -0
- package/dist/inspect-live-schema-BYnhztxZ.mjs +91 -0
- package/dist/inspect-live-schema-BYnhztxZ.mjs.map +1 -0
- package/dist/migration-command-scaffold-CntCcntR.mjs +105 -0
- package/dist/migration-command-scaffold-CntCcntR.mjs.map +1 -0
- package/dist/migration-status-CJANY4yr.mjs +1583 -0
- package/dist/migration-status-CJANY4yr.mjs.map +1 -0
- package/dist/migrations-DTZBYXm1.mjs +173 -0
- package/dist/migrations-DTZBYXm1.mjs.map +1 -0
- package/dist/progress-adapter-B-YvmcDu.mjs +43 -0
- package/dist/progress-adapter-B-YvmcDu.mjs.map +1 -0
- package/dist/quick-reference-mongo.md +93 -0
- package/dist/quick-reference-postgres.md +91 -0
- package/dist/result-handler-oK_vA-Fn.mjs +697 -0
- package/dist/result-handler-oK_vA-Fn.mjs.map +1 -0
- package/dist/terminal-ui-C5k88MmW.mjs +274 -0
- package/dist/terminal-ui-C5k88MmW.mjs.map +1 -0
- package/dist/validate-contract-deps-esa-VQ0h.mjs +37 -0
- package/dist/validate-contract-deps-esa-VQ0h.mjs.map +1 -0
- package/dist/verify-DlFQ2FOw.mjs +385 -0
- package/dist/verify-DlFQ2FOw.mjs.map +1 -0
- package/package.json +87 -40
- package/src/cli.ts +118 -58
- package/src/commands/contract-emit.ts +101 -78
- 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 +46 -73
- package/src/commands/db-update.ts +236 -0
- package/src/commands/db-verify.ts +409 -119
- package/src/commands/init/detect-package-manager.ts +47 -0
- package/src/commands/init/index.ts +21 -0
- package/src/commands/init/init.ts +203 -0
- package/src/commands/init/templates/agent-skill-mongo.md +106 -0
- package/src/commands/init/templates/agent-skill-postgres.md +106 -0
- package/src/commands/init/templates/agent-skill.ts +19 -0
- package/src/commands/init/templates/code-templates.ts +168 -0
- package/src/commands/init/templates/quick-reference-mongo.md +93 -0
- package/src/commands/init/templates/quick-reference-postgres.md +91 -0
- package/src/commands/init/templates/quick-reference.ts +19 -0
- package/src/commands/init/templates/render.ts +20 -0
- package/src/commands/init/templates/tsconfig.ts +35 -0
- 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 +205 -183
- 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 +181 -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 +274 -52
- package/src/exports/config-types.ts +4 -3
- package/src/exports/control-api.ts +15 -5
- 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/src/utils/validate-contract-deps.ts +49 -0
- package/dist/chunk-AGOTG4L3.js +0 -965
- package/dist/chunk-AGOTG4L3.js.map +0 -1
- package/dist/chunk-HLLI4YL7.js +0 -180
- package/dist/chunk-HLLI4YL7.js.map +0 -1
- package/dist/chunk-HWYQOCAJ.js +0 -47
- package/dist/chunk-HWYQOCAJ.js.map +0 -1
- package/dist/chunk-VG2R7DGF.js +0 -735
- package/dist/chunk-VG2R7DGF.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 -10
- 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 -257
- 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 -155
- 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 -171
- 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 -195
- 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 -193
- 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 -387
- 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 -7
- 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 -176
- package/dist/exports/index.js.map +0 -1
- package/dist/load-ts-contract.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/src/commands/db-introspect.ts +0 -227
- package/src/commands/db-schema-verify.ts +0 -238
- package/src/utils/output.ts +0 -1471
|
@@ -1,10 +1,20 @@
|
|
|
1
1
|
import { readFile } from 'node:fs/promises';
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import type {
|
|
3
|
+
VerifyDatabaseResult,
|
|
4
|
+
VerifyDatabaseSchemaResult,
|
|
5
|
+
} from '@prisma-next/framework-components/control';
|
|
6
|
+
import {
|
|
7
|
+
VERIFY_CODE_HASH_MISMATCH,
|
|
8
|
+
VERIFY_CODE_MARKER_MISSING,
|
|
9
|
+
VERIFY_CODE_TARGET_MISMATCH,
|
|
10
|
+
} from '@prisma-next/framework-components/control';
|
|
11
|
+
import { ifDefined } from '@prisma-next/utils/defined';
|
|
4
12
|
import { notOk, ok, type Result } from '@prisma-next/utils/result';
|
|
5
13
|
import { Command } from 'commander';
|
|
14
|
+
import { relative, resolve } from 'pathe';
|
|
6
15
|
import { loadConfig } from '../config-loader';
|
|
7
16
|
import { createControlClient } from '../control-api/client';
|
|
17
|
+
import { ContractValidationError } from '../control-api/errors';
|
|
8
18
|
import {
|
|
9
19
|
CliStructuredError,
|
|
10
20
|
errorContractValidationFailed,
|
|
@@ -12,53 +22,73 @@ import {
|
|
|
12
22
|
errorDriverRequired,
|
|
13
23
|
errorFileNotFound,
|
|
14
24
|
errorHashMismatch,
|
|
15
|
-
errorJsonFormatNotSupported,
|
|
16
25
|
errorMarkerMissing,
|
|
17
26
|
errorRuntime,
|
|
18
27
|
errorTargetMismatch,
|
|
19
28
|
errorUnexpected,
|
|
20
29
|
} from '../utils/cli-errors';
|
|
21
|
-
import { setCommandDescriptions } from '../utils/command-helpers';
|
|
22
|
-
import { type GlobalFlags, parseGlobalFlags } from '../utils/global-flags';
|
|
23
30
|
import {
|
|
24
|
-
|
|
25
|
-
|
|
31
|
+
addGlobalOptions,
|
|
32
|
+
maskConnectionUrl,
|
|
33
|
+
resolveContractPath,
|
|
34
|
+
setCommandDescriptions,
|
|
35
|
+
setCommandExamples,
|
|
36
|
+
} from '../utils/command-helpers';
|
|
37
|
+
import { formatStyledHeader } from '../utils/formatters/styled';
|
|
38
|
+
import {
|
|
39
|
+
type DbVerifyCommandSuccessResult,
|
|
40
|
+
formatSchemaVerifyJson,
|
|
41
|
+
formatSchemaVerifyOutput,
|
|
26
42
|
formatVerifyJson,
|
|
27
43
|
formatVerifyOutput,
|
|
28
|
-
} from '../utils/
|
|
44
|
+
} from '../utils/formatters/verify';
|
|
45
|
+
import type { CommonCommandOptions } from '../utils/global-flags';
|
|
46
|
+
import { type GlobalFlags, parseGlobalFlags } from '../utils/global-flags';
|
|
29
47
|
import { createProgressAdapter } from '../utils/progress-adapter';
|
|
30
48
|
import { handleResult } from '../utils/result-handler';
|
|
49
|
+
import { TerminalUI } from '../utils/terminal-ui';
|
|
31
50
|
|
|
32
|
-
interface DbVerifyOptions {
|
|
51
|
+
interface DbVerifyOptions extends CommonCommandOptions {
|
|
33
52
|
readonly db?: string;
|
|
34
53
|
readonly config?: string;
|
|
35
|
-
readonly
|
|
36
|
-
readonly
|
|
37
|
-
readonly
|
|
38
|
-
readonly verbose?: boolean;
|
|
39
|
-
readonly v?: boolean;
|
|
40
|
-
readonly vv?: boolean;
|
|
41
|
-
readonly trace?: boolean;
|
|
42
|
-
readonly timestamps?: boolean;
|
|
43
|
-
readonly color?: boolean;
|
|
44
|
-
readonly 'no-color'?: boolean;
|
|
54
|
+
readonly markerOnly?: boolean;
|
|
55
|
+
readonly schemaOnly?: boolean;
|
|
56
|
+
readonly strict?: boolean;
|
|
45
57
|
}
|
|
46
58
|
|
|
59
|
+
type DbVerifyMode = 'full' | 'marker-only' | 'schema-only';
|
|
60
|
+
|
|
47
61
|
/**
|
|
48
62
|
* Maps a VerifyDatabaseResult failure to a CliStructuredError.
|
|
49
63
|
*/
|
|
50
64
|
function mapVerifyFailure(verifyResult: VerifyDatabaseResult): CliStructuredError {
|
|
51
65
|
if (!verifyResult.ok && verifyResult.code) {
|
|
52
|
-
if (verifyResult.code ===
|
|
66
|
+
if (verifyResult.code === VERIFY_CODE_MARKER_MISSING) {
|
|
53
67
|
return errorMarkerMissing();
|
|
54
68
|
}
|
|
55
|
-
if (verifyResult.code ===
|
|
69
|
+
if (verifyResult.code === VERIFY_CODE_HASH_MISMATCH) {
|
|
70
|
+
const storageMatch = verifyResult.marker?.storageHash === verifyResult.contract.storageHash;
|
|
71
|
+
const profileMatch =
|
|
72
|
+
!verifyResult.contract.profileHash ||
|
|
73
|
+
verifyResult.marker?.profileHash === verifyResult.contract.profileHash;
|
|
74
|
+
|
|
75
|
+
if (!storageMatch) {
|
|
76
|
+
return errorHashMismatch({
|
|
77
|
+
why: 'Contract storageHash does not match database marker',
|
|
78
|
+
expected: verifyResult.contract.storageHash,
|
|
79
|
+
...ifDefined('actual', verifyResult.marker?.storageHash),
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
56
83
|
return errorHashMismatch({
|
|
57
|
-
|
|
58
|
-
|
|
84
|
+
why: profileMatch
|
|
85
|
+
? 'Contract hash does not match database marker'
|
|
86
|
+
: 'Contract profileHash does not match database marker',
|
|
87
|
+
...ifDefined('expected', verifyResult.contract.profileHash),
|
|
88
|
+
...ifDefined('actual', verifyResult.marker?.profileHash),
|
|
59
89
|
});
|
|
60
90
|
}
|
|
61
|
-
if (verifyResult.code ===
|
|
91
|
+
if (verifyResult.code === VERIFY_CODE_TARGET_MISMATCH) {
|
|
62
92
|
return errorTargetMismatch(
|
|
63
93
|
verifyResult.target.expected,
|
|
64
94
|
verifyResult.target.actual ?? 'unknown',
|
|
@@ -69,43 +99,152 @@ function mapVerifyFailure(verifyResult: VerifyDatabaseResult): CliStructuredErro
|
|
|
69
99
|
return errorRuntime(verifyResult.summary);
|
|
70
100
|
}
|
|
71
101
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
102
|
+
type DbVerifyFailure = CliStructuredError | VerifyDatabaseSchemaResult;
|
|
103
|
+
|
|
104
|
+
function errorInvalidVerifyMode(options: {
|
|
105
|
+
readonly why: string;
|
|
106
|
+
readonly fix: string;
|
|
107
|
+
}): CliStructuredError {
|
|
108
|
+
return new CliStructuredError('4012', 'Invalid verify mode', {
|
|
109
|
+
domain: 'CLI',
|
|
110
|
+
why: options.why,
|
|
111
|
+
fix: options.fix,
|
|
112
|
+
docsUrl: 'https://pris.ly/db-verify',
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function resolveDbVerifyMode(options: DbVerifyOptions): Result<DbVerifyMode, CliStructuredError> {
|
|
117
|
+
if (options.markerOnly && options.schemaOnly) {
|
|
118
|
+
return notOk(
|
|
119
|
+
errorInvalidVerifyMode({
|
|
120
|
+
why: '`--marker-only` and `--schema-only` cannot be used together',
|
|
121
|
+
fix: 'Choose one mode: omit both to check the marker and schema, use `--marker-only` to check only the marker, or use `--schema-only` to check only the live schema.',
|
|
122
|
+
}),
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (options.markerOnly && options.strict) {
|
|
127
|
+
return notOk(
|
|
128
|
+
errorInvalidVerifyMode({
|
|
129
|
+
why: '`--strict` requires schema verification, but `--marker-only` skips it',
|
|
130
|
+
fix: 'Remove `--strict`, or use `db verify` / `db verify --schema-only` when you want to check the live schema in strict mode.',
|
|
131
|
+
}),
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (options.schemaOnly) {
|
|
136
|
+
return ok('schema-only');
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (options.markerOnly) {
|
|
140
|
+
return ok('marker-only');
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return ok('full');
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function formatDbVerifyModeLabel(mode: DbVerifyMode, strict: boolean): string {
|
|
147
|
+
if (mode === 'marker-only') {
|
|
148
|
+
return 'marker only';
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (mode === 'schema-only') {
|
|
152
|
+
return `schema only (${strict ? 'strict' : 'tolerant'})`;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return `full (marker + schema, ${strict ? 'strict' : 'tolerant'})`;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function formatDbVerifyInvocation(mode: DbVerifyMode, strict: boolean): string {
|
|
159
|
+
const args = ['db verify'];
|
|
160
|
+
|
|
161
|
+
if (mode === 'marker-only') {
|
|
162
|
+
args.push('--marker-only');
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (mode === 'schema-only') {
|
|
166
|
+
args.push('--schema-only');
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (strict) {
|
|
170
|
+
args.push('--strict');
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
return args.join(' ');
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function createDbVerifyConnectionRequiredError(options: {
|
|
177
|
+
readonly configPath: string;
|
|
178
|
+
readonly mode: DbVerifyMode;
|
|
179
|
+
readonly strict: boolean;
|
|
180
|
+
}): CliStructuredError {
|
|
181
|
+
const invocation = formatDbVerifyInvocation(options.mode, options.strict);
|
|
182
|
+
return errorDatabaseConnectionRequired({
|
|
183
|
+
why: `Database connection is required for ${invocation} (set db.connection in ${options.configPath}, or pass --db <url>)`,
|
|
184
|
+
retryCommand: `prisma-next ${invocation} --db <url>`,
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function renderVerifyHeader(
|
|
189
|
+
paths: { configPath: string; contractPath: string },
|
|
76
190
|
options: DbVerifyOptions,
|
|
191
|
+
mode: DbVerifyMode,
|
|
77
192
|
flags: GlobalFlags,
|
|
78
|
-
|
|
79
|
-
|
|
193
|
+
ui: TerminalUI,
|
|
194
|
+
): void {
|
|
195
|
+
if (flags.json || flags.quiet) return;
|
|
196
|
+
|
|
197
|
+
const description =
|
|
198
|
+
mode === 'schema-only'
|
|
199
|
+
? 'Check whether the live database schema matches your contract'
|
|
200
|
+
: mode === 'marker-only'
|
|
201
|
+
? 'Check whether the database marker matches your contract'
|
|
202
|
+
: 'Check whether the database marker and live schema match your contract';
|
|
203
|
+
|
|
204
|
+
const details: Array<{ label: string; value: string }> = [
|
|
205
|
+
{ label: 'config', value: paths.configPath },
|
|
206
|
+
{ label: 'contract', value: paths.contractPath },
|
|
207
|
+
{ label: 'mode', value: formatDbVerifyModeLabel(mode, options.strict ?? false) },
|
|
208
|
+
];
|
|
209
|
+
if (options.db) {
|
|
210
|
+
details.push({ label: 'database', value: maskConnectionUrl(options.db) });
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
ui.stderr(
|
|
214
|
+
formatStyledHeader({
|
|
215
|
+
command: 'db verify',
|
|
216
|
+
description,
|
|
217
|
+
url: 'https://pris.ly/db-verify',
|
|
218
|
+
details,
|
|
219
|
+
flags,
|
|
220
|
+
}),
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
async function resolveVerifyPaths(options: DbVerifyOptions) {
|
|
80
225
|
const config = await loadConfig(options.config);
|
|
81
226
|
const configPath = options.config
|
|
82
227
|
? relative(process.cwd(), resolve(options.config))
|
|
83
228
|
: 'prisma-next.config.ts';
|
|
84
|
-
const contractPathAbsolute = config
|
|
85
|
-
? resolve(config.contract.output)
|
|
86
|
-
: resolve('src/prisma/contract.json');
|
|
229
|
+
const contractPathAbsolute = resolveContractPath(config);
|
|
87
230
|
const contractPath = relative(process.cwd(), contractPathAbsolute);
|
|
231
|
+
return { config, configPath, contractPathAbsolute, contractPath };
|
|
232
|
+
}
|
|
88
233
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
details,
|
|
103
|
-
flags,
|
|
104
|
-
});
|
|
105
|
-
console.log(header);
|
|
106
|
-
}
|
|
234
|
+
type VerifyPaths = Awaited<ReturnType<typeof resolveVerifyPaths>>;
|
|
235
|
+
|
|
236
|
+
interface VerifySetup extends VerifyPaths {
|
|
237
|
+
readonly contractJson: Record<string, unknown>;
|
|
238
|
+
readonly dbConnection: string;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
async function resolveVerifySetup(
|
|
242
|
+
paths: VerifyPaths,
|
|
243
|
+
options: DbVerifyOptions,
|
|
244
|
+
mode: DbVerifyMode,
|
|
245
|
+
): Promise<Result<VerifySetup, CliStructuredError>> {
|
|
246
|
+
const { config, configPath, contractPathAbsolute, contractPath } = paths;
|
|
107
247
|
|
|
108
|
-
// Load contract file
|
|
109
248
|
let contractJsonContent: string;
|
|
110
249
|
try {
|
|
111
250
|
contractJsonContent = await readFile(contractPathAbsolute, 'utf-8');
|
|
@@ -137,63 +276,174 @@ async function executeDbVerifyCommand(
|
|
|
137
276
|
);
|
|
138
277
|
}
|
|
139
278
|
|
|
140
|
-
// Resolve database connection (--db flag or config.db.connection)
|
|
141
279
|
const dbConnection = options.db ?? config.db?.connection;
|
|
142
|
-
if (
|
|
280
|
+
if (typeof dbConnection !== 'string' || dbConnection.length === 0) {
|
|
143
281
|
return notOk(
|
|
144
|
-
|
|
145
|
-
|
|
282
|
+
createDbVerifyConnectionRequiredError({
|
|
283
|
+
configPath,
|
|
284
|
+
mode,
|
|
285
|
+
strict: options.strict ?? false,
|
|
146
286
|
}),
|
|
147
287
|
);
|
|
148
288
|
}
|
|
149
289
|
|
|
150
|
-
// Check for driver
|
|
151
290
|
if (!config.driver) {
|
|
152
|
-
return notOk(
|
|
291
|
+
return notOk(
|
|
292
|
+
errorDriverRequired({
|
|
293
|
+
why: `Config.driver is required for ${formatDbVerifyInvocation(mode, options.strict ?? false)}`,
|
|
294
|
+
}),
|
|
295
|
+
);
|
|
153
296
|
}
|
|
154
297
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
298
|
+
return ok({ ...paths, contractJson, dbConnection });
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
function createVerifyClient(setup: VerifySetup) {
|
|
302
|
+
return createControlClient({
|
|
303
|
+
family: setup.config.family,
|
|
304
|
+
target: setup.config.target,
|
|
305
|
+
adapter: setup.config.adapter,
|
|
306
|
+
driver: setup.config.driver!,
|
|
307
|
+
extensionPacks: setup.config.extensionPacks ?? [],
|
|
162
308
|
});
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
function wrapVerifyError(
|
|
312
|
+
error: unknown,
|
|
313
|
+
contractPathAbsolute: string,
|
|
314
|
+
modeLabel: string,
|
|
315
|
+
): Result<never, CliStructuredError> {
|
|
316
|
+
if (error instanceof CliStructuredError) {
|
|
317
|
+
return notOk(error);
|
|
318
|
+
}
|
|
319
|
+
if (error instanceof ContractValidationError) {
|
|
320
|
+
return notOk(
|
|
321
|
+
errorContractValidationFailed(`Contract validation failed: ${error.message}`, {
|
|
322
|
+
where: { path: contractPathAbsolute },
|
|
323
|
+
}),
|
|
324
|
+
);
|
|
325
|
+
}
|
|
326
|
+
return notOk(
|
|
327
|
+
errorUnexpected(error instanceof Error ? error.message : String(error), {
|
|
328
|
+
why: `Unexpected error during ${modeLabel}: ${error instanceof Error ? error.message : String(error)}`,
|
|
329
|
+
}),
|
|
330
|
+
);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* Executes the db verify command and returns a structured Result.
|
|
335
|
+
*/
|
|
336
|
+
async function executeDbVerifyCommand(
|
|
337
|
+
options: DbVerifyOptions,
|
|
338
|
+
flags: GlobalFlags,
|
|
339
|
+
ui: TerminalUI,
|
|
340
|
+
mode: Extract<DbVerifyMode, 'full' | 'marker-only'>,
|
|
341
|
+
): Promise<Result<DbVerifyCommandSuccessResult, DbVerifyFailure>> {
|
|
342
|
+
const startTime = Date.now();
|
|
343
|
+
const paths = await resolveVerifyPaths(options);
|
|
344
|
+
renderVerifyHeader(paths, options, mode, flags, ui);
|
|
163
345
|
|
|
164
|
-
|
|
165
|
-
|
|
346
|
+
const setupResult = await resolveVerifySetup(paths, options, mode);
|
|
347
|
+
if (!setupResult.ok) return setupResult;
|
|
348
|
+
const { contractJson, dbConnection, contractPathAbsolute } = setupResult.value;
|
|
349
|
+
|
|
350
|
+
const client = createVerifyClient(setupResult.value);
|
|
351
|
+
const onProgress = createProgressAdapter({ ui, flags });
|
|
166
352
|
|
|
167
353
|
try {
|
|
168
354
|
const verifyResult = await client.verify({
|
|
169
|
-
|
|
355
|
+
contract: contractJson,
|
|
170
356
|
connection: dbConnection,
|
|
171
357
|
onProgress,
|
|
172
358
|
});
|
|
173
359
|
|
|
174
|
-
// Add blank line after all async operations if spinners were shown
|
|
175
|
-
if (!flags.quiet && flags.json !== 'object' && process.stdout.isTTY) {
|
|
176
|
-
console.log('');
|
|
177
|
-
}
|
|
178
|
-
|
|
179
360
|
// If verification failed, map to CLI structured error
|
|
180
361
|
if (!verifyResult.ok) {
|
|
181
362
|
return notOk(mapVerifyFailure(verifyResult));
|
|
182
363
|
}
|
|
183
364
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
365
|
+
if (mode === 'marker-only') {
|
|
366
|
+
return ok({
|
|
367
|
+
ok: true,
|
|
368
|
+
mode: 'marker-only',
|
|
369
|
+
summary: 'Database marker matches contract',
|
|
370
|
+
contract: verifyResult.contract,
|
|
371
|
+
marker: verifyResult.marker,
|
|
372
|
+
target: verifyResult.target,
|
|
373
|
+
...ifDefined('missingCodecs', verifyResult.missingCodecs),
|
|
374
|
+
...ifDefined('codecCoverageSkipped', verifyResult.codecCoverageSkipped),
|
|
375
|
+
warning: 'Schema verification skipped because --marker-only was provided',
|
|
376
|
+
meta: {
|
|
377
|
+
...(verifyResult.meta ?? {}),
|
|
378
|
+
schemaVerification: 'skipped',
|
|
379
|
+
},
|
|
380
|
+
timings: { total: Date.now() - startTime },
|
|
381
|
+
});
|
|
189
382
|
}
|
|
190
383
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
384
|
+
const schemaVerifyResult = await client.schemaVerify({
|
|
385
|
+
contract: contractJson,
|
|
386
|
+
strict: options.strict ?? false,
|
|
387
|
+
onProgress,
|
|
388
|
+
});
|
|
389
|
+
|
|
390
|
+
if (!schemaVerifyResult.ok) {
|
|
391
|
+
return notOk(schemaVerifyResult);
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
return ok({
|
|
395
|
+
ok: true,
|
|
396
|
+
mode: 'full',
|
|
397
|
+
summary: 'Database marker and schema match contract',
|
|
398
|
+
contract: verifyResult.contract,
|
|
399
|
+
marker: verifyResult.marker,
|
|
400
|
+
target: verifyResult.target,
|
|
401
|
+
...ifDefined('missingCodecs', verifyResult.missingCodecs),
|
|
402
|
+
...ifDefined('codecCoverageSkipped', verifyResult.codecCoverageSkipped),
|
|
403
|
+
schema: {
|
|
404
|
+
summary: schemaVerifyResult.summary,
|
|
405
|
+
counts: schemaVerifyResult.schema.counts,
|
|
406
|
+
strict: schemaVerifyResult.meta?.strict ?? false,
|
|
407
|
+
},
|
|
408
|
+
meta: {
|
|
409
|
+
...(verifyResult.meta ?? {}),
|
|
410
|
+
schemaVerification: 'performed',
|
|
411
|
+
},
|
|
412
|
+
timings: { total: Date.now() - startTime },
|
|
413
|
+
});
|
|
414
|
+
} catch (error) {
|
|
415
|
+
return wrapVerifyError(error, contractPathAbsolute, 'db verify');
|
|
416
|
+
} finally {
|
|
417
|
+
await client.close();
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
async function executeDbSchemaOnlyVerifyCommand(
|
|
422
|
+
options: DbVerifyOptions,
|
|
423
|
+
flags: GlobalFlags,
|
|
424
|
+
ui: TerminalUI,
|
|
425
|
+
): Promise<Result<VerifyDatabaseSchemaResult, CliStructuredError>> {
|
|
426
|
+
const paths = await resolveVerifyPaths(options);
|
|
427
|
+
renderVerifyHeader(paths, options, 'schema-only', flags, ui);
|
|
428
|
+
|
|
429
|
+
const setupResult = await resolveVerifySetup(paths, options, 'schema-only');
|
|
430
|
+
if (!setupResult.ok) return setupResult;
|
|
431
|
+
const { contractJson, dbConnection, contractPathAbsolute } = setupResult.value;
|
|
432
|
+
|
|
433
|
+
const client = createVerifyClient(setupResult.value);
|
|
434
|
+
const onProgress = createProgressAdapter({ ui, flags });
|
|
435
|
+
|
|
436
|
+
try {
|
|
437
|
+
const schemaVerifyResult = await client.schemaVerify({
|
|
438
|
+
contract: contractJson,
|
|
439
|
+
strict: options.strict ?? false,
|
|
440
|
+
connection: dbConnection,
|
|
441
|
+
onProgress,
|
|
442
|
+
});
|
|
443
|
+
|
|
444
|
+
return ok(schemaVerifyResult);
|
|
445
|
+
} catch (error) {
|
|
446
|
+
return wrapVerifyError(error, contractPathAbsolute, 'db verify --schema-only');
|
|
197
447
|
} finally {
|
|
198
448
|
await client.close();
|
|
199
449
|
}
|
|
@@ -203,55 +453,95 @@ export function createDbVerifyCommand(): Command {
|
|
|
203
453
|
const command = new Command('verify');
|
|
204
454
|
setCommandDescriptions(
|
|
205
455
|
command,
|
|
206
|
-
'Check whether the database
|
|
207
|
-
'Verifies
|
|
208
|
-
'
|
|
456
|
+
'Check whether the database marker and live schema match your contract',
|
|
457
|
+
'Verifies the database marker first, then checks the database schema matches your contract.\n' +
|
|
458
|
+
'Use `--marker-only` for marker-only verification, `--schema-only` to skip marker checks and\n' +
|
|
459
|
+
'inspect only the live schema, and `--strict` to fail if the database includes elements\n' +
|
|
460
|
+
'not present in the contract.',
|
|
209
461
|
);
|
|
210
|
-
command
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
462
|
+
setCommandExamples(command, [
|
|
463
|
+
'prisma-next db verify --db $DATABASE_URL',
|
|
464
|
+
'prisma-next db verify --db $DATABASE_URL --strict',
|
|
465
|
+
'prisma-next db verify --db $DATABASE_URL --schema-only',
|
|
466
|
+
'prisma-next db verify --db $DATABASE_URL --schema-only --strict',
|
|
467
|
+
'prisma-next db verify --db $DATABASE_URL --marker-only',
|
|
468
|
+
'prisma-next db verify --db $DATABASE_URL --json',
|
|
469
|
+
]);
|
|
470
|
+
addGlobalOptions(command)
|
|
217
471
|
.option('--db <url>', 'Database connection string')
|
|
218
472
|
.option('--config <path>', 'Path to prisma-next.config.ts')
|
|
219
|
-
.option('--
|
|
220
|
-
.option(
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
.option(
|
|
225
|
-
|
|
473
|
+
.option('--marker-only', 'Skip schema verification and only check the database marker')
|
|
474
|
+
.option(
|
|
475
|
+
'--schema-only',
|
|
476
|
+
'Skip marker verification and only check whether the live schema satisfies the contract',
|
|
477
|
+
)
|
|
478
|
+
.option(
|
|
479
|
+
'--strict',
|
|
480
|
+
'Strict mode: schema elements not present in the contract are considered an error',
|
|
481
|
+
false,
|
|
482
|
+
)
|
|
226
483
|
.action(async (options: DbVerifyOptions) => {
|
|
227
484
|
const flags = parseGlobalFlags(options);
|
|
485
|
+
const ui = new TerminalUI({ color: flags.color, interactive: flags.interactive });
|
|
486
|
+
|
|
487
|
+
const modeResult = resolveDbVerifyMode(options);
|
|
488
|
+
if (!modeResult.ok) {
|
|
489
|
+
const exitCode = handleResult(modeResult as Result<never, CliStructuredError>, flags, ui);
|
|
490
|
+
process.exit(exitCode);
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
const mode = modeResult.value;
|
|
494
|
+
|
|
495
|
+
if (mode === 'schema-only') {
|
|
496
|
+
const result = await executeDbSchemaOnlyVerifyCommand(options, flags, ui);
|
|
497
|
+
const exitCode = handleResult(result, flags, ui, (schemaVerifyResult) => {
|
|
498
|
+
if (flags.json) {
|
|
499
|
+
ui.output(formatSchemaVerifyJson(schemaVerifyResult));
|
|
500
|
+
} else {
|
|
501
|
+
const output = formatSchemaVerifyOutput(schemaVerifyResult, flags);
|
|
502
|
+
if (output) {
|
|
503
|
+
ui.log(output);
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
});
|
|
507
|
+
|
|
508
|
+
if (result.ok && !result.value.ok) {
|
|
509
|
+
process.exit(1);
|
|
510
|
+
}
|
|
228
511
|
|
|
229
|
-
// Validate JSON format option
|
|
230
|
-
if (flags.json === 'ndjson') {
|
|
231
|
-
const result = notOk(
|
|
232
|
-
errorJsonFormatNotSupported({
|
|
233
|
-
command: 'db verify',
|
|
234
|
-
format: 'ndjson',
|
|
235
|
-
supportedFormats: ['object'],
|
|
236
|
-
}),
|
|
237
|
-
);
|
|
238
|
-
const exitCode = handleResult(result, flags);
|
|
239
512
|
process.exit(exitCode);
|
|
240
513
|
}
|
|
241
514
|
|
|
242
|
-
const result = await executeDbVerifyCommand(options, flags);
|
|
515
|
+
const result = await executeDbVerifyCommand(options, flags, ui, mode);
|
|
243
516
|
|
|
244
|
-
|
|
245
|
-
if (flags.json
|
|
246
|
-
|
|
517
|
+
if (result.ok) {
|
|
518
|
+
if (flags.json) {
|
|
519
|
+
ui.output(formatVerifyJson(result.value));
|
|
247
520
|
} else {
|
|
248
|
-
const output = formatVerifyOutput(
|
|
521
|
+
const output = formatVerifyOutput(result.value, flags);
|
|
249
522
|
if (output) {
|
|
250
|
-
|
|
523
|
+
ui.log(output);
|
|
251
524
|
}
|
|
252
525
|
}
|
|
253
|
-
|
|
254
|
-
|
|
526
|
+
process.exit(0);
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
if (CliStructuredError.is(result.failure)) {
|
|
530
|
+
const exitCode = handleResult(result as Result<never, CliStructuredError>, flags, ui);
|
|
531
|
+
process.exit(exitCode);
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
if (flags.json) {
|
|
535
|
+
ui.output(formatSchemaVerifyJson(result.failure));
|
|
536
|
+
} else {
|
|
537
|
+
// Always show schema-drift failures, even in quiet mode — exiting 1 without
|
|
538
|
+
// diagnostics is unhelpful.
|
|
539
|
+
const output = formatSchemaVerifyOutput(result.failure, { ...flags, quiet: false });
|
|
540
|
+
if (output) {
|
|
541
|
+
ui.log(output);
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
process.exit(1);
|
|
255
545
|
});
|
|
256
546
|
|
|
257
547
|
return command;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { detect } from 'package-manager-detector/detect';
|
|
3
|
+
import { join } from 'pathe';
|
|
4
|
+
|
|
5
|
+
export type PackageManager = 'pnpm' | 'npm' | 'yarn' | 'bun' | 'deno';
|
|
6
|
+
|
|
7
|
+
const KNOWN: ReadonlySet<string> = new Set<PackageManager>(['pnpm', 'npm', 'yarn', 'bun', 'deno']);
|
|
8
|
+
|
|
9
|
+
export async function detectPackageManager(cwd: string): Promise<PackageManager> {
|
|
10
|
+
const result = await detect({ cwd });
|
|
11
|
+
if (result && KNOWN.has(result.name)) {
|
|
12
|
+
return result.name as PackageManager;
|
|
13
|
+
}
|
|
14
|
+
return 'npm';
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function hasProjectManifest(cwd: string): boolean {
|
|
18
|
+
return (
|
|
19
|
+
existsSync(join(cwd, 'package.json')) ||
|
|
20
|
+
existsSync(join(cwd, 'deno.json')) ||
|
|
21
|
+
existsSync(join(cwd, 'deno.jsonc'))
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function formatRunCommand(pm: PackageManager, bin: string, args: string): string {
|
|
26
|
+
if (pm === 'npm') {
|
|
27
|
+
return `npx ${bin} ${args}`;
|
|
28
|
+
}
|
|
29
|
+
if (pm === 'deno') {
|
|
30
|
+
return `deno run npm:${bin} ${args}`;
|
|
31
|
+
}
|
|
32
|
+
return `${pm} ${bin} ${args}`;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function formatAddArgs(pm: PackageManager, packages: string[]): string[] {
|
|
36
|
+
if (pm === 'deno') {
|
|
37
|
+
return ['add', ...packages.map((p) => `npm:${p}`)];
|
|
38
|
+
}
|
|
39
|
+
return ['add', ...packages];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function formatAddDevArgs(pm: PackageManager, packages: string[]): string[] {
|
|
43
|
+
if (pm === 'deno') {
|
|
44
|
+
return ['add', '--dev', ...packages.map((p) => `npm:${p}`)];
|
|
45
|
+
}
|
|
46
|
+
return ['add', '-D', ...packages];
|
|
47
|
+
}
|