@samebase/alchemy-convex 0.12.0 → 0.13.0

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 CHANGED
@@ -167,7 +167,7 @@ values explicitly: `Convex.providers(Convex.fromValues({ accessToken, deployKey
167
167
  ## State in Convex
168
168
 
169
169
  `state: Convex.state({ team })` keeps the Alchemy state of every stack and stage of a Convex team in
170
- one project of that team, `alchemy-state`, so a repository holds one secret and a stack can create
170
+ one project of that team, `samebase`, so a repository holds one secret and a stack can create
171
171
  and destroy its own project. [docs/design/convex-state.md](docs/design/convex-state.md) records the
172
172
  decisions and the measurements.
173
173
 
@@ -185,7 +185,7 @@ Every run needs the team token in `CONVEX_ACCESS_TOKEN`, or the Convex CLI login
185
185
  team access token names its team, so `Convex.state()` needs no `team` with one; a `team` slug that
186
186
  is set must be the slug of that team, checked against its projects, and a token of another team
187
187
  fails the run. The Convex CLI login needs the slug or the id. The first run of a team creates
188
- the project `alchemy-state` and pushes the store functions to its
188
+ the project `samebase` and pushes the store functions to its
189
189
  production deployment with the Convex CLI of the app; a later version of this package pushes a
190
190
  newer store when it finds an older one. A store that is newer than the package fails the run with
191
191
  both versions, so the repositories of a team upgrade the package together. Each run makes a
package/lib/index.d.ts CHANGED
@@ -457,9 +457,9 @@ export declare const withRunRecord: (output: unknown, record: RunRecord) => obje
457
457
  //#endregion
458
458
  //#region src/State.d.ts
459
459
  /** The name of the state project in each team. */
460
- export declare const STORE_PROJECT_NAME = "alchemy-state";
460
+ export declare const STORE_PROJECT_NAME = "samebase";
461
461
  /**
462
- * Alchemy state in the `alchemy-state` project of `team`, with the team token
462
+ * Alchemy state in the `samebase` project of `team`, with the team token
463
463
  * in CONVEX_ACCESS_TOKEN or the Convex CLI login. A team access token names
464
464
  * its team, so `team` is optional with one; the Convex CLI login needs the
465
465
  * slug or the id. The first use of the run finds or creates the project and
package/lib/index.js CHANGED
@@ -1545,7 +1545,7 @@ const withRunRecord = (output, record) => isPlainObject(output) ? "samebase.run"
1545
1545
  //#endregion
1546
1546
  //#region src/State.ts
1547
1547
  /** The name of the state project in each team. */
1548
- const STORE_PROJECT_NAME = "alchemy-state";
1548
+ const STORE_PROJECT_NAME = "samebase";
1549
1549
  /**
1550
1550
  * The actions of the key of one run: the internal queries and mutations of
1551
1551
  * the store, nothing else. Measured: `deployment:data:view` and
@@ -1715,7 +1715,7 @@ const createStoreProject = (api, teamId, team) => Effect.gen(function* () {
1715
1715
  return oldest;
1716
1716
  });
1717
1717
  /**
1718
- * The StateService over the `alchemy-state` project of the team: found or
1718
+ * The StateService over the `samebase` project of the team: found or
1719
1719
  * created, its store pushed when it is missing or older, and read and
1720
1720
  * written with the keys of this run.
1721
1721
  */
@@ -1723,12 +1723,12 @@ const makeConvexState = (options) => Effect.gen(function* () {
1723
1723
  const { api } = options;
1724
1724
  const teamId = yield* api.resolveTeamId(options.team);
1725
1725
  const team = options.team ?? teamId;
1726
- const project = (yield* findProjectByName(api, teamId, "alchemy-state")) ?? (yield* createStoreProject(api, teamId, team));
1726
+ const project = (yield* findProjectByName(api, teamId, "samebase")) ?? (yield* createStoreProject(api, teamId, team));
1727
1727
  const deployment = yield* prodDeploymentOf(api, project.id);
1728
1728
  if (deployment === void 0) return yield* new ProductionDeploymentNotFound({ projectId: project.id });
1729
1729
  const keys = [];
1730
1730
  yield* Scope.addFinalizer(options.scope, Effect.suspend(() => Effect.forEach(keys, (key) => deleteDeployKey(api, deployment.name, key), { discard: true })));
1731
- const mint = createDeployKey(api, deployment.name, "alchemy-state", RUN_KEY_ACTIONS).pipe(Effect.map((key) => {
1731
+ const mint = createDeployKey(api, deployment.name, STORE_PROJECT_NAME, RUN_KEY_ACTIONS).pipe(Effect.map((key) => {
1732
1732
  keys.push(key);
1733
1733
  return makeFunctionApi(deployment.deploymentUrl, key);
1734
1734
  }), Effect.mapError((error) => failure(`no key for ${deployment.name}: ${error.message}`)));
@@ -1787,7 +1787,7 @@ const makeConvexState = (options) => Effect.gen(function* () {
1787
1787
  };
1788
1788
  });
1789
1789
  /**
1790
- * Alchemy state in the `alchemy-state` project of `team`, with the team token
1790
+ * Alchemy state in the `samebase` project of `team`, with the team token
1791
1791
  * in CONVEX_ACCESS_TOKEN or the Convex CLI login. A team access token names
1792
1792
  * its team, so `team` is optional with one; the Convex CLI login needs the
1793
1793
  * slug or the id. The first use of the run finds or creates the project and
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["valueOf","DeploymentRow","DeploymentRows"],"sources":["../src/Component.ts","../src/Credentials.ts","../src/Adoption.ts","../src/ManagementApi.ts","../src/Push.ts","../src/Deployment.ts","../src/Project.ts","../src/Providers.ts","../src/RunRecord.ts","../src/State.ts"],"sourcesContent":["import { toPath } from \"alchemy/FQN\";\nimport type { NamespaceNode } from \"alchemy/Namespace\";\nimport { Stack } from \"alchemy/Stack\";\nimport * as Effect from \"effect/Effect\";\nimport * as Schema from \"effect/Schema\";\nimport type { Deployment } from \"./Deployment.ts\";\n\n/** A component's resources occupy this namespace in the deployment's Alchemy stack and stage. */\nexport interface ComponentBinding {\n readonly type: \"component\";\n readonly path: string;\n readonly namespace: readonly string[];\n}\n\n/**\n * Associate a native namespace with an installed component. `component` is the\n * installed name from the app's `convex.config.ts`; a nested install joins the\n * names with slashes, such as `\"workspace/mail\"`. An undefined namespace\n * associates the stack root. This records display metadata; it does not install\n * the component, set its environment, or change removal policies.\n */\nexport const bindComponent = (options: {\n deployment: Deployment;\n component: string;\n namespace: NamespaceNode | undefined;\n}) =>\n Effect.gen(function* () {\n if (options.component === \"\") {\n return yield* Effect.die(new Error(\"The component name is empty.\"));\n }\n const namespace = toPath(options.namespace);\n const sid = `convex.component:${JSON.stringify(namespace)}`;\n const stack = yield* Stack;\n const previous = stack.bindings[options.deployment.FQN]?.find((binding) => binding.sid === sid);\n // Alchemy keeps the last binding with a given sid. Reject conflicting owners before that happens.\n if (previous !== undefined) {\n const existing = Schema.decodeUnknownSync(Schema.Struct({ path: Schema.String }))(\n previous.data,\n );\n if (existing.path !== options.component) {\n return yield* Effect.die(\n new Error(\n `Alchemy namespace ${JSON.stringify(namespace)} is already bound to ${existing.path}.`,\n ),\n );\n }\n return;\n }\n yield* options.deployment.bind(sid, {\n type: \"component\",\n path: options.component,\n namespace,\n });\n });\n","// Convex credentials for the provider, by scope.\n//\n// - The access token works on the Management API: a team access token, an\n// OAuth token, or the Convex CLI login. Convex.Project needs it. A\n// Convex.Deployment needs it only when the deploy key does not fit.\n// - The deploy key is optional. A deploy key of one deployment\n// (`prod:<name>|...`, `dev:<name>|...`) lets Convex.Deployment set\n// variables and push to that deployment with no access token. A preview\n// deploy key of a project (`preview:<team>:<project>|...`) lets it create,\n// push to, and delete preview deployments of that project with no access\n// token.\n//\n// Credentials are a layer, never props: they do not go into Alchemy state.\n// Both values are Effects, so that building the providers layer never touches\n// the environment or the filesystem. A value is read on the first call that\n// needs it, which keeps `alchemy plan` on an unrelated stack free of Convex\n// credential errors.\nimport { readFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport * as Config from \"effect/Config\";\nimport * as Context from \"effect/Context\";\nimport * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\nimport * as Option from \"effect/Option\";\nimport * as Redacted from \"effect/Redacted\";\nimport * as Result from \"effect/Result\";\nimport * as Schema from \"effect/Schema\";\n\nexport interface ResolvedCredentials {\n /** Bearer token accepted by https://api.convex.dev/v1: a team access token, an OAuth token, or the Convex CLI login. */\n readonly accessToken: Redacted.Redacted<string>;\n /** Where the token came from, for error messages only. */\n readonly source: \"env\" | \"explicit\" | \"convex-cli-login\";\n}\n\nexport interface CredentialsService {\n /** The Management API token. Dies when there is none. */\n readonly accessToken: Effect.Effect<ResolvedCredentials>;\n /** True when there is a Management API token. */\n readonly hasAccessToken: Effect.Effect<boolean>;\n /** A deploy key or a preview deploy key, or undefined. */\n readonly deployKey: Effect.Effect<Redacted.Redacted<string> | undefined>;\n}\n\nexport class Credentials extends Context.Service<Credentials, CredentialsService>()(\n \"@samebase/alchemy-convex/Credentials\",\n) {}\n\n/** Environment variable for the access token, read by {@link fromConfig}. */\nexport const ACCESS_TOKEN_ENV = \"CONVEX_ACCESS_TOKEN\";\n\n/** Environment variable for the deploy key, read by {@link fromConfig}. The Convex CLI reads the same name. */\nexport const DEPLOY_KEY_ENV = \"CONVEX_DEPLOY_KEY\";\n\n/** The Convex CLI stores its device login here after `npx convex login`. */\nexport const convexCliConfigPath = () => join(homedir(), \".convex\", \"config.json\");\n\nconst CliConfig = Schema.Struct({ accessToken: Schema.String });\n\nexport class CredentialsError extends Schema.TaggedError<CredentialsError>()(\"CredentialsError\", {\n reason: Schema.String,\n}) {}\n\n/**\n * Token the Convex CLI saved on this machine. It works on the Management API\n * for the teams the logged-in user belongs to. Fails when nobody is logged in.\n */\nexport const readConvexCliLogin: Effect.Effect<ResolvedCredentials, CredentialsError> = Effect.gen(\n function* () {\n const path = convexCliConfigPath();\n const text = yield* Effect.tryPromise({\n try: () => readFile(path, \"utf8\"),\n catch: () =>\n new CredentialsError({\n reason: `This step needs the Convex Management API. Set ${ACCESS_TOKEN_ENV} to a team access token, or run \\`npx convex login\\`. There is no Convex CLI login at ${path}.`,\n }),\n });\n const parsed = yield* Schema.decodeUnknownEffect(Schema.fromJsonString(CliConfig))(text).pipe(\n Effect.mapError(() => new CredentialsError({ reason: `${path} has no accessToken` })),\n );\n return { accessToken: Redacted.make(parsed.accessToken), source: \"convex-cli-login\" } as const;\n },\n);\n\n/**\n * Default resolution through the stack ConfigProvider (process env, `.env`,\n * stack secrets): `CONVEX_ACCESS_TOKEN`, then the Convex CLI login on this\n * machine, for the access token; `CONVEX_DEPLOY_KEY` for the deploy key. A\n * developer who ran `npx convex login` needs nothing. CI sets only the\n * deploy key when the stack pushes to deployments that exist, and the access\n * token when the stack also creates projects or deployments.\n */\nexport const fromConfig = (): Layer.Layer<Credentials> =>\n Layer.effect(\n Credentials,\n Effect.gen(function* () {\n const resolved = yield* Effect.cached(\n Config.Redacted(ACCESS_TOKEN_ENV).pipe(\n Effect.map((token): ResolvedCredentials => ({ accessToken: token, source: \"env\" })),\n Effect.catch(() => readConvexCliLogin),\n Effect.result,\n ),\n );\n const deployKey = yield* Effect.cached(\n Config.option(Config.Redacted(DEPLOY_KEY_ENV)).pipe(\n Effect.map(Option.getOrUndefined),\n Effect.orDie,\n ),\n );\n return {\n accessToken: resolved.pipe(Effect.flatMap(Effect.fromResult), Effect.orDie),\n hasAccessToken: resolved.pipe(Effect.map(Result.isSuccess)),\n deployKey,\n };\n }),\n );\n\n/** Explicit values, for tests or callers that already hold them. */\nexport const fromValues = (values: {\n readonly accessToken?: Redacted.Redacted<string>;\n readonly deployKey?: Redacted.Redacted<string>;\n}): Layer.Layer<Credentials> =>\n Layer.succeed(Credentials, {\n accessToken:\n values.accessToken === undefined\n ? Effect.die(\n new CredentialsError({\n reason:\n \"This step needs the Convex Management API, and fromValues got no accessToken.\",\n }),\n )\n : Effect.succeed({ accessToken: values.accessToken, source: \"explicit\" } as const),\n hasAccessToken: Effect.succeed(values.accessToken !== undefined),\n deployKey: Effect.succeed(values.deployKey),\n });\n","// Adoption check for reconcile.\n//\n// The engine checks ownership during plan: `read` returns `Unowned(...)` for\n// an object that is not in state, and the engine then needs `--adopt`. A\n// reconcile without state can still find an existing object, for example\n// after a replacement, after an interrupted create, or when another run\n// created it between plan and apply. Reconcile takes that object over only\n// when adoption is on. The order is the same as in the engine: the\n// resource's own `adopt(...)`, then the AdoptPolicy service, then the\n// `--adopt` flag in AlchemyContext.\n//\n// Pattern from Confect, `packages/alchemy/src/internal/Lifecycle.ts`\n// (https://github.com/rjdellecese/confect, ISC license).\nimport { AdoptPolicy } from \"alchemy/AdoptPolicy\";\nimport { AlchemyContext } from \"alchemy/AlchemyContext\";\nimport { Stack } from \"alchemy/Stack\";\nimport * as Effect from \"effect/Effect\";\nimport * as Option from \"effect/Option\";\n\n/** True when the resource `fqn` may take over an object that is not in state. */\nexport const shouldAdopt = (fqn: string): Effect.Effect<boolean> =>\n Effect.gen(function* () {\n const stack = yield* Effect.serviceOption(Stack);\n const own = Option.isSome(stack) ? stack.value.resources[fqn]?.Adopt : undefined;\n if (own !== undefined) return own;\n const policy = yield* Effect.serviceOption(AdoptPolicy);\n if (Option.isSome(policy)) return policy.value;\n const context = yield* Effect.serviceOption(AlchemyContext);\n return Option.isSome(context) && context.value.adopt;\n });\n","// Effect wrapper around the official Convex platform client.\n//\n// `@convex-dev/platform` is an openapi-fetch client: every call resolves to\n// `{ data, error, response }`. This service turns that into an Effect with one\n// typed error, resolves credentials lazily, and validates the fields the\n// provider relies on at runtime.\nimport { createDeploymentClient, createManagementClient } from \"@convex-dev/platform\";\nimport * as Context from \"effect/Context\";\nimport * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\nimport * as Redacted from \"effect/Redacted\";\nimport * as Schedule from \"effect/Schedule\";\nimport * as Schema from \"effect/Schema\";\nimport { Credentials, type ResolvedCredentials } from \"./Credentials.ts\";\n\nexport type ManagementClient = ReturnType<typeof createManagementClient>;\nexport type DeploymentClient = ReturnType<typeof createDeploymentClient>;\n\n/** Shape of every openapi-fetch result we consume. */\nexport interface FetchResult<T> {\n readonly data?: T;\n readonly error?: unknown;\n readonly response: Response;\n}\n\n/**\n * One error for every control-plane and deployment call. Resources branch on\n * `status` (404 means absent for read and delete), so the class is load\n * bearing, not decorative.\n */\nexport class ConvexApiError extends Schema.TaggedError<ConvexApiError>()(\"ConvexApiError\", {\n operation: Schema.String,\n status: Schema.Number,\n code: Schema.optionalKey(Schema.String),\n message: Schema.String,\n}) {}\n\nconst ErrorBody = Schema.Struct({\n code: Schema.optionalKey(Schema.String),\n message: Schema.optionalKey(Schema.String),\n});\n\nconst toApiError = (operation: string, result: FetchResult<unknown>) => {\n const body = Schema.decodeUnknownSync(Schema.NullishOr(ErrorBody))(result.error ?? null);\n const code = body?.code;\n return new ConvexApiError({\n operation,\n status: result.response.status,\n ...(code === undefined ? {} : { code }),\n message: body?.message ?? `${operation} failed with HTTP ${result.response.status}`,\n });\n};\n\nexport interface ManagementApiService {\n /** Run one management call with the resolved credentials. */\n readonly request: <T>(\n operation: string,\n run: (client: ManagementClient) => Promise<FetchResult<T>>,\n ) => Effect.Effect<T, ConvexApiError>;\n /** Run one management call whose success response has no body. */\n readonly requestVoid: (\n operation: string,\n run: (client: ManagementClient) => Promise<FetchResult<unknown>>,\n ) => Effect.Effect<void, ConvexApiError>;\n /** Run one deployment-scoped call authenticated with a deploy key. */\n readonly deploymentRequest: <T>(\n operation: string,\n deploymentUrlOrName: string,\n deployKey: Redacted.Redacted<string>,\n run: (client: DeploymentClient) => Promise<FetchResult<T>>,\n ) => Effect.Effect<T, ConvexApiError>;\n /**\n * Team id for a numeric id, a slug, or nothing. A team access token names\n * its team (`GET /token_details`); a slug is then checked against the\n * `teamSlug` of the team's projects, so a token of another team fails. The\n * Convex CLI login and a personal token answer 403 there, so a slug goes to\n * the dashboard's team list, and nothing is an error.\n */\n readonly resolveTeamId: (\n team: string | number | undefined,\n ) => Effect.Effect<number, ConvexApiError>;\n /**\n * True when a deploy key that Convex returned carries the token of the\n * Management API credential itself. With an OAuth token, create_deploy_key\n * and create_preview_deploy_key create no new key: they return the OAuth\n * token with a new prefix, and the part after \"|\" is the same. A delete of\n * that key would revoke the credential.\n */\n readonly isCredentialToken: (secret: string) => Effect.Effect<boolean>;\n /**\n * The same calls with another bearer token, such as a preview deploy key,\n * which the Management API takes for the preview deployments of its project.\n */\n readonly withToken: (token: Redacted.Redacted<string>) => ManagementApiService;\n}\n\n/** The part of a Convex token after the first \"|\", or the whole value when it has none. */\nconst tokenPart = (value: string) => value.slice(value.indexOf(\"|\") + 1);\n\nexport class ManagementApi extends Context.Service<ManagementApi, ManagementApiService>()(\n \"@samebase/alchemy-convex/ManagementApi\",\n) {}\n\nconst attempt = <T>(operation: string, run: () => Promise<FetchResult<T>>) =>\n Effect.tryPromise({\n try: run,\n catch: (cause) =>\n new ConvexApiError({\n operation,\n status: 0,\n message: cause instanceof Error ? cause.message : String(cause),\n }),\n });\n\n/** Reads `data` or fails with the HTTP status and the API's own code and message. */\nexport const settle = <T>(\n operation: string,\n run: () => Promise<FetchResult<T>>,\n): Effect.Effect<T, ConvexApiError> =>\n attempt(operation, run).pipe(\n Effect.flatMap((result) =>\n result.response.ok && result.data !== undefined\n ? Effect.succeed(result.data)\n : Effect.fail(toApiError(operation, result)),\n ),\n );\n\n/** For endpoints that answer with an empty body, such as delete calls. */\nexport const settleVoid = (\n operation: string,\n run: () => Promise<FetchResult<unknown>>,\n): Effect.Effect<void, ConvexApiError> =>\n attempt(operation, run).pipe(\n Effect.flatMap((result) =>\n result.response.ok ? Effect.void : Effect.fail(toApiError(operation, result)),\n ),\n );\n\n/**\n * True when an idempotent write can succeed on a new attempt:\n *\n * - A Convex write conflict. Two parallel update_environment_variables calls\n * on one deployment gave HTTP 503 `OptimisticConcurrencyControlFailure`,\n * \"Data read or written in this mutation changed while it was being run\",\n * in a live run. The platform codes `OCC` and `WriteConflict` and the\n * message \"... changed while this mutation was being run ...\" mean the same.\n * - Any other 5xx answer. Two parallel delete_preview_deploy_key calls on one\n * project gave HTTP 500 `InternalServerError`, \"Your request couldn't be\n * completed. Try again later.\", in a live run. The next attempt succeeded.\n */\nexport const isRetryableWriteError = (error: ConvexApiError): boolean =>\n error.code === \"OptimisticConcurrencyControlFailure\" ||\n error.code === \"OCC\" ||\n error.code === \"WriteConflict\" ||\n /changed while (it|this mutation) was being run/.test(error.message) ||\n error.status >= 500;\n\n/**\n * Runs an idempotent write again after a retryable Convex error: at most\n * four more attempts, with exponential backoff from 100 ms and jitter. Other\n * errors fail at once, and so does the last retryable error. Use it only for\n * a write that has the same result when it runs twice, such as setting a\n * value or deleting by id. Never for a create that does not check first.\n */\nexport const retryIdempotentWrite = <A, E, R>(\n effect: Effect.Effect<A, E, R>,\n): Effect.Effect<A, E, R> =>\n effect.pipe(\n Effect.retry({\n while: (error: E) => error instanceof ConvexApiError && isRetryableWriteError(error),\n times: 4,\n schedule: Schedule.exponential(\"100 millis\").pipe(Schedule.jittered),\n }),\n );\n\n/** Turns a 404 into `undefined` so read and delete stay idempotent. */\nexport const absentAsUndefined = <A, R>(\n effect: Effect.Effect<A, ConvexApiError, R>,\n): Effect.Effect<A | undefined, ConvexApiError, R> =>\n effect.pipe(\n Effect.catchIf(\n (error) => error.status === 404,\n () => Effect.succeed(undefined),\n ),\n );\n\nconst TeamRow = Schema.Struct({ id: Schema.Number, slug: Schema.String });\nconst TeamRows = Schema.Array(TeamRow);\n\n/** The first page of GET /teams/{team_id}/projects: every row carries the slug of the team. */\nconst ProjectSlugRows = Schema.Struct({\n items: Schema.Array(Schema.Struct({ teamSlug: Schema.String })),\n});\n\n/** GET /token_details: the team of a team token, or the project of a project token. */\nconst TokenDetails = Schema.Union([\n Schema.Struct({ type: Schema.Literal(\"teamToken\"), teamId: Schema.Number }),\n Schema.Struct({ type: Schema.Literal(\"projectToken\"), projectId: Schema.Number }),\n]);\n\n/** The service for one way to get the bearer token. */\nconst makeService = (credentials: Effect.Effect<ResolvedCredentials>): ManagementApiService => {\n const client = Effect.cached(\n credentials.pipe(\n Effect.map((resolved) => createManagementClient(Redacted.value(resolved.accessToken))),\n ),\n ).pipe(Effect.flatten);\n\n const request: ManagementApiService[\"request\"] = (operation, run) =>\n client.pipe(Effect.flatMap((c) => settle(operation, () => run(c))));\n\n const requestVoid: ManagementApiService[\"requestVoid\"] = (operation, run) =>\n client.pipe(Effect.flatMap((c) => settleVoid(operation, () => run(c))));\n\n const deploymentRequest: ManagementApiService[\"deploymentRequest\"] = (\n operation,\n deploymentUrlOrName,\n deployKey,\n run,\n ) =>\n settle(operation, () =>\n run(createDeploymentClient(deploymentUrlOrName, Redacted.value(deployKey))),\n );\n\n // Measured: a team access token answers `GET /token_details` with its\n // team id and gets HTTP 403 from the dashboard's team list; the Convex CLI\n // login answers the team list and gets HTTP 403 `NotOAuthTeamToken` from\n // token_details. Read once for each service.\n // `Effect.cached` only allocates the cache, so runSync makes one for this service.\n const tokenDetails = Effect.runSync(\n Effect.cached(\n request(\"get token details\", (c) => c.GET(\"/token_details\")).pipe(\n Effect.map((body) => Schema.decodeUnknownSync(TokenDetails)(body)),\n Effect.catchIf(\n (error) => error.status === 403,\n () => Effect.succeed(undefined),\n ),\n ),\n ),\n );\n\n /** The slug of the team, from the first project of its listing, or undefined for a team without one. Read once. */\n const teamSlug = (teamId: number) =>\n request(\"list projects\", (c) =>\n c.GET(\"/teams/{team_id}/projects\", { params: { path: { team_id: teamId } } }),\n ).pipe(\n Effect.map((body) => Schema.decodeUnknownSync(ProjectSlugRows)(body).items[0]?.teamSlug),\n );\n\n // The Management API addresses teams by numeric id. The only slug lookup\n // it offers is per project, so a slug falls back to the dashboard's team\n // list, which is unofficial. Pass the numeric team id to skip this.\n const resolveTeamId: ManagementApiService[\"resolveTeamId\"] = (team) =>\n Effect.gen(function* () {\n if (typeof team === \"number\") return team;\n if (team !== undefined && /^\\d+$/.test(team)) return Number(team);\n const details = yield* tokenDetails;\n if (details?.type === \"teamToken\") {\n if (team === undefined) return details.teamId;\n // The Management API has no team-by-id call, so the slug of the\n // team comes from any of its projects. A team without a project\n // cannot be checked: the numeric id, or no team, is the fix.\n const slug = yield* teamSlug(details.teamId);\n if (slug === undefined) {\n return yield* new ConvexApiError({\n operation: \"resolve team\",\n status: 0,\n message: `team \"${team}\" cannot be checked against the access token: team ${details.teamId} has no project yet. Set team to ${details.teamId}, or leave it out.`,\n });\n }\n if (slug !== team) {\n return yield* new ConvexApiError({\n operation: \"resolve team\",\n status: 403,\n message: `the access token belongs to team ${details.teamId} (\"${slug}\"), and team is \"${team}\". Use a token of \"${team}\", or set team to ${details.teamId}.`,\n });\n }\n return details.teamId;\n }\n if (details?.type === \"projectToken\") {\n return yield* new ConvexApiError({\n operation: \"resolve team\",\n status: 403,\n message: `the access token belongs to project ${details.projectId}, and a project token cannot create projects. Use a team access token.`,\n });\n }\n if (team === undefined) {\n return yield* new ConvexApiError({\n operation: \"resolve team\",\n status: 0,\n message:\n \"set team to the slug or the id of the Convex team: this access token does not name a team.\",\n });\n }\n const resolved = yield* credentials;\n const rows = yield* Effect.tryPromise({\n try: async () => {\n const response = await fetch(\"https://api.convex.dev/api/dashboard/teams\", {\n headers: { Authorization: `Bearer ${Redacted.value(resolved.accessToken)}` },\n });\n if (!response.ok) {\n throw new Error(`team lookup for \"${team}\" failed with HTTP ${response.status}`);\n }\n return Schema.decodeUnknownSync(TeamRows)(await response.json());\n },\n catch: (cause) =>\n new ConvexApiError({\n operation: \"resolve team\",\n status: 0,\n message: cause instanceof Error ? cause.message : String(cause),\n }),\n });\n const match = rows.find((row) => row.slug === team);\n if (match === undefined) {\n return yield* new ConvexApiError({\n operation: \"resolve team\",\n status: 404,\n message: `no team with slug \"${team}\" for this token`,\n });\n }\n return match.id;\n });\n\n const isCredentialToken: ManagementApiService[\"isCredentialToken\"] = (secret) =>\n credentials.pipe(\n Effect.map(\n (resolved) => tokenPart(Redacted.value(resolved.accessToken)) === tokenPart(secret),\n ),\n );\n\n const withToken: ManagementApiService[\"withToken\"] = (token) =>\n makeService(Effect.succeed({ accessToken: token, source: \"explicit\" }));\n\n return {\n request,\n requestVoid,\n deploymentRequest,\n resolveTeamId,\n isCredentialToken,\n withToken,\n };\n};\n\nexport const ManagementApiLive = (): Layer.Layer<ManagementApi, never, Credentials> =>\n Layer.effect(\n ManagementApi,\n Effect.gen(function* () {\n const credentials = yield* Credentials;\n return makeService(credentials.accessToken);\n }),\n );\n","// The push of a Convex.Deployment: a short-lived deploy key, the `env`\n// variables, and `convex deploy` with the Convex CLI that the app installed.\n//\n// - The key is created for one push with the Management API credential and\n// deleted after it, also after a failure. It can only deploy and read and\n// write variables (with a push command: every action), and it expires\n// after PUSH_KEY_LIFETIME_MS, so a run that stops before the delete leaves\n// no key that works for long. No key\n// goes into state, into an output, or to another resource.\n// - With an OAuth token as the credential, Convex creates no new key: it\n// returns the OAuth token with a new prefix. The push uses it, and the\n// delete is skipped, because it would revoke the OAuth token.\n// - The key reaches the CLI only through an env file (`--env-file`) with\n// mode 0600 in a new temporary directory. The directory is removed after\n// the run, on success, on failure, and on interruption. It is also the home\n// directory of the CLI, so the CLI cannot read the Convex login of this\n// machine. Variables named `CONVEX_*` are not passed on to the CLI.\n// - The CLI output stays out of the logs. A failure shows its last lines with\n// the key removed.\n//\n// The CLI runner follows Confect `packages/alchemy/src/internal/CommandRunner.ts`\n// (https://github.com/rjdellecese/confect, ISC license, see NOTICE).\nimport { createHash } from \"node:crypto\";\nimport { access, mkdtemp, readFile, rm, writeFile } from \"node:fs/promises\";\nimport { createRequire } from \"node:module\";\nimport { tmpdir } from \"node:os\";\nimport { dirname, join, relative, resolve } from \"node:path\";\nimport { stripVTControlCharacters } from \"node:util\";\nimport { createDeploymentClient } from \"@convex-dev/platform\";\nimport type { paths } from \"@convex-dev/platform/managementApi\";\nimport { hashDirectory } from \"alchemy/Command/Memo\";\nimport * as Clock from \"effect/Clock\";\nimport * as Effect from \"effect/Effect\";\nimport * as ChildProcess from \"effect/process/ChildProcess\";\nimport * as ChildProcessSpawner from \"effect/process/ChildProcessSpawner\";\nimport * as Redacted from \"effect/Redacted\";\nimport * as Schema from \"effect/Schema\";\nimport * as Stream from \"effect/Stream\";\nimport {\n absentAsUndefined,\n type ManagementApiService,\n retryIdempotentWrite,\n settle,\n settleVoid,\n} from \"./ManagementApi.ts\";\n\n/** A value of the `env` prop: a string, or a secret such as `Config.Redacted(\"AUTH_SECRET\")`. */\nexport type EnvValue = string | Redacted.Redacted<string>;\n\n/**\n * The `source` prop: the Convex functions directory relative to the app\n * directory (`rootDir`), such as `./convex`, or that directory with a push\n * command and more files for the content identity.\n */\nexport type Source =\n | string\n | {\n /** The Convex functions directory relative to the app directory, such as `./convex`. */\n readonly path: string;\n /**\n * Replaces `convex deploy`: a program and its arguments, run in the app\n * directory with CONVEX_DEPLOY_KEY in its environment, such as\n * `[\"pnpm\", \"exec\", \"convex-hosting\", \"deploy\", \"--build\", \"pnpm run build\", \"--dist\", \"dist\"]`.\n * It must push with `convex deploy`, such as through `--cmd`, so that\n * its output has the CLI's \"Deployed Convex functions to\" line.\n */\n readonly command?: readonly [string, ...string[]];\n /**\n * The files of the content identity, as globs relative to the app\n * directory, next to `path`, package.json, convex.json, and the\n * lockfile, such as the build inputs `[\"src/**\", \"vite.config.ts\"]`.\n * By default, every file of the app that git does not ignore.\n */\n readonly include?: readonly string[];\n };\n\nconst sourceOf = (source: Source) =>\n typeof source === \"string\"\n ? { path: source, command: undefined, include: undefined }\n : { path: source.path, command: source.command, include: source.include };\n\n/** Lifetime of a push key. Long enough for a slow push with index backfills. */\nexport const PUSH_KEY_LIFETIME_MS = 2 * 60 * 60 * 1000;\n\n/** An action of a deploy key, such as `deployment:deploy`, from the generated schema. */\nexport type DeployKeyAction = NonNullable<\n NonNullable<\n paths[\"/deployments/{deployment_name}/create_deploy_key\"][\"post\"][\"requestBody\"]\n >[\"content\"][\"application/json\"][\"allowedActions\"]\n>[number];\n\n/** The only actions a key for `convex deploy` gets. */\nexport const PUSH_KEY_ACTIONS = [\n \"deployment:deploy\",\n \"deployment:env:view\",\n \"deployment:env:write\",\n] as const satisfies readonly DeployKeyAction[];\n\n/** POST /deployments/{deployment_name}/create_deploy_key */\nconst CreatedDeployKey = Schema.Struct({ deployKey: Schema.String });\n\n/** GET https://<deployment>.convex.cloud/api/v1/list_environment_variables */\nconst EnvironmentVariableList = Schema.Struct({\n environmentVariables: Schema.Record(Schema.String, Schema.String),\n});\n\n/** No `convex` package resolves from the app directory. */\nexport class ConvexCliNotFound extends Schema.TaggedError<ConvexCliNotFound>()(\n \"ConvexCliNotFound\",\n { cwd: Schema.String },\n) {\n override get message() {\n return `Convex.Deployment found no installed convex package from ${this.cwd}, and it does not download one. Install convex in the app (npm install convex), or set rootDir to the directory of the app.`;\n }\n}\n\n/** The app directory (`rootDir`) has no package.json. */\nexport class ConvexAppNotFound extends Schema.TaggedError<ConvexAppNotFound>()(\n \"ConvexAppNotFound\",\n {\n /** The app directory, resolved against the working directory of the deploy. */\n rootDir: Schema.String,\n },\n) {\n override get message() {\n return `Convex.Deployment found no package.json in ${this.rootDir}. Set rootDir to the directory of the Convex app, relative to the directory where the deploy runs, such as \"apps/web\".`;\n }\n}\n\n/** The Convex CLI failed, or exited 0 without the deployment URL. The output tail never contains the key. */\nexport class CodePushFailed extends Schema.TaggedError<CodePushFailed>()(\"CodePushFailed\", {\n /** Exit code of the CLI. Undefined when it did not start or a signal stopped it. */\n exitCode: Schema.UndefinedOr(Schema.Number),\n /** The last lines of the CLI output, with the deploy key removed. */\n outputTail: Schema.String,\n}) {\n override get message() {\n return this.exitCode === 0\n ? `convex deploy exited 0 but printed no \"Deployed Convex functions to <url>\" line. Last output, with the deploy key removed:\\n${this.outputTail}`\n : `convex deploy failed${this.exitCode === undefined ? \"\" : ` with exit code ${this.exitCode}`}. Last output, with the deploy key removed:\\n${this.outputTail}`;\n }\n}\n\n/** The CLI pushed to another deployment than the one of the resource. Checked after the push. */\nexport class PushTargetMismatch extends Schema.TaggedError<PushTargetMismatch>()(\n \"PushTargetMismatch\",\n { expected: Schema.String, actual: Schema.String },\n) {\n override get message() {\n return `The Convex CLI pushed the functions to deployment ${this.actual}, but Convex.Deployment expected ${this.expected}. Check that convex.json does not select another deployment.`;\n }\n}\n\n/** Variables in `env` exist on the deployment with other values, and adoption is off. */\nexport class VariablesOwnedBySomeoneElse extends Schema.TaggedError<VariablesOwnedBySomeoneElse>()(\n \"VariablesOwnedBySomeoneElse\",\n { deployment: Schema.String, names: Schema.Array(Schema.String) },\n) {\n override get message() {\n return `Environment variables ${this.names.join(\", \")} already exist on deployment ${this.deployment} with other values. Re-run with --adopt to take them over and overwrite them, or remove them from env.`;\n }\n}\n\n/** A preview deploy key cannot set variables: the deployment API takes only a deploy key of the deployment. */\nexport class EnvironmentNeedsDeployKey extends Schema.TaggedError<EnvironmentNeedsDeployKey>()(\n \"EnvironmentNeedsDeployKey\",\n { deployment: Schema.String },\n) {\n override get message() {\n return `Convex.Deployment cannot set or remove env variables on preview deployment ${this.deployment} with a preview deploy key: Convex lets that key create, push to, and delete preview deployments, but not change their variables. Set CONVEX_ACCESS_TOKEN for this stage, or set the values as project default environment variables for preview deployments in the Convex dashboard.`;\n }\n}\n\n/**\n * What a deploy key targets, from its prefix: `<type>:<deployment>|<secret>`\n * (or `<deployment>|<secret>` in old keys) for one deployment, and\n * `preview:<team>:<project>|<secret>` for the preview deployments of a\n * project. Same rules as convex 1.46 `cli/lib/deployment.js`.\n */\nexport const keyTargetOf = (\n key: string,\n):\n | { readonly kind: \"deployment\"; readonly deployment: string }\n | { readonly kind: \"preview\"; readonly team: string; readonly project: string }\n | { readonly kind: \"other\" } => {\n const bar = key.indexOf(\"|\");\n // A key in the env file must be one unquoted dotenv value.\n if (bar <= 0 || /[\\s#'\"`]/.test(key)) return { kind: \"other\" };\n const [first, second, third, ...rest] = key.slice(0, bar).split(\":\");\n if (rest.length > 0) return { kind: \"other\" };\n if (first === \"preview\" && second && third)\n return { kind: \"preview\", team: second, project: third };\n if (third !== undefined) return { kind: \"other\" };\n if (second) return { kind: \"deployment\", deployment: second };\n if (first && second === undefined) return { kind: \"deployment\", deployment: first };\n return { kind: \"other\" };\n};\n\n/**\n * The CLI prints this line with `logFinishedStep` after the push succeeds, to\n * stderr (convex 1.46 `cli/lib/deploy2.js`). The host is\n * `<deployment>.convex.cloud` or `<deployment>.<region>.convex.cloud`.\n */\nconst DEPLOYED_LINE =\n /Deployed Convex functions to (https:\\/\\/([a-z0-9]+(?:-[a-z0-9]+)*)(?:\\.[a-z0-9]+(?:-[a-z0-9]+)*)?\\.convex\\.cloud)\\/?(?=\\s|$)/m;\n\n/** Reads the deployment URL from `convex deploy` output. ANSI escape codes are removed first. */\nexport const parseDeployOutput = (\n text: string,\n): { url: string; deploymentName: string } | undefined => {\n const match = DEPLOYED_LINE.exec(stripVTControlCharacters(text));\n const url = match?.[1];\n const deploymentName = match?.[2];\n return url === undefined || deploymentName === undefined ? undefined : { url, deploymentName };\n};\n\n/** Number of output lines that a failure quotes. */\nconst OUTPUT_TAIL_LINES = 20;\n\n/** The last non-empty lines of `text`, without escape codes and with every secret replaced. */\nconst outputTail = (text: string, secrets: readonly string[]) =>\n secrets\n .reduce(\n (redacted, secret) => redacted.split(secret).join(\"[REDACTED]\"),\n stripVTControlCharacters(text),\n )\n .split(/\\r?\\n|\\r/)\n .filter((line) => line.trim() !== \"\")\n .slice(-OUTPUT_TAIL_LINES)\n .join(\"\\n\");\n\nconst valueOf = (value: EnvValue) => (Redacted.isRedacted(value) ? Redacted.value(value) : value);\n\n/**\n * The app directory: `rootDir` resolved against the working directory of the\n * deploy. It must have a package.json. There is no search above it.\n */\nconst appDirectoryOf = (rootDir: string) => {\n const directory = resolve(rootDir);\n return Effect.tryPromise({\n try: () => access(join(directory, \"package.json\")).then(() => directory),\n catch: () => new ConvexAppNotFound({ rootDir: directory }),\n });\n};\n\n/** `source` is not the functions directory that the Convex CLI pushes from the app directory. */\nexport class SourceMismatch extends Schema.TaggedError<SourceMismatch>()(\"SourceMismatch\", {\n /** The app directory, resolved. */\n rootDir: Schema.String,\n source: Schema.String,\n functions: Schema.String,\n}) {\n override get message() {\n return `Convex.Deployment source is ${this.source}, but the Convex CLI pushes ${this.functions} from the app directory ${this.rootDir} (the \"functions\" field of convex.json, or convex/ by default). Set rootDir to the directory of the Convex app, and source to its functions directory relative to rootDir, such as \"./convex\".`;\n }\n}\n\nconst ConvexJson = Schema.Struct({ functions: Schema.optionalKey(Schema.String) });\n\n/** Fails with {@link SourceMismatch} when `path` is not the functions directory of the app in `cwd`. */\nconst checkFunctionsDirectory = (cwd: string, path: string) =>\n Effect.gen(function* () {\n const text = yield* Effect.promise(() =>\n readFile(join(cwd, \"convex.json\"), \"utf8\").catch(() => undefined),\n );\n const configured =\n text === undefined\n ? undefined\n : Schema.decodeUnknownSync(Schema.fromJsonString(ConvexJson))(text).functions;\n const functions = resolve(cwd, configured ?? \"convex\");\n if (functions !== path) {\n return yield* new SourceMismatch({ rootDir: cwd, source: path, functions });\n }\n });\n\nconst CliManifest = Schema.Struct({\n bin: Schema.Union([Schema.String, Schema.Record(Schema.String, Schema.String)]),\n});\n\n/** `[node, <convex bin>]` for the `convex` package that `cwd` resolves. Never downloads. */\nexport const installedCli = (cwd: string) =>\n Effect.tryPromise({\n try: async (): Promise<readonly [string, ...string[]]> => {\n const manifestPath = createRequire(join(cwd, \"package.json\")).resolve(\"convex/package.json\");\n const { bin } = Schema.decodeUnknownSync(Schema.fromJsonString(CliManifest))(\n await readFile(manifestPath, \"utf8\"),\n );\n const entry = typeof bin === \"string\" ? bin : bin[\"convex\"];\n if (entry === undefined) throw new Error(\"the convex package has no convex bin\");\n return [process.execPath, resolve(dirname(manifestPath), entry)];\n },\n catch: () => new ConvexCliNotFound({ cwd }),\n });\n\n/**\n * The content identity of a push: the files of the app directory that git\n * does not ignore (or `path`, the manifests, and the `include` globs), the\n * nearest lockfile, the target deployment, and the `env` names and values.\n * A change in a workspace package outside the app directory is not seen.\n */\nexport const pushHash = (options: {\n /** The app directory, relative to the working directory of the deploy or absolute. */\n readonly rootDir: string;\n readonly source: Source | undefined;\n readonly deployment: string;\n readonly env: Readonly<Record<string, EnvValue>>;\n}) =>\n Effect.gen(function* () {\n const source = options.source === undefined ? undefined : sourceOf(options.source);\n const files =\n source === undefined\n ? undefined\n : yield* appDirectoryOf(options.rootDir).pipe(\n Effect.flatMap((cwd) => {\n const functions = relative(cwd, resolve(cwd, source.path)).split(\"\\\\\").join(\"/\");\n return hashDirectory({\n cwd,\n // By default every file of the app that git does not ignore,\n // such as a module outside `source` that a function imports,\n // and the functions when convex.json puts them outside\n // rootDir. `include` narrows it to the functions, the\n // manifests, and the listed globs.\n memo:\n source.include !== undefined\n ? {\n include: [\n `${functions}/**`,\n \"package.json\",\n \"convex.json\",\n ...source.include,\n ],\n lockfile: true,\n }\n : functions === \"..\" || functions.startsWith(\"../\")\n ? { include: [\"**/*\", `${functions}/**`], lockfile: true }\n : {},\n });\n }),\n );\n const env = Object.entries(options.env)\n .map(([name, value]): readonly [string, string] => [name, valueOf(value)])\n .sort(([a], [b]) => (a < b ? -1 : 1));\n return createHash(\"sha256\")\n .update(JSON.stringify({ files, deployment: options.deployment, env }))\n .digest(\"hex\");\n });\n\n/**\n * Runs `use` with an env file that holds the key, in a new temporary\n * directory, and removes the directory afterwards: on success, on failure,\n * and on interruption.\n */\nconst withKeyFile = <A, E, R>(\n key: string,\n use: (paths: { readonly envFile: string; readonly home: string }) => Effect.Effect<A, E, R>,\n) =>\n Effect.acquireUseRelease(\n Effect.promise(() => mkdtemp(join(tmpdir(), \"alchemy-convex-\"))),\n (home) =>\n Effect.promise(() =>\n writeFile(join(home, \"deploy.env\"), `CONVEX_DEPLOY_KEY=${key}\\n`, { mode: 0o600 }),\n ).pipe(Effect.andThen(use({ envFile: join(home, \"deploy.env\"), home }))),\n (home) => Effect.promise(() => rm(home, { recursive: true, force: true })),\n );\n\n/** This process's variables without `CONVEX_*`, with `home` as the home directory. */\nconst cliEnvironment = (home: string): Record<string, string | undefined> => ({\n ...Object.fromEntries(\n Object.entries(process.env).filter(([name]) => !name.toUpperCase().startsWith(\"CONVEX_\")),\n ),\n HOME: home,\n USERPROFILE: home,\n XDG_CONFIG_HOME: home,\n});\n\n/**\n * A deploy key of `deployment` that expires after PUSH_KEY_LIFETIME_MS, with\n * only `allowedActions`, or every action when that is undefined. Delete it\n * with {@link deleteDeployKey} when the work is done.\n */\nexport const createDeployKey = (\n api: ManagementApiService,\n deployment: string,\n name: string,\n allowedActions: readonly DeployKeyAction[] | undefined,\n) =>\n Effect.gen(function* () {\n const now = yield* Clock.currentTimeMillis;\n const created = yield* api.request(\"create deploy key\", (client) =>\n client.POST(\"/deployments/{deployment_name}/create_deploy_key\", {\n params: { path: { deployment_name: deployment } },\n body: {\n name,\n ...(allowedActions === undefined ? {} : { allowedActions: [...allowedActions] }),\n expiresAt: now + PUSH_KEY_LIFETIME_MS,\n },\n }),\n );\n return Redacted.make(Schema.decodeUnknownSync(CreatedDeployKey)(created).deployKey);\n });\n\n/**\n * Deletes a key that {@link createDeployKey} made. The delete is skipped for\n * a key that is the OAuth credential. A failed delete is logged: the key\n * expires anyway.\n */\nexport const deleteDeployKey = (\n api: ManagementApiService,\n deployment: string,\n key: Redacted.Redacted<string>,\n) =>\n Effect.gen(function* () {\n if (yield* api.isCredentialToken(Redacted.value(key))) return;\n yield* absentAsUndefined(\n retryIdempotentWrite(\n api.requestVoid(\"delete deploy key\", (client) =>\n client.POST(\"/deployments/{deployment_name}/delete_deploy_key\", {\n params: { path: { deployment_name: deployment } },\n body: { id: Redacted.value(key) },\n }),\n ),\n ),\n );\n }).pipe(\n Effect.catch((error) =>\n Effect.logWarning(\n `Convex.Deployment could not delete its key on ${deployment} (${error.message}). The key expires on its own within ${PUSH_KEY_LIFETIME_MS / 60_000} minutes.`,\n ),\n ),\n );\n\n/**\n * Creates a deploy key for one push, runs `use` with it, and deletes it\n * afterwards, also after a failure. `allowedActions` is PUSH_KEY_ACTIONS for\n * `convex deploy`, or undefined for a push command, which can do more than a\n * push, such as the uploads of convex-hosting through `convex run`.\n */\nexport const withPushKey = <A, E, R>(\n api: ManagementApiService,\n deployment: string,\n allowedActions: readonly DeployKeyAction[] | undefined,\n use: (key: Redacted.Redacted<string>) => Effect.Effect<A, E, R>,\n) =>\n Effect.acquireUseRelease(\n createDeployKey(api, deployment, \"alchemy-push\", allowedActions),\n use,\n (key) => deleteDeployKey(api, deployment, key),\n );\n\n/** Every variable of the deployment with its value. */\nconst listVariables = (url: string, key: Redacted.Redacted<string>) =>\n settle(\"list environment variables\", () =>\n createDeploymentClient(url, Redacted.value(key)).GET(\"/list_environment_variables\"),\n ).pipe(\n Effect.map(\n (body) => Schema.decodeUnknownSync(EnvironmentVariableList)(body).environmentVariables,\n ),\n );\n\n/** One call that sets variables, or removes those whose value is null. */\nconst writeVariables = (\n url: string,\n key: Redacted.Redacted<string>,\n changes: ReadonlyArray<{ readonly name: string; readonly value: string | null }>,\n) =>\n settleVoid(\"update environment variables\", () =>\n createDeploymentClient(url, Redacted.value(key)).POST(\"/update_environment_variables\", {\n body: { changes: changes.map(({ name, value }) => ({ name, value })) },\n }),\n );\n\nexport interface PushOptions {\n /** Deployment name, such as `happy-animal-123`. */\n readonly deployment: string;\n /** Client URL of the deployment. */\n readonly url: string;\n /** The app directory, relative to the working directory of the deploy or absolute. The push runs in it. */\n readonly rootDir: string;\n /** The functions directory relative to `rootDir`, or it with a push command. Without it, only the variables change. */\n readonly source: Source | undefined;\n readonly env: Readonly<Record<string, EnvValue>>;\n /** Names that an earlier push set on this deployment. Names that left `env` are removed. */\n readonly previousEnvNames: readonly string[];\n /** True when the resource may overwrite variables that it did not set. */\n readonly adopt: boolean;\n /**\n * The preview name for `convex deploy --preview-name`, when `key` is a\n * preview deploy key. Such a key cannot set variables.\n */\n readonly previewName: string | undefined;\n}\n\n/**\n * The app directory and the program of a push. Fails before any change when\n * `rootDir` has no package.json, when `source` is not the functions directory\n * of the app, or when the app has no installed Convex CLI and no push command.\n */\nexport const checkSource = (rootDir: string, input: Source) =>\n Effect.gen(function* () {\n const source = sourceOf(input);\n const cwd = yield* appDirectoryOf(rootDir);\n yield* checkFunctionsDirectory(cwd, resolve(cwd, source.path));\n const program = source.command ?? (yield* installedCli(cwd));\n return { cwd, program };\n });\n\n/**\n * Sets the `env` variables and pushes the functions of `source` to one\n * deployment with `key`: a deploy key of the deployment, or a preview deploy\n * key of its project with `previewName`. Returns the URL that the CLI\n * printed, or undefined without `source`.\n */\nexport const push = (\n spawner: ChildProcessSpawner.ChildProcessSpawner[\"Service\"],\n key: Redacted.Redacted<string>,\n options: PushOptions,\n) =>\n Effect.gen(function* () {\n const source = options.source === undefined ? undefined : sourceOf(options.source);\n const resolved =\n options.source === undefined\n ? undefined\n : yield* checkSource(options.rootDir, options.source);\n const cwd = resolved?.cwd;\n const program = resolved?.program;\n const env = Object.entries(options.env).sort(([a], [b]) => (a < b ? -1 : 1));\n const removed = options.previousEnvNames.filter((name) => !Object.hasOwn(options.env, name));\n\n // 1. Variables before the push, so the push sees them. Each attempt\n // reads the current values first, so a retry after a write conflict never\n // overwrites a value that another writer set in the meantime. Only\n // changed values are written, and the earlier ones are kept for a\n // rollback.\n const written =\n env.length === 0 && removed.length === 0\n ? { current: {}, changes: [] }\n : yield* retryIdempotentWrite(\n Effect.gen(function* () {\n const current = yield* listVariables(options.url, key);\n if (!options.adopt) {\n // The same value loses nothing, such as a value that an\n // earlier run set before its push failed.\n const taken = env\n .filter(\n ([name, value]) =>\n !options.previousEnvNames.includes(name) &&\n Object.hasOwn(current, name) &&\n current[name] !== valueOf(value),\n )\n .map(([name]) => name);\n if (taken.length > 0) {\n return yield* new VariablesOwnedBySomeoneElse({\n deployment: options.deployment,\n names: taken,\n });\n }\n }\n const changes = [\n ...env\n .filter(([name, value]) => current[name] !== valueOf(value))\n .map(([name, value]) => ({ name, value: valueOf(value) })),\n ...removed\n .filter((name) => Object.hasOwn(current, name))\n .map((name) => ({ name, value: null })),\n ];\n if (changes.length > 0) yield* writeVariables(options.url, key, changes);\n return { current, changes };\n }),\n );\n\n /**\n * After a failed push, the variables go back to their earlier values, so\n * that the deployment matches the hash in state. A failed rollback is\n * logged: the push error is the one to report.\n */\n const rollback =\n written.changes.length === 0\n ? Effect.void\n : retryIdempotentWrite(\n writeVariables(\n options.url,\n key,\n written.changes.map(({ name }) => ({\n name,\n value: Object.hasOwn(written.current, name)\n ? (written.current[name] ?? null)\n : null,\n })),\n ),\n ).pipe(\n Effect.catch((error) =>\n Effect.logWarning(\n `Convex.Deployment could not set the env variables of ${options.deployment} back after the failed push (${error.message}). Run the deploy again.`,\n ),\n ),\n );\n\n // 2. The push, with the key only in the env file.\n if (source === undefined || cwd === undefined || program === undefined) return undefined;\n return yield* runPush(spawner, key, { ...options, cwd, program, command: source.command }).pipe(\n Effect.onError(() => rollback),\n );\n });\n\n/** Runs the installed CLI or the push command once, and checks the deployment that it names. */\nconst runPush = (\n spawner: ChildProcessSpawner.ChildProcessSpawner[\"Service\"],\n key: Redacted.Redacted<string>,\n options: PushOptions & {\n readonly cwd: string;\n readonly program: readonly [string, ...string[]];\n readonly command: readonly [string, ...string[]] | undefined;\n },\n) =>\n Effect.gen(function* () {\n const { cwd, program } = options;\n const secret = Redacted.value(key);\n const secrets = [secret, secret.slice(secret.indexOf(\"|\") + 1)].filter(\n (value) => value.length >= 8,\n );\n const result = yield* withKeyFile(secret, ({ envFile, home }) =>\n Effect.gen(function* () {\n const [command, ...programArgs] = program;\n // The installed CLI reads the key from the env file. A push command\n // gets it as CONVEX_DEPLOY_KEY, which the CLI that it runs reads.\n const args =\n options.command === undefined\n ? [\n ...programArgs,\n \"deploy\",\n ...(options.previewName === undefined\n ? []\n : [\"--preview-name\", options.previewName]),\n \"--env-file\",\n envFile,\n ]\n : programArgs;\n const child = yield* spawner.spawn(\n ChildProcess.make(command, args, {\n cwd,\n env: {\n ...cliEnvironment(home),\n ...(options.command === undefined ? {} : { CONVEX_DEPLOY_KEY: secret }),\n },\n extendEnv: false,\n stdin: \"ignore\",\n stdout: \"pipe\",\n stderr: \"pipe\",\n }),\n );\n const [exitCode, stdout, stderr] = yield* Effect.all(\n [\n child.exitCode,\n Stream.mkString(Stream.decodeText(child.stdout)),\n Stream.mkString(Stream.decodeText(child.stderr)),\n ],\n { concurrency: \"unbounded\" },\n );\n return { exitCode: Number(exitCode), output: `${stdout}\\n${stderr}` };\n }).pipe(Effect.scoped),\n ).pipe(\n Effect.mapError(\n (error) =>\n new CodePushFailed({\n exitCode: undefined,\n outputTail: outputTail(error.message, secrets),\n }),\n ),\n );\n const deployed = parseDeployOutput(result.output);\n if (result.exitCode !== 0 || deployed === undefined) {\n return yield* new CodePushFailed({\n exitCode: result.exitCode,\n outputTail: outputTail(result.output, secrets),\n });\n }\n if (deployed.deploymentName !== options.deployment) {\n return yield* new PushTargetMismatch({\n expected: options.deployment,\n actual: deployed.deploymentName,\n });\n }\n return deployed.url;\n });\n","// Convex.Deployment: one deployment of a Convex project, its environment\n// variables, and its functions, with the URLs that a frontend or a Worker\n// needs. This is the Convex plane of a stack: no deploy key leaves it.\n//\n// - `rootDir` is the app directory, relative to the directory where the\n// deploy runs (the directory of the stack file), such as `apps/web`, and\n// \".\" by default. The push runs in it, and `source` is relative to it.\n// The constructor writes it into the props, \".\" included, so that a reader\n// of the state row finds the app directory of every deployment.\n// - `source` is the Convex functions directory relative to `rootDir`, such\n// as `./convex`. The update pushes it with the Convex CLI that the app\n// installed (Push.ts).\n// The content identity of the push is a hash of the source files, the\n// app's package.json, convex.json, and lockfile, the deployment name, and\n// `env`. The same hash is a no-op. The hash is taken again after the push,\n// so files that `convex deploy` generates are part of it.\n// `source.command` replaces `convex deploy`, such as `convex-hosting\n// deploy`, and `source.include` adds the files that it reads to the hash.\n// - `env` is set on the deployment before the push. A name that leaves `env`\n// is removed. A variable that exists with another value and that this\n// resource did not set is someone else's: it is overwritten only with\n// --adopt. Delete leaves the variables: they go with the deployment.\n// - Credentials by scope (see Access below): a deploy key of the deployment,\n// a preview deploy key of the project, or the Management API token.\n// - `prod` is the project's default production deployment. Convex creates it\n// with the project, so this resource never creates one. It takes the\n// deployment over without --adopt: it never changes or deletes a production\n// deployment, so the takeover cannot lose data. It follows the default:\n// when another production deployment becomes the default, the next deploy\n// outputs that one. With a deploy key, `prod` is the production deployment\n// of that key. To delete a production deployment, delete its project\n// (Convex.Project with RemovalPolicy.destroy()). Delete reads the live type\n// first, so a dev or preview deployment that became a production\n// deployment is not deleted either.\n// - `dev` and `preview` are created with POST\n// /projects/{project_id}/create_deployment and the `name` prop as the\n// reference. Convex keeps a dev reference as given. For a preview, Convex\n// records `name` as the preview identifier, the name that\n// `npx convex deploy --preview-name <name>` finds, and derives the reference\n// from it (`preview/<slug>`). A create for a preview name that already has\n// a preview deployment deletes that deployment and creates a new one, so\n// reconcile always looks the name up first and never creates over an\n// existing deployment. A dev or preview deployment that exists but is not\n// in state belongs to someone else: the resource takes it over only with\n// --adopt.\n// - `projectId`, `type`, and `name` are the identity. A change fails with\n// DeploymentIdentityChange; the resource is never replaced.\n// - The removal policy is `retain` for every type. A preview deployment\n// expires on Convex's schedule (14 days by default). To delete a dev or\n// preview deployment with the resource, add RemovalPolicy.destroy().\n//\n// Patterns from Confect `packages/alchemy/src/Deployment.ts`\n// (https://github.com/rjdellecese/confect, ISC license, see NOTICE).\nimport { posix, win32 } from \"node:path\";\nimport { Resource } from \"alchemy\";\nimport { OwnedBySomeoneElse, Unowned } from \"alchemy/AdoptPolicy\";\nimport { diffBindings, isResolved } from \"alchemy/Diff\";\nimport type { InputProps } from \"alchemy/Input\";\nimport * as Provider from \"alchemy/Provider\";\nimport * as Effect from \"effect/Effect\";\nimport * as ChildProcessSpawner from \"effect/process/ChildProcessSpawner\";\nimport * as Redacted from \"effect/Redacted\";\nimport * as Schema from \"effect/Schema\";\nimport { shouldAdopt } from \"./Adoption.ts\";\nimport { Credentials } from \"./Credentials.ts\";\nimport type { ComponentBinding } from \"./Component.ts\";\nimport {\n absentAsUndefined,\n type ConvexApiError,\n ManagementApi,\n type ManagementApiService,\n retryIdempotentWrite,\n} from \"./ManagementApi.ts\";\nimport type { Providers } from \"./Providers.ts\";\nimport {\n checkSource,\n EnvironmentNeedsDeployKey,\n type EnvValue,\n keyTargetOf,\n push,\n PUSH_KEY_ACTIONS,\n pushHash,\n type Source,\n withPushKey,\n} from \"./Push.ts\";\n\ninterface DeploymentInputs {\n /** The project: a Convex.Project resource, or `{ projectId }`. Cannot change. */\n readonly project: { readonly projectId: number };\n /**\n * The app directory, relative to the directory where the deploy runs (the\n * directory of the stack file), such as `apps/web`. Default \".\". It must\n * have a package.json. The push runs in it, and `source` is relative to\n * it. State from 0.7 has no `rootDir`.\n */\n readonly rootDir?: string;\n /**\n * The Convex functions directory relative to `rootDir`, such as\n * `./convex`, or that directory with a push command and more hashed\n * files. Without `source`, the resource pushes nothing.\n */\n readonly source?: Source;\n /** Environment variables to set on the deployment before the push. */\n readonly env?: Readonly<Record<string, EnvValue>>;\n}\n\nexport type DeploymentProps =\n | (DeploymentInputs & {\n /** The project's default production deployment. Cannot change. */\n readonly type: \"prod\";\n })\n | (DeploymentInputs & {\n /** A dev deployment or a preview deployment that this resource creates. Cannot change. */\n readonly type: \"dev\" | \"preview\";\n /**\n * The dev reference, such as `staging`, or the preview name, such as\n * the stage name. Unique in the project. Cannot change.\n */\n readonly name: string;\n });\n\n/** The deployment itself, without the state of the push. */\ninterface DeploymentTarget {\n readonly projectId: number;\n readonly type: DeploymentProps[\"type\"];\n /** Deployment name, such as `happy-animal-123`. */\n readonly name: string;\n /** The reference that Convex lists, such as `production`, `staging`, or `preview/pr-42`. */\n readonly reference: string;\n /** The preview name of a preview deployment. Undefined for prod and dev. */\n readonly previewName: string | undefined;\n /** Client URL, such as `https://happy-animal-123.convex.cloud`. */\n readonly url: string;\n /** HTTP actions URL, such as `https://happy-animal-123.convex.site`. */\n readonly siteUrl: string;\n}\n\nexport interface DeploymentAttributes extends DeploymentTarget {\n /** Content identity of the last push and `env`. Undefined when the resource pushed nothing. */\n readonly hash: string | undefined;\n /** The names of the `env` variables that this resource set on the deployment, sorted. */\n readonly envNames: readonly string[];\n}\n\nexport type Deployment = Resource<\n \"Convex.Deployment\",\n DeploymentProps,\n DeploymentAttributes,\n ComponentBinding,\n Providers\n>;\n/** The resource class. Stacks call {@link Deployment}, which writes `rootDir` into the props. */\nexport const DeploymentResource = Resource<Deployment>(\"Convex.Deployment\", {\n defaultRemovalPolicy: \"retain\",\n});\n\n/** The props of a `Convex.Deployment` call: Alchemy inputs, with `rootDir` a plain string. */\nexport type DeploymentInput = DeploymentProps extends infer P\n ? P extends DeploymentProps\n ? InputProps<P, \"rootDir\">\n : never\n : never;\n\n/** `rootDir` in POSIX form, without \"./\" and a trailing slash, such as `apps/web` or \".\". */\nconst normalizeRootDir = (rootDir: string) => {\n const normalized = posix.normalize(rootDir.replaceAll(\"\\\\\", \"/\"));\n return normalized.length > 1 && normalized.endsWith(\"/\") ? normalized.slice(0, -1) : normalized;\n};\n\n/** `rootDir` is an absolute path. The declaration stops with it as a defect, before the plan. */\nexport class AbsoluteRootDir extends Schema.TaggedError<AbsoluteRootDir>()(\"AbsoluteRootDir\", {\n rootDir: Schema.String,\n}) {\n override get message() {\n return `Convex.Deployment rootDir ${this.rootDir} is an absolute path. State keeps rootDir for every machine that runs the stack, so set it relative to the directory where the deploy runs, such as \"apps/web\".`;\n }\n}\n\n/**\n * `Convex.Deployment(\"id\", props)`. The props go to state with `rootDir` in\n * POSIX form, and with \".\" when it is not set, so that every row names the\n * app directory of its deployment. An absolute `rootDir` stops the\n * declaration, so it never reaches the plan or state. The check dies,\n * because the program of `Alchemy.Stack` can fail only with a ConfigError.\n * `win32.isAbsolute` also answers true for a POSIX absolute path. The other\n * fields keep it usable where Alchemy takes a resource class, such as\n * `Provider.collection`.\n */\nexport const Deployment = Object.assign(\n (id: string, props: DeploymentInput) => {\n const rootDir = props.rootDir ?? \".\";\n return win32.isAbsolute(rootDir)\n ? Effect.die(new AbsoluteRootDir({ rootDir }))\n : DeploymentResource(id, { ...props, rootDir: normalizeRootDir(rootDir) });\n },\n {\n Type: DeploymentResource.Type,\n Props: DeploymentResource.Props,\n Self: DeploymentResource.Self,\n Provider: DeploymentResource.Provider,\n Aliases: DeploymentResource.Aliases,\n ref: (id: string, options?: { stage?: string; stack?: string }) =>\n DeploymentResource.ref(id, options),\n },\n);\n\n/** The props name another deployment than the one in state. */\nexport class DeploymentIdentityChange extends Schema.TaggedError<DeploymentIdentityChange>()(\n \"DeploymentIdentityChange\",\n {\n /** Name of the deployment in state, such as `happy-animal-123`. */\n deployment: Schema.String,\n field: Schema.Literals([\"projectId\", \"type\", \"name\"]),\n current: Schema.String,\n requested: Schema.String,\n },\n) {\n override get message() {\n return `Convex.Deployment cannot change the ${this.field} of deployment ${this.deployment} from ${this.current} to ${this.requested}. Set ${this.field} back to ${this.current}. For another deployment, create a new resource with a new logical id.`;\n }\n}\n\n/** The project has no default production deployment for a `prod` resource to take over. */\nexport class ProductionDeploymentNotFound extends Schema.TaggedError<ProductionDeploymentNotFound>()(\n \"ProductionDeploymentNotFound\",\n { projectId: Schema.Number },\n) {\n override get message() {\n return `Project ${this.projectId} has no default production deployment, and Convex.Deployment does not create one. Create it in the Convex dashboard, or with \\`npx convex deployment create --type prod --default\\` in the project, then run the deploy again.`;\n }\n}\n\n/** More than one deployment of the project has the name, so the lookup cannot choose one. */\nexport class AmbiguousDeployment extends Schema.TaggedError<AmbiguousDeployment>()(\n \"AmbiguousDeployment\",\n {\n projectId: Schema.Number,\n type: Schema.Literals([\"dev\", \"preview\"]),\n name: Schema.String,\n deployments: Schema.Array(Schema.String),\n },\n) {\n override get message() {\n return `Project ${this.projectId} has ${this.deployments.length} ${this.type} deployments named \"${this.name}\" (${this.deployments.join(\", \")}). Convex.Deployment does not choose one. Delete the extra deployments in the Convex dashboard, or use another name.`;\n }\n}\n\n/**\n * The URL of a Convex cloud deployment: `https://<name>.convex.cloud`, or\n * `https://<name>.<region>.convex.cloud` outside US East.\n */\nconst CLOUD_URL =\n /^https:\\/\\/[a-z0-9]+(?:-[a-z0-9]+)*(?:\\.[a-z0-9]+(?:-[a-z0-9]+)*)?\\.convex\\.cloud$/;\n\n/**\n * The HTTP actions URL of a deployment: the client URL with `.convex.site`\n * for `.convex.cloud`, as Convex sets CONVEX_SITE_URL. Custom domains are\n * not covered.\n */\nexport const siteUrlOf = (url: string): string => url.replace(/\\.convex\\.cloud$/, \".convex.site\");\n\n/** One row of list_deployments, GET /deployments/{name}, and create_deployment. Only the fields the provider uses. */\nexport const DeploymentRow = Schema.Struct({\n name: Schema.String,\n projectId: Schema.Number,\n deploymentType: Schema.String,\n isDefault: Schema.Boolean,\n reference: Schema.String,\n /** Set in list_deployments and create_deployment rows only: GET /deployments/{name} answers null. */\n previewIdentifier: Schema.optionalKey(Schema.NullOr(Schema.String)),\n deploymentUrl: Schema.String.check(Schema.isPattern(CLOUD_URL)),\n /** Absent or null until the first push: list_deployments leaves it out for a new deployment. */\n lastDeployTime: Schema.optionalKey(Schema.NullOr(Schema.Number)),\n});\ntype DeploymentRow = typeof DeploymentRow.Type;\nconst DeploymentRows = Schema.Array(DeploymentRow);\n\n/** GET https://<deployment>/api/v1/deployment_info, for a cloud deployment. Only the fields the provider uses. */\nconst DeploymentInfo = Schema.Struct({\n kind: Schema.Literal(\"cloud\"),\n projectId: Schema.Number,\n deploymentType: Schema.String,\n reference: Schema.optionalKey(Schema.NullOr(Schema.String)),\n});\n\n/** GET https://<deployment>/api/v1/get_canonical_urls */\nconst CanonicalUrls = Schema.Struct({\n convexCloudUrl: Schema.String,\n convexSiteUrl: Schema.String,\n});\n\nconst targetOf = (\n row: DeploymentRow,\n type: DeploymentProps[\"type\"],\n previewName: string | undefined,\n): DeploymentTarget => ({\n projectId: row.projectId,\n type,\n name: row.name,\n reference: row.reference,\n previewName: type === \"preview\" ? previewName : undefined,\n url: row.deploymentUrl,\n siteUrl: siteUrlOf(row.deploymentUrl),\n});\n\n/** True when the deployment has received a push. */\nconst isDeployed = (row: DeploymentRow) =>\n row.lastDeployTime !== undefined && row.lastDeployTime !== null;\n\n/** The `name` prop of a deployment: the dev reference or the preview name. */\nconst nameOf = (target: DeploymentTarget) =>\n target.type === \"dev\"\n ? target.reference\n : target.type === \"preview\"\n ? target.previewName\n : undefined;\n\n/**\n * Fails with {@link DeploymentIdentityChange} when the props name another\n * deployment than `current`: the attributes in state, or a live deployment.\n */\nconst checkIdentity = (current: DeploymentTarget, news: DeploymentProps) => {\n const change = (field: \"projectId\" | \"type\" | \"name\", from: string, to: string) =>\n Effect.fail(\n new DeploymentIdentityChange({\n deployment: current.name,\n field,\n current: from,\n requested: to,\n }),\n );\n if (current.projectId !== news.project.projectId) {\n return change(\"projectId\", String(current.projectId), String(news.project.projectId));\n }\n if (current.type !== news.type) return change(\"type\", current.type, news.type);\n const currentName = nameOf(current);\n if (news.type !== \"prod\" && currentName !== news.name) {\n return change(\"name\", currentName ?? \"(none)\", news.name);\n }\n return Effect.void;\n};\n\n/** The deployment that a resource addresses: its project, type, and dev or preview name. */\ninterface Address {\n readonly projectId: number;\n readonly type: DeploymentProps[\"type\"];\n readonly name: string | undefined;\n}\n\nconst addressOf = (props: DeploymentProps): Address => ({\n projectId: props.project.projectId,\n type: props.type,\n name: props.type === \"prod\" ? undefined : props.name,\n});\n\n/** True when an update writes or removes variables: `env` has names, or state has names to remove. */\nconst changesEnv = (news: DeploymentProps, output: DeploymentAttributes | undefined) =>\n Object.keys(news.env ?? {}).length > 0 || envNamesOf(output).length > 0;\n\n/** The `env` names in state. State from 0.3 has none. */\nconst envNamesOf = (output: DeploymentAttributes | undefined): readonly string[] =>\n output?.envNames ?? [];\n\n/** The address of the deployment in state. */\nconst addressInState = (output: DeploymentAttributes): Address => ({\n projectId: output.projectId,\n type: output.type,\n name: nameOf(output),\n});\n\n/**\n * How the provider reaches one deployment, by the narrowest credential that\n * fits:\n *\n * - `deployKey`: the configured deploy key belongs to this deployment. The\n * deployment API answers its identity and URLs, the key sets variables and\n * pushes, and no Management API call is made.\n * - `previewKey`: the configured preview deploy key belongs to this project.\n * The Management API takes it for the preview deployments of the project,\n * and the CLI pushes with it and `--preview-name`.\n * - `token`: the Management API access token. Each push gets a short-lived\n * deploy key (Push.ts).\n */\ntype Access =\n | {\n readonly kind: \"deployKey\";\n readonly key: Redacted.Redacted<string>;\n readonly target: DeploymentTarget;\n }\n | {\n readonly kind: \"previewKey\";\n readonly key: Redacted.Redacted<string>;\n readonly api: ManagementApiService;\n }\n | { readonly kind: \"token\"; readonly api: ManagementApiService };\n\nconst ProjectSlugs = Schema.Struct({ slug: Schema.String, teamSlug: Schema.String });\n\n/** True for an answer that says this credential cannot read the object. */\nconst isRefused = (error: ConvexApiError) =>\n error.status === 400 || error.status === 401 || error.status === 403 || error.status === 404;\n\nexport const DeploymentProvider = () =>\n Provider.effect(\n DeploymentResource,\n Effect.gen(function* () {\n const api = yield* ManagementApi;\n const credentials = yield* Credentials;\n const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;\n\n /** The live deployment, or undefined after a 404. GET /deployments/{name} answers no preview identifier. */\n const getByName = (management: ManagementApiService, name: string) =>\n absentAsUndefined(\n management.request(\"get deployment\", (client) =>\n client.GET(\"/deployments/{deployment_name}\", {\n params: { path: { deployment_name: name } },\n }),\n ),\n ).pipe(\n Effect.map((body) =>\n body === undefined ? undefined : Schema.decodeUnknownSync(DeploymentRow)(body),\n ),\n );\n\n const listDeployments = (\n management: ManagementApiService,\n projectId: number,\n type: DeploymentProps[\"type\"],\n isDefault?: boolean,\n ) =>\n management\n .request(\"list deployments\", (client) =>\n client.GET(\"/projects/{project_id}/list_deployments\", {\n params: {\n path: { project_id: projectId },\n query: { deploymentType: type, ...(isDefault === undefined ? {} : { isDefault }) },\n },\n }),\n )\n .pipe(Effect.map((body) => Schema.decodeUnknownSync(DeploymentRows)(body)));\n\n /** The row of the project's default production deployment, or undefined. */\n const productionRow = (management: ManagementApiService, projectId: number) =>\n listDeployments(management, projectId, \"prod\", true).pipe(\n Effect.map((rows) =>\n rows.find((candidate) => candidate.deploymentType === \"prod\" && candidate.isDefault),\n ),\n );\n\n /** The project's default production deployment, or undefined. */\n const production = (management: ManagementApiService, projectId: number) =>\n productionRow(management, projectId).pipe(\n Effect.map((row) => (row === undefined ? undefined : targetOf(row, \"prod\", undefined))),\n );\n\n /**\n * The one dev deployment with this reference, or the one preview\n * deployment with this preview name, or undefined.\n */\n const findByName = (\n management: ManagementApiService,\n projectId: number,\n type: \"dev\" | \"preview\",\n name: string,\n ) =>\n Effect.gen(function* () {\n const matches = (yield* listDeployments(management, projectId, type)).filter(\n (row) =>\n row.deploymentType === type &&\n (type === \"dev\" ? row.reference === name : row.previewIdentifier === name),\n );\n if (matches.length > 1) {\n return yield* new AmbiguousDeployment({\n projectId,\n type,\n name,\n deployments: matches.map((row) => row.name),\n });\n }\n return matches[0];\n });\n\n /** The deployment that the address names, through the Management API, or undefined. */\n const lookup = (management: ManagementApiService, address: Address) =>\n address.type === \"prod\" || address.name === undefined\n ? production(management, address.projectId)\n : findByName(management, address.projectId, address.type, address.name).pipe(\n Effect.map((row) =>\n row === undefined ? undefined : targetOf(row, address.type, address.name),\n ),\n );\n\n /** The deployment of a deploy key, when it is the deployment that the address names. */\n const deployKeyTarget = (\n key: Redacted.Redacted<string>,\n deployment: string,\n address: Address,\n ) =>\n Effect.gen(function* () {\n const info = Schema.decodeUnknownSync(DeploymentInfo)(\n yield* api.deploymentRequest(\"get deployment info\", deployment, key, (client) =>\n client.GET(\"/deployment_info\"),\n ),\n );\n const reference = info.reference ?? \"\";\n if (\n info.projectId !== address.projectId ||\n info.deploymentType !== address.type ||\n (address.type === \"dev\" && reference !== address.name)\n ) {\n return undefined;\n }\n const urls = Schema.decodeUnknownSync(CanonicalUrls)(\n yield* api.deploymentRequest(\"get canonical urls\", deployment, key, (client) =>\n client.GET(\"/get_canonical_urls\"),\n ),\n );\n return {\n projectId: info.projectId,\n type: address.type,\n name: deployment,\n reference,\n previewName: undefined,\n url: urls.convexCloudUrl,\n siteUrl: urls.convexSiteUrl,\n } satisfies DeploymentTarget;\n }).pipe(Effect.catchIf(isRefused, () => Effect.succeed(undefined)));\n\n /** True when the preview deploy key belongs to the project. */\n const previewKeyFits = (\n management: ManagementApiService,\n slugs: { readonly team: string; readonly project: string },\n projectId: number,\n ) =>\n management\n .request(\"get project\", (client) =>\n client.GET(\"/projects/{project_id}\", { params: { path: { project_id: projectId } } }),\n )\n .pipe(\n Effect.map((body) => {\n const project = Schema.decodeUnknownSync(ProjectSlugs)(body);\n return project.slug === slugs.project && project.teamSlug === slugs.team;\n }),\n Effect.catchIf(isRefused, () => Effect.succeed(false)),\n );\n\n /**\n * The narrowest credential that reaches the deployment. See {@link Access}.\n * When `changesEnv`, a preview deploy key gives way to the access token,\n * because it cannot change variables.\n */\n const accessFor = (address: Address, changesEnv: boolean) =>\n Effect.gen(function* (): Effect.fn.Return<Access, ConvexApiError> {\n const key = yield* credentials.deployKey;\n if (key !== undefined) {\n const target = keyTargetOf(Redacted.value(key));\n if (target.kind === \"deployment\" && address.type !== \"preview\") {\n const found = yield* deployKeyTarget(key, target.deployment, address);\n if (found !== undefined) return { kind: \"deployKey\", key, target: found };\n }\n if (target.kind === \"preview\" && address.type === \"preview\") {\n const scoped = api.withToken(key);\n if (\n !(changesEnv && (yield* credentials.hasAccessToken)) &&\n (yield* previewKeyFits(scoped, target, address.projectId))\n ) {\n return { kind: \"previewKey\", key, api: scoped };\n }\n }\n }\n return { kind: \"token\", api };\n });\n\n /** The live deployment of a resource in state, or undefined when it is gone. */\n const live = (access: Access, output: DeploymentAttributes) =>\n Effect.gen(function* () {\n if (access.kind === \"deployKey\") return access.target;\n // 404 for a deleted project: its production deployment is gone too.\n if (output.type === \"prod\")\n return yield* absentAsUndefined(production(access.api, output.projectId));\n const row = yield* getByName(access.api, output.name);\n return row === undefined ? undefined : targetOf(row, output.type, output.previewName);\n });\n\n /** The content identity of `source` and `env` on a deployment, or undefined when there is nothing to push. */\n const wantedHash = (news: DeploymentProps, rootDir: string, deployment: string) =>\n news.source === undefined && Object.keys(news.env ?? {}).length === 0\n ? Effect.succeed(undefined)\n : pushHash({ rootDir, source: news.source, deployment, env: news.env ?? {} });\n\n return {\n // `name`, `reference`, and the URLs change when an expired preview is\n // created again, or when another production deployment becomes the\n // default.\n stables: [\"projectId\", \"type\", \"previewName\"],\n\n // Compares with the attributes: after a refused change, `olds` are\n // the refused props. Only `rootDir` compares with `olds`, because it\n // is in the props only. A refused update leaves the row `updating`,\n // and the next plan updates it again anyway.\n diff: Effect.fn(function* ({ news, olds, output, oldBindings, newBindings }) {\n if (!isResolved(news) || output === undefined) return undefined;\n yield* checkIdentity(output, news);\n if (!isResolved(newBindings)) return undefined;\n // State from 0.7 has no rootDir; the constructor always writes it.\n const rootDir = news.rootDir ?? \".\";\n // Also here, so that a wrong rootDir stops the plan before Apply\n // writes the new props to the row.\n if (news.source !== undefined) yield* checkSource(rootDir, news.source);\n // State from 0.7 has no rootDir, and another rootDir is another\n // app directory. The update writes the props to state; it pushes\n // only when the hash changed.\n if (olds.rootDir !== rootDir) return { action: \"update\" } as const;\n const access = yield* accessFor(addressOf(news), changesEnv(news, output));\n // A preview expires, anyone can delete a deployment, and another\n // production deployment can become the default. Reconcile then\n // finds or creates the right one, so the stack never hands out the\n // URL of a deployment that is gone.\n const current = yield* live(access, output);\n if (current?.name !== output.name) return { action: \"update\" } as const;\n const hash = yield* wantedHash(news, rootDir, output.name);\n if (hash !== output.hash) return { action: \"update\" } as const;\n if (diffBindings(oldBindings, newBindings).every((binding) => binding.action === \"noop\"))\n return { action: \"noop\" } as const;\n // Binding metadata does not change deployment outputs. Keep unchanged\n // values available to consumers so the plan does not update them too.\n return {\n action: \"update\" as const,\n stables: [\n \"hash\",\n \"envNames\",\n ...(\n [\"projectId\", \"type\", \"previewName\", \"name\", \"reference\", \"url\", \"siteUrl\"] as const\n ).filter((key) => current[key] === output[key]),\n ],\n };\n }),\n\n read: Effect.fn(function* ({ olds, output }) {\n if (output !== undefined) {\n const access = yield* accessFor(addressInState(output), false);\n const current = yield* live(access, output);\n return current === undefined ? undefined : { ...output, ...current };\n }\n const address = addressOf(olds);\n const access = yield* accessFor(address, false);\n if (access.kind === \"deployKey\") {\n // The deployment API does not say whether the deployment has code.\n return Unowned({ ...access.target, hash: undefined, envNames: [] });\n }\n if (olds.type === \"prod\") {\n const row = yield* productionRow(access.api, address.projectId);\n if (row === undefined) return undefined;\n const attributes = {\n ...targetOf(row, \"prod\", undefined),\n hash: undefined,\n envNames: [],\n };\n // A production deployment that never received a push, such as\n // the one of a project that this stack created, loses nothing to\n // a push. One with code is someone else's until --adopt.\n return isDeployed(row) ? Unowned(attributes) : attributes;\n }\n const found = yield* lookup(access.api, address);\n if (found === undefined) return undefined;\n // A dev or preview deployment that is not in state is someone\n // else's until the user passes --adopt.\n return Unowned({ ...found, hash: undefined, envNames: [] });\n }),\n\n reconcile: Effect.fn(function* ({ fqn, news, output }) {\n // Also here: with an unresolved prop in plan, diff could not check.\n if (output !== undefined) yield* checkIdentity(output, news);\n // The app directory, the functions directory, and the program,\n // before any change.\n const rootDir = news.rootDir ?? \".\";\n if (news.source !== undefined) yield* checkSource(rootDir, news.source);\n const address = addressOf(news);\n const access = yield* accessFor(address, changesEnv(news, output));\n const env = news.env ?? {};\n // Before any create: a preview deploy key cannot change variables,\n // and accessFor chose it because there is no access token.\n if (access.kind === \"previewKey\" && changesEnv(news, output)) {\n return yield* new EnvironmentNeedsDeployKey({\n deployment: output?.name ?? address.name ?? \"(new)\",\n });\n }\n const adopt = yield* shouldAdopt(fqn);\n const refuse = (name: string) =>\n new OwnedBySomeoneElse({\n message: `Project ${address.projectId} already has ${news.type} deployment ${name}${news.type === \"prod\" ? \" with code\" : ` named \"${news.name}\"`}. Re-run with --adopt to take it over${news.type === \"prod\" ? \"\" : \", or use another name\"}.`,\n resourceType: DeploymentResource.Type,\n physicalName: name,\n });\n\n // 1. The deployment. `created` is true when this reconcile created it.\n const { target, created } = yield* Effect.gen(function* () {\n if (access.kind === \"deployKey\") {\n // read() refused it without --adopt; this covers an apply without a plan.\n if (output === undefined && !adopt) return yield* refuse(access.target.name);\n return { target: access.target, created: false };\n }\n if (news.type === \"prod\") {\n // Always the current default, also when another production\n // deployment became the default after the last deploy.\n const row = yield* productionRow(access.api, address.projectId);\n if (row === undefined) {\n return yield* new ProductionDeploymentNotFound({ projectId: address.projectId });\n }\n // Code that appeared after the plan is someone else's.\n if (output === undefined && isDeployed(row) && !adopt) return yield* refuse(row.name);\n return { target: targetOf(row, \"prod\", undefined), created: false };\n }\n if (output !== undefined) {\n const row = yield* getByName(access.api, output.name);\n if (row !== undefined) {\n if (row.deploymentType !== output.type) {\n return yield* new DeploymentIdentityChange({\n deployment: row.name,\n field: \"type\",\n current: row.deploymentType,\n requested: news.type,\n });\n }\n const current = targetOf(row, output.type, output.previewName);\n // The live deployment can have moved to another project.\n yield* checkIdentity(current, news);\n return { target: current, created: false };\n }\n // The deployment in state is gone, such as an expired preview.\n // Find or create it below like a resource without state.\n }\n // Never create over an existing deployment: a preview create\n // replaces the preview deployment with the same name. Another\n // writer can still create one between this lookup and the create.\n const existing = yield* lookup(access.api, address);\n if (existing !== undefined) {\n if (!adopt) return yield* refuse(existing.name);\n return { target: existing, created: false };\n }\n const row = yield* access.api.request(\"create deployment\", (client) =>\n client.POST(\"/projects/{project_id}/create_deployment\", {\n params: { path: { project_id: address.projectId } },\n body: { type: news.type, reference: news.name },\n }),\n );\n return {\n target: targetOf(Schema.decodeUnknownSync(DeploymentRow)(row), news.type, news.name),\n created: true,\n };\n });\n\n // 2. The variables and the push, only when their content changed.\n // Variables set on another deployment stay there: they are not ours\n // on this one.\n const previousEnvNames = output?.name === target.name ? envNamesOf(output) : [];\n const before = yield* wantedHash(news, rootDir, target.name);\n if (before === undefined && previousEnvNames.length === 0) {\n return { ...target, hash: undefined, envNames: [] };\n }\n if (output?.name === target.name && before === output.hash) {\n return { ...target, hash: output.hash, envNames: previousEnvNames };\n }\n const options = {\n deployment: target.name,\n url: target.url,\n rootDir,\n source: news.source,\n env,\n previousEnvNames,\n adopt,\n };\n const pushed =\n access.kind === \"deployKey\"\n ? push(spawner, access.key, { ...options, previewName: undefined })\n : access.kind === \"previewKey\"\n ? push(spawner, access.key, { ...options, previewName: target.previewName })\n : withPushKey(\n access.api,\n target.name,\n // A push command gets every action; `convex deploy` only its own.\n typeof news.source === \"object\" && news.source.command !== undefined\n ? undefined\n : PUSH_KEY_ACTIONS,\n (key) => push(spawner, key, { ...options, previewName: undefined }),\n );\n yield* pushed.pipe(\n // A deployment that this reconcile created and could not push to\n // would be someone else's on the next run, and a dev deployment\n // never expires. It is new and empty, so it goes.\n Effect.onError(() =>\n created && access.kind !== \"deployKey\"\n ? absentAsUndefined(\n retryIdempotentWrite(\n access.api.requestVoid(\"delete deployment\", (client) =>\n client.POST(\"/deployments/{deployment_name}/delete\", {\n params: { path: { deployment_name: target.name } },\n }),\n ),\n ),\n ).pipe(\n Effect.catch((error) =>\n Effect.logWarning(\n `Convex.Deployment could not delete ${target.name} after the failed push (${error.message}). The next run takes it over only with --adopt.`,\n ),\n ),\n )\n : Effect.void,\n ),\n );\n // Taken again after the push, so that files the push generates,\n // such as convex/_generated, are part of the identity.\n return {\n ...target,\n hash: yield* wantedHash(news, rootDir, target.name),\n envNames: Object.keys(env).sort(),\n };\n }),\n\n // Runs only with RemovalPolicy.destroy(): the default policy is\n // `retain`. The variables go with the deployment.\n delete: Effect.fn(function* ({ output }) {\n const keep = Effect.logWarning(\n `Convex.Deployment does not delete production deployment ${output.name}: it belongs to project ${output.projectId}. To delete it, delete the project with RemovalPolicy.destroy() on Convex.Project.`,\n );\n if (output.type === \"prod\") return yield* keep;\n const access = yield* accessFor(addressInState(output), false);\n // A deploy key cannot delete its deployment.\n const management = access.kind === \"deployKey\" ? api : access.api;\n // The type in state can be old: a dev or preview deployment can\n // become a production deployment in Convex. The live type decides.\n const row = yield* getByName(management, output.name);\n // 404: an earlier attempt, the expiry, or someone else deleted it.\n if (row === undefined) return;\n if (row.deploymentType === \"prod\") return yield* keep;\n yield* absentAsUndefined(\n retryIdempotentWrite(\n management.requestVoid(\"delete deployment\", (client) =>\n client.POST(\"/deployments/{deployment_name}/delete\", {\n params: { path: { deployment_name: output.name } },\n }),\n ),\n ),\n );\n }),\n };\n }),\n );\n","// Convex.Project: a project in a Convex team, with its default production deployment.\n//\n// Deleting a project deletes all of its deployments and data, so this\n// resource never replaces a project and keeps it by default:\n//\n// - A name change is an update in place: PATCH /projects/{project_id} with\n// the new name. The slug stays the same.\n// - `team`, `deploymentType`, and `deploymentRegion` cannot change on an\n// existing project. A change fails with a typed error that names the fix.\n// - The removal policy is `retain`. Alchemy deletes the project only when the\n// resource has `RemovalPolicy.destroy()`.\n// - With state, every call addresses the project by `output.projectId`. Only\n// a resource without state looks a project up by name, and it takes over a\n// project that it finds only when adoption is on.\n// - With `slug` instead of `name`, the resource is an existing project,\n// found by GET /teams/{team}/projects/{slug}. It never creates, renames, or\n// (by default) deletes that project. A stack that only pushes to an\n// existing project can pass `{ projectId }` to Convex.Deployment instead\n// and needs no Management API token for the project.\nimport { Resource } from \"alchemy\";\nimport { OwnedBySomeoneElse, Unowned } from \"alchemy/AdoptPolicy\";\nimport { isResolved } from \"alchemy/Diff\";\nimport * as Provider from \"alchemy/Provider\";\nimport * as Effect from \"effect/Effect\";\nimport * as Schema from \"effect/Schema\";\nimport type { components } from \"@convex-dev/platform/managementApi\";\nimport { shouldAdopt } from \"./Adoption.ts\";\nimport {\n absentAsUndefined,\n ConvexApiError,\n ManagementApi,\n type ManagementApiService,\n} from \"./ManagementApi.ts\";\nimport type { Providers } from \"./Providers.ts\";\n\n/** Region names the Management API accepts, from the generated schema. */\nexport type DeploymentRegion = components[\"schemas\"][\"RegionName\"];\n\nexport type ProjectProps =\n | {\n /** Team slug or numeric team id. A slug costs one extra lookup per run. Cannot change. */\n readonly team: string | number;\n /** Display name. Convex derives the slug from it at creation. A change renames the project. */\n readonly name: string;\n /** Region of the deployment created with the project. Defaults to the team default. Cannot change. */\n readonly deploymentRegion?: DeploymentRegion;\n /** Deployment created with the project. Defaults to `prod`. Cannot change. */\n readonly deploymentType?: \"prod\" | \"dev\";\n }\n | {\n /** Team slug or numeric team id. Cannot change. */\n readonly team: string | number;\n /** Slug of an existing project, such as `score-four`. The resource never creates a project. Cannot change. */\n readonly slug: string;\n };\n\nexport interface ProjectAttributes {\n readonly projectId: number;\n readonly slug: string;\n readonly name: string;\n readonly teamId: number;\n readonly prodDeploymentName: string | undefined;\n readonly prodDeploymentUrl: string | undefined;\n}\n\nexport type Project = Resource<\"Convex.Project\", ProjectProps, ProjectAttributes, never, Providers>;\nexport const Project = Resource<Project>(\"Convex.Project\", { defaultRemovalPolicy: \"retain\" });\n\n/** The props change the team of an existing project. Convex cannot move a project. */\nexport class ProjectTeamChange extends Schema.TaggedError<ProjectTeamChange>()(\n \"ProjectTeamChange\",\n { projectId: Schema.Number, teamId: Schema.Number, requestedTeamId: Schema.Number },\n) {\n override get message() {\n return `Convex.Project cannot move project ${this.projectId} from team ${this.teamId} to team ${this.requestedTeamId}. Set team back to ${this.teamId}. To use the other team, create a new resource with a new logical id and move the data yourself.`;\n }\n}\n\n/**\n * The props change `deploymentType` or `deploymentRegion` of an existing\n * project. Convex uses them only when it creates the project.\n */\nexport class ProjectDeploymentChange extends Schema.TaggedError<ProjectDeploymentChange>()(\n \"ProjectDeploymentChange\",\n {\n projectId: Schema.Number,\n field: Schema.Literals([\"deploymentType\", \"deploymentRegion\"]),\n current: Schema.UndefinedOr(Schema.String),\n requested: Schema.UndefinedOr(Schema.String),\n },\n) {\n override get message() {\n const show = (value: string | undefined) => (value === undefined ? \"(not set)\" : value);\n return `Convex.Project cannot change ${this.field} of project ${this.projectId} from ${show(this.current)} to ${show(this.requested)}: Convex uses it only when it creates a project. Set ${this.field} back to ${show(this.current)}. For a new deployment, create a new resource with a new logical id and move the data yourself.`;\n }\n}\n\n/** More than one project in the team has the name, so the lookup cannot choose one. */\nexport class AmbiguousProject extends Schema.TaggedError<AmbiguousProject>()(\"AmbiguousProject\", {\n teamId: Schema.Number,\n name: Schema.String,\n projectIds: Schema.Array(Schema.Number),\n}) {\n override get message() {\n return `Team ${this.teamId} has ${this.projectIds.length} projects named \"${this.name}\" (ids ${this.projectIds.join(\", \")}). Convex.Project does not choose one. Rename the projects in the Convex dashboard so that only one has this name, or use a different name.`;\n }\n}\n\n/** Convex answered a create call but then did not return the project. */\nexport class CreatedProjectNotFound extends Schema.TaggedError<CreatedProjectNotFound>()(\n \"CreatedProjectNotFound\",\n { projectId: Schema.Number },\n) {\n override get message() {\n return `Convex created project ${this.projectId} but GET /projects/${this.projectId} did not return it. Run the deploy again with --adopt to take over project ${this.projectId}.`;\n }\n}\n\n/** No project in the team has the slug. A `slug` resource never creates one. */\nexport class ProjectNotFound extends Schema.TaggedError<ProjectNotFound>()(\"ProjectNotFound\", {\n team: Schema.String,\n slug: Schema.String,\n}) {\n override get message() {\n return `Team ${this.team} has no project with the slug \"${this.slug}\", and a Convex.Project with a slug never creates one. Check the slug in the project URL of the Convex dashboard, or use name to create a project.`;\n }\n}\n\n/** The props change the slug of a `slug` resource: that is another project. */\nexport class ProjectSlugChange extends Schema.TaggedError<ProjectSlugChange>()(\n \"ProjectSlugChange\",\n { projectId: Schema.Number, slug: Schema.String, requestedSlug: Schema.String },\n) {\n override get message() {\n return `Convex.Project ${this.projectId} has the slug \"${this.slug}\", and the props ask for \"${this.requestedSlug}\", which is another project. Set slug back to \"${this.slug}\". For the other project, create a new resource with a new logical id.`;\n }\n}\n\n/** Fields of GET /projects/{id}, PATCH /projects/{id}, and GET /teams/{team}/projects rows that the provider uses. */\nconst ProjectDetails = Schema.Struct({\n id: Schema.Number,\n name: Schema.String,\n slug: Schema.String,\n teamId: Schema.Number,\n teamSlug: Schema.String,\n prodDeploymentName: Schema.NullOr(Schema.String),\n});\ntype ProjectDetails = typeof ProjectDetails.Type;\n\n/** GET /teams/{team_id}/projects: one page of projects. */\nexport const ProjectPage = Schema.Struct({\n items: Schema.Array(ProjectDetails),\n pagination: Schema.Struct({\n hasMore: Schema.Boolean,\n nextCursor: Schema.optionalKey(Schema.NullOr(Schema.String)),\n }),\n});\n\n/** POST /teams/{team_id}/create_project. Only the id: everything else comes from GET /projects/{id}. */\nconst CreatedProject = Schema.Struct({ projectId: Schema.Number });\n\nconst DeploymentRow = Schema.Struct({\n name: Schema.String,\n deploymentType: Schema.String,\n isDefault: Schema.Boolean,\n deploymentUrl: Schema.String,\n /** Absent or null until the first push. */\n lastDeployTime: Schema.optionalKey(Schema.NullOr(Schema.Number)),\n});\nconst DeploymentRows = Schema.Array(DeploymentRow);\n\n/**\n * Fails with {@link ProjectDeploymentChange} when a create-time prop\n * changed. An omitted `deploymentType` means `prod`.\n */\nconst checkCreateTimeProps = (\n projectId: number,\n olds: Extract<ProjectProps, { name: string }>,\n news: Extract<ProjectProps, { name: string }>,\n) => {\n const oldType = olds.deploymentType ?? \"prod\";\n const newType = news.deploymentType ?? \"prod\";\n if (oldType !== newType) {\n return Effect.fail(\n new ProjectDeploymentChange({\n projectId,\n field: \"deploymentType\",\n current: oldType,\n requested: newType,\n }),\n );\n }\n if (olds.deploymentRegion !== news.deploymentRegion) {\n return Effect.fail(\n new ProjectDeploymentChange({\n projectId,\n field: \"deploymentRegion\",\n current: olds.deploymentRegion,\n requested: news.deploymentRegion,\n }),\n );\n }\n return Effect.void;\n};\n\n/** True when `team`, a slug or a numeric id, names the team of the project. */\nconst isTeamOf = (details: ProjectDetails, team: string | number) =>\n typeof team === \"number\" || /^\\d+$/.test(team)\n ? details.teamId === Number(team)\n : details.teamSlug === team;\n\n/** The row of the project's default production deployment, or undefined. */\nexport const prodDeploymentOf = (api: ManagementApiService, projectId: number) =>\n api\n .request(\"list deployments\", (client) =>\n client.GET(\"/projects/{project_id}/list_deployments\", {\n params: { path: { project_id: projectId } },\n }),\n )\n .pipe(\n Effect.map((rows) =>\n Schema.decodeUnknownSync(DeploymentRows)(rows).find(\n (row) => row.deploymentType === \"prod\" && row.isDefault,\n ),\n ),\n );\n\n/** GET /projects/{id}, or undefined after a 404. */\nexport const getProjectById = (api: ManagementApiService, projectId: number) =>\n absentAsUndefined(\n api.request(\"get project\", (client) =>\n client.GET(\"/projects/{project_id}\", { params: { path: { project_id: projectId } } }),\n ),\n ).pipe(\n Effect.map((body) =>\n body === undefined ? undefined : Schema.decodeUnknownSync(ProjectDetails)(body),\n ),\n );\n\n/**\n * Every project in the team with exactly this name, in the order of the\n * listing. Reads every page. `q` narrows the listing on the server, and the\n * exact match here decides. Pattern from Confect\n * `packages/alchemy/src/ConvexClient.ts` and `Project.ts`\n * (https://github.com/rjdellecese/confect, ISC license).\n */\nexport const listProjectsByName = (api: ManagementApiService, teamId: number, name: string) =>\n Effect.gen(function* () {\n const matches: ProjectDetails[] = [];\n const seenCursors = new Set<string>();\n let cursor: string | undefined;\n while (true) {\n const body = yield* api.request(\"list projects\", (client) =>\n client.GET(\"/teams/{team_id}/projects\", {\n params: {\n path: { team_id: teamId },\n query: { q: name, ...(cursor === undefined ? {} : { cursor }) },\n },\n }),\n );\n const page = Schema.decodeUnknownSync(ProjectPage)(body);\n matches.push(...page.items.filter((row) => row.name === name));\n if (!page.pagination.hasMore) break;\n const next = page.pagination.nextCursor;\n if (next === undefined || next === null || seenCursors.has(next)) {\n return yield* new ConvexApiError({\n operation: \"list projects\",\n status: 0,\n code: \"InvalidPagination\",\n message: `The project listing of team ${teamId} reports more pages but gives no new cursor. Convex.Project stops so that it does not miss a project named \"${name}\".`,\n });\n }\n seenCursors.add(next);\n cursor = next;\n }\n return matches;\n });\n\n/** The one project in the team with exactly this name, or undefined. More than one is an error. */\nexport const findProjectByName = (api: ManagementApiService, teamId: number, name: string) =>\n listProjectsByName(api, teamId, name).pipe(\n Effect.flatMap((matches) =>\n matches.length > 1\n ? new AmbiguousProject({ teamId, name, projectIds: matches.map((row) => row.id) })\n : Effect.succeed(matches[0]),\n ),\n );\n\n/**\n * POST /teams/{team_id}/create_project, then GET /projects/{id}. The identity\n * comes from the create response, never from a name lookup.\n */\nexport const createProject = (\n api: ManagementApiService,\n teamId: number,\n props: {\n readonly name: string;\n readonly deploymentType: \"prod\" | \"dev\";\n readonly deploymentRegion: DeploymentRegion | undefined;\n },\n) =>\n Effect.gen(function* () {\n const created = yield* api.request(\"create project\", (client) =>\n client.POST(\"/teams/{team_id}/create_project\", {\n params: { path: { team_id: teamId } },\n body: {\n projectName: props.name,\n deploymentType: props.deploymentType,\n ...(props.deploymentRegion === undefined\n ? {}\n : { deploymentRegion: props.deploymentRegion }),\n },\n }),\n );\n const { projectId } = Schema.decodeUnknownSync(CreatedProject)(created);\n const details = yield* getProjectById(api, projectId);\n if (details === undefined) return yield* new CreatedProjectNotFound({ projectId });\n return details;\n });\n\nexport const ProjectProvider = () =>\n Provider.effect(\n Project,\n Effect.gen(function* () {\n const api = yield* ManagementApi;\n\n const attributesOf = (details: ProjectDetails) =>\n prodDeploymentOf(api, details.id).pipe(\n Effect.map((prod): ProjectAttributes => ({\n projectId: details.id,\n slug: details.slug,\n name: details.name,\n teamId: details.teamId,\n prodDeploymentName: prod?.name ?? details.prodDeploymentName ?? undefined,\n prodDeploymentUrl: prod?.deploymentUrl,\n })),\n );\n\n const getById = (projectId: number) => getProjectById(api, projectId);\n\n /** The project with this slug in the team, or undefined. Official endpoint; the team can be a slug. */\n const getBySlug = (team: string | number, slug: string) =>\n absentAsUndefined(\n api.request(\"get project by slug\", (client) =>\n client.GET(\"/teams/{team_id_or_slug}/projects/{project_slug}\", {\n params: { path: { team_id_or_slug: String(team), project_slug: slug } },\n }),\n ),\n ).pipe(\n Effect.map((body) =>\n body === undefined ? undefined : Schema.decodeUnknownSync(ProjectDetails)(body),\n ),\n );\n\n const findByName = (teamId: number, name: string) => findProjectByName(api, teamId, name);\n\n /**\n * Brings an existing project to the desired name. The team cannot\n * change, so a project in another team fails.\n */\n const converge = (details: ProjectDetails, teamId: number, name: string) =>\n Effect.gen(function* () {\n if (details.teamId !== teamId) {\n return yield* new ProjectTeamChange({\n projectId: details.id,\n teamId: details.teamId,\n requestedTeamId: teamId,\n });\n }\n if (details.name === name) return yield* attributesOf(details);\n const updated = yield* api.request(\"update project\", (client) =>\n client.PATCH(\"/projects/{project_id}\", {\n params: { path: { project_id: details.id } },\n body: { name },\n }),\n );\n return yield* attributesOf(Schema.decodeUnknownSync(ProjectDetails)(updated));\n });\n\n return {\n stables: [\"projectId\", \"slug\", \"teamId\"],\n\n diff: Effect.fn(function* ({ olds, news, output }) {\n if (!isResolved(news)) return undefined;\n // Nothing exists yet, so nothing can be lost.\n if (output === undefined) return undefined;\n if (\"slug\" in news) {\n if (news.slug !== output.slug) {\n return yield* new ProjectSlugChange({\n projectId: output.projectId,\n slug: output.slug,\n requestedSlug: news.slug,\n });\n }\n if (olds.team !== news.team) {\n const details = yield* getById(output.projectId);\n if (details !== undefined && !isTeamOf(details, news.team)) {\n return yield* new ProjectTeamChange({\n projectId: output.projectId,\n teamId: output.teamId,\n requestedTeamId: yield* api.resolveTeamId(news.team),\n });\n }\n }\n // The resource changes nothing on the project.\n return { action: \"noop\" } as const;\n }\n // A deploymentType or deploymentRegion change fails in reconcile,\n // before any API call. Reconcile compares with the props of the last\n // successful deploy. Here, `olds` can be the props of a refused\n // update, so a check here would also refuse the props that fix it.\n if (olds.team !== news.team) {\n const requestedTeamId = yield* api.resolveTeamId(news.team);\n if (requestedTeamId !== output.teamId) {\n return yield* new ProjectTeamChange({\n projectId: output.projectId,\n teamId: output.teamId,\n requestedTeamId,\n });\n }\n }\n // Never \"replace\". A name change is an update; reconcile renames\n // the project with PATCH. Otherwise the engine compares the props.\n return \"name\" in olds && olds.name === news.name\n ? undefined\n : ({ action: \"update\" } as const);\n }),\n\n read: Effect.fn(function* ({ olds, output }) {\n if (output !== undefined) {\n const details = yield* getById(output.projectId);\n return details === undefined ? undefined : yield* attributesOf(details);\n }\n // No state: an existing project belongs to someone else until the\n // user passes --adopt. Convex has no ownership tags.\n const existing =\n \"slug\" in olds\n ? yield* getBySlug(olds.team, olds.slug)\n : yield* findByName(yield* api.resolveTeamId(olds.team), olds.name);\n return existing === undefined ? undefined : Unowned(yield* attributesOf(existing));\n }),\n\n reconcile: Effect.fn(function* ({ fqn, olds, news, output }) {\n if (\"slug\" in news) {\n // An existing project: found, checked, never created or changed.\n const details =\n output === undefined\n ? yield* getBySlug(news.team, news.slug)\n : yield* getById(output.projectId);\n if (details === undefined) {\n return yield* new ProjectNotFound({ team: String(news.team), slug: news.slug });\n }\n if (details.slug !== news.slug) {\n return yield* new ProjectSlugChange({\n projectId: details.id,\n slug: details.slug,\n requestedSlug: news.slug,\n });\n }\n if (!isTeamOf(details, news.team)) {\n return yield* new ProjectTeamChange({\n projectId: details.id,\n teamId: details.teamId,\n requestedTeamId: yield* api.resolveTeamId(news.team),\n });\n }\n if (output === undefined && !(yield* shouldAdopt(fqn))) {\n return yield* new OwnedBySomeoneElse({\n message: `Convex project ${details.id} (\"${news.slug}\") exists and is not in this stack's state. Re-run with --adopt to take it over.`,\n resourceType: Project.Type,\n physicalName: news.slug,\n });\n }\n return yield* attributesOf(details);\n }\n const teamId = yield* api.resolveTeamId(news.team);\n if (output !== undefined) {\n // State names the project. Never look it up by name here.\n if (olds !== undefined && \"name\" in olds) {\n yield* checkCreateTimeProps(output.projectId, olds, news);\n }\n if (output.teamId !== teamId) {\n return yield* new ProjectTeamChange({\n projectId: output.projectId,\n teamId: output.teamId,\n requestedTeamId: teamId,\n });\n }\n const details = yield* getById(output.projectId);\n if (details !== undefined) return yield* converge(details, teamId, news.name);\n // The project in state was deleted outside Alchemy. Creating a\n // new project below loses nothing.\n } else {\n // No state: a project with this name is someone else's unless\n // adoption is on. The engine checked this in plan; this check\n // covers a project that appeared after the plan.\n const existing = yield* findByName(teamId, news.name);\n if (existing !== undefined) {\n if (!(yield* shouldAdopt(fqn))) {\n return yield* new OwnedBySomeoneElse({\n message: `Convex project ${existing.id} in team ${teamId} already has the name \"${news.name}\". Re-run with --adopt to take it over, or use a different name.`,\n resourceType: Project.Type,\n physicalName: news.name,\n });\n }\n return yield* converge(existing, teamId, news.name);\n }\n }\n const details = yield* createProject(api, teamId, {\n name: news.name,\n deploymentType: news.deploymentType ?? \"prod\",\n deploymentRegion: news.deploymentRegion,\n });\n return yield* converge(details, teamId, news.name);\n }),\n\n // Runs only with `RemovalPolicy.destroy()`: the default policy is `retain`.\n delete: Effect.fn(function* ({ output }) {\n yield* absentAsUndefined(\n api.requestVoid(\"delete project\", (client) =>\n client.POST(\"/projects/{project_id}/delete\", {\n params: { path: { project_id: output.projectId } },\n }),\n ),\n );\n }),\n };\n }),\n );\n","// The provider collection users merge into a stack:\n// providers: Layer.mergeAll(Cloudflare.providers(), Convex.providers())\nimport * as Provider from \"alchemy/Provider\";\nimport * as Layer from \"effect/Layer\";\nimport { type Credentials, fromConfig } from \"./Credentials.ts\";\nimport { DeploymentProvider, DeploymentResource } from \"./Deployment.ts\";\nimport { ManagementApiLive } from \"./ManagementApi.ts\";\nimport { Project, ProjectProvider } from \"./Project.ts\";\n\nexport class Providers extends Provider.ProviderCollection<Providers>()(\"Convex\") {}\n\n/**\n * The Convex resource providers. Pass a credentials layer to override the\n * default lookup (`CONVEX_ACCESS_TOKEN`, then the Convex CLI login, and\n * `CONVEX_DEPLOY_KEY`).\n */\nexport const providers = (credentials: Layer.Layer<Credentials> = fromConfig()) =>\n Layer.effect(Providers, Provider.collection([Project, DeploymentResource])).pipe(\n Layer.provide(Layer.mergeAll(ProjectProvider(), DeploymentProvider())),\n Layer.provide(ManagementApiLive()),\n Layer.provide(credentials),\n Layer.orDie,\n );\n","// The run record: what the stage output says about the run that wrote it.\n// Alchemy state holds no time, author, commit, branch, or run (measured in\n// the Samebase research of 2026-10-21), so a state layer adds this record to\n// the output document under the reserved key `samebase.run`. The record\n// depends on no store: it comes from the GitHub Actions variables, or from\n// git on a laptop, and holds no secret. See docs/design/convex-state.md.\nimport { execFile } from \"node:child_process\";\nimport { readFile, realpath } from \"node:fs/promises\";\nimport { relative, sep } from \"node:path\";\nimport { promisify } from \"node:util\";\nimport * as Clock from \"effect/Clock\";\nimport * as Effect from \"effect/Effect\";\nimport * as Schema from \"effect/Schema\";\n\n/** The key of the record in the stage output document. */\nexport const RUN_RECORD_KEY = \"samebase.run\";\n\n/** The name of the stack file. Alchemy resolves `--config` against the working directory and does not expose it to a state layer, so the record assumes the default name. */\nexport const STACK_FILE_NAME = \"alchemy.run.ts\";\n\n/** Version 1 of the record. A reader validates `version` first. */\nexport interface RunRecord {\n readonly version: 1;\n /** GitHub `owner/name`. */\n readonly repository: string;\n /** Path of the stack file from the repository root, POSIX separators, such as `apps/samebase/alchemy.run.ts`. */\n readonly stackFile: string;\n /** The branch that was deployed: the head branch of a pull request, else the pushed branch. */\n readonly branch: string;\n /** The pull request whose head was deployed, or null for a push and for a laptop. */\n readonly pullRequest: number | null;\n /** The commit that was deployed: the head of the pull request, else GITHUB_SHA, else git HEAD. */\n readonly headCommit: string;\n /** The GitHub Actions run and attempt, or null for a laptop. */\n readonly runUrl: string | null;\n readonly source: \"github-actions\" | \"laptop\";\n /** ISO 8601, when the record was written. */\n readonly recordedAt: string;\n}\n\nexport class RunRecordError extends Schema.TaggedError<RunRecordError>()(\"RunRecordError\", {\n reason: Schema.String,\n}) {\n override get message() {\n return `The run record of the stage output cannot be made: ${this.reason}`;\n }\n}\n\n/** Where the run happens: the working directory of the stack and the process environment. */\nexport interface RunEnvironment {\n readonly cwd: string;\n readonly env: Readonly<Record<string, string | undefined>>;\n}\n\n/** The part of the GitHub Actions event payload that the record reads. A push event has no `pull_request`. */\nconst EventPayload = Schema.Struct({\n pull_request: Schema.optionalKey(\n Schema.Struct({ number: Schema.Number, head: Schema.Struct({ sha: Schema.String }) }),\n ),\n});\n\n/** `owner/name` of an https, ssh, or scp-like git URL with a host. A local path is not one. */\nconst REMOTE_URL = /^(?:[a-z+]+:\\/\\/[^/]+\\/|[^/@:]+@[^:/]+:)([^/]+)\\/([^/]+?)(?:\\.git)?\\/?$/;\n\nconst execFileAsync = promisify(execFile);\n\nconst now = Clock.currentTimeMillis.pipe(Effect.map((millis) => new Date(millis).toISOString()));\n\nconst git = (cwd: string, args: readonly string[]) =>\n Effect.tryPromise({\n try: async () =>\n (await execFileAsync(\"git\", [\"-C\", cwd, ...args], { encoding: \"utf8\" })).stdout.trim(),\n catch: (error) =>\n new RunRecordError({\n reason: `git ${args.join(\" \")} failed in ${cwd} (${error instanceof Error ? error.message.split(\"\\n\")[0] : String(error)})`,\n }),\n });\n\n/** The stack file from the repository root: the working directory below the git top level, plus {@link STACK_FILE_NAME}. */\nconst stackFileOf = (cwd: string) =>\n Effect.gen(function* () {\n const top = yield* git(cwd, [\"rev-parse\", \"--show-toplevel\"]);\n // git prints the real path, and the working directory can hold a symlink, such as macOS /tmp.\n const [realTop, realCwd] = yield* Effect.tryPromise({\n try: () => Promise.all([realpath(top), realpath(cwd)]),\n catch: () => new RunRecordError({ reason: `${cwd} is gone` }),\n });\n const directory = relative(realTop, realCwd)\n .split(sep)\n .filter((part) => part !== \"\");\n return [...directory, STACK_FILE_NAME].join(\"/\");\n });\n\nconst variable = (env: RunEnvironment[\"env\"], name: string) =>\n Effect.suspend(() => {\n const value = env[name];\n return value === undefined || value === \"\"\n ? Effect.fail(\n new RunRecordError({ reason: `GITHUB_ACTIONS is true, and ${name} is not set` }),\n )\n : Effect.succeed(value);\n });\n\nconst fromGitHubActions = (where: RunEnvironment) =>\n Effect.gen(function* () {\n const { env } = where;\n const repository = yield* variable(env, \"GITHUB_REPOSITORY\");\n const refName = yield* variable(env, \"GITHUB_REF_NAME\");\n const sha = yield* variable(env, \"GITHUB_SHA\");\n const serverUrl = yield* variable(env, \"GITHUB_SERVER_URL\");\n const runId = yield* variable(env, \"GITHUB_RUN_ID\");\n const runAttempt = yield* variable(env, \"GITHUB_RUN_ATTEMPT\");\n const eventPath = env[\"GITHUB_EVENT_PATH\"];\n const payload =\n eventPath === undefined || eventPath === \"\"\n ? undefined\n : yield* Effect.tryPromise({\n try: () => readFile(eventPath, \"utf8\"),\n catch: () =>\n new RunRecordError({ reason: `GITHUB_EVENT_PATH ${eventPath} cannot be read` }),\n }).pipe(\n Effect.flatMap(Schema.decodeUnknownEffect(Schema.fromJsonString(EventPayload))),\n Effect.mapError((error) =>\n error instanceof RunRecordError\n ? error\n : new RunRecordError({\n reason: `GITHUB_EVENT_PATH ${eventPath} is not an event payload`,\n }),\n ),\n );\n const pullRequest = payload?.pull_request;\n // GITHUB_SHA is the merge commit on a pull request event; the head of the pull request is what a person sees.\n const headCommit = pullRequest?.head.sha ?? sha;\n const headRef = env[\"GITHUB_HEAD_REF\"];\n const mergeRef = /^refs\\/pull\\/(\\d+)\\/merge$/.exec(env[\"GITHUB_REF\"] ?? \"\");\n const stackFile = yield* stackFileOf(where.cwd);\n const record: RunRecord = {\n version: 1,\n repository,\n stackFile,\n branch: headRef === undefined || headRef === \"\" ? refName : headRef,\n pullRequest: pullRequest?.number ?? (mergeRef === null ? null : Number(mergeRef[1])),\n headCommit,\n runUrl: `${serverUrl}/${repository}/actions/runs/${runId}/attempts/${runAttempt}`,\n source: \"github-actions\",\n recordedAt: yield* now,\n };\n return record;\n });\n\nconst fromGit = (where: RunEnvironment) =>\n Effect.gen(function* () {\n const { cwd } = where;\n const origin = yield* git(cwd, [\"remote\", \"get-url\", \"origin\"]);\n const match = REMOTE_URL.exec(origin);\n if (match === null) {\n return yield* new RunRecordError({\n reason: `the origin remote of ${cwd} is not a git URL with a host and owner/name: ${origin}`,\n });\n }\n const branch = yield* git(cwd, [\"rev-parse\", \"--abbrev-ref\", \"HEAD\"]);\n if (branch === \"HEAD\") {\n return yield* new RunRecordError({\n reason: `the checkout at ${cwd} is on no branch (detached HEAD)`,\n });\n }\n const record: RunRecord = {\n version: 1,\n repository: `${match[1]}/${match[2]}`,\n stackFile: yield* stackFileOf(cwd),\n branch,\n pullRequest: null,\n headCommit: yield* git(cwd, [\"rev-parse\", \"HEAD\"]),\n runUrl: null,\n source: \"laptop\",\n recordedAt: yield* now,\n };\n return record;\n });\n\n/**\n * The record of this run: from the GitHub Actions variables and the event\n * payload when GITHUB_ACTIONS is `true`, else from git in `cwd`, which needs\n * a branch and an `origin` remote with `owner/name`. Fails when a value is\n * missing; nothing is guessed.\n */\nexport const runRecord = (where: RunEnvironment): Effect.Effect<RunRecord, RunRecordError> =>\n where.env[\"GITHUB_ACTIONS\"] === \"true\" ? fromGitHubActions(where) : fromGit(where);\n\n/** A plain object, which a spread keeps whole. A Date, a Duration, or a Redacted value is an object too, and a spread loses it. */\nconst isPlainObject = (value: unknown): value is Record<string, unknown> => {\n if (typeof value !== \"object\" || value === null) return false;\n const prototype: unknown = Object.getPrototypeOf(value);\n return prototype === Object.prototype || prototype === null;\n};\n\n/**\n * The output document of a stage: the stack's output plus the record under\n * {@link RUN_RECORD_KEY}, or undefined for an output with no place for the\n * key: a string, an array, null, or an object that is not plain, such as a\n * Date. A value that the stack itself put under the key stays.\n */\nexport const withRunRecord = (output: unknown, record: RunRecord): object | undefined =>\n isPlainObject(output)\n ? RUN_RECORD_KEY in output\n ? output\n : { ...output, [RUN_RECORD_KEY]: record }\n : undefined;\n","// Alchemy state in Convex: `state: Convex.state({ team })` in `Alchemy.Stack`.\n//\n// One project for each Convex team, `alchemy-state`, holds the state of\n// every stack and stage of the team in its production deployment: the\n// tables `resources (stack, stage, fqn, value)` and `outputs (stack, stage,\n// value)` of the alchemyState component (src/store/component), served by the\n// functions of src/store/convex. The store lives\n// outside every resource that a stack manages, so a stack can create and\n// destroy its own project. See docs/design/convex-state.md.\n//\n// Bootstrap, on the first call of the run: the team token (CONVEX_ACCESS_TOKEN,\n// or the Convex CLI login) finds the project by name, or creates it; a deploy\n// key of its production deployment that can run internal queries and\n// mutations, and nothing else, is created for the run and deleted at its\n// end; the `state:version` query says whether the deployment has the store\n// of this version. Without one, or with an older one, the installed Convex\n// CLI pushes src/store/convex to it, with a push key that is deleted after\n// the push. The raw state functions are internal; authenticated readers get\n// repository-scoped subscriptions with secret values removed. A key that stops working during a\n// long run (it expires after two hours) is replaced once per call.\n//\n// Two first runs of a team can both create a project named `alchemy-state`.\n// The run whose project is not the oldest deletes its own, before it writes\n// anything, and uses the oldest: both runs end on one store.\n//\n// Samebase reads `stacks`, `getOutput`, `readStack`, and `reader:repository`\n// by name. The store and its readers are released and upgraded together:\n// STORE_VERSION rises with each change of a function, and a client works only\n// with a store of its own version. An older store is pushed over; a newer one\n// fails the run.\n//\n// The stage output that `setOutput` stores is the stack's output plus the\n// run record of src/RunRecord.ts under the key `samebase.run`: the\n// repository, stack file, branch, pull request, commit, and run that wrote\n// the stage. `getOutput` gives the document back as stored.\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport * as Clock from \"effect/Clock\";\nimport * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\nimport * as ChildProcessSpawner from \"effect/process/ChildProcessSpawner\";\nimport * as Redacted from \"effect/Redacted\";\nimport * as Schedule from \"effect/Schedule\";\nimport * as Schema from \"effect/Schema\";\nimport * as Scope from \"effect/Scope\";\nimport {\n encodeState,\n type PersistedState,\n type ReplacedResourceState,\n reviveState,\n State,\n type StateService,\n STATE_STORE_VERSION,\n StateStoreError,\n} from \"alchemy/State\";\nimport { fromConfig } from \"./Credentials.ts\";\nimport { ProductionDeploymentNotFound } from \"./Deployment.ts\";\nimport {\n absentAsUndefined,\n ManagementApi,\n ManagementApiLive,\n type ManagementApiService,\n retryIdempotentWrite,\n} from \"./ManagementApi.ts\";\nimport {\n createProject,\n findProjectByName,\n listProjectsByName,\n prodDeploymentOf,\n} from \"./Project.ts\";\nimport {\n createDeployKey,\n deleteDeployKey,\n installedCli,\n push,\n PUSH_KEY_ACTIONS,\n withPushKey,\n} from \"./Push.ts\";\nimport { type RunRecord, runRecord, withRunRecord } from \"./RunRecord.ts\";\nimport { STORE_VERSION } from \"./store/convex/version.ts\";\n\n/** The name of the state project in each team. */\nexport const STORE_PROJECT_NAME = \"alchemy-state\";\n\n/**\n * The actions of the key of one run: the internal queries and mutations of\n * the store, nothing else. Measured: `deployment:data:view` and\n * `deployment:data:write` do not run an internal function.\n */\nexport const RUN_KEY_ACTIONS = [\n \"deployment:functions:runInternalQueries\",\n \"deployment:functions:runInternalMutations\",\n] as const;\n\n/** The body of POST /api/function, with HTTP 200 for a function error too. */\nconst Reply = Schema.Union([\n Schema.Struct({ status: Schema.Literal(\"success\"), value: Schema.Unknown }),\n Schema.Struct({ status: Schema.Literal(\"error\"), errorMessage: Schema.String }),\n]);\ntype Reply = typeof Reply.Type;\n\n/** The error reply of /api/function for a function that the deployment does not have (recorded). */\nconst MISSING_FUNCTION = /Could not find function for '/;\n\n/** HTTP 401 or 403 from the function API: the key is gone or expired (recorded: 403 without a key). */\nconst isUnauthorized = (error: StateStoreError) =>\n error.http?.status === 401 || error.http?.status === 403;\n\nconst failure = (message: string) => new StateStoreError({ message: `Convex state: ${message}` });\n\n/** No reply, HTTP 429, or HTTP 5xx: a new attempt can succeed. Every call of the store is idempotent. */\nconst isTransient = (error: StateStoreError) =>\n error.http !== undefined &&\n (error.http.status === undefined || error.http.status === 429 || error.http.status >= 500);\n\nconst post = (\n url: string,\n headers: Record<string, string>,\n body: unknown,\n): Effect.Effect<unknown, StateStoreError> =>\n Effect.tryPromise({\n try: () =>\n fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", ...headers },\n body: JSON.stringify(body),\n }),\n catch: () => new StateStoreError({ message: `Convex state: POST ${url} failed`, http: {} }),\n }).pipe(\n Effect.flatMap((response) =>\n response.ok || response.status === 560\n ? Effect.tryPromise({\n try: (): Promise<unknown> => response.json(),\n catch: () => failure(`${url} gave no JSON`),\n })\n : Effect.fail(\n new StateStoreError({\n message: `Convex state: POST ${url} failed with HTTP ${response.status}`,\n http: { status: response.status },\n }),\n ),\n ),\n Effect.retry({\n while: isTransient,\n schedule: Schedule.exponential(\"100 millis\").pipe(Schedule.jittered),\n times: 5,\n }),\n );\n\nconst decode =\n <S extends Schema.Codec<unknown, unknown>>(schema: S, what: string) =>\n (value: unknown) =>\n Schema.decodeUnknownEffect(schema)(value).pipe(Effect.mapError(() => failure(`bad ${what}`)));\n\n/** The function API of the store deployment, with a deploy key. */\nexport interface FunctionApi {\n /** POST /api/function, the call that `convex run` makes: the reply, which can be a function error. */\n readonly call: (\n path: string,\n args: Record<string, string | RunRecord | undefined>,\n ) => Effect.Effect<Reply, StateStoreError>;\n}\n\nexport const makeFunctionApi = (url: string, key: Redacted.Redacted<string>): FunctionApi => ({\n call: (path, args) =>\n post(\n `${url}/api/function`,\n { Authorization: `Convex ${Redacted.value(key)}` },\n { path, args, format: \"json\" },\n ).pipe(Effect.flatMap(decode(Reply, `reply of ${path}`))),\n});\n\n/** The value of a reply, or the Convex message, which names the function and the cause, such as a missing key action. */\nconst valueOf = (reply: Reply) =>\n reply.status === \"success\"\n ? Effect.succeed(reply.value)\n : Effect.fail(failure(reply.errorMessage.trim()));\n\n/** The functions of the store with Alchemy's encoding: the JSON text of encodeState. */\nconst remoteOf = (api: FunctionApi, record: RunRecord | undefined) => {\n const run = (name: string, args: Record<string, string | RunRecord | undefined>) =>\n api.call(`state:${name}`, args).pipe(Effect.flatMap(valueOf));\n const write = (name: string, args: Record<string, string>) =>\n Effect.gen(function* () {\n const currentRun =\n record === undefined\n ? undefined\n : {\n ...record,\n recordedAt: new Date(yield* Clock.currentTimeMillis).toISOString(),\n };\n return yield* run(name, { ...args, run: currentRun });\n });\n const strings = (name: string, args: Record<string, string>) =>\n run(name, args).pipe(Effect.flatMap(decode(Schema.Array(Schema.String), name)));\n const optional = (name: string, args: Record<string, string>) =>\n run(name, args).pipe(Effect.flatMap(decode(Schema.NullOr(Schema.String), name)));\n const encode = (value: unknown) => JSON.stringify(encodeState(value));\n return {\n listStacks: () => strings(\"stacks\", {}),\n listStages: (stack: string) => strings(\"stages\", { stack }),\n list: (r: { stack: string; stage: string }) =>\n strings(\"list\", { stack: r.stack, stage: r.stage }),\n // Like Alchemy's own stores, the store gives back the state that it got.\n get: (r: { stack: string; stage: string; fqn: string }) =>\n optional(\"get\", { stack: r.stack, stage: r.stage, fqn: r.fqn }).pipe(\n Effect.map((text): PersistedState | undefined =>\n text === null ? undefined : JSON.parse(text, reviveState),\n ),\n ),\n getReplacedResources: (r: { stack: string; stage: string }) =>\n strings(\"replaced\", { stack: r.stack, stage: r.stage }).pipe(\n Effect.map((texts) =>\n texts.map((text): ReplacedResourceState => JSON.parse(text, reviveState)),\n ),\n ),\n getOutput: (r: { stack: string; stage: string }) =>\n optional(\"getOutput\", { stack: r.stack, stage: r.stage }).pipe(\n Effect.map((text): unknown => (text === null ? undefined : JSON.parse(text, reviveState))),\n ),\n set: (r: { stack: string; stage: string; fqn: string; value: PersistedState }) =>\n write(\"set\", { stack: r.stack, stage: r.stage, fqn: r.fqn, value: encode(r.value) }),\n delete: (r: { stack: string; stage: string; fqn: string }) =>\n write(\"remove\", { stack: r.stack, stage: r.stage, fqn: r.fqn }),\n deleteStack: (r: { stack: string; stage?: string }) =>\n run(\"removeStack\", { stack: r.stack, stage: r.stage }),\n setOutput: (r: { stack: string; stage: string; value: unknown }) =>\n write(\"setOutput\", { stack: r.stack, stage: r.stage, value: encode(r.value) }),\n };\n};\n\n/** The version that the store answers, or undefined when the deployment has no `state:version`. */\nconst storeVersion = (api: FunctionApi) =>\n api\n .call(\"state:version\", {})\n .pipe(\n Effect.flatMap((reply) =>\n reply.status === \"error\" && MISSING_FUNCTION.test(reply.errorMessage)\n ? Effect.succeed(undefined)\n : valueOf(reply).pipe(Effect.flatMap(decode(Schema.Number, \"store version\"))),\n ),\n );\n\n/**\n * The functions directory of the store app, `src/store/convex` of this\n * package. This file is `src/State.ts` in a checkout and a chunk in `lib/`\n * in the installed package, which ships `src` too, so the directory is\n * `../src/store/convex` from either place. Its `convex.config.ts` mounts the\n * alchemyState component of `src/store/component`, inside the same push root.\n */\nexport const storeDirectory = () =>\n join(dirname(fileURLToPath(import.meta.url)), \"..\", \"src\", \"store\", \"convex\");\n\nexport interface StoreOptions {\n /** Team slug or numeric team id of the `alchemy-state` project, or undefined with a team access token, which names its team. */\n readonly team: string | number | undefined;\n readonly api: ManagementApiService;\n readonly spawner: ChildProcessSpawner.ChildProcessSpawner[\"Service\"];\n /** The key of the run is deleted when this scope closes. */\n readonly scope: Scope.Scope;\n /** The functions directory that an outdated store gets: {@link storeDirectory}. */\n readonly store: string;\n /** The run recorded with resource writes and output, or undefined for a run without one. */\n readonly run: RunRecord | undefined;\n}\n\n/**\n * Pushes `store` to the production deployment of the state project with the\n * installed Convex CLI: no typecheck, no codegen, the key only in the\n * environment of the CLI.\n */\nconst pushStore = (\n options: StoreOptions,\n deployment: { readonly name: string; readonly deploymentUrl: string },\n) =>\n Effect.gen(function* () {\n const cli = yield* installedCli(join(options.store, \"..\"));\n yield* Effect.logInfo(\n `Convex state: pushing the store version ${STORE_VERSION} to ${deployment.name}`,\n );\n yield* withPushKey(options.api, deployment.name, PUSH_KEY_ACTIONS, (key) =>\n push(options.spawner, key, {\n deployment: deployment.name,\n url: deployment.deploymentUrl,\n rootDir: join(options.store, \"..\"),\n source: {\n path: options.store,\n command: [...cli, \"deploy\", \"--typecheck\", \"disable\", \"--codegen\", \"disable\"],\n },\n env: {},\n previousEnvNames: [],\n adopt: false,\n previewName: undefined,\n }),\n );\n });\n\n/**\n * Creates the state project of the team. Two first runs can both create one:\n * the run whose project is not the oldest deletes its own, which holds\n * nothing yet, and uses the oldest, so that every run ends on one store.\n */\nconst createStoreProject = (api: ManagementApiService, teamId: number, team: string | number) =>\n Effect.gen(function* () {\n yield* Effect.logInfo(\n `Convex state: creating the project ${STORE_PROJECT_NAME} in team ${team}`,\n );\n const created = yield* createProject(api, teamId, {\n name: STORE_PROJECT_NAME,\n deploymentType: \"prod\",\n deploymentRegion: undefined,\n });\n const all = yield* listProjectsByName(api, teamId, STORE_PROJECT_NAME);\n const oldest = all.reduce((a, b) => (b.id < a.id ? b : a), created);\n if (oldest.id === created.id) return created;\n yield* Effect.logInfo(\n `Convex state: another run created ${STORE_PROJECT_NAME} ${oldest.id} first; project ${created.id} is deleted again.`,\n );\n yield* absentAsUndefined(\n retryIdempotentWrite(\n api.requestVoid(\"delete project\", (client) =>\n client.POST(\"/projects/{project_id}/delete\", {\n params: { path: { project_id: created.id } },\n }),\n ),\n ),\n );\n return oldest;\n });\n\n/**\n * The StateService over the `alchemy-state` project of the team: found or\n * created, its store pushed when it is missing or older, and read and\n * written with the keys of this run.\n */\nexport const makeConvexState = (options: StoreOptions) =>\n Effect.gen(function* () {\n const { api } = options;\n const teamId = yield* api.resolveTeamId(options.team);\n const team = options.team ?? teamId;\n const found = yield* findProjectByName(api, teamId, STORE_PROJECT_NAME);\n const project = found ?? (yield* createStoreProject(api, teamId, team));\n const deployment = yield* prodDeploymentOf(api, project.id);\n if (deployment === undefined) {\n return yield* new ProductionDeploymentNotFound({ projectId: project.id });\n }\n\n // The keys of this run, deleted together when the scope closes. A call\n // that the current key no longer authorizes gets one new key and one\n // more attempt.\n const keys: Redacted.Redacted<string>[] = [];\n yield* Scope.addFinalizer(\n options.scope,\n Effect.suspend(() =>\n Effect.forEach(keys, (key) => deleteDeployKey(api, deployment.name, key), {\n discard: true,\n }),\n ),\n );\n const mint = createDeployKey(api, deployment.name, \"alchemy-state\", RUN_KEY_ACTIONS).pipe(\n Effect.map((key) => {\n keys.push(key);\n return makeFunctionApi(deployment.deploymentUrl, key);\n }),\n Effect.mapError((error) => failure(`no key for ${deployment.name}: ${error.message}`)),\n );\n let current = yield* mint;\n const functions: FunctionApi = {\n call: (path, args) =>\n current.call(path, args).pipe(\n Effect.catchIf(isUnauthorized, () =>\n mint.pipe(\n Effect.flatMap((next) => {\n current = next;\n return next.call(path, args);\n }),\n ),\n ),\n ),\n };\n\n let version = yield* storeVersion(functions);\n if (version === undefined || version < STORE_VERSION) {\n // Code without `state:version` is another app with the name of the store.\n if (version === undefined && deployment.lastDeployTime) {\n return yield* failure(\n `project ${STORE_PROJECT_NAME} (${project.id}) of team ${team} has code that is not the state store, and Convex.state does not push over it. Rename that project in the Convex dashboard.`,\n );\n }\n // Another run can push a newer store in the meantime: read again right\n // before the push. The push itself has no lock (see the design note).\n version = yield* storeVersion(functions);\n if (version === undefined || version < STORE_VERSION) {\n yield* pushStore(options, deployment);\n version = yield* storeVersion(functions);\n }\n }\n if (version !== STORE_VERSION) {\n return yield* failure(\n `${deployment.name} answers store version ${version ?? \"none\"}, and this package needs store version ${STORE_VERSION}.`,\n );\n }\n\n const remote = remoteOf(functions, options.run);\n /** The stack's output plus the record, when the run has one and the output has a place for it. */\n const documentOf = (request: { stack: string; stage: string; value: unknown }) =>\n Effect.gen(function* () {\n const { run } = options;\n if (run === undefined) return request.value;\n const recordedAt = new Date(yield* Clock.currentTimeMillis).toISOString();\n const document = withRunRecord(request.value, { ...run, recordedAt });\n if (document === undefined) {\n yield* Effect.logWarning(\n `Convex state: the output of ${request.stack}/${request.stage} is not a plain object, so it carries no run record.`,\n );\n return request.value;\n }\n return document;\n });\n const service: StateService = {\n id: \"convex\",\n getVersion: () => Effect.succeed(STATE_STORE_VERSION),\n listStacks: remote.listStacks,\n listStages: remote.listStages,\n list: remote.list,\n get: remote.get,\n getReplacedResources: remote.getReplacedResources,\n getOutput: remote.getOutput,\n set: (request) => remote.set(request).pipe(Effect.as(request.value)),\n delete: (request) => remote.delete(request).pipe(Effect.asVoid),\n deleteStack: (request) => remote.deleteStack(request).pipe(Effect.asVoid),\n // The document is the stack's output plus the record under `samebase.run`.\n setOutput: (request) =>\n Effect.gen(function* () {\n const value = yield* documentOf(request);\n yield* remote.setOutput({ stack: request.stack, stage: request.stage, value });\n return value;\n }),\n };\n return service;\n });\n\n/**\n * Alchemy state in the `alchemy-state` project of `team`, with the team token\n * in CONVEX_ACCESS_TOKEN or the Convex CLI login. A team access token names\n * its team, so `team` is optional with one; the Convex CLI login needs the\n * slug or the id. The first use of the run finds or creates the project and\n * pushes the store when it is missing or older. `alchemy plan` on another\n * stack never touches Convex.\n */\nexport const state = (\n options: { readonly team?: string | number } = {},\n): Layer.Layer<State, never, ChildProcessSpawner.ChildProcessSpawner> =>\n Layer.effect(\n State,\n Effect.gen(function* () {\n const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;\n const scope = yield* Scope.Scope;\n // The stack's ConfigProvider, for the read of the token on first use.\n const context = yield* Effect.context<never>();\n return yield* Effect.cached(\n Effect.gen(function* () {\n const api = yield* ManagementApi.pipe(\n Effect.provide(ManagementApiLive().pipe(Layer.provide(fromConfig()))),\n );\n // The record is derived once, before the first read. A checkout\n // that gives none, such as a tarball without git, a checkout\n // without origin, or a detached HEAD, still reads, plans, and\n // destroys: its outputs are written without the record, and the\n // log says why.\n const run = yield* runRecord({ cwd: process.cwd(), env: process.env }).pipe(\n Effect.catch((error) =>\n Effect.logWarning(\n `Convex state: the stage outputs of this run carry no record. ${error.message}`,\n ).pipe(Effect.as(undefined)),\n ),\n );\n return yield* makeConvexState({\n team: options.team,\n api,\n spawner,\n scope,\n store: storeDirectory(),\n run,\n });\n }).pipe(Effect.provideContext(context), Effect.orDie),\n );\n }),\n );\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["valueOf","DeploymentRow","DeploymentRows"],"sources":["../src/Component.ts","../src/Credentials.ts","../src/Adoption.ts","../src/ManagementApi.ts","../src/Push.ts","../src/Deployment.ts","../src/Project.ts","../src/Providers.ts","../src/RunRecord.ts","../src/State.ts"],"sourcesContent":["import { toPath } from \"alchemy/FQN\";\nimport type { NamespaceNode } from \"alchemy/Namespace\";\nimport { Stack } from \"alchemy/Stack\";\nimport * as Effect from \"effect/Effect\";\nimport * as Schema from \"effect/Schema\";\nimport type { Deployment } from \"./Deployment.ts\";\n\n/** A component's resources occupy this namespace in the deployment's Alchemy stack and stage. */\nexport interface ComponentBinding {\n readonly type: \"component\";\n readonly path: string;\n readonly namespace: readonly string[];\n}\n\n/**\n * Associate a native namespace with an installed component. `component` is the\n * installed name from the app's `convex.config.ts`; a nested install joins the\n * names with slashes, such as `\"workspace/mail\"`. An undefined namespace\n * associates the stack root. This records display metadata; it does not install\n * the component, set its environment, or change removal policies.\n */\nexport const bindComponent = (options: {\n deployment: Deployment;\n component: string;\n namespace: NamespaceNode | undefined;\n}) =>\n Effect.gen(function* () {\n if (options.component === \"\") {\n return yield* Effect.die(new Error(\"The component name is empty.\"));\n }\n const namespace = toPath(options.namespace);\n const sid = `convex.component:${JSON.stringify(namespace)}`;\n const stack = yield* Stack;\n const previous = stack.bindings[options.deployment.FQN]?.find((binding) => binding.sid === sid);\n // Alchemy keeps the last binding with a given sid. Reject conflicting owners before that happens.\n if (previous !== undefined) {\n const existing = Schema.decodeUnknownSync(Schema.Struct({ path: Schema.String }))(\n previous.data,\n );\n if (existing.path !== options.component) {\n return yield* Effect.die(\n new Error(\n `Alchemy namespace ${JSON.stringify(namespace)} is already bound to ${existing.path}.`,\n ),\n );\n }\n return;\n }\n yield* options.deployment.bind(sid, {\n type: \"component\",\n path: options.component,\n namespace,\n });\n });\n","// Convex credentials for the provider, by scope.\n//\n// - The access token works on the Management API: a team access token, an\n// OAuth token, or the Convex CLI login. Convex.Project needs it. A\n// Convex.Deployment needs it only when the deploy key does not fit.\n// - The deploy key is optional. A deploy key of one deployment\n// (`prod:<name>|...`, `dev:<name>|...`) lets Convex.Deployment set\n// variables and push to that deployment with no access token. A preview\n// deploy key of a project (`preview:<team>:<project>|...`) lets it create,\n// push to, and delete preview deployments of that project with no access\n// token.\n//\n// Credentials are a layer, never props: they do not go into Alchemy state.\n// Both values are Effects, so that building the providers layer never touches\n// the environment or the filesystem. A value is read on the first call that\n// needs it, which keeps `alchemy plan` on an unrelated stack free of Convex\n// credential errors.\nimport { readFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport * as Config from \"effect/Config\";\nimport * as Context from \"effect/Context\";\nimport * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\nimport * as Option from \"effect/Option\";\nimport * as Redacted from \"effect/Redacted\";\nimport * as Result from \"effect/Result\";\nimport * as Schema from \"effect/Schema\";\n\nexport interface ResolvedCredentials {\n /** Bearer token accepted by https://api.convex.dev/v1: a team access token, an OAuth token, or the Convex CLI login. */\n readonly accessToken: Redacted.Redacted<string>;\n /** Where the token came from, for error messages only. */\n readonly source: \"env\" | \"explicit\" | \"convex-cli-login\";\n}\n\nexport interface CredentialsService {\n /** The Management API token. Dies when there is none. */\n readonly accessToken: Effect.Effect<ResolvedCredentials>;\n /** True when there is a Management API token. */\n readonly hasAccessToken: Effect.Effect<boolean>;\n /** A deploy key or a preview deploy key, or undefined. */\n readonly deployKey: Effect.Effect<Redacted.Redacted<string> | undefined>;\n}\n\nexport class Credentials extends Context.Service<Credentials, CredentialsService>()(\n \"@samebase/alchemy-convex/Credentials\",\n) {}\n\n/** Environment variable for the access token, read by {@link fromConfig}. */\nexport const ACCESS_TOKEN_ENV = \"CONVEX_ACCESS_TOKEN\";\n\n/** Environment variable for the deploy key, read by {@link fromConfig}. The Convex CLI reads the same name. */\nexport const DEPLOY_KEY_ENV = \"CONVEX_DEPLOY_KEY\";\n\n/** The Convex CLI stores its device login here after `npx convex login`. */\nexport const convexCliConfigPath = () => join(homedir(), \".convex\", \"config.json\");\n\nconst CliConfig = Schema.Struct({ accessToken: Schema.String });\n\nexport class CredentialsError extends Schema.TaggedError<CredentialsError>()(\"CredentialsError\", {\n reason: Schema.String,\n}) {}\n\n/**\n * Token the Convex CLI saved on this machine. It works on the Management API\n * for the teams the logged-in user belongs to. Fails when nobody is logged in.\n */\nexport const readConvexCliLogin: Effect.Effect<ResolvedCredentials, CredentialsError> = Effect.gen(\n function* () {\n const path = convexCliConfigPath();\n const text = yield* Effect.tryPromise({\n try: () => readFile(path, \"utf8\"),\n catch: () =>\n new CredentialsError({\n reason: `This step needs the Convex Management API. Set ${ACCESS_TOKEN_ENV} to a team access token, or run \\`npx convex login\\`. There is no Convex CLI login at ${path}.`,\n }),\n });\n const parsed = yield* Schema.decodeUnknownEffect(Schema.fromJsonString(CliConfig))(text).pipe(\n Effect.mapError(() => new CredentialsError({ reason: `${path} has no accessToken` })),\n );\n return { accessToken: Redacted.make(parsed.accessToken), source: \"convex-cli-login\" } as const;\n },\n);\n\n/**\n * Default resolution through the stack ConfigProvider (process env, `.env`,\n * stack secrets): `CONVEX_ACCESS_TOKEN`, then the Convex CLI login on this\n * machine, for the access token; `CONVEX_DEPLOY_KEY` for the deploy key. A\n * developer who ran `npx convex login` needs nothing. CI sets only the\n * deploy key when the stack pushes to deployments that exist, and the access\n * token when the stack also creates projects or deployments.\n */\nexport const fromConfig = (): Layer.Layer<Credentials> =>\n Layer.effect(\n Credentials,\n Effect.gen(function* () {\n const resolved = yield* Effect.cached(\n Config.Redacted(ACCESS_TOKEN_ENV).pipe(\n Effect.map((token): ResolvedCredentials => ({ accessToken: token, source: \"env\" })),\n Effect.catch(() => readConvexCliLogin),\n Effect.result,\n ),\n );\n const deployKey = yield* Effect.cached(\n Config.option(Config.Redacted(DEPLOY_KEY_ENV)).pipe(\n Effect.map(Option.getOrUndefined),\n Effect.orDie,\n ),\n );\n return {\n accessToken: resolved.pipe(Effect.flatMap(Effect.fromResult), Effect.orDie),\n hasAccessToken: resolved.pipe(Effect.map(Result.isSuccess)),\n deployKey,\n };\n }),\n );\n\n/** Explicit values, for tests or callers that already hold them. */\nexport const fromValues = (values: {\n readonly accessToken?: Redacted.Redacted<string>;\n readonly deployKey?: Redacted.Redacted<string>;\n}): Layer.Layer<Credentials> =>\n Layer.succeed(Credentials, {\n accessToken:\n values.accessToken === undefined\n ? Effect.die(\n new CredentialsError({\n reason:\n \"This step needs the Convex Management API, and fromValues got no accessToken.\",\n }),\n )\n : Effect.succeed({ accessToken: values.accessToken, source: \"explicit\" } as const),\n hasAccessToken: Effect.succeed(values.accessToken !== undefined),\n deployKey: Effect.succeed(values.deployKey),\n });\n","// Adoption check for reconcile.\n//\n// The engine checks ownership during plan: `read` returns `Unowned(...)` for\n// an object that is not in state, and the engine then needs `--adopt`. A\n// reconcile without state can still find an existing object, for example\n// after a replacement, after an interrupted create, or when another run\n// created it between plan and apply. Reconcile takes that object over only\n// when adoption is on. The order is the same as in the engine: the\n// resource's own `adopt(...)`, then the AdoptPolicy service, then the\n// `--adopt` flag in AlchemyContext.\n//\n// Pattern from Confect, `packages/alchemy/src/internal/Lifecycle.ts`\n// (https://github.com/rjdellecese/confect, ISC license).\nimport { AdoptPolicy } from \"alchemy/AdoptPolicy\";\nimport { AlchemyContext } from \"alchemy/AlchemyContext\";\nimport { Stack } from \"alchemy/Stack\";\nimport * as Effect from \"effect/Effect\";\nimport * as Option from \"effect/Option\";\n\n/** True when the resource `fqn` may take over an object that is not in state. */\nexport const shouldAdopt = (fqn: string): Effect.Effect<boolean> =>\n Effect.gen(function* () {\n const stack = yield* Effect.serviceOption(Stack);\n const own = Option.isSome(stack) ? stack.value.resources[fqn]?.Adopt : undefined;\n if (own !== undefined) return own;\n const policy = yield* Effect.serviceOption(AdoptPolicy);\n if (Option.isSome(policy)) return policy.value;\n const context = yield* Effect.serviceOption(AlchemyContext);\n return Option.isSome(context) && context.value.adopt;\n });\n","// Effect wrapper around the official Convex platform client.\n//\n// `@convex-dev/platform` is an openapi-fetch client: every call resolves to\n// `{ data, error, response }`. This service turns that into an Effect with one\n// typed error, resolves credentials lazily, and validates the fields the\n// provider relies on at runtime.\nimport { createDeploymentClient, createManagementClient } from \"@convex-dev/platform\";\nimport * as Context from \"effect/Context\";\nimport * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\nimport * as Redacted from \"effect/Redacted\";\nimport * as Schedule from \"effect/Schedule\";\nimport * as Schema from \"effect/Schema\";\nimport { Credentials, type ResolvedCredentials } from \"./Credentials.ts\";\n\nexport type ManagementClient = ReturnType<typeof createManagementClient>;\nexport type DeploymentClient = ReturnType<typeof createDeploymentClient>;\n\n/** Shape of every openapi-fetch result we consume. */\nexport interface FetchResult<T> {\n readonly data?: T;\n readonly error?: unknown;\n readonly response: Response;\n}\n\n/**\n * One error for every control-plane and deployment call. Resources branch on\n * `status` (404 means absent for read and delete), so the class is load\n * bearing, not decorative.\n */\nexport class ConvexApiError extends Schema.TaggedError<ConvexApiError>()(\"ConvexApiError\", {\n operation: Schema.String,\n status: Schema.Number,\n code: Schema.optionalKey(Schema.String),\n message: Schema.String,\n}) {}\n\nconst ErrorBody = Schema.Struct({\n code: Schema.optionalKey(Schema.String),\n message: Schema.optionalKey(Schema.String),\n});\n\nconst toApiError = (operation: string, result: FetchResult<unknown>) => {\n const body = Schema.decodeUnknownSync(Schema.NullishOr(ErrorBody))(result.error ?? null);\n const code = body?.code;\n return new ConvexApiError({\n operation,\n status: result.response.status,\n ...(code === undefined ? {} : { code }),\n message: body?.message ?? `${operation} failed with HTTP ${result.response.status}`,\n });\n};\n\nexport interface ManagementApiService {\n /** Run one management call with the resolved credentials. */\n readonly request: <T>(\n operation: string,\n run: (client: ManagementClient) => Promise<FetchResult<T>>,\n ) => Effect.Effect<T, ConvexApiError>;\n /** Run one management call whose success response has no body. */\n readonly requestVoid: (\n operation: string,\n run: (client: ManagementClient) => Promise<FetchResult<unknown>>,\n ) => Effect.Effect<void, ConvexApiError>;\n /** Run one deployment-scoped call authenticated with a deploy key. */\n readonly deploymentRequest: <T>(\n operation: string,\n deploymentUrlOrName: string,\n deployKey: Redacted.Redacted<string>,\n run: (client: DeploymentClient) => Promise<FetchResult<T>>,\n ) => Effect.Effect<T, ConvexApiError>;\n /**\n * Team id for a numeric id, a slug, or nothing. A team access token names\n * its team (`GET /token_details`); a slug is then checked against the\n * `teamSlug` of the team's projects, so a token of another team fails. The\n * Convex CLI login and a personal token answer 403 there, so a slug goes to\n * the dashboard's team list, and nothing is an error.\n */\n readonly resolveTeamId: (\n team: string | number | undefined,\n ) => Effect.Effect<number, ConvexApiError>;\n /**\n * True when a deploy key that Convex returned carries the token of the\n * Management API credential itself. With an OAuth token, create_deploy_key\n * and create_preview_deploy_key create no new key: they return the OAuth\n * token with a new prefix, and the part after \"|\" is the same. A delete of\n * that key would revoke the credential.\n */\n readonly isCredentialToken: (secret: string) => Effect.Effect<boolean>;\n /**\n * The same calls with another bearer token, such as a preview deploy key,\n * which the Management API takes for the preview deployments of its project.\n */\n readonly withToken: (token: Redacted.Redacted<string>) => ManagementApiService;\n}\n\n/** The part of a Convex token after the first \"|\", or the whole value when it has none. */\nconst tokenPart = (value: string) => value.slice(value.indexOf(\"|\") + 1);\n\nexport class ManagementApi extends Context.Service<ManagementApi, ManagementApiService>()(\n \"@samebase/alchemy-convex/ManagementApi\",\n) {}\n\nconst attempt = <T>(operation: string, run: () => Promise<FetchResult<T>>) =>\n Effect.tryPromise({\n try: run,\n catch: (cause) =>\n new ConvexApiError({\n operation,\n status: 0,\n message: cause instanceof Error ? cause.message : String(cause),\n }),\n });\n\n/** Reads `data` or fails with the HTTP status and the API's own code and message. */\nexport const settle = <T>(\n operation: string,\n run: () => Promise<FetchResult<T>>,\n): Effect.Effect<T, ConvexApiError> =>\n attempt(operation, run).pipe(\n Effect.flatMap((result) =>\n result.response.ok && result.data !== undefined\n ? Effect.succeed(result.data)\n : Effect.fail(toApiError(operation, result)),\n ),\n );\n\n/** For endpoints that answer with an empty body, such as delete calls. */\nexport const settleVoid = (\n operation: string,\n run: () => Promise<FetchResult<unknown>>,\n): Effect.Effect<void, ConvexApiError> =>\n attempt(operation, run).pipe(\n Effect.flatMap((result) =>\n result.response.ok ? Effect.void : Effect.fail(toApiError(operation, result)),\n ),\n );\n\n/**\n * True when an idempotent write can succeed on a new attempt:\n *\n * - A Convex write conflict. Two parallel update_environment_variables calls\n * on one deployment gave HTTP 503 `OptimisticConcurrencyControlFailure`,\n * \"Data read or written in this mutation changed while it was being run\",\n * in a live run. The platform codes `OCC` and `WriteConflict` and the\n * message \"... changed while this mutation was being run ...\" mean the same.\n * - Any other 5xx answer. Two parallel delete_preview_deploy_key calls on one\n * project gave HTTP 500 `InternalServerError`, \"Your request couldn't be\n * completed. Try again later.\", in a live run. The next attempt succeeded.\n */\nexport const isRetryableWriteError = (error: ConvexApiError): boolean =>\n error.code === \"OptimisticConcurrencyControlFailure\" ||\n error.code === \"OCC\" ||\n error.code === \"WriteConflict\" ||\n /changed while (it|this mutation) was being run/.test(error.message) ||\n error.status >= 500;\n\n/**\n * Runs an idempotent write again after a retryable Convex error: at most\n * four more attempts, with exponential backoff from 100 ms and jitter. Other\n * errors fail at once, and so does the last retryable error. Use it only for\n * a write that has the same result when it runs twice, such as setting a\n * value or deleting by id. Never for a create that does not check first.\n */\nexport const retryIdempotentWrite = <A, E, R>(\n effect: Effect.Effect<A, E, R>,\n): Effect.Effect<A, E, R> =>\n effect.pipe(\n Effect.retry({\n while: (error: E) => error instanceof ConvexApiError && isRetryableWriteError(error),\n times: 4,\n schedule: Schedule.exponential(\"100 millis\").pipe(Schedule.jittered),\n }),\n );\n\n/** Turns a 404 into `undefined` so read and delete stay idempotent. */\nexport const absentAsUndefined = <A, R>(\n effect: Effect.Effect<A, ConvexApiError, R>,\n): Effect.Effect<A | undefined, ConvexApiError, R> =>\n effect.pipe(\n Effect.catchIf(\n (error) => error.status === 404,\n () => Effect.succeed(undefined),\n ),\n );\n\nconst TeamRow = Schema.Struct({ id: Schema.Number, slug: Schema.String });\nconst TeamRows = Schema.Array(TeamRow);\n\n/** The first page of GET /teams/{team_id}/projects: every row carries the slug of the team. */\nconst ProjectSlugRows = Schema.Struct({\n items: Schema.Array(Schema.Struct({ teamSlug: Schema.String })),\n});\n\n/** GET /token_details: the team of a team token, or the project of a project token. */\nconst TokenDetails = Schema.Union([\n Schema.Struct({ type: Schema.Literal(\"teamToken\"), teamId: Schema.Number }),\n Schema.Struct({ type: Schema.Literal(\"projectToken\"), projectId: Schema.Number }),\n]);\n\n/** The service for one way to get the bearer token. */\nconst makeService = (credentials: Effect.Effect<ResolvedCredentials>): ManagementApiService => {\n const client = Effect.cached(\n credentials.pipe(\n Effect.map((resolved) => createManagementClient(Redacted.value(resolved.accessToken))),\n ),\n ).pipe(Effect.flatten);\n\n const request: ManagementApiService[\"request\"] = (operation, run) =>\n client.pipe(Effect.flatMap((c) => settle(operation, () => run(c))));\n\n const requestVoid: ManagementApiService[\"requestVoid\"] = (operation, run) =>\n client.pipe(Effect.flatMap((c) => settleVoid(operation, () => run(c))));\n\n const deploymentRequest: ManagementApiService[\"deploymentRequest\"] = (\n operation,\n deploymentUrlOrName,\n deployKey,\n run,\n ) =>\n settle(operation, () =>\n run(createDeploymentClient(deploymentUrlOrName, Redacted.value(deployKey))),\n );\n\n // Measured: a team access token answers `GET /token_details` with its\n // team id and gets HTTP 403 from the dashboard's team list; the Convex CLI\n // login answers the team list and gets HTTP 403 `NotOAuthTeamToken` from\n // token_details. Read once for each service.\n // `Effect.cached` only allocates the cache, so runSync makes one for this service.\n const tokenDetails = Effect.runSync(\n Effect.cached(\n request(\"get token details\", (c) => c.GET(\"/token_details\")).pipe(\n Effect.map((body) => Schema.decodeUnknownSync(TokenDetails)(body)),\n Effect.catchIf(\n (error) => error.status === 403,\n () => Effect.succeed(undefined),\n ),\n ),\n ),\n );\n\n /** The slug of the team, from the first project of its listing, or undefined for a team without one. Read once. */\n const teamSlug = (teamId: number) =>\n request(\"list projects\", (c) =>\n c.GET(\"/teams/{team_id}/projects\", { params: { path: { team_id: teamId } } }),\n ).pipe(\n Effect.map((body) => Schema.decodeUnknownSync(ProjectSlugRows)(body).items[0]?.teamSlug),\n );\n\n // The Management API addresses teams by numeric id. The only slug lookup\n // it offers is per project, so a slug falls back to the dashboard's team\n // list, which is unofficial. Pass the numeric team id to skip this.\n const resolveTeamId: ManagementApiService[\"resolveTeamId\"] = (team) =>\n Effect.gen(function* () {\n if (typeof team === \"number\") return team;\n if (team !== undefined && /^\\d+$/.test(team)) return Number(team);\n const details = yield* tokenDetails;\n if (details?.type === \"teamToken\") {\n if (team === undefined) return details.teamId;\n // The Management API has no team-by-id call, so the slug of the\n // team comes from any of its projects. A team without a project\n // cannot be checked: the numeric id, or no team, is the fix.\n const slug = yield* teamSlug(details.teamId);\n if (slug === undefined) {\n return yield* new ConvexApiError({\n operation: \"resolve team\",\n status: 0,\n message: `team \"${team}\" cannot be checked against the access token: team ${details.teamId} has no project yet. Set team to ${details.teamId}, or leave it out.`,\n });\n }\n if (slug !== team) {\n return yield* new ConvexApiError({\n operation: \"resolve team\",\n status: 403,\n message: `the access token belongs to team ${details.teamId} (\"${slug}\"), and team is \"${team}\". Use a token of \"${team}\", or set team to ${details.teamId}.`,\n });\n }\n return details.teamId;\n }\n if (details?.type === \"projectToken\") {\n return yield* new ConvexApiError({\n operation: \"resolve team\",\n status: 403,\n message: `the access token belongs to project ${details.projectId}, and a project token cannot create projects. Use a team access token.`,\n });\n }\n if (team === undefined) {\n return yield* new ConvexApiError({\n operation: \"resolve team\",\n status: 0,\n message:\n \"set team to the slug or the id of the Convex team: this access token does not name a team.\",\n });\n }\n const resolved = yield* credentials;\n const rows = yield* Effect.tryPromise({\n try: async () => {\n const response = await fetch(\"https://api.convex.dev/api/dashboard/teams\", {\n headers: { Authorization: `Bearer ${Redacted.value(resolved.accessToken)}` },\n });\n if (!response.ok) {\n throw new Error(`team lookup for \"${team}\" failed with HTTP ${response.status}`);\n }\n return Schema.decodeUnknownSync(TeamRows)(await response.json());\n },\n catch: (cause) =>\n new ConvexApiError({\n operation: \"resolve team\",\n status: 0,\n message: cause instanceof Error ? cause.message : String(cause),\n }),\n });\n const match = rows.find((row) => row.slug === team);\n if (match === undefined) {\n return yield* new ConvexApiError({\n operation: \"resolve team\",\n status: 404,\n message: `no team with slug \"${team}\" for this token`,\n });\n }\n return match.id;\n });\n\n const isCredentialToken: ManagementApiService[\"isCredentialToken\"] = (secret) =>\n credentials.pipe(\n Effect.map(\n (resolved) => tokenPart(Redacted.value(resolved.accessToken)) === tokenPart(secret),\n ),\n );\n\n const withToken: ManagementApiService[\"withToken\"] = (token) =>\n makeService(Effect.succeed({ accessToken: token, source: \"explicit\" }));\n\n return {\n request,\n requestVoid,\n deploymentRequest,\n resolveTeamId,\n isCredentialToken,\n withToken,\n };\n};\n\nexport const ManagementApiLive = (): Layer.Layer<ManagementApi, never, Credentials> =>\n Layer.effect(\n ManagementApi,\n Effect.gen(function* () {\n const credentials = yield* Credentials;\n return makeService(credentials.accessToken);\n }),\n );\n","// The push of a Convex.Deployment: a short-lived deploy key, the `env`\n// variables, and `convex deploy` with the Convex CLI that the app installed.\n//\n// - The key is created for one push with the Management API credential and\n// deleted after it, also after a failure. It can only deploy and read and\n// write variables (with a push command: every action), and it expires\n// after PUSH_KEY_LIFETIME_MS, so a run that stops before the delete leaves\n// no key that works for long. No key\n// goes into state, into an output, or to another resource.\n// - With an OAuth token as the credential, Convex creates no new key: it\n// returns the OAuth token with a new prefix. The push uses it, and the\n// delete is skipped, because it would revoke the OAuth token.\n// - The key reaches the CLI only through an env file (`--env-file`) with\n// mode 0600 in a new temporary directory. The directory is removed after\n// the run, on success, on failure, and on interruption. It is also the home\n// directory of the CLI, so the CLI cannot read the Convex login of this\n// machine. Variables named `CONVEX_*` are not passed on to the CLI.\n// - The CLI output stays out of the logs. A failure shows its last lines with\n// the key removed.\n//\n// The CLI runner follows Confect `packages/alchemy/src/internal/CommandRunner.ts`\n// (https://github.com/rjdellecese/confect, ISC license, see NOTICE).\nimport { createHash } from \"node:crypto\";\nimport { access, mkdtemp, readFile, rm, writeFile } from \"node:fs/promises\";\nimport { createRequire } from \"node:module\";\nimport { tmpdir } from \"node:os\";\nimport { dirname, join, relative, resolve } from \"node:path\";\nimport { stripVTControlCharacters } from \"node:util\";\nimport { createDeploymentClient } from \"@convex-dev/platform\";\nimport type { paths } from \"@convex-dev/platform/managementApi\";\nimport { hashDirectory } from \"alchemy/Command/Memo\";\nimport * as Clock from \"effect/Clock\";\nimport * as Effect from \"effect/Effect\";\nimport * as ChildProcess from \"effect/process/ChildProcess\";\nimport * as ChildProcessSpawner from \"effect/process/ChildProcessSpawner\";\nimport * as Redacted from \"effect/Redacted\";\nimport * as Schema from \"effect/Schema\";\nimport * as Stream from \"effect/Stream\";\nimport {\n absentAsUndefined,\n type ManagementApiService,\n retryIdempotentWrite,\n settle,\n settleVoid,\n} from \"./ManagementApi.ts\";\n\n/** A value of the `env` prop: a string, or a secret such as `Config.Redacted(\"AUTH_SECRET\")`. */\nexport type EnvValue = string | Redacted.Redacted<string>;\n\n/**\n * The `source` prop: the Convex functions directory relative to the app\n * directory (`rootDir`), such as `./convex`, or that directory with a push\n * command and more files for the content identity.\n */\nexport type Source =\n | string\n | {\n /** The Convex functions directory relative to the app directory, such as `./convex`. */\n readonly path: string;\n /**\n * Replaces `convex deploy`: a program and its arguments, run in the app\n * directory with CONVEX_DEPLOY_KEY in its environment, such as\n * `[\"pnpm\", \"exec\", \"convex-hosting\", \"deploy\", \"--build\", \"pnpm run build\", \"--dist\", \"dist\"]`.\n * It must push with `convex deploy`, such as through `--cmd`, so that\n * its output has the CLI's \"Deployed Convex functions to\" line.\n */\n readonly command?: readonly [string, ...string[]];\n /**\n * The files of the content identity, as globs relative to the app\n * directory, next to `path`, package.json, convex.json, and the\n * lockfile, such as the build inputs `[\"src/**\", \"vite.config.ts\"]`.\n * By default, every file of the app that git does not ignore.\n */\n readonly include?: readonly string[];\n };\n\nconst sourceOf = (source: Source) =>\n typeof source === \"string\"\n ? { path: source, command: undefined, include: undefined }\n : { path: source.path, command: source.command, include: source.include };\n\n/** Lifetime of a push key. Long enough for a slow push with index backfills. */\nexport const PUSH_KEY_LIFETIME_MS = 2 * 60 * 60 * 1000;\n\n/** An action of a deploy key, such as `deployment:deploy`, from the generated schema. */\nexport type DeployKeyAction = NonNullable<\n NonNullable<\n paths[\"/deployments/{deployment_name}/create_deploy_key\"][\"post\"][\"requestBody\"]\n >[\"content\"][\"application/json\"][\"allowedActions\"]\n>[number];\n\n/** The only actions a key for `convex deploy` gets. */\nexport const PUSH_KEY_ACTIONS = [\n \"deployment:deploy\",\n \"deployment:env:view\",\n \"deployment:env:write\",\n] as const satisfies readonly DeployKeyAction[];\n\n/** POST /deployments/{deployment_name}/create_deploy_key */\nconst CreatedDeployKey = Schema.Struct({ deployKey: Schema.String });\n\n/** GET https://<deployment>.convex.cloud/api/v1/list_environment_variables */\nconst EnvironmentVariableList = Schema.Struct({\n environmentVariables: Schema.Record(Schema.String, Schema.String),\n});\n\n/** No `convex` package resolves from the app directory. */\nexport class ConvexCliNotFound extends Schema.TaggedError<ConvexCliNotFound>()(\n \"ConvexCliNotFound\",\n { cwd: Schema.String },\n) {\n override get message() {\n return `Convex.Deployment found no installed convex package from ${this.cwd}, and it does not download one. Install convex in the app (npm install convex), or set rootDir to the directory of the app.`;\n }\n}\n\n/** The app directory (`rootDir`) has no package.json. */\nexport class ConvexAppNotFound extends Schema.TaggedError<ConvexAppNotFound>()(\n \"ConvexAppNotFound\",\n {\n /** The app directory, resolved against the working directory of the deploy. */\n rootDir: Schema.String,\n },\n) {\n override get message() {\n return `Convex.Deployment found no package.json in ${this.rootDir}. Set rootDir to the directory of the Convex app, relative to the directory where the deploy runs, such as \"apps/web\".`;\n }\n}\n\n/** The Convex CLI failed, or exited 0 without the deployment URL. The output tail never contains the key. */\nexport class CodePushFailed extends Schema.TaggedError<CodePushFailed>()(\"CodePushFailed\", {\n /** Exit code of the CLI. Undefined when it did not start or a signal stopped it. */\n exitCode: Schema.UndefinedOr(Schema.Number),\n /** The last lines of the CLI output, with the deploy key removed. */\n outputTail: Schema.String,\n}) {\n override get message() {\n return this.exitCode === 0\n ? `convex deploy exited 0 but printed no \"Deployed Convex functions to <url>\" line. Last output, with the deploy key removed:\\n${this.outputTail}`\n : `convex deploy failed${this.exitCode === undefined ? \"\" : ` with exit code ${this.exitCode}`}. Last output, with the deploy key removed:\\n${this.outputTail}`;\n }\n}\n\n/** The CLI pushed to another deployment than the one of the resource. Checked after the push. */\nexport class PushTargetMismatch extends Schema.TaggedError<PushTargetMismatch>()(\n \"PushTargetMismatch\",\n { expected: Schema.String, actual: Schema.String },\n) {\n override get message() {\n return `The Convex CLI pushed the functions to deployment ${this.actual}, but Convex.Deployment expected ${this.expected}. Check that convex.json does not select another deployment.`;\n }\n}\n\n/** Variables in `env` exist on the deployment with other values, and adoption is off. */\nexport class VariablesOwnedBySomeoneElse extends Schema.TaggedError<VariablesOwnedBySomeoneElse>()(\n \"VariablesOwnedBySomeoneElse\",\n { deployment: Schema.String, names: Schema.Array(Schema.String) },\n) {\n override get message() {\n return `Environment variables ${this.names.join(\", \")} already exist on deployment ${this.deployment} with other values. Re-run with --adopt to take them over and overwrite them, or remove them from env.`;\n }\n}\n\n/** A preview deploy key cannot set variables: the deployment API takes only a deploy key of the deployment. */\nexport class EnvironmentNeedsDeployKey extends Schema.TaggedError<EnvironmentNeedsDeployKey>()(\n \"EnvironmentNeedsDeployKey\",\n { deployment: Schema.String },\n) {\n override get message() {\n return `Convex.Deployment cannot set or remove env variables on preview deployment ${this.deployment} with a preview deploy key: Convex lets that key create, push to, and delete preview deployments, but not change their variables. Set CONVEX_ACCESS_TOKEN for this stage, or set the values as project default environment variables for preview deployments in the Convex dashboard.`;\n }\n}\n\n/**\n * What a deploy key targets, from its prefix: `<type>:<deployment>|<secret>`\n * (or `<deployment>|<secret>` in old keys) for one deployment, and\n * `preview:<team>:<project>|<secret>` for the preview deployments of a\n * project. Same rules as convex 1.46 `cli/lib/deployment.js`.\n */\nexport const keyTargetOf = (\n key: string,\n):\n | { readonly kind: \"deployment\"; readonly deployment: string }\n | { readonly kind: \"preview\"; readonly team: string; readonly project: string }\n | { readonly kind: \"other\" } => {\n const bar = key.indexOf(\"|\");\n // A key in the env file must be one unquoted dotenv value.\n if (bar <= 0 || /[\\s#'\"`]/.test(key)) return { kind: \"other\" };\n const [first, second, third, ...rest] = key.slice(0, bar).split(\":\");\n if (rest.length > 0) return { kind: \"other\" };\n if (first === \"preview\" && second && third)\n return { kind: \"preview\", team: second, project: third };\n if (third !== undefined) return { kind: \"other\" };\n if (second) return { kind: \"deployment\", deployment: second };\n if (first && second === undefined) return { kind: \"deployment\", deployment: first };\n return { kind: \"other\" };\n};\n\n/**\n * The CLI prints this line with `logFinishedStep` after the push succeeds, to\n * stderr (convex 1.46 `cli/lib/deploy2.js`). The host is\n * `<deployment>.convex.cloud` or `<deployment>.<region>.convex.cloud`.\n */\nconst DEPLOYED_LINE =\n /Deployed Convex functions to (https:\\/\\/([a-z0-9]+(?:-[a-z0-9]+)*)(?:\\.[a-z0-9]+(?:-[a-z0-9]+)*)?\\.convex\\.cloud)\\/?(?=\\s|$)/m;\n\n/** Reads the deployment URL from `convex deploy` output. ANSI escape codes are removed first. */\nexport const parseDeployOutput = (\n text: string,\n): { url: string; deploymentName: string } | undefined => {\n const match = DEPLOYED_LINE.exec(stripVTControlCharacters(text));\n const url = match?.[1];\n const deploymentName = match?.[2];\n return url === undefined || deploymentName === undefined ? undefined : { url, deploymentName };\n};\n\n/** Number of output lines that a failure quotes. */\nconst OUTPUT_TAIL_LINES = 20;\n\n/** The last non-empty lines of `text`, without escape codes and with every secret replaced. */\nconst outputTail = (text: string, secrets: readonly string[]) =>\n secrets\n .reduce(\n (redacted, secret) => redacted.split(secret).join(\"[REDACTED]\"),\n stripVTControlCharacters(text),\n )\n .split(/\\r?\\n|\\r/)\n .filter((line) => line.trim() !== \"\")\n .slice(-OUTPUT_TAIL_LINES)\n .join(\"\\n\");\n\nconst valueOf = (value: EnvValue) => (Redacted.isRedacted(value) ? Redacted.value(value) : value);\n\n/**\n * The app directory: `rootDir` resolved against the working directory of the\n * deploy. It must have a package.json. There is no search above it.\n */\nconst appDirectoryOf = (rootDir: string) => {\n const directory = resolve(rootDir);\n return Effect.tryPromise({\n try: () => access(join(directory, \"package.json\")).then(() => directory),\n catch: () => new ConvexAppNotFound({ rootDir: directory }),\n });\n};\n\n/** `source` is not the functions directory that the Convex CLI pushes from the app directory. */\nexport class SourceMismatch extends Schema.TaggedError<SourceMismatch>()(\"SourceMismatch\", {\n /** The app directory, resolved. */\n rootDir: Schema.String,\n source: Schema.String,\n functions: Schema.String,\n}) {\n override get message() {\n return `Convex.Deployment source is ${this.source}, but the Convex CLI pushes ${this.functions} from the app directory ${this.rootDir} (the \"functions\" field of convex.json, or convex/ by default). Set rootDir to the directory of the Convex app, and source to its functions directory relative to rootDir, such as \"./convex\".`;\n }\n}\n\nconst ConvexJson = Schema.Struct({ functions: Schema.optionalKey(Schema.String) });\n\n/** Fails with {@link SourceMismatch} when `path` is not the functions directory of the app in `cwd`. */\nconst checkFunctionsDirectory = (cwd: string, path: string) =>\n Effect.gen(function* () {\n const text = yield* Effect.promise(() =>\n readFile(join(cwd, \"convex.json\"), \"utf8\").catch(() => undefined),\n );\n const configured =\n text === undefined\n ? undefined\n : Schema.decodeUnknownSync(Schema.fromJsonString(ConvexJson))(text).functions;\n const functions = resolve(cwd, configured ?? \"convex\");\n if (functions !== path) {\n return yield* new SourceMismatch({ rootDir: cwd, source: path, functions });\n }\n });\n\nconst CliManifest = Schema.Struct({\n bin: Schema.Union([Schema.String, Schema.Record(Schema.String, Schema.String)]),\n});\n\n/** `[node, <convex bin>]` for the `convex` package that `cwd` resolves. Never downloads. */\nexport const installedCli = (cwd: string) =>\n Effect.tryPromise({\n try: async (): Promise<readonly [string, ...string[]]> => {\n const manifestPath = createRequire(join(cwd, \"package.json\")).resolve(\"convex/package.json\");\n const { bin } = Schema.decodeUnknownSync(Schema.fromJsonString(CliManifest))(\n await readFile(manifestPath, \"utf8\"),\n );\n const entry = typeof bin === \"string\" ? bin : bin[\"convex\"];\n if (entry === undefined) throw new Error(\"the convex package has no convex bin\");\n return [process.execPath, resolve(dirname(manifestPath), entry)];\n },\n catch: () => new ConvexCliNotFound({ cwd }),\n });\n\n/**\n * The content identity of a push: the files of the app directory that git\n * does not ignore (or `path`, the manifests, and the `include` globs), the\n * nearest lockfile, the target deployment, and the `env` names and values.\n * A change in a workspace package outside the app directory is not seen.\n */\nexport const pushHash = (options: {\n /** The app directory, relative to the working directory of the deploy or absolute. */\n readonly rootDir: string;\n readonly source: Source | undefined;\n readonly deployment: string;\n readonly env: Readonly<Record<string, EnvValue>>;\n}) =>\n Effect.gen(function* () {\n const source = options.source === undefined ? undefined : sourceOf(options.source);\n const files =\n source === undefined\n ? undefined\n : yield* appDirectoryOf(options.rootDir).pipe(\n Effect.flatMap((cwd) => {\n const functions = relative(cwd, resolve(cwd, source.path)).split(\"\\\\\").join(\"/\");\n return hashDirectory({\n cwd,\n // By default every file of the app that git does not ignore,\n // such as a module outside `source` that a function imports,\n // and the functions when convex.json puts them outside\n // rootDir. `include` narrows it to the functions, the\n // manifests, and the listed globs.\n memo:\n source.include !== undefined\n ? {\n include: [\n `${functions}/**`,\n \"package.json\",\n \"convex.json\",\n ...source.include,\n ],\n lockfile: true,\n }\n : functions === \"..\" || functions.startsWith(\"../\")\n ? { include: [\"**/*\", `${functions}/**`], lockfile: true }\n : {},\n });\n }),\n );\n const env = Object.entries(options.env)\n .map(([name, value]): readonly [string, string] => [name, valueOf(value)])\n .sort(([a], [b]) => (a < b ? -1 : 1));\n return createHash(\"sha256\")\n .update(JSON.stringify({ files, deployment: options.deployment, env }))\n .digest(\"hex\");\n });\n\n/**\n * Runs `use` with an env file that holds the key, in a new temporary\n * directory, and removes the directory afterwards: on success, on failure,\n * and on interruption.\n */\nconst withKeyFile = <A, E, R>(\n key: string,\n use: (paths: { readonly envFile: string; readonly home: string }) => Effect.Effect<A, E, R>,\n) =>\n Effect.acquireUseRelease(\n Effect.promise(() => mkdtemp(join(tmpdir(), \"alchemy-convex-\"))),\n (home) =>\n Effect.promise(() =>\n writeFile(join(home, \"deploy.env\"), `CONVEX_DEPLOY_KEY=${key}\\n`, { mode: 0o600 }),\n ).pipe(Effect.andThen(use({ envFile: join(home, \"deploy.env\"), home }))),\n (home) => Effect.promise(() => rm(home, { recursive: true, force: true })),\n );\n\n/** This process's variables without `CONVEX_*`, with `home` as the home directory. */\nconst cliEnvironment = (home: string): Record<string, string | undefined> => ({\n ...Object.fromEntries(\n Object.entries(process.env).filter(([name]) => !name.toUpperCase().startsWith(\"CONVEX_\")),\n ),\n HOME: home,\n USERPROFILE: home,\n XDG_CONFIG_HOME: home,\n});\n\n/**\n * A deploy key of `deployment` that expires after PUSH_KEY_LIFETIME_MS, with\n * only `allowedActions`, or every action when that is undefined. Delete it\n * with {@link deleteDeployKey} when the work is done.\n */\nexport const createDeployKey = (\n api: ManagementApiService,\n deployment: string,\n name: string,\n allowedActions: readonly DeployKeyAction[] | undefined,\n) =>\n Effect.gen(function* () {\n const now = yield* Clock.currentTimeMillis;\n const created = yield* api.request(\"create deploy key\", (client) =>\n client.POST(\"/deployments/{deployment_name}/create_deploy_key\", {\n params: { path: { deployment_name: deployment } },\n body: {\n name,\n ...(allowedActions === undefined ? {} : { allowedActions: [...allowedActions] }),\n expiresAt: now + PUSH_KEY_LIFETIME_MS,\n },\n }),\n );\n return Redacted.make(Schema.decodeUnknownSync(CreatedDeployKey)(created).deployKey);\n });\n\n/**\n * Deletes a key that {@link createDeployKey} made. The delete is skipped for\n * a key that is the OAuth credential. A failed delete is logged: the key\n * expires anyway.\n */\nexport const deleteDeployKey = (\n api: ManagementApiService,\n deployment: string,\n key: Redacted.Redacted<string>,\n) =>\n Effect.gen(function* () {\n if (yield* api.isCredentialToken(Redacted.value(key))) return;\n yield* absentAsUndefined(\n retryIdempotentWrite(\n api.requestVoid(\"delete deploy key\", (client) =>\n client.POST(\"/deployments/{deployment_name}/delete_deploy_key\", {\n params: { path: { deployment_name: deployment } },\n body: { id: Redacted.value(key) },\n }),\n ),\n ),\n );\n }).pipe(\n Effect.catch((error) =>\n Effect.logWarning(\n `Convex.Deployment could not delete its key on ${deployment} (${error.message}). The key expires on its own within ${PUSH_KEY_LIFETIME_MS / 60_000} minutes.`,\n ),\n ),\n );\n\n/**\n * Creates a deploy key for one push, runs `use` with it, and deletes it\n * afterwards, also after a failure. `allowedActions` is PUSH_KEY_ACTIONS for\n * `convex deploy`, or undefined for a push command, which can do more than a\n * push, such as the uploads of convex-hosting through `convex run`.\n */\nexport const withPushKey = <A, E, R>(\n api: ManagementApiService,\n deployment: string,\n allowedActions: readonly DeployKeyAction[] | undefined,\n use: (key: Redacted.Redacted<string>) => Effect.Effect<A, E, R>,\n) =>\n Effect.acquireUseRelease(\n createDeployKey(api, deployment, \"alchemy-push\", allowedActions),\n use,\n (key) => deleteDeployKey(api, deployment, key),\n );\n\n/** Every variable of the deployment with its value. */\nconst listVariables = (url: string, key: Redacted.Redacted<string>) =>\n settle(\"list environment variables\", () =>\n createDeploymentClient(url, Redacted.value(key)).GET(\"/list_environment_variables\"),\n ).pipe(\n Effect.map(\n (body) => Schema.decodeUnknownSync(EnvironmentVariableList)(body).environmentVariables,\n ),\n );\n\n/** One call that sets variables, or removes those whose value is null. */\nconst writeVariables = (\n url: string,\n key: Redacted.Redacted<string>,\n changes: ReadonlyArray<{ readonly name: string; readonly value: string | null }>,\n) =>\n settleVoid(\"update environment variables\", () =>\n createDeploymentClient(url, Redacted.value(key)).POST(\"/update_environment_variables\", {\n body: { changes: changes.map(({ name, value }) => ({ name, value })) },\n }),\n );\n\nexport interface PushOptions {\n /** Deployment name, such as `happy-animal-123`. */\n readonly deployment: string;\n /** Client URL of the deployment. */\n readonly url: string;\n /** The app directory, relative to the working directory of the deploy or absolute. The push runs in it. */\n readonly rootDir: string;\n /** The functions directory relative to `rootDir`, or it with a push command. Without it, only the variables change. */\n readonly source: Source | undefined;\n readonly env: Readonly<Record<string, EnvValue>>;\n /** Names that an earlier push set on this deployment. Names that left `env` are removed. */\n readonly previousEnvNames: readonly string[];\n /** True when the resource may overwrite variables that it did not set. */\n readonly adopt: boolean;\n /**\n * The preview name for `convex deploy --preview-name`, when `key` is a\n * preview deploy key. Such a key cannot set variables.\n */\n readonly previewName: string | undefined;\n}\n\n/**\n * The app directory and the program of a push. Fails before any change when\n * `rootDir` has no package.json, when `source` is not the functions directory\n * of the app, or when the app has no installed Convex CLI and no push command.\n */\nexport const checkSource = (rootDir: string, input: Source) =>\n Effect.gen(function* () {\n const source = sourceOf(input);\n const cwd = yield* appDirectoryOf(rootDir);\n yield* checkFunctionsDirectory(cwd, resolve(cwd, source.path));\n const program = source.command ?? (yield* installedCli(cwd));\n return { cwd, program };\n });\n\n/**\n * Sets the `env` variables and pushes the functions of `source` to one\n * deployment with `key`: a deploy key of the deployment, or a preview deploy\n * key of its project with `previewName`. Returns the URL that the CLI\n * printed, or undefined without `source`.\n */\nexport const push = (\n spawner: ChildProcessSpawner.ChildProcessSpawner[\"Service\"],\n key: Redacted.Redacted<string>,\n options: PushOptions,\n) =>\n Effect.gen(function* () {\n const source = options.source === undefined ? undefined : sourceOf(options.source);\n const resolved =\n options.source === undefined\n ? undefined\n : yield* checkSource(options.rootDir, options.source);\n const cwd = resolved?.cwd;\n const program = resolved?.program;\n const env = Object.entries(options.env).sort(([a], [b]) => (a < b ? -1 : 1));\n const removed = options.previousEnvNames.filter((name) => !Object.hasOwn(options.env, name));\n\n // 1. Variables before the push, so the push sees them. Each attempt\n // reads the current values first, so a retry after a write conflict never\n // overwrites a value that another writer set in the meantime. Only\n // changed values are written, and the earlier ones are kept for a\n // rollback.\n const written =\n env.length === 0 && removed.length === 0\n ? { current: {}, changes: [] }\n : yield* retryIdempotentWrite(\n Effect.gen(function* () {\n const current = yield* listVariables(options.url, key);\n if (!options.adopt) {\n // The same value loses nothing, such as a value that an\n // earlier run set before its push failed.\n const taken = env\n .filter(\n ([name, value]) =>\n !options.previousEnvNames.includes(name) &&\n Object.hasOwn(current, name) &&\n current[name] !== valueOf(value),\n )\n .map(([name]) => name);\n if (taken.length > 0) {\n return yield* new VariablesOwnedBySomeoneElse({\n deployment: options.deployment,\n names: taken,\n });\n }\n }\n const changes = [\n ...env\n .filter(([name, value]) => current[name] !== valueOf(value))\n .map(([name, value]) => ({ name, value: valueOf(value) })),\n ...removed\n .filter((name) => Object.hasOwn(current, name))\n .map((name) => ({ name, value: null })),\n ];\n if (changes.length > 0) yield* writeVariables(options.url, key, changes);\n return { current, changes };\n }),\n );\n\n /**\n * After a failed push, the variables go back to their earlier values, so\n * that the deployment matches the hash in state. A failed rollback is\n * logged: the push error is the one to report.\n */\n const rollback =\n written.changes.length === 0\n ? Effect.void\n : retryIdempotentWrite(\n writeVariables(\n options.url,\n key,\n written.changes.map(({ name }) => ({\n name,\n value: Object.hasOwn(written.current, name)\n ? (written.current[name] ?? null)\n : null,\n })),\n ),\n ).pipe(\n Effect.catch((error) =>\n Effect.logWarning(\n `Convex.Deployment could not set the env variables of ${options.deployment} back after the failed push (${error.message}). Run the deploy again.`,\n ),\n ),\n );\n\n // 2. The push, with the key only in the env file.\n if (source === undefined || cwd === undefined || program === undefined) return undefined;\n return yield* runPush(spawner, key, { ...options, cwd, program, command: source.command }).pipe(\n Effect.onError(() => rollback),\n );\n });\n\n/** Runs the installed CLI or the push command once, and checks the deployment that it names. */\nconst runPush = (\n spawner: ChildProcessSpawner.ChildProcessSpawner[\"Service\"],\n key: Redacted.Redacted<string>,\n options: PushOptions & {\n readonly cwd: string;\n readonly program: readonly [string, ...string[]];\n readonly command: readonly [string, ...string[]] | undefined;\n },\n) =>\n Effect.gen(function* () {\n const { cwd, program } = options;\n const secret = Redacted.value(key);\n const secrets = [secret, secret.slice(secret.indexOf(\"|\") + 1)].filter(\n (value) => value.length >= 8,\n );\n const result = yield* withKeyFile(secret, ({ envFile, home }) =>\n Effect.gen(function* () {\n const [command, ...programArgs] = program;\n // The installed CLI reads the key from the env file. A push command\n // gets it as CONVEX_DEPLOY_KEY, which the CLI that it runs reads.\n const args =\n options.command === undefined\n ? [\n ...programArgs,\n \"deploy\",\n ...(options.previewName === undefined\n ? []\n : [\"--preview-name\", options.previewName]),\n \"--env-file\",\n envFile,\n ]\n : programArgs;\n const child = yield* spawner.spawn(\n ChildProcess.make(command, args, {\n cwd,\n env: {\n ...cliEnvironment(home),\n ...(options.command === undefined ? {} : { CONVEX_DEPLOY_KEY: secret }),\n },\n extendEnv: false,\n stdin: \"ignore\",\n stdout: \"pipe\",\n stderr: \"pipe\",\n }),\n );\n const [exitCode, stdout, stderr] = yield* Effect.all(\n [\n child.exitCode,\n Stream.mkString(Stream.decodeText(child.stdout)),\n Stream.mkString(Stream.decodeText(child.stderr)),\n ],\n { concurrency: \"unbounded\" },\n );\n return { exitCode: Number(exitCode), output: `${stdout}\\n${stderr}` };\n }).pipe(Effect.scoped),\n ).pipe(\n Effect.mapError(\n (error) =>\n new CodePushFailed({\n exitCode: undefined,\n outputTail: outputTail(error.message, secrets),\n }),\n ),\n );\n const deployed = parseDeployOutput(result.output);\n if (result.exitCode !== 0 || deployed === undefined) {\n return yield* new CodePushFailed({\n exitCode: result.exitCode,\n outputTail: outputTail(result.output, secrets),\n });\n }\n if (deployed.deploymentName !== options.deployment) {\n return yield* new PushTargetMismatch({\n expected: options.deployment,\n actual: deployed.deploymentName,\n });\n }\n return deployed.url;\n });\n","// Convex.Deployment: one deployment of a Convex project, its environment\n// variables, and its functions, with the URLs that a frontend or a Worker\n// needs. This is the Convex plane of a stack: no deploy key leaves it.\n//\n// - `rootDir` is the app directory, relative to the directory where the\n// deploy runs (the directory of the stack file), such as `apps/web`, and\n// \".\" by default. The push runs in it, and `source` is relative to it.\n// The constructor writes it into the props, \".\" included, so that a reader\n// of the state row finds the app directory of every deployment.\n// - `source` is the Convex functions directory relative to `rootDir`, such\n// as `./convex`. The update pushes it with the Convex CLI that the app\n// installed (Push.ts).\n// The content identity of the push is a hash of the source files, the\n// app's package.json, convex.json, and lockfile, the deployment name, and\n// `env`. The same hash is a no-op. The hash is taken again after the push,\n// so files that `convex deploy` generates are part of it.\n// `source.command` replaces `convex deploy`, such as `convex-hosting\n// deploy`, and `source.include` adds the files that it reads to the hash.\n// - `env` is set on the deployment before the push. A name that leaves `env`\n// is removed. A variable that exists with another value and that this\n// resource did not set is someone else's: it is overwritten only with\n// --adopt. Delete leaves the variables: they go with the deployment.\n// - Credentials by scope (see Access below): a deploy key of the deployment,\n// a preview deploy key of the project, or the Management API token.\n// - `prod` is the project's default production deployment. Convex creates it\n// with the project, so this resource never creates one. It takes the\n// deployment over without --adopt: it never changes or deletes a production\n// deployment, so the takeover cannot lose data. It follows the default:\n// when another production deployment becomes the default, the next deploy\n// outputs that one. With a deploy key, `prod` is the production deployment\n// of that key. To delete a production deployment, delete its project\n// (Convex.Project with RemovalPolicy.destroy()). Delete reads the live type\n// first, so a dev or preview deployment that became a production\n// deployment is not deleted either.\n// - `dev` and `preview` are created with POST\n// /projects/{project_id}/create_deployment and the `name` prop as the\n// reference. Convex keeps a dev reference as given. For a preview, Convex\n// records `name` as the preview identifier, the name that\n// `npx convex deploy --preview-name <name>` finds, and derives the reference\n// from it (`preview/<slug>`). A create for a preview name that already has\n// a preview deployment deletes that deployment and creates a new one, so\n// reconcile always looks the name up first and never creates over an\n// existing deployment. A dev or preview deployment that exists but is not\n// in state belongs to someone else: the resource takes it over only with\n// --adopt.\n// - `projectId`, `type`, and `name` are the identity. A change fails with\n// DeploymentIdentityChange; the resource is never replaced.\n// - The removal policy is `retain` for every type. A preview deployment\n// expires on Convex's schedule (14 days by default). To delete a dev or\n// preview deployment with the resource, add RemovalPolicy.destroy().\n//\n// Patterns from Confect `packages/alchemy/src/Deployment.ts`\n// (https://github.com/rjdellecese/confect, ISC license, see NOTICE).\nimport { posix, win32 } from \"node:path\";\nimport { Resource } from \"alchemy\";\nimport { OwnedBySomeoneElse, Unowned } from \"alchemy/AdoptPolicy\";\nimport { diffBindings, isResolved } from \"alchemy/Diff\";\nimport type { InputProps } from \"alchemy/Input\";\nimport * as Provider from \"alchemy/Provider\";\nimport * as Effect from \"effect/Effect\";\nimport * as ChildProcessSpawner from \"effect/process/ChildProcessSpawner\";\nimport * as Redacted from \"effect/Redacted\";\nimport * as Schema from \"effect/Schema\";\nimport { shouldAdopt } from \"./Adoption.ts\";\nimport { Credentials } from \"./Credentials.ts\";\nimport type { ComponentBinding } from \"./Component.ts\";\nimport {\n absentAsUndefined,\n type ConvexApiError,\n ManagementApi,\n type ManagementApiService,\n retryIdempotentWrite,\n} from \"./ManagementApi.ts\";\nimport type { Providers } from \"./Providers.ts\";\nimport {\n checkSource,\n EnvironmentNeedsDeployKey,\n type EnvValue,\n keyTargetOf,\n push,\n PUSH_KEY_ACTIONS,\n pushHash,\n type Source,\n withPushKey,\n} from \"./Push.ts\";\n\ninterface DeploymentInputs {\n /** The project: a Convex.Project resource, or `{ projectId }`. Cannot change. */\n readonly project: { readonly projectId: number };\n /**\n * The app directory, relative to the directory where the deploy runs (the\n * directory of the stack file), such as `apps/web`. Default \".\". It must\n * have a package.json. The push runs in it, and `source` is relative to\n * it. State from 0.7 has no `rootDir`.\n */\n readonly rootDir?: string;\n /**\n * The Convex functions directory relative to `rootDir`, such as\n * `./convex`, or that directory with a push command and more hashed\n * files. Without `source`, the resource pushes nothing.\n */\n readonly source?: Source;\n /** Environment variables to set on the deployment before the push. */\n readonly env?: Readonly<Record<string, EnvValue>>;\n}\n\nexport type DeploymentProps =\n | (DeploymentInputs & {\n /** The project's default production deployment. Cannot change. */\n readonly type: \"prod\";\n })\n | (DeploymentInputs & {\n /** A dev deployment or a preview deployment that this resource creates. Cannot change. */\n readonly type: \"dev\" | \"preview\";\n /**\n * The dev reference, such as `staging`, or the preview name, such as\n * the stage name. Unique in the project. Cannot change.\n */\n readonly name: string;\n });\n\n/** The deployment itself, without the state of the push. */\ninterface DeploymentTarget {\n readonly projectId: number;\n readonly type: DeploymentProps[\"type\"];\n /** Deployment name, such as `happy-animal-123`. */\n readonly name: string;\n /** The reference that Convex lists, such as `production`, `staging`, or `preview/pr-42`. */\n readonly reference: string;\n /** The preview name of a preview deployment. Undefined for prod and dev. */\n readonly previewName: string | undefined;\n /** Client URL, such as `https://happy-animal-123.convex.cloud`. */\n readonly url: string;\n /** HTTP actions URL, such as `https://happy-animal-123.convex.site`. */\n readonly siteUrl: string;\n}\n\nexport interface DeploymentAttributes extends DeploymentTarget {\n /** Content identity of the last push and `env`. Undefined when the resource pushed nothing. */\n readonly hash: string | undefined;\n /** The names of the `env` variables that this resource set on the deployment, sorted. */\n readonly envNames: readonly string[];\n}\n\nexport type Deployment = Resource<\n \"Convex.Deployment\",\n DeploymentProps,\n DeploymentAttributes,\n ComponentBinding,\n Providers\n>;\n/** The resource class. Stacks call {@link Deployment}, which writes `rootDir` into the props. */\nexport const DeploymentResource = Resource<Deployment>(\"Convex.Deployment\", {\n defaultRemovalPolicy: \"retain\",\n});\n\n/** The props of a `Convex.Deployment` call: Alchemy inputs, with `rootDir` a plain string. */\nexport type DeploymentInput = DeploymentProps extends infer P\n ? P extends DeploymentProps\n ? InputProps<P, \"rootDir\">\n : never\n : never;\n\n/** `rootDir` in POSIX form, without \"./\" and a trailing slash, such as `apps/web` or \".\". */\nconst normalizeRootDir = (rootDir: string) => {\n const normalized = posix.normalize(rootDir.replaceAll(\"\\\\\", \"/\"));\n return normalized.length > 1 && normalized.endsWith(\"/\") ? normalized.slice(0, -1) : normalized;\n};\n\n/** `rootDir` is an absolute path. The declaration stops with it as a defect, before the plan. */\nexport class AbsoluteRootDir extends Schema.TaggedError<AbsoluteRootDir>()(\"AbsoluteRootDir\", {\n rootDir: Schema.String,\n}) {\n override get message() {\n return `Convex.Deployment rootDir ${this.rootDir} is an absolute path. State keeps rootDir for every machine that runs the stack, so set it relative to the directory where the deploy runs, such as \"apps/web\".`;\n }\n}\n\n/**\n * `Convex.Deployment(\"id\", props)`. The props go to state with `rootDir` in\n * POSIX form, and with \".\" when it is not set, so that every row names the\n * app directory of its deployment. An absolute `rootDir` stops the\n * declaration, so it never reaches the plan or state. The check dies,\n * because the program of `Alchemy.Stack` can fail only with a ConfigError.\n * `win32.isAbsolute` also answers true for a POSIX absolute path. The other\n * fields keep it usable where Alchemy takes a resource class, such as\n * `Provider.collection`.\n */\nexport const Deployment = Object.assign(\n (id: string, props: DeploymentInput) => {\n const rootDir = props.rootDir ?? \".\";\n return win32.isAbsolute(rootDir)\n ? Effect.die(new AbsoluteRootDir({ rootDir }))\n : DeploymentResource(id, { ...props, rootDir: normalizeRootDir(rootDir) });\n },\n {\n Type: DeploymentResource.Type,\n Props: DeploymentResource.Props,\n Self: DeploymentResource.Self,\n Provider: DeploymentResource.Provider,\n Aliases: DeploymentResource.Aliases,\n ref: (id: string, options?: { stage?: string; stack?: string }) =>\n DeploymentResource.ref(id, options),\n },\n);\n\n/** The props name another deployment than the one in state. */\nexport class DeploymentIdentityChange extends Schema.TaggedError<DeploymentIdentityChange>()(\n \"DeploymentIdentityChange\",\n {\n /** Name of the deployment in state, such as `happy-animal-123`. */\n deployment: Schema.String,\n field: Schema.Literals([\"projectId\", \"type\", \"name\"]),\n current: Schema.String,\n requested: Schema.String,\n },\n) {\n override get message() {\n return `Convex.Deployment cannot change the ${this.field} of deployment ${this.deployment} from ${this.current} to ${this.requested}. Set ${this.field} back to ${this.current}. For another deployment, create a new resource with a new logical id.`;\n }\n}\n\n/** The project has no default production deployment for a `prod` resource to take over. */\nexport class ProductionDeploymentNotFound extends Schema.TaggedError<ProductionDeploymentNotFound>()(\n \"ProductionDeploymentNotFound\",\n { projectId: Schema.Number },\n) {\n override get message() {\n return `Project ${this.projectId} has no default production deployment, and Convex.Deployment does not create one. Create it in the Convex dashboard, or with \\`npx convex deployment create --type prod --default\\` in the project, then run the deploy again.`;\n }\n}\n\n/** More than one deployment of the project has the name, so the lookup cannot choose one. */\nexport class AmbiguousDeployment extends Schema.TaggedError<AmbiguousDeployment>()(\n \"AmbiguousDeployment\",\n {\n projectId: Schema.Number,\n type: Schema.Literals([\"dev\", \"preview\"]),\n name: Schema.String,\n deployments: Schema.Array(Schema.String),\n },\n) {\n override get message() {\n return `Project ${this.projectId} has ${this.deployments.length} ${this.type} deployments named \"${this.name}\" (${this.deployments.join(\", \")}). Convex.Deployment does not choose one. Delete the extra deployments in the Convex dashboard, or use another name.`;\n }\n}\n\n/**\n * The URL of a Convex cloud deployment: `https://<name>.convex.cloud`, or\n * `https://<name>.<region>.convex.cloud` outside US East.\n */\nconst CLOUD_URL =\n /^https:\\/\\/[a-z0-9]+(?:-[a-z0-9]+)*(?:\\.[a-z0-9]+(?:-[a-z0-9]+)*)?\\.convex\\.cloud$/;\n\n/**\n * The HTTP actions URL of a deployment: the client URL with `.convex.site`\n * for `.convex.cloud`, as Convex sets CONVEX_SITE_URL. Custom domains are\n * not covered.\n */\nexport const siteUrlOf = (url: string): string => url.replace(/\\.convex\\.cloud$/, \".convex.site\");\n\n/** One row of list_deployments, GET /deployments/{name}, and create_deployment. Only the fields the provider uses. */\nexport const DeploymentRow = Schema.Struct({\n name: Schema.String,\n projectId: Schema.Number,\n deploymentType: Schema.String,\n isDefault: Schema.Boolean,\n reference: Schema.String,\n /** Set in list_deployments and create_deployment rows only: GET /deployments/{name} answers null. */\n previewIdentifier: Schema.optionalKey(Schema.NullOr(Schema.String)),\n deploymentUrl: Schema.String.check(Schema.isPattern(CLOUD_URL)),\n /** Absent or null until the first push: list_deployments leaves it out for a new deployment. */\n lastDeployTime: Schema.optionalKey(Schema.NullOr(Schema.Number)),\n});\ntype DeploymentRow = typeof DeploymentRow.Type;\nconst DeploymentRows = Schema.Array(DeploymentRow);\n\n/** GET https://<deployment>/api/v1/deployment_info, for a cloud deployment. Only the fields the provider uses. */\nconst DeploymentInfo = Schema.Struct({\n kind: Schema.Literal(\"cloud\"),\n projectId: Schema.Number,\n deploymentType: Schema.String,\n reference: Schema.optionalKey(Schema.NullOr(Schema.String)),\n});\n\n/** GET https://<deployment>/api/v1/get_canonical_urls */\nconst CanonicalUrls = Schema.Struct({\n convexCloudUrl: Schema.String,\n convexSiteUrl: Schema.String,\n});\n\nconst targetOf = (\n row: DeploymentRow,\n type: DeploymentProps[\"type\"],\n previewName: string | undefined,\n): DeploymentTarget => ({\n projectId: row.projectId,\n type,\n name: row.name,\n reference: row.reference,\n previewName: type === \"preview\" ? previewName : undefined,\n url: row.deploymentUrl,\n siteUrl: siteUrlOf(row.deploymentUrl),\n});\n\n/** True when the deployment has received a push. */\nconst isDeployed = (row: DeploymentRow) =>\n row.lastDeployTime !== undefined && row.lastDeployTime !== null;\n\n/** The `name` prop of a deployment: the dev reference or the preview name. */\nconst nameOf = (target: DeploymentTarget) =>\n target.type === \"dev\"\n ? target.reference\n : target.type === \"preview\"\n ? target.previewName\n : undefined;\n\n/**\n * Fails with {@link DeploymentIdentityChange} when the props name another\n * deployment than `current`: the attributes in state, or a live deployment.\n */\nconst checkIdentity = (current: DeploymentTarget, news: DeploymentProps) => {\n const change = (field: \"projectId\" | \"type\" | \"name\", from: string, to: string) =>\n Effect.fail(\n new DeploymentIdentityChange({\n deployment: current.name,\n field,\n current: from,\n requested: to,\n }),\n );\n if (current.projectId !== news.project.projectId) {\n return change(\"projectId\", String(current.projectId), String(news.project.projectId));\n }\n if (current.type !== news.type) return change(\"type\", current.type, news.type);\n const currentName = nameOf(current);\n if (news.type !== \"prod\" && currentName !== news.name) {\n return change(\"name\", currentName ?? \"(none)\", news.name);\n }\n return Effect.void;\n};\n\n/** The deployment that a resource addresses: its project, type, and dev or preview name. */\ninterface Address {\n readonly projectId: number;\n readonly type: DeploymentProps[\"type\"];\n readonly name: string | undefined;\n}\n\nconst addressOf = (props: DeploymentProps): Address => ({\n projectId: props.project.projectId,\n type: props.type,\n name: props.type === \"prod\" ? undefined : props.name,\n});\n\n/** True when an update writes or removes variables: `env` has names, or state has names to remove. */\nconst changesEnv = (news: DeploymentProps, output: DeploymentAttributes | undefined) =>\n Object.keys(news.env ?? {}).length > 0 || envNamesOf(output).length > 0;\n\n/** The `env` names in state. State from 0.3 has none. */\nconst envNamesOf = (output: DeploymentAttributes | undefined): readonly string[] =>\n output?.envNames ?? [];\n\n/** The address of the deployment in state. */\nconst addressInState = (output: DeploymentAttributes): Address => ({\n projectId: output.projectId,\n type: output.type,\n name: nameOf(output),\n});\n\n/**\n * How the provider reaches one deployment, by the narrowest credential that\n * fits:\n *\n * - `deployKey`: the configured deploy key belongs to this deployment. The\n * deployment API answers its identity and URLs, the key sets variables and\n * pushes, and no Management API call is made.\n * - `previewKey`: the configured preview deploy key belongs to this project.\n * The Management API takes it for the preview deployments of the project,\n * and the CLI pushes with it and `--preview-name`.\n * - `token`: the Management API access token. Each push gets a short-lived\n * deploy key (Push.ts).\n */\ntype Access =\n | {\n readonly kind: \"deployKey\";\n readonly key: Redacted.Redacted<string>;\n readonly target: DeploymentTarget;\n }\n | {\n readonly kind: \"previewKey\";\n readonly key: Redacted.Redacted<string>;\n readonly api: ManagementApiService;\n }\n | { readonly kind: \"token\"; readonly api: ManagementApiService };\n\nconst ProjectSlugs = Schema.Struct({ slug: Schema.String, teamSlug: Schema.String });\n\n/** True for an answer that says this credential cannot read the object. */\nconst isRefused = (error: ConvexApiError) =>\n error.status === 400 || error.status === 401 || error.status === 403 || error.status === 404;\n\nexport const DeploymentProvider = () =>\n Provider.effect(\n DeploymentResource,\n Effect.gen(function* () {\n const api = yield* ManagementApi;\n const credentials = yield* Credentials;\n const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;\n\n /** The live deployment, or undefined after a 404. GET /deployments/{name} answers no preview identifier. */\n const getByName = (management: ManagementApiService, name: string) =>\n absentAsUndefined(\n management.request(\"get deployment\", (client) =>\n client.GET(\"/deployments/{deployment_name}\", {\n params: { path: { deployment_name: name } },\n }),\n ),\n ).pipe(\n Effect.map((body) =>\n body === undefined ? undefined : Schema.decodeUnknownSync(DeploymentRow)(body),\n ),\n );\n\n const listDeployments = (\n management: ManagementApiService,\n projectId: number,\n type: DeploymentProps[\"type\"],\n isDefault?: boolean,\n ) =>\n management\n .request(\"list deployments\", (client) =>\n client.GET(\"/projects/{project_id}/list_deployments\", {\n params: {\n path: { project_id: projectId },\n query: { deploymentType: type, ...(isDefault === undefined ? {} : { isDefault }) },\n },\n }),\n )\n .pipe(Effect.map((body) => Schema.decodeUnknownSync(DeploymentRows)(body)));\n\n /** The row of the project's default production deployment, or undefined. */\n const productionRow = (management: ManagementApiService, projectId: number) =>\n listDeployments(management, projectId, \"prod\", true).pipe(\n Effect.map((rows) =>\n rows.find((candidate) => candidate.deploymentType === \"prod\" && candidate.isDefault),\n ),\n );\n\n /** The project's default production deployment, or undefined. */\n const production = (management: ManagementApiService, projectId: number) =>\n productionRow(management, projectId).pipe(\n Effect.map((row) => (row === undefined ? undefined : targetOf(row, \"prod\", undefined))),\n );\n\n /**\n * The one dev deployment with this reference, or the one preview\n * deployment with this preview name, or undefined.\n */\n const findByName = (\n management: ManagementApiService,\n projectId: number,\n type: \"dev\" | \"preview\",\n name: string,\n ) =>\n Effect.gen(function* () {\n const matches = (yield* listDeployments(management, projectId, type)).filter(\n (row) =>\n row.deploymentType === type &&\n (type === \"dev\" ? row.reference === name : row.previewIdentifier === name),\n );\n if (matches.length > 1) {\n return yield* new AmbiguousDeployment({\n projectId,\n type,\n name,\n deployments: matches.map((row) => row.name),\n });\n }\n return matches[0];\n });\n\n /** The deployment that the address names, through the Management API, or undefined. */\n const lookup = (management: ManagementApiService, address: Address) =>\n address.type === \"prod\" || address.name === undefined\n ? production(management, address.projectId)\n : findByName(management, address.projectId, address.type, address.name).pipe(\n Effect.map((row) =>\n row === undefined ? undefined : targetOf(row, address.type, address.name),\n ),\n );\n\n /** The deployment of a deploy key, when it is the deployment that the address names. */\n const deployKeyTarget = (\n key: Redacted.Redacted<string>,\n deployment: string,\n address: Address,\n ) =>\n Effect.gen(function* () {\n const info = Schema.decodeUnknownSync(DeploymentInfo)(\n yield* api.deploymentRequest(\"get deployment info\", deployment, key, (client) =>\n client.GET(\"/deployment_info\"),\n ),\n );\n const reference = info.reference ?? \"\";\n if (\n info.projectId !== address.projectId ||\n info.deploymentType !== address.type ||\n (address.type === \"dev\" && reference !== address.name)\n ) {\n return undefined;\n }\n const urls = Schema.decodeUnknownSync(CanonicalUrls)(\n yield* api.deploymentRequest(\"get canonical urls\", deployment, key, (client) =>\n client.GET(\"/get_canonical_urls\"),\n ),\n );\n return {\n projectId: info.projectId,\n type: address.type,\n name: deployment,\n reference,\n previewName: undefined,\n url: urls.convexCloudUrl,\n siteUrl: urls.convexSiteUrl,\n } satisfies DeploymentTarget;\n }).pipe(Effect.catchIf(isRefused, () => Effect.succeed(undefined)));\n\n /** True when the preview deploy key belongs to the project. */\n const previewKeyFits = (\n management: ManagementApiService,\n slugs: { readonly team: string; readonly project: string },\n projectId: number,\n ) =>\n management\n .request(\"get project\", (client) =>\n client.GET(\"/projects/{project_id}\", { params: { path: { project_id: projectId } } }),\n )\n .pipe(\n Effect.map((body) => {\n const project = Schema.decodeUnknownSync(ProjectSlugs)(body);\n return project.slug === slugs.project && project.teamSlug === slugs.team;\n }),\n Effect.catchIf(isRefused, () => Effect.succeed(false)),\n );\n\n /**\n * The narrowest credential that reaches the deployment. See {@link Access}.\n * When `changesEnv`, a preview deploy key gives way to the access token,\n * because it cannot change variables.\n */\n const accessFor = (address: Address, changesEnv: boolean) =>\n Effect.gen(function* (): Effect.fn.Return<Access, ConvexApiError> {\n const key = yield* credentials.deployKey;\n if (key !== undefined) {\n const target = keyTargetOf(Redacted.value(key));\n if (target.kind === \"deployment\" && address.type !== \"preview\") {\n const found = yield* deployKeyTarget(key, target.deployment, address);\n if (found !== undefined) return { kind: \"deployKey\", key, target: found };\n }\n if (target.kind === \"preview\" && address.type === \"preview\") {\n const scoped = api.withToken(key);\n if (\n !(changesEnv && (yield* credentials.hasAccessToken)) &&\n (yield* previewKeyFits(scoped, target, address.projectId))\n ) {\n return { kind: \"previewKey\", key, api: scoped };\n }\n }\n }\n return { kind: \"token\", api };\n });\n\n /** The live deployment of a resource in state, or undefined when it is gone. */\n const live = (access: Access, output: DeploymentAttributes) =>\n Effect.gen(function* () {\n if (access.kind === \"deployKey\") return access.target;\n // 404 for a deleted project: its production deployment is gone too.\n if (output.type === \"prod\")\n return yield* absentAsUndefined(production(access.api, output.projectId));\n const row = yield* getByName(access.api, output.name);\n return row === undefined ? undefined : targetOf(row, output.type, output.previewName);\n });\n\n /** The content identity of `source` and `env` on a deployment, or undefined when there is nothing to push. */\n const wantedHash = (news: DeploymentProps, rootDir: string, deployment: string) =>\n news.source === undefined && Object.keys(news.env ?? {}).length === 0\n ? Effect.succeed(undefined)\n : pushHash({ rootDir, source: news.source, deployment, env: news.env ?? {} });\n\n return {\n // `name`, `reference`, and the URLs change when an expired preview is\n // created again, or when another production deployment becomes the\n // default.\n stables: [\"projectId\", \"type\", \"previewName\"],\n\n // Compares with the attributes: after a refused change, `olds` are\n // the refused props. Only `rootDir` compares with `olds`, because it\n // is in the props only. A refused update leaves the row `updating`,\n // and the next plan updates it again anyway.\n diff: Effect.fn(function* ({ news, olds, output, oldBindings, newBindings }) {\n if (!isResolved(news) || output === undefined) return undefined;\n yield* checkIdentity(output, news);\n if (!isResolved(newBindings)) return undefined;\n // State from 0.7 has no rootDir; the constructor always writes it.\n const rootDir = news.rootDir ?? \".\";\n // Also here, so that a wrong rootDir stops the plan before Apply\n // writes the new props to the row.\n if (news.source !== undefined) yield* checkSource(rootDir, news.source);\n // State from 0.7 has no rootDir, and another rootDir is another\n // app directory. The update writes the props to state; it pushes\n // only when the hash changed.\n if (olds.rootDir !== rootDir) return { action: \"update\" } as const;\n const access = yield* accessFor(addressOf(news), changesEnv(news, output));\n // A preview expires, anyone can delete a deployment, and another\n // production deployment can become the default. Reconcile then\n // finds or creates the right one, so the stack never hands out the\n // URL of a deployment that is gone.\n const current = yield* live(access, output);\n if (current?.name !== output.name) return { action: \"update\" } as const;\n const hash = yield* wantedHash(news, rootDir, output.name);\n if (hash !== output.hash) return { action: \"update\" } as const;\n if (diffBindings(oldBindings, newBindings).every((binding) => binding.action === \"noop\"))\n return { action: \"noop\" } as const;\n // Binding metadata does not change deployment outputs. Keep unchanged\n // values available to consumers so the plan does not update them too.\n return {\n action: \"update\" as const,\n stables: [\n \"hash\",\n \"envNames\",\n ...(\n [\"projectId\", \"type\", \"previewName\", \"name\", \"reference\", \"url\", \"siteUrl\"] as const\n ).filter((key) => current[key] === output[key]),\n ],\n };\n }),\n\n read: Effect.fn(function* ({ olds, output }) {\n if (output !== undefined) {\n const access = yield* accessFor(addressInState(output), false);\n const current = yield* live(access, output);\n return current === undefined ? undefined : { ...output, ...current };\n }\n const address = addressOf(olds);\n const access = yield* accessFor(address, false);\n if (access.kind === \"deployKey\") {\n // The deployment API does not say whether the deployment has code.\n return Unowned({ ...access.target, hash: undefined, envNames: [] });\n }\n if (olds.type === \"prod\") {\n const row = yield* productionRow(access.api, address.projectId);\n if (row === undefined) return undefined;\n const attributes = {\n ...targetOf(row, \"prod\", undefined),\n hash: undefined,\n envNames: [],\n };\n // A production deployment that never received a push, such as\n // the one of a project that this stack created, loses nothing to\n // a push. One with code is someone else's until --adopt.\n return isDeployed(row) ? Unowned(attributes) : attributes;\n }\n const found = yield* lookup(access.api, address);\n if (found === undefined) return undefined;\n // A dev or preview deployment that is not in state is someone\n // else's until the user passes --adopt.\n return Unowned({ ...found, hash: undefined, envNames: [] });\n }),\n\n reconcile: Effect.fn(function* ({ fqn, news, output }) {\n // Also here: with an unresolved prop in plan, diff could not check.\n if (output !== undefined) yield* checkIdentity(output, news);\n // The app directory, the functions directory, and the program,\n // before any change.\n const rootDir = news.rootDir ?? \".\";\n if (news.source !== undefined) yield* checkSource(rootDir, news.source);\n const address = addressOf(news);\n const access = yield* accessFor(address, changesEnv(news, output));\n const env = news.env ?? {};\n // Before any create: a preview deploy key cannot change variables,\n // and accessFor chose it because there is no access token.\n if (access.kind === \"previewKey\" && changesEnv(news, output)) {\n return yield* new EnvironmentNeedsDeployKey({\n deployment: output?.name ?? address.name ?? \"(new)\",\n });\n }\n const adopt = yield* shouldAdopt(fqn);\n const refuse = (name: string) =>\n new OwnedBySomeoneElse({\n message: `Project ${address.projectId} already has ${news.type} deployment ${name}${news.type === \"prod\" ? \" with code\" : ` named \"${news.name}\"`}. Re-run with --adopt to take it over${news.type === \"prod\" ? \"\" : \", or use another name\"}.`,\n resourceType: DeploymentResource.Type,\n physicalName: name,\n });\n\n // 1. The deployment. `created` is true when this reconcile created it.\n const { target, created } = yield* Effect.gen(function* () {\n if (access.kind === \"deployKey\") {\n // read() refused it without --adopt; this covers an apply without a plan.\n if (output === undefined && !adopt) return yield* refuse(access.target.name);\n return { target: access.target, created: false };\n }\n if (news.type === \"prod\") {\n // Always the current default, also when another production\n // deployment became the default after the last deploy.\n const row = yield* productionRow(access.api, address.projectId);\n if (row === undefined) {\n return yield* new ProductionDeploymentNotFound({ projectId: address.projectId });\n }\n // Code that appeared after the plan is someone else's.\n if (output === undefined && isDeployed(row) && !adopt) return yield* refuse(row.name);\n return { target: targetOf(row, \"prod\", undefined), created: false };\n }\n if (output !== undefined) {\n const row = yield* getByName(access.api, output.name);\n if (row !== undefined) {\n if (row.deploymentType !== output.type) {\n return yield* new DeploymentIdentityChange({\n deployment: row.name,\n field: \"type\",\n current: row.deploymentType,\n requested: news.type,\n });\n }\n const current = targetOf(row, output.type, output.previewName);\n // The live deployment can have moved to another project.\n yield* checkIdentity(current, news);\n return { target: current, created: false };\n }\n // The deployment in state is gone, such as an expired preview.\n // Find or create it below like a resource without state.\n }\n // Never create over an existing deployment: a preview create\n // replaces the preview deployment with the same name. Another\n // writer can still create one between this lookup and the create.\n const existing = yield* lookup(access.api, address);\n if (existing !== undefined) {\n if (!adopt) return yield* refuse(existing.name);\n return { target: existing, created: false };\n }\n const row = yield* access.api.request(\"create deployment\", (client) =>\n client.POST(\"/projects/{project_id}/create_deployment\", {\n params: { path: { project_id: address.projectId } },\n body: { type: news.type, reference: news.name },\n }),\n );\n return {\n target: targetOf(Schema.decodeUnknownSync(DeploymentRow)(row), news.type, news.name),\n created: true,\n };\n });\n\n // 2. The variables and the push, only when their content changed.\n // Variables set on another deployment stay there: they are not ours\n // on this one.\n const previousEnvNames = output?.name === target.name ? envNamesOf(output) : [];\n const before = yield* wantedHash(news, rootDir, target.name);\n if (before === undefined && previousEnvNames.length === 0) {\n return { ...target, hash: undefined, envNames: [] };\n }\n if (output?.name === target.name && before === output.hash) {\n return { ...target, hash: output.hash, envNames: previousEnvNames };\n }\n const options = {\n deployment: target.name,\n url: target.url,\n rootDir,\n source: news.source,\n env,\n previousEnvNames,\n adopt,\n };\n const pushed =\n access.kind === \"deployKey\"\n ? push(spawner, access.key, { ...options, previewName: undefined })\n : access.kind === \"previewKey\"\n ? push(spawner, access.key, { ...options, previewName: target.previewName })\n : withPushKey(\n access.api,\n target.name,\n // A push command gets every action; `convex deploy` only its own.\n typeof news.source === \"object\" && news.source.command !== undefined\n ? undefined\n : PUSH_KEY_ACTIONS,\n (key) => push(spawner, key, { ...options, previewName: undefined }),\n );\n yield* pushed.pipe(\n // A deployment that this reconcile created and could not push to\n // would be someone else's on the next run, and a dev deployment\n // never expires. It is new and empty, so it goes.\n Effect.onError(() =>\n created && access.kind !== \"deployKey\"\n ? absentAsUndefined(\n retryIdempotentWrite(\n access.api.requestVoid(\"delete deployment\", (client) =>\n client.POST(\"/deployments/{deployment_name}/delete\", {\n params: { path: { deployment_name: target.name } },\n }),\n ),\n ),\n ).pipe(\n Effect.catch((error) =>\n Effect.logWarning(\n `Convex.Deployment could not delete ${target.name} after the failed push (${error.message}). The next run takes it over only with --adopt.`,\n ),\n ),\n )\n : Effect.void,\n ),\n );\n // Taken again after the push, so that files the push generates,\n // such as convex/_generated, are part of the identity.\n return {\n ...target,\n hash: yield* wantedHash(news, rootDir, target.name),\n envNames: Object.keys(env).sort(),\n };\n }),\n\n // Runs only with RemovalPolicy.destroy(): the default policy is\n // `retain`. The variables go with the deployment.\n delete: Effect.fn(function* ({ output }) {\n const keep = Effect.logWarning(\n `Convex.Deployment does not delete production deployment ${output.name}: it belongs to project ${output.projectId}. To delete it, delete the project with RemovalPolicy.destroy() on Convex.Project.`,\n );\n if (output.type === \"prod\") return yield* keep;\n const access = yield* accessFor(addressInState(output), false);\n // A deploy key cannot delete its deployment.\n const management = access.kind === \"deployKey\" ? api : access.api;\n // The type in state can be old: a dev or preview deployment can\n // become a production deployment in Convex. The live type decides.\n const row = yield* getByName(management, output.name);\n // 404: an earlier attempt, the expiry, or someone else deleted it.\n if (row === undefined) return;\n if (row.deploymentType === \"prod\") return yield* keep;\n yield* absentAsUndefined(\n retryIdempotentWrite(\n management.requestVoid(\"delete deployment\", (client) =>\n client.POST(\"/deployments/{deployment_name}/delete\", {\n params: { path: { deployment_name: output.name } },\n }),\n ),\n ),\n );\n }),\n };\n }),\n );\n","// Convex.Project: a project in a Convex team, with its default production deployment.\n//\n// Deleting a project deletes all of its deployments and data, so this\n// resource never replaces a project and keeps it by default:\n//\n// - A name change is an update in place: PATCH /projects/{project_id} with\n// the new name. The slug stays the same.\n// - `team`, `deploymentType`, and `deploymentRegion` cannot change on an\n// existing project. A change fails with a typed error that names the fix.\n// - The removal policy is `retain`. Alchemy deletes the project only when the\n// resource has `RemovalPolicy.destroy()`.\n// - With state, every call addresses the project by `output.projectId`. Only\n// a resource without state looks a project up by name, and it takes over a\n// project that it finds only when adoption is on.\n// - With `slug` instead of `name`, the resource is an existing project,\n// found by GET /teams/{team}/projects/{slug}. It never creates, renames, or\n// (by default) deletes that project. A stack that only pushes to an\n// existing project can pass `{ projectId }` to Convex.Deployment instead\n// and needs no Management API token for the project.\nimport { Resource } from \"alchemy\";\nimport { OwnedBySomeoneElse, Unowned } from \"alchemy/AdoptPolicy\";\nimport { isResolved } from \"alchemy/Diff\";\nimport * as Provider from \"alchemy/Provider\";\nimport * as Effect from \"effect/Effect\";\nimport * as Schema from \"effect/Schema\";\nimport type { components } from \"@convex-dev/platform/managementApi\";\nimport { shouldAdopt } from \"./Adoption.ts\";\nimport {\n absentAsUndefined,\n ConvexApiError,\n ManagementApi,\n type ManagementApiService,\n} from \"./ManagementApi.ts\";\nimport type { Providers } from \"./Providers.ts\";\n\n/** Region names the Management API accepts, from the generated schema. */\nexport type DeploymentRegion = components[\"schemas\"][\"RegionName\"];\n\nexport type ProjectProps =\n | {\n /** Team slug or numeric team id. A slug costs one extra lookup per run. Cannot change. */\n readonly team: string | number;\n /** Display name. Convex derives the slug from it at creation. A change renames the project. */\n readonly name: string;\n /** Region of the deployment created with the project. Defaults to the team default. Cannot change. */\n readonly deploymentRegion?: DeploymentRegion;\n /** Deployment created with the project. Defaults to `prod`. Cannot change. */\n readonly deploymentType?: \"prod\" | \"dev\";\n }\n | {\n /** Team slug or numeric team id. Cannot change. */\n readonly team: string | number;\n /** Slug of an existing project, such as `score-four`. The resource never creates a project. Cannot change. */\n readonly slug: string;\n };\n\nexport interface ProjectAttributes {\n readonly projectId: number;\n readonly slug: string;\n readonly name: string;\n readonly teamId: number;\n readonly prodDeploymentName: string | undefined;\n readonly prodDeploymentUrl: string | undefined;\n}\n\nexport type Project = Resource<\"Convex.Project\", ProjectProps, ProjectAttributes, never, Providers>;\nexport const Project = Resource<Project>(\"Convex.Project\", { defaultRemovalPolicy: \"retain\" });\n\n/** The props change the team of an existing project. Convex cannot move a project. */\nexport class ProjectTeamChange extends Schema.TaggedError<ProjectTeamChange>()(\n \"ProjectTeamChange\",\n { projectId: Schema.Number, teamId: Schema.Number, requestedTeamId: Schema.Number },\n) {\n override get message() {\n return `Convex.Project cannot move project ${this.projectId} from team ${this.teamId} to team ${this.requestedTeamId}. Set team back to ${this.teamId}. To use the other team, create a new resource with a new logical id and move the data yourself.`;\n }\n}\n\n/**\n * The props change `deploymentType` or `deploymentRegion` of an existing\n * project. Convex uses them only when it creates the project.\n */\nexport class ProjectDeploymentChange extends Schema.TaggedError<ProjectDeploymentChange>()(\n \"ProjectDeploymentChange\",\n {\n projectId: Schema.Number,\n field: Schema.Literals([\"deploymentType\", \"deploymentRegion\"]),\n current: Schema.UndefinedOr(Schema.String),\n requested: Schema.UndefinedOr(Schema.String),\n },\n) {\n override get message() {\n const show = (value: string | undefined) => (value === undefined ? \"(not set)\" : value);\n return `Convex.Project cannot change ${this.field} of project ${this.projectId} from ${show(this.current)} to ${show(this.requested)}: Convex uses it only when it creates a project. Set ${this.field} back to ${show(this.current)}. For a new deployment, create a new resource with a new logical id and move the data yourself.`;\n }\n}\n\n/** More than one project in the team has the name, so the lookup cannot choose one. */\nexport class AmbiguousProject extends Schema.TaggedError<AmbiguousProject>()(\"AmbiguousProject\", {\n teamId: Schema.Number,\n name: Schema.String,\n projectIds: Schema.Array(Schema.Number),\n}) {\n override get message() {\n return `Team ${this.teamId} has ${this.projectIds.length} projects named \"${this.name}\" (ids ${this.projectIds.join(\", \")}). Convex.Project does not choose one. Rename the projects in the Convex dashboard so that only one has this name, or use a different name.`;\n }\n}\n\n/** Convex answered a create call but then did not return the project. */\nexport class CreatedProjectNotFound extends Schema.TaggedError<CreatedProjectNotFound>()(\n \"CreatedProjectNotFound\",\n { projectId: Schema.Number },\n) {\n override get message() {\n return `Convex created project ${this.projectId} but GET /projects/${this.projectId} did not return it. Run the deploy again with --adopt to take over project ${this.projectId}.`;\n }\n}\n\n/** No project in the team has the slug. A `slug` resource never creates one. */\nexport class ProjectNotFound extends Schema.TaggedError<ProjectNotFound>()(\"ProjectNotFound\", {\n team: Schema.String,\n slug: Schema.String,\n}) {\n override get message() {\n return `Team ${this.team} has no project with the slug \"${this.slug}\", and a Convex.Project with a slug never creates one. Check the slug in the project URL of the Convex dashboard, or use name to create a project.`;\n }\n}\n\n/** The props change the slug of a `slug` resource: that is another project. */\nexport class ProjectSlugChange extends Schema.TaggedError<ProjectSlugChange>()(\n \"ProjectSlugChange\",\n { projectId: Schema.Number, slug: Schema.String, requestedSlug: Schema.String },\n) {\n override get message() {\n return `Convex.Project ${this.projectId} has the slug \"${this.slug}\", and the props ask for \"${this.requestedSlug}\", which is another project. Set slug back to \"${this.slug}\". For the other project, create a new resource with a new logical id.`;\n }\n}\n\n/** Fields of GET /projects/{id}, PATCH /projects/{id}, and GET /teams/{team}/projects rows that the provider uses. */\nconst ProjectDetails = Schema.Struct({\n id: Schema.Number,\n name: Schema.String,\n slug: Schema.String,\n teamId: Schema.Number,\n teamSlug: Schema.String,\n prodDeploymentName: Schema.NullOr(Schema.String),\n});\ntype ProjectDetails = typeof ProjectDetails.Type;\n\n/** GET /teams/{team_id}/projects: one page of projects. */\nexport const ProjectPage = Schema.Struct({\n items: Schema.Array(ProjectDetails),\n pagination: Schema.Struct({\n hasMore: Schema.Boolean,\n nextCursor: Schema.optionalKey(Schema.NullOr(Schema.String)),\n }),\n});\n\n/** POST /teams/{team_id}/create_project. Only the id: everything else comes from GET /projects/{id}. */\nconst CreatedProject = Schema.Struct({ projectId: Schema.Number });\n\nconst DeploymentRow = Schema.Struct({\n name: Schema.String,\n deploymentType: Schema.String,\n isDefault: Schema.Boolean,\n deploymentUrl: Schema.String,\n /** Absent or null until the first push. */\n lastDeployTime: Schema.optionalKey(Schema.NullOr(Schema.Number)),\n});\nconst DeploymentRows = Schema.Array(DeploymentRow);\n\n/**\n * Fails with {@link ProjectDeploymentChange} when a create-time prop\n * changed. An omitted `deploymentType` means `prod`.\n */\nconst checkCreateTimeProps = (\n projectId: number,\n olds: Extract<ProjectProps, { name: string }>,\n news: Extract<ProjectProps, { name: string }>,\n) => {\n const oldType = olds.deploymentType ?? \"prod\";\n const newType = news.deploymentType ?? \"prod\";\n if (oldType !== newType) {\n return Effect.fail(\n new ProjectDeploymentChange({\n projectId,\n field: \"deploymentType\",\n current: oldType,\n requested: newType,\n }),\n );\n }\n if (olds.deploymentRegion !== news.deploymentRegion) {\n return Effect.fail(\n new ProjectDeploymentChange({\n projectId,\n field: \"deploymentRegion\",\n current: olds.deploymentRegion,\n requested: news.deploymentRegion,\n }),\n );\n }\n return Effect.void;\n};\n\n/** True when `team`, a slug or a numeric id, names the team of the project. */\nconst isTeamOf = (details: ProjectDetails, team: string | number) =>\n typeof team === \"number\" || /^\\d+$/.test(team)\n ? details.teamId === Number(team)\n : details.teamSlug === team;\n\n/** The row of the project's default production deployment, or undefined. */\nexport const prodDeploymentOf = (api: ManagementApiService, projectId: number) =>\n api\n .request(\"list deployments\", (client) =>\n client.GET(\"/projects/{project_id}/list_deployments\", {\n params: { path: { project_id: projectId } },\n }),\n )\n .pipe(\n Effect.map((rows) =>\n Schema.decodeUnknownSync(DeploymentRows)(rows).find(\n (row) => row.deploymentType === \"prod\" && row.isDefault,\n ),\n ),\n );\n\n/** GET /projects/{id}, or undefined after a 404. */\nexport const getProjectById = (api: ManagementApiService, projectId: number) =>\n absentAsUndefined(\n api.request(\"get project\", (client) =>\n client.GET(\"/projects/{project_id}\", { params: { path: { project_id: projectId } } }),\n ),\n ).pipe(\n Effect.map((body) =>\n body === undefined ? undefined : Schema.decodeUnknownSync(ProjectDetails)(body),\n ),\n );\n\n/**\n * Every project in the team with exactly this name, in the order of the\n * listing. Reads every page. `q` narrows the listing on the server, and the\n * exact match here decides. Pattern from Confect\n * `packages/alchemy/src/ConvexClient.ts` and `Project.ts`\n * (https://github.com/rjdellecese/confect, ISC license).\n */\nexport const listProjectsByName = (api: ManagementApiService, teamId: number, name: string) =>\n Effect.gen(function* () {\n const matches: ProjectDetails[] = [];\n const seenCursors = new Set<string>();\n let cursor: string | undefined;\n while (true) {\n const body = yield* api.request(\"list projects\", (client) =>\n client.GET(\"/teams/{team_id}/projects\", {\n params: {\n path: { team_id: teamId },\n query: { q: name, ...(cursor === undefined ? {} : { cursor }) },\n },\n }),\n );\n const page = Schema.decodeUnknownSync(ProjectPage)(body);\n matches.push(...page.items.filter((row) => row.name === name));\n if (!page.pagination.hasMore) break;\n const next = page.pagination.nextCursor;\n if (next === undefined || next === null || seenCursors.has(next)) {\n return yield* new ConvexApiError({\n operation: \"list projects\",\n status: 0,\n code: \"InvalidPagination\",\n message: `The project listing of team ${teamId} reports more pages but gives no new cursor. Convex.Project stops so that it does not miss a project named \"${name}\".`,\n });\n }\n seenCursors.add(next);\n cursor = next;\n }\n return matches;\n });\n\n/** The one project in the team with exactly this name, or undefined. More than one is an error. */\nexport const findProjectByName = (api: ManagementApiService, teamId: number, name: string) =>\n listProjectsByName(api, teamId, name).pipe(\n Effect.flatMap((matches) =>\n matches.length > 1\n ? new AmbiguousProject({ teamId, name, projectIds: matches.map((row) => row.id) })\n : Effect.succeed(matches[0]),\n ),\n );\n\n/**\n * POST /teams/{team_id}/create_project, then GET /projects/{id}. The identity\n * comes from the create response, never from a name lookup.\n */\nexport const createProject = (\n api: ManagementApiService,\n teamId: number,\n props: {\n readonly name: string;\n readonly deploymentType: \"prod\" | \"dev\";\n readonly deploymentRegion: DeploymentRegion | undefined;\n },\n) =>\n Effect.gen(function* () {\n const created = yield* api.request(\"create project\", (client) =>\n client.POST(\"/teams/{team_id}/create_project\", {\n params: { path: { team_id: teamId } },\n body: {\n projectName: props.name,\n deploymentType: props.deploymentType,\n ...(props.deploymentRegion === undefined\n ? {}\n : { deploymentRegion: props.deploymentRegion }),\n },\n }),\n );\n const { projectId } = Schema.decodeUnknownSync(CreatedProject)(created);\n const details = yield* getProjectById(api, projectId);\n if (details === undefined) return yield* new CreatedProjectNotFound({ projectId });\n return details;\n });\n\nexport const ProjectProvider = () =>\n Provider.effect(\n Project,\n Effect.gen(function* () {\n const api = yield* ManagementApi;\n\n const attributesOf = (details: ProjectDetails) =>\n prodDeploymentOf(api, details.id).pipe(\n Effect.map((prod): ProjectAttributes => ({\n projectId: details.id,\n slug: details.slug,\n name: details.name,\n teamId: details.teamId,\n prodDeploymentName: prod?.name ?? details.prodDeploymentName ?? undefined,\n prodDeploymentUrl: prod?.deploymentUrl,\n })),\n );\n\n const getById = (projectId: number) => getProjectById(api, projectId);\n\n /** The project with this slug in the team, or undefined. Official endpoint; the team can be a slug. */\n const getBySlug = (team: string | number, slug: string) =>\n absentAsUndefined(\n api.request(\"get project by slug\", (client) =>\n client.GET(\"/teams/{team_id_or_slug}/projects/{project_slug}\", {\n params: { path: { team_id_or_slug: String(team), project_slug: slug } },\n }),\n ),\n ).pipe(\n Effect.map((body) =>\n body === undefined ? undefined : Schema.decodeUnknownSync(ProjectDetails)(body),\n ),\n );\n\n const findByName = (teamId: number, name: string) => findProjectByName(api, teamId, name);\n\n /**\n * Brings an existing project to the desired name. The team cannot\n * change, so a project in another team fails.\n */\n const converge = (details: ProjectDetails, teamId: number, name: string) =>\n Effect.gen(function* () {\n if (details.teamId !== teamId) {\n return yield* new ProjectTeamChange({\n projectId: details.id,\n teamId: details.teamId,\n requestedTeamId: teamId,\n });\n }\n if (details.name === name) return yield* attributesOf(details);\n const updated = yield* api.request(\"update project\", (client) =>\n client.PATCH(\"/projects/{project_id}\", {\n params: { path: { project_id: details.id } },\n body: { name },\n }),\n );\n return yield* attributesOf(Schema.decodeUnknownSync(ProjectDetails)(updated));\n });\n\n return {\n stables: [\"projectId\", \"slug\", \"teamId\"],\n\n diff: Effect.fn(function* ({ olds, news, output }) {\n if (!isResolved(news)) return undefined;\n // Nothing exists yet, so nothing can be lost.\n if (output === undefined) return undefined;\n if (\"slug\" in news) {\n if (news.slug !== output.slug) {\n return yield* new ProjectSlugChange({\n projectId: output.projectId,\n slug: output.slug,\n requestedSlug: news.slug,\n });\n }\n if (olds.team !== news.team) {\n const details = yield* getById(output.projectId);\n if (details !== undefined && !isTeamOf(details, news.team)) {\n return yield* new ProjectTeamChange({\n projectId: output.projectId,\n teamId: output.teamId,\n requestedTeamId: yield* api.resolveTeamId(news.team),\n });\n }\n }\n // The resource changes nothing on the project.\n return { action: \"noop\" } as const;\n }\n // A deploymentType or deploymentRegion change fails in reconcile,\n // before any API call. Reconcile compares with the props of the last\n // successful deploy. Here, `olds` can be the props of a refused\n // update, so a check here would also refuse the props that fix it.\n if (olds.team !== news.team) {\n const requestedTeamId = yield* api.resolveTeamId(news.team);\n if (requestedTeamId !== output.teamId) {\n return yield* new ProjectTeamChange({\n projectId: output.projectId,\n teamId: output.teamId,\n requestedTeamId,\n });\n }\n }\n // Never \"replace\". A name change is an update; reconcile renames\n // the project with PATCH. Otherwise the engine compares the props.\n return \"name\" in olds && olds.name === news.name\n ? undefined\n : ({ action: \"update\" } as const);\n }),\n\n read: Effect.fn(function* ({ olds, output }) {\n if (output !== undefined) {\n const details = yield* getById(output.projectId);\n return details === undefined ? undefined : yield* attributesOf(details);\n }\n // No state: an existing project belongs to someone else until the\n // user passes --adopt. Convex has no ownership tags.\n const existing =\n \"slug\" in olds\n ? yield* getBySlug(olds.team, olds.slug)\n : yield* findByName(yield* api.resolveTeamId(olds.team), olds.name);\n return existing === undefined ? undefined : Unowned(yield* attributesOf(existing));\n }),\n\n reconcile: Effect.fn(function* ({ fqn, olds, news, output }) {\n if (\"slug\" in news) {\n // An existing project: found, checked, never created or changed.\n const details =\n output === undefined\n ? yield* getBySlug(news.team, news.slug)\n : yield* getById(output.projectId);\n if (details === undefined) {\n return yield* new ProjectNotFound({ team: String(news.team), slug: news.slug });\n }\n if (details.slug !== news.slug) {\n return yield* new ProjectSlugChange({\n projectId: details.id,\n slug: details.slug,\n requestedSlug: news.slug,\n });\n }\n if (!isTeamOf(details, news.team)) {\n return yield* new ProjectTeamChange({\n projectId: details.id,\n teamId: details.teamId,\n requestedTeamId: yield* api.resolveTeamId(news.team),\n });\n }\n if (output === undefined && !(yield* shouldAdopt(fqn))) {\n return yield* new OwnedBySomeoneElse({\n message: `Convex project ${details.id} (\"${news.slug}\") exists and is not in this stack's state. Re-run with --adopt to take it over.`,\n resourceType: Project.Type,\n physicalName: news.slug,\n });\n }\n return yield* attributesOf(details);\n }\n const teamId = yield* api.resolveTeamId(news.team);\n if (output !== undefined) {\n // State names the project. Never look it up by name here.\n if (olds !== undefined && \"name\" in olds) {\n yield* checkCreateTimeProps(output.projectId, olds, news);\n }\n if (output.teamId !== teamId) {\n return yield* new ProjectTeamChange({\n projectId: output.projectId,\n teamId: output.teamId,\n requestedTeamId: teamId,\n });\n }\n const details = yield* getById(output.projectId);\n if (details !== undefined) return yield* converge(details, teamId, news.name);\n // The project in state was deleted outside Alchemy. Creating a\n // new project below loses nothing.\n } else {\n // No state: a project with this name is someone else's unless\n // adoption is on. The engine checked this in plan; this check\n // covers a project that appeared after the plan.\n const existing = yield* findByName(teamId, news.name);\n if (existing !== undefined) {\n if (!(yield* shouldAdopt(fqn))) {\n return yield* new OwnedBySomeoneElse({\n message: `Convex project ${existing.id} in team ${teamId} already has the name \"${news.name}\". Re-run with --adopt to take it over, or use a different name.`,\n resourceType: Project.Type,\n physicalName: news.name,\n });\n }\n return yield* converge(existing, teamId, news.name);\n }\n }\n const details = yield* createProject(api, teamId, {\n name: news.name,\n deploymentType: news.deploymentType ?? \"prod\",\n deploymentRegion: news.deploymentRegion,\n });\n return yield* converge(details, teamId, news.name);\n }),\n\n // Runs only with `RemovalPolicy.destroy()`: the default policy is `retain`.\n delete: Effect.fn(function* ({ output }) {\n yield* absentAsUndefined(\n api.requestVoid(\"delete project\", (client) =>\n client.POST(\"/projects/{project_id}/delete\", {\n params: { path: { project_id: output.projectId } },\n }),\n ),\n );\n }),\n };\n }),\n );\n","// The provider collection users merge into a stack:\n// providers: Layer.mergeAll(Cloudflare.providers(), Convex.providers())\nimport * as Provider from \"alchemy/Provider\";\nimport * as Layer from \"effect/Layer\";\nimport { type Credentials, fromConfig } from \"./Credentials.ts\";\nimport { DeploymentProvider, DeploymentResource } from \"./Deployment.ts\";\nimport { ManagementApiLive } from \"./ManagementApi.ts\";\nimport { Project, ProjectProvider } from \"./Project.ts\";\n\nexport class Providers extends Provider.ProviderCollection<Providers>()(\"Convex\") {}\n\n/**\n * The Convex resource providers. Pass a credentials layer to override the\n * default lookup (`CONVEX_ACCESS_TOKEN`, then the Convex CLI login, and\n * `CONVEX_DEPLOY_KEY`).\n */\nexport const providers = (credentials: Layer.Layer<Credentials> = fromConfig()) =>\n Layer.effect(Providers, Provider.collection([Project, DeploymentResource])).pipe(\n Layer.provide(Layer.mergeAll(ProjectProvider(), DeploymentProvider())),\n Layer.provide(ManagementApiLive()),\n Layer.provide(credentials),\n Layer.orDie,\n );\n","// The run record: what the stage output says about the run that wrote it.\n// Alchemy state holds no time, author, commit, branch, or run (measured in\n// the Samebase research of 2026-10-21), so a state layer adds this record to\n// the output document under the reserved key `samebase.run`. The record\n// depends on no store: it comes from the GitHub Actions variables, or from\n// git on a laptop, and holds no secret. See docs/design/convex-state.md.\nimport { execFile } from \"node:child_process\";\nimport { readFile, realpath } from \"node:fs/promises\";\nimport { relative, sep } from \"node:path\";\nimport { promisify } from \"node:util\";\nimport * as Clock from \"effect/Clock\";\nimport * as Effect from \"effect/Effect\";\nimport * as Schema from \"effect/Schema\";\n\n/** The key of the record in the stage output document. */\nexport const RUN_RECORD_KEY = \"samebase.run\";\n\n/** The name of the stack file. Alchemy resolves `--config` against the working directory and does not expose it to a state layer, so the record assumes the default name. */\nexport const STACK_FILE_NAME = \"alchemy.run.ts\";\n\n/** Version 1 of the record. A reader validates `version` first. */\nexport interface RunRecord {\n readonly version: 1;\n /** GitHub `owner/name`. */\n readonly repository: string;\n /** Path of the stack file from the repository root, POSIX separators, such as `apps/samebase/alchemy.run.ts`. */\n readonly stackFile: string;\n /** The branch that was deployed: the head branch of a pull request, else the pushed branch. */\n readonly branch: string;\n /** The pull request whose head was deployed, or null for a push and for a laptop. */\n readonly pullRequest: number | null;\n /** The commit that was deployed: the head of the pull request, else GITHUB_SHA, else git HEAD. */\n readonly headCommit: string;\n /** The GitHub Actions run and attempt, or null for a laptop. */\n readonly runUrl: string | null;\n readonly source: \"github-actions\" | \"laptop\";\n /** ISO 8601, when the record was written. */\n readonly recordedAt: string;\n}\n\nexport class RunRecordError extends Schema.TaggedError<RunRecordError>()(\"RunRecordError\", {\n reason: Schema.String,\n}) {\n override get message() {\n return `The run record of the stage output cannot be made: ${this.reason}`;\n }\n}\n\n/** Where the run happens: the working directory of the stack and the process environment. */\nexport interface RunEnvironment {\n readonly cwd: string;\n readonly env: Readonly<Record<string, string | undefined>>;\n}\n\n/** The part of the GitHub Actions event payload that the record reads. A push event has no `pull_request`. */\nconst EventPayload = Schema.Struct({\n pull_request: Schema.optionalKey(\n Schema.Struct({ number: Schema.Number, head: Schema.Struct({ sha: Schema.String }) }),\n ),\n});\n\n/** `owner/name` of an https, ssh, or scp-like git URL with a host. A local path is not one. */\nconst REMOTE_URL = /^(?:[a-z+]+:\\/\\/[^/]+\\/|[^/@:]+@[^:/]+:)([^/]+)\\/([^/]+?)(?:\\.git)?\\/?$/;\n\nconst execFileAsync = promisify(execFile);\n\nconst now = Clock.currentTimeMillis.pipe(Effect.map((millis) => new Date(millis).toISOString()));\n\nconst git = (cwd: string, args: readonly string[]) =>\n Effect.tryPromise({\n try: async () =>\n (await execFileAsync(\"git\", [\"-C\", cwd, ...args], { encoding: \"utf8\" })).stdout.trim(),\n catch: (error) =>\n new RunRecordError({\n reason: `git ${args.join(\" \")} failed in ${cwd} (${error instanceof Error ? error.message.split(\"\\n\")[0] : String(error)})`,\n }),\n });\n\n/** The stack file from the repository root: the working directory below the git top level, plus {@link STACK_FILE_NAME}. */\nconst stackFileOf = (cwd: string) =>\n Effect.gen(function* () {\n const top = yield* git(cwd, [\"rev-parse\", \"--show-toplevel\"]);\n // git prints the real path, and the working directory can hold a symlink, such as macOS /tmp.\n const [realTop, realCwd] = yield* Effect.tryPromise({\n try: () => Promise.all([realpath(top), realpath(cwd)]),\n catch: () => new RunRecordError({ reason: `${cwd} is gone` }),\n });\n const directory = relative(realTop, realCwd)\n .split(sep)\n .filter((part) => part !== \"\");\n return [...directory, STACK_FILE_NAME].join(\"/\");\n });\n\nconst variable = (env: RunEnvironment[\"env\"], name: string) =>\n Effect.suspend(() => {\n const value = env[name];\n return value === undefined || value === \"\"\n ? Effect.fail(\n new RunRecordError({ reason: `GITHUB_ACTIONS is true, and ${name} is not set` }),\n )\n : Effect.succeed(value);\n });\n\nconst fromGitHubActions = (where: RunEnvironment) =>\n Effect.gen(function* () {\n const { env } = where;\n const repository = yield* variable(env, \"GITHUB_REPOSITORY\");\n const refName = yield* variable(env, \"GITHUB_REF_NAME\");\n const sha = yield* variable(env, \"GITHUB_SHA\");\n const serverUrl = yield* variable(env, \"GITHUB_SERVER_URL\");\n const runId = yield* variable(env, \"GITHUB_RUN_ID\");\n const runAttempt = yield* variable(env, \"GITHUB_RUN_ATTEMPT\");\n const eventPath = env[\"GITHUB_EVENT_PATH\"];\n const payload =\n eventPath === undefined || eventPath === \"\"\n ? undefined\n : yield* Effect.tryPromise({\n try: () => readFile(eventPath, \"utf8\"),\n catch: () =>\n new RunRecordError({ reason: `GITHUB_EVENT_PATH ${eventPath} cannot be read` }),\n }).pipe(\n Effect.flatMap(Schema.decodeUnknownEffect(Schema.fromJsonString(EventPayload))),\n Effect.mapError((error) =>\n error instanceof RunRecordError\n ? error\n : new RunRecordError({\n reason: `GITHUB_EVENT_PATH ${eventPath} is not an event payload`,\n }),\n ),\n );\n const pullRequest = payload?.pull_request;\n // GITHUB_SHA is the merge commit on a pull request event; the head of the pull request is what a person sees.\n const headCommit = pullRequest?.head.sha ?? sha;\n const headRef = env[\"GITHUB_HEAD_REF\"];\n const mergeRef = /^refs\\/pull\\/(\\d+)\\/merge$/.exec(env[\"GITHUB_REF\"] ?? \"\");\n const stackFile = yield* stackFileOf(where.cwd);\n const record: RunRecord = {\n version: 1,\n repository,\n stackFile,\n branch: headRef === undefined || headRef === \"\" ? refName : headRef,\n pullRequest: pullRequest?.number ?? (mergeRef === null ? null : Number(mergeRef[1])),\n headCommit,\n runUrl: `${serverUrl}/${repository}/actions/runs/${runId}/attempts/${runAttempt}`,\n source: \"github-actions\",\n recordedAt: yield* now,\n };\n return record;\n });\n\nconst fromGit = (where: RunEnvironment) =>\n Effect.gen(function* () {\n const { cwd } = where;\n const origin = yield* git(cwd, [\"remote\", \"get-url\", \"origin\"]);\n const match = REMOTE_URL.exec(origin);\n if (match === null) {\n return yield* new RunRecordError({\n reason: `the origin remote of ${cwd} is not a git URL with a host and owner/name: ${origin}`,\n });\n }\n const branch = yield* git(cwd, [\"rev-parse\", \"--abbrev-ref\", \"HEAD\"]);\n if (branch === \"HEAD\") {\n return yield* new RunRecordError({\n reason: `the checkout at ${cwd} is on no branch (detached HEAD)`,\n });\n }\n const record: RunRecord = {\n version: 1,\n repository: `${match[1]}/${match[2]}`,\n stackFile: yield* stackFileOf(cwd),\n branch,\n pullRequest: null,\n headCommit: yield* git(cwd, [\"rev-parse\", \"HEAD\"]),\n runUrl: null,\n source: \"laptop\",\n recordedAt: yield* now,\n };\n return record;\n });\n\n/**\n * The record of this run: from the GitHub Actions variables and the event\n * payload when GITHUB_ACTIONS is `true`, else from git in `cwd`, which needs\n * a branch and an `origin` remote with `owner/name`. Fails when a value is\n * missing; nothing is guessed.\n */\nexport const runRecord = (where: RunEnvironment): Effect.Effect<RunRecord, RunRecordError> =>\n where.env[\"GITHUB_ACTIONS\"] === \"true\" ? fromGitHubActions(where) : fromGit(where);\n\n/** A plain object, which a spread keeps whole. A Date, a Duration, or a Redacted value is an object too, and a spread loses it. */\nconst isPlainObject = (value: unknown): value is Record<string, unknown> => {\n if (typeof value !== \"object\" || value === null) return false;\n const prototype: unknown = Object.getPrototypeOf(value);\n return prototype === Object.prototype || prototype === null;\n};\n\n/**\n * The output document of a stage: the stack's output plus the record under\n * {@link RUN_RECORD_KEY}, or undefined for an output with no place for the\n * key: a string, an array, null, or an object that is not plain, such as a\n * Date. A value that the stack itself put under the key stays.\n */\nexport const withRunRecord = (output: unknown, record: RunRecord): object | undefined =>\n isPlainObject(output)\n ? RUN_RECORD_KEY in output\n ? output\n : { ...output, [RUN_RECORD_KEY]: record }\n : undefined;\n","// Alchemy state in Convex: `state: Convex.state({ team })` in `Alchemy.Stack`.\n//\n// One project for each Convex team, `samebase`, holds the state of\n// every stack and stage of the team in its production deployment: the\n// tables `resources (stack, stage, fqn, value)` and `outputs (stack, stage,\n// value)` of the alchemyState component (src/store/component), served by the\n// functions of src/store/convex. The store lives\n// outside every resource that a stack manages, so a stack can create and\n// destroy its own project. See docs/design/convex-state.md.\n//\n// Bootstrap, on the first call of the run: the team token (CONVEX_ACCESS_TOKEN,\n// or the Convex CLI login) finds the project by name, or creates it; a deploy\n// key of its production deployment that can run internal queries and\n// mutations, and nothing else, is created for the run and deleted at its\n// end; the `state:version` query says whether the deployment has the store\n// of this version. Without one, or with an older one, the installed Convex\n// CLI pushes src/store/convex to it, with a push key that is deleted after\n// the push. The raw state functions are internal; authenticated readers get\n// repository-scoped subscriptions with secret values removed. A key that stops working during a\n// long run (it expires after two hours) is replaced once per call.\n//\n// Two first runs of a team can both create a project named `samebase`.\n// The run whose project is not the oldest deletes its own, before it writes\n// anything, and uses the oldest: both runs end on one store.\n//\n// Samebase reads `stacks`, `getOutput`, `readStack`, and `reader:repository`\n// by name. The store and its readers are released and upgraded together:\n// STORE_VERSION rises with each change of a function, and a client works only\n// with a store of its own version. An older store is pushed over; a newer one\n// fails the run.\n//\n// The stage output that `setOutput` stores is the stack's output plus the\n// run record of src/RunRecord.ts under the key `samebase.run`: the\n// repository, stack file, branch, pull request, commit, and run that wrote\n// the stage. `getOutput` gives the document back as stored.\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport * as Clock from \"effect/Clock\";\nimport * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\nimport * as ChildProcessSpawner from \"effect/process/ChildProcessSpawner\";\nimport * as Redacted from \"effect/Redacted\";\nimport * as Schedule from \"effect/Schedule\";\nimport * as Schema from \"effect/Schema\";\nimport * as Scope from \"effect/Scope\";\nimport {\n encodeState,\n type PersistedState,\n type ReplacedResourceState,\n reviveState,\n State,\n type StateService,\n STATE_STORE_VERSION,\n StateStoreError,\n} from \"alchemy/State\";\nimport { fromConfig } from \"./Credentials.ts\";\nimport { ProductionDeploymentNotFound } from \"./Deployment.ts\";\nimport {\n absentAsUndefined,\n ManagementApi,\n ManagementApiLive,\n type ManagementApiService,\n retryIdempotentWrite,\n} from \"./ManagementApi.ts\";\nimport {\n createProject,\n findProjectByName,\n listProjectsByName,\n prodDeploymentOf,\n} from \"./Project.ts\";\nimport {\n createDeployKey,\n deleteDeployKey,\n installedCli,\n push,\n PUSH_KEY_ACTIONS,\n withPushKey,\n} from \"./Push.ts\";\nimport { type RunRecord, runRecord, withRunRecord } from \"./RunRecord.ts\";\nimport { STORE_VERSION } from \"./store/convex/version.ts\";\n\n/** The name of the state project in each team. */\nexport const STORE_PROJECT_NAME = \"samebase\";\n\n/**\n * The actions of the key of one run: the internal queries and mutations of\n * the store, nothing else. Measured: `deployment:data:view` and\n * `deployment:data:write` do not run an internal function.\n */\nexport const RUN_KEY_ACTIONS = [\n \"deployment:functions:runInternalQueries\",\n \"deployment:functions:runInternalMutations\",\n] as const;\n\n/** The body of POST /api/function, with HTTP 200 for a function error too. */\nconst Reply = Schema.Union([\n Schema.Struct({ status: Schema.Literal(\"success\"), value: Schema.Unknown }),\n Schema.Struct({ status: Schema.Literal(\"error\"), errorMessage: Schema.String }),\n]);\ntype Reply = typeof Reply.Type;\n\n/** The error reply of /api/function for a function that the deployment does not have (recorded). */\nconst MISSING_FUNCTION = /Could not find function for '/;\n\n/** HTTP 401 or 403 from the function API: the key is gone or expired (recorded: 403 without a key). */\nconst isUnauthorized = (error: StateStoreError) =>\n error.http?.status === 401 || error.http?.status === 403;\n\nconst failure = (message: string) => new StateStoreError({ message: `Convex state: ${message}` });\n\n/** No reply, HTTP 429, or HTTP 5xx: a new attempt can succeed. Every call of the store is idempotent. */\nconst isTransient = (error: StateStoreError) =>\n error.http !== undefined &&\n (error.http.status === undefined || error.http.status === 429 || error.http.status >= 500);\n\nconst post = (\n url: string,\n headers: Record<string, string>,\n body: unknown,\n): Effect.Effect<unknown, StateStoreError> =>\n Effect.tryPromise({\n try: () =>\n fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", ...headers },\n body: JSON.stringify(body),\n }),\n catch: () => new StateStoreError({ message: `Convex state: POST ${url} failed`, http: {} }),\n }).pipe(\n Effect.flatMap((response) =>\n response.ok || response.status === 560\n ? Effect.tryPromise({\n try: (): Promise<unknown> => response.json(),\n catch: () => failure(`${url} gave no JSON`),\n })\n : Effect.fail(\n new StateStoreError({\n message: `Convex state: POST ${url} failed with HTTP ${response.status}`,\n http: { status: response.status },\n }),\n ),\n ),\n Effect.retry({\n while: isTransient,\n schedule: Schedule.exponential(\"100 millis\").pipe(Schedule.jittered),\n times: 5,\n }),\n );\n\nconst decode =\n <S extends Schema.Codec<unknown, unknown>>(schema: S, what: string) =>\n (value: unknown) =>\n Schema.decodeUnknownEffect(schema)(value).pipe(Effect.mapError(() => failure(`bad ${what}`)));\n\n/** The function API of the store deployment, with a deploy key. */\nexport interface FunctionApi {\n /** POST /api/function, the call that `convex run` makes: the reply, which can be a function error. */\n readonly call: (\n path: string,\n args: Record<string, string | RunRecord | undefined>,\n ) => Effect.Effect<Reply, StateStoreError>;\n}\n\nexport const makeFunctionApi = (url: string, key: Redacted.Redacted<string>): FunctionApi => ({\n call: (path, args) =>\n post(\n `${url}/api/function`,\n { Authorization: `Convex ${Redacted.value(key)}` },\n { path, args, format: \"json\" },\n ).pipe(Effect.flatMap(decode(Reply, `reply of ${path}`))),\n});\n\n/** The value of a reply, or the Convex message, which names the function and the cause, such as a missing key action. */\nconst valueOf = (reply: Reply) =>\n reply.status === \"success\"\n ? Effect.succeed(reply.value)\n : Effect.fail(failure(reply.errorMessage.trim()));\n\n/** The functions of the store with Alchemy's encoding: the JSON text of encodeState. */\nconst remoteOf = (api: FunctionApi, record: RunRecord | undefined) => {\n const run = (name: string, args: Record<string, string | RunRecord | undefined>) =>\n api.call(`state:${name}`, args).pipe(Effect.flatMap(valueOf));\n const write = (name: string, args: Record<string, string>) =>\n Effect.gen(function* () {\n const currentRun =\n record === undefined\n ? undefined\n : {\n ...record,\n recordedAt: new Date(yield* Clock.currentTimeMillis).toISOString(),\n };\n return yield* run(name, { ...args, run: currentRun });\n });\n const strings = (name: string, args: Record<string, string>) =>\n run(name, args).pipe(Effect.flatMap(decode(Schema.Array(Schema.String), name)));\n const optional = (name: string, args: Record<string, string>) =>\n run(name, args).pipe(Effect.flatMap(decode(Schema.NullOr(Schema.String), name)));\n const encode = (value: unknown) => JSON.stringify(encodeState(value));\n return {\n listStacks: () => strings(\"stacks\", {}),\n listStages: (stack: string) => strings(\"stages\", { stack }),\n list: (r: { stack: string; stage: string }) =>\n strings(\"list\", { stack: r.stack, stage: r.stage }),\n // Like Alchemy's own stores, the store gives back the state that it got.\n get: (r: { stack: string; stage: string; fqn: string }) =>\n optional(\"get\", { stack: r.stack, stage: r.stage, fqn: r.fqn }).pipe(\n Effect.map((text): PersistedState | undefined =>\n text === null ? undefined : JSON.parse(text, reviveState),\n ),\n ),\n getReplacedResources: (r: { stack: string; stage: string }) =>\n strings(\"replaced\", { stack: r.stack, stage: r.stage }).pipe(\n Effect.map((texts) =>\n texts.map((text): ReplacedResourceState => JSON.parse(text, reviveState)),\n ),\n ),\n getOutput: (r: { stack: string; stage: string }) =>\n optional(\"getOutput\", { stack: r.stack, stage: r.stage }).pipe(\n Effect.map((text): unknown => (text === null ? undefined : JSON.parse(text, reviveState))),\n ),\n set: (r: { stack: string; stage: string; fqn: string; value: PersistedState }) =>\n write(\"set\", { stack: r.stack, stage: r.stage, fqn: r.fqn, value: encode(r.value) }),\n delete: (r: { stack: string; stage: string; fqn: string }) =>\n write(\"remove\", { stack: r.stack, stage: r.stage, fqn: r.fqn }),\n deleteStack: (r: { stack: string; stage?: string }) =>\n run(\"removeStack\", { stack: r.stack, stage: r.stage }),\n setOutput: (r: { stack: string; stage: string; value: unknown }) =>\n write(\"setOutput\", { stack: r.stack, stage: r.stage, value: encode(r.value) }),\n };\n};\n\n/** The version that the store answers, or undefined when the deployment has no `state:version`. */\nconst storeVersion = (api: FunctionApi) =>\n api\n .call(\"state:version\", {})\n .pipe(\n Effect.flatMap((reply) =>\n reply.status === \"error\" && MISSING_FUNCTION.test(reply.errorMessage)\n ? Effect.succeed(undefined)\n : valueOf(reply).pipe(Effect.flatMap(decode(Schema.Number, \"store version\"))),\n ),\n );\n\n/**\n * The functions directory of the store app, `src/store/convex` of this\n * package. This file is `src/State.ts` in a checkout and a chunk in `lib/`\n * in the installed package, which ships `src` too, so the directory is\n * `../src/store/convex` from either place. Its `convex.config.ts` mounts the\n * alchemyState component of `src/store/component`, inside the same push root.\n */\nexport const storeDirectory = () =>\n join(dirname(fileURLToPath(import.meta.url)), \"..\", \"src\", \"store\", \"convex\");\n\nexport interface StoreOptions {\n /** Team slug or numeric team id of the `samebase` project, or undefined with a team access token, which names its team. */\n readonly team: string | number | undefined;\n readonly api: ManagementApiService;\n readonly spawner: ChildProcessSpawner.ChildProcessSpawner[\"Service\"];\n /** The key of the run is deleted when this scope closes. */\n readonly scope: Scope.Scope;\n /** The functions directory that an outdated store gets: {@link storeDirectory}. */\n readonly store: string;\n /** The run recorded with resource writes and output, or undefined for a run without one. */\n readonly run: RunRecord | undefined;\n}\n\n/**\n * Pushes `store` to the production deployment of the state project with the\n * installed Convex CLI: no typecheck, no codegen, the key only in the\n * environment of the CLI.\n */\nconst pushStore = (\n options: StoreOptions,\n deployment: { readonly name: string; readonly deploymentUrl: string },\n) =>\n Effect.gen(function* () {\n const cli = yield* installedCli(join(options.store, \"..\"));\n yield* Effect.logInfo(\n `Convex state: pushing the store version ${STORE_VERSION} to ${deployment.name}`,\n );\n yield* withPushKey(options.api, deployment.name, PUSH_KEY_ACTIONS, (key) =>\n push(options.spawner, key, {\n deployment: deployment.name,\n url: deployment.deploymentUrl,\n rootDir: join(options.store, \"..\"),\n source: {\n path: options.store,\n command: [...cli, \"deploy\", \"--typecheck\", \"disable\", \"--codegen\", \"disable\"],\n },\n env: {},\n previousEnvNames: [],\n adopt: false,\n previewName: undefined,\n }),\n );\n });\n\n/**\n * Creates the state project of the team. Two first runs can both create one:\n * the run whose project is not the oldest deletes its own, which holds\n * nothing yet, and uses the oldest, so that every run ends on one store.\n */\nconst createStoreProject = (api: ManagementApiService, teamId: number, team: string | number) =>\n Effect.gen(function* () {\n yield* Effect.logInfo(\n `Convex state: creating the project ${STORE_PROJECT_NAME} in team ${team}`,\n );\n const created = yield* createProject(api, teamId, {\n name: STORE_PROJECT_NAME,\n deploymentType: \"prod\",\n deploymentRegion: undefined,\n });\n const all = yield* listProjectsByName(api, teamId, STORE_PROJECT_NAME);\n const oldest = all.reduce((a, b) => (b.id < a.id ? b : a), created);\n if (oldest.id === created.id) return created;\n yield* Effect.logInfo(\n `Convex state: another run created ${STORE_PROJECT_NAME} ${oldest.id} first; project ${created.id} is deleted again.`,\n );\n yield* absentAsUndefined(\n retryIdempotentWrite(\n api.requestVoid(\"delete project\", (client) =>\n client.POST(\"/projects/{project_id}/delete\", {\n params: { path: { project_id: created.id } },\n }),\n ),\n ),\n );\n return oldest;\n });\n\n/**\n * The StateService over the `samebase` project of the team: found or\n * created, its store pushed when it is missing or older, and read and\n * written with the keys of this run.\n */\nexport const makeConvexState = (options: StoreOptions) =>\n Effect.gen(function* () {\n const { api } = options;\n const teamId = yield* api.resolveTeamId(options.team);\n const team = options.team ?? teamId;\n const found = yield* findProjectByName(api, teamId, STORE_PROJECT_NAME);\n const project = found ?? (yield* createStoreProject(api, teamId, team));\n const deployment = yield* prodDeploymentOf(api, project.id);\n if (deployment === undefined) {\n return yield* new ProductionDeploymentNotFound({ projectId: project.id });\n }\n\n // The keys of this run, deleted together when the scope closes. A call\n // that the current key no longer authorizes gets one new key and one\n // more attempt.\n const keys: Redacted.Redacted<string>[] = [];\n yield* Scope.addFinalizer(\n options.scope,\n Effect.suspend(() =>\n Effect.forEach(keys, (key) => deleteDeployKey(api, deployment.name, key), {\n discard: true,\n }),\n ),\n );\n const mint = createDeployKey(api, deployment.name, STORE_PROJECT_NAME, RUN_KEY_ACTIONS).pipe(\n Effect.map((key) => {\n keys.push(key);\n return makeFunctionApi(deployment.deploymentUrl, key);\n }),\n Effect.mapError((error) => failure(`no key for ${deployment.name}: ${error.message}`)),\n );\n let current = yield* mint;\n const functions: FunctionApi = {\n call: (path, args) =>\n current.call(path, args).pipe(\n Effect.catchIf(isUnauthorized, () =>\n mint.pipe(\n Effect.flatMap((next) => {\n current = next;\n return next.call(path, args);\n }),\n ),\n ),\n ),\n };\n\n let version = yield* storeVersion(functions);\n if (version === undefined || version < STORE_VERSION) {\n // Code without `state:version` is another app with the name of the store.\n if (version === undefined && deployment.lastDeployTime) {\n return yield* failure(\n `project ${STORE_PROJECT_NAME} (${project.id}) of team ${team} has code that is not the state store, and Convex.state does not push over it. Rename that project in the Convex dashboard.`,\n );\n }\n // Another run can push a newer store in the meantime: read again right\n // before the push. The push itself has no lock (see the design note).\n version = yield* storeVersion(functions);\n if (version === undefined || version < STORE_VERSION) {\n yield* pushStore(options, deployment);\n version = yield* storeVersion(functions);\n }\n }\n if (version !== STORE_VERSION) {\n return yield* failure(\n `${deployment.name} answers store version ${version ?? \"none\"}, and this package needs store version ${STORE_VERSION}.`,\n );\n }\n\n const remote = remoteOf(functions, options.run);\n /** The stack's output plus the record, when the run has one and the output has a place for it. */\n const documentOf = (request: { stack: string; stage: string; value: unknown }) =>\n Effect.gen(function* () {\n const { run } = options;\n if (run === undefined) return request.value;\n const recordedAt = new Date(yield* Clock.currentTimeMillis).toISOString();\n const document = withRunRecord(request.value, { ...run, recordedAt });\n if (document === undefined) {\n yield* Effect.logWarning(\n `Convex state: the output of ${request.stack}/${request.stage} is not a plain object, so it carries no run record.`,\n );\n return request.value;\n }\n return document;\n });\n const service: StateService = {\n id: \"convex\",\n getVersion: () => Effect.succeed(STATE_STORE_VERSION),\n listStacks: remote.listStacks,\n listStages: remote.listStages,\n list: remote.list,\n get: remote.get,\n getReplacedResources: remote.getReplacedResources,\n getOutput: remote.getOutput,\n set: (request) => remote.set(request).pipe(Effect.as(request.value)),\n delete: (request) => remote.delete(request).pipe(Effect.asVoid),\n deleteStack: (request) => remote.deleteStack(request).pipe(Effect.asVoid),\n // The document is the stack's output plus the record under `samebase.run`.\n setOutput: (request) =>\n Effect.gen(function* () {\n const value = yield* documentOf(request);\n yield* remote.setOutput({ stack: request.stack, stage: request.stage, value });\n return value;\n }),\n };\n return service;\n });\n\n/**\n * Alchemy state in the `samebase` project of `team`, with the team token\n * in CONVEX_ACCESS_TOKEN or the Convex CLI login. A team access token names\n * its team, so `team` is optional with one; the Convex CLI login needs the\n * slug or the id. The first use of the run finds or creates the project and\n * pushes the store when it is missing or older. `alchemy plan` on another\n * stack never touches Convex.\n */\nexport const state = (\n options: { readonly team?: string | number } = {},\n): Layer.Layer<State, never, ChildProcessSpawner.ChildProcessSpawner> =>\n Layer.effect(\n State,\n Effect.gen(function* () {\n const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;\n const scope = yield* Scope.Scope;\n // The stack's ConfigProvider, for the read of the token on first use.\n const context = yield* Effect.context<never>();\n return yield* Effect.cached(\n Effect.gen(function* () {\n const api = yield* ManagementApi.pipe(\n Effect.provide(ManagementApiLive().pipe(Layer.provide(fromConfig()))),\n );\n // The record is derived once, before the first read. A checkout\n // that gives none, such as a tarball without git, a checkout\n // without origin, or a detached HEAD, still reads, plans, and\n // destroys: its outputs are written without the record, and the\n // log says why.\n const run = yield* runRecord({ cwd: process.cwd(), env: process.env }).pipe(\n Effect.catch((error) =>\n Effect.logWarning(\n `Convex state: the stage outputs of this run carry no record. ${error.message}`,\n ).pipe(Effect.as(undefined)),\n ),\n );\n return yield* makeConvexState({\n team: options.team,\n api,\n spawner,\n scope,\n store: storeDirectory(),\n run,\n });\n }).pipe(Effect.provideContext(context), Effect.orDie),\n );\n }),\n );\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@samebase/alchemy-convex",
3
- "version": "0.12.0",
3
+ "version": "0.13.0",
4
4
  "description": "The Convex plane for Alchemy v2: projects, deployments, environment variables, and the push of the functions",
5
5
  "keywords": [
6
6
  "alchemy",
@@ -31,6 +31,10 @@
31
31
  ".": {
32
32
  "types": "./lib/index.d.ts",
33
33
  "import": "./lib/index.js"
34
+ },
35
+ "./state/convex.config": {
36
+ "types": "./src/store/component/convex.config.ts",
37
+ "default": "./src/store/component/convex.config.ts"
34
38
  }
35
39
  },
36
40
  "publishConfig": {
package/src/State.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  // Alchemy state in Convex: `state: Convex.state({ team })` in `Alchemy.Stack`.
2
2
  //
3
- // One project for each Convex team, `alchemy-state`, holds the state of
3
+ // One project for each Convex team, `samebase`, holds the state of
4
4
  // every stack and stage of the team in its production deployment: the
5
5
  // tables `resources (stack, stage, fqn, value)` and `outputs (stack, stage,
6
6
  // value)` of the alchemyState component (src/store/component), served by the
@@ -19,7 +19,7 @@
19
19
  // repository-scoped subscriptions with secret values removed. A key that stops working during a
20
20
  // long run (it expires after two hours) is replaced once per call.
21
21
  //
22
- // Two first runs of a team can both create a project named `alchemy-state`.
22
+ // Two first runs of a team can both create a project named `samebase`.
23
23
  // The run whose project is not the oldest deletes its own, before it writes
24
24
  // anything, and uses the oldest: both runs end on one store.
25
25
  //
@@ -80,7 +80,7 @@ import { type RunRecord, runRecord, withRunRecord } from "./RunRecord.ts";
80
80
  import { STORE_VERSION } from "./store/convex/version.ts";
81
81
 
82
82
  /** The name of the state project in each team. */
83
- export const STORE_PROJECT_NAME = "alchemy-state";
83
+ export const STORE_PROJECT_NAME = "samebase";
84
84
 
85
85
  /**
86
86
  * The actions of the key of one run: the internal queries and mutations of
@@ -252,7 +252,7 @@ export const storeDirectory = () =>
252
252
  join(dirname(fileURLToPath(import.meta.url)), "..", "src", "store", "convex");
253
253
 
254
254
  export interface StoreOptions {
255
- /** Team slug or numeric team id of the `alchemy-state` project, or undefined with a team access token, which names its team. */
255
+ /** Team slug or numeric team id of the `samebase` project, or undefined with a team access token, which names its team. */
256
256
  readonly team: string | number | undefined;
257
257
  readonly api: ManagementApiService;
258
258
  readonly spawner: ChildProcessSpawner.ChildProcessSpawner["Service"];
@@ -329,7 +329,7 @@ const createStoreProject = (api: ManagementApiService, teamId: number, team: str
329
329
  });
330
330
 
331
331
  /**
332
- * The StateService over the `alchemy-state` project of the team: found or
332
+ * The StateService over the `samebase` project of the team: found or
333
333
  * created, its store pushed when it is missing or older, and read and
334
334
  * written with the keys of this run.
335
335
  */
@@ -357,7 +357,7 @@ export const makeConvexState = (options: StoreOptions) =>
357
357
  }),
358
358
  ),
359
359
  );
