effect-cf 0.25.3 → 0.26.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 +10 -0
- package/README.md +211 -1
- package/dist/Artifacts-DcoXcRP5.d.mts +231 -0
- package/dist/ComputerWorkspaceHost.d.mts +71 -0
- package/dist/ComputerWorkspaceHost.mjs +74 -0
- package/dist/ComputerWorkspaceHostRegistry-CY5Fv4Ng.mjs +8 -0
- package/dist/index.d.mts +418 -12
- package/dist/index.mjs +892 -63
- package/package.json +12 -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 +4 -0
- package/src/internal/ComputerWorkspaceHostRegistry.ts +10 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# effect-cf
|
|
2
2
|
|
|
3
|
+
## 0.26.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#97](https://github.com/danieljvdm/effect-cf/pull/97) [`b7bc27e`](https://github.com/danieljvdm/effect-cf/commit/b7bc27eb03130578e13a593d9efc45bb8d3d5269) Thanks [@danieljvdm](https://github.com/danieljvdm)! - Add first-class Cloudflare Artifacts binding support through the new `Artifacts` module. Namespace lifecycle operations, repository token and fork operations, and Git commit-history, commit, and tree reads are available as typed Effects with validated bindings, structured options and results, tracing spans, and Cloudflare error identifiers.
|
|
8
|
+
|
|
9
|
+
- [#98](https://github.com/danieljvdm/effect-cf/pull/98) [`5b9a05e`](https://github.com/danieljvdm/effect-cf/commit/5b9a05e976f653eb9a9d2003fdd57379d906c871) Thanks [@danieljvdm](https://github.com/danieljvdm)! - Add Effect-native Cloudflare Computer workspaces, scoped execution handles, a Durable Object host mixin, and session-isolated Artifacts clients.
|
|
10
|
+
|
|
11
|
+
- [#94](https://github.com/danieljvdm/effect-cf/pull/94) [`8a7ec63`](https://github.com/danieljvdm/effect-cf/commit/8a7ec630ecb2ddc2b55348cb6c701f5a9ce42d3b) Thanks [@danieljvdm](https://github.com/danieljvdm)! - Add the `WebTransport` module: a truthful WebTransport/HTTP-3 boundary for Workers. `inboundTransport` decodes the HTTP protocol metadata Cloudflare's edge attaches to requests (`httpProtocol`, `clientQuicRtt`, `clientTcpRtt`) with `isHttp3` on top; `capabilities` feature-detects what the runtime provides; and `inboundSessionsUnsupported` is an explicit typed boundary for the inbound WebTransport session API that workerd does not have (cloudflare/workerd#6451).
|
|
12
|
+
|
|
3
13
|
## 0.25.3
|
|
4
14
|
|
|
5
15
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# effect-cf
|
|
2
2
|
|
|
3
|
-
Effect-native Cloudflare primitives for Workers, Durable Objects, Containers, bindings, Cache, KV, D1, Queues, Email, Analytics Engine, Workflows, and Durable Object storage.
|
|
3
|
+
Effect-native Cloudflare primitives for Workers, Durable Objects, Containers, bindings, Cache, KV, D1, R2, Artifacts, Queues, Email, Analytics Engine, Workflows, and Durable Object storage.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
@@ -18,6 +18,21 @@ pnpm add effect-cf "effect@^4.0.0-beta.105"
|
|
|
18
18
|
npm install effect-cf "effect@^4.0.0-beta.105"
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
+
The Computer workspace integration is an optional peer. Install it only in
|
|
22
|
+
applications that import `ComputerWorkspace`, `ComputerArtifacts`, or
|
|
23
|
+
`effect-cf/computer-workspace-host`:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
bun add "@cloudflare/computer@^0.2.0"
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Workspace Git operations additionally require `@platformatic/vfs`,
|
|
30
|
+
`@cloudflare/computer/git`'s own optional peer:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
bun add "@platformatic/vfs@^0.4.0"
|
|
34
|
+
```
|
|
35
|
+
|
|
21
36
|
## Goal
|
|
22
37
|
|
|
23
38
|
Cloudflare APIs return promises and expose platform-specific bindings. `effect-cf` wraps those boundaries as `Context`, `Layer`, and `Effect` values so application code stays inside one managed Effect runtime.
|
|
@@ -35,6 +50,10 @@ Runtime creation belongs at Cloudflare entrypoints, not inside binding helpers.
|
|
|
35
50
|
- `Kv` - typed KV namespace helper
|
|
36
51
|
- `D1` - typed D1 database binding helper with an `@effect/sql-d1` backed SQL layer
|
|
37
52
|
- `R2` - typed R2 bucket binding helper with Effect-wrapped object and multipart operations
|
|
53
|
+
- `Artifacts` - typed Cloudflare Artifacts namespace and repository helpers, including repository lifecycle, tokens, and Git object reads
|
|
54
|
+
- `ComputerWorkspace` - scoped Effect wrappers for the complete Cloudflare Computer filesystem, Git, runtime, Assets, Artifacts, and Think-compatible client surfaces
|
|
55
|
+
- `ComputerArtifacts` - session-isolated Artifacts repositories backed by `@cloudflare/computer/artifacts`
|
|
56
|
+
- `effect-cf/computer-workspace-host` - optional Durable Object host mixin, worker-shell backend wiring, and `WorkspaceServiceProxy`
|
|
38
57
|
- `Hyperdrive` - typed Hyperdrive binding helper for connection strings and optional Postgres SQL integration
|
|
39
58
|
- `Images` - typed Cloudflare Images binding helper with transformation APIs and optional hosted image operations
|
|
40
59
|
- `Email` - typed Cloudflare Email Service binding helper for `send_email` bindings, with limit validation and typed error codes
|
|
@@ -42,6 +61,7 @@ Runtime creation belongs at Cloudflare entrypoints, not inside binding helpers.
|
|
|
42
61
|
- `Queue` - typed Queue producer/consumer tags plus client and error types
|
|
43
62
|
- `Workflow` - typed Workflow entrypoints, steps, starter clients, and instance types
|
|
44
63
|
- `Rpc` - Cloudflare RPC type helpers and scoped disposal utilities
|
|
64
|
+
- `WebTransport` - truthful WebTransport/HTTP-3 boundary: typed runtime capabilities and decoded inbound protocol metadata
|
|
45
65
|
- `WorkerConfig` - Effect `Config` helpers backed by Cloudflare `env`
|
|
46
66
|
- `effect-cf/vitest` - Effect-native runners and scoped test helpers for Cloudflare's Vitest Workers pool
|
|
47
67
|
|
|
@@ -399,6 +419,166 @@ export const readArtifact = (key: string) =>
|
|
|
399
419
|
|
|
400
420
|
Use `createMultipartUpload(...)` or `resumeMultipartUpload(...)` for large objects; returned upload handles wrap `uploadPart`, `complete`, and `abort` in Effect.
|
|
401
421
|
|
|
422
|
+
## Artifacts Example
|
|
423
|
+
|
|
424
|
+
Artifacts tags expose every namespace and repository-handle binding operation as an Effect. Configure the binding under Wrangler's `artifacts` field:
|
|
425
|
+
|
|
426
|
+
```jsonc
|
|
427
|
+
{
|
|
428
|
+
"artifacts": [
|
|
429
|
+
{
|
|
430
|
+
"binding": "ARTIFACTS",
|
|
431
|
+
"namespace": "default",
|
|
432
|
+
// Optional in local development:
|
|
433
|
+
"remote": true,
|
|
434
|
+
},
|
|
435
|
+
],
|
|
436
|
+
}
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
```ts
|
|
440
|
+
import { Effect } from "effect";
|
|
441
|
+
import { Artifacts } from "effect-cf";
|
|
442
|
+
|
|
443
|
+
class Repositories extends Artifacts.Tag<Repositories>()("Repositories") {}
|
|
444
|
+
|
|
445
|
+
export const RepositoriesLayer = Repositories.layer({ binding: "ARTIFACTS" });
|
|
446
|
+
|
|
447
|
+
export const createWorkspace = Effect.gen(function* () {
|
|
448
|
+
const artifacts = yield* Repositories;
|
|
449
|
+
const created = yield* artifacts.create("agent-workspace", {
|
|
450
|
+
description: "Versioned agent workspace",
|
|
451
|
+
setDefaultBranch: "main",
|
|
452
|
+
});
|
|
453
|
+
const repo = yield* artifacts.get(created.name);
|
|
454
|
+
const readToken = yield* repo.createToken("read", 3600);
|
|
455
|
+
|
|
456
|
+
return {
|
|
457
|
+
remote: created.remote,
|
|
458
|
+
token: readToken.plaintext,
|
|
459
|
+
history: yield* repo.log({ ref: "main", limit: 10 }),
|
|
460
|
+
};
|
|
461
|
+
});
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
`create`, `import`, and `fork` return an initial plaintext token. Treat returned tokens as secrets and avoid logging or persisting them unnecessarily.
|
|
465
|
+
|
|
466
|
+
## Computer Workspace Example
|
|
467
|
+
|
|
468
|
+
`ComputerWorkspace` exposes the complete `@cloudflare/computer`
|
|
469
|
+
`WorkspaceClient` as Effects. The workspace client and every runtime execution
|
|
470
|
+
handle are owned by an Effect `Scope`, so RPC stubs are disposed when their
|
|
471
|
+
scope closes. The host mixin is a separate optional-dependency entrypoint:
|
|
472
|
+
|
|
473
|
+
```ts
|
|
474
|
+
import shellCurl from "@cloudflare/computer/shell/curl";
|
|
475
|
+
import { Effect, Schema as S } from "effect";
|
|
476
|
+
import { ComputerWorkspace, DurableObjectDefinition } from "effect-cf";
|
|
477
|
+
import { withComputerWorkspace, WorkspaceServiceProxy } from "effect-cf/computer-workspace-host";
|
|
478
|
+
|
|
479
|
+
export { WorkspaceServiceProxy };
|
|
480
|
+
|
|
481
|
+
const ResearchWorkspace = DurableObjectDefinition.make("ResearchWorkspace", {
|
|
482
|
+
inspect: DurableObjectDefinition.method({ success: S.String }),
|
|
483
|
+
});
|
|
484
|
+
|
|
485
|
+
const ResearchWorkspaceLive = ResearchWorkspace.make(ComputerWorkspace.ComputerWorkspace.layer, {
|
|
486
|
+
rpc: {
|
|
487
|
+
inspect: () =>
|
|
488
|
+
Effect.gen(function* () {
|
|
489
|
+
const workspace = yield* ComputerWorkspace.ComputerWorkspace;
|
|
490
|
+
|
|
491
|
+
// Keep reads bounded when returning their contents over RPC.
|
|
492
|
+
const readme = yield* workspace.readFile("/repo/README.md", {
|
|
493
|
+
byteLength: 256 * 1024,
|
|
494
|
+
});
|
|
495
|
+
const commits = yield* workspace.git.log({ maxCount: 20 });
|
|
496
|
+
const run = yield* workspace.execCollect("git status --short", {
|
|
497
|
+
cwd: "/repo",
|
|
498
|
+
timeoutMillis: 30_000,
|
|
499
|
+
});
|
|
500
|
+
|
|
501
|
+
return `${commits.length}:${run.exitCode}:${readme.length}`;
|
|
502
|
+
}),
|
|
503
|
+
},
|
|
504
|
+
});
|
|
505
|
+
|
|
506
|
+
const HostedResearchWorkspace = withComputerWorkspace(ResearchWorkspaceLive, (_, state, env) => ({
|
|
507
|
+
storage: state.storage,
|
|
508
|
+
sessionId: state.id.toString(),
|
|
509
|
+
gitIdentity: { name: "Research Agent", email: "agent@example.test" },
|
|
510
|
+
artifacts: { binding: env.ARTIFACTS },
|
|
511
|
+
shell: {
|
|
512
|
+
loader: env.WORKER_LOADER,
|
|
513
|
+
hostBinding: "RESEARCH_WORKSPACE",
|
|
514
|
+
hostId: state.id.toString(),
|
|
515
|
+
executionContext: state,
|
|
516
|
+
commands: [shellCurl],
|
|
517
|
+
egress: { mode: "none" },
|
|
518
|
+
},
|
|
519
|
+
}));
|
|
520
|
+
|
|
521
|
+
export class ResearchWorkspaceDurableObject extends HostedResearchWorkspace {}
|
|
522
|
+
```
|
|
523
|
+
|
|
524
|
+
Serialize checkout mutations such as `clone`, `fetch`, and reset/checkout
|
|
525
|
+
sequences with an Effect `Semaphore` when several RPC methods can update the
|
|
526
|
+
same working tree concurrently. Reads can remain concurrent.
|
|
527
|
+
|
|
528
|
+
The corresponding Wrangler configuration needs SQLite-backed Durable Object
|
|
529
|
+
storage. Worker-shell execution additionally requires the `experimental` flag,
|
|
530
|
+
a Worker Loader binding, the loopback namespace binding named by `hostBinding`,
|
|
531
|
+
and the exact `WorkspaceServiceProxy` export shown above:
|
|
532
|
+
|
|
533
|
+
```jsonc
|
|
534
|
+
{
|
|
535
|
+
"compatibility_flags": ["nodejs_compat", "experimental"],
|
|
536
|
+
"worker_loaders": [{ "binding": "WORKER_LOADER" }],
|
|
537
|
+
"artifacts": [{ "binding": "ARTIFACTS", "namespace": "default" }],
|
|
538
|
+
"durable_objects": {
|
|
539
|
+
"bindings": [
|
|
540
|
+
{
|
|
541
|
+
"name": "RESEARCH_WORKSPACE",
|
|
542
|
+
"class_name": "ResearchWorkspaceDurableObject",
|
|
543
|
+
},
|
|
544
|
+
],
|
|
545
|
+
},
|
|
546
|
+
"migrations": [
|
|
547
|
+
{
|
|
548
|
+
"tag": "v1",
|
|
549
|
+
"new_sqlite_classes": ["ResearchWorkspaceDurableObject"],
|
|
550
|
+
},
|
|
551
|
+
],
|
|
552
|
+
}
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
Omit `shell` and the Worker Loader configuration when only the SQLite
|
|
556
|
+
filesystem and Git client are needed. Supplying `artifacts` also installs the
|
|
557
|
+
session-scoped client at `workspace.artifacts` and makes the in-shell
|
|
558
|
+
`artifacts` command use the same upstream repository-prefixing convention.
|
|
559
|
+
|
|
560
|
+
Workers can use that session isolation without a Durable Object or workspace:
|
|
561
|
+
|
|
562
|
+
```ts
|
|
563
|
+
import { Effect } from "effect";
|
|
564
|
+
import { Artifacts, ComputerArtifacts } from "effect-cf";
|
|
565
|
+
|
|
566
|
+
export const createSessionRepo = (binding: Artifacts.ArtifactsBinding, sessionId: string) =>
|
|
567
|
+
Effect.gen(function* () {
|
|
568
|
+
const artifacts = yield* ComputerArtifacts.makeClient(binding, sessionId);
|
|
569
|
+
const created = yield* artifacts.create("build-cache", {
|
|
570
|
+
description: "CI artifacts",
|
|
571
|
+
});
|
|
572
|
+
const token = yield* artifacts.createToken("build-cache", "read", 3600);
|
|
573
|
+
|
|
574
|
+
return { remote: created.remote, token: token.plaintext };
|
|
575
|
+
});
|
|
576
|
+
```
|
|
577
|
+
|
|
578
|
+
Repository prefixing, list filtering, and the argv API are delegated directly
|
|
579
|
+
to `@cloudflare/computer/artifacts`, keeping this API and the in-shell command
|
|
580
|
+
in agreement.
|
|
581
|
+
|
|
402
582
|
## Hyperdrive Example
|
|
403
583
|
|
|
404
584
|
Hyperdrive tags expose the binding `connectionString` directly on the yielded service.
|
|
@@ -698,6 +878,36 @@ if (Worker.isWebSocketUpgrade(request)) {
|
|
|
698
878
|
|
|
699
879
|
Use `DurableObjectRpcWebSocket.layer(...)` for Effect RPC-over-WebSocket transports. It owns protocol parsing and RPC client bookkeeping; use `DurableWebSocket` for general application sockets, rooms, presence, and broadcast flows.
|
|
700
880
|
|
|
881
|
+
## WebTransport and HTTP/3
|
|
882
|
+
|
|
883
|
+
Cloudflare Workers cannot accept inbound WebTransport sessions today: workerd contains no QUIC/HTTP-3 stack, there is no `WebSocketPair`-style session API, and the maintainers state the feature "is not currently on our priority list" ([cloudflare/workerd#6451](https://github.com/cloudflare/workerd/issues/6451), [discussion #6454](https://github.com/cloudflare/workerd/discussions/6454)). Inbound HTTP/3 is a zone-level setting — the edge terminates QUIC and the Worker still receives an ordinary `fetch` Request. Workers and Durable Objects can accept inbound WebSocket connections; Durable Objects additionally support the hibernation WebSocket API.
|
|
884
|
+
|
|
885
|
+
The `WebTransport` module gives that boundary a typed shape rather than pretending otherwise:
|
|
886
|
+
|
|
887
|
+
```ts
|
|
888
|
+
import { Effect, Option } from "effect";
|
|
889
|
+
import { WebTransport } from "effect-cf";
|
|
890
|
+
|
|
891
|
+
const fetch = Effect.fn("fetch")(function* (request: Request) {
|
|
892
|
+
// Decoded metadata about the browser→edge hop (HTTP/3 does not reach you).
|
|
893
|
+
const transport = WebTransport.inboundTransport(request);
|
|
894
|
+
const viaHttp3 = Option.match(transport, {
|
|
895
|
+
onNone: () => false,
|
|
896
|
+
onSome: WebTransport.isHttp3,
|
|
897
|
+
});
|
|
898
|
+
|
|
899
|
+
// Feature-detected runtime capabilities: { inboundSessions: false, ... }.
|
|
900
|
+
const capabilities = yield* WebTransport.capabilities;
|
|
901
|
+
|
|
902
|
+
// Explicit typed boundary where a future inbound session API would slot in.
|
|
903
|
+
// yield* WebTransport.inboundSessionsUnsupported;
|
|
904
|
+
|
|
905
|
+
return Response.json({ viaHttp3, capabilities });
|
|
906
|
+
});
|
|
907
|
+
```
|
|
908
|
+
|
|
909
|
+
For clients that prefer WebTransport where it exists and fall back to Cloudflare-supported WebSockets, see the companion [`effect-webtransport`](../effect-webtransport) package's `Fallback` module — `examples/todo-rpc-ws` wires it up end to end.
|
|
910
|
+
|
|
701
911
|
## License
|
|
702
912
|
|
|
703
913
|
MIT
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
import { c as WorkerEnvironment, r as BindingValidationError, t as BindingNotFoundError } from "./Binding-COCtoJXa.mjs";
|
|
2
|
+
import { Context, Effect, Layer } from "effect";
|
|
3
|
+
declare namespace Artifacts_d_exports {
|
|
4
|
+
export { ArtifactsBinding, ArtifactsClient, ArtifactsCommit, ArtifactsCreateOptions, ArtifactsCreateRepoResult, ArtifactsCreateTokenResult, ArtifactsDefinition, ArtifactsErrorCode, ArtifactsForkOptions, ArtifactsImportParams, ArtifactsImportSource, ArtifactsImportTarget, ArtifactsImportTargetOptions, ArtifactsListOptions, ArtifactsLogOptions, ArtifactsLogResult, ArtifactsOperation, ArtifactsOperationError, ArtifactsRepoBinding, ArtifactsRepoClient, ArtifactsRepoInfo, ArtifactsRepoListEntry, ArtifactsRepoListResult, ArtifactsRepoStatus, ArtifactsService, ArtifactsTokenInfo, ArtifactsTokenListResult, ArtifactsTokenScope, ArtifactsTokenState, ArtifactsTree, Cursor, LayerOptions, RepoName, Tag, TagClass, artifactsErrorCodes, artifactsErrorNumericCodes, isArtifactsBinding, isArtifactsRepoBinding, layer, make, makeClient };
|
|
5
|
+
}
|
|
6
|
+
/** Artifacts operation represented by {@link ArtifactsOperationError}. */
|
|
7
|
+
type ArtifactsOperation = "createClient" | "create" | "get" | "import" | "list" | "delete" | "createToken" | "listTokens" | "getToken" | "revokeToken" | "fork" | "log" | "readCommit" | "readTree" | "cli";
|
|
8
|
+
/** Documented string error codes returned by Cloudflare Artifacts. */
|
|
9
|
+
declare const artifactsErrorCodes: readonly ["ALREADY_EXISTS", "NOT_FOUND", "IMPORT_IN_PROGRESS", "FORK_IN_PROGRESS", "INVALID_INPUT", "INVALID_REPO_NAME", "INVALID_TTL", "INVALID_URL", "REMOTE_AUTH_REQUIRED", "UPSTREAM_UNAVAILABLE", "MEMORY_LIMIT", "INTERNAL_ERROR"];
|
|
10
|
+
/** Documented numeric error codes returned by Cloudflare Artifacts. */
|
|
11
|
+
declare const artifactsErrorNumericCodes: {
|
|
12
|
+
readonly ALREADY_EXISTS: 10201;
|
|
13
|
+
readonly NOT_FOUND: 10200;
|
|
14
|
+
readonly IMPORT_IN_PROGRESS: 10302;
|
|
15
|
+
readonly FORK_IN_PROGRESS: 10303;
|
|
16
|
+
readonly INVALID_INPUT: 10100;
|
|
17
|
+
readonly INVALID_REPO_NAME: 10101;
|
|
18
|
+
readonly INVALID_TTL: 10103;
|
|
19
|
+
readonly INVALID_URL: 10104;
|
|
20
|
+
readonly REMOTE_AUTH_REQUIRED: 10106;
|
|
21
|
+
readonly UPSTREAM_UNAVAILABLE: 10401;
|
|
22
|
+
readonly MEMORY_LIMIT: 10402;
|
|
23
|
+
readonly INTERNAL_ERROR: 10400;
|
|
24
|
+
};
|
|
25
|
+
/** A documented Cloudflare Artifacts string error code. */
|
|
26
|
+
type ArtifactsErrorCode = CloudflareArtifactsErrorCode;
|
|
27
|
+
declare const ArtifactsOperationError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
28
|
+
readonly _tag: "ArtifactsOperationError";
|
|
29
|
+
} & Readonly<A>;
|
|
30
|
+
/** Error raised when a Cloudflare Artifacts operation fails. */
|
|
31
|
+
declare class ArtifactsOperationError extends ArtifactsOperationError_base<{
|
|
32
|
+
readonly binding: string;
|
|
33
|
+
readonly operation: ArtifactsOperation;
|
|
34
|
+
readonly cause: unknown;
|
|
35
|
+
/** Cloudflare string error code, when retained by the runtime. */
|
|
36
|
+
readonly code?: ArtifactsErrorCode | (string & {});
|
|
37
|
+
/** Cloudflare REST-compatible numeric error code, when retained by the runtime. */
|
|
38
|
+
readonly numericCode?: number;
|
|
39
|
+
}> {
|
|
40
|
+
get message(): string;
|
|
41
|
+
}
|
|
42
|
+
/** Typed Cloudflare Artifacts binding definition. */
|
|
43
|
+
interface ArtifactsDefinition {
|
|
44
|
+
/** Binding name from an `artifacts` entry in `wrangler.jsonc`. */
|
|
45
|
+
readonly binding: string;
|
|
46
|
+
}
|
|
47
|
+
/** Repository name containing alphanumeric characters, dots, hyphens, or underscores. */
|
|
48
|
+
type RepoName = string;
|
|
49
|
+
/** Cursor used by repository list pagination. */
|
|
50
|
+
type Cursor = string;
|
|
51
|
+
/** Scope granted to a repository token. */
|
|
52
|
+
type ArtifactsTokenScope = "read" | "write";
|
|
53
|
+
/** Lifecycle state of a repository token. */
|
|
54
|
+
type ArtifactsTokenState = "active" | "expired" | "revoked";
|
|
55
|
+
/** Lifecycle state included with repositories returned by `list()`. */
|
|
56
|
+
type ArtifactsRepoStatus = "ready" | "importing" | "forking";
|
|
57
|
+
/** Stable repository metadata returned by Cloudflare Artifacts. */
|
|
58
|
+
type ArtifactsRepoInfo = CloudflareArtifactsRepoInfo;
|
|
59
|
+
/** Result of creating, importing, or forking a repository. */
|
|
60
|
+
type ArtifactsCreateRepoResult = Readonly<CloudflareArtifactsCreateRepoResult>;
|
|
61
|
+
/** Repository metadata returned by `list()`. */
|
|
62
|
+
interface ArtifactsRepoListEntry extends ArtifactsRepoInfo {
|
|
63
|
+
readonly status: ArtifactsRepoStatus;
|
|
64
|
+
}
|
|
65
|
+
/** Cursor-paginated repository list result. */
|
|
66
|
+
interface ArtifactsRepoListResult {
|
|
67
|
+
readonly repos: ReadonlyArray<ArtifactsRepoListEntry>;
|
|
68
|
+
readonly total: number;
|
|
69
|
+
readonly cursor?: Cursor;
|
|
70
|
+
}
|
|
71
|
+
/** Result of creating a repository token. */
|
|
72
|
+
type ArtifactsCreateTokenResult = CloudflareArtifactsCreateTokenResult;
|
|
73
|
+
/** Repository token metadata, excluding its plaintext secret. */
|
|
74
|
+
type ArtifactsTokenInfo = CloudflareArtifactsTokenInfo;
|
|
75
|
+
/** Repository token list result. */
|
|
76
|
+
type ArtifactsTokenListResult = CloudflareArtifactsTokenListResult;
|
|
77
|
+
/**
|
|
78
|
+
* Commit history returned by `log()`.
|
|
79
|
+
*
|
|
80
|
+
* Cloudflare currently documents this generated type by name but does not
|
|
81
|
+
* publish its fields in the binding reference or Workers type declarations.
|
|
82
|
+
*/
|
|
83
|
+
interface ArtifactsLogResult {
|
|
84
|
+
readonly [field: string]: unknown;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Parsed Git commit returned by `readCommit()`.
|
|
88
|
+
*
|
|
89
|
+
* Cloudflare currently documents this generated type by name but does not
|
|
90
|
+
* publish its fields in the binding reference or Workers type declarations.
|
|
91
|
+
*/
|
|
92
|
+
interface ArtifactsCommit {
|
|
93
|
+
readonly [field: string]: unknown;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Parsed Git tree returned by `readTree()`.
|
|
97
|
+
*
|
|
98
|
+
* Cloudflare currently documents this generated type by name but does not
|
|
99
|
+
* publish its fields in the binding reference or Workers type declarations.
|
|
100
|
+
*/
|
|
101
|
+
interface ArtifactsTree {
|
|
102
|
+
readonly [field: string]: unknown;
|
|
103
|
+
}
|
|
104
|
+
/** Options for `Artifacts.create()`. */
|
|
105
|
+
interface ArtifactsCreateOptions {
|
|
106
|
+
/** Prevent pushes to the repository. */
|
|
107
|
+
readonly readOnly?: boolean;
|
|
108
|
+
readonly description?: string;
|
|
109
|
+
/** Initial default branch name. */
|
|
110
|
+
readonly setDefaultBranch?: string;
|
|
111
|
+
}
|
|
112
|
+
/** Options for cursor-paginating `Artifacts.list()`. */
|
|
113
|
+
interface ArtifactsListOptions {
|
|
114
|
+
/** Page size from 1 through 200. Defaults to 50. */
|
|
115
|
+
readonly limit?: number;
|
|
116
|
+
/** Cursor returned by a previous list result. */
|
|
117
|
+
readonly cursor?: Cursor;
|
|
118
|
+
}
|
|
119
|
+
/** External Git source used by `Artifacts.import()`. */
|
|
120
|
+
interface ArtifactsImportSource {
|
|
121
|
+
/** Full HTTPS URL of the Git repository. */
|
|
122
|
+
readonly url: string;
|
|
123
|
+
/** Source branch. Defaults to the remote's default branch. */
|
|
124
|
+
readonly branch?: string;
|
|
125
|
+
/** Shallow clone depth. */
|
|
126
|
+
readonly depth?: number;
|
|
127
|
+
}
|
|
128
|
+
/** Options for the target of `Artifacts.import()`. */
|
|
129
|
+
interface ArtifactsImportTargetOptions {
|
|
130
|
+
readonly description?: string;
|
|
131
|
+
readonly readOnly?: boolean;
|
|
132
|
+
}
|
|
133
|
+
/** Target repository used by `Artifacts.import()`. */
|
|
134
|
+
interface ArtifactsImportTarget {
|
|
135
|
+
readonly name: RepoName;
|
|
136
|
+
readonly opts?: ArtifactsImportTargetOptions;
|
|
137
|
+
}
|
|
138
|
+
/** Parameters for `Artifacts.import()`. */
|
|
139
|
+
interface ArtifactsImportParams {
|
|
140
|
+
readonly source: ArtifactsImportSource;
|
|
141
|
+
readonly target: ArtifactsImportTarget;
|
|
142
|
+
}
|
|
143
|
+
/** Options for `ArtifactsRepoClient.fork()`. */
|
|
144
|
+
interface ArtifactsForkOptions {
|
|
145
|
+
readonly description?: string;
|
|
146
|
+
readonly readOnly?: boolean;
|
|
147
|
+
/** Only copy the default branch. Defaults to `true`. */
|
|
148
|
+
readonly defaultBranchOnly?: boolean;
|
|
149
|
+
}
|
|
150
|
+
/** Options for `ArtifactsRepoClient.log()`. */
|
|
151
|
+
interface ArtifactsLogOptions {
|
|
152
|
+
/** Branch, tag, or commit hash. */
|
|
153
|
+
readonly ref?: string;
|
|
154
|
+
readonly limit?: number;
|
|
155
|
+
readonly offset?: number;
|
|
156
|
+
}
|
|
157
|
+
/** Runtime repository handle, including methods absent from current shipped Workers types. */
|
|
158
|
+
interface ArtifactsRepoBinding extends ArtifactsRepoInfo {
|
|
159
|
+
/**
|
|
160
|
+
* Create a Git token for the repository.
|
|
161
|
+
*
|
|
162
|
+
* Scope defaults to `"write"`. TTL is measured in seconds, defaults to
|
|
163
|
+
* 86,400, and must be between 60 and 31,536,000.
|
|
164
|
+
*/
|
|
165
|
+
readonly createToken: (scope?: ArtifactsTokenScope, ttl?: number) => Promise<ArtifactsCreateTokenResult>;
|
|
166
|
+
readonly listTokens: () => Promise<ArtifactsTokenListResult>;
|
|
167
|
+
readonly revokeToken: (tokenOrId: string) => Promise<boolean>;
|
|
168
|
+
readonly fork: (name: RepoName, options?: ArtifactsForkOptions) => Promise<ArtifactsCreateRepoResult>;
|
|
169
|
+
readonly log: (options?: ArtifactsLogOptions) => Promise<ArtifactsLogResult>;
|
|
170
|
+
readonly readCommit: (hash: string) => Promise<ArtifactsCommit>;
|
|
171
|
+
readonly readTree: (hash: string) => Promise<ArtifactsTree>;
|
|
172
|
+
}
|
|
173
|
+
/** Cloudflare Artifacts namespace binding. */
|
|
174
|
+
interface ArtifactsBinding {
|
|
175
|
+
readonly create: (name: RepoName, options?: ArtifactsCreateOptions) => Promise<ArtifactsCreateRepoResult>;
|
|
176
|
+
readonly get: (name: RepoName) => Promise<ArtifactsRepoBinding>;
|
|
177
|
+
readonly import: (params: ArtifactsImportParams) => Promise<ArtifactsCreateRepoResult>;
|
|
178
|
+
readonly list: (options?: ArtifactsListOptions) => Promise<ArtifactsRepoListResult>;
|
|
179
|
+
readonly delete: (name: RepoName) => Promise<boolean>;
|
|
180
|
+
}
|
|
181
|
+
/** Effect wrapper around a repository handle returned by `Artifacts.get()`. */
|
|
182
|
+
interface ArtifactsRepoClient extends ArtifactsRepoInfo {
|
|
183
|
+
/**
|
|
184
|
+
* Create a Git token for the repository.
|
|
185
|
+
*
|
|
186
|
+
* Scope defaults to `"write"`. TTL is measured in seconds, defaults to
|
|
187
|
+
* 86,400, and must be between 60 and 31,536,000.
|
|
188
|
+
*/
|
|
189
|
+
readonly createToken: (scope?: ArtifactsTokenScope, ttl?: number) => Effect.Effect<ArtifactsCreateTokenResult, ArtifactsOperationError>;
|
|
190
|
+
readonly listTokens: Effect.Effect<ArtifactsTokenListResult, ArtifactsOperationError>;
|
|
191
|
+
readonly revokeToken: (tokenOrId: string) => Effect.Effect<boolean, ArtifactsOperationError>;
|
|
192
|
+
readonly fork: (name: RepoName, options?: ArtifactsForkOptions) => Effect.Effect<ArtifactsCreateRepoResult, ArtifactsOperationError>;
|
|
193
|
+
readonly log: (options?: ArtifactsLogOptions) => Effect.Effect<ArtifactsLogResult, ArtifactsOperationError>;
|
|
194
|
+
readonly readCommit: (hash: string) => Effect.Effect<ArtifactsCommit, ArtifactsOperationError>;
|
|
195
|
+
readonly readTree: (hash: string) => Effect.Effect<ArtifactsTree, ArtifactsOperationError>;
|
|
196
|
+
readonly raw: ArtifactsRepoBinding;
|
|
197
|
+
}
|
|
198
|
+
/** Effect wrapper around a Cloudflare Artifacts namespace binding. */
|
|
199
|
+
interface ArtifactsClient {
|
|
200
|
+
readonly create: (name: RepoName, options?: ArtifactsCreateOptions) => Effect.Effect<ArtifactsCreateRepoResult, ArtifactsOperationError>;
|
|
201
|
+
readonly get: (name: RepoName) => Effect.Effect<ArtifactsRepoClient, ArtifactsOperationError>;
|
|
202
|
+
readonly import: (params: ArtifactsImportParams) => Effect.Effect<ArtifactsCreateRepoResult, ArtifactsOperationError>;
|
|
203
|
+
readonly list: (options?: ArtifactsListOptions) => Effect.Effect<ArtifactsRepoListResult, ArtifactsOperationError>;
|
|
204
|
+
readonly delete: (name: RepoName) => Effect.Effect<boolean, ArtifactsOperationError>;
|
|
205
|
+
readonly rawUnsafe: Effect.Effect<ArtifactsBinding>;
|
|
206
|
+
readonly definition: ArtifactsDefinition;
|
|
207
|
+
}
|
|
208
|
+
declare const ArtifactsServiceTypeId: unique symbol;
|
|
209
|
+
/** Nominal service marker for Artifacts services created with {@link make}. */
|
|
210
|
+
interface ArtifactsService<Id extends string> {
|
|
211
|
+
readonly [ArtifactsServiceTypeId]: {
|
|
212
|
+
readonly id: Id;
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
type LayerOptions = {
|
|
216
|
+
readonly binding: string;
|
|
217
|
+
};
|
|
218
|
+
interface TagClass<Self, Id extends string> extends Context.ServiceClass<Self, Id, ArtifactsClient> {
|
|
219
|
+
readonly id: Id;
|
|
220
|
+
readonly layer: (options: LayerOptions) => Layer.Layer<Self, BindingNotFoundError | BindingValidationError, WorkerEnvironment>;
|
|
221
|
+
}
|
|
222
|
+
/** Tests whether a value exposes the complete documented Artifacts repo handle API. */
|
|
223
|
+
declare const isArtifactsRepoBinding: (value: unknown) => value is ArtifactsRepoBinding;
|
|
224
|
+
/** Tests whether a value exposes the complete documented Artifacts namespace API. */
|
|
225
|
+
declare const isArtifactsBinding: (value: unknown) => value is ArtifactsBinding;
|
|
226
|
+
declare const makeClient: (definition: ArtifactsDefinition) => (artifacts: ArtifactsBinding) => ArtifactsClient;
|
|
227
|
+
declare const layer: <Self>(tag: Context.Service<Self, ArtifactsClient>, definition: ArtifactsDefinition) => Layer.Layer<Self, BindingNotFoundError | BindingValidationError, WorkerEnvironment>;
|
|
228
|
+
declare const make: <Id extends string>(id: Id) => TagClass<ArtifactsService<Id>, Id>;
|
|
229
|
+
declare const Tag: <Self>() => <Id extends string>(id: Id) => TagClass<Self, Id>;
|
|
230
|
+
//#endregion
|
|
231
|
+
export { ArtifactsOperationError as a, ArtifactsTokenListResult as c, ArtifactsCreateTokenResult as i, Artifacts_d_exports as l, ArtifactsCreateOptions as n, ArtifactsRepoInfo as o, ArtifactsCreateRepoResult as r, ArtifactsTokenInfo as s, ArtifactsBinding as t, RepoName as u };
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { t as ArtifactsBinding } from "./Artifacts-DcoXcRP5.mjs";
|
|
2
|
+
import { GitClientFactory } from "@cloudflare/computer/git";
|
|
3
|
+
import { DurableObjectStorageLike, SyncRetryIntent, SyncRetryOptions, SyncRetryScheduler, WithWorkspaceCtor, WorkspaceAttributeValue, WorkspaceAttributes, WorkspaceObserver, WorkspaceOptions, WorkspaceRegisteredBackend, WorkspaceRetryPendingSyncResult, WorkspaceServiceProxy, WorkspaceSpan } from "@cloudflare/computer";
|
|
4
|
+
import { ShellModuleGroup, WorkerShellBackendOptions, WorkerShellLoader, WorkspaceEgressPolicy } from "@cloudflare/computer/backends/worker-shell";
|
|
5
|
+
//#region src/ComputerWorkspaceHost.d.ts
|
|
6
|
+
/** The value of a `worker_loaders` binding. */
|
|
7
|
+
type DynamicWorkerLoader = WorkerShellLoader;
|
|
8
|
+
/** Default author and committer identity for workspace Git operations. */
|
|
9
|
+
interface ComputerWorkspaceGitIdentity {
|
|
10
|
+
readonly name: string;
|
|
11
|
+
readonly email: string;
|
|
12
|
+
}
|
|
13
|
+
/** Session-scoped Artifacts configuration passed through to `Workspace`. */
|
|
14
|
+
interface ComputerWorkspaceArtifactsOptions {
|
|
15
|
+
readonly binding: ArtifactsBinding;
|
|
16
|
+
/**
|
|
17
|
+
* Session prefix for repository names. When omitted, `sessionId` from the
|
|
18
|
+
* enclosing host configuration is used.
|
|
19
|
+
*/
|
|
20
|
+
readonly sessionId?: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Worker-shell backend options with the loopback workspace wiring named in
|
|
24
|
+
* Durable Object terms.
|
|
25
|
+
*/
|
|
26
|
+
interface ComputerWorkspaceShellOptions extends Omit<WorkerShellBackendOptions, "source" | "loader" | "workspace" | "ctx" | "egress"> {
|
|
27
|
+
readonly loader: DynamicWorkerLoader;
|
|
28
|
+
/** Durable Object namespace binding that points back to the wrapped class. */
|
|
29
|
+
readonly hostBinding: string;
|
|
30
|
+
/** Current Durable Object id, normally `ctx.id.toString()`. */
|
|
31
|
+
readonly hostId: string;
|
|
32
|
+
/** Current Durable Object execution context, normally `ctx`. */
|
|
33
|
+
readonly executionContext: unknown;
|
|
34
|
+
/** Dynamic Worker egress policy. Defaults to `{ mode: "none" }`. */
|
|
35
|
+
readonly egress?: WorkspaceEgressPolicy;
|
|
36
|
+
}
|
|
37
|
+
/** Configuration accepted by {@link withComputerWorkspace}. */
|
|
38
|
+
interface ComputerWorkspaceHostConfig {
|
|
39
|
+
/** Native SQLite-backed Durable Object storage (`ctx.storage`). */
|
|
40
|
+
readonly storage: globalThis.DurableObjectStorage | DurableObjectStorageLike;
|
|
41
|
+
/** Stable workspace id used by mounts and as the default Artifacts session. */
|
|
42
|
+
readonly sessionId?: string;
|
|
43
|
+
readonly gitIdentity?: ComputerWorkspaceGitIdentity;
|
|
44
|
+
/** Override the default `createGitClient()` factory. */
|
|
45
|
+
readonly git?: GitClientFactory;
|
|
46
|
+
/** Additional container, Worker JavaScript, shell, or custom backends. */
|
|
47
|
+
readonly backends?: ReadonlyArray<WorkspaceRegisteredBackend>;
|
|
48
|
+
/** Convenience wiring for one Worker Shell backend. */
|
|
49
|
+
readonly shell?: ComputerWorkspaceShellOptions;
|
|
50
|
+
readonly mounts?: WorkspaceOptions["mounts"];
|
|
51
|
+
readonly observer?: WorkspaceOptions["observer"];
|
|
52
|
+
readonly retryScheduler?: WorkspaceOptions["retryScheduler"];
|
|
53
|
+
readonly retry?: WorkspaceOptions["retry"];
|
|
54
|
+
readonly assets?: WorkspaceOptions["assets"];
|
|
55
|
+
readonly artifacts?: ComputerWorkspaceArtifactsOptions;
|
|
56
|
+
readonly now?: WorkspaceOptions["now"];
|
|
57
|
+
readonly useThink?: WorkspaceOptions["useThink"];
|
|
58
|
+
}
|
|
59
|
+
type DurableObjectConstructor = new (...args: Array<any>) => object;
|
|
60
|
+
/**
|
|
61
|
+
* Wraps a Durable Object class with one SQLite-backed Cloudflare Computer
|
|
62
|
+
* workspace and registers that local workspace for {@link ComputerWorkspace}
|
|
63
|
+
* to acquire through its Effect layer.
|
|
64
|
+
*
|
|
65
|
+
* The class must use a `new_sqlite_classes` migration. If `shell` is present,
|
|
66
|
+
* its Worker must also configure a `worker_loaders` binding, enable the
|
|
67
|
+
* `experimental` compatibility flag, and export `WorkspaceServiceProxy`.
|
|
68
|
+
*/
|
|
69
|
+
declare const withComputerWorkspace: <TBase extends DurableObjectConstructor>(Base: TBase, config: (self: InstanceType<TBase>, state: globalThis.DurableObjectState, env: ConstructorParameters<TBase>[1]) => ComputerWorkspaceHostConfig) => WithWorkspaceCtor<TBase>;
|
|
70
|
+
//#endregion
|
|
71
|
+
export { ComputerWorkspaceArtifactsOptions, ComputerWorkspaceGitIdentity, ComputerWorkspaceHostConfig, ComputerWorkspaceShellOptions, DynamicWorkerLoader, type ShellModuleGroup, type SyncRetryIntent, type SyncRetryOptions, type SyncRetryScheduler, type WorkspaceAttributeValue, type WorkspaceAttributes, type WorkspaceEgressPolicy, type WorkspaceObserver, type WorkspaceRetryPendingSyncResult, WorkspaceServiceProxy, type WorkspaceSpan, withComputerWorkspace };
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { n as register } from "./ComputerWorkspaceHostRegistry-CY5Fv4Ng.mjs";
|
|
2
|
+
import { createGitClient } from "@cloudflare/computer/git";
|
|
3
|
+
import { WorkspaceServiceProxy, withWorkspace } from "@cloudflare/computer";
|
|
4
|
+
import { WorkerShellBackend } from "@cloudflare/computer/backends/worker-shell";
|
|
5
|
+
//#region src/ComputerWorkspaceHost.ts
|
|
6
|
+
const toWorkspaceOptions = (config) => {
|
|
7
|
+
const backends = [...config.backends ?? []];
|
|
8
|
+
if (config.shell !== void 0) {
|
|
9
|
+
const { egress, executionContext, hostBinding, hostId, loader, ...shellOptions } = config.shell;
|
|
10
|
+
backends.push(new WorkerShellBackend({
|
|
11
|
+
...shellOptions,
|
|
12
|
+
loader,
|
|
13
|
+
workspace: {
|
|
14
|
+
binding: hostBinding,
|
|
15
|
+
id: hostId
|
|
16
|
+
},
|
|
17
|
+
ctx: executionContext,
|
|
18
|
+
egress: egress ?? { mode: "none" }
|
|
19
|
+
}));
|
|
20
|
+
}
|
|
21
|
+
return {
|
|
22
|
+
storage: config.storage,
|
|
23
|
+
git: config.git ?? createGitClient(),
|
|
24
|
+
...config.gitIdentity === void 0 ? {} : { defaultGitIdentity: config.gitIdentity },
|
|
25
|
+
...backends.length === 0 ? {} : { backends },
|
|
26
|
+
...config.sessionId === void 0 ? {} : { sessionId: config.sessionId },
|
|
27
|
+
...config.mounts === void 0 ? {} : { mounts: config.mounts },
|
|
28
|
+
...config.observer === void 0 ? {} : { observer: config.observer },
|
|
29
|
+
...config.retryScheduler === void 0 ? {} : { retryScheduler: config.retryScheduler },
|
|
30
|
+
...config.retry === void 0 ? {} : { retry: config.retry },
|
|
31
|
+
...config.assets === void 0 ? {} : { assets: config.assets },
|
|
32
|
+
...config.artifacts === void 0 ? {} : { artifacts: {
|
|
33
|
+
binding: config.artifacts.binding,
|
|
34
|
+
...config.artifacts.sessionId === void 0 ? {} : { sessionId: config.artifacts.sessionId }
|
|
35
|
+
} },
|
|
36
|
+
...config.now === void 0 ? {} : { now: config.now },
|
|
37
|
+
...config.useThink === void 0 ? {} : { useThink: config.useThink }
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
const HostArguments = Symbol("effect-cf/ComputerWorkspaceHost/arguments");
|
|
41
|
+
/**
|
|
42
|
+
* Wraps a Durable Object class with one SQLite-backed Cloudflare Computer
|
|
43
|
+
* workspace and registers that local workspace for {@link ComputerWorkspace}
|
|
44
|
+
* to acquire through its Effect layer.
|
|
45
|
+
*
|
|
46
|
+
* The class must use a `new_sqlite_classes` migration. If `shell` is present,
|
|
47
|
+
* its Worker must also configure a `worker_loaders` binding, enable the
|
|
48
|
+
* `experimental` compatibility flag, and export `WorkspaceServiceProxy`.
|
|
49
|
+
*/
|
|
50
|
+
const withComputerWorkspace = (Base, config) => {
|
|
51
|
+
const CapturedBase = class extends Base {
|
|
52
|
+
[HostArguments];
|
|
53
|
+
constructor(...args) {
|
|
54
|
+
super(...args);
|
|
55
|
+
this[HostArguments] = {
|
|
56
|
+
state: args[0],
|
|
57
|
+
env: args[1]
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
const WithWorkspace = withWorkspace(CapturedBase, (self) => {
|
|
62
|
+
const { env, state } = self[HostArguments];
|
|
63
|
+
return toWorkspaceOptions(config(self, state, env));
|
|
64
|
+
});
|
|
65
|
+
class WithComputerWorkspace extends WithWorkspace {
|
|
66
|
+
constructor(...args) {
|
|
67
|
+
super(...args);
|
|
68
|
+
register(args[0], this);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return WithComputerWorkspace;
|
|
72
|
+
};
|
|
73
|
+
//#endregion
|
|
74
|
+
export { WorkspaceServiceProxy, withComputerWorkspace };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
//#region src/internal/ComputerWorkspaceHostRegistry.ts
|
|
2
|
+
const hosts = /* @__PURE__ */ new WeakMap();
|
|
3
|
+
const register = (state, host) => {
|
|
4
|
+
hosts.set(state, host);
|
|
5
|
+
};
|
|
6
|
+
const lookup = (state) => hosts.get(state);
|
|
7
|
+
//#endregion
|
|
8
|
+
export { register as n, lookup as t };
|