effect-cf 0.26.0 → 0.27.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/CHANGELOG.md +6 -0
- package/README.md +8 -6
- package/dist/Artifacts-BhWrdyqX.mjs +241 -0
- package/dist/ComputerArtifacts.d.mts +55 -0
- package/dist/ComputerArtifacts.mjs +95 -0
- package/dist/ComputerWorkspace.d.mts +279 -0
- package/dist/ComputerWorkspace.mjs +545 -0
- package/dist/{DurableObjectState-CEh0DVw7.mjs → DurableObjectState-Dux8KfjG.mjs} +3 -48
- package/dist/{WorkflowBinding-D5iWzCUa.d.mts → DurableObjectState-biHrHwrh.d.mts} +7 -81
- package/dist/ErrorMessage-_lg53p3W.mjs +49 -0
- package/dist/Vitest.d.mts +2 -1
- package/dist/Vitest.mjs +2 -1
- package/dist/WorkflowBinding-zlRPCXVf.d.mts +79 -0
- package/dist/index.d.mts +15 -343
- package/dist/index.mjs +66 -946
- package/package.json +12 -1
- package/src/index.ts +0 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# effect-cf
|
|
2
2
|
|
|
3
|
+
## 0.27.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#99](https://github.com/danieljvdm/effect-cf/pull/99) [`5195812`](https://github.com/danieljvdm/effect-cf/commit/519581205c3d3b63e977515f2a33db989a5c9875) Thanks [@danieljvdm](https://github.com/danieljvdm)! - Keep the optional `@cloudflare/computer` integration out of the root bundle so Durable Object and other unrelated consumers can bundle `effect-cf` without installing or externalizing that peer. The synchronous root namespaces could not be preserved without making esbuild resolve the optional dependency before tree-shaking, so update `ComputerWorkspace` imports to `effect-cf/computer-workspace` and `ComputerArtifacts` imports to `effect-cf/computer-artifacts`; `effect-cf/computer-workspace-host` remains unchanged.
|
|
8
|
+
|
|
3
9
|
## 0.26.0
|
|
4
10
|
|
|
5
11
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -19,8 +19,8 @@ npm install effect-cf "effect@^4.0.0-beta.105"
|
|
|
19
19
|
```
|
|
20
20
|
|
|
21
21
|
The Computer workspace integration is an optional peer. Install it only in
|
|
22
|
-
applications that import `
|
|
23
|
-
`effect-cf/computer-workspace-host`:
|
|
22
|
+
applications that import `effect-cf/computer-workspace`,
|
|
23
|
+
`effect-cf/computer-artifacts`, or `effect-cf/computer-workspace-host`:
|
|
24
24
|
|
|
25
25
|
```bash
|
|
26
26
|
bun add "@cloudflare/computer@^0.2.0"
|
|
@@ -51,8 +51,8 @@ Runtime creation belongs at Cloudflare entrypoints, not inside binding helpers.
|
|
|
51
51
|
- `D1` - typed D1 database binding helper with an `@effect/sql-d1` backed SQL layer
|
|
52
52
|
- `R2` - typed R2 bucket binding helper with Effect-wrapped object and multipart operations
|
|
53
53
|
- `Artifacts` - typed Cloudflare Artifacts namespace and repository helpers, including repository lifecycle, tokens, and Git object reads
|
|
54
|
-
- `
|
|
55
|
-
- `
|
|
54
|
+
- `effect-cf/computer-workspace` - scoped Effect wrappers for the complete Cloudflare Computer filesystem, Git, runtime, Assets, Artifacts, and Think-compatible client surfaces
|
|
55
|
+
- `effect-cf/computer-artifacts` - session-isolated Artifacts repositories backed by `@cloudflare/computer/artifacts`
|
|
56
56
|
- `effect-cf/computer-workspace-host` - optional Durable Object host mixin, worker-shell backend wiring, and `WorkspaceServiceProxy`
|
|
57
57
|
- `Hyperdrive` - typed Hyperdrive binding helper for connection strings and optional Postgres SQL integration
|
|
58
58
|
- `Images` - typed Cloudflare Images binding helper with transformation APIs and optional hosted image operations
|
|
@@ -473,7 +473,8 @@ scope closes. The host mixin is a separate optional-dependency entrypoint:
|
|
|
473
473
|
```ts
|
|
474
474
|
import shellCurl from "@cloudflare/computer/shell/curl";
|
|
475
475
|
import { Effect, Schema as S } from "effect";
|
|
476
|
-
import {
|
|
476
|
+
import { DurableObjectDefinition } from "effect-cf";
|
|
477
|
+
import * as ComputerWorkspace from "effect-cf/computer-workspace";
|
|
477
478
|
import { withComputerWorkspace, WorkspaceServiceProxy } from "effect-cf/computer-workspace-host";
|
|
478
479
|
|
|
479
480
|
export { WorkspaceServiceProxy };
|
|
@@ -561,7 +562,8 @@ Workers can use that session isolation without a Durable Object or workspace:
|
|
|
561
562
|
|
|
562
563
|
```ts
|
|
563
564
|
import { Effect } from "effect";
|
|
564
|
-
import { Artifacts
|
|
565
|
+
import { Artifacts } from "effect-cf";
|
|
566
|
+
import * as ComputerArtifacts from "effect-cf/computer-artifacts";
|
|
565
567
|
|
|
566
568
|
export const createSessionRepo = (binding: Artifacts.ArtifactsBinding, sessionId: string) =>
|
|
567
569
|
Effect.gen(function* () {
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
|
|
2
|
+
import { a as WorkerEnvironment, t as causeMessage } from "./ErrorMessage-_lg53p3W.mjs";
|
|
3
|
+
import { Context, Data, Effect, Layer } from "effect";
|
|
4
|
+
//#region src/Binding.ts
|
|
5
|
+
var Binding_exports = /* @__PURE__ */ __exportAll({
|
|
6
|
+
BindingNotFoundError: () => BindingNotFoundError,
|
|
7
|
+
BindingValidationError: () => BindingValidationError,
|
|
8
|
+
Service: () => Service,
|
|
9
|
+
TypeId: () => TypeId,
|
|
10
|
+
layer: () => layer$1
|
|
11
|
+
});
|
|
12
|
+
/** Internal type id marker used by binding helper services. */
|
|
13
|
+
const TypeId = "~effect-cf/Binding";
|
|
14
|
+
/** Error raised when a configured binding does not exist on `env`. */
|
|
15
|
+
var BindingNotFoundError = class extends Data.TaggedError("BindingNotFoundError") {};
|
|
16
|
+
/** Error raised when a binding exists but does not match the expected shape. */
|
|
17
|
+
var BindingValidationError = class extends Data.TaggedError("BindingValidationError") {};
|
|
18
|
+
const defaultExpected = "Cloudflare binding resource";
|
|
19
|
+
const isPropertyTarget = (value) => (typeof value === "object" || typeof value === "function") && value !== null;
|
|
20
|
+
const getObjectName = (value) => {
|
|
21
|
+
const tag = (() => {
|
|
22
|
+
try {
|
|
23
|
+
return Object.prototype.toString.call(value).slice(8, -1);
|
|
24
|
+
} catch {
|
|
25
|
+
return typeof value;
|
|
26
|
+
}
|
|
27
|
+
})();
|
|
28
|
+
const constructorName = (() => {
|
|
29
|
+
try {
|
|
30
|
+
return "constructor" in value && typeof value.constructor === "function" && typeof value.constructor.name === "string" ? value.constructor.name : void 0;
|
|
31
|
+
} catch {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
})();
|
|
35
|
+
if (tag !== "Object") return tag;
|
|
36
|
+
if (constructorName !== void 0 && constructorName !== "" && constructorName !== "Object") return constructorName;
|
|
37
|
+
return tag;
|
|
38
|
+
};
|
|
39
|
+
const propertyNames = (value) => {
|
|
40
|
+
const names = /* @__PURE__ */ new Set();
|
|
41
|
+
for (const target of [value, Object.getPrototypeOf(value)]) {
|
|
42
|
+
if (target === null || target === Object.prototype || target === Function.prototype) continue;
|
|
43
|
+
try {
|
|
44
|
+
for (const name of Object.getOwnPropertyNames(target)) names.add(name);
|
|
45
|
+
} catch {
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return [...names].filter((name) => name !== "constructor").sort();
|
|
50
|
+
};
|
|
51
|
+
const isMethod = (value, name) => {
|
|
52
|
+
try {
|
|
53
|
+
return typeof Reflect.get(value, name) === "function";
|
|
54
|
+
} catch {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
const describeActual = (value) => {
|
|
59
|
+
if (value === null) return "null";
|
|
60
|
+
if (typeof value !== "object" && typeof value !== "function") return typeof value;
|
|
61
|
+
const names = propertyNames(value);
|
|
62
|
+
const methods = names.filter((name) => isMethod(value, name));
|
|
63
|
+
const properties = names.filter((name) => !methods.includes(name));
|
|
64
|
+
const details = [methods.length > 0 ? `methods ${methods.join(", ")}` : void 0, properties.length > 0 ? `properties ${properties.join(", ")}` : void 0].filter((detail) => detail !== void 0);
|
|
65
|
+
if (details.length === 0) return getObjectName(value);
|
|
66
|
+
return `${getObjectName(value)} with ${details.join("; ")}`;
|
|
67
|
+
};
|
|
68
|
+
const getBinding = (env, binding, isResource, options) => Effect.gen(function* () {
|
|
69
|
+
if (!isPropertyTarget(env)) {
|
|
70
|
+
const actual = describeActual(env);
|
|
71
|
+
return yield* Effect.fail(new BindingValidationError({
|
|
72
|
+
binding,
|
|
73
|
+
expected: "WorkerEnvironment object",
|
|
74
|
+
actual,
|
|
75
|
+
message: `Cloudflare binding "${binding}" failed validation. Expected WorkerEnvironment object; got ${actual}`
|
|
76
|
+
}));
|
|
77
|
+
}
|
|
78
|
+
const resource = Reflect.get(env, binding);
|
|
79
|
+
if (resource === void 0) return yield* Effect.fail(new BindingNotFoundError({
|
|
80
|
+
binding,
|
|
81
|
+
message: `Cloudflare binding "${binding}" was not found in WorkerEnvironment`
|
|
82
|
+
}));
|
|
83
|
+
if (!isResource(resource)) {
|
|
84
|
+
const expected = options?.expected ?? defaultExpected;
|
|
85
|
+
const actual = describeActual(resource);
|
|
86
|
+
return yield* Effect.fail(new BindingValidationError({
|
|
87
|
+
binding,
|
|
88
|
+
expected,
|
|
89
|
+
actual,
|
|
90
|
+
message: `Cloudflare binding "${binding}" failed validation. Expected ${expected}; got ${actual}`
|
|
91
|
+
}));
|
|
92
|
+
}
|
|
93
|
+
return resource;
|
|
94
|
+
});
|
|
95
|
+
/**
|
|
96
|
+
* The overloads on {@link layer} and {@link Service} guarantee that
|
|
97
|
+
* `Service = Resource` whenever `wrap` is absent, making the fallback cast
|
|
98
|
+
* safe.
|
|
99
|
+
*/
|
|
100
|
+
const makeBindingLayer = (tag, binding, isResource, wrap, options) => Layer.effect(tag, Effect.gen(function* () {
|
|
101
|
+
const env = yield* WorkerEnvironment;
|
|
102
|
+
const resource = yield* getBinding(env, binding, isResource, options);
|
|
103
|
+
return wrap === void 0 ? resource : wrap(resource);
|
|
104
|
+
}));
|
|
105
|
+
function layer$1(tag, binding, isResource, wrap, options) {
|
|
106
|
+
return makeBindingLayer(tag, binding, isResource, wrap, options);
|
|
107
|
+
}
|
|
108
|
+
const Service = () => {
|
|
109
|
+
function makeService(id, binding, isResource, wrap, options) {
|
|
110
|
+
const tag = Context.Service()(`effect-cf/Binding/${id}`);
|
|
111
|
+
const serviceLayer = makeBindingLayer(tag, binding, isResource, wrap, options);
|
|
112
|
+
return Object.assign(tag, {
|
|
113
|
+
[TypeId]: TypeId,
|
|
114
|
+
id,
|
|
115
|
+
binding,
|
|
116
|
+
layer: serviceLayer
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
return makeService;
|
|
120
|
+
};
|
|
121
|
+
//#endregion
|
|
122
|
+
//#region src/Artifacts.ts
|
|
123
|
+
var Artifacts_exports = /* @__PURE__ */ __exportAll({
|
|
124
|
+
ArtifactsOperationError: () => ArtifactsOperationError,
|
|
125
|
+
Tag: () => Tag,
|
|
126
|
+
artifactsErrorCodes: () => artifactsErrorCodes,
|
|
127
|
+
artifactsErrorNumericCodes: () => artifactsErrorNumericCodes,
|
|
128
|
+
isArtifactsBinding: () => isArtifactsBinding,
|
|
129
|
+
isArtifactsRepoBinding: () => isArtifactsRepoBinding,
|
|
130
|
+
layer: () => layer,
|
|
131
|
+
make: () => make,
|
|
132
|
+
makeClient: () => makeClient
|
|
133
|
+
});
|
|
134
|
+
const expectedArtifactsBinding = "Artifacts binding with create(), get(), import(), list(), and delete()";
|
|
135
|
+
const expectedArtifactsRepo = "Artifacts repo handle with createToken(), listTokens(), revokeToken(), fork(), log(), readCommit(), and readTree()";
|
|
136
|
+
/** Documented string error codes returned by Cloudflare Artifacts. */
|
|
137
|
+
const artifactsErrorCodes = [
|
|
138
|
+
"ALREADY_EXISTS",
|
|
139
|
+
"NOT_FOUND",
|
|
140
|
+
"IMPORT_IN_PROGRESS",
|
|
141
|
+
"FORK_IN_PROGRESS",
|
|
142
|
+
"INVALID_INPUT",
|
|
143
|
+
"INVALID_REPO_NAME",
|
|
144
|
+
"INVALID_TTL",
|
|
145
|
+
"INVALID_URL",
|
|
146
|
+
"REMOTE_AUTH_REQUIRED",
|
|
147
|
+
"UPSTREAM_UNAVAILABLE",
|
|
148
|
+
"MEMORY_LIMIT",
|
|
149
|
+
"INTERNAL_ERROR"
|
|
150
|
+
];
|
|
151
|
+
/** Documented numeric error codes returned by Cloudflare Artifacts. */
|
|
152
|
+
const artifactsErrorNumericCodes = {
|
|
153
|
+
ALREADY_EXISTS: 10201,
|
|
154
|
+
NOT_FOUND: 10200,
|
|
155
|
+
IMPORT_IN_PROGRESS: 10302,
|
|
156
|
+
FORK_IN_PROGRESS: 10303,
|
|
157
|
+
INVALID_INPUT: 10100,
|
|
158
|
+
INVALID_REPO_NAME: 10101,
|
|
159
|
+
INVALID_TTL: 10103,
|
|
160
|
+
INVALID_URL: 10104,
|
|
161
|
+
REMOTE_AUTH_REQUIRED: 10106,
|
|
162
|
+
UPSTREAM_UNAVAILABLE: 10401,
|
|
163
|
+
MEMORY_LIMIT: 10402,
|
|
164
|
+
INTERNAL_ERROR: 10400
|
|
165
|
+
};
|
|
166
|
+
/** Error raised when a Cloudflare Artifacts operation fails. */
|
|
167
|
+
var ArtifactsOperationError = class extends Data.TaggedError("ArtifactsOperationError") {
|
|
168
|
+
get message() {
|
|
169
|
+
const code = this.code === void 0 ? "" : ` (${this.code})`;
|
|
170
|
+
return `Artifacts ${this.operation} failed for binding "${this.binding}"${code}: ${causeMessage(this.cause)}`;
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
const artifactsErrorDetails = (cause) => {
|
|
174
|
+
if (typeof cause !== "object" || cause === null) return {};
|
|
175
|
+
const code = Reflect.get(cause, "code");
|
|
176
|
+
const numericCode = Reflect.get(cause, "numericCode");
|
|
177
|
+
return {
|
|
178
|
+
...typeof code === "string" ? { code } : {},
|
|
179
|
+
...typeof numericCode === "number" ? { numericCode } : {}
|
|
180
|
+
};
|
|
181
|
+
};
|
|
182
|
+
const artifactsError = (binding, operation, cause) => new ArtifactsOperationError({
|
|
183
|
+
binding,
|
|
184
|
+
operation,
|
|
185
|
+
cause,
|
|
186
|
+
...artifactsErrorDetails(cause)
|
|
187
|
+
});
|
|
188
|
+
const tryArtifactsPromise = (binding, operation, evaluate) => Effect.tryPromise({
|
|
189
|
+
try: evaluate,
|
|
190
|
+
catch: (cause) => artifactsError(binding, operation, cause)
|
|
191
|
+
});
|
|
192
|
+
const spanOptions = (binding, operation) => ({ attributes: {
|
|
193
|
+
binding,
|
|
194
|
+
operation
|
|
195
|
+
} });
|
|
196
|
+
const hasFunction = (value, key) => typeof Reflect.get(value, key) === "function";
|
|
197
|
+
/** Tests whether a value exposes the complete documented Artifacts repo handle API. */
|
|
198
|
+
const isArtifactsRepoBinding = (value) => typeof value === "object" && value !== null && hasFunction(value, "createToken") && hasFunction(value, "listTokens") && hasFunction(value, "revokeToken") && hasFunction(value, "fork") && hasFunction(value, "log") && hasFunction(value, "readCommit") && hasFunction(value, "readTree");
|
|
199
|
+
/** Tests whether a value exposes the complete documented Artifacts namespace API. */
|
|
200
|
+
const isArtifactsBinding = (value) => typeof value === "object" && value !== null && hasFunction(value, "create") && hasFunction(value, "get") && hasFunction(value, "import") && hasFunction(value, "list") && hasFunction(value, "delete");
|
|
201
|
+
const wrapRepo = (binding, repo) => ({
|
|
202
|
+
id: repo.id,
|
|
203
|
+
name: repo.name,
|
|
204
|
+
description: repo.description,
|
|
205
|
+
defaultBranch: repo.defaultBranch,
|
|
206
|
+
createdAt: repo.createdAt,
|
|
207
|
+
updatedAt: repo.updatedAt,
|
|
208
|
+
lastPushAt: repo.lastPushAt,
|
|
209
|
+
source: repo.source,
|
|
210
|
+
readOnly: repo.readOnly,
|
|
211
|
+
remote: repo.remote,
|
|
212
|
+
createToken: Effect.fn("Artifacts.createToken", spanOptions(binding, "createToken"))((scope, ttl) => tryArtifactsPromise(binding, "createToken", () => repo.createToken(scope, ttl))),
|
|
213
|
+
listTokens: tryArtifactsPromise(binding, "listTokens", () => repo.listTokens()).pipe(Effect.withSpan("Artifacts.listTokens", spanOptions(binding, "listTokens"))),
|
|
214
|
+
revokeToken: Effect.fn("Artifacts.revokeToken", spanOptions(binding, "revokeToken"))((tokenOrId) => tryArtifactsPromise(binding, "revokeToken", () => repo.revokeToken(tokenOrId))),
|
|
215
|
+
fork: Effect.fn("Artifacts.fork", spanOptions(binding, "fork"))((name, options) => tryArtifactsPromise(binding, "fork", () => repo.fork(name, options))),
|
|
216
|
+
log: Effect.fn("Artifacts.log", spanOptions(binding, "log"))((options) => tryArtifactsPromise(binding, "log", () => repo.log(options))),
|
|
217
|
+
readCommit: Effect.fn("Artifacts.readCommit", spanOptions(binding, "readCommit"))((hash) => tryArtifactsPromise(binding, "readCommit", () => repo.readCommit(hash))),
|
|
218
|
+
readTree: Effect.fn("Artifacts.readTree", spanOptions(binding, "readTree"))((hash) => tryArtifactsPromise(binding, "readTree", () => repo.readTree(hash))),
|
|
219
|
+
raw: repo
|
|
220
|
+
});
|
|
221
|
+
const makeClient = (definition) => (artifacts) => ({
|
|
222
|
+
definition,
|
|
223
|
+
create: Effect.fn("Artifacts.create", spanOptions(definition.binding, "create"))((name, options) => tryArtifactsPromise(definition.binding, "create", () => artifacts.create(name, options))),
|
|
224
|
+
get: Effect.fn("Artifacts.get", spanOptions(definition.binding, "get"))((name) => tryArtifactsPromise(definition.binding, "get", () => artifacts.get(name)).pipe(Effect.flatMap((repo) => isArtifactsRepoBinding(repo) ? Effect.succeed(wrapRepo(definition.binding, repo)) : Effect.fail(artifactsError(definition.binding, "get", /* @__PURE__ */ new TypeError(`Expected ${expectedArtifactsRepo}`)))))),
|
|
225
|
+
import: Effect.fn("Artifacts.import", spanOptions(definition.binding, "import"))((params) => tryArtifactsPromise(definition.binding, "import", () => artifacts.import(params))),
|
|
226
|
+
list: Effect.fn("Artifacts.list", spanOptions(definition.binding, "list"))((options) => tryArtifactsPromise(definition.binding, "list", () => artifacts.list(options))),
|
|
227
|
+
delete: Effect.fn("Artifacts.delete", spanOptions(definition.binding, "delete"))((name) => tryArtifactsPromise(definition.binding, "delete", () => artifacts.delete(name))),
|
|
228
|
+
rawUnsafe: Effect.succeed(artifacts)
|
|
229
|
+
});
|
|
230
|
+
const layer = (tag, definition) => layer$1(tag, definition.binding, isArtifactsBinding, makeClient(definition), { expected: expectedArtifactsBinding });
|
|
231
|
+
const make = (id) => Tag()(id);
|
|
232
|
+
const Tag = () => (id) => {
|
|
233
|
+
const tag = Context.Service()(id);
|
|
234
|
+
const makeLayer = (definition) => layer(tag, definition);
|
|
235
|
+
return Object.assign(tag, {
|
|
236
|
+
id,
|
|
237
|
+
layer: makeLayer
|
|
238
|
+
});
|
|
239
|
+
};
|
|
240
|
+
//#endregion
|
|
241
|
+
export { layer$1 as a, Service as i, Artifacts_exports as n, Binding_exports as r, ArtifactsOperationError as t };
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { a as ArtifactsOperationError, c as ArtifactsTokenListResult, i as ArtifactsCreateTokenResult, n as ArtifactsCreateOptions, o as ArtifactsRepoInfo, r as ArtifactsCreateRepoResult, s as ArtifactsTokenInfo, t as ArtifactsBinding, u as RepoName } from "./Artifacts-DcoXcRP5.mjs";
|
|
2
|
+
import { Effect } from "effect";
|
|
3
|
+
import { ArtifactClient, ArtifactImportOptions, ArtifactImportSource, ArtifactRepoSummary, ArtifactScope, ArtifactsCLIInput, ArtifactsCLIResult, RemoteAddFn } from "@cloudflare/computer/artifacts";
|
|
4
|
+
//#region src/ComputerArtifacts.d.ts
|
|
5
|
+
/** External Git source accepted by a session-scoped repository import. */
|
|
6
|
+
type ComputerArtifactImportSource = Readonly<ArtifactImportSource>;
|
|
7
|
+
/** Target options accepted by a session-scoped repository import. */
|
|
8
|
+
type ComputerArtifactImportOptions = Readonly<ArtifactImportOptions>;
|
|
9
|
+
/** Repository metadata returned by a session-scoped list operation. */
|
|
10
|
+
type ComputerArtifactRepoSummary = Readonly<ArtifactRepoSummary>;
|
|
11
|
+
/** Token scope accepted by the upstream session facade. */
|
|
12
|
+
type ComputerArtifactScope = ArtifactScope;
|
|
13
|
+
/** Optional Git remote-registration seam accepted by the argv API. */
|
|
14
|
+
type ComputerArtifactsRemoteAdd = RemoteAddFn;
|
|
15
|
+
/** Input to the session-scoped `artifacts` argv API. */
|
|
16
|
+
type ComputerArtifactsCliInput = ArtifactsCLIInput;
|
|
17
|
+
/** Result from the session-scoped `artifacts` argv API. */
|
|
18
|
+
type ComputerArtifactsCliResult = Readonly<ArtifactsCLIResult>;
|
|
19
|
+
/** Options used when wrapping a session-scoped Artifacts client. */
|
|
20
|
+
interface ComputerArtifactsClientOptions {
|
|
21
|
+
/** Binding name attached to errors and tracing spans. Defaults to `ARTIFACTS`. */
|
|
22
|
+
readonly binding?: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Effect-native facade over `@cloudflare/computer/artifacts`.
|
|
26
|
+
*
|
|
27
|
+
* Repository names are local to {@link sessionId}. Prefixing and filtering are
|
|
28
|
+
* intentionally delegated to the upstream `createArtifact` implementation so
|
|
29
|
+
* this client and the worker-shell `artifacts` command always use the same
|
|
30
|
+
* namespace convention.
|
|
31
|
+
*/
|
|
32
|
+
interface ComputerArtifactsClient {
|
|
33
|
+
readonly sessionId: string;
|
|
34
|
+
readonly create: (name: RepoName, options?: ArtifactsCreateOptions) => Effect.Effect<ArtifactsCreateRepoResult, ArtifactsOperationError>;
|
|
35
|
+
readonly get: (name: RepoName) => Effect.Effect<ArtifactsRepoInfo, ArtifactsOperationError>;
|
|
36
|
+
readonly list: Effect.Effect<ReadonlyArray<ComputerArtifactRepoSummary>, ArtifactsOperationError>;
|
|
37
|
+
readonly import: (name: RepoName, source: ComputerArtifactImportSource, options?: ComputerArtifactImportOptions) => Effect.Effect<ArtifactsCreateRepoResult, ArtifactsOperationError>;
|
|
38
|
+
readonly delete: (name: RepoName) => Effect.Effect<boolean, ArtifactsOperationError>;
|
|
39
|
+
readonly createToken: (name: RepoName, scope?: ComputerArtifactScope, ttl?: number) => Effect.Effect<ArtifactsCreateTokenResult, ArtifactsOperationError>;
|
|
40
|
+
readonly listTokens: (name: RepoName) => Effect.Effect<ArtifactsTokenListResult, ArtifactsOperationError>;
|
|
41
|
+
readonly getToken: (name: RepoName, id: string) => Effect.Effect<ArtifactsTokenInfo, ArtifactsOperationError>;
|
|
42
|
+
readonly revokeToken: (name: RepoName, tokenOrId: string) => Effect.Effect<boolean, ArtifactsOperationError>;
|
|
43
|
+
readonly cli: (input: ComputerArtifactsCliInput) => Effect.Effect<ComputerArtifactsCliResult, ArtifactsOperationError>;
|
|
44
|
+
readonly rawUnsafe: Effect.Effect<ArtifactClient>;
|
|
45
|
+
}
|
|
46
|
+
/** Wraps an already-created upstream session client. */
|
|
47
|
+
declare const fromClient: (client: ArtifactClient, options?: ComputerArtifactsClientOptions) => ComputerArtifactsClient;
|
|
48
|
+
/**
|
|
49
|
+
* Creates an Effect-native session client directly from a Worker Artifacts
|
|
50
|
+
* binding. `@cloudflare/computer` is loaded only when this Effect runs, keeping
|
|
51
|
+
* the optional peer out of applications that do not use this integration.
|
|
52
|
+
*/
|
|
53
|
+
declare const makeClient: (bindingValue: ArtifactsBinding, sessionId: string, options?: ComputerArtifactsClientOptions | undefined) => Effect.Effect<ComputerArtifactsClient, ArtifactsOperationError, never>;
|
|
54
|
+
//#endregion
|
|
55
|
+
export { ComputerArtifactImportOptions, ComputerArtifactImportSource, ComputerArtifactRepoSummary, ComputerArtifactScope, ComputerArtifactsCliInput, ComputerArtifactsCliResult, ComputerArtifactsClient, ComputerArtifactsClientOptions, ComputerArtifactsRemoteAdd, fromClient, makeClient };
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { t as ArtifactsOperationError } from "./Artifacts-BhWrdyqX.mjs";
|
|
2
|
+
import { Effect } from "effect";
|
|
3
|
+
//#region src/ComputerArtifacts.ts
|
|
4
|
+
const artifactsErrorDetails = (cause) => {
|
|
5
|
+
if (typeof cause !== "object" || cause === null) return {};
|
|
6
|
+
const code = Reflect.get(cause, "code");
|
|
7
|
+
const numericCode = Reflect.get(cause, "numericCode");
|
|
8
|
+
return {
|
|
9
|
+
...typeof code === "string" ? { code } : {},
|
|
10
|
+
...typeof numericCode === "number" ? { numericCode } : {}
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
const operationError = (binding, operation, cause) => new ArtifactsOperationError({
|
|
14
|
+
binding,
|
|
15
|
+
operation,
|
|
16
|
+
cause,
|
|
17
|
+
...artifactsErrorDetails(cause)
|
|
18
|
+
});
|
|
19
|
+
const tryOperation = (binding, operation, evaluate) => Effect.tryPromise({
|
|
20
|
+
try: evaluate,
|
|
21
|
+
catch: (cause) => operationError(binding, operation, cause)
|
|
22
|
+
});
|
|
23
|
+
const spanOptions = (binding, sessionId, operation) => ({ attributes: {
|
|
24
|
+
binding,
|
|
25
|
+
sessionId,
|
|
26
|
+
operation
|
|
27
|
+
} });
|
|
28
|
+
/** Wraps an already-created upstream session client. */
|
|
29
|
+
const fromClient = (client, options = {}) => {
|
|
30
|
+
const binding = options.binding ?? "ARTIFACTS";
|
|
31
|
+
const { sessionId } = client;
|
|
32
|
+
return {
|
|
33
|
+
sessionId,
|
|
34
|
+
create: Effect.fn("ComputerArtifacts.create", spanOptions(binding, sessionId, "create"))(function* (name, createOptions) {
|
|
35
|
+
yield* Effect.annotateCurrentSpan("repo", name);
|
|
36
|
+
return yield* tryOperation(binding, "create", () => client.create(name, createOptions));
|
|
37
|
+
}),
|
|
38
|
+
get: Effect.fn("ComputerArtifacts.get", spanOptions(binding, sessionId, "get"))(function* (name) {
|
|
39
|
+
yield* Effect.annotateCurrentSpan("repo", name);
|
|
40
|
+
return yield* tryOperation(binding, "get", () => client.get(name));
|
|
41
|
+
}),
|
|
42
|
+
list: tryOperation(binding, "list", () => client.list()).pipe(Effect.withSpan("ComputerArtifacts.list", spanOptions(binding, sessionId, "list"))),
|
|
43
|
+
import: Effect.fn("ComputerArtifacts.import", spanOptions(binding, sessionId, "import"))(function* (name, source, importOptions) {
|
|
44
|
+
yield* Effect.annotateCurrentSpan("repo", name);
|
|
45
|
+
return yield* tryOperation(binding, "import", () => client.import(name, source, importOptions));
|
|
46
|
+
}),
|
|
47
|
+
delete: Effect.fn("ComputerArtifacts.delete", spanOptions(binding, sessionId, "delete"))(function* (name) {
|
|
48
|
+
yield* Effect.annotateCurrentSpan("repo", name);
|
|
49
|
+
return yield* tryOperation(binding, "delete", () => client.delete(name));
|
|
50
|
+
}),
|
|
51
|
+
createToken: Effect.fn("ComputerArtifacts.createToken", spanOptions(binding, sessionId, "createToken"))(function* (name, scope, ttl) {
|
|
52
|
+
yield* Effect.annotateCurrentSpan("repo", name);
|
|
53
|
+
return yield* tryOperation(binding, "createToken", () => client.createToken(name, scope, ttl));
|
|
54
|
+
}),
|
|
55
|
+
listTokens: Effect.fn("ComputerArtifacts.listTokens", spanOptions(binding, sessionId, "listTokens"))(function* (name) {
|
|
56
|
+
yield* Effect.annotateCurrentSpan("repo", name);
|
|
57
|
+
return yield* tryOperation(binding, "listTokens", () => client.listTokens(name));
|
|
58
|
+
}),
|
|
59
|
+
getToken: Effect.fn("ComputerArtifacts.getToken", spanOptions(binding, sessionId, "getToken"))(function* (name, id) {
|
|
60
|
+
yield* Effect.annotateCurrentSpan({
|
|
61
|
+
repo: name,
|
|
62
|
+
tokenId: id
|
|
63
|
+
});
|
|
64
|
+
return yield* tryOperation(binding, "getToken", () => client.getToken(name, id));
|
|
65
|
+
}),
|
|
66
|
+
revokeToken: Effect.fn("ComputerArtifacts.revokeToken", spanOptions(binding, sessionId, "revokeToken"))(function* (name, tokenOrId) {
|
|
67
|
+
yield* Effect.annotateCurrentSpan("repo", name);
|
|
68
|
+
return yield* tryOperation(binding, "revokeToken", () => client.revokeToken(name, tokenOrId));
|
|
69
|
+
}),
|
|
70
|
+
cli: Effect.fn("ComputerArtifacts.cli", spanOptions(binding, sessionId, "cli"))(function* (input) {
|
|
71
|
+
yield* Effect.annotateCurrentSpan("argv", input.argv.join(" "));
|
|
72
|
+
return yield* tryOperation(binding, "cli", () => client.cli(input));
|
|
73
|
+
}),
|
|
74
|
+
rawUnsafe: Effect.succeed(client)
|
|
75
|
+
};
|
|
76
|
+
};
|
|
77
|
+
/**
|
|
78
|
+
* Creates an Effect-native session client directly from a Worker Artifacts
|
|
79
|
+
* binding. `@cloudflare/computer` is loaded only when this Effect runs, keeping
|
|
80
|
+
* the optional peer out of applications that do not use this integration.
|
|
81
|
+
*/
|
|
82
|
+
const makeClient = Effect.fn("ComputerArtifacts.makeClient")(function* (bindingValue, sessionId, options = {}) {
|
|
83
|
+
const binding = options.binding ?? "ARTIFACTS";
|
|
84
|
+
const computerArtifacts = yield* Effect.tryPromise({
|
|
85
|
+
try: () => import("@cloudflare/computer/artifacts"),
|
|
86
|
+
catch: (cause) => operationError(binding, "createClient", cause)
|
|
87
|
+
});
|
|
88
|
+
const client = yield* Effect.try({
|
|
89
|
+
try: () => computerArtifacts.createArtifact(bindingValue, sessionId),
|
|
90
|
+
catch: (cause) => operationError(binding, "createClient", cause)
|
|
91
|
+
});
|
|
92
|
+
return fromClient(client, { binding });
|
|
93
|
+
});
|
|
94
|
+
//#endregion
|
|
95
|
+
export { fromClient, makeClient };
|