diff --git a/README.md b/README.md index a26c2f4b..65681a77 100644 --- a/README.md +++ b/README.md @@ -84,7 +84,7 @@ The canonical command shape is: prisma ``` -The package includes project, environment-variable, service and service-version inspection, promotion, rollback, and deletion commands, plus the Prisma ORM (`contract`, `db`, `migration`, `orm init`) and Composer workflows (root `dev` and `deploy`), and the `postgres` and `bucket` resource groups. The product model intentionally avoids product-specific namespaces. +The package includes project, environment-variable, service and service-version inspection, promotion, rollback, and deletion commands, plus the Prisma ORM (`contract`, `db`, `migration`, `orm init`) and Composer workflows (root `dev` and `deploy`, with `dev url`, `dev stop` and `emulator list`), and the `postgres` and `bucket` resource groups. The product model intentionally avoids product-specific namespaces. ## Documentation diff --git a/packages/cli/AGENTS.md b/packages/cli/AGENTS.md index 80934c19..003c02e5 100644 --- a/packages/cli/AGENTS.md +++ b/packages/cli/AGENTS.md @@ -33,7 +33,7 @@ Architecture and contributor workflow references: - Group commands by developer workflow, not product ownership. - No `orm`, `postgres`, or `compute` namespaces in the command surface. - Canonical command shape is `prisma `. -- The shipped groups are `auth`, `project`, `git`, `branch`, `postgres`, `bucket`, `service`, `skills`, the root `init`, `dev` and `deploy` verbs, and the ORM family (`contract`, `db`, `migration`, `orm init`, `lsp`). +- The shipped groups are `auth`, `project`, `git`, `branch`, `postgres`, `bucket`, `service`, `skills`, the root `init` and `deploy` verbs, `dev` (a command that is also a group: `dev url`, `dev stop`), `emulator`, and the ORM family (`contract`, `db`, `migration`, `orm init`, `lsp`). - Preserve the long-term resource model: `workspace -> project -> branch -> { service, database, bucket }`. The mounted tree in `packages/cli/src/cli.ts` is the authoritative command surface. diff --git a/packages/cli/README.md b/packages/cli/README.md index 1394fc70..23dbd2cc 100644 --- a/packages/cli/README.md +++ b/packages/cli/README.md @@ -77,7 +77,8 @@ This package exposes `prisma-cli` so it can coexist with the existing | `postgres` | Create, inspect, back up, restore, and delete Prisma Postgres databases and their connections. | | `bucket` | Create, list, and delete object-store buckets and their access keys. | | `service` | Inspect services: versions, logs, domains, promote, roll back, delete. | -| `dev`, `deploy` | Run a Composer app locally; deploy it to the platform. | +| `dev`, `deploy` | Run a Composer app locally; deploy it to the platform. `dev url` prints a running node's local URL and `dev stop` stops the app. | +| `emulator` | List the local emulators `prisma dev` runs services, databases and buckets on. | | `contract`, `db`, `migration`, `orm init`, `lsp` | The Prisma ORM workflow. | Common examples: diff --git a/packages/cli/package.json b/packages/cli/package.json index 5bb8e990..889e650d 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -50,7 +50,7 @@ "dependencies": { "@manypkg/tools": "^2.1.2", "@prisma/cli-engine": "workspace:0.9.0", - "@prisma/composer-cli": "0.30.0", + "@prisma/composer-cli": "0.31.0", "@prisma/compute-sdk": "0.43.0", "@prisma/management-api-sdk": "1.80.0", "@prisma/orm-toolchain": "8.0.0-rc.18", @@ -62,7 +62,7 @@ "open": "^11.0.0" }, "devDependencies": { - "@prisma/composer": "0.30.0", + "@prisma/composer": "0.31.0", "@prisma/credentials-store": "^7.8.0", "@repo/cli-conformance": "workspace:8.0.0-rc.23", "@repo/cli-telemetry": "workspace:8.0.0-rc.23", diff --git a/packages/cli/src/cli.ts b/packages/cli/src/cli.ts index 7afbb9cc..b66688a3 100644 --- a/packages/cli/src/cli.ts +++ b/packages/cli/src/cli.ts @@ -346,6 +346,16 @@ export const cliGroups: Readonly< "A ref is a named pointer to a contract, letting commands target a contract by a stable name. Set, list, and delete refs here.", }, orm: { brief: "Initialize a Prisma ORM project" }, + dev: { + brief: + "Run your app on this machine, with no Prisma account. Start it, print a node's local URL, stop it", + }, + emulator: { + brief: + "Inspect the local emulators: programs on this machine that stand in for Prisma Cloud during 'prisma dev'", + description: + "An emulator runs one kind of resource locally, so 'prisma dev' needs no account or network: one runs services, one runs Postgres databases, one runs S3-compatible buckets. Each holds instances, one per service, database or bucket that a 'prisma dev' started, from any directory on this machine. Emulators keep running after 'prisma dev' ends. Instances and their data stay until 'prisma dev --fresh' removes the current app's, and a stopped instance keeps its port.", + }, skills: { brief: "Manage Prisma skills for AI coding agents. Sync and list the instruction files", @@ -411,9 +421,13 @@ export const mountedCommands: Readonly> = { "service domain delete": serviceDomainDeleteCommand, "service domain retry": serviceDomainRetryCommand, "service domain wait": serviceDomainWaitCommand, - // Composer's two product verbs, mounted at the root. + // Composer's product verbs: deploy and dev at the root, dev's + // children beneath it, and the local emulators under their own group. deploy: composerCommandFamily.commands.deploy, dev: composerCommandFamily.commands.dev, + "dev url": composerCommandFamily.commands["dev url"], + "dev stop": composerCommandFamily.commands["dev stop"], + "emulator list": composerCommandFamily.commands["emulator list"], // The ORM family. Written out per path: the shell owns the tree // (R12), so this map — not the family's own keying — is the source of // truth for where each command mounts. diff --git a/packages/cli/tests/composer-mount.test.ts b/packages/cli/tests/composer-mount.test.ts new file mode 100644 index 00000000..d95a6cbc --- /dev/null +++ b/packages/cli/tests/composer-mount.test.ts @@ -0,0 +1,138 @@ +/** + * Composer's commands, mounted at the paths this shell gives them, run + * against Composer's operations double: what is proven is the mount and + * what a pipe receives, not Composer's dev logic, which Composer's own + * integration tests run against real emulators. + */ +import { createTestCli } from "@prisma/cli-engine/testing"; +import { defineConfig as composer } from "@prisma/composer/config"; +import { nodeBuild } from "@prisma/composer/node/control"; +import { + createComposerFamily, + type ListEmulators, +} from "@prisma/composer-cli/family"; +import { createOperationsDouble } from "@prisma/composer-cli/testing"; +import { describe, expect, it } from "vitest"; +import { cliGroups, mountedCommands } from "../src/cli"; + +const build = nodeBuild(); + +const COMPOSER_SECTION = composer({ + extensions: [build], + state: { + extension: build.id, + create: () => { + throw new Error("no command in these tests reaches the state store"); + }, + }, +}); + +type Listing = Awaited>; + +function listing(emulators: readonly EmulatorListing[]): Listing { + const value = { emulators }; + return { + ok: true as const, + value, + assertOk: () => value, + assertNotOk: (): never => { + throw new Error("the listing succeeded"); + }, + }; +} + +type EmulatorListing = Extract< + Listing, + { ok: true } +>["value"]["emulators"][number]; + +/** One running service emulator holding one instance that `prisma dev` + * started, and a database emulator that is not running. */ +const ONE_INSTANCE = listing([ + { + kind: "service", + running: true, + url: "http://localhost:4000", + instances: [ + { + id: "svc_gateway", + kind: "service", + url: "http://localhost:4001", + state: "running", + labels: { + "composer.address": "gateway", + "composer.directory": "/projects/shop", + }, + }, + ], + error: null, + }, + { kind: "database", running: false, url: null, instances: [], error: null }, +]); + +const COMPOSER_PATHS = ["dev", "dev url", "dev stop", "emulator list"]; + +function shell(emulators: Listing = listing([])) { + const family = createComposerFamily({ + operations: createOperationsDouble().operations, + listEmulators: async () => emulators, + }); + const commands = Object.fromEntries( + COMPOSER_PATHS.map((path) => [path, family.commands[path]]), + ); + return createTestCli({ + commandFamilies: [family], + commands, + groups: { dev: cliGroups.dev, emulator: cliGroups.emulator }, + config: { composer: COMPOSER_SECTION }, + now: () => new Date(0), + }); +} + +describe("Composer's commands in the shell", () => { + it("mounts Composer's dev children and emulator list where the shell says", () => { + for (const path of COMPOSER_PATHS) { + expect(mountedCommands[path], path).toBeDefined(); + } + expect(cliGroups.dev).toBeDefined(); + expect(cliGroups.emulator?.description).toContain("emulator"); + }); + + it("pipes the bare URL from dev url", async () => { + const result = await shell().run(["dev", "url", "gateway"]); + + expect(result.exitCode).toBe(0); + expect(result.stdout).toBe("http://localhost:3000\n"); + }); + + it("pipes nothing from dev stop", async () => { + const result = await shell().run(["dev", "stop"]); + + expect(result.exitCode).toBe(0); + expect(result.stdout).toBe(""); + }); + + it("lists emulators", async () => { + const result = await shell().run(["emulator", "list"]); + + expect(result.exitCode).toBe(0); + }); + + it("pipes one tab-separated line per emulator instance", async () => { + const result = await shell(ONE_INSTANCE).run(["emulator", "list"]); + + expect(result.exitCode).toBe(0); + expect(result.stdout).toBe( + "service\tsvc_gateway\thttp://localhost:4001\trunning\tgateway\t/projects/shop\n", + ); + }); + + it("shows dev's own help with its children listed", async () => { + const result = await shell().run(["dev", "--help"]); + + expect(result.exitCode).toBe(0); + expect(result.stdout).toContain("prisma-test dev"); + expect(result.stdout).toContain("url
"); + expect(result.stdout).toContain("stop"); + }); +}); diff --git a/packages/cli/tests/e2e-coverage.test.ts b/packages/cli/tests/e2e-coverage.test.ts index a7e5f58a..46593825 100644 --- a/packages/cli/tests/e2e-coverage.test.ts +++ b/packages/cli/tests/e2e-coverage.test.ts @@ -50,6 +50,14 @@ const E2E_DIR = path.resolve(import.meta.dirname, "../e2e"); const ORM_FAMILY_REASON = "ORM command: no management API involved. Real e2e lives in prisma/prisma (R7); the shell proves composition in orm-mount.test.ts (R8)."; +/** + * Composer's local commands talk to emulators on this machine, never to + * the management API this suite exists to cover. Composer's own + * integration tests run them against real emulators. + */ +const LOCAL_EMULATOR_REASON = + "Local emulators only: no management API involved. Composer's own integration tests run it against real emulators."; + const EXCLUSIONS: Readonly> = { "contract emit": ORM_FAMILY_REASON, "contract infer": ORM_FAMILY_REASON, @@ -98,6 +106,9 @@ const EXCLUSIONS: Readonly> = { deploy: "Provisions real cloud infrastructure for an app entry point, through a child `alchemy deploy`. Standing that up per CI run is neither cheap nor unattended-safe.", dev: "A session command: it runs until SIGINT or SIGTERM, redeploying on file change, so it has no happy path that terminates on its own.", + "dev url": LOCAL_EMULATOR_REASON, + "dev stop": LOCAL_EMULATOR_REASON, + "emulator list": LOCAL_EMULATOR_REASON, }; /** diff --git a/packages/cli/tests/mount-coverage.test.ts b/packages/cli/tests/mount-coverage.test.ts index d1275329..5d86dc13 100644 --- a/packages/cli/tests/mount-coverage.test.ts +++ b/packages/cli/tests/mount-coverage.test.ts @@ -100,6 +100,9 @@ const EXPECTED_MOUNT_PATHS: readonly string[] = [ "db verify", "deploy", "dev", + "dev stop", + "dev url", + "emulator list", "feedback", "git connect", "git disconnect", diff --git a/packages/prisma/README.md b/packages/prisma/README.md index 84dbfa62..04d6f640 100644 --- a/packages/prisma/README.md +++ b/packages/prisma/README.md @@ -74,7 +74,8 @@ npx prisma project env list --role preview | `postgres` | Create, inspect, back up, restore, and delete Prisma Postgres databases and their connections. | | `bucket` | Create, list, and delete object-store buckets and their access keys. | | `service` | Inspect services: versions, logs, domains, promote, roll back, delete. | -| `dev`, `deploy` | Run a Composer app locally; deploy it to the platform. | +| `dev`, `deploy` | Run a Composer app locally; deploy it to the platform. `dev url` prints a running node's local URL and `dev stop` stops the app. | +| `emulator` | List the local emulators `prisma dev` runs services, databases and buckets on. | | `contract`, `db`, `migration`, `orm init`, `lsp` | The Prisma ORM workflow. | Common examples: diff --git a/packages/prisma/package.json b/packages/prisma/package.json index 3cf76781..ca76f620 100644 --- a/packages/prisma/package.json +++ b/packages/prisma/package.json @@ -51,7 +51,7 @@ "dependencies": { "@manypkg/tools": "^2.1.2", "@prisma/cli-engine": "workspace:0.9.0", - "@prisma/composer-cli": "0.30.0", + "@prisma/composer-cli": "0.31.0", "@prisma/compute-sdk": "0.43.0", "@prisma/management-api-sdk": "1.80.0", "@prisma/orm-toolchain": "8.0.0-rc.18", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6782262f..1496a188 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -30,8 +30,8 @@ importers: specifier: workspace:0.9.0 version: link:../cli-engine '@prisma/composer-cli': - specifier: 0.30.0 - version: 0.30.0(@effect/vitest@4.0.3(effect@4.0.3)(vitest@4.1.8(@types/node@22.19.19)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))))(@prisma/cli-engine@packages+cli-engine)(@types/node@22.19.19)(@vercel/nft@1.10.2(rollup@4.62.2))(hono@4.11.4)(mongodb@6.21.0(@aws-sdk/credential-providers@3.1107.0))(pg@8.23.0)(typescript@6.0.3)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))(vitest@4.1.8(@types/node@22.19.19)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)))(ws@8.21.0) + specifier: 0.31.0 + version: 0.31.0(@effect/vitest@4.0.3(effect@4.0.3)(vitest@4.1.8(@types/node@22.19.19)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))))(@prisma/cli-engine@packages+cli-engine)(@types/node@22.19.19)(@vercel/nft@1.10.2(rollup@4.62.2))(hono@4.11.4)(mongodb@6.21.0(@aws-sdk/credential-providers@3.1107.0))(pg@8.23.0)(typescript@6.0.3)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))(vitest@4.1.8(@types/node@22.19.19)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)))(ws@8.21.0) '@prisma/compute-sdk': specifier: 0.43.0 version: 0.43.0(@prisma/management-api-sdk@1.80.0)(rollup@4.62.2) @@ -61,8 +61,8 @@ importers: version: 11.0.0 devDependencies: '@prisma/composer': - specifier: 0.30.0 - version: 0.30.0(@types/node@22.19.19)(@vercel/nft@1.10.2(rollup@4.62.2))(hono@4.11.4)(mongodb@6.21.0(@aws-sdk/credential-providers@3.1107.0))(pg@8.23.0)(typescript@6.0.3)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))(vitest@4.1.8(@types/node@22.19.19)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)))(ws@8.21.0) + specifier: 0.31.0 + version: 0.31.0(@types/node@22.19.19)(@vercel/nft@1.10.2(rollup@4.62.2))(hono@4.11.4)(mongodb@6.21.0(@aws-sdk/credential-providers@3.1107.0))(pg@8.23.0)(typescript@6.0.3)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))(vitest@4.1.8(@types/node@22.19.19)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)))(ws@8.21.0) '@prisma/credentials-store': specifier: ^7.8.0 version: 7.8.0 @@ -213,8 +213,8 @@ importers: specifier: workspace:0.9.0 version: link:../cli-engine '@prisma/composer-cli': - specifier: 0.30.0 - version: 0.30.0(@effect/vitest@4.0.3(effect@4.0.3)(vitest@4.1.8(@types/node@22.19.19)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))))(@prisma/cli-engine@packages+cli-engine)(@types/node@22.19.19)(@vercel/nft@1.10.2(rollup@4.62.2))(hono@4.11.4)(mongodb@6.21.0(@aws-sdk/credential-providers@3.1107.0))(pg@8.23.0)(typescript@6.0.3)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))(vitest@4.1.8(@types/node@22.19.19)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)))(ws@8.21.0) + specifier: 0.31.0 + version: 0.31.0(@effect/vitest@4.0.3(effect@4.0.3)(vitest@4.1.8(@types/node@22.19.19)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))))(@prisma/cli-engine@packages+cli-engine)(@types/node@22.19.19)(@vercel/nft@1.10.2(rollup@4.62.2))(hono@4.11.4)(mongodb@6.21.0(@aws-sdk/credential-providers@3.1107.0))(pg@8.23.0)(typescript@6.0.3)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))(vitest@4.1.8(@types/node@22.19.19)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)))(ws@8.21.0) '@prisma/compute-sdk': specifier: 0.43.0 version: 0.43.0(@prisma/management-api-sdk@1.80.0)(rollup@4.62.2) @@ -1342,14 +1342,14 @@ packages: '@oxc-project/types@0.146.0': resolution: {integrity: sha512-XC0QsnnhVe7sLIWmYmdPw7x5P0h4W8vUU3Nv1ySgWXtvCz8NizoAEpGXA0sOYoJQV2Rl13LgURAHQ5cI5ILCSA==} - '@prisma/composer-cli@0.30.0': - resolution: {integrity: sha512-HgLn3hZ59NI/qxb7O762lfdkb8L3tOisURF/PtJ7SAOE/DllXv/ePh5KMpqEBW5NLPqhK/lfsdMGIksn+nv0Jg==} + '@prisma/composer-cli@0.31.0': + resolution: {integrity: sha512-a7E0dnq2D/352qxfDt64jSIxfZT5C4xZpCd4DKsmfGq5GfvbFohsXZpzVZ8dLqQnNYlScD03QxqWnV29yTgJlw==} engines: {node: ^22.18.0 || ^24.11.0 || >=26.0.0} peerDependencies: '@prisma/cli-engine': 0.7.0 - '@prisma/composer@0.30.0': - resolution: {integrity: sha512-/P/x6ZGGMUOehieCk62Xd4W32A/BlX5kFjvXlpZR3DhZ2zSNr7Nu5NLR7n8pzaGBI5MrZvai21L3oJU9iHzrEg==} + '@prisma/composer@0.31.0': + resolution: {integrity: sha512-sMU6rW1MyymJyre1x3b/JxQG/PqJn95DT76FWj6UZMLVk7ERskGOrB2S8Aum7uExtEAiz05Ow1D4Ok3F6XgzQQ==} engines: {node: ^22.18.0 || ^24.11.0 || >=26.0.0} '@prisma/compute-sdk@0.43.0': @@ -4059,10 +4059,10 @@ snapshots: '@oxc-project/types@0.146.0': {} - '@prisma/composer-cli@0.30.0(@effect/vitest@4.0.3(effect@4.0.3)(vitest@4.1.8(@types/node@22.19.19)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))))(@prisma/cli-engine@packages+cli-engine)(@types/node@22.19.19)(@vercel/nft@1.10.2(rollup@4.62.2))(hono@4.11.4)(mongodb@6.21.0(@aws-sdk/credential-providers@3.1107.0))(pg@8.23.0)(typescript@6.0.3)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))(vitest@4.1.8(@types/node@22.19.19)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)))(ws@8.21.0)': + '@prisma/composer-cli@0.31.0(@effect/vitest@4.0.3(effect@4.0.3)(vitest@4.1.8(@types/node@22.19.19)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))))(@prisma/cli-engine@packages+cli-engine)(@types/node@22.19.19)(@vercel/nft@1.10.2(rollup@4.62.2))(hono@4.11.4)(mongodb@6.21.0(@aws-sdk/credential-providers@3.1107.0))(pg@8.23.0)(typescript@6.0.3)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))(vitest@4.1.8(@types/node@22.19.19)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)))(ws@8.21.0)': dependencies: '@prisma/cli-engine': link:packages/cli-engine - '@prisma/composer': 0.30.0(@types/node@22.19.19)(@vercel/nft@1.10.2(rollup@4.62.2))(hono@4.11.4)(mongodb@6.21.0(@aws-sdk/credential-providers@3.1107.0))(pg@8.23.0)(typescript@6.0.3)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))(vitest@4.1.8(@types/node@22.19.19)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)))(ws@8.21.0) + '@prisma/composer': 0.31.0(@types/node@22.19.19)(@vercel/nft@1.10.2(rollup@4.62.2))(hono@4.11.4)(mongodb@6.21.0(@aws-sdk/credential-providers@3.1107.0))(pg@8.23.0)(typescript@6.0.3)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))(vitest@4.1.8(@types/node@22.19.19)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)))(ws@8.21.0) alchemy: 2.0.0-beta.83(@effect/vitest@4.0.3(effect@4.0.3)(vitest@4.1.8(@types/node@22.19.19)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))))(@types/node@22.19.19)(@vercel/nft@1.10.2(rollup@4.62.2))(effect@4.0.3)(hono@4.11.4)(mongodb@6.21.0(@aws-sdk/credential-providers@3.1107.0))(pg@8.23.0)(typescript@6.0.3)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))(ws@8.21.0) cross-spawn: 7.0.6 effect: 4.0.3 @@ -4096,7 +4096,7 @@ snapshots: - vitest - ws - '@prisma/composer@0.30.0(@types/node@22.19.19)(@vercel/nft@1.10.2(rollup@4.62.2))(hono@4.11.4)(mongodb@6.21.0(@aws-sdk/credential-providers@3.1107.0))(pg@8.23.0)(typescript@6.0.3)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))(vitest@4.1.8(@types/node@22.19.19)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)))(ws@8.21.0)': + '@prisma/composer@0.31.0(@types/node@22.19.19)(@vercel/nft@1.10.2(rollup@4.62.2))(hono@4.11.4)(mongodb@6.21.0(@aws-sdk/credential-providers@3.1107.0))(pg@8.23.0)(typescript@6.0.3)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))(vitest@4.1.8(@types/node@22.19.19)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)))(ws@8.21.0)': dependencies: '@effect/sql-d1': 4.0.3(effect@4.0.3) '@effect/sql-sqlite-do': 4.0.3(effect@4.0.3) diff --git a/skills/prisma-platform-core-concepts/SKILL.md b/skills/prisma-platform-core-concepts/SKILL.md index bf8c7507..7822d57a 100644 --- a/skills/prisma-platform-core-concepts/SKILL.md +++ b/skills/prisma-platform-core-concepts/SKILL.md @@ -333,11 +333,17 @@ own work: applies the schema, creates local stand-ins for declared buckets, starts the services, and prints a local URL. It watches built output and restarts a service when its build changes. -2. Exercise the running app directly (for example with `curl` against the - printed URL) instead of reasoning about what the code would do. -3. Stopping `dev` leaves local databases, buckets, and their data in place; - the next run is a warm start. `--fresh` wipes this app's local instances - and data first. +2. Exercise the running app directly (for example with + `curl "$(prisma dev url gateway)"`, with your service's name in place of + `gateway`) instead of reasoning about what the + code would do. `prisma dev url ` prints one node's local URL: a + service's HTTP URL, a database's connection string, or a bucket's S3 + address. Use `prisma dev --detach` to start the app and get your shell + back. +3. Stopping `dev` (Ctrl-C, or `prisma dev stop`) leaves local databases, + buckets, and their data in place; the next run is a warm start. `--fresh` + wipes this app's local instances and data first. `prisma emulator list` + shows every local instance on the machine. 4. Deploying is the same pipeline pointed at the platform: switching from local to hosted is a configuration change, not a code change. Reach for `prisma deploy --stage ` only when you need a shareable URL or