Repository navigation
feat(dev): prisma dev url prints where a local service answers; add prisma dev stop and prisma emulator list - #357
Conversation
…ommands Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
`@prisma/composer/control` gains two operations that act on the app
`prisma dev` last ran from a directory, read from its dev state alone:
- `devUrl({ config, address, cwd })` returns `{ address, kind, url,
state }` for a running node: a service's URL, a database's connection
string, or a bucket's S3 endpoint plus `/<bucket>`.
- `devStop({ config, cwd })` stops the app's service processes and
database servers and returns what it stopped. Data and ports stay.
They fail with DEV.NOT_STARTED_HERE (no record in the directory),
DEV.ADDRESS_UNKNOWN (listing the known addresses),
DEV.EMULATOR_UNREACHABLE (the node's emulator is not running) and
DEV.NOT_RUNNING (naming the node's state).
The core local-target seam gains an optional `current({ devDir })`,
which returns the recorded app's name, its addresses, `locate(address)`
and `stop()`. Core never reads the record; the Prisma Cloud target
implements it from emulator-instances.json.
`listEmulators()` in the Prisma Cloud domain, exported from
`@prisma/composer-prisma-cloud/local-target`, lists each emulator
(`service`, `database`, `bucket`), whether it runs, its admin URL, and
its instances with id, kind, URL, state and labels. Nothing running is a
valid answer.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
The family ships two more commands, keyed by the path they are meant to
mount at; the host decides where each one mounts.
- `dev url <address>` prints a node's local URL. In human format the
URL alone goes to stdout, so `$(prisma dev url gateway --format
human)` is the URL; the JSON result is `{ address, kind, url, state }`.
- `dev stop` stops the app `prisma dev` last ran from the directory and
returns `{ app, stopped }`.
Both declare the `composer` config section. `createComposerFamily`
takes extra `commands`, so the published family can add `emulator
list`, and the operations double covers `devUrl` and `devStop`. The
`dev` command's description now defines what the commands beneath it
rely on: an emulator, a node's address, and that the app is recorded
in the directory.
The family's tests mount `deploy` and `dev` explicitly, since the
engine they build against (0.7.0) cannot mount commands beneath a
command.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
`@prisma/composer-cli/family` assembles `emulator list` into the
family, beside the framework's commands; it needs no project and no
config. The listing comes from the Prisma Cloud domain, which this
public package may import and the framework may not, and loads on first
use, so the family's static graph stays light.
Human output is one tree: each emulator, whether it runs and its admin
URL, and under it each instance with its URL, state, and the node and
directory that started it. The JSON result is `{ emulators: [{ kind,
running, url, instances: [{ id, kind, url, state, labels }] }] }`.
`createComposerFamily({ listEmulators })` lets a host substitute the
listing in its tests.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
ADR-0053 records the three commands, the devUrl and devStop operations, the core local-target current() seam and the DEV errors it raises. It amends ADR-0050 (the family was exactly deploy and dev) and ADR-0043 (the control subpath had four operations). The running-locally guide, the deploying guide, local-dev.md, deploy-cli.md and the core-concepts skill describe the commands, the jq form for scripts, and that prisma emulator start and stop are planned. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
…de is down The executor gave every error, bugs included, the DEV.EMULATOR_FAILED code. Now only failures from the target's current, locate and stop calls get it; other errors are rethrown, and a recorded address the target cannot locate is an InternalError. DEV.NOT_RUNNING now chooses its reason and fix from the node's condition, which the target reports: a stopped node needs `prisma dev`, a crash-looping service needs its log read, and a node its emulator lost is created again by `prisma dev`. dev stop reports only the nodes whose emulator was running. Stopping no longer swallows errors other than "the emulator is not running", so an invalid emulators directory fails with DEV.EMULATORS_DIR_INVALID. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
An emulator that does not answer, or answers with an error, no longer fails
the whole listing. Its entry carries `error: { code, message }`, with
DEV.EMULATOR_UNREACHABLE or DEV.EMULATOR_FAILED, and the others are still
listed. `url` is null for an emulator that is not running. Only an
invalid emulators directory fails the command.
The listEmulators re-export from @prisma/composer-prisma-cloud/local-target
is removed: nothing used it, and the command uses the client bundled into
@prisma/composer-cli.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
…rks after dev ends The dev card now defines a node as one service, database or bucket in the app, and says that `prisma dev url` works while `prisma dev` runs and `prisma dev stop` also works after it was killed. The dev url summary defines a node in place, the address brief drops "module", and the jq example uses -e so a failure does not print a URL. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
… a real config The target's own emulators hook records the integration fixture's app in a temporary directory on real emulators in a temporary emulators directory. devUrl, called with the package's prisma.config.ts, gives a URL the service answers at and the database's connection string; devStop stops the services and the database server, their ports close, and devUrl then fails with DEV.NOT_RUNNING. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
…s, and the safe jq form ADR-0053 and local-dev.md say emulator list uses the client bundled into @prisma/composer-cli, record that the emulators' registry files and list routes are now read across Composer versions, and give the per-emulator error and null url in its JSON. ADR-0044 says devStop raises only NOT_STARTED_HERE. The guide, the skill and the ADR use `url=$(… | jq -er …) && curl "$url"`, because jq -r alone prints null on failure and curl runs anyway. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
|
✅ Gizmo reviewed 9329213 — posted 0 inline comment(s) this pass. Open findings: none Change walkthroughThis incremental pass reviewed the delta since the last reviewed commit: a coordinated dependency/version-bump block across the workspace, plus design-doc, guide, skill, and integration-test updates. It does not touch the Version and dependency bumps. Every workspace manifest moves from 0.29.1 to 0.30.0 (the minor bump produced by scripts/bump-minior.ts's procedure via Docs. docs/design/10-domains/local-dev.md refines the concurrent-starts rules: a start whose process has already exited no longer accepts waiters, so a session-resume or identical-deployment PUT arriving in that window starts the service again — the prose and the two qualified table rows agree with each other and with the readiness/crash-loop rules earlier in the section. docs/guides/deploying.md documents the node-address-as- Tests. test/integration/test/control.dev-current.test.ts hardens the port-skip placeholder-instance setup: a failed creation now throws with the status and response body before the unchecked |
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configuration
Comment |
commit: |
…T_RUNNING The local-target seam reserves an absent URL for an instance the emulator lost, which reports the `missing` condition. A target that reports a node as running with no URL broke that contract, and devUrl printed "is not running (running)". It now raises an InternalError, as it does for a recorded address the target cannot locate. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
… use Each test file runs its own Compute emulator, and each emulator gives service ports from 3000. A port is free when the emulator gives it, but another file's service can bind it first, and then the readiness probe and the test's fetch reach that file's service: on macOS CI the gateway answered "first", the body compute-deployment.test.ts serves. The two files that fetch a service they deployed now fill the ports below a start of their own with placeholder instances first: 3050 for local-target-current.test.ts and 3100 for control.dev-current.test.ts. Each asserts its service's port is at or above that start, and the listing test ignores the placeholders. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
Brings in the `listens: false` deployment property for services that never listen on their port, and the test of its error-message rewrite. No conflicts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
Brings in the bucket-path fix in the local-dev criteria 4 and 5 proof. Signed-off-by: Will Madden <madden@prisma.io> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Brings in #353's start fixes and tests, the readiness tests' own ports, and main. The target extension's and @prisma/composer-cli's manifests keep this branch's dev dependencies at main's version, 0.30.0, and take main's @distilled.cloud/prisma; the lockfile follows. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
…st at its cause The loop that fills ports below 3100 read .port from any response. It now throws with the emulator's status and body when creating a placeholder fails. local-target-current.test.ts creates its placeholders through the compute client, which already throws on an error response. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
Brings in #353's own port range for the readiness tests; the test file keeps the instance-keyed version. No other changes. Signed-off-by: Will Madden <madden@prisma.io> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Linked issue
n/a. Part of the local-dev work; the plan is in
.drive/projects/emulator-commands/.Summary
Scripts, docs and agents can ask where a locally running service is, instead of assuming its port:
Decision: Composer adds three commands,
prisma dev url,prisma dev stopandprisma emulator list. The first two are also programmatic operations,devUrlanddevStop, on@prisma/composer/control. ADR-0053 records this.Why
Local ports aren't fixed.
prisma devgives services the lowest free ports from 3000, in dependency order, and each directory keeps its own (#354). Solocalhost:3001is right for one checkout on one machine and wrong for the next. Composer's getting-started page currently hard-codescurl localhost:3001.prisma dev urllets it ask instead.Background
prisma devruns an app against emulators: long-lived local stand-ins for Prisma Cloud, shared across the machine, which run its services, Postgres databases and buckets. Each part of the app is a node, and its address is its dotted name in the app, such asgatewayorshop.quotes. #354 and #356 madeprisma devrecord, in.prisma-composer/dev/emulator-instances.json, which emulator instance runs each node of the app it last ran from that directory.prisma dev url <address>prisma dev urlreads that record for the current directory and prints where the node answers:http://localhost:<port>;/<bucket>. Access keys are never printed.It prints a URL only while the node is running, so every URL it prints answers. Its JSON result is
{ address, kind, url, state }. Failures each have their own code:prisma devnever ran in this directoryDEV.NOT_STARTED_HEREDEV.ADDRESS_UNKNOWNDEV.EMULATOR_UNREACHABLEprisma dev; it's crashing, so read its log; or its emulator lost it, soprisma devre-creates it, emptyDEV.NOT_RUNNINGprisma dev stopprisma dev stopstops the current directory's app, its service processes and its Postgres servers, as endingprisma devdoes. Data and ports stay. It's for an agent cleaning up before deleting its checkout, or for aprisma devthat was killed before it could stop the app. It reports what it actually stopped.prisma emulator listprisma emulator listasks about the machine, not a project, so it needs noprisma.config.ts. For each emulator it shows:An emulator that doesn't answer gets an error in its own entry, and the others are still listed.
How it fits Composer's layers
Composer's core doesn't know about any particular deploy target.
devUrlanddevStoptherefore go through the local-target interface that core already has. It gains an optionalcurrent({ devDir }), which returns the directory's recorded app and lets core locate or stop its nodes. The Prisma Cloud target implements it from the record.emulator listhas no project to start from, so it lives next to the emulator clients, and@prisma/composer-cliadds it to the command family.Mounting and piping
These commands reach users once the
prismaCLI mounts them. That needs@prisma/cli-engine0.8.0, which letsprisma devbe both a command and a group (prisma/prisma-cli#349, merged).Today a piped
prismacommand prints JSON, so the guide shows scripts usingjq. prisma/prisma-cli#353 changes a pipe to get the plain URL, after whichcurl "$(prisma dev url gateway)"works directly.Testing performed
prisma.config.tsagainst real emulators (skipped on Windows):devUrlreturns a service URL that answers and a database connection string.devStopstops exactly the app's nodes and closes their ports.devUrlthen fails withDEV.NOT_RUNNING.select 1, and a bucket URL takes an S3 write and listing.emulator listwith nothing running, with an emulator that doesn't answer, and with one that returns an HTTP 500.Also
pnpm build,typecheck,lint,lint:deps,lint:casts, the family import-graph check, and the packaging checks.Checklist
git commit -s) per the DCO. The DCO status check will block merge if any commit is missing aSigned-off-by:trailer.feat,fix,chore,docs,refactor,test,build) — PR titles drive the auto-generated release notes.n/aif the change is doc-only / refactor with no behavioural delta).Notes for the reviewer
mainas the stack merges.DEVcodes);local-dev.md;deploy-cli.md; the running-locally and deploying guides; the core-concepts skill. They sayprisma emulator startandstopare planned.prismaCLI now carries the emulator client.@prisma/composer-clibundles it, and the emulators may have been started by a different Composer version. So the emulators' registry files and instance-list routes now have to stay backward compatible. ADR-0053 says so.emulator list's JSON departs from the CLI's usual list shape. It nests emulators and their instances, because an instance means nothing without its emulator.Alternatives considered
prisma emulator url <address>. It would behave the same, but it answers a question about this directory's app, which belongs underdev. Theemulatorcommands are about the machine.prisma url. It's ambiguous between a local service and a deployed one.--app. Addresses are relative to the directory's app, and app names repeat across checkouts.emulator listthrough the local-target interface. That would require a project and a configuration for a question about the machine.Agent: attila-51
🤖 Generated with Claude Code