@samebase/alchemy-convex 0.6.1 → 0.8.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 +72 -13
- package/lib/index.d.ts +97 -11
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +260 -62
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
- package/src/Deployment.ts +97 -18
- package/src/Providers.ts +2 -2
- package/src/Push.ts +58 -48
- package/src/RunRecord.ts +208 -0
- package/src/State.ts +50 -6
- package/src/index.ts +9 -0
- package/src/store/convex/state.ts +48 -2
- package/src/store/convex/version.ts +8 -4
package/README.md
CHANGED
|
@@ -69,6 +69,28 @@ deployment if it has code, only with `--adopt`.
|
|
|
69
69
|
it stays until Convex deletes it at expiry (14 days by default).
|
|
70
70
|
[`examples/app/alchemy.run.ts`](examples/app/alchemy.run.ts) is the same stack.
|
|
71
71
|
|
|
72
|
+
### The stack file at the repository root
|
|
73
|
+
|
|
74
|
+
`rootDir` is the app directory, relative to the directory where `alchemy deploy` runs, which is
|
|
75
|
+
the directory of the stack file. The default is `"."`. The push runs in `rootDir`, and `source` is
|
|
76
|
+
relative to it:
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
Effect.gen(function* () {
|
|
80
|
+
const project = yield* Convex.Project("Project", { team: "my-team", slug: "my-app" });
|
|
81
|
+
const backend = yield* Convex.Deployment("Backend", {
|
|
82
|
+
project,
|
|
83
|
+
type: "prod",
|
|
84
|
+
rootDir: "apps/web", // the Convex app, with its package.json
|
|
85
|
+
source: "./convex", // apps/web/convex
|
|
86
|
+
});
|
|
87
|
+
return { convexUrl: backend.url };
|
|
88
|
+
});
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
State always holds `rootDir`, `"."` included, so a reader of the state finds the app directory of
|
|
92
|
+
each deployment.
|
|
93
|
+
|
|
72
94
|
## Credentials
|
|
73
95
|
|
|
74
96
|
Credentials are a layer, never props, so they do not go into Alchemy state. `Convex.providers()`
|
|
@@ -119,6 +141,39 @@ the end. Rows are in the tables `resources` and `outputs` in the dashboard, unde
|
|
|
119
141
|
The store has no lock: run one deploy of a stage at a time, such as with a CI concurrency group.
|
|
120
142
|
The names of the store functions are a wire contract: never renamed or removed.
|
|
121
143
|
|
|
144
|
+
### What the output records about a run
|
|
145
|
+
|
|
146
|
+
Alchemy state holds no time, commit, branch, or run. `Convex.state()` adds them to the stage output:
|
|
147
|
+
the document that `setOutput` stores is the stack's output plus the key `samebase.run`. On GitHub
|
|
148
|
+
Actions the record comes from the run's variables and the event payload; on a laptop from git, which
|
|
149
|
+
needs a branch and an `origin` remote. It holds no secret.
|
|
150
|
+
|
|
151
|
+
```json
|
|
152
|
+
{
|
|
153
|
+
"convexUrl": "https://modest-guanaco-252.convex.cloud",
|
|
154
|
+
"samebase.run": {
|
|
155
|
+
"version": 1,
|
|
156
|
+
"repository": "samebase/base-alchemy",
|
|
157
|
+
"stackFile": "alchemy.run.ts",
|
|
158
|
+
"branch": "feature",
|
|
159
|
+
"pullRequest": 42,
|
|
160
|
+
"headCommit": "8af3c5b7932c528939cbc7aa0597b1fc36c8dc83",
|
|
161
|
+
"runUrl": "https://github.com/samebase/base-alchemy/actions/runs/12345678901/attempts/1",
|
|
162
|
+
"source": "github-actions",
|
|
163
|
+
"recordedAt": "2026-10-21T10:00:00.000Z"
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
`stackFile` is the working directory of the run below the repository root plus `alchemy.run.ts`.
|
|
169
|
+
`pullRequest` and `runUrl` are `null` for a push and for a laptop, where `source` is `laptop`. A
|
|
170
|
+
value that the stack itself returns under `samebase.run` stays. A checkout that gives no record,
|
|
171
|
+
such as a tarball without git or a detached HEAD, writes its outputs without one, and the log says
|
|
172
|
+
why. Alchemy writes the output once after a full successful deploy, so a failed deploy leaves the
|
|
173
|
+
previous record, and a deploy of selected resources writes none. A reader gets every stage of a
|
|
174
|
+
stack, with its resources and output, from the store function `state:readStack({ stack })` in one
|
|
175
|
+
call.
|
|
176
|
+
|
|
122
177
|
## Resources
|
|
123
178
|
|
|
124
179
|
- `Convex.Project`: `{ team, name, deploymentRegion?, deploymentType? }` creates a project with its
|
|
@@ -127,25 +182,29 @@ The names of the store functions are a wire contract: never renamed or removed.
|
|
|
127
182
|
taken over with `--adopt`; it never creates or renames a project. Outputs `projectId`, `slug`,
|
|
128
183
|
`name`, `teamId`, `prodDeploymentName`, `prodDeploymentUrl`.
|
|
129
184
|
- `Convex.Deployment`: `{ project, type: "prod" }` or `{ project, type: "dev" | "preview", name }`,
|
|
130
|
-
each with optional `source
|
|
131
|
-
`siteUrl`, `type`, `projectId`, `reference`, `previewName`, `hash`, and `envNames`.
|
|
185
|
+
each with optional `rootDir`, `source`, and `env`. Outputs `name` (such as `happy-animal-123`),
|
|
186
|
+
`url`, `siteUrl`, `type`, `projectId`, `reference`, `previewName`, `hash`, and `envNames`.
|
|
132
187
|
- `prod` is the project's default production deployment (with a deploy key: the key's
|
|
133
188
|
production deployment). The resource never creates or deletes one. A production deployment
|
|
134
189
|
with code that is not in state is taken over only with `--adopt`.
|
|
135
190
|
- `dev` creates a dev deployment with `name` as its reference; `preview` creates a preview
|
|
136
191
|
deployment with `name` as its preview name. An expired preview is created again on the next
|
|
137
192
|
deploy.
|
|
138
|
-
- `
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
193
|
+
- `rootDir` is the app directory, relative to the directory where the deploy runs, `"."` by
|
|
194
|
+
default. It must be relative (`AbsoluteRootDir`) and have a package.json (`ConvexAppNotFound`).
|
|
195
|
+
There is no search in the directories above it. When convex.json puts the functions outside
|
|
196
|
+
`rootDir`, the hash covers them too.
|
|
197
|
+
- `source` is the Convex functions directory relative to `rootDir`: `convex/`, or the `functions`
|
|
198
|
+
field of convex.json (`SourceMismatch`). The CLI runs in `rootDir`, with the Node.js that runs
|
|
199
|
+
Alchemy, and is never downloaded (`ConvexCliNotFound`).
|
|
200
|
+
- The content identity is a hash of every file of `rootDir` that git does not ignore, the nearest
|
|
201
|
+
lockfile, the deployment name, and `env`. The same hash is a no-op. Otherwise the update sets
|
|
202
|
+
`env`, then pushes. A failed push sets the changed variables back, and deletes a dev or preview
|
|
203
|
+
deployment that the same run created.
|
|
145
204
|
- `env` values are strings or secrets such as `Config.Redacted("AUTH_SECRET")`. A name that
|
|
146
205
|
leaves `env` is removed from the deployment.
|
|
147
|
-
- `source: { path, command?, include? }` replaces `convex deploy` with `command`, run in
|
|
148
|
-
|
|
206
|
+
- `source: { path, command?, include? }` replaces `convex deploy` with `command`, run in `rootDir`
|
|
207
|
+
with the push key in `CONVEX_DEPLOY_KEY`, such as
|
|
149
208
|
`["node_modules/.bin/convex-hosting", "deploy", "--build", "node_modules/.bin/vp build", "--dist", "dist/client"]`.
|
|
150
209
|
The command must push with `convex deploy` (convex-hosting does, through `--cmd`). `include`
|
|
151
210
|
narrows the hash to `path`, package.json, convex.json, the lockfile, and the listed globs, such
|
|
@@ -182,8 +241,8 @@ The names of the store functions are a wire contract: never renamed or removed.
|
|
|
182
241
|
|
|
183
242
|
- `env` values are props, so Alchemy state holds them. Keep `.alchemy/` git-ignored, and use an
|
|
184
243
|
encrypted state store, such as `Cloudflare.state()`, in CI.
|
|
185
|
-
- The hash does not see a change in a workspace package outside
|
|
186
|
-
|
|
244
|
+
- The hash does not see a change in a workspace package outside `rootDir`, or a push from outside
|
|
245
|
+
Alchemy. Change a file of the app to push again.
|
|
187
246
|
- With a deploy key, the provider reaches the deployment at `https://<name>.convex.cloud`, so the
|
|
188
247
|
deployment must answer there.
|
|
189
248
|
- A run that stops between a deployment create and the state write leaves a deployment that state
|
package/lib/index.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ import * as ChildProcessSpawner from "effect/process/ChildProcessSpawner";
|
|
|
9
9
|
import { createDeploymentClient, createManagementClient } from "@convex-dev/platform";
|
|
10
10
|
import "effect/Scope";
|
|
11
11
|
import { State, StateStoreError } from "alchemy/State";
|
|
12
|
+
import { InputProps } from "alchemy/Input";
|
|
12
13
|
import { components } from "@convex-dev/platform/managementApi";
|
|
13
14
|
//#region src/Credentials.d.ts
|
|
14
15
|
interface ResolvedCredentials {
|
|
@@ -117,11 +118,12 @@ export declare const providers: (credentials?: Layer.Layer<Credentials>) => Laye
|
|
|
117
118
|
/** A value of the `env` prop: a string, or a secret such as `Config.Redacted("AUTH_SECRET")`. */
|
|
118
119
|
type EnvValue = string | Redacted.Redacted<string>;
|
|
119
120
|
/**
|
|
120
|
-
* The `source` prop: the Convex functions directory
|
|
121
|
-
*
|
|
121
|
+
* The `source` prop: the Convex functions directory relative to the app
|
|
122
|
+
* directory (`rootDir`), such as `./convex`, or that directory with a push
|
|
123
|
+
* command and more files for the content identity.
|
|
122
124
|
*/
|
|
123
125
|
type Source = string | {
|
|
124
|
-
/** The Convex functions directory, such as `./convex`. */
|
|
126
|
+
/** The Convex functions directory relative to the app directory, such as `./convex`. */
|
|
125
127
|
readonly path: string;
|
|
126
128
|
/**
|
|
127
129
|
* Replaces `convex deploy`: a program and its arguments, run in the app
|
|
@@ -147,9 +149,10 @@ export declare class ConvexCliNotFound extends ConvexCliNotFound_base {
|
|
|
147
149
|
get message(): string;
|
|
148
150
|
}
|
|
149
151
|
declare const ConvexAppNotFound_base: Schema.Class<ConvexAppNotFound, Schema.TaggedStruct<"ConvexAppNotFound", {
|
|
150
|
-
|
|
152
|
+
/** The app directory, resolved against the working directory of the deploy. */
|
|
153
|
+
readonly rootDir: Schema.String;
|
|
151
154
|
}>, import("effect/Cause").YieldableError>;
|
|
152
|
-
/**
|
|
155
|
+
/** The app directory (`rootDir`) has no package.json. */
|
|
153
156
|
export declare class ConvexAppNotFound extends ConvexAppNotFound_base {
|
|
154
157
|
get message(): string;
|
|
155
158
|
}
|
|
@@ -199,10 +202,16 @@ interface DeploymentInputs {
|
|
|
199
202
|
readonly projectId: number;
|
|
200
203
|
};
|
|
201
204
|
/**
|
|
202
|
-
* The
|
|
203
|
-
*
|
|
204
|
-
*
|
|
205
|
-
*
|
|
205
|
+
* The app directory, relative to the directory where the deploy runs (the
|
|
206
|
+
* directory of the stack file), such as `apps/web`. Default ".". It must
|
|
207
|
+
* have a package.json. The push runs in it, and `source` is relative to
|
|
208
|
+
* it. State from 0.7 has no `rootDir`.
|
|
209
|
+
*/
|
|
210
|
+
readonly rootDir?: string;
|
|
211
|
+
/**
|
|
212
|
+
* The Convex functions directory relative to `rootDir`, such as
|
|
213
|
+
* `./convex`, or that directory with a push command and more hashed
|
|
214
|
+
* files. Without `source`, the resource pushes nothing.
|
|
206
215
|
*/
|
|
207
216
|
readonly source?: Source;
|
|
208
217
|
/** Environment variables to set on the deployment before the push. */
|
|
@@ -242,7 +251,36 @@ interface DeploymentAttributes extends DeploymentTarget {
|
|
|
242
251
|
readonly envNames: readonly string[];
|
|
243
252
|
}
|
|
244
253
|
export type Deployment = Resource<"Convex.Deployment", DeploymentProps, DeploymentAttributes, never, Providers>;
|
|
245
|
-
|
|
254
|
+
/** The props of a `Convex.Deployment` call: Alchemy inputs, with `rootDir` a plain string. */
|
|
255
|
+
type DeploymentInput = DeploymentProps extends (infer P) ? P extends DeploymentProps ? InputProps<P, "rootDir"> : never : never;
|
|
256
|
+
declare const AbsoluteRootDir_base: Schema.Class<AbsoluteRootDir, Schema.TaggedStruct<"AbsoluteRootDir", {
|
|
257
|
+
readonly rootDir: Schema.String;
|
|
258
|
+
}>, import("effect/Cause").YieldableError>;
|
|
259
|
+
/** `rootDir` is an absolute path. The declaration stops with it as a defect, before the plan. */
|
|
260
|
+
export declare class AbsoluteRootDir extends AbsoluteRootDir_base {
|
|
261
|
+
get message(): string;
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* `Convex.Deployment("id", props)`. The props go to state with `rootDir` in
|
|
265
|
+
* POSIX form, and with "." when it is not set, so that every row names the
|
|
266
|
+
* app directory of its deployment. An absolute `rootDir` stops the
|
|
267
|
+
* declaration, so it never reaches the plan or state. The check dies,
|
|
268
|
+
* because the program of `Alchemy.Stack` can fail only with a ConfigError.
|
|
269
|
+
* `win32.isAbsolute` also answers true for a POSIX absolute path. The other
|
|
270
|
+
* fields keep it usable where Alchemy takes a resource class, such as
|
|
271
|
+
* `Provider.collection`.
|
|
272
|
+
*/
|
|
273
|
+
export declare const Deployment: ((id: string, props: DeploymentInput) => Effect.Effect<Deployment, never, Providers>) & {
|
|
274
|
+
Type: "Convex.Deployment";
|
|
275
|
+
Props: DeploymentProps;
|
|
276
|
+
Self: import("alchemy/Self").Self<Deployment>;
|
|
277
|
+
Provider: Provider.Provider<Deployment>;
|
|
278
|
+
Aliases: readonly string[] | undefined;
|
|
279
|
+
ref: (id: string, options?: {
|
|
280
|
+
stage?: string;
|
|
281
|
+
stack?: string;
|
|
282
|
+
}) => Effect.Effect<Deployment, never, never>;
|
|
283
|
+
};
|
|
246
284
|
declare const DeploymentIdentityChange_base: Schema.Class<DeploymentIdentityChange, Schema.TaggedStruct<"DeploymentIdentityChange", {
|
|
247
285
|
/** Name of the deployment in state, such as `happy-animal-123`. */
|
|
248
286
|
readonly deployment: Schema.String;
|
|
@@ -347,6 +385,54 @@ export declare class ProjectNotFound extends ProjectNotFound_base {
|
|
|
347
385
|
get message(): string;
|
|
348
386
|
}
|
|
349
387
|
//#endregion
|
|
388
|
+
//#region src/RunRecord.d.ts
|
|
389
|
+
/** The key of the record in the stage output document. */
|
|
390
|
+
export declare const RUN_RECORD_KEY = "samebase.run";
|
|
391
|
+
/** Version 1 of the record. A reader validates `version` first. */
|
|
392
|
+
interface RunRecord {
|
|
393
|
+
readonly version: 1;
|
|
394
|
+
/** GitHub `owner/name`. */
|
|
395
|
+
readonly repository: string;
|
|
396
|
+
/** Path of the stack file from the repository root, POSIX separators, such as `apps/samebase/alchemy.run.ts`. */
|
|
397
|
+
readonly stackFile: string;
|
|
398
|
+
/** The branch that was deployed: the head branch of a pull request, else the pushed branch. */
|
|
399
|
+
readonly branch: string;
|
|
400
|
+
/** The pull request whose head was deployed, or null for a push and for a laptop. */
|
|
401
|
+
readonly pullRequest: number | null;
|
|
402
|
+
/** The commit that was deployed: the head of the pull request, else GITHUB_SHA, else git HEAD. */
|
|
403
|
+
readonly headCommit: string;
|
|
404
|
+
/** The GitHub Actions run and attempt, or null for a laptop. */
|
|
405
|
+
readonly runUrl: string | null;
|
|
406
|
+
readonly source: "github-actions" | "laptop";
|
|
407
|
+
/** ISO 8601, when the record was written. */
|
|
408
|
+
readonly recordedAt: string;
|
|
409
|
+
}
|
|
410
|
+
declare const RunRecordError_base: Schema.Class<RunRecordError, Schema.TaggedStruct<"RunRecordError", {
|
|
411
|
+
readonly reason: Schema.String;
|
|
412
|
+
}>, import("effect/Cause").YieldableError>;
|
|
413
|
+
export declare class RunRecordError extends RunRecordError_base {
|
|
414
|
+
get message(): string;
|
|
415
|
+
}
|
|
416
|
+
/** Where the run happens: the working directory of the stack and the process environment. */
|
|
417
|
+
interface RunEnvironment {
|
|
418
|
+
readonly cwd: string;
|
|
419
|
+
readonly env: Readonly<Record<string, string | undefined>>;
|
|
420
|
+
}
|
|
421
|
+
/**
|
|
422
|
+
* The record of this run: from the GitHub Actions variables and the event
|
|
423
|
+
* payload when GITHUB_ACTIONS is `true`, else from git in `cwd`, which needs
|
|
424
|
+
* a branch and an `origin` remote with `owner/name`. Fails when a value is
|
|
425
|
+
* missing; nothing is guessed.
|
|
426
|
+
*/
|
|
427
|
+
export declare const runRecord: (where: RunEnvironment) => Effect.Effect<RunRecord, RunRecordError>;
|
|
428
|
+
/**
|
|
429
|
+
* The output document of a stage: the stack's output plus the record under
|
|
430
|
+
* {@link RUN_RECORD_KEY}, or undefined for an output with no place for the
|
|
431
|
+
* key: a string, an array, null, or an object that is not plain, such as a
|
|
432
|
+
* Date. A value that the stack itself put under the key stays.
|
|
433
|
+
*/
|
|
434
|
+
export declare const withRunRecord: (output: unknown, record: RunRecord) => object | undefined;
|
|
435
|
+
//#endregion
|
|
350
436
|
//#region src/State.d.ts
|
|
351
437
|
/** The name of the state project in each team. */
|
|
352
438
|
export declare const STORE_PROJECT_NAME = "alchemy-state";
|
|
@@ -362,5 +448,5 @@ export declare const state: (options?: {
|
|
|
362
448
|
readonly team?: string | number;
|
|
363
449
|
}) => Layer.Layer<State, never, ChildProcessSpawner.ChildProcessSpawner>;
|
|
364
450
|
//#endregion
|
|
365
|
-
export type { DeploymentAttributes, DeploymentProps, DeploymentRegion, EnvValue, ProjectAttributes, ProjectProps, Source };
|
|
451
|
+
export type { DeploymentAttributes, DeploymentInput, DeploymentProps, DeploymentRegion, EnvValue, ProjectAttributes, ProjectProps, RunRecord, Source };
|
|
366
452
|
//# sourceMappingURL=index.d.ts.map
|
package/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/Credentials.ts","../src/ManagementApi.ts","../src/Providers.ts","../src/Push.ts","../src/Deployment.ts","../src/Project.ts","../src/State.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/Credentials.ts","../src/ManagementApi.ts","../src/Providers.ts","../src/Push.ts","../src/Deployment.ts","../src/Project.ts","../src/RunRecord.ts","../src/State.ts"],"mappings":"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"}
|