@prisma-next/cli 0.8.0 → 0.9.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/README.md +8 -9
- package/dist/{cli-errors-D3_sMh2K.mjs → cli-errors-CF60g2cG.mjs} +40 -2
- package/dist/cli-errors-CF60g2cG.mjs.map +1 -0
- package/dist/cli.mjs +67 -19
- package/dist/cli.mjs.map +1 -1
- package/dist/{client-BCnP7cHo.mjs → client-Brv4qlfB.mjs} +28 -30
- package/dist/client-Brv4qlfB.mjs.map +1 -0
- package/dist/{command-helpers-BeZHkxV8.mjs → command-helpers-D3vL5yi8.mjs} +29 -6
- package/dist/command-helpers-D3vL5yi8.mjs.map +1 -0
- package/dist/commands/contract-emit.mjs +1 -1
- package/dist/commands/contract-infer.mjs +1 -1
- package/dist/commands/db-init.mjs +7 -7
- package/dist/commands/db-schema.mjs +5 -5
- package/dist/commands/db-sign.d.mts.map +1 -1
- package/dist/commands/db-sign.mjs +67 -25
- package/dist/commands/db-sign.mjs.map +1 -1
- package/dist/commands/db-update.d.mts.map +1 -1
- package/dist/commands/db-update.mjs +37 -9
- package/dist/commands/db-update.mjs.map +1 -1
- package/dist/commands/db-verify.d.mts.map +1 -1
- package/dist/commands/db-verify.mjs +1 -1
- package/dist/commands/migrate.d.mts +28 -0
- package/dist/commands/migrate.d.mts.map +1 -0
- package/dist/commands/{migration-apply.mjs → migrate.mjs} +65 -39
- package/dist/commands/migrate.mjs.map +1 -0
- package/dist/commands/migration-check.d.mts +18 -0
- package/dist/commands/migration-check.d.mts.map +1 -0
- package/dist/commands/migration-check.mjs +284 -0
- package/dist/commands/migration-check.mjs.map +1 -0
- package/dist/commands/migration-graph.d.mts +16 -0
- package/dist/commands/migration-graph.d.mts.map +1 -0
- package/dist/commands/migration-graph.mjs +141 -0
- package/dist/commands/migration-graph.mjs.map +1 -0
- package/dist/commands/migration-list.d.mts +20 -0
- package/dist/commands/migration-list.d.mts.map +1 -0
- package/dist/commands/migration-list.mjs +107 -0
- package/dist/commands/migration-list.mjs.map +1 -0
- package/dist/commands/migration-log.d.mts +21 -0
- package/dist/commands/migration-log.d.mts.map +1 -0
- package/dist/commands/migration-log.mjs +146 -0
- package/dist/commands/migration-log.mjs.map +1 -0
- package/dist/commands/migration-new.d.mts.map +1 -1
- package/dist/commands/migration-new.mjs +30 -29
- package/dist/commands/migration-new.mjs.map +1 -1
- package/dist/commands/migration-plan.d.mts +2 -2
- package/dist/commands/migration-plan.d.mts.map +1 -1
- package/dist/commands/migration-plan.mjs +1 -1
- package/dist/commands/migration-show.d.mts +1 -1
- package/dist/commands/migration-show.d.mts.map +1 -1
- package/dist/commands/migration-show.mjs +90 -52
- package/dist/commands/migration-show.mjs.map +1 -1
- package/dist/commands/migration-status.d.mts +5 -17
- package/dist/commands/migration-status.d.mts.map +1 -1
- package/dist/commands/migration-status.mjs +732 -1
- package/dist/commands/migration-status.mjs.map +1 -0
- package/dist/commands/ref.d.mts +34 -0
- package/dist/commands/ref.d.mts.map +1 -0
- package/dist/commands/{migration-ref.mjs → ref.mjs} +28 -57
- package/dist/commands/ref.mjs.map +1 -0
- package/dist/{contract-emit-9DBda5Ou.mjs → contract-emit-C3STUIBg.mjs} +6 -6
- package/dist/{contract-emit-9DBda5Ou.mjs.map → contract-emit-C3STUIBg.mjs.map} +1 -1
- package/dist/{contract-emit-B77TsJqf.mjs → contract-emit-iynA3BCA.mjs} +9 -5
- package/dist/contract-emit-iynA3BCA.mjs.map +1 -0
- package/dist/{contract-infer-ByxhPjpW.mjs → contract-infer-Cnj8G1E2.mjs} +5 -5
- package/dist/{contract-infer-ByxhPjpW.mjs.map → contract-infer-Cnj8G1E2.mjs.map} +1 -1
- package/dist/{contract-space-aggregate-loader-BrwKK6Q6.mjs → contract-space-aggregate-loader-pAc8CDfY.mjs} +4 -4
- package/dist/{contract-space-aggregate-loader-BrwKK6Q6.mjs.map → contract-space-aggregate-loader-pAc8CDfY.mjs.map} +1 -1
- package/dist/{db-verify-Czm5T-J4.mjs → db-verify-D7cyH_zz.mjs} +12 -9
- package/dist/db-verify-D7cyH_zz.mjs.map +1 -0
- package/dist/errors-Cw6kyTyV.mjs +56 -0
- package/dist/errors-Cw6kyTyV.mjs.map +1 -0
- package/dist/exports/control-api.d.mts +1 -1
- package/dist/exports/control-api.d.mts.map +1 -1
- package/dist/exports/control-api.mjs +2 -2
- package/dist/exports/index.mjs +1 -1
- package/dist/exports/index.mjs.map +1 -1
- package/dist/exports/init-output.mjs +1 -1
- package/dist/{framework-components-ChqVUxR-.mjs → framework-components-xFLFpZUO.mjs} +2 -2
- package/dist/{framework-components-ChqVUxR-.mjs.map → framework-components-xFLFpZUO.mjs.map} +1 -1
- package/dist/{global-flags-Icqpxk23.d.mts → global-flags-DGmw6Kqg.d.mts} +1 -1
- package/dist/{global-flags-Icqpxk23.d.mts.map → global-flags-DGmw6Kqg.d.mts.map} +1 -1
- package/dist/{migration-status-By9G5p2H.mjs → graph-render-eJDcLWny.mjs} +3 -692
- package/dist/graph-render-eJDcLWny.mjs.map +1 -0
- package/dist/{init-B-k3a1Qw.mjs → init-Bqg5JWg7.mjs} +133 -61
- package/dist/init-Bqg5JWg7.mjs.map +1 -0
- package/dist/{inspect-live-schema-DxdBd4Er.mjs → inspect-live-schema-CWLK_lgs.mjs} +4 -4
- package/dist/{inspect-live-schema-DxdBd4Er.mjs.map → inspect-live-schema-CWLK_lgs.mjs.map} +1 -1
- package/dist/migration-cli.mjs +1 -1
- package/dist/migration-cli.mjs.map +1 -1
- package/dist/{migration-command-scaffold-BdV8JYXV.mjs → migration-command-scaffold-CmXXC1UZ.mjs} +4 -4
- package/dist/{migration-command-scaffold-BdV8JYXV.mjs.map → migration-command-scaffold-CmXXC1UZ.mjs.map} +1 -1
- package/dist/{migration-plan-mRu5K81L.mjs → migration-plan-CHyUlBV0.mjs} +76 -37
- package/dist/migration-plan-CHyUlBV0.mjs.map +1 -0
- package/dist/migration-types-D2FW63pr.d.mts +15 -0
- package/dist/migration-types-D2FW63pr.d.mts.map +1 -0
- package/dist/{migrations-CTsyBXCA.mjs → migrations-DyUf5lTt.mjs} +2 -2
- package/dist/migrations-DyUf5lTt.mjs.map +1 -0
- package/dist/{output-BVj6a971.mjs → output-B60Gw5fu.mjs} +12 -11
- package/dist/{output-BVj6a971.mjs.map → output-B60Gw5fu.mjs.map} +1 -1
- package/dist/{result-handler-rmPVKIP2.mjs → result-handler-Bm_6dDYg.mjs} +2 -2
- package/dist/{result-handler-rmPVKIP2.mjs.map → result-handler-Bm_6dDYg.mjs.map} +1 -1
- package/dist/{terminal-ui-C_hFNbAn.mjs → terminal-ui-XtOQsqe9.mjs} +2 -54
- package/dist/terminal-ui-XtOQsqe9.mjs.map +1 -0
- package/dist/{types-LItU7E4l.d.mts → types-0aS865QN.d.mts} +14 -8
- package/dist/types-0aS865QN.d.mts.map +1 -0
- package/dist/{verify-CiwNWM9N.mjs → verify-D7ypCCe6.mjs} +1 -1
- package/dist/{verify-CiwNWM9N.mjs.map → verify-D7ypCCe6.mjs.map} +1 -1
- package/package.json +39 -23
- package/src/cli.ts +78 -15
- package/src/commands/db-sign.ts +102 -32
- package/src/commands/db-update.ts +56 -4
- package/src/commands/db-verify.ts +19 -3
- package/src/commands/init/agent-skill-install.ts +145 -43
- package/src/commands/init/errors.ts +2 -2
- package/src/commands/init/exit-codes.ts +2 -2
- package/src/commands/init/index.ts +1 -1
- package/src/commands/init/init.ts +15 -6
- package/src/commands/init/inputs.ts +1 -1
- package/src/commands/init/output.ts +22 -17
- package/src/commands/{migration-apply.ts → migrate.ts} +77 -73
- package/src/commands/migration-check/exit-codes.ts +3 -0
- package/src/commands/migration-check.ts +369 -0
- package/src/commands/migration-graph.ts +184 -0
- package/src/commands/migration-list.ts +155 -0
- package/src/commands/migration-log.ts +218 -0
- package/src/commands/migration-new.ts +30 -22
- package/src/commands/migration-plan.ts +104 -35
- package/src/commands/migration-show.ts +141 -65
- package/src/commands/migration-status.ts +82 -69
- package/src/commands/{migration-ref.ts → ref.ts} +32 -86
- package/src/control-api/client.ts +30 -21
- package/src/control-api/operations/apply-aggregate.ts +4 -4
- package/src/control-api/operations/contract-emit.ts +26 -3
- package/src/control-api/operations/db-apply-aggregate.ts +4 -3
- package/src/control-api/operations/db-verify.ts +2 -2
- package/src/control-api/operations/migration-apply.ts +5 -4
- package/src/control-api/types.ts +12 -7
- package/src/load-ts-contract.ts +9 -1
- package/src/migration-cli.ts +1 -1
- package/src/utils/cli-errors.ts +37 -0
- package/src/utils/command-helpers.ts +28 -3
- package/src/utils/contract-space-aggregate-loader.ts +4 -4
- package/src/utils/contract-space-seed-phase.ts +2 -2
- package/src/utils/formatters/help.ts +12 -2
- package/src/utils/formatters/migrations.ts +2 -2
- package/dist/cli-errors-D3_sMh2K.mjs.map +0 -1
- package/dist/client-BCnP7cHo.mjs.map +0 -1
- package/dist/command-helpers-BeZHkxV8.mjs.map +0 -1
- package/dist/commands/migration-apply.d.mts +0 -51
- package/dist/commands/migration-apply.d.mts.map +0 -1
- package/dist/commands/migration-apply.mjs.map +0 -1
- package/dist/commands/migration-ref.d.mts +0 -45
- package/dist/commands/migration-ref.d.mts.map +0 -1
- package/dist/commands/migration-ref.mjs.map +0 -1
- package/dist/contract-emit-B77TsJqf.mjs.map +0 -1
- package/dist/db-verify-Czm5T-J4.mjs.map +0 -1
- package/dist/init-B-k3a1Qw.mjs.map +0 -1
- package/dist/migration-plan-mRu5K81L.mjs.map +0 -1
- package/dist/migration-status-By9G5p2H.mjs.map +0 -1
- package/dist/migrations-CTsyBXCA.mjs.map +0 -1
- package/dist/terminal-ui-C_hFNbAn.mjs.map +0 -1
- package/dist/types-LItU7E4l.d.mts.map +0 -1
- /package/dist/{cli-errors-B9OBbled.d.mts → cli-errors-DdcjVLJV.d.mts} +0 -0
|
@@ -1,44 +1,133 @@
|
|
|
1
1
|
import { execFile } from 'node:child_process';
|
|
2
2
|
import { promisify } from 'node:util';
|
|
3
|
+
import { version as cliVersion } from '../../../package.json' with { type: 'json' };
|
|
3
4
|
import type { PackageManager } from './detect-package-manager';
|
|
4
5
|
import { errorInitSkillInstallFailed } from './errors';
|
|
5
6
|
|
|
6
7
|
const exec = promisify(execFile);
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
10
|
+
* Default base for the GitHub-URL form `<owner>/<repo>` consumed by
|
|
11
|
+
* upstream `skills add`. Each `SkillSource` joins this base with its
|
|
12
|
+
* own subpath (and optional `#ref` for version-pinned clusters).
|
|
13
|
+
*/
|
|
14
|
+
export const DEFAULT_AGENT_SKILL_BASE = 'prisma/prisma-next';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* One discovery scope inside the Prisma Next monorepo. The CLI emits
|
|
18
|
+
* one `skills add <base>/<subpath>[#ref] --all` invocation per source
|
|
19
|
+
* during `init`.
|
|
12
20
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
21
|
+
* `ref` semantics:
|
|
22
|
+
* - `cli`: pin to the CLI's own package version (lockstep with the
|
|
23
|
+
* skills' SPI). Used for the version-locked usage cluster — the
|
|
24
|
+
* skills under `skills/<X>/SKILL.md`, which describe the public
|
|
25
|
+
* package API and are pinned to the version of `@prisma-next/*`
|
|
26
|
+
* currently installed in the consumer's project.
|
|
27
|
+
* - `null`: no ref. The cluster is "always-latest" — the cumulative
|
|
28
|
+
* instruction set is the source of truth, and the latest revision
|
|
29
|
+
* on `main` includes bug fixes for every prior transition. Used
|
|
30
|
+
* for the upgrade and extension-author clusters.
|
|
20
31
|
*/
|
|
21
|
-
export
|
|
32
|
+
export interface SkillSource {
|
|
33
|
+
readonly subpath: string;
|
|
34
|
+
readonly ref: 'cli' | null;
|
|
35
|
+
readonly description: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export const DEFAULT_AGENT_SKILL_SOURCES: readonly SkillSource[] = [
|
|
39
|
+
{
|
|
40
|
+
subpath: 'skills',
|
|
41
|
+
ref: 'cli',
|
|
42
|
+
description: 'usage skills (version-locked to installed Prisma Next)',
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
subpath: 'skills/upgrade',
|
|
46
|
+
ref: null,
|
|
47
|
+
description: 'upgrade skill (always tracks `main`)',
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
subpath: 'skills/extension-author',
|
|
51
|
+
ref: null,
|
|
52
|
+
description: 'extension-author skill (always tracks `main`)',
|
|
53
|
+
},
|
|
54
|
+
];
|
|
22
55
|
|
|
23
56
|
/**
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
57
|
+
* Test-only escape hatch for pinning the install base to a local
|
|
58
|
+
* checkout. Production runs leave this unset, so installs always use
|
|
59
|
+
* `DEFAULT_AGENT_SKILL_BASE`.
|
|
60
|
+
*
|
|
61
|
+
* When set to an absolute filesystem path (typical for tests), the
|
|
62
|
+
* `#ref` fragment is dropped — local-path mode in upstream's CLI does
|
|
63
|
+
* not accept refs, and the local clone has whatever content the test
|
|
64
|
+
* checked into it anyway. When set to anything else (e.g. a fork name
|
|
65
|
+
* `myuser/prisma-next`), the ref policy is preserved.
|
|
66
|
+
*/
|
|
67
|
+
function resolveAgentSkillBase(): string {
|
|
68
|
+
const override = process.env['PRISMA_NEXT_SKILLS_BASE']?.trim();
|
|
69
|
+
return override && override.length > 0 ? override : DEFAULT_AGENT_SKILL_BASE;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function isLocalPath(base: string): boolean {
|
|
73
|
+
return base.startsWith('/') || /^[a-zA-Z]:[\\/]/.test(base);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Build the `<base>/<subpath>[#ref]` URL the `skills` CLI will
|
|
78
|
+
* resolve. Exported for unit tests so the per-source format can be
|
|
79
|
+
* asserted without going through the full install loop.
|
|
80
|
+
*/
|
|
81
|
+
export function formatSkillSourceUrl(source: SkillSource): string {
|
|
82
|
+
const base = resolveAgentSkillBase();
|
|
83
|
+
const url = `${base}/${source.subpath}`;
|
|
84
|
+
if (source.ref === null) return url;
|
|
85
|
+
if (isLocalPath(base)) return url;
|
|
86
|
+
if (source.ref === 'cli') return `${url}#v${cliVersion}`;
|
|
87
|
+
return url;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* The skill-install command for one source, formatted for the
|
|
92
|
+
* project's detected package manager. `npx`/`pnpm dlx`/`bunx` are
|
|
93
|
+
* interchangeable to the user; we pick the variant that matches the
|
|
94
|
+
* rest of the install step so a single project consistently uses one
|
|
95
|
+
* runner.
|
|
28
96
|
*
|
|
29
97
|
* `--all` auto-selects every skill in the cluster and every detected
|
|
30
98
|
* agent runtime, skipping the multi-select prompts the `skills` CLI
|
|
31
99
|
* shows by default. A non-interactive scaffold step cannot present
|
|
32
|
-
* prompts
|
|
33
|
-
* router skill routes between the workflow-scoped siblings). Users who
|
|
34
|
-
* want a narrower install run `npx skills add @prisma-next/agent-skill`
|
|
35
|
-
* themselves after `init` with the flags they want.
|
|
100
|
+
* prompts.
|
|
36
101
|
*
|
|
37
102
|
* Exported for unit tests so the per-PM dispatch can be asserted
|
|
38
103
|
* without a live subprocess.
|
|
39
104
|
*/
|
|
40
|
-
export function formatSkillInstallCommand(pm: PackageManager): string {
|
|
41
|
-
const args = ['skills', 'add',
|
|
105
|
+
export function formatSkillInstallCommand(pm: PackageManager, source: SkillSource): string {
|
|
106
|
+
const args = ['skills@latest', 'add', formatSkillSourceUrl(source), '--all'];
|
|
107
|
+
return formatPackageManagerCommand(pm, args);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* `skills add --all` should cover Claude Code, but upstream currently skips
|
|
112
|
+
* project-local Claude symlinks when `.claude/` does not already exist. Run
|
|
113
|
+
* the explicit Claude Code install as well so fresh projects get
|
|
114
|
+
* `.claude/skills` without asking users to create that folder first.
|
|
115
|
+
*/
|
|
116
|
+
export function formatClaudeSkillInstallCommand(pm: PackageManager, source: SkillSource): string {
|
|
117
|
+
const args = [
|
|
118
|
+
'skills@latest',
|
|
119
|
+
'add',
|
|
120
|
+
formatSkillSourceUrl(source),
|
|
121
|
+
'--agent',
|
|
122
|
+
'claude-code',
|
|
123
|
+
'--skill',
|
|
124
|
+
"'*'",
|
|
125
|
+
'-y',
|
|
126
|
+
];
|
|
127
|
+
return formatPackageManagerCommand(pm, args);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function formatPackageManagerCommand(pm: PackageManager, args: readonly string[]): string {
|
|
42
131
|
switch (pm) {
|
|
43
132
|
case 'pnpm':
|
|
44
133
|
return `pnpm dlx ${args.join(' ')}`;
|
|
@@ -58,42 +147,55 @@ export function formatSkillInstallCommand(pm: PackageManager): string {
|
|
|
58
147
|
* format-then-parse split keeps the user-facing command string the same
|
|
59
148
|
* as the surface the structured error advertises, so a user who copies
|
|
60
149
|
* the error's `fix` line gets the same invocation that init just
|
|
61
|
-
* attempted.
|
|
150
|
+
* attempted. Single quotes are preserved in the display form so `*` is
|
|
151
|
+
* safe to copy into a shell, then stripped before `execFile`.
|
|
62
152
|
*/
|
|
63
153
|
function commandToExec(command: string): {
|
|
64
154
|
readonly file: string;
|
|
65
155
|
readonly args: readonly string[];
|
|
66
156
|
} {
|
|
67
|
-
const tokens = command.
|
|
157
|
+
const tokens = (command.match(/'[^']*'|\S+/g) ?? []).map((token) =>
|
|
158
|
+
token.startsWith("'") && token.endsWith("'") ? token.slice(1, -1) : token,
|
|
159
|
+
);
|
|
68
160
|
return { file: tokens[0] ?? 'npx', args: tokens.slice(1) };
|
|
69
161
|
}
|
|
70
162
|
|
|
71
163
|
/**
|
|
72
|
-
* Runs the project-level skill install
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
164
|
+
* Runs the project-level skill install for every source in
|
|
165
|
+
* `DEFAULT_AGENT_SKILL_SOURCES`, in order. Returns
|
|
166
|
+
* `{ ok: true, commands }` on success; throws a structured
|
|
167
|
+
* `errorInitSkillInstallFailed` on the first failure (subsequent
|
|
168
|
+
* sources are not attempted — the user opted into Prisma Next by
|
|
169
|
+
* running `init` and a partial install would leave the project in an
|
|
170
|
+
* ambiguous state). The throw is intentionally fatal — project-level
|
|
171
|
+
* skill install is unconditional (modulo `--no-skill`).
|
|
78
172
|
*/
|
|
79
173
|
export async function runProjectLevelSkillInstall(ctx: {
|
|
80
174
|
readonly baseDir: string;
|
|
81
175
|
readonly pm: PackageManager;
|
|
82
176
|
readonly filesWritten: readonly string[];
|
|
83
|
-
}): Promise<{ readonly ok: true; readonly
|
|
84
|
-
const
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
})
|
|
177
|
+
}): Promise<{ readonly ok: true; readonly commands: readonly string[] }> {
|
|
178
|
+
const commands: string[] = [];
|
|
179
|
+
const installCommands = DEFAULT_AGENT_SKILL_SOURCES.flatMap((source) => [
|
|
180
|
+
formatSkillInstallCommand(ctx.pm, source),
|
|
181
|
+
formatClaudeSkillInstallCommand(ctx.pm, source),
|
|
182
|
+
]);
|
|
183
|
+
|
|
184
|
+
for (const command of installCommands) {
|
|
185
|
+
const { file, args } = commandToExec(command);
|
|
186
|
+
try {
|
|
187
|
+
await exec(file, args, { cwd: ctx.baseDir });
|
|
188
|
+
commands.push(command);
|
|
189
|
+
} catch (err) {
|
|
190
|
+
throw errorInitSkillInstallFailed({
|
|
191
|
+
skillInstallCommand: command,
|
|
192
|
+
filesWritten: ctx.filesWritten,
|
|
193
|
+
cause:
|
|
194
|
+
redactSecrets(readChildStderr(err)) || (err instanceof Error ? err.message : String(err)),
|
|
195
|
+
});
|
|
196
|
+
}
|
|
96
197
|
}
|
|
198
|
+
return { ok: true, commands };
|
|
97
199
|
}
|
|
98
200
|
|
|
99
201
|
function readChildStderr(err: unknown): string {
|
|
@@ -125,6 +227,6 @@ export function redactSecrets(stderr: string): string {
|
|
|
125
227
|
/**
|
|
126
228
|
* Hand-rolled skill stub path that init must not leave behind. Removed
|
|
127
229
|
* on every init run so a project's `.agents/skills/prisma-next/` does
|
|
128
|
-
* not shadow the
|
|
230
|
+
* not shadow the installed Prisma Next skill cluster.
|
|
129
231
|
*/
|
|
130
232
|
export const LEGACY_SKILL_FILE = '.agents/skills/prisma-next/SKILL.md';
|
|
@@ -239,7 +239,7 @@ export function errorInitEmitFailed(options: {
|
|
|
239
239
|
|
|
240
240
|
/**
|
|
241
241
|
* The project-level agent-skill install (`npx skills add
|
|
242
|
-
*
|
|
242
|
+
* prisma/prisma-next#v<version>`) failed after a successful dependency
|
|
243
243
|
* install + emit. The project's scaffold remains on disk; the user
|
|
244
244
|
* can either fix the underlying issue (network, registry, PATH) and
|
|
245
245
|
* run the install command manually, or re-run `init --no-skill` to
|
|
@@ -253,7 +253,7 @@ export function errorInitSkillInstallFailed(options: {
|
|
|
253
253
|
readonly filesWritten: readonly string[];
|
|
254
254
|
readonly cause: string;
|
|
255
255
|
}): CliStructuredError {
|
|
256
|
-
return new CliStructuredError('5013', 'Failed to install
|
|
256
|
+
return new CliStructuredError('5013', 'Failed to install Prisma Next skills', {
|
|
257
257
|
domain: 'CLI',
|
|
258
258
|
why: `\`${options.skillInstallCommand}\` exited with an error: ${options.cause}`,
|
|
259
259
|
fix:
|
|
@@ -62,8 +62,8 @@ export const INIT_EXIT_INSTALL_FAILED = 4;
|
|
|
62
62
|
export const INIT_EXIT_EMIT_FAILED = 5;
|
|
63
63
|
|
|
64
64
|
/**
|
|
65
|
-
* The project-level
|
|
66
|
-
*
|
|
65
|
+
* The project-level Prisma Next skills install (`npx skills add
|
|
66
|
+
* prisma/prisma-next#v<version>`) failed after a successful dependency
|
|
67
67
|
* install + emit. The scaffolded project files remain on disk; the
|
|
68
68
|
* user can fix the underlying issue (network, registry reachability,
|
|
69
69
|
* `npx skills` not on PATH) and run the install manually, or re-run
|
|
@@ -89,7 +89,7 @@ export function createInitCommand(): Command {
|
|
|
89
89
|
.option('--no-install', 'Skip dependency installation and contract emission')
|
|
90
90
|
.option(
|
|
91
91
|
'--no-skill',
|
|
92
|
-
'Skip
|
|
92
|
+
'Skip Prisma Next skills install (air-gapped CI, restricted registries, etc.)',
|
|
93
93
|
)
|
|
94
94
|
.action(async (options: InitCommandOptions) => {
|
|
95
95
|
const { runInit } = await import('./init');
|
|
@@ -8,6 +8,8 @@ import { formatErrorJson, formatErrorOutput } from '../../utils/formatters/error
|
|
|
8
8
|
import type { GlobalFlags } from '../../utils/global-flags';
|
|
9
9
|
import { TerminalUI } from '../../utils/terminal-ui';
|
|
10
10
|
import {
|
|
11
|
+
DEFAULT_AGENT_SKILL_SOURCES,
|
|
12
|
+
formatClaudeSkillInstallCommand,
|
|
11
13
|
formatSkillInstallCommand,
|
|
12
14
|
LEGACY_SKILL_FILE,
|
|
13
15
|
runProjectLevelSkillInstall,
|
|
@@ -182,7 +184,7 @@ export async function runInit(
|
|
|
182
184
|
// and missing-on-disk-at-write-time is tolerated.
|
|
183
185
|
const filesToDelete: string[] = inputs.reinit ? [...findStaleArtefacts(baseDir, schemaDir)] : [];
|
|
184
186
|
|
|
185
|
-
// `init` delegates the skill to `npx skills add
|
|
187
|
+
// `init` delegates the skill to `npx skills add prisma/prisma-next#v<version>`,
|
|
186
188
|
// so a hand-rolled `.agents/skills/prisma-next/SKILL.md` in the project
|
|
187
189
|
// would shadow the published package. Queue it for deletion on every
|
|
188
190
|
// run (not gated on `--reinit`).
|
|
@@ -449,18 +451,23 @@ export async function runInit(
|
|
|
449
451
|
// potentially fails. We skip the install when the user passed
|
|
450
452
|
// `--no-install` for the same reason — no `node_modules` means the
|
|
451
453
|
// workspace isn't ready to consume the skill yet anyway.
|
|
452
|
-
const
|
|
454
|
+
const manualProjectSkillCommands = DEFAULT_AGENT_SKILL_SOURCES.flatMap((source) => [
|
|
455
|
+
formatSkillInstallCommand(install.effectivePm, source),
|
|
456
|
+
formatClaudeSkillInstallCommand(install.effectivePm, source),
|
|
457
|
+
]);
|
|
458
|
+
const manualProjectSkillSummary = manualProjectSkillCommands.map((c) => `\`${c}\``).join(' && ');
|
|
459
|
+
let skillRegistered = false;
|
|
453
460
|
if (!inputs.installProjectSkill) {
|
|
454
461
|
warnings.push(
|
|
455
|
-
`Skipped
|
|
462
|
+
`Skipped Prisma Next agent-skill install (--no-skill). To install the skills later, run: ${manualProjectSkillSummary}`,
|
|
456
463
|
);
|
|
457
464
|
} else if (install.skipped) {
|
|
458
465
|
warnings.push(
|
|
459
|
-
`Skipped
|
|
466
|
+
`Skipped Prisma Next agent-skill install because --no-install was passed. After you run install manually, install the skills with: ${manualProjectSkillSummary}`,
|
|
460
467
|
);
|
|
461
468
|
} else {
|
|
462
469
|
const spinner = ui.spinner();
|
|
463
|
-
spinner.start('Registering
|
|
470
|
+
spinner.start('Registering Prisma Next skills with the agent runtime...');
|
|
464
471
|
try {
|
|
465
472
|
const project = await runProjectLevelSkillInstall({
|
|
466
473
|
baseDir,
|
|
@@ -468,8 +475,9 @@ export async function runInit(
|
|
|
468
475
|
filesWritten,
|
|
469
476
|
});
|
|
470
477
|
spinner.stop(
|
|
471
|
-
`Registered
|
|
478
|
+
`Registered Prisma Next skills (project level) — ran ${project.commands.map((c) => `\`${c}\``).join(', ')}`,
|
|
472
479
|
);
|
|
480
|
+
skillRegistered = true;
|
|
473
481
|
} catch (error) {
|
|
474
482
|
spinner.stop('Agent-skill install failed');
|
|
475
483
|
if (CliStructuredError.is(error)) {
|
|
@@ -497,6 +505,7 @@ export async function runInit(
|
|
|
497
505
|
contractEmitted,
|
|
498
506
|
emitCommand,
|
|
499
507
|
schemaPath: inputs.schemaPath,
|
|
508
|
+
skillRegistered,
|
|
500
509
|
}),
|
|
501
510
|
warnings,
|
|
502
511
|
};
|
|
@@ -69,7 +69,7 @@ export interface ResolvedInitInputs {
|
|
|
69
69
|
*/
|
|
70
70
|
readonly removePreviousFacade: string | null;
|
|
71
71
|
/**
|
|
72
|
-
* Whether to run `npx skills add
|
|
72
|
+
* Whether to run `npx skills add prisma/prisma-next#v<version>` at the
|
|
73
73
|
* project level after install + emit. True by default; `--no-skill`
|
|
74
74
|
* sets it to `false`. The skill is always project-level (never
|
|
75
75
|
* user-level / global) so its version stays locked to the project's
|
|
@@ -120,27 +120,32 @@ export function buildNextSteps(options: {
|
|
|
120
120
|
readonly contractEmitted: boolean;
|
|
121
121
|
readonly emitCommand: string;
|
|
122
122
|
readonly schemaPath: string;
|
|
123
|
+
/**
|
|
124
|
+
* Whether the project-level Prisma Next skills install actually ran
|
|
125
|
+
* and succeeded during this `init`. When false (the user passed
|
|
126
|
+
* `--no-skill` or `--no-install`, so the install was skipped), the
|
|
127
|
+
* "registered with your agent runtime" step is omitted — the skip is
|
|
128
|
+
* already surfaced in the warnings array with a manual-install hint.
|
|
129
|
+
*/
|
|
130
|
+
readonly skillRegistered: boolean;
|
|
123
131
|
}): string[] {
|
|
124
132
|
const steps: string[] = [];
|
|
125
|
-
|
|
133
|
+
let stepNumber = 1;
|
|
134
|
+
const push = (text: string): void => {
|
|
135
|
+
steps.push(`${stepNumber}. ${text}`);
|
|
136
|
+
stepNumber += 1;
|
|
137
|
+
};
|
|
138
|
+
push('Set DATABASE_URL in your environment (export it or add it to .env).');
|
|
126
139
|
if (!options.contractEmitted) {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
steps.push(
|
|
130
|
-
'4. Open prisma-next.md for a quick reference on how to write your first typed query.',
|
|
131
|
-
);
|
|
132
|
-
steps.push(
|
|
133
|
-
'5. @prisma-next/agent-skill is registered with your agent runtime — open the project in your IDE and ask the agent to add a model, run a query, or plan a migration.',
|
|
134
|
-
);
|
|
140
|
+
push(`Emit the contract: \`${options.emitCommand}\``);
|
|
141
|
+
push(`Edit your schema at ${options.schemaPath}, then re-run the emit command.`);
|
|
135
142
|
} else {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
steps.push(
|
|
143
|
-
'4. @prisma-next/agent-skill is registered with your agent runtime — open the project in your IDE and ask the agent to add a model, run a query, or plan a migration.',
|
|
143
|
+
push(`Edit your schema at ${options.schemaPath}, then re-run \`${options.emitCommand}\`.`);
|
|
144
|
+
}
|
|
145
|
+
push('Open prisma-next.md for a quick reference on how to write your first typed query.');
|
|
146
|
+
if (options.skillRegistered) {
|
|
147
|
+
push(
|
|
148
|
+
'Prisma Next skills are registered with your agent runtime — open the project in your IDE and ask the agent to add a model, run a query, or plan a migration.',
|
|
144
149
|
);
|
|
145
150
|
}
|
|
146
151
|
return steps;
|