@prisma-next/cli 0.13.0 → 0.14.0-dev.10
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 +2 -2
- package/dist/cli.mjs +33 -16
- package/dist/cli.mjs.map +1 -1
- package/dist/{client-CJzuo5wX.mjs → client-EnAjSmZg.mjs} +4 -4
- package/dist/{client-CJzuo5wX.mjs.map → client-EnAjSmZg.mjs.map} +1 -1
- package/dist/{command-helpers-DGMvGBeX.mjs → command-helpers-6cNJZ863.mjs} +3 -3
- package/dist/{command-helpers-DGMvGBeX.mjs.map → command-helpers-6cNJZ863.mjs.map} +1 -1
- package/dist/commands/contract-emit.mjs +1 -1
- package/dist/commands/contract-infer.mjs +1 -1
- package/dist/commands/db-init.mjs +3 -3
- package/dist/commands/db-schema.mjs +3 -3
- package/dist/commands/db-sign.mjs +5 -5
- package/dist/commands/db-sign.mjs.map +1 -1
- package/dist/commands/db-update.mjs +4 -4
- package/dist/commands/db-verify.mjs +1 -1
- package/dist/commands/migrate.d.mts +1 -1
- package/dist/commands/migrate.mjs +6 -6
- package/dist/commands/migrate.mjs.map +1 -1
- package/dist/commands/migration-check.d.mts +1 -1
- package/dist/commands/migration-check.mjs +1 -1
- package/dist/commands/migration-graph.d.mts +1 -1
- package/dist/commands/migration-graph.mjs +4 -4
- package/dist/commands/migration-graph.mjs.map +1 -1
- package/dist/commands/migration-list.d.mts +1 -1
- package/dist/commands/migration-list.mjs +1 -1
- package/dist/commands/migration-log.d.mts +1 -1
- package/dist/commands/migration-log.mjs +1 -1
- package/dist/commands/migration-new.mjs +4 -4
- package/dist/commands/migration-new.mjs.map +1 -1
- package/dist/commands/migration-plan.mjs +1 -1
- package/dist/commands/migration-show.mjs +4 -4
- package/dist/commands/migration-show.mjs.map +1 -1
- package/dist/commands/migration-status.d.mts +1 -1
- package/dist/commands/migration-status.mjs +1 -1
- package/dist/commands/ref.d.mts +1 -1
- package/dist/commands/ref.mjs +3 -3
- package/dist/commands/ref.mjs.map +1 -1
- package/dist/commands/telemetry/index.mjs +1 -1
- package/dist/{contract-at-errors-CFXsstzm.mjs → contract-at-errors-DdxWRjMc.mjs} +2 -2
- package/dist/{contract-at-errors-CFXsstzm.mjs.map → contract-at-errors-DdxWRjMc.mjs.map} +1 -1
- package/dist/{contract-emit-B_qriF8B.mjs → contract-emit-D4xDDFkO.mjs} +6 -6
- package/dist/contract-emit-D4xDDFkO.mjs.map +1 -0
- package/dist/{contract-emit-C8HmtboH.mjs → contract-emit-fz6pDR2n.mjs} +4 -4
- package/dist/contract-emit-fz6pDR2n.mjs.map +1 -0
- package/dist/{contract-infer-BYT_ra_U.mjs → contract-infer-Ars4yjBv.mjs} +3 -3
- package/dist/{contract-infer-BYT_ra_U.mjs.map → contract-infer-Ars4yjBv.mjs.map} +1 -1
- package/dist/{contract-space-aggregate-loader-ClI1KN6d.mjs → contract-space-aggregate-loader-Bu2fjSWV.mjs} +2 -2
- package/dist/{contract-space-aggregate-loader-ClI1KN6d.mjs.map → contract-space-aggregate-loader-Bu2fjSWV.mjs.map} +1 -1
- package/dist/{db-verify-C24FKhb7.mjs → db-verify-CZxRV_er.mjs} +5 -5
- package/dist/db-verify-CZxRV_er.mjs.map +1 -0
- package/dist/exports/control-api.d.mts +1 -1
- package/dist/exports/control-api.mjs +2 -2
- package/dist/exports/index.d.mts +5 -1
- package/dist/exports/index.d.mts.map +1 -1
- package/dist/exports/index.mjs +4 -3
- package/dist/exports/index.mjs.map +1 -1
- package/dist/format-C3XdaDuA.mjs +102 -0
- package/dist/format-C3XdaDuA.mjs.map +1 -0
- package/dist/{framework-components-YVQHhPH7.mjs → framework-components-5RljWT7Q.mjs} +2 -2
- package/dist/{framework-components-YVQHhPH7.mjs.map → framework-components-5RljWT7Q.mjs.map} +1 -1
- package/dist/{init-0HwB-Vh8.mjs → init-C79Yb97u.mjs} +12 -8
- package/dist/init-C79Yb97u.mjs.map +1 -0
- package/dist/{inspect-live-schema-DF6IwcDl.mjs → inspect-live-schema-DR8Eyt29.mjs} +4 -4
- package/dist/inspect-live-schema-DR8Eyt29.mjs.map +1 -0
- package/dist/{migration-check-soB5uZEQ.mjs → migration-check-CTcJfCC4.mjs} +5 -5
- package/dist/migration-check-CTcJfCC4.mjs.map +1 -0
- package/dist/migration-cli.mjs +4 -4
- package/dist/migration-cli.mjs.map +1 -1
- package/dist/{migration-command-scaffold-DA-Lhx6o.mjs → migration-command-scaffold-6OT_Q-3Y.mjs} +4 -4
- package/dist/migration-command-scaffold-6OT_Q-3Y.mjs.map +1 -0
- package/dist/{migration-list-DlJJ_38Z.mjs → migration-list-DVHVmMrf.mjs} +4 -4
- package/dist/migration-list-DVHVmMrf.mjs.map +1 -0
- package/dist/{migration-log-CG0qQAFm.mjs → migration-log-CQpc9JoL.mjs} +4 -4
- package/dist/migration-log-CQpc9JoL.mjs.map +1 -0
- package/dist/{migration-path-target-Ce6OZImp.mjs → migration-path-target-zK6RG6JY.mjs} +2 -2
- package/dist/{migration-path-target-Ce6OZImp.mjs.map → migration-path-target-zK6RG6JY.mjs.map} +1 -1
- package/dist/{migration-plan-z5Ing-TD.mjs → migration-plan-o2aqjnfd.mjs} +7 -7
- package/dist/migration-plan-o2aqjnfd.mjs.map +1 -0
- package/dist/{migration-status-CgWSoI_g.mjs → migration-status-2aXGtYMW.mjs} +6 -6
- package/dist/migration-status-2aXGtYMW.mjs.map +1 -0
- package/dist/{telemetry-BIM4beEO.mjs → telemetry-BckOSUWG.mjs} +2 -2
- package/dist/{telemetry-BIM4beEO.mjs.map → telemetry-BckOSUWG.mjs.map} +1 -1
- package/dist/{types-C_tYiJYx.d.mts → types-qETCCNbe.d.mts} +2 -2
- package/dist/{types-C_tYiJYx.d.mts.map → types-qETCCNbe.d.mts.map} +1 -1
- package/dist/{verify-DcOYZ1tH.mjs → verify-DLqhL2LU.mjs} +2 -2
- package/dist/{verify-DcOYZ1tH.mjs.map → verify-DLqhL2LU.mjs.map} +1 -1
- package/package.json +21 -23
- package/src/cli.ts +7 -0
- package/src/commands/contract-emit.ts +1 -1
- package/src/commands/db-sign.ts +1 -1
- package/src/commands/db-verify.ts +1 -1
- package/src/commands/format.ts +75 -0
- package/src/commands/init/detect-package-manager.ts +8 -4
- package/src/commands/init/hygiene-package-scripts.ts +16 -3
- package/src/commands/init/templates/code-templates.ts +4 -4
- package/src/commands/inspect-live-schema.ts +1 -1
- package/src/commands/lsp.ts +32 -0
- package/src/commands/migrate.ts +1 -1
- package/src/commands/migration-check.ts +1 -1
- package/src/commands/migration-graph.ts +1 -1
- package/src/commands/migration-list.ts +1 -1
- package/src/commands/migration-log.ts +1 -1
- package/src/commands/migration-new.ts +1 -1
- package/src/commands/migration-plan.ts +2 -2
- package/src/commands/migration-show.ts +1 -1
- package/src/commands/migration-status.ts +1 -1
- package/src/commands/ref.ts +1 -1
- package/src/control-api/operations/contract-emit.ts +1 -1
- package/src/control-api/operations/format.ts +98 -0
- package/src/exports/index.ts +1 -0
- package/src/migration-cli.ts +5 -5
- package/src/utils/migration-command-scaffold.ts +1 -1
- package/dist/config-loader-p9JMrekQ.mjs +0 -88
- package/dist/config-loader-p9JMrekQ.mjs.map +0 -1
- package/dist/config-loader.d.mts +0 -16
- package/dist/config-loader.d.mts.map +0 -1
- package/dist/config-loader.mjs +0 -2
- package/dist/contract-emit-B_qriF8B.mjs.map +0 -1
- package/dist/contract-emit-C8HmtboH.mjs.map +0 -1
- package/dist/db-verify-C24FKhb7.mjs.map +0 -1
- package/dist/init-0HwB-Vh8.mjs.map +0 -1
- package/dist/inspect-live-schema-DF6IwcDl.mjs.map +0 -1
- package/dist/migration-check-soB5uZEQ.mjs.map +0 -1
- package/dist/migration-command-scaffold-DA-Lhx6o.mjs.map +0 -1
- package/dist/migration-list-DlJJ_38Z.mjs.map +0 -1
- package/dist/migration-log-CG0qQAFm.mjs.map +0 -1
- package/dist/migration-plan-z5Ing-TD.mjs.map +0 -1
- package/dist/migration-status-CgWSoI_g.mjs.map +0 -1
- package/src/config-loader.ts +0 -92
- package/src/config-path-validation.ts +0 -74
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { ifDefined } from '@prisma-next/utils/defined';
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
import { relative, resolve } from 'pathe';
|
|
4
|
+
import { executeFormat } from '../control-api/operations/format';
|
|
5
|
+
import {
|
|
6
|
+
addGlobalOptions,
|
|
7
|
+
setCommandDescriptions,
|
|
8
|
+
setCommandExamples,
|
|
9
|
+
} from '../utils/command-helpers';
|
|
10
|
+
import { formatStyledHeader } from '../utils/formatters/styled';
|
|
11
|
+
import type { CommonCommandOptions } from '../utils/global-flags';
|
|
12
|
+
import { parseGlobalFlagsOrExit } from '../utils/global-flags';
|
|
13
|
+
import { handleResult } from '../utils/result-handler';
|
|
14
|
+
import { createTerminalUI } from '../utils/terminal-ui';
|
|
15
|
+
|
|
16
|
+
interface FormatCommandOptions extends CommonCommandOptions {
|
|
17
|
+
readonly config?: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function createFormatCommand(): Command {
|
|
21
|
+
const command = new Command('format');
|
|
22
|
+
setCommandDescriptions(
|
|
23
|
+
command,
|
|
24
|
+
'Format your PSL contract source',
|
|
25
|
+
'Formats the Prisma schema (PSL) contract source declared in your config\n' +
|
|
26
|
+
'(contract.source.inputs[0]) in place. Only runs when contract.source.sourceFormat\n' +
|
|
27
|
+
"is 'psl'; a TypeScript or unset source is left untouched. Indent and newline are\n" +
|
|
28
|
+
'read from the optional formatter config section, defaulting to two spaces and the\n' +
|
|
29
|
+
'system newline.',
|
|
30
|
+
);
|
|
31
|
+
setCommandExamples(command, [
|
|
32
|
+
'prisma-next format',
|
|
33
|
+
'prisma-next format --config ./custom-config.ts',
|
|
34
|
+
]);
|
|
35
|
+
addGlobalOptions(command)
|
|
36
|
+
.option('--config <path>', 'Path to prisma-next.config.ts')
|
|
37
|
+
.action(async (options: FormatCommandOptions) => {
|
|
38
|
+
const flags = parseGlobalFlagsOrExit(options);
|
|
39
|
+
const ui = createTerminalUI(flags);
|
|
40
|
+
|
|
41
|
+
if (!flags.json && !flags.quiet) {
|
|
42
|
+
const displayConfigPath = options.config
|
|
43
|
+
? relative(process.cwd(), resolve(options.config))
|
|
44
|
+
: 'prisma-next.config.ts';
|
|
45
|
+
ui.stderr(
|
|
46
|
+
formatStyledHeader({
|
|
47
|
+
command: 'format',
|
|
48
|
+
description: 'Format your PSL contract source',
|
|
49
|
+
details: [{ label: 'config', value: displayConfigPath }],
|
|
50
|
+
flags,
|
|
51
|
+
}),
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const result = await executeFormat({ ...ifDefined('configPath', options.config) });
|
|
56
|
+
|
|
57
|
+
const exitCode = handleResult(result, flags, ui, (value) => {
|
|
58
|
+
if (flags.json) {
|
|
59
|
+
ui.output(JSON.stringify(value));
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
if (flags.quiet) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
if (value.formatted) {
|
|
66
|
+
ui.success(`Formatted ${relative(process.cwd(), value.path ?? '')}`);
|
|
67
|
+
} else {
|
|
68
|
+
ui.info('Nothing to format (contract source is not PSL).');
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
process.exit(exitCode);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
return command;
|
|
75
|
+
}
|
|
@@ -6,6 +6,10 @@ export type PackageManager = 'pnpm' | 'npm' | 'yarn' | 'bun' | 'deno';
|
|
|
6
6
|
|
|
7
7
|
const KNOWN: ReadonlySet<string> = new Set<PackageManager>(['pnpm', 'npm', 'yarn', 'bun', 'deno']);
|
|
8
8
|
|
|
9
|
+
function isPackageManager(name: string): name is PackageManager {
|
|
10
|
+
return KNOWN.has(name);
|
|
11
|
+
}
|
|
12
|
+
|
|
9
13
|
/**
|
|
10
14
|
* Resolves the package manager `init` should drive for `add` / `install`
|
|
11
15
|
* commands. Tries, in order:
|
|
@@ -28,12 +32,12 @@ const KNOWN: ReadonlySet<string> = new Set<PackageManager>(['pnpm', 'npm', 'yarn
|
|
|
28
32
|
*/
|
|
29
33
|
export async function detectPackageManager(cwd: string): Promise<PackageManager> {
|
|
30
34
|
const detected = await detect({ cwd });
|
|
31
|
-
if (detected &&
|
|
32
|
-
return detected.name
|
|
35
|
+
if (detected && isPackageManager(detected.name)) {
|
|
36
|
+
return detected.name;
|
|
33
37
|
}
|
|
34
38
|
const userAgent = getUserAgent();
|
|
35
|
-
if (userAgent !== null &&
|
|
36
|
-
return userAgent
|
|
39
|
+
if (userAgent !== null && isPackageManager(userAgent)) {
|
|
40
|
+
return userAgent;
|
|
37
41
|
}
|
|
38
42
|
return 'npm';
|
|
39
43
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { blindCast } from '@prisma-next/utils/casts';
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* The package.json `scripts` entries `init` adds idempotently (FR3.5).
|
|
3
5
|
* The script *name* mirrors the CLI subcommand path (`contract:emit` →
|
|
@@ -58,10 +60,18 @@ export function mergePackageScripts(
|
|
|
58
60
|
existing: string,
|
|
59
61
|
required: readonly RequiredScript[] = REQUIRED_SCRIPTS,
|
|
60
62
|
): PackageScriptsMergeResult {
|
|
61
|
-
const parsed =
|
|
63
|
+
const parsed = blindCast<
|
|
64
|
+
Record<string, unknown>,
|
|
65
|
+
'JSON.parse returns `unknown`; package.json is a JSON object so its top level is a string-keyed record'
|
|
66
|
+
>(JSON.parse(existing));
|
|
62
67
|
const scripts: Record<string, string> =
|
|
63
68
|
typeof parsed['scripts'] === 'object' && parsed['scripts'] !== null
|
|
64
|
-
? {
|
|
69
|
+
? {
|
|
70
|
+
...blindCast<
|
|
71
|
+
Record<string, string>,
|
|
72
|
+
'guarded above: parsed.scripts is a non-null object; package.json `scripts` values are command strings'
|
|
73
|
+
>(parsed['scripts']),
|
|
74
|
+
}
|
|
65
75
|
: {};
|
|
66
76
|
|
|
67
77
|
const warnings: string[] = [];
|
|
@@ -131,7 +141,10 @@ export interface EsmModuleTypeResult {
|
|
|
131
141
|
* ESM and we don't silently overwrite that.
|
|
132
142
|
*/
|
|
133
143
|
export function ensureEsmModuleType(existing: string): EsmModuleTypeResult {
|
|
134
|
-
const parsed =
|
|
144
|
+
const parsed = blindCast<
|
|
145
|
+
Record<string, unknown>,
|
|
146
|
+
'JSON.parse returns `unknown`; package.json is a JSON object so its top level is a string-keyed record'
|
|
147
|
+
>(JSON.parse(existing));
|
|
135
148
|
const currentType = parsed['type'];
|
|
136
149
|
|
|
137
150
|
if (currentType === 'module') {
|
|
@@ -74,7 +74,7 @@ export const contract = defineContract(
|
|
|
74
74
|
models: {
|
|
75
75
|
User: model('User', {
|
|
76
76
|
fields: {
|
|
77
|
-
id: field.id.
|
|
77
|
+
id: field.id.uuidv7String(),
|
|
78
78
|
email: field.text().unique(),
|
|
79
79
|
username: field.text().optional(),
|
|
80
80
|
name: field.text().optional(),
|
|
@@ -166,7 +166,7 @@ export const contract = defineContract(
|
|
|
166
166
|
models: {
|
|
167
167
|
User: model('User', {
|
|
168
168
|
fields: {
|
|
169
|
-
id: field.id.
|
|
169
|
+
id: field.id.uuidv7String(),
|
|
170
170
|
email: field.text().unique(),
|
|
171
171
|
username: field.text().optional(),
|
|
172
172
|
name: field.text().optional(),
|
|
@@ -180,10 +180,10 @@ export const contract = defineContract(
|
|
|
180
180
|
|
|
181
181
|
Post: model('Post', {
|
|
182
182
|
fields: {
|
|
183
|
-
id: field.id.
|
|
183
|
+
id: field.id.uuidv7String(),
|
|
184
184
|
title: field.text(),
|
|
185
185
|
content: field.text().optional(),
|
|
186
|
-
authorId: field.
|
|
186
|
+
authorId: field.uuidString(),
|
|
187
187
|
createdAt: field.temporal.createdAt(),
|
|
188
188
|
updatedAt: field.temporal.updatedAt(),
|
|
189
189
|
},
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
import { loadConfig } from '@prisma-next/config-loader';
|
|
1
2
|
import type { AuthoringPslBlockDescriptorNamespace } from '@prisma-next/framework-components/authoring';
|
|
2
3
|
import type { CoreSchemaView } from '@prisma-next/framework-components/control';
|
|
3
4
|
import type { PslDocumentAst } from '@prisma-next/framework-components/psl-ast';
|
|
4
5
|
import { notOk, ok, type Result } from '@prisma-next/utils/result';
|
|
5
6
|
import { relative, resolve } from 'pathe';
|
|
6
|
-
import { loadConfig } from '../config-loader';
|
|
7
7
|
import { createControlClient } from '../control-api/client';
|
|
8
8
|
import {
|
|
9
9
|
CliStructuredError,
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import {
|
|
3
|
+
addGlobalOptions,
|
|
4
|
+
setCommandDescriptions,
|
|
5
|
+
setCommandExamples,
|
|
6
|
+
} from '../utils/command-helpers';
|
|
7
|
+
|
|
8
|
+
export function createLspCommand(): Command {
|
|
9
|
+
const command = new Command('lsp');
|
|
10
|
+
setCommandDescriptions(
|
|
11
|
+
command,
|
|
12
|
+
'Start the Prisma Next language server',
|
|
13
|
+
'Launches a Language Server Protocol server that publishes PSL parse diagnostics\n' +
|
|
14
|
+
'and handles whole-document PSL formatting for the schema inputs declared in\n' +
|
|
15
|
+
'your config (contract.source.inputs). Formatting uses the Prisma Next PSL\n' +
|
|
16
|
+
'formatter and the formatter block from the project config.\n' +
|
|
17
|
+
'Communicates over stdio; intended to be spawned by an\n' +
|
|
18
|
+
'editor, not run interactively. The server keeps running until the editor client\n' +
|
|
19
|
+
'disconnects.',
|
|
20
|
+
);
|
|
21
|
+
setCommandExamples(command, ['prisma-next lsp --stdio']);
|
|
22
|
+
addGlobalOptions(command)
|
|
23
|
+
.option('--stdio', 'Communicate with the editor over stdio (the default and only transport)')
|
|
24
|
+
.action(async () => {
|
|
25
|
+
// Lazy import so `vscode-languageserver` stays off every other command's
|
|
26
|
+
// startup path — only `prisma-next lsp` pays its load cost.
|
|
27
|
+
const { startServer } = await import('@prisma-next/language-server');
|
|
28
|
+
startServer();
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
return command;
|
|
32
|
+
}
|
package/src/commands/migrate.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { loadConfig } from '@prisma-next/config-loader';
|
|
2
3
|
import type { Contract } from '@prisma-next/contract/types';
|
|
3
4
|
import { createControlStack } from '@prisma-next/framework-components/control';
|
|
4
5
|
import { type ContractSpaceMember, requireHeadRef } from '@prisma-next/migration-tools/aggregate';
|
|
@@ -11,7 +12,6 @@ import { readRefs } from '@prisma-next/migration-tools/refs';
|
|
|
11
12
|
import { ifDefined } from '@prisma-next/utils/defined';
|
|
12
13
|
import { notOk, ok, type Result } from '@prisma-next/utils/result';
|
|
13
14
|
import { Command } from 'commander';
|
|
14
|
-
import { loadConfig } from '../config-loader';
|
|
15
15
|
import { createControlClient } from '../control-api/client';
|
|
16
16
|
import { planMemberPath } from '../control-api/operations/migrate';
|
|
17
17
|
import type {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
|
|
2
2
|
import { readFile } from 'node:fs/promises';
|
|
3
|
+
import { loadConfig } from '@prisma-next/config-loader';
|
|
3
4
|
import { createControlStack } from '@prisma-next/framework-components/control';
|
|
4
5
|
import type {
|
|
5
6
|
ContractSpaceAggregate,
|
|
@@ -25,7 +26,6 @@ import { ifDefined } from '@prisma-next/utils/defined';
|
|
|
25
26
|
import { notOk, ok, type Result } from '@prisma-next/utils/result';
|
|
26
27
|
import { Command } from 'commander';
|
|
27
28
|
import { join, relative } from 'pathe';
|
|
28
|
-
import { loadConfig } from '../config-loader';
|
|
29
29
|
import {
|
|
30
30
|
type CliStructuredError,
|
|
31
31
|
errorAmbiguousMigrationRef,
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
import { loadConfig } from '@prisma-next/config-loader';
|
|
1
2
|
import { EMPTY_CONTRACT_HASH } from '@prisma-next/migration-tools/constants';
|
|
2
3
|
import type { MigrationGraph } from '@prisma-next/migration-tools/graph';
|
|
3
4
|
import { ifDefined } from '@prisma-next/utils/defined';
|
|
4
5
|
import { ok, type Result } from '@prisma-next/utils/result';
|
|
5
6
|
import { Command } from 'commander';
|
|
6
|
-
import { loadConfig } from '../config-loader';
|
|
7
7
|
import type { CliStructuredError } from '../utils/cli-errors';
|
|
8
8
|
import {
|
|
9
9
|
addGlobalOptions,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { loadConfig } from '@prisma-next/config-loader';
|
|
1
2
|
import type {
|
|
2
3
|
ContractSpaceAggregate,
|
|
3
4
|
ContractSpaceMember,
|
|
@@ -13,7 +14,6 @@ import {
|
|
|
13
14
|
import { ifDefined } from '@prisma-next/utils/defined';
|
|
14
15
|
import { notOk, ok, type Result } from '@prisma-next/utils/result';
|
|
15
16
|
import { Command } from 'commander';
|
|
16
|
-
import { loadConfig } from '../config-loader';
|
|
17
17
|
import {
|
|
18
18
|
type CliStructuredError,
|
|
19
19
|
errorInvalidSpaceId,
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
import { loadConfig } from '@prisma-next/config-loader';
|
|
1
2
|
import type { LedgerEntryRecord } from '@prisma-next/contract/types';
|
|
2
3
|
import { MigrationToolsError } from '@prisma-next/migration-tools/errors';
|
|
3
4
|
import { ifDefined } from '@prisma-next/utils/defined';
|
|
4
5
|
import { notOk, ok, type Result } from '@prisma-next/utils/result';
|
|
5
6
|
import { Command } from 'commander';
|
|
6
|
-
import { loadConfig } from '../config-loader';
|
|
7
7
|
import { createControlClient } from '../control-api/client';
|
|
8
8
|
import {
|
|
9
9
|
CliStructuredError,
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
import { readFile } from 'node:fs/promises';
|
|
12
|
+
import { loadConfig } from '@prisma-next/config-loader';
|
|
12
13
|
import type { Contract } from '@prisma-next/contract/types';
|
|
13
14
|
import { getEmittedArtifactPaths } from '@prisma-next/emitter';
|
|
14
15
|
import { APP_SPACE_ID, createControlStack } from '@prisma-next/framework-components/control';
|
|
@@ -25,7 +26,6 @@ import { writeMigrationTs } from '@prisma-next/migration-tools/migration-ts';
|
|
|
25
26
|
import { notOk, ok, type Result } from '@prisma-next/utils/result';
|
|
26
27
|
import { Command } from 'commander';
|
|
27
28
|
import { join, relative } from 'pathe';
|
|
28
|
-
import { loadConfig } from '../config-loader';
|
|
29
29
|
import {
|
|
30
30
|
CliStructuredError,
|
|
31
31
|
errorFileNotFound,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { loadConfig } from '@prisma-next/config-loader';
|
|
2
3
|
import type { Contract } from '@prisma-next/contract/types';
|
|
3
4
|
import { getEmittedArtifactPaths } from '@prisma-next/emitter';
|
|
4
5
|
import {
|
|
@@ -21,7 +22,6 @@ import { writeMigrationTs } from '@prisma-next/migration-tools/migration-ts';
|
|
|
21
22
|
import { notOk, ok, type Result } from '@prisma-next/utils/result';
|
|
22
23
|
import { Command } from 'commander';
|
|
23
24
|
import { join, relative } from 'pathe';
|
|
24
|
-
import { loadConfig } from '../config-loader';
|
|
25
25
|
import {
|
|
26
26
|
type CliErrorConflict,
|
|
27
27
|
CliStructuredError,
|
|
@@ -118,7 +118,7 @@ async function runPlannerLeg(
|
|
|
118
118
|
let plannedOps: readonly MigrationPlanOperation[] = [];
|
|
119
119
|
let hasPlaceholders = false;
|
|
120
120
|
try {
|
|
121
|
-
plannedOps = plannerResult.plan.operations;
|
|
121
|
+
plannedOps = await Promise.all(plannerResult.plan.operations);
|
|
122
122
|
if (plannedOps.length === 0) {
|
|
123
123
|
return notOk(
|
|
124
124
|
errorMigrationPlanningFailed({
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { loadConfig } from '@prisma-next/config-loader';
|
|
2
3
|
import type { Contract } from '@prisma-next/contract/types';
|
|
3
4
|
import {
|
|
4
5
|
APP_SPACE_ID,
|
|
@@ -13,7 +14,6 @@ import { ifDefined } from '@prisma-next/utils/defined';
|
|
|
13
14
|
import { notOk, ok, type Result } from '@prisma-next/utils/result';
|
|
14
15
|
import { Command } from 'commander';
|
|
15
16
|
import { relative } from 'pathe';
|
|
16
|
-
import { loadConfig } from '../config-loader';
|
|
17
17
|
import { createControlClient } from '../control-api/client';
|
|
18
18
|
import {
|
|
19
19
|
type CliStructuredError,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { loadConfig } from '@prisma-next/config-loader';
|
|
1
2
|
import type { LedgerEntryRecord } from '@prisma-next/contract/types';
|
|
2
3
|
import type {
|
|
3
4
|
ContractMarkerRecordLike,
|
|
@@ -17,7 +18,6 @@ import { ifDefined } from '@prisma-next/utils/defined';
|
|
|
17
18
|
import { notOk, ok, type Result } from '@prisma-next/utils/result';
|
|
18
19
|
import { dim, yellow } from 'colorette';
|
|
19
20
|
import { Command } from 'commander';
|
|
20
|
-
import { loadConfig } from '../config-loader';
|
|
21
21
|
import { createControlClient } from '../control-api/client';
|
|
22
22
|
import {
|
|
23
23
|
CliStructuredError,
|
package/src/commands/ref.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { loadConfig } from '@prisma-next/config-loader';
|
|
2
3
|
import { EMPTY_CONTRACT_HASH } from '@prisma-next/migration-tools/constants';
|
|
3
4
|
import { MigrationToolsError } from '@prisma-next/migration-tools/errors';
|
|
4
5
|
import { findLatestMigration, isGraphNode } from '@prisma-next/migration-tools/migration-graph';
|
|
@@ -14,7 +15,6 @@ import {
|
|
|
14
15
|
import { notOk, ok, type Result } from '@prisma-next/utils/result';
|
|
15
16
|
import { Command } from 'commander';
|
|
16
17
|
import { join } from 'pathe';
|
|
17
|
-
import { loadConfig } from '../config-loader';
|
|
18
18
|
import {
|
|
19
19
|
CliStructuredError,
|
|
20
20
|
errorFileNotFound,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { mkdir } from 'node:fs/promises';
|
|
2
|
+
import { loadConfig } from '@prisma-next/config-loader';
|
|
2
3
|
import type { Contract } from '@prisma-next/contract/types';
|
|
3
4
|
import { emit, getEmittedArtifactPaths } from '@prisma-next/emitter';
|
|
4
5
|
import { createControlStack } from '@prisma-next/framework-components/control';
|
|
@@ -7,7 +8,6 @@ import { blindCast } from '@prisma-next/utils/casts';
|
|
|
7
8
|
import { ifDefined } from '@prisma-next/utils/defined';
|
|
8
9
|
import type { JsonObject } from '@prisma-next/utils/json';
|
|
9
10
|
import { dirname, join } from 'pathe';
|
|
10
|
-
import { loadConfig } from '../../config-loader';
|
|
11
11
|
import { errorContractConfigMissing, errorRuntime } from '../../utils/cli-errors';
|
|
12
12
|
import { queueEmitByOutput } from '../../utils/emit-queue';
|
|
13
13
|
import { toExtensionInputs } from '../../utils/extension-pack-inputs';
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { readFile, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { EOL } from 'node:os';
|
|
3
|
+
import { loadConfig } from '@prisma-next/config-loader';
|
|
4
|
+
import { type FormatOptions, format, PslFormatError } from '@prisma-next/psl-parser/format';
|
|
5
|
+
import { notOk, ok, type Result } from '@prisma-next/utils/result';
|
|
6
|
+
import { CliStructuredError, errorRuntime, errorUnexpected } from '../../utils/cli-errors';
|
|
7
|
+
|
|
8
|
+
export interface FormatOperationOptions {
|
|
9
|
+
readonly configPath?: string;
|
|
10
|
+
readonly eol?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface FormatOperationResult {
|
|
14
|
+
readonly formatted: boolean;
|
|
15
|
+
readonly path?: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function resolveNewline(
|
|
19
|
+
formatterNewline: 'LF' | 'CRLF' | undefined,
|
|
20
|
+
eol: string,
|
|
21
|
+
): 'LF' | 'CRLF' {
|
|
22
|
+
if (formatterNewline !== undefined) {
|
|
23
|
+
return formatterNewline;
|
|
24
|
+
}
|
|
25
|
+
return eol === '\r\n' ? 'CRLF' : 'LF';
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export async function executeFormat(
|
|
29
|
+
options: FormatOperationOptions,
|
|
30
|
+
): Promise<Result<FormatOperationResult, CliStructuredError>> {
|
|
31
|
+
const eol = options.eol ?? EOL;
|
|
32
|
+
|
|
33
|
+
let config: Awaited<ReturnType<typeof loadConfig>>;
|
|
34
|
+
try {
|
|
35
|
+
config = await loadConfig(options.configPath);
|
|
36
|
+
} catch (error) {
|
|
37
|
+
if (CliStructuredError.is(error)) {
|
|
38
|
+
return notOk(error);
|
|
39
|
+
}
|
|
40
|
+
return notOk(errorUnexpected(error instanceof Error ? error.message : String(error)));
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const source = config.contract?.source;
|
|
44
|
+
if (source?.sourceFormat !== 'psl') {
|
|
45
|
+
return ok({ formatted: false });
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const inputPath = source.inputs?.[0];
|
|
49
|
+
if (inputPath === undefined) {
|
|
50
|
+
return ok({ formatted: false });
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
let contents: string;
|
|
54
|
+
try {
|
|
55
|
+
contents = await readFile(inputPath, 'utf-8');
|
|
56
|
+
} catch (error) {
|
|
57
|
+
return notOk(
|
|
58
|
+
errorRuntime('Failed to read contract source file', {
|
|
59
|
+
why: error instanceof Error ? error.message : String(error),
|
|
60
|
+
fix: `Check that ${inputPath} exists and is readable.`,
|
|
61
|
+
}),
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const formatOptions: FormatOptions = {
|
|
66
|
+
indent: config.formatter?.indent ?? 2,
|
|
67
|
+
newline: resolveNewline(config.formatter?.newline, eol),
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
let formatted: string;
|
|
71
|
+
try {
|
|
72
|
+
formatted = format(contents, formatOptions);
|
|
73
|
+
} catch (error) {
|
|
74
|
+
if (error instanceof PslFormatError) {
|
|
75
|
+
return notOk(
|
|
76
|
+
errorRuntime('Cannot format PSL with parse errors', {
|
|
77
|
+
why: error.message,
|
|
78
|
+
fix: 'Fix the parse errors in your schema and try again.',
|
|
79
|
+
meta: { diagnostics: error.diagnostics },
|
|
80
|
+
}),
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
return notOk(errorUnexpected(error instanceof Error ? error.message : String(error)));
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
try {
|
|
87
|
+
await writeFile(inputPath, formatted, 'utf-8');
|
|
88
|
+
} catch (error) {
|
|
89
|
+
return notOk(
|
|
90
|
+
errorRuntime('Failed to write formatted contract source file', {
|
|
91
|
+
why: error instanceof Error ? error.message : String(error),
|
|
92
|
+
fix: `Check that ${inputPath} is writable.`,
|
|
93
|
+
}),
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return ok({ formatted: true, path: inputPath });
|
|
98
|
+
}
|
package/src/exports/index.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// CLI-specific exports
|
|
2
2
|
export { createContractEmitCommand } from '../commands/contract-emit';
|
|
3
|
+
export { createFormatCommand } from '../commands/format';
|
|
3
4
|
export type { LoadTsContractOptions } from '../load-ts-contract';
|
|
4
5
|
export { loadContractFromTs } from '../load-ts-contract';
|
package/src/migration-cli.ts
CHANGED
|
@@ -45,6 +45,7 @@
|
|
|
45
45
|
import { readFileSync, realpathSync, writeFileSync } from 'node:fs';
|
|
46
46
|
import type { Writable } from 'node:stream';
|
|
47
47
|
import { fileURLToPath } from 'node:url';
|
|
48
|
+
import { loadConfig } from '@prisma-next/config-loader';
|
|
48
49
|
import {
|
|
49
50
|
CliStructuredError,
|
|
50
51
|
errorMigrationCliInvalidConfigArg,
|
|
@@ -57,7 +58,6 @@ import type { MigrationMetadata } from '@prisma-next/migration-tools/metadata';
|
|
|
57
58
|
import { buildMigrationArtifacts, type Migration } from '@prisma-next/migration-tools/migration';
|
|
58
59
|
import { Cli, Command, Option, UsageError } from 'clipanion';
|
|
59
60
|
import { dirname, join } from 'pathe';
|
|
60
|
-
import { loadConfig } from './config-loader';
|
|
61
61
|
|
|
62
62
|
/**
|
|
63
63
|
* Constructor shape accepted by `MigrationCLI.run`. `Migration` subclasses
|
|
@@ -505,15 +505,15 @@ function readExistingMetadata(metadataPath: string): Partial<MigrationMetadata>
|
|
|
505
505
|
* legitimate site for combining config loading, stack assembly, and
|
|
506
506
|
* filesystem persistence.
|
|
507
507
|
*/
|
|
508
|
-
function serializeMigrationToDisk(
|
|
508
|
+
async function serializeMigrationToDisk(
|
|
509
509
|
instance: Migration,
|
|
510
510
|
migrationDir: string,
|
|
511
511
|
dryRun: boolean,
|
|
512
512
|
stdout: MigrationCliWritable,
|
|
513
|
-
): void {
|
|
513
|
+
): Promise<void> {
|
|
514
514
|
const metadataPath = join(migrationDir, 'migration.json');
|
|
515
515
|
const existing = readExistingMetadata(metadataPath);
|
|
516
|
-
const { opsJson, metadataJson } = buildMigrationArtifacts(instance, existing);
|
|
516
|
+
const { opsJson, metadataJson } = await buildMigrationArtifacts(instance, existing);
|
|
517
517
|
|
|
518
518
|
if (dryRun) {
|
|
519
519
|
stdout.write(`--- migration.json ---\n${metadataJson}\n`);
|
|
@@ -572,6 +572,6 @@ async function runMigration(
|
|
|
572
572
|
const stack = createControlStack(config);
|
|
573
573
|
const instance = new MigrationClass(stack);
|
|
574
574
|
|
|
575
|
-
serializeMigrationToDisk(instance, migrationDir, parsed.dryRun, ctx.stdout);
|
|
575
|
+
await serializeMigrationToDisk(instance, migrationDir, parsed.dryRun, ctx.stdout);
|
|
576
576
|
void ctx.stderr;
|
|
577
577
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { readFile } from 'node:fs/promises';
|
|
2
2
|
import { relative, resolve } from 'node:path';
|
|
3
|
+
import { loadConfig } from '@prisma-next/config-loader';
|
|
3
4
|
import { hasMigrations } from '@prisma-next/framework-components/control';
|
|
4
5
|
import { notOk, ok, type Result } from '@prisma-next/utils/result';
|
|
5
6
|
import type { Command } from 'commander';
|
|
6
|
-
import { loadConfig } from '../config-loader';
|
|
7
7
|
import { createControlClient } from '../control-api/client';
|
|
8
8
|
import type { ControlClient } from '../control-api/types';
|
|
9
9
|
import {
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
import { getEmittedArtifactPaths } from "@prisma-next/emitter";
|
|
2
|
-
import { errorConfigFileNotFound, errorConfigValidation, errorUnexpected } from "@prisma-next/errors/control";
|
|
3
|
-
import { ifDefined } from "@prisma-next/utils/defined";
|
|
4
|
-
import { dirname, resolve } from "pathe";
|
|
5
|
-
import { ConfigValidationError, validateConfig } from "@prisma-next/config/config-validation";
|
|
6
|
-
import { loadConfig } from "c12";
|
|
7
|
-
import { normalizeContractConfig } from "@prisma-next/config/config-types";
|
|
8
|
-
//#region src/config-path-validation.ts
|
|
9
|
-
function throwValidation(field, why) {
|
|
10
|
-
throw new ConfigValidationError(field, why);
|
|
11
|
-
}
|
|
12
|
-
function finalizeContractSource(source, configDir) {
|
|
13
|
-
const resolvedInputs = source.inputs?.map((input) => resolve(configDir, input));
|
|
14
|
-
if (resolvedInputs === void 0) return source;
|
|
15
|
-
return {
|
|
16
|
-
...source,
|
|
17
|
-
inputs: resolvedInputs
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
function validateNoOutputsAreInputs(inputs, output) {
|
|
21
|
-
if (inputs === void 0 || output === void 0) return;
|
|
22
|
-
let emittedArtifactPaths;
|
|
23
|
-
try {
|
|
24
|
-
emittedArtifactPaths = getEmittedArtifactPaths(output);
|
|
25
|
-
} catch (error) {
|
|
26
|
-
throwValidation("contract.output", error instanceof Error ? error.message : String(error));
|
|
27
|
-
}
|
|
28
|
-
const emittedPaths = new Set([emittedArtifactPaths.jsonPath, emittedArtifactPaths.dtsPath]);
|
|
29
|
-
for (const input of inputs) if (emittedPaths.has(input)) throwValidation("contract.source.inputs[]", "Config.contract.source.inputs must not include emitted artifact paths derived from contract.output");
|
|
30
|
-
}
|
|
31
|
-
function finalizeConfig(config, configDir) {
|
|
32
|
-
if (!config.contract) return config;
|
|
33
|
-
const contract = normalizeContractConfig(config.contract);
|
|
34
|
-
const source = finalizeContractSource(contract.source, configDir);
|
|
35
|
-
const output = resolve(configDir, contract.output);
|
|
36
|
-
validateNoOutputsAreInputs(source.inputs, output);
|
|
37
|
-
return {
|
|
38
|
-
...config,
|
|
39
|
-
contract: {
|
|
40
|
-
...contract,
|
|
41
|
-
source,
|
|
42
|
-
output
|
|
43
|
-
}
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
//#endregion
|
|
47
|
-
//#region src/config-loader.ts
|
|
48
|
-
async function loadValidatedConfig(configPath) {
|
|
49
|
-
const cwd = process.cwd();
|
|
50
|
-
const resolvedConfigPath = configPath ? resolve(cwd, configPath) : void 0;
|
|
51
|
-
const configCwd = resolvedConfigPath ? dirname(resolvedConfigPath) : cwd;
|
|
52
|
-
const result = await loadConfig({
|
|
53
|
-
name: "prisma-next",
|
|
54
|
-
...ifDefined("configFile", resolvedConfigPath),
|
|
55
|
-
cwd: configCwd
|
|
56
|
-
});
|
|
57
|
-
if (resolvedConfigPath && result.configFile !== resolvedConfigPath) throw errorConfigFileNotFound(resolvedConfigPath);
|
|
58
|
-
if (!result.config || Object.keys(result.config).length === 0) throw errorConfigFileNotFound(result.configFile || resolvedConfigPath || configPath);
|
|
59
|
-
validateConfig(result.config);
|
|
60
|
-
const loadedConfigDir = result.configFile ? dirname(result.configFile) : configCwd;
|
|
61
|
-
return finalizeConfig(result.config, loadedConfigDir);
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Loads the Prisma Next config from a TypeScript file.
|
|
65
|
-
* Supports both default export and named export.
|
|
66
|
-
* Uses c12 to automatically handle TypeScript compilation and config file discovery.
|
|
67
|
-
*
|
|
68
|
-
* @param configPath - Optional path to config file. Defaults to `./prisma-next.config.ts` in current directory.
|
|
69
|
-
* @returns The loaded config object.
|
|
70
|
-
* @throws Error if config file doesn't exist or is invalid.
|
|
71
|
-
*/
|
|
72
|
-
async function loadConfig$1(configPath) {
|
|
73
|
-
try {
|
|
74
|
-
return await loadValidatedConfig(configPath);
|
|
75
|
-
} catch (error) {
|
|
76
|
-
if (error instanceof ConfigValidationError) throw errorConfigValidation(error.field, { why: error.why });
|
|
77
|
-
if (error instanceof Error && "code" in error && typeof error.code === "string") throw error;
|
|
78
|
-
if (error instanceof Error) {
|
|
79
|
-
if (error.message.includes("not found") || error.message.includes("Cannot find") || error.message.includes("ENOENT")) throw errorConfigFileNotFound(configPath ? resolve(process.cwd(), configPath) : void 0, { why: error.message });
|
|
80
|
-
throw errorUnexpected(error.message, { why: `Failed to load config: ${error.message}` });
|
|
81
|
-
}
|
|
82
|
-
throw errorUnexpected(String(error));
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
//#endregion
|
|
86
|
-
export { loadConfig$1 as t };
|
|
87
|
-
|
|
88
|
-
//# sourceMappingURL=config-loader-p9JMrekQ.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"config-loader-p9JMrekQ.mjs","names":["loadConfigC12","loadConfig"],"sources":["../src/config-path-validation.ts","../src/config-loader.ts"],"sourcesContent":["import {\n type ContractSourceProvider,\n normalizeContractConfig,\n type PrismaNextConfig,\n} from '@prisma-next/config/config-types';\nimport { ConfigValidationError } from '@prisma-next/config/config-validation';\nimport { getEmittedArtifactPaths } from '@prisma-next/emitter';\nimport { resolve } from 'pathe';\n\nfunction throwValidation(field: string, why: string): never {\n throw new ConfigValidationError(field, why);\n}\n\nfunction finalizeContractSource(\n source: ContractSourceProvider,\n configDir: string,\n): ContractSourceProvider {\n const resolvedInputs = source.inputs?.map((input) => resolve(configDir, input));\n if (resolvedInputs === undefined) {\n return source;\n }\n\n return {\n ...source,\n inputs: resolvedInputs,\n };\n}\n\nfunction validateNoOutputsAreInputs(\n inputs: readonly string[] | undefined,\n output: string | undefined,\n): void {\n if (inputs === undefined || output === undefined) {\n return;\n }\n\n let emittedArtifactPaths: ReturnType<typeof getEmittedArtifactPaths>;\n try {\n emittedArtifactPaths = getEmittedArtifactPaths(output);\n } catch (error) {\n throwValidation('contract.output', error instanceof Error ? error.message : String(error));\n }\n\n const emittedPaths = new Set([emittedArtifactPaths.jsonPath, emittedArtifactPaths.dtsPath]);\n\n for (const input of inputs) {\n if (emittedPaths.has(input)) {\n throwValidation(\n 'contract.source.inputs[]',\n 'Config.contract.source.inputs must not include emitted artifact paths derived from contract.output',\n );\n }\n }\n}\n\nexport function finalizeConfig(config: PrismaNextConfig, configDir: string): PrismaNextConfig {\n if (!config.contract) {\n return config;\n }\n const contract = normalizeContractConfig(config.contract);\n const source = finalizeContractSource(contract.source, configDir);\n const output = resolve(configDir, contract.output);\n\n validateNoOutputsAreInputs(source.inputs, output);\n\n return {\n ...config,\n contract: {\n ...contract,\n source,\n output,\n },\n };\n}\n","import type { PrismaNextConfig } from '@prisma-next/config/config-types';\nimport { ConfigValidationError, validateConfig } from '@prisma-next/config/config-validation';\nimport {\n errorConfigFileNotFound,\n errorConfigValidation,\n errorUnexpected,\n} from '@prisma-next/errors/control';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport { loadConfig as loadConfigC12 } from 'c12';\nimport { dirname, resolve } from 'pathe';\nimport { finalizeConfig } from './config-path-validation';\n\nasync function loadValidatedConfig(configPath?: string): Promise<PrismaNextConfig> {\n const cwd = process.cwd();\n const resolvedConfigPath = configPath ? resolve(cwd, configPath) : undefined;\n const configCwd = resolvedConfigPath ? dirname(resolvedConfigPath) : cwd;\n\n const result = await loadConfigC12<PrismaNextConfig>({\n name: 'prisma-next',\n ...ifDefined('configFile', resolvedConfigPath),\n cwd: configCwd,\n });\n\n // When a specific config file was requested, verify it was actually loaded\n // (c12 falls back to searching by name if the specified file doesn't exist)\n if (resolvedConfigPath && result.configFile !== resolvedConfigPath) {\n throw errorConfigFileNotFound(resolvedConfigPath);\n }\n\n // Check if config is missing or empty (c12 may return empty object when file doesn't exist)\n if (!result.config || Object.keys(result.config).length === 0) {\n // Use c12's configFile if available, otherwise use explicit configPath, otherwise omit path\n const displayPath = result.configFile || resolvedConfigPath || configPath;\n throw errorConfigFileNotFound(displayPath);\n }\n\n // Validate config structure\n validateConfig(result.config);\n\n const loadedConfigDir = result.configFile ? dirname(result.configFile) : configCwd;\n return finalizeConfig(result.config, loadedConfigDir);\n}\n\n/**\n * Loads the Prisma Next config from a TypeScript file.\n * Supports both default export and named export.\n * Uses c12 to automatically handle TypeScript compilation and config file discovery.\n *\n * @param configPath - Optional path to config file. Defaults to `./prisma-next.config.ts` in current directory.\n * @returns The loaded config object.\n * @throws Error if config file doesn't exist or is invalid.\n */\nexport async function loadConfig(configPath?: string): Promise<PrismaNextConfig> {\n try {\n return await loadValidatedConfig(configPath);\n } catch (error) {\n if (error instanceof ConfigValidationError) {\n throw errorConfigValidation(error.field, {\n why: error.why,\n });\n }\n\n // Re-throw structured errors as-is\n if (\n error instanceof Error &&\n 'code' in error &&\n typeof (error as { code: string }).code === 'string'\n ) {\n throw error;\n }\n\n if (error instanceof Error) {\n // Check for file not found errors\n if (\n error.message.includes('not found') ||\n error.message.includes('Cannot find') ||\n error.message.includes('ENOENT')\n ) {\n // Use resolved path if available, otherwise use original configPath\n const displayPath = configPath ? resolve(process.cwd(), configPath) : undefined;\n throw errorConfigFileNotFound(displayPath, {\n why: error.message,\n });\n }\n // For other errors, wrap in unexpected error\n throw errorUnexpected(error.message, {\n why: `Failed to load config: ${error.message}`,\n });\n }\n throw errorUnexpected(String(error));\n }\n}\n"],"mappings":";;;;;;;;AASA,SAAS,gBAAgB,OAAe,KAAoB;CAC1D,MAAM,IAAI,sBAAsB,OAAO,GAAG;AAC5C;AAEA,SAAS,uBACP,QACA,WACwB;CACxB,MAAM,iBAAiB,OAAO,QAAQ,KAAK,UAAU,QAAQ,WAAW,KAAK,CAAC;CAC9E,IAAI,mBAAmB,KAAA,GACrB,OAAO;CAGT,OAAO;EACL,GAAG;EACH,QAAQ;CACV;AACF;AAEA,SAAS,2BACP,QACA,QACM;CACN,IAAI,WAAW,KAAA,KAAa,WAAW,KAAA,GACrC;CAGF,IAAI;CACJ,IAAI;EACF,uBAAuB,wBAAwB,MAAM;CACvD,SAAS,OAAO;EACd,gBAAgB,mBAAmB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;CAC3F;CAEA,MAAM,eAAe,IAAI,IAAI,CAAC,qBAAqB,UAAU,qBAAqB,OAAO,CAAC;CAE1F,KAAK,MAAM,SAAS,QAClB,IAAI,aAAa,IAAI,KAAK,GACxB,gBACE,4BACA,oGACF;AAGN;AAEA,SAAgB,eAAe,QAA0B,WAAqC;CAC5F,IAAI,CAAC,OAAO,UACV,OAAO;CAET,MAAM,WAAW,wBAAwB,OAAO,QAAQ;CACxD,MAAM,SAAS,uBAAuB,SAAS,QAAQ,SAAS;CAChE,MAAM,SAAS,QAAQ,WAAW,SAAS,MAAM;CAEjD,2BAA2B,OAAO,QAAQ,MAAM;CAEhD,OAAO;EACL,GAAG;EACH,UAAU;GACR,GAAG;GACH;GACA;EACF;CACF;AACF;;;AC7DA,eAAe,oBAAoB,YAAgD;CACjF,MAAM,MAAM,QAAQ,IAAI;CACxB,MAAM,qBAAqB,aAAa,QAAQ,KAAK,UAAU,IAAI,KAAA;CACnE,MAAM,YAAY,qBAAqB,QAAQ,kBAAkB,IAAI;CAErE,MAAM,SAAS,MAAMA,WAAgC;EACnD,MAAM;EACN,GAAG,UAAU,cAAc,kBAAkB;EAC7C,KAAK;CACP,CAAC;CAID,IAAI,sBAAsB,OAAO,eAAe,oBAC9C,MAAM,wBAAwB,kBAAkB;CAIlD,IAAI,CAAC,OAAO,UAAU,OAAO,KAAK,OAAO,MAAM,CAAC,CAAC,WAAW,GAG1D,MAAM,wBADc,OAAO,cAAc,sBAAsB,UACtB;CAI3C,eAAe,OAAO,MAAM;CAE5B,MAAM,kBAAkB,OAAO,aAAa,QAAQ,OAAO,UAAU,IAAI;CACzE,OAAO,eAAe,OAAO,QAAQ,eAAe;AACtD;;;;;;;;;;AAWA,eAAsBC,aAAW,YAAgD;CAC/E,IAAI;EACF,OAAO,MAAM,oBAAoB,UAAU;CAC7C,SAAS,OAAO;EACd,IAAI,iBAAiB,uBACnB,MAAM,sBAAsB,MAAM,OAAO,EACvC,KAAK,MAAM,IACb,CAAC;EAIH,IACE,iBAAiB,SACjB,UAAU,SACV,OAAQ,MAA2B,SAAS,UAE5C,MAAM;EAGR,IAAI,iBAAiB,OAAO;GAE1B,IACE,MAAM,QAAQ,SAAS,WAAW,KAClC,MAAM,QAAQ,SAAS,aAAa,KACpC,MAAM,QAAQ,SAAS,QAAQ,GAI/B,MAAM,wBADc,aAAa,QAAQ,QAAQ,IAAI,GAAG,UAAU,IAAI,KAAA,GAC3B,EACzC,KAAK,MAAM,QACb,CAAC;GAGH,MAAM,gBAAgB,MAAM,SAAS,EACnC,KAAK,0BAA0B,MAAM,UACvC,CAAC;EACH;EACA,MAAM,gBAAgB,OAAO,KAAK,CAAC;CACrC;AACF"}
|