Use single-quoted strings for multiline git commit messages in the Shell tool. Prevents heredoc escaping failures that produce garbled commit messages.
日本語の概要は準備中です。原文の説明を表示しています。
Use when deploying or managing an app that uses Prisma Composer (`@prisma/composer`): wiring its services and Modules, running it locally, testing composed services, or standing up / tearing down an environment. Triggers on "prisma composer", "@prisma/composer", "prisma app", `prisma deploy`, `prisma dev`, `compute()`, `module()`, `contract()`, `service.load()`, `mockService`, `bootstrapService`.
インストール方法を見るインストールする前に、エージェントに与えられる指示の中身を確認できます。
A Prisma App is a tree of typed declarations composed in TypeScript and
handed to the prisma CLI, which has two Composer commands: prisma deploy
and prisma dev. Teardown and logs are not commands; they are the destroy
and log operations of @prisma/composer/control, called from a script.
This file covers structures, hierarchies, relationships, and workflows: the
concepts you cannot observe from the code or the CLI's help output. It is not
a CLI reference; discover each command's flags with prisma <command> --help
rather than inferring them. The Prisma platform moves fast, so treat this file as the
stable conceptual core and find current, fuller documentation at
https://www.prisma.io/docs. For working code, read examples/ in the
prisma/composer repo.
Two principles govern everything and are binding
(docs/design/01-principles/):
process.env is never the answer.Everything you author is a declaration: plain data describing a piece of the app, executing nothing when imported. Three node kinds exist:
| Kind | Declared with | Purpose |
|---|---|---|
| Service | compute() | A running unit of your code; atomic, Composer sees only its ports |
| Resource | rawPostgres(), bucket() | A stateful managed dependency |
| Module | module() | A grouping boundary; runs no code of its own, exposes typed ports |
Nodes connect through ports: deps declares what a node requires,
expose declares what it offers. Wiring happens in a Module's builder via
provision(), and the root Module, handed to the CLI, is the App:
// module.ts
import { module } from '@prisma/composer';
export default module('store', ({ provision }) => {
const catalog = provision(catalogModule);
provision(storefrontService, { deps: { catalog: catalog.rpc } });
});
Because ports are typed, the compiler verifies every wire. A dependency
wired to the wrong producer, a missing RPC handler, a literal input value of
the wrong shape: all of it fails tsc, not the deploy. Env-bound input is
the exception: those values exist only at deploy, so secret-binding
mismatches and missing platform variables surface as early deploy-time
refusals instead (see Two channels below). Typecheck, then build, then
deploy; don't use the cloud to find out whether the wiring is correct.
Composer itself is target-agnostic: @prisma/composer carries authoring,
testing, and the CLI, coupled to no platform. A deploy target is an extension
registered in the deploy config; @prisma/composer-prisma-cloud is the
Prisma Cloud target and the one this skill's deploy sections assume. Its
root exports compute, rawPostgres, bucket, envSecret, and
envParam; the ORM vocabulary (postgres, dataContract) lives under the
/orm subpath, alongside the shared /cron, /storage, /streams,
/auth, and /email modules. These are the only two Composer packages a
basic Prisma Cloud app needs, and nothing installs them for you: a fresh
project starts with neither, so add both as dependencies first. An
extension adds its own prisma-composer-* package alongside them. Compose
an existing Module before implementing a capability yourself; wiring one in
is a couple of lines.
Within the entry graph (everything reachable from module.ts), write
relative imports with explicit .ts extensions (./service.ts, with
allowImportingTsExtensions in tsconfig): that form resolves everywhere.
prisma deploy and prisma dev also map ./service.js and extensionless
./service to the .ts source, but other tools may not.
Your runtime code receives everything from the service declaration it imports:
service.load(): dependencies (typed RPC clients, database bindings).service.input(): the whole input as one schema-validated object;
credentials in it are redacting SecretString boxes.service.port(): the reserved port to bind (default 3000).A service declaration is pure data; the server entry is what your build produces and the platform boots:
// service.ts
export default compute({
name: 'auth',
deps: { db: rawPostgres() },
build: node({ module: import.meta.url, entry: '../dist/server.mjs' }),
expose: { rpc: authContract },
});
// server.ts
const { db } = service.load(); // { url }: you construct your own client
const handler = serve(service, {
rpc: { verify: async ({ token }) => ({ ok: token.length > 0 }) },
});
Bun.serve({ port: service.port(), hostname: '0.0.0.0', fetch: handler });
The consumer declares deps: { auth: rpc(authContract) } and gets a typed
client back from load().
| The value is… | Declare | Provide | Read |
|---|---|---|---|
| produced by another node | deps: { db: rawPostgres() } | wire at provision() | load() |
| anything else (config or credential) | one field of the input schema | bind at provision(): literal, envParam(), or envSecret() | input() |
The service declares its whole incoming configuration, plain values and
credentials together, as one Standard Schema
(arktype is the house choice). A credential is a field typed as
secretString() from @prisma/composer/arktype; conditional legality ("no
stripe key unless billing is on") is an ordinary schema union. The binding at
provision() mirrors the schema's shape; envSecret('NAME') names the
platform variable and never carries the value.
Rules that bite:
SecretString fails the deploy; envSecret bound to a plain
string field fails the same way.envParam values arrive as raw strings; bind them to string fields.
The stage's platform variable is the store; the deploying shell only seeds
a missing name (and the deploy fails early, naming the variable, when both
lack it). Changing the platform value needs a redeploy.{"$secret":"VAR"} pointers)
and every key that resolved absent.port is outside the schema. Read it through
service.port(), never process.env. The framework also exports PORT
for Next.js standalone, which binds it itself.secrets: { signingKey: secret() } on the Module boundary and
pass the forwarded ref as a binding leaf; the parent binds the real
source.input.apiKey.expose() is the only way to a secret's value; the box
redacts everywhere else (logs, JSON, errors).A contract is the typed interface through which services communicate. It
lives with the service that owns it, typed by any Standard Schema validator,
and both provider (serve(), exhaustive over the contract's methods at
compile time) and consumer (rpc(contract)) reference the same value. Calls
travel as RPC over HTTP. Two behaviours are provisioned for you and must not
be reimplemented:
serve() returns 401 to anything else before
the handler runs. Nothing in your code declares it. Consequences: don't
build your own service-to-service auth, and don't curl a deployed
/rpc/<method> to check it works. An unwired caller always gets 401,
which looks like a broken deploy and isn't. Debug through a consumer, or
locally, where nothing is enforced. Keys are per binding (one leaking
can't impersonate another consumer), service-scoped (any valid key
reaches every method; split services to gate separately), rotated only by
removing the binding or destroying the stack and redeploying, and stored
in deploy-owned COMPOSER_* variables you never hand-edit.Idempotency-Key; dropped calls retry with backoff, and serve() runs
one call per key, replaying the completed answer to late retries. Every
method is therefore safely retryable and no contract declares anything
about it (there is no "is this idempotent" flag; don't invent one). A
handler may take an optional third argument (input, deps, ctx) and read
ctx.idempotencyKey (string | undefined) if it needs exactly-once
beyond one instance's memory; most don't. Locally and in tests nothing is
provisioned, so serve() passes every call through: never supply a key
in test inputs.You build, the framework assembles. For a plain server process, entry
points at the ESM file your build produced. By default
(dependencies: 'bundled') deploy copies exactly that and never ships
node_modules, so everything except runtime built-ins (bun, bun:*,
node:*) must be inlined, or it fails at boot, not at deploy. Rules that
bite:
dir + entry (dir relative to the service
module, entry a file inside dir; ../ is an error). The tree is
copied verbatim, so the server must resolve siblings against
import.meta.url, not the working directory. The tree must contain no
symlinks: the packager rejects them, names the link, and assembly fails.dependencies: 'external'
(either form). Deploy then traces entry and stages the installed
packages it imports, which can take minutes on a large build. Astro's Node
adapter, SvelteKit's adapter-node and React Router's server build leave
packages external by default. The default, 'bundled', copies exactly
what was built. A service that fails to start with
Cannot find package 'x' needs x bundled, or dependencies: 'external'.next build with output: 'standalone' is the whole build;
nextjs({ module, appDir }) names the app root. Any page or action that
calls load() needs export const dynamic = 'force-dynamic', because
the runtime environment doesn't exist at build time and Next ignores
runtime env for prerendered routes.deploy or dev. Neither builds for you.Deploy configuration is the composer section of prisma.config.ts, and
nothing else. It registers extensions (prismaCloud(), nodeBuild(),
nextjsBuild() when the app has a Next.js service) and the deploy-state
backend (prismaState()):
// prisma.config.ts
import { defineConfig as composer } from '@prisma/composer/config';
import { nodeBuild } from '@prisma/composer/node/control';
import { prismaCloud, prismaState } from '@prisma/composer-prisma-cloud/control';
import { definePrismaConfig } from 'prisma/config';
export default definePrismaConfig({
composer: composer({ extensions: [prismaCloud(), nodeBuild()], state: prismaState() }),
});
The commands find prisma.config.ts from the directory they run in, walking up
to the repository root; the nearest file that declares composer wins, and its
section is used whole, never merged key by key. Only extensions and state
are allowed; any other key is an error. App code never imports the file.
A separate prisma-composer.config.ts is no longer read, and the old setup is
refused, never silently ignored: CONFIG.SECTION_MISSING when no loaded
prisma.config.ts declares a composer section, CONFIG.FIELD_RETIRED when
the section still has configPath, CONFIG.FILE_RETIRED when a
prisma-composer.config.* sits next to the declaring prisma.config.ts; all
three under the CLI's CLI.CONFIG_SECTION_INVALID. SECTION_MISSING is fixed by
adding the composer section to prisma.config.ts. FIELD_RETIRED and
FILE_RETIRED are fixed by moving the old file's extensions and state into
the section, then removing configPath or deleting the old file.
@prisma/composer-cli/family no longer exports ComposerSection; the
section's type is PrismaAppConfig from @prisma/composer/config.
Two kinds of Postgres dependency:
rawPostgres(): the binding is { url } and the app owns its client.postgres(...): a Prisma-ORM-typed database. The binding is
{ url, client } (ADR-0040): the raw connection URL plus the typed
client Composer constructs from your data contract, lazily on first
access, so queries go through binding.client and are compile-time
checked. Both postgres and dataContract import from
@prisma/composer-prisma-cloud/orm, not the package root. One
dataContract-wrapped value (emitted from contract.prisma by
prisma contract emit) is referenced by both the dependency end
(deps: { db: postgres(catalogData) }) and the resource end, which also
names the prisma.config.ts path so the deploy's migration step can
reload the emitted contract.json and find migrations/.Deploys are replay-only: they apply the migrations committed under
migrations/ and never create schema themselves. Every schema change,
including the first schema of a new database, follows one loop:
contract.prisma.prisma contract emit regenerates contract.json + contract.d.ts.prisma migration plan --name <slug> authors the migration (on an empty
graph this authors the baseline).migrations/ with the change, then deploy. A fresh database
replays the whole path from empty.Every service that uses the database deploys only after its migration completes: a failed migration means the new code does not ship. The old code serves against the new schema until the new deployment is live, so keep each migration compatible with the code it replaces.
If no authored path reaches the target contract, deploy (and dev against a
stale local database) refuses with MIGRATION_PATH_NOT_FOUND; its message
lists the two ways out: author the missing migration, or, when iterating
against a local
database only, prisma db update. The tracked migration resource persists only
compact contract identity in deploy state; if the emitted contract artifact
named by prisma.config.ts is missing, unreadable, or no longer matches the
declared dataContract(...) value, deploy fails before touching the database.
Never skip step 3 before a deploy. See examples/store/modules/catalog for the
complete pattern.
Deploy compares the declared topology against recorded deploy state and
applies only the difference. Re-deploying with nothing changed is a no-op;
removing a node removes its deployed resource. prisma deploy needs a signed-in
identity: prisma auth login stores a session on a developer machine, and
PRISMA_SERVICE_TOKEN overrides it in CI. The /control operations, and so
a destroy script, never use that session: deploy and destroy read
PRISMA_SERVICE_TOKEN and PRISMA_WORKSPACE_ID from the environment (both
in the workspace's Console settings); dev and log read neither. The
prisma bin starts under Node; use pnpm prisma … or npx prisma … by
default. Composer starts Alchemy with Node, but Alchemy's launcher moves to
Bun under bunx or bun run: bunx prisma gives Node then Bun,
bunx --bun prisma Bun then Bun. When the modules module.ts imports use
Bun APIs, bun node_modules/prisma/dist/prisma.js deploy module.ts from a
shell runs prisma under Bun with Alchemy on Node.
Progress. prisma deploy prints each step as it starts and finishes, with
its duration (✔ assemble web (3m 42s)), and ends with the real total
(Deployed <app> to <stage> in 5m 25s.). Steps: load config and app, one
assemble per service, connect to project and branch, check environment
variables, plan and apply (one step: alchemy does both in one process), record
result. A slow assemble is usually a Node service with
dependencies: 'external', whose runtime dependencies are being traced. In json mode (--json, or stdout not a
terminal) each step is a step-started/step-finished line whose data
holds durationMs plus whatever the build adapter or deploy target reported;
those extra fields vary, so don't parse them as a stable format. The
deploy operation's onEvent receives the same steps, and its result's
durationMs is the total.
Stages. A stage is an environment name chosen on the command line at deploy time, never written in the topology. The identical graph deploys everywhere. On the Prisma Cloud target, a Prisma App is one Project and a stage is a Branch of it, with its own running services, its own empty database, its own configuration. A stage name must be a valid git ref name; an invalid name is a hard error.
Destroy is the destroy operation, and its target is required:
{ kind: 'stage', stage } or { kind: 'production' }, never a default:
await destroy({ entry: 'module.ts', target: { kind: 'stage', stage: 'pr-42' }, config });
Destroying a stage deletes its Branch after removing its resources. Destroying production removes only the resources inside the production Branch, never the Branch itself directly; once the Project is empty it is deleted too, and that deletion takes the production Branch with it. A Project still holding another stage's resources is kept. Destroy never creates anything: destroying a never-deployed stage fails rather than standing one up.
The engine underneath is alchemy. Convergence is executed by alchemy, a third-party infrastructure-as-code engine that arrives as an ordinary, exactly-pinned npm dependency of @prisma/composer (2.0.0-beta.78 at this library version). Your code never imports or configures it; consult alchemy's own docs for the engine itself. What matters operationally:
Composer runs the alchemy package installed beside the app's
@prisma/composer and starts it with Node (the first node on PATH when prisma runs
under Bun; DEPLOY.NODE_MISSING if none), so the app needs no direct
alchemy dependency and no .bin link. No global Alchemy installation is
needed.
.prisma-composer/alchemy.run.ts, then run the alchemy CLI
against it as a child process; dev does the same at
.prisma-composer/dev/alchemy.run.ts with local providers. The file
carries the computed values as literals but reads credentials via
fromEnv(), so nothing sensitive lands on disk, and it is regenerated
every run: output, not configuration, never edited.alchemy
Composer depends on, with deploy .prisma-composer/alchemy.run.ts --yes --stage <stage>. Running it directly separates "the framework computed the wrong thing" from "the engine or
platform rejected the right thing". An engine failure surfaces as
DEPLOY.ENGINE_FAILED carrying the exit code, the engine's own error
lines (credentials redacted, capped at 1000 characters) and that reproduce
command; the child's live output streams to the terminal either way.effect pin exists: it resolves the effect
constellation, and a hoisted newer effect halts every command (failure
mode 1 below).The deploy report ends with the app's own topology: authored names, the platform resource each became, and public URLs. Read ids out of it rather than hunting in the Console. A URL appears only where the address is genuinely public: a service prints one, a database never does, and a node whose product is secret material reports no resource line at all.
Connection contract refusals. A connection declares the values it needs by name; a producer that omits one fails the deploy, naming the edge, the param, and what the producer did supply:
Connection input "auth.db" declares param "url", but its producer "db" did not
supply it — the producer's outputs carry [host].
This is a deploy-time refusal, not a broken deploy, and it can appear on an
app whose code didn't change (the gap used to pass silently as undefined
and crash the consumer at boot). Fix whichever end is wrong; don't mark the
param optional unless absent really is legal. Only reachable if you
authored the connection or an extension on one side.
Driving deploys from code. A script imports only
@prisma/composer/control; the extensions' /control entries are imported
only by prisma.config.ts (ADR-0017). @prisma/composer/control exposes typed
deploy, destroy, dev, and log returning structured results;
prisma deploy and prisma dev render deploy and dev. Each takes
a required config: { value, file } (ComposerConfigSource): the composer
export of your prisma.config.ts and that file's path; a relative file
resolves against cwd, so build it from import.meta.url. The operations
never look for a config file, but refuse what the CLI refuses before any work
starts (CONFIG.FIELD_UNKNOWN for the whole export instead of its composer
property, CONFIG.FILE_RETIRED, CONFIG.FILE_MISSING); the deploy re-imports
file, so value must be its composer export. Failures come back as
{ ok: false, failure } with a dotted failure.code from a closed registry
(e.g. ASSEMBLE.BUILD_FAILED, DEPLOY.ENGINE_FAILED,
DEPS.EXECUTOR_UNLOADABLE); branch on the code, not the message. A
non-structured rejection out of an operation is a bug in composer, not an
expected failure.
prisma dev runs the whole app on this machine, wired as it deploys,
against local emulators. No cloud credentials are needed or read. Concepts
that surprise:
It runs the same pipeline as deploy, so build first, exactly like deploy. It watches built output and restarts a service when its build changes.
Ctrl-C stops the app's processes but leaves local databases, buckets, and their data up: the next dev is a warm start. Starting clean, wiping this app's local instances and data first, is an explicit opt-in flag. On a fresh start, each service gets the lowest free port from 3000 up, in dependency order: a service before the services that call it, otherwise provision order. A warm start keeps the ports services already have.
dev does not print service logs. The log operation follows the
already-running app's merged logs; it never builds, provisions, starts, or
stops anything:
const attached = await log({ entry: 'module.ts', config, tail: 20, signal });
if (attached.ok) for await (const { service, line } of attached.value.lines) console.log(service, line);
dev reads prisma.config.ts once, at start, and watches it: after an
edit it says so and pauses rebuilds until you restart dev.
An unset secret doesn't block a local run: it becomes a placeholder plus a warning, and only the code path that spends it fails, at the external service it calls.
The emulators are machine-wide daemons shared by every dev, registered
under ~/.prisma-composer/emulators. Set PRISMA_COMPOSER_EMULATORS_DIR
to an absolute directory to give a checkout or CI job its own compute and
buckets daemons, registry and data; a relative path (or an unexpanded ~)
fails with DEV.EMULATORS_DIR_INVALID. It does not isolate local Postgres:
servers are named after the app and database, so two checkouts of one app
share a server, and --fresh or teardown in either stops it and deletes
the database for both. emulatorRegistryRoot() from
@prisma/composer-prisma-cloud/local-target returns the directory in
effect.
Windows isn't supported yet.
Local Postgres runs on @prisma/dev, which @prisma/composer-prisma-cloud
declares as its own dependency (^0.25.2) and resolves from its own package.
Nothing needs adding to the app, and an app's own @prisma/dev (for example the
^0.20.0 alchemy pulls in, which crashes on any Postgres message over 64 KiB) is
ignored. If the emulator reports that @prisma/dev did not resolve, the install
is broken: reinstall dependencies rather than adding @prisma/dev or prisma.
Cloud deployment and local apps without Postgres never load this runtime.
A test is just another environment: one where you decide what load() and
input() return, never by editing the code under test.
| You want to… | Use | From |
|---|---|---|
| Test a page / action / handler in isolation | mockService | @prisma/composer/testing |
| Run the real boot + request path against a fake dependency | bootstrapService | @prisma/composer-prisma-cloud/testing |
mockService returns a copy of the service whose load() yields your
doubles (type-checked against the declared deps) and whose input() yields
the object passed under the reserved input key (required exactly when the
service declares an input schema; handed over as-is, not validated). Wiring
the module substitution is your runner's job (vi.mock in Vitest,
mock.module in bun test).
bootstrapService boots the service's real built entry in-process against a
config you choose; drive it over real HTTP. Gotchas:
service.port must be concrete: the entry self-listens, and no
OS-assigned port is reported back.close(); run each integration-test file in its own process
(bun test does).standaloneServerPath from @prisma/composer/nextjs/control.input in the config, a binding
exactly like provision()'s, run through the real serialize/read path.A dependency's type is its contract, so any value of that shape is a valid
double: a bare object, the real client over an in-memory handler, or a real
local server. Ship a dependency's fake from its own package as a /fake
entry point, outside src/, so the fake and the real service share one
contract.
First-party Modules ship inside @prisma/composer-prisma-cloud and
provision exactly like your own:
| Import | What it provisions | Exposes |
|---|---|---|
cron from /cron | An always-on scheduler (it holds Compute's keep-awake guard) firing your schedule at your runner service; input on cron() binds the runner's input schema | nothing |
storage from /storage | An S3-backed blob store (own Postgres + minted credentials) | store |
streams from /streams | Durable append-only event streams over a store | streams |
auth from /auth | Signup, login, sessions, and JWT verification (Better Auth in one service, own database). auth({ signUp: 'closed' }) makes Better Auth refuse self-service sign-up; operator-created accounts go through admin.createUser({ email, name, password?, emailVerified? }) from a service wired to admin (it throws on a duplicate email and sends no mail); a signed-in user deletes their own account with Better Auth's POST /api/auth/delete-user through the proxy (password, or a session < 24 h old); operators delete with admin.removeUser({ userId }); either way your own rows follow your auth:User FK's onDelete (Cascade deletes them, Restrict refuses the deletion) | api, session, admin |
email from /email | Transactional email with a stored outbox (own service and database) | send, outbox |
bucket() (imported alongside rawPostgres) is a raw S3-compatible bucket:
the dependency end receives { url, bucket, accessKeyId, secretAccessKey },
shape-compatible with /storage's s3() dependency, so a service wired to
s3() can be rewired to a bucket resource unchanged.
An extension (a package bringing its own Modules, resources, or deploy
target) is published on npm as prisma-composer-*. The ecosystem is new:
today the blocks above plus your own Modules are the whole set, so verify a
prisma-composer-* package exists on npm before reaching for it.
prisma deploy and prisma dev stop with CLI.CONFIG_UNREADABLE on an
effect version conflict (prisma.config.ts could not be evaluated:
followed by a module error from inside alchemy, such as
Schema.TaggedError is not a function). The extensions in the composer
section import alchemy, and the app, or one of its dependencies, pins a
different effect that the package manager hoisted over Composer's pin. Match the app's own
effect to @prisma/composer's exact pin, or force it, then reinstall:
npm: "overrides": { "effect": "<pin>" } in package.json; pnpm 11+:
an overrides: block in pnpm-workspace.yaml; pnpm 10 and earlier:
pnpm.overrides in package.json; Yarn: resolutions in package.json. A plain Composer
app never hits this: the public packages pin every effect-family
package alchemy would float./rpc/<method> returns 401 to anything but a wired
peer. Not a broken deploy; see Contracts above.new SQL({ url, max: 1, idleTimeout: 10 }) for Bun)
and the process logs uncaughtException/unhandledRejection instead of
dying. Under dev, add prepare: false as well: the local Postgres
is one session shared by every connection and it outlives your
processes, so a restarted process collides on prepared-statement
names (42P05) and crash-loops.ECONNRESET; retry it.0.0.0.0, not loopback. The platform routes external HTTP to
the VM; a loopback-only listener is unreachable.[A-Za-z0-9]): they
derive config keys and address segments, so a hyphenated name like
my-db passes tsc and then fails the load. The root module's name is
exempt. A provision id shorter than 3 characters is rejected by the
platform (name the database 'database', not 'db'), and a service
whose name equals its enclosing Module's reads as auth.auth unless
given an explicit id.MIGRATION_PATH_NOT_FOUND: see Databases above; author the missing
migration, don't skip the plan step.Temporal.* values on read. Bun and
stock Node ship no global Temporal, so a service with DateTime
contract columns compiles and deploys, then fails on the first timestamp
read. Provide the global at the server entry
(import 'temporal-polyfill/global') or use string column types./api/auth/* returns 403 MISSING_OR_NULL_ORIGIN
to a Node script. It is the browser surface: Better Auth origin-checks
any request carrying a cookie, an Origin/Referer, or a Sec-Fetch-*
header, and Node's built-in fetch sends Sec-Fetch-Mode on every
request (the same curl passes). Send an Origin equal to the module's
baseUrl, or, for provisioning, don't use that surface at all: call
admin.createUser from a service wired to the admin port. A deployed
stack's rpc ports are reachable only from inside its graph, so the app
exposes its own operator route that makes that call.Name the gap instead of inventing an API:
prisma command for teardown or logs. Use the destroy and log
operations of @prisma/composer/control from a script. A destroy script
cannot use the prisma auth login session; it needs PRISMA_SERVICE_TOKEN
and PRISMA_WORKSPACE_ID in the environment.bootstrapService with a loopback
fake.For anything else missing, check examples/, docs/design/10-domains/, and
docs/design/90-decisions/ in the prisma/composer repo, then file an issue
there rather than guessing.
まだレビューはありません。使ってみた感想をお寄せください。
概要と使いどころ
Use single-quoted strings for multiline git commit messages in the Shell tool. Prevents heredoc escaping failures that produce garbled commit messages.
日本語の概要は準備中です。原文の説明を表示しています。
Cuts the next minor release of Prisma Composer: bumps the root package.json version, propagates it to every workspace package in lockstep, and opens a PR titled "chore(release): v<next-version>". When a maintainer merges the PR, the `Publish to npm` workflow runs automatically and ships the new version to npm under dist-tag `latest`, plus a matching GitHub Release with auto-generated notes. Use when a maintainer asks to "cut the next minor", "bump to the next version", "open a release PR", or "prepare a publish PR".
日本語の概要は準備中です。原文の説明を表示しています。
How to upgrade `alchemy` and the `effect` constellation across this repo and keep them consistent for consumers: which packages pin what, why `effect` and every `@effect/*` companion move as one set, what breaks in a typical upgrade, and how to verify a standalone `npm install` still resolves a single `effect`. Use when asked to upgrade or bump alchemy or effect, when a deploy dies inside an alchemy provider with a `TypeError` naming a missing combinator, when `check:npm-effect-resolution` fails, or when deciding whether the alchemy patch is still needed.
日本語の概要は準備中です。原文の説明を表示しています。