@samebase/alchemy-convex 0.2.0 → 0.4.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/NOTICE +24 -0
- package/README.md +135 -164
- package/lib/index.d.ts +175 -185
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +800 -502
- package/lib/index.js.map +1 -1
- package/package.json +4 -3
- package/src/Credentials.ts +85 -27
- package/src/Deployment.ts +748 -0
- package/src/ManagementApi.ts +84 -64
- package/src/Project.ts +133 -16
- package/src/Providers.ts +6 -34
- package/src/Push.ts +646 -0
- package/src/index.ts +22 -35
- package/src/DefaultEnvironmentVariable.ts +0 -263
- package/src/Deploy.ts +0 -193
- package/src/DeployKey.ts +0 -332
- package/src/EnvironmentVariable.ts +0 -262
- package/src/PreviewDeployKey.ts +0 -153
package/src/PreviewDeployKey.ts
DELETED
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
// Convex.PreviewDeployKey: a project key that creates and deploys preview
|
|
2
|
-
// deployments, such as the key CI passes to `npx convex deploy` for a branch.
|
|
3
|
-
//
|
|
4
|
-
// Convex returns the secret only once, from create_preview_deploy_key. The
|
|
5
|
-
// identity rules are the same as for Convex.DeployKey: a requested name that
|
|
6
|
-
// is unique for each resource instance, exactly one listed key after the
|
|
7
|
-
// create with its numeric id in state, delete by the secret only, and never
|
|
8
|
-
// keep a key that is the OAuth credential itself. A key cannot change after
|
|
9
|
-
// creation, so every property change is a replacement.
|
|
10
|
-
import { Resource } from "alchemy";
|
|
11
|
-
import { havePropsChanged, isResolved } from "alchemy/Diff";
|
|
12
|
-
import * as Provider from "alchemy/Provider";
|
|
13
|
-
import * as Effect from "effect/Effect";
|
|
14
|
-
import * as Redacted from "effect/Redacted";
|
|
15
|
-
import * as Schema from "effect/Schema";
|
|
16
|
-
import {
|
|
17
|
-
createTrackedKey,
|
|
18
|
-
isKeyListed,
|
|
19
|
-
ListedKey,
|
|
20
|
-
requestedKeyName,
|
|
21
|
-
secretToDelete,
|
|
22
|
-
} from "./DeployKey.ts";
|
|
23
|
-
import { absentAsUndefined, ManagementApi, retryIdempotentWrite } from "./ManagementApi.ts";
|
|
24
|
-
import type { Providers } from "./Providers.ts";
|
|
25
|
-
|
|
26
|
-
/** GET /projects/{project_id}/list_preview_deploy_keys */
|
|
27
|
-
export const PreviewDeployKeyList = Schema.Struct({ items: Schema.Array(ListedKey) });
|
|
28
|
-
|
|
29
|
-
/** POST /projects/{project_id}/create_preview_deploy_key */
|
|
30
|
-
export const CreatedPreviewDeployKey = Schema.Struct({ previewDeployKey: Schema.String });
|
|
31
|
-
|
|
32
|
-
export interface PreviewDeployKeyProps {
|
|
33
|
-
/** Numeric project id, such as `project.projectId`. */
|
|
34
|
-
readonly projectId: number;
|
|
35
|
-
/**
|
|
36
|
-
* Key name. The provider requests this name, a dash, and a hash of the
|
|
37
|
-
* resource identity, so two resources with one `name` get different keys.
|
|
38
|
-
*/
|
|
39
|
-
readonly name: string;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export interface PreviewDeployKeyAttributes {
|
|
43
|
-
/** The name Convex lists the key under, such as "ci-3f2a1b0c9d8e". */
|
|
44
|
-
readonly uniqueName: string;
|
|
45
|
-
/** Numeric id of the key in the listing. Undefined in state written by 0.1.x. */
|
|
46
|
-
readonly keyId: number | undefined;
|
|
47
|
-
readonly projectId: number;
|
|
48
|
-
/** The secret, such as `preview:<team>:<project>|<token>`. Convex returns it only at creation. */
|
|
49
|
-
readonly previewDeployKey: Redacted.Redacted<string>;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export type PreviewDeployKey = Resource<
|
|
53
|
-
"Convex.PreviewDeployKey",
|
|
54
|
-
PreviewDeployKeyProps,
|
|
55
|
-
PreviewDeployKeyAttributes,
|
|
56
|
-
never,
|
|
57
|
-
Providers
|
|
58
|
-
>;
|
|
59
|
-
export const PreviewDeployKey = Resource<PreviewDeployKey>("Convex.PreviewDeployKey");
|
|
60
|
-
|
|
61
|
-
export const PreviewDeployKeyProvider = () =>
|
|
62
|
-
Provider.effect(
|
|
63
|
-
PreviewDeployKey,
|
|
64
|
-
Effect.gen(function* () {
|
|
65
|
-
const api = yield* ManagementApi;
|
|
66
|
-
|
|
67
|
-
const listKeys = (projectId: number) =>
|
|
68
|
-
api
|
|
69
|
-
.request("list preview deploy keys", (client) =>
|
|
70
|
-
client.GET("/projects/{project_id}/list_preview_deploy_keys", {
|
|
71
|
-
params: { path: { project_id: projectId } },
|
|
72
|
-
}),
|
|
73
|
-
)
|
|
74
|
-
.pipe(Effect.map((body) => Schema.decodeUnknownSync(PreviewDeployKeyList)(body).items));
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* `id` is the secret: Convex accepts it, and it matches only the key
|
|
78
|
-
* that this resource created. A second delete answers 404.
|
|
79
|
-
*/
|
|
80
|
-
const deleteKey = (projectId: number, secret: string) =>
|
|
81
|
-
retryIdempotentWrite(
|
|
82
|
-
api.requestVoid("delete preview deploy key", (client) =>
|
|
83
|
-
client.POST("/projects/{project_id}/delete_preview_deploy_key", {
|
|
84
|
-
params: { path: { project_id: projectId } },
|
|
85
|
-
body: { id: secret },
|
|
86
|
-
}),
|
|
87
|
-
),
|
|
88
|
-
);
|
|
89
|
-
|
|
90
|
-
return {
|
|
91
|
-
stables: ["uniqueName", "projectId"],
|
|
92
|
-
|
|
93
|
-
diff: ({ olds, news, output }) => {
|
|
94
|
-
if (!isResolved(news)) return Effect.succeed(undefined);
|
|
95
|
-
// State written without the secret cannot hand a key to dependents,
|
|
96
|
-
// and Convex cannot return it again, so only a new key helps.
|
|
97
|
-
return Effect.succeed(
|
|
98
|
-
(output !== undefined && output.previewDeployKey === undefined) ||
|
|
99
|
-
havePropsChanged(olds, news)
|
|
100
|
-
? ({ action: "replace" } as const)
|
|
101
|
-
: ({ action: "noop" } as const),
|
|
102
|
-
);
|
|
103
|
-
},
|
|
104
|
-
|
|
105
|
-
read: Effect.fn(function* ({ output }) {
|
|
106
|
-
// A key that is not in state has no known secret, so it is never adopted.
|
|
107
|
-
if (output === undefined) return undefined;
|
|
108
|
-
const entries = yield* absentAsUndefined(listKeys(output.projectId));
|
|
109
|
-
return entries !== undefined && isKeyListed(entries, output) ? output : undefined;
|
|
110
|
-
}),
|
|
111
|
-
|
|
112
|
-
reconcile: Effect.fn(function* ({ fqn, instanceId, news, output }) {
|
|
113
|
-
if (output !== undefined) {
|
|
114
|
-
// The secret cannot be read back. A key that still exists keeps the one in state.
|
|
115
|
-
if (isKeyListed(yield* listKeys(news.projectId), output)) return output;
|
|
116
|
-
}
|
|
117
|
-
const name = requestedKeyName(news.name, fqn, instanceId);
|
|
118
|
-
const { keyId, uniqueName, secret } = yield* createTrackedKey({
|
|
119
|
-
target: `project ${news.projectId}`,
|
|
120
|
-
name,
|
|
121
|
-
list: listKeys(news.projectId),
|
|
122
|
-
create: api
|
|
123
|
-
.request("create preview deploy key", (client) =>
|
|
124
|
-
client.POST("/projects/{project_id}/create_preview_deploy_key", {
|
|
125
|
-
params: { path: { project_id: news.projectId } },
|
|
126
|
-
body: { name },
|
|
127
|
-
}),
|
|
128
|
-
)
|
|
129
|
-
.pipe(
|
|
130
|
-
Effect.map(
|
|
131
|
-
(body) =>
|
|
132
|
-
Schema.decodeUnknownSync(CreatedPreviewDeployKey)(body).previewDeployKey,
|
|
133
|
-
),
|
|
134
|
-
),
|
|
135
|
-
isCredentialToken: api.isCredentialToken,
|
|
136
|
-
});
|
|
137
|
-
return { uniqueName, keyId, projectId: news.projectId, previewDeployKey: secret };
|
|
138
|
-
}),
|
|
139
|
-
|
|
140
|
-
delete: Effect.fn(function* ({ output }) {
|
|
141
|
-
// Only the secret names this key alone: 0.1.x state can hold the
|
|
142
|
-
// listed name of another resource's key.
|
|
143
|
-
const secret = yield* secretToDelete(
|
|
144
|
-
{ keyId: output.keyId, secret: output.previewDeployKey },
|
|
145
|
-
`Convex.PreviewDeployKey "${output.uniqueName}" in project ${output.projectId}`,
|
|
146
|
-
);
|
|
147
|
-
if (secret === undefined) return;
|
|
148
|
-
// 404 PreviewDeployKeyNotFound: an earlier attempt or someone else deleted it.
|
|
149
|
-
yield* absentAsUndefined(deleteKey(output.projectId, secret));
|
|
150
|
-
}),
|
|
151
|
-
};
|
|
152
|
-
}),
|
|
153
|
-
);
|