@prisma/cli 8.0.0-rc.13-dev.94 → 8.0.0-rc.13-dev.96

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.
Files changed (2) hide show
  1. package/dist/cli.js +54 -21
  2. package/package.json +9 -7
package/dist/cli.js CHANGED
@@ -9,7 +9,7 @@ import { AuthError, createManagementApiClient, createManagementApiSdk } from "@p
9
9
  import os from "node:os";
10
10
  import path from "node:path";
11
11
  import { randomBytes, randomUUID } from "node:crypto";
12
- import fs, { mkdir, readFile, readdir, rename, rm, stat, unlink, writeFile } from "node:fs/promises";
12
+ import fs, { mkdir, readFile, readdir, rename, rm, rmdir, stat, unlink, writeFile } from "node:fs/promises";
13
13
  import { mkdir as mkdir$1, readFile as readFile$1, writeFile as writeFile$1 } from "fs/promises";
14
14
  import path$1 from "path";
15
15
  import events from "node:events";
@@ -27,6 +27,7 @@ import { fileURLToPath } from "node:url";
27
27
  import { execa } from "execa";
28
28
  import { Writable } from "node:stream";
29
29
  import { pipeline } from "node:stream/promises";
30
+ import spawn$1 from "cross-spawn";
30
31
  //#region \0rolldown/runtime.js
31
32
  var __create = Object.create;
32
33
  var __defProp = Object.defineProperty;
@@ -2044,9 +2045,14 @@ async function hasPackageJsonWorkspaces(root) {
2044
2045
  }
2045
2046
  //#endregion
2046
2047
  //#region src/lib/skills/status.ts
2048
+ /** Reads every skill the installed source packages ship and the state
2049
+ * of each copy in the configured agents' directories, plus the copies
2050
+ * the next sync will remove. */
2047
2051
  async function readSkillsStatus(cwd, options) {
2048
2052
  const projectRoot = path.resolve(cwd);
2049
- const dirs = agentSkillDirs(options?.agents ?? DEFAULT_AGENTS);
2053
+ const agents = options?.agents ?? DEFAULT_AGENTS;
2054
+ const dirs = agentSkillDirs(agents);
2055
+ const unconfiguredDirs = agentSkillDirs(KNOWN_AGENTS.filter((agent) => !agents.includes(agent)));
2050
2056
  const checkDisabled = options?.checkDisabled ?? await readSkillsCheckDisabled(projectRoot);
2051
2057
  const packages = await findInstalledSourcePackages(projectRoot);
2052
2058
  const sources = await collectSkillSources(packages);
@@ -2058,7 +2064,7 @@ async function readSkillsStatus(cwd, options) {
2058
2064
  checkDisabled,
2059
2065
  packages,
2060
2066
  skills,
2061
- orphans: options?.orphans === false ? [] : await findOrphanedSkills(projectRoot, dirs, new Set(sources.keys())),
2067
+ orphans: options?.orphans === false ? [] : await findOrphanedSkills(projectRoot, dirs, new Set(sources.keys()), unconfiguredDirs),
2062
2068
  upToDate: skills.every((skill) => skill.upToDate)
2063
2069
  };
2064
2070
  }
@@ -2144,16 +2150,25 @@ async function missingFromDisk(target) {
2144
2150
  }
2145
2151
  /**
2146
2152
  * Copies in the harness directories that this CLI installed — their
2147
- * SKILL.md names an allowlisted package as its `library` — and that no
2148
- * installed package still provides. A skill from anywhere else is
2149
- * someone else's file and is never touched.
2153
+ * SKILL.md names an allowlisted package as its `library` — and that
2154
+ * nothing wants any more: in a configured directory, one no installed
2155
+ * package still provides; in the directory of an agent the config no
2156
+ * longer names, every one. A skill from anywhere else is someone
2157
+ * else's file and is never touched.
2150
2158
  */