360
- const mint = createDeployKey(api, deployment.name, "alchemy-state", RUN_KEY_ACTIONS).pipe(
360
+ const mint = createDeployKey(api, deployment.name, STORE_PROJECT_NAME, RUN_KEY_ACTIONS).pipe(
361
361
  Effect.map((key) => {
362
362
  keys.push(key);
363
363
  return makeFunctionApi(deployment.deploymentUrl, key);
@@ -441,7 +441,7 @@ export const makeConvexState = (options: StoreOptions) =>
441
441
  });
442
442
 
443
443
  /**
444
- * Alchemy state in the `alchemy-state` project of `team`, with the team token
444
+ * Alchemy state in the `samebase` project of `team`, with the team token
445
445
  * in CONVEX_ACCESS_TOKEN or the Convex CLI login. A team access token names
446
446
  * its team, so `team` is optional with one; the Convex CLI login needs the
447
447
  * slug or the id. The first use of the run finds or creates the project and
@@ -1,4 +1,4 @@
1
- // The state functions of the alchemy-state project: one project for each
1
+ // The state functions of the samebase project of a team: one project for each
2
2
  // Convex team, pushed by Convex.state() from this directory. These raw state
3
3
  // functions are internal. reader.ts exposes authenticated, redacted reads.
4
4
  //
@@ -1,5 +1,5 @@
1
1
  {
2
- "name": "alchemy-state",
2
+ "name": "samebase",
3
3
  "private": true,
4
4
  "type": "module",
5
5
  "peerDependencies": {