effect-cf 0.25.3 → 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 +16 -0
- package/README.md +213 -1
- package/dist/Artifacts-BhWrdyqX.mjs +241 -0
- package/dist/Artifacts-DcoXcRP5.d.mts +231 -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/ComputerWorkspaceHost.d.mts +71 -0
- package/dist/ComputerWorkspaceHost.mjs +74 -0
- package/dist/ComputerWorkspaceHostRegistry-CY5Fv4Ng.mjs +8 -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 +80 -2
- package/dist/index.mjs +72 -123
- package/package.json +23 -1
- package/src/Artifacts.ts +519 -0
- package/src/ComputerArtifacts.ts +255 -0
- package/src/ComputerWorkspace.ts +1098 -0
- package/src/ComputerWorkspaceHost.ts +216 -0
- package/src/WebTransport.ts +123 -0
- package/src/index.ts +2 -0
- package/src/internal/ComputerWorkspaceHostRegistry.ts +10 -0
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
|
|
2
|
-
import { a as
|
|
3
|
-
import {
|
|
2
|
+
import { a as WorkerEnvironment, i as WorkerConfig, n as violationsMessage, r as Environment_exports, t as causeMessage } from "./ErrorMessage-_lg53p3W.mjs";
|
|
3
|
+
import { a as layer$19, i as Service$2, n as Artifacts_exports, r as Binding_exports } from "./Artifacts-BhWrdyqX.mjs";
|
|
4
|
+
import { a as DurableObjectWebSocket_exports, i as fromExecutionContext, n as DurableObjectState_exports, o as fromWebSocket, r as fromDurableObjectState, s as DurableObjectStorage_exports, t as DurableObjectState } from "./DurableObjectState-Dux8KfjG.mjs";
|
|
5
|
+
import { Clock, Config, ConfigProvider, Context, Data, DateTime, Duration, Effect, Exit, Function, Layer, ManagedRuntime, Option, Predicate, Queue, Result, Schema } from "effect";
|
|
4
6
|
import { FetchHttpClient, HttpClient, HttpClientRequest, HttpEffect, HttpServerRequest, HttpServerResponse } from "effect/unstable/http";
|
|
5
7
|
import { OtlpExporter, OtlpLogger, OtlpMetrics, OtlpSerialization, OtlpTracer } from "effect/unstable/observability";
|
|
6
8
|
import { D1Client } from "@effect/sql-d1";
|
|
@@ -9,124 +11,6 @@ import * as RpcMessage from "effect/unstable/rpc/RpcMessage";
|
|
|
9
11
|
import * as RpcSerialization from "effect/unstable/rpc/RpcSerialization";
|
|
10
12
|
import * as RpcServer from "effect/unstable/rpc/RpcServer";
|
|
11
13
|
import { SqliteClient } from "@effect/sql-sqlite-do";
|
|
12
|
-
//#region src/Binding.ts
|
|
13
|
-
var Binding_exports = /* @__PURE__ */ __exportAll({
|
|
14
|
-
BindingNotFoundError: () => BindingNotFoundError,
|
|
15
|
-
BindingValidationError: () => BindingValidationError,
|
|
16
|
-
Service: () => Service$2,
|
|
17
|
-
TypeId: () => TypeId$3,
|
|
18
|
-
layer: () => layer$19
|
|
19
|
-
});
|
|
20
|
-
/** Internal type id marker used by binding helper services. */
|
|
21
|
-
const TypeId$3 = "~effect-cf/Binding";
|
|
22
|
-
/** Error raised when a configured binding does not exist on `env`. */
|
|
23
|
-
var BindingNotFoundError = class extends Data.TaggedError("BindingNotFoundError") {};
|
|
24
|
-
/** Error raised when a binding exists but does not match the expected shape. */
|
|
25
|
-
var BindingValidationError = class extends Data.TaggedError("BindingValidationError") {};
|
|
26
|
-
const defaultExpected = "Cloudflare binding resource";
|
|
27
|
-
const isPropertyTarget$1 = (value) => (typeof value === "object" || typeof value === "function") && value !== null;
|
|
28
|
-
const getObjectName = (value) => {
|
|
29
|
-
const tag = (() => {
|
|
30
|
-
try {
|
|
31
|
-
return Object.prototype.toString.call(value).slice(8, -1);
|
|
32
|
-
} catch {
|
|
33
|
-
return typeof value;
|
|
34
|
-
}
|
|
35
|
-
})();
|
|
36
|
-
const constructorName = (() => {
|
|
37
|
-
try {
|
|
38
|
-
return "constructor" in value && typeof value.constructor === "function" && typeof value.constructor.name === "string" ? value.constructor.name : void 0;
|
|
39
|
-
} catch {
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
})();
|
|
43
|
-
if (tag !== "Object") return tag;
|
|
44
|
-
if (constructorName !== void 0 && constructorName !== "" && constructorName !== "Object") return constructorName;
|
|
45
|
-
return tag;
|
|
46
|
-
};
|
|
47
|
-
const propertyNames = (value) => {
|
|
48
|
-
const names = /* @__PURE__ */ new Set();
|
|
49
|
-
for (const target of [value, Object.getPrototypeOf(value)]) {
|
|
50
|
-
if (target === null || target === Object.prototype || target === Function.prototype) continue;
|
|
51
|
-
try {
|
|
52
|
-
for (const name of Object.getOwnPropertyNames(target)) names.add(name);
|
|
53
|
-
} catch {
|
|
54
|
-
continue;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
return [...names].filter((name) => name !== "constructor").sort();
|
|
58
|
-
};
|
|
59
|
-
const isMethod = (value, name) => {
|
|
60
|
-
try {
|
|
61
|
-
return typeof Reflect.get(value, name) === "function";
|
|
62
|
-
} catch {
|
|
63
|
-
return false;
|
|
64
|
-
}
|
|
65
|
-
};
|
|
66
|
-
const describeActual = (value) => {
|
|
67
|
-
if (value === null) return "null";
|
|
68
|
-
if (typeof value !== "object" && typeof value !== "function") return typeof value;
|
|
69
|
-
const names = propertyNames(value);
|
|
70
|
-
const methods = names.filter((name) => isMethod(value, name));
|
|
71
|
-
const properties = names.filter((name) => !methods.includes(name));
|
|
72
|
-
const details = [methods.length > 0 ? `methods ${methods.join(", ")}` : void 0, properties.length > 0 ? `properties ${properties.join(", ")}` : void 0].filter((detail) => detail !== void 0);
|
|
73
|
-
if (details.length === 0) return getObjectName(value);
|
|
74
|
-
return `${getObjectName(value)} with ${details.join("; ")}`;
|
|
75
|
-
};
|
|
76
|
-
const getBinding = (env, binding, isResource, options) => Effect.gen(function* () {
|
|
77
|
-
if (!isPropertyTarget$1(env)) {
|
|
78
|
-
const actual = describeActual(env);
|
|
79
|
-
return yield* Effect.fail(new BindingValidationError({
|
|
80
|
-
binding,
|
|
81
|
-
expected: "WorkerEnvironment object",
|
|
82
|
-
actual,
|
|
83
|
-
message: `Cloudflare binding "${binding}" failed validation. Expected WorkerEnvironment object; got ${actual}`
|
|
84
|
-
}));
|
|
85
|
-
}
|
|
86
|
-
const resource = Reflect.get(env, binding);
|
|
87
|
-
if (resource === void 0) return yield* Effect.fail(new BindingNotFoundError({
|
|
88
|
-
binding,
|
|
89
|
-
message: `Cloudflare binding "${binding}" was not found in WorkerEnvironment`
|
|
90
|
-
}));
|
|
91
|
-
if (!isResource(resource)) {
|
|
92
|
-
const expected = options?.expected ?? defaultExpected;
|
|
93
|
-
const actual = describeActual(resource);
|
|
94
|
-
return yield* Effect.fail(new BindingValidationError({
|
|
95
|
-
binding,
|
|
96
|
-
expected,
|
|
97
|
-
actual,
|
|
98
|
-
message: `Cloudflare binding "${binding}" failed validation. Expected ${expected}; got ${actual}`
|
|
99
|
-
}));
|
|
100
|
-
}
|
|
101
|
-
return resource;
|
|
102
|
-
});
|
|
103
|
-
/**
|
|
104
|
-
* The overloads on {@link layer} and {@link Service} guarantee that
|
|
105
|
-
* `Service = Resource` whenever `wrap` is absent, making the fallback cast
|
|
106
|
-
* safe.
|
|
107
|
-
*/
|
|
108
|
-
const makeBindingLayer = (tag, binding, isResource, wrap, options) => Layer.effect(tag, Effect.gen(function* () {
|
|
109
|
-
const env = yield* WorkerEnvironment;
|
|
110
|
-
const resource = yield* getBinding(env, binding, isResource, options);
|
|
111
|
-
return wrap === void 0 ? resource : wrap(resource);
|
|
112
|
-
}));
|
|
113
|
-
function layer$19(tag, binding, isResource, wrap, options) {
|
|
114
|
-
return makeBindingLayer(tag, binding, isResource, wrap, options);
|
|
115
|
-
}
|
|
116
|
-
const Service$2 = () => {
|
|
117
|
-
function makeService(id, binding, isResource, wrap, options) {
|
|
118
|
-
const tag = Context.Service()(`effect-cf/Binding/${id}`);
|
|
119
|
-
const serviceLayer = makeBindingLayer(tag, binding, isResource, wrap, options);
|
|
120
|
-
return Object.assign(tag, {
|
|
121
|
-
[TypeId$3]: TypeId$3,
|
|
122
|
-
id,
|
|
123
|
-
binding,
|
|
124
|
-
layer: serviceLayer
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
return makeService;
|
|
128
|
-
};
|
|
129
|
-
//#endregion
|
|
130
14
|
//#region src/WorkersAi.ts
|
|
131
15
|
var WorkersAi_exports = /* @__PURE__ */ __exportAll({
|
|
132
16
|
Tag: () => Tag$16,
|
|
@@ -2933,8 +2817,8 @@ const makeSteps = (steps) => ({
|
|
|
2933
2817
|
});
|
|
2934
2818
|
/** Empty Images transformation pipeline. */
|
|
2935
2819
|
const empty = makeSteps([]);
|
|
2936
|
-
const transform = Function
|
|
2937
|
-
const draw = Function
|
|
2820
|
+
const transform = Function.dual(2, (steps, transformValue) => makeSteps([...steps.steps, Step.Transform({ transform: transformValue })]));
|
|
2821
|
+
const draw = Function.dual(2, (steps, drawValue) => makeSteps([...steps.steps, Step.Draw(drawValue)]));
|
|
2938
2822
|
const imagesError = (binding, operation, cause) => new ImagesOperationError({
|
|
2939
2823
|
binding,
|
|
2940
2824
|
operation,
|
|
@@ -3297,6 +3181,71 @@ const Tag$2 = () => (id) => {
|
|
|
3297
3181
|
});
|
|
3298
3182
|
};
|
|
3299
3183
|
//#endregion
|
|
3184
|
+
//#region src/WebTransport.ts
|
|
3185
|
+
var WebTransport_exports = /* @__PURE__ */ __exportAll({
|
|
3186
|
+
InboundTransport: () => InboundTransport,
|
|
3187
|
+
WebTransportUnsupportedError: () => WebTransportUnsupportedError,
|
|
3188
|
+
capabilities: () => capabilities,
|
|
3189
|
+
inboundSessionsUnsupported: () => inboundSessionsUnsupported,
|
|
3190
|
+
inboundTransport: () => inboundTransport,
|
|
3191
|
+
isHttp3: () => isHttp3
|
|
3192
|
+
});
|
|
3193
|
+
/**
|
|
3194
|
+
* Metadata Cloudflare's edge reports about the inbound client connection.
|
|
3195
|
+
*
|
|
3196
|
+
* `httpProtocol` and `clientTcpRtt` are declared in
|
|
3197
|
+
* `@cloudflare/workers-types`; `clientQuicRtt` is documented by Cloudflare
|
|
3198
|
+
* ("only present when the client connected over QUIC (HTTP/3)") but not yet
|
|
3199
|
+
* present in the published types, so it is decoded from the open
|
|
3200
|
+
* `Record<string, unknown>` side of `request.cf`.
|
|
3201
|
+
*/
|
|
3202
|
+
var InboundTransport = class extends Schema.Class("InboundTransport")({
|
|
3203
|
+
/** The HTTP protocol the client used, e.g. `"HTTP/2"` or `"HTTP/3"`. */
|
|
3204
|
+
httpProtocol: Schema.String,
|
|
3205
|
+
/** Client round-trip time; only present for QUIC (HTTP/3) connections. */
|
|
3206
|
+
clientQuicRtt: Schema.optional(Schema.Number),
|
|
3207
|
+
/** Client round-trip time; only present for TCP (HTTP/1.x, HTTP/2) connections. */
|
|
3208
|
+
clientTcpRtt: Schema.optional(Schema.Number)
|
|
3209
|
+
}) {};
|
|
3210
|
+
const decodeInboundTransport = Schema.decodeUnknownResult(InboundTransport);
|
|
3211
|
+
/**
|
|
3212
|
+
* Decodes the inbound transport metadata from `request.cf`.
|
|
3213
|
+
*
|
|
3214
|
+
* Returns `None` when the metadata is absent (for example in local `wrangler
|
|
3215
|
+
* dev` or when a Worker invokes another Worker directly) or does not match
|
|
3216
|
+
* the expected shape.
|
|
3217
|
+
*/
|
|
3218
|
+
const inboundTransport = (request) => Result.getSuccess(decodeInboundTransport(request.cf));
|
|
3219
|
+
/**
|
|
3220
|
+
* Returns `true` when the client reached Cloudflare's edge over QUIC
|
|
3221
|
+
* (HTTP/3). Prefers the documented QUIC signal (`clientQuicRtt` is only
|
|
3222
|
+
* present for QUIC connections) and falls back to the `httpProtocol` string.
|
|
3223
|
+
*
|
|
3224
|
+
* Note this describes the browser→edge hop only: the edge always terminates
|
|
3225
|
+
* QUIC, and the Worker still handles an ordinary `fetch` Request.
|
|
3226
|
+
*/
|
|
3227
|
+
const isHttp3 = (transport) => transport.clientQuicRtt !== void 0 || transport.httpProtocol === "HTTP/3";
|
|
3228
|
+
/** Feature-detects the WebTransport capabilities of the current runtime. */
|
|
3229
|
+
const capabilities = Effect.sync(() => ({
|
|
3230
|
+
inboundSessions: false,
|
|
3231
|
+
outboundSessions: typeof globalThis["WebTransport"] === "function"
|
|
3232
|
+
}));
|
|
3233
|
+
/** Raised when a WebTransport capability is unavailable in this runtime. */
|
|
3234
|
+
var WebTransportUnsupportedError = class extends Data.TaggedError("WebTransportUnsupportedError") {
|
|
3235
|
+
get message() {
|
|
3236
|
+
return this.capability === "inbound-sessions" ? "Cloudflare Workers cannot accept inbound WebTransport sessions: the edge terminates QUIC and no runtime session API exists (cloudflare/workerd#6451). Use Durable Object WebSockets for bidirectional push." : "This Workers runtime provides no WebTransport client: workerd has no QUIC stack and cloudflare:sockets is TCP-only.";
|
|
3237
|
+
}
|
|
3238
|
+
};
|
|
3239
|
+
/**
|
|
3240
|
+
* The explicit typed boundary for inbound WebTransport sessions.
|
|
3241
|
+
*
|
|
3242
|
+
* Always fails with {@link WebTransportUnsupportedError} today. Route the
|
|
3243
|
+
* code path that would accept a session through this effect so the
|
|
3244
|
+
* limitation is visible in the type system and greppable when Cloudflare
|
|
3245
|
+
* ships a real API.
|
|
3246
|
+
*/
|
|
3247
|
+
const inboundSessionsUnsupported = Effect.fail(new WebTransportUnsupportedError({ capability: "inbound-sessions" }));
|
|
3248
|
+
//#endregion
|
|
3300
3249
|
//#region src/WorkflowBinding.ts
|
|
3301
3250
|
var WorkflowBinding_exports = /* @__PURE__ */ __exportAll({
|
|
3302
3251
|
WorkflowOperationError: () => WorkflowOperationError,
|
|
@@ -3546,4 +3495,4 @@ const waitForEvent = (name, options) => Effect.flatMap(WorkflowStep$1, (workflow
|
|
|
3546
3495
|
const Tag = Tag$1;
|
|
3547
3496
|
const implement = implement$1;
|
|
3548
3497
|
//#endregion
|
|
3549
|
-
export { AiGateway_exports as AiGateway, AnalyticsEngine_exports as AnalyticsEngine, Binding_exports as Binding, BrowserRendering_exports as BrowserRendering, Cache_exports as Cache, CloudflareOtlp_exports as CloudflareOtlp, ContainerNamespace_exports as ContainerNamespace, D1_exports as D1, DurableObject_exports as DurableObject, DurableObjectAlarm_exports as DurableObjectAlarm, DurableObjectDefinition_exports as DurableObjectDefinition, DurableObjectNamespace_exports as DurableObjectNamespace, DurableObjectRpcWebSocket_exports as DurableObjectRpcWebSocket, DurableObjectSqlite_exports as DurableObjectSqlite, DurableObjectState_exports as DurableObjectState, DurableObjectStorage_exports as DurableObjectStorage, DurableObjectWebSocket_exports as DurableObjectWebSocket, Email_exports as Email, Environment_exports as Environment, Hyperdrive_exports as Hyperdrive, Images_exports as Images, Kv_exports as Kv, Queue_exports as Queue, QueueBinding_exports as QueueBinding, QueueDefinition_exports as QueueDefinition, R2_exports as R2, Rpc_exports as Rpc, RpcDefinition_exports as RpcDefinition, ServiceBinding_exports as ServiceBinding, Vectorize_exports as Vectorize, Worker_exports as Worker, WorkerConfig, WorkerDefinition_exports as WorkerDefinition, WorkerEnvironment, WorkersAi_exports as WorkersAi, Workflow_exports as Workflow, WorkflowBinding_exports as WorkflowBinding, WorkflowDefinition_exports as WorkflowDefinition };
|
|
3498
|
+
export { AiGateway_exports as AiGateway, AnalyticsEngine_exports as AnalyticsEngine, Artifacts_exports as Artifacts, Binding_exports as Binding, BrowserRendering_exports as BrowserRendering, Cache_exports as Cache, CloudflareOtlp_exports as CloudflareOtlp, ContainerNamespace_exports as ContainerNamespace, D1_exports as D1, DurableObject_exports as DurableObject, DurableObjectAlarm_exports as DurableObjectAlarm, DurableObjectDefinition_exports as DurableObjectDefinition, DurableObjectNamespace_exports as DurableObjectNamespace, DurableObjectRpcWebSocket_exports as DurableObjectRpcWebSocket, DurableObjectSqlite_exports as DurableObjectSqlite, DurableObjectState_exports as DurableObjectState, DurableObjectStorage_exports as DurableObjectStorage, DurableObjectWebSocket_exports as DurableObjectWebSocket, Email_exports as Email, Environment_exports as Environment, Hyperdrive_exports as Hyperdrive, Images_exports as Images, Kv_exports as Kv, Queue_exports as Queue, QueueBinding_exports as QueueBinding, QueueDefinition_exports as QueueDefinition, R2_exports as R2, Rpc_exports as Rpc, RpcDefinition_exports as RpcDefinition, ServiceBinding_exports as ServiceBinding, Vectorize_exports as Vectorize, WebTransport_exports as WebTransport, Worker_exports as Worker, WorkerConfig, WorkerDefinition_exports as WorkerDefinition, WorkerEnvironment, WorkersAi_exports as WorkersAi, Workflow_exports as Workflow, WorkflowBinding_exports as WorkflowBinding, WorkflowDefinition_exports as WorkflowDefinition };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "effect-cf",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.27.0",
|
|
4
4
|
"description": "Effect-native primitives for Cloudflare Workers and bindings.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -27,6 +27,21 @@
|
|
|
27
27
|
"import": "./dist/HyperdrivePg.mjs",
|
|
28
28
|
"default": "./dist/HyperdrivePg.mjs"
|
|
29
29
|
},
|
|
30
|
+
"./computer-artifacts": {
|
|
31
|
+
"types": "./dist/ComputerArtifacts.d.mts",
|
|
32
|
+
"import": "./dist/ComputerArtifacts.mjs",
|
|
33
|
+
"default": "./dist/ComputerArtifacts.mjs"
|
|
34
|
+
},
|
|
35
|
+
"./computer-workspace": {
|
|
36
|
+
"types": "./dist/ComputerWorkspace.d.mts",
|
|
37
|
+
"import": "./dist/ComputerWorkspace.mjs",
|
|
38
|
+
"default": "./dist/ComputerWorkspace.mjs"
|
|
39
|
+
},
|
|
40
|
+
"./computer-workspace-host": {
|
|
41
|
+
"types": "./dist/ComputerWorkspaceHost.d.mts",
|
|
42
|
+
"import": "./dist/ComputerWorkspaceHost.mjs",
|
|
43
|
+
"default": "./dist/ComputerWorkspaceHost.mjs"
|
|
44
|
+
},
|
|
30
45
|
"./vitest": {
|
|
31
46
|
"types": "./dist/Vitest.d.mts",
|
|
32
47
|
"import": "./dist/Vitest.mjs",
|
|
@@ -45,6 +60,7 @@
|
|
|
45
60
|
"typecheck": "tsc --noEmit"
|
|
46
61
|
},
|
|
47
62
|
"devDependencies": {
|
|
63
|
+
"@cloudflare/computer": "0.2.0",
|
|
48
64
|
"@cloudflare/containers": "catalog:",
|
|
49
65
|
"@cloudflare/vitest-pool-workers": "catalog:",
|
|
50
66
|
"@cloudflare/workers-types": "catalog:",
|
|
@@ -53,11 +69,14 @@
|
|
|
53
69
|
"@effect/sql-pg": "catalog:",
|
|
54
70
|
"@effect/sql-sqlite-do": "catalog:",
|
|
55
71
|
"@effect/vitest": "catalog:",
|
|
72
|
+
"@platformatic/vfs": "^0.4.0",
|
|
56
73
|
"effect": "catalog:",
|
|
74
|
+
"esbuild": "^0.28.1",
|
|
57
75
|
"vite-plus": "catalog:",
|
|
58
76
|
"vitest": "catalog:"
|
|
59
77
|
},
|
|
60
78
|
"peerDependencies": {
|
|
79
|
+
"@cloudflare/computer": "^0.2.0",
|
|
61
80
|
"@cloudflare/vitest-pool-workers": "^0.21.3",
|
|
62
81
|
"@cloudflare/workers-types": "^4.20260611.1",
|
|
63
82
|
"@effect/sql-d1": "^4.0.0-beta.107 <4.0.0-rc.0",
|
|
@@ -66,6 +85,9 @@
|
|
|
66
85
|
"effect": "^4.0.0-beta.107 <4.0.0-rc.0"
|
|
67
86
|
},
|
|
68
87
|
"peerDependenciesMeta": {
|
|
88
|
+
"@cloudflare/computer": {
|
|
89
|
+
"optional": true
|
|
90
|
+
},
|
|
69
91
|
"@cloudflare/vitest-pool-workers": {
|
|
70
92
|
"optional": true
|
|
71
93
|
},
|