2151
- async function findOrphanedSkills(projectRoot, dirs, provided) {
2159
+ async function findOrphanedSkills(projectRoot, dirs, provided, unconfiguredDirs = []) {
2152
2160
  const orphans = /* @__PURE__ */ new Map();
2153
- for (const dir of dirs) {
2161
+ const scan = [...dirs.map((dir) => ({
2162
+ dir,
2163
+ wanted: provided
2164
+ })), ...unconfiguredDirs.map((dir) => ({
2165
+ dir,
2166
+ wanted: /* @__PURE__ */ new Set()
2167
+ }))];
2168
+ for (const { dir, wanted } of scan) {
2154
2169
  const harnessDir = path.join(projectRoot, dir);
2155
2170
  for (const skill of await skillDirectories(harnessDir)) {
2156
- if (provided.has(skill)) continue;
2171
+ if (wanted.has(skill)) continue;
2157
2172
  const stamp = await readSkillStamp(path.join(harnessDir, skill, "SKILL.md"));
2158
2173
  if (stamp?.library === null || stamp === null) continue;
2159
2174
  if (!isSkillSourcePackage(stamp.library)) continue;
@@ -5526,11 +5541,12 @@ const gitDisconnectCommand = defineCommand({
5526
5541
  //#region src/lib/skills/sync.ts
5527
5542
  /**
5528
5543
  * Brings the harness skill directories in line with the installed
5529
- * source packages: copies each skill tree whose stamp does not match
5530
- * the package it came from, and removes copies whose source package is
5531
- * gone. A target directory that exists but is not this CLI's copy is
5532
- * refused, never replaced. Doing nothing is the normal outcome and is
5533
- * not an error.
5544
+ * source packages and the configured agents: copies each skill tree
5545
+ * whose stamp does not match the package it came from, and removes
5546
+ * copies whose source package is gone or whose agent the config no
5547
+ * longer names. A target directory that exists but is not this CLI's
5548
+ * copy is refused, never replaced. Doing nothing is the normal outcome
5549
+ * and is not an error.
5534
5550
  */
5535
5551
  async function syncSkills(status) {
5536
5552
  const synced = [];
@@ -5554,10 +5570,13 @@ async function syncSkills(status) {
5554
5570
  }
5555
5571
  const pruned = [];
5556
5572
  for (const orphan of status.orphans) {
5557
- for (const dir of orphan.dirs) await rm(path.join(status.projectRoot, dir, orphan.skill), {
5558
- recursive: true,
5559
- force: true
5560
- });
5573
+ for (const dir of orphan.dirs) {
5574
+ await rm(path.join(status.projectRoot, dir, orphan.skill), {
5575
+ recursive: true,
5576
+ force: true
5577
+ });
5578
+ await removeEmptyHarnessDirs(status.projectRoot, dir);
5579
+ }
5561
5580
  pruned.push({
5562
5581
  skill: orphan.skill,
5563
5582
  library: orphan.library,
@@ -5574,6 +5593,20 @@ async function syncSkills(status) {
5574
5593
  checkDisabled: status.checkDisabled
5575
5594
  };
5576
5595
  }
5596
+ /**
5597
+ * A harness directory this CLI emptied by removing its last copy is
5598
+ * removed too, and so is its parent (`.claude/skills`, then `.claude`),
5599
+ * so opting an agent out leaves nothing behind. `rmdir` refuses a
5600
+ * directory holding anything else, which is exactly the user's file
5601
+ * that must stay.
5602
+ */
5603
+ async function removeEmptyHarnessDirs(projectRoot, dir) {
5604
+ for (let current = dir; current !== "." && current !== ""; current = path.dirname(current)) try {
5605
+ await rmdir(path.join(projectRoot, current));
5606
+ } catch {
5607
+ return;
5608
+ }
5609
+ }
5577
5610
  const OLD_CLI_GITIGNORE = /^\*\r?\n?$/;
5578
5611
  async function removeOldCliGitignore(file) {
5579
5612
  let content;
@@ -5777,7 +5810,7 @@ function bothSwitchesError() {
5777
5810
  const skillsSyncCommand = defineCommand({
5778
5811
  help: {
5779
5812
  summary: "Copy the AI-agent instruction files (skills) from installed Prisma packages into this project",
5780
- description: "Agent skills are instruction files that teach AI coding agents (Claude Code, Cursor, and others) how to use the installed Prisma packages. They ship inside the packages themselves, so they always describe the version in use. Sync copies them into the skill directories the agent harnesses read, and removes copies whose package is gone. It does nothing, and exits 0, when everything is already current.",
5813
+ description: "Agent skills are instruction files that teach AI coding agents (Claude Code, Cursor, and others) how to use the installed Prisma packages. They ship inside the packages themselves, so they always describe the version in use. Sync copies them into the skill directories of the agents that skills.agents in prisma.config.ts names (every known agent when unset), and removes copies whose package is gone or whose agent is no longer named there — agents: [] removes them all. It does nothing, and exits 0, when everything is already current.",
5781
5814
  examples: ["skills sync", "skills sync --disable"]
5782
5815
  },
5783
5816
  needs: { config: skillsConfigSection },
@@ -14244,7 +14277,7 @@ const runPackageManager = async ({ file, args, cwd, signal, onOutput }) => {
14244
14277
  * must not wait on it, so the pipes are destroyed after this grace. */
14245
14278
  const POST_EXIT_DRAIN_GRACE_MS = 5e3;
14246
14279
  /**
14247
- * The engine's spawn seam, adapted to node:child_process. Human mode
14280
+ * The engine's spawn seam, adapted through cross-spawn. Human mode
14248
14281
  * inherits stdio; structured mode pipes both child output streams to
14249
14282
  * diagnostics. Neither mode detaches or opens a new console, so the child
14250
14283
  * stays in this process's group (POSIX) or console (Windows).
@@ -14258,7 +14291,7 @@ function makeSpawnChild(diagnostics, options) {
14258
14291
  const drainGraceMs = options?.drainGraceMs ?? POST_EXIT_DRAIN_GRACE_MS;
14259
14292
  return (request) => {
14260
14293
  const structured = request.output === "diagnostic";
14261
- const child = spawn(request.command, [...request.args], {
14294
+ const child = spawn$1(request.command, [...request.args], {
14262
14295
  cwd: request.cwd,
14263
14296
  env: request.env,
14264
14297
  stdio: structured ? [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prisma/cli",
3
- "version": "8.0.0-rc.13-dev.94",
3
+ "version": "8.0.0-rc.13-dev.96",
4
4
  "description": "Command-line interface for the Prisma Developer Platform.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -41,23 +41,25 @@
41
41
  "dependencies": {
42
42
  "@manypkg/tools": "^2.1.2",
43
43
  "@prisma/cli-engine": "0.3.0",
44
- "@prisma/composer-cli": "0.17.0-dev.2",
44
+ "@prisma/composer-cli": "0.17.0-dev.4",
45
45
  "@prisma/compute-sdk": "0.42.0",
46
46
  "@prisma/management-api-sdk": "1.69.0",
47
- "@prisma/orm-toolchain": "8.0.0-rc.8-dev.18",
47
+ "@prisma/orm-toolchain": "8.0.0-rc.9-dev.2",
48
48
  "@vercel/detect-agent": "^1.2.3",
49
49
  "better-result": "^2.9.2",
50
+ "cross-spawn": "^7.0.6",
50
51
  "dotenv": "^17.4.2",
51
52
  "execa": "^9.6.1",
52
53
  "open": "^11.0.0"
53
54
  },
54
55
  "devDependencies": {
55
- "@prisma/composer": "0.17.0-dev.2",
56
+ "@prisma/composer": "0.17.0-dev.4",
56
57
  "@prisma/credentials-store": "^7.8.0",
57
- "@repo/cli-conformance": "8.0.0-rc.13-dev.94",
58
- "@repo/cli-telemetry": "8.0.0-rc.13-dev.94",
59
- "@repo/tsconfig": "8.0.0-rc.13-dev.94",
58
+ "@repo/cli-conformance": "8.0.0-rc.13-dev.96",
59
+ "@repo/cli-telemetry": "8.0.0-rc.13-dev.96",
60
+ "@repo/tsconfig": "8.0.0-rc.13-dev.96",
60
61
  "@types/node": "^22.19.19",
62
+ "@types/cross-spawn": "^6.0.6",
61
63
  "tsdown": "^0.21.10",
62
64
  "tsx": "^4.22.4",
63
65
  "typescript": "^6.0.3",