alchemy 2.0.0-beta.3 → 2.0.0-beta.4
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/bin/{alchemy-effect.js → alchemy.js} +170 -170
- package/bin/alchemy.js.map +1 -0
- package/bin/{alchemy-effect.sh → alchemy.sh} +2 -2
- package/lib/cli/index.d.ts.map +1 -1
- package/lib/cli/index.js +167 -167
- package/lib/cli/index.js.map +1 -1
- package/package.json +38 -38
- package/src/AWS/AGENTS.md +10 -10
- package/src/AWS/Assets.ts +1 -1
- package/src/AWS/AuthProvider.ts +392 -0
- package/src/AWS/Credentials.ts +0 -1
- package/src/AWS/DynamoDB/Table.ts +63 -10
- package/src/AWS/EC2/VpcEndpoint.ts +4 -4
- package/src/AWS/EC2/hosted.ts +1 -1
- package/src/AWS/ECS/Task.ts +1 -1
- package/src/AWS/Kinesis/Stream.ts +44 -8
- package/src/AWS/Lambda/Function.ts +218 -10
- package/src/AWS/S3/Bucket.ts +26 -19
- package/src/AWS/S3/BucketNotifications.ts +1 -1
- package/src/AWS/SNS/Topic.ts +47 -10
- package/src/AWS/SQS/Queue.ts +66 -0
- package/src/Auth/AuthProvider.ts +33 -0
- package/src/Auth/Credentials.ts +56 -0
- package/src/Auth/Env.ts +45 -0
- package/src/Auth/Profile.ts +72 -0
- package/src/Auth/index.ts +2 -0
- package/src/Cloudflare/Auth/AuthProvider.ts +670 -0
- package/src/Cloudflare/Auth/OAuthClient.ts +315 -0
- package/src/Cloudflare/Container/ContainerApplication.ts +3 -3
- package/src/Cloudflare/Container/ContainerBinding.ts +2 -4
- package/src/Cloudflare/Container/StartContainer.ts +1 -1
- package/src/Cloudflare/Providers.ts +1 -6
- package/src/Cloudflare/R2/R2Bucket.ts +2 -2
- package/src/Cloudflare/Website/StaticSite.ts +44 -15
- package/src/Cloudflare/Website/Vite.ts +34 -12
- package/src/Cloudflare/Workers/Assets.ts +170 -207
- package/src/Cloudflare/Workers/DurableObjectNamespace.ts +230 -370
- package/src/Cloudflare/Workers/DurableObjectState.ts +63 -0
- package/src/Cloudflare/Workers/DurableObjectStorage.ts +256 -0
- package/src/Cloudflare/Workers/InferEnv.ts +11 -7
- package/src/Cloudflare/Workers/Rpc.ts +13 -2
- package/src/Cloudflare/Workers/ScheduledEvents.ts +185 -0
- package/src/Cloudflare/Workers/WebSocket.ts +1 -1
- package/src/Cloudflare/Workers/Worker.ts +261 -61
- package/src/Cloudflare/Workers/index.ts +3 -0
- package/src/Construct.ts +2 -2
- package/src/GitHub/Secret.ts +52 -7
- package/src/GitHub/Variable.ts +45 -2
- package/src/Kubernetes/client.ts +2 -2
- package/src/Output.ts +1 -1
- package/src/Platform.ts +10 -5
- package/src/Resource.ts +4 -4
- package/src/Test/Vitest.ts +4 -3
- package/src/Util/Clank.ts +77 -0
- package/src/Util/PlatformServices.ts +21 -0
- package/src/Util/dedent.ts +4 -1
- package/bin/alchemy-effect.js.map +0 -1
- package/src/Daemon/Client.ts +0 -116
- package/src/Daemon/Config.ts +0 -28
- package/src/Daemon/Errors.ts +0 -48
- package/src/Daemon/Lock.ts +0 -162
- package/src/Daemon/ProcessRegistry.ts +0 -284
- package/src/Daemon/RpcSchema.ts +0 -43
- package/src/Daemon/RpcServer.ts +0 -231
- package/src/Daemon/index.ts +0 -27
- package/src/Spawn.ts +0 -23
- /package/bin/{alchemy-effect.ts → alchemy.ts} +0 -0
|
@@ -9,8 +9,12 @@ import type { HttpEffect } from "../../Http.ts";
|
|
|
9
9
|
import * as Output from "../../Output.ts";
|
|
10
10
|
import type { PlatformServices } from "../../Platform.ts";
|
|
11
11
|
import { effectClass, taggedFunction } from "../../Util/effect.ts";
|
|
12
|
+
import {
|
|
13
|
+
DurableObjectState,
|
|
14
|
+
fromDurableObjectState,
|
|
15
|
+
} from "./DurableObjectState.ts";
|
|
12
16
|
import { makeRpcStub } from "./Rpc.ts";
|
|
13
|
-
import {
|
|
17
|
+
import { type DurableWebSocket } from "./WebSocket.ts";
|
|
14
18
|
import { Worker, WorkerEnvironment, type WorkerServices } from "./Worker.ts";
|
|
15
19
|
|
|
16
20
|
export interface DurableObjectExport {
|
|
@@ -39,7 +43,26 @@ export type AlarmInvocationInfo = cf.AlarmInvocationInfo;
|
|
|
39
43
|
type TypeId = "Cloudflare.DurableObjectNamespace";
|
|
40
44
|
const TypeId = "Cloudflare.DurableObjectNamespace";
|
|
41
45
|
|
|
42
|
-
export
|
|
46
|
+
export const isDurableObjectNamespaceLike = (
|
|
47
|
+
value: unknown,
|
|
48
|
+
): value is DurableObjectNamespaceLike =>
|
|
49
|
+
typeof value === "object" &&
|
|
50
|
+
value !== null &&
|
|
51
|
+
"kind" in value &&
|
|
52
|
+
value.kind === TypeId;
|
|
53
|
+
|
|
54
|
+
export interface DurableObjectNamespaceLike<Shape = any> {
|
|
55
|
+
kind: TypeId;
|
|
56
|
+
name: string;
|
|
57
|
+
/** @internal phantom */
|
|
58
|
+
className?: string;
|
|
59
|
+
/** @internal phantom */
|
|
60
|
+
Shape?: Shape;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export interface DurableObjectNamespace<
|
|
64
|
+
Shape = unknown,
|
|
65
|
+
> extends DurableObjectNamespaceLike<Shape> {
|
|
43
66
|
Type: TypeId;
|
|
44
67
|
name: string;
|
|
45
68
|
namespaceId: Output.Output<string>;
|
|
@@ -63,7 +86,7 @@ export interface DurableObjectShape {
|
|
|
63
86
|
) => Effect.Effect<void, never, never>;
|
|
64
87
|
webSocketMessage?: (
|
|
65
88
|
socket: DurableWebSocket,
|
|
66
|
-
message: string |
|
|
89
|
+
message: string | ArrayBuffer,
|
|
67
90
|
) => Effect.Effect<void>;
|
|
68
91
|
webSocketClose?: (
|
|
69
92
|
socket: DurableWebSocket,
|
|
@@ -79,6 +102,17 @@ export type DurableObjectServices =
|
|
|
79
102
|
| WorkerServices
|
|
80
103
|
| PlatformServices;
|
|
81
104
|
|
|
105
|
+
export interface DurableObjectNamespaceProps {
|
|
106
|
+
/**
|
|
107
|
+
* @default name
|
|
108
|
+
*/
|
|
109
|
+
className: string;
|
|
110
|
+
// scriptName?: string | undefined;
|
|
111
|
+
// environment?: string | undefined;
|
|
112
|
+
// sqlite?: boolean | undefined;
|
|
113
|
+
// namespaceId?: string | undefined;
|
|
114
|
+
}
|
|
115
|
+
|
|
82
116
|
export interface DurableObjectNamespaceClass extends Effect.Effect<
|
|
83
117
|
DurableObjectNamespace,
|
|
84
118
|
never,
|
|
@@ -100,6 +134,10 @@ export interface DurableObjectNamespaceClass extends Effect.Effect<
|
|
|
100
134
|
new (_: never): Shape;
|
|
101
135
|
};
|
|
102
136
|
};
|
|
137
|
+
<Shape>(
|
|
138
|
+
name: string,
|
|
139
|
+
props?: DurableObjectNamespaceProps,
|
|
140
|
+
): DurableObjectNamespaceLike<Shape>;
|
|
103
141
|
<Shape, InitReq = never>(
|
|
104
142
|
name: string,
|
|
105
143
|
impl: Effect.Effect<
|
|
@@ -360,11 +398,59 @@ export class DurableObjectNamespaceScope extends Context.Service<
|
|
|
360
398
|
* }),
|
|
361
399
|
* };
|
|
362
400
|
* ```
|
|
401
|
+
*
|
|
402
|
+
* @section Binding in an Async Worker
|
|
403
|
+
* When using an Async Worker (plain `async fetch` handler, no Effect
|
|
404
|
+
* runtime), declare Durable Objects in the `bindings` prop of the
|
|
405
|
+
* Worker resource. Pass a `DurableObjectNamespace` reference with a
|
|
406
|
+
* `className` matching the exported `DurableObject` subclass in your
|
|
407
|
+
* worker source file. Use `Cloudflare.InferEnv` to get a fully typed
|
|
408
|
+
* `env` object that includes the namespace.
|
|
409
|
+
*
|
|
410
|
+
* @example Declaring a DO binding in the stack
|
|
411
|
+
* ```typescript
|
|
412
|
+
* // alchemy.run.ts
|
|
413
|
+
* import type { Counter } from "./src/worker.ts";
|
|
414
|
+
*
|
|
415
|
+
* export type WorkerEnv = Cloudflare.InferEnv<typeof Worker>;
|
|
416
|
+
*
|
|
417
|
+
* export const Worker = Cloudflare.Worker("Worker", {
|
|
418
|
+
* main: "./src/worker.ts",
|
|
419
|
+
* bindings: {
|
|
420
|
+
* Counter: Cloudflare.DurableObjectNamespace<Counter>("Counter", {
|
|
421
|
+
* className: "Counter",
|
|
422
|
+
* }),
|
|
423
|
+
* },
|
|
424
|
+
* });
|
|
425
|
+
* ```
|
|
426
|
+
*
|
|
427
|
+
* @example Using the DO from a plain async handler
|
|
428
|
+
* ```typescript
|
|
429
|
+
* // src/worker.ts
|
|
430
|
+
* import { DurableObject } from "cloudflare:workers";
|
|
431
|
+
* import type { WorkerEnv } from "../alchemy.run.ts";
|
|
432
|
+
*
|
|
433
|
+
* export default {
|
|
434
|
+
* async fetch(request: Request, env: WorkerEnv) {
|
|
435
|
+
* const counter = env.Counter.getByName("my-counter");
|
|
436
|
+
* const count = await counter.increment();
|
|
437
|
+
* return new Response(JSON.stringify({ count }));
|
|
438
|
+
* },
|
|
439
|
+
* };
|
|
440
|
+
*
|
|
441
|
+
* export class Counter extends DurableObject {
|
|
442
|
+
* private counter = 0;
|
|
443
|
+
* async increment() {
|
|
444
|
+
* return ++this.counter;
|
|
445
|
+
* }
|
|
446
|
+
* }
|
|
447
|
+
* ```
|
|
363
448
|
*/
|
|
364
449
|
export const DurableObjectNamespace: DurableObjectNamespaceClass =
|
|
365
450
|
taggedFunction(DurableObjectNamespaceScope, ((
|
|
366
451
|
...args:
|
|
367
452
|
| []
|
|
453
|
+
| [name: string, props?: DurableObjectNamespaceProps]
|
|
368
454
|
| [
|
|
369
455
|
name: string,
|
|
370
456
|
impl: Effect.Effect<
|
|
@@ -378,137 +464,156 @@ export const DurableObjectNamespace: DurableObjectNamespaceClass =
|
|
|
378
464
|
) =>
|
|
379
465
|
args.length === 0
|
|
380
466
|
? DurableObjectNamespace
|
|
381
|
-
:
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
467
|
+
: !Effect.isEffect(args[1])
|
|
468
|
+
? ({
|
|
469
|
+
kind: TypeId,
|
|
470
|
+
name: args[0],
|
|
471
|
+
className: (args[1] as DurableObjectNamespaceProps | undefined)
|
|
472
|
+
?.className,
|
|
473
|
+
} satisfies DurableObjectNamespaceLike<any>)
|
|
474
|
+
: effectClass(
|
|
475
|
+
Effect.gen(function* () {
|
|
476
|
+
const [namespace, impl] = args as any as [
|
|
477
|
+
name: string,
|
|
478
|
+
impl: Effect.Effect<
|
|
479
|
+
Effect.Effect<
|
|
480
|
+
DurableObjectNamespace<any>,
|
|
481
|
+
never,
|
|
482
|
+
DurableObjectState
|
|
483
|
+
>
|
|
484
|
+
>,
|
|
485
|
+
];
|
|
486
|
+
const worker = yield* Worker;
|
|
385
487
|
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
488
|
+
yield* worker.bind`${namespace}`({
|
|
489
|
+
// TODO(sam): automate class migrations, probably in the provider
|
|
490
|
+
bindings: [
|
|
491
|
+
{
|
|
492
|
+
type: "durable_object_namespace",
|
|
493
|
+
name: namespace,
|
|
494
|
+
className: namespace,
|
|
495
|
+
// scriptName:
|
|
496
|
+
// binding.scriptName === props.workerName
|
|
497
|
+
// ? undefined
|
|
498
|
+
// : binding.scriptName,
|
|
499
|
+
// environment: binding.environment,
|
|
500
|
+
// namespaceId: binding.namespaceId,
|
|
501
|
+
},
|
|
502
|
+
],
|
|
503
|
+
});
|
|
402
504
|
|
|
403
|
-
|
|
404
|
-
|
|
505
|
+
const services =
|
|
506
|
+
yield* Effect.context<Effect.Services<typeof impl>>();
|
|
405
507
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
508
|
+
yield* worker.export(namespace, {
|
|
509
|
+
kind: "durableObject",
|
|
510
|
+
make: (state: cf.DurableObjectState, env: any) => {
|
|
511
|
+
const doState = fromDurableObjectState(state);
|
|
512
|
+
return constructor.pipe(
|
|
513
|
+
Effect.provideContext(services),
|
|
514
|
+
Effect.provideService(DurableObjectState, doState),
|
|
515
|
+
Effect.provideService(WorkerEnvironment, env),
|
|
516
|
+
Effect.map((methods: any) => {
|
|
517
|
+
console.log(
|
|
518
|
+
"[DurableObject] wrapping methods:",
|
|
519
|
+
Object.keys(methods),
|
|
520
|
+
"own:",
|
|
521
|
+
Object.getOwnPropertyNames(methods),
|
|
522
|
+
);
|
|
523
|
+
const wrapped: Record<string, unknown> = {};
|
|
524
|
+
for (const key of Object.getOwnPropertyNames(methods)) {
|
|
525
|
+
const value = methods[key];
|
|
526
|
+
if (Effect.isEffect(value)) {
|
|
527
|
+
wrapped[key] = (
|
|
528
|
+
value as Effect.Effect<any, any, any>
|
|
529
|
+
).pipe(
|
|
530
|
+
Effect.provideService(DurableObjectState, doState),
|
|
531
|
+
);
|
|
532
|
+
} else if (typeof value === "function") {
|
|
533
|
+
wrapped[key] = (...args: unknown[]) => {
|
|
534
|
+
const result = (value as Function)(...args);
|
|
535
|
+
if (Effect.isEffect(result)) {
|
|
536
|
+
return (
|
|
537
|
+
result as Effect.Effect<any, any, any>
|
|
538
|
+
).pipe(
|
|
539
|
+
Effect.provideService(
|
|
540
|
+
DurableObjectState,
|
|
541
|
+
doState,
|
|
542
|
+
),
|
|
543
|
+
);
|
|
544
|
+
}
|
|
545
|
+
return result;
|
|
546
|
+
};
|
|
547
|
+
} else {
|
|
548
|
+
wrapped[key] = value;
|
|
549
|
+
}
|
|
447
550
|
}
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
}),
|
|
451
|
-
);
|
|
452
|
-
},
|
|
453
|
-
} satisfies DurableObjectExport);
|
|
454
|
-
|
|
455
|
-
const binding = yield* Effect.serviceOption(WorkerEnvironment).pipe(
|
|
456
|
-
Effect.map(Option.getOrUndefined),
|
|
457
|
-
Effect.flatMap((env) => {
|
|
458
|
-
if (env === undefined) {
|
|
459
|
-
// should be fine to return undefined here (it is only undefined at plantime)
|
|
460
|
-
return Effect.succeed(undefined);
|
|
461
|
-
}
|
|
462
|
-
const ns = env[namespace];
|
|
463
|
-
if (!ns) {
|
|
464
|
-
return Effect.die(
|
|
465
|
-
new Error(
|
|
466
|
-
`DurableObjectNamespace '${namespace}' not found`,
|
|
467
|
-
),
|
|
551
|
+
return wrapped;
|
|
552
|
+
}),
|
|
468
553
|
);
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
} else {
|
|
472
|
-
return Effect.die(
|
|
473
|
-
new Error(
|
|
474
|
-
`DurableObjectNamespace '${namespace}' is not a DurableObjectNamespace`,
|
|
475
|
-
),
|
|
476
|
-
);
|
|
477
|
-
}
|
|
478
|
-
}),
|
|
479
|
-
);
|
|
554
|
+
},
|
|
555
|
+
} satisfies DurableObjectExport);
|
|
480
556
|
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
557
|
+
const binding = yield* Effect.serviceOption(
|
|
558
|
+
WorkerEnvironment,
|
|
559
|
+
).pipe(
|
|
560
|
+
Effect.map(Option.getOrUndefined),
|
|
561
|
+
Effect.flatMap((env) => {
|
|
562
|
+
if (env === undefined) {
|
|
563
|
+
// should be fine to return undefined here (it is only undefined at plantime)
|
|
564
|
+
return Effect.succeed(undefined);
|
|
565
|
+
}
|
|
566
|
+
const ns = env[namespace];
|
|
567
|
+
if (!ns) {
|
|
568
|
+
return Effect.die(
|
|
569
|
+
new Error(
|
|
570
|
+
`DurableObjectNamespace '${namespace}' not found`,
|
|
571
|
+
),
|
|
572
|
+
);
|
|
573
|
+
} else if (typeof ns.getByName === "function") {
|
|
574
|
+
return Effect.succeed(ns);
|
|
575
|
+
} else {
|
|
576
|
+
return Effect.die(
|
|
577
|
+
new Error(
|
|
578
|
+
`DurableObjectNamespace '${namespace}' is not a DurableObjectNamespace`,
|
|
579
|
+
),
|
|
580
|
+
);
|
|
581
|
+
}
|
|
582
|
+
}),
|
|
583
|
+
);
|
|
584
|
+
|
|
585
|
+
const namespaceId = worker.durableObjectNamespaces.pipe(
|
|
586
|
+
Output.map(
|
|
587
|
+
(durableObjectNamespaces) =>
|
|
588
|
+
durableObjectNamespaces?.[namespace],
|
|
589
|
+
),
|
|
590
|
+
);
|
|
487
591
|
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
592
|
+
const self = {
|
|
593
|
+
Type: TypeId,
|
|
594
|
+
LogicalId: namespace,
|
|
595
|
+
name: namespace,
|
|
596
|
+
namespaceId,
|
|
597
|
+
getByName: (name: string) =>
|
|
598
|
+
makeRpcStub(binding.getByName(name)),
|
|
599
|
+
// newUniqueId: () => use((ns) => ns.newUniqueId()),
|
|
600
|
+
// idFromName: (name: string) => use((ns) => ns.idFromName(name)),
|
|
601
|
+
// idFromString: (id: string) => use((ns) => ns.idFromString(id)),
|
|
602
|
+
// get: (
|
|
603
|
+
// id: cf.DurableObjectId,
|
|
604
|
+
// options?: cf.DurableObjectNamespaceGetDurableObjectOptions,
|
|
605
|
+
// ) => use((ns) => makeRpcStub(ns.get(id, options))),
|
|
606
|
+
// jurisdiction: (jurisdiction: cf.DurableObjectJurisdiction) =>
|
|
607
|
+
// use((ns) => ns.jurisdiction(jurisdiction) as any),
|
|
608
|
+
};
|
|
504
609
|
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
610
|
+
const constructor = yield* impl.pipe(
|
|
611
|
+
Effect.provideService(DurableObjectNamespaceScope, self as any),
|
|
612
|
+
);
|
|
508
613
|
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
614
|
+
return self;
|
|
615
|
+
}),
|
|
616
|
+
)) as any);
|
|
512
617
|
|
|
513
618
|
export type DurableObjectStub<Shape> = {
|
|
514
619
|
// TODO(sam): do we need to transform? hopefully not
|
|
@@ -522,248 +627,3 @@ export type DurableObjectStub<Shape> = {
|
|
|
522
627
|
never
|
|
523
628
|
>;
|
|
524
629
|
};
|
|
525
|
-
|
|
526
|
-
export class DurableObjectState extends Context.Service<
|
|
527
|
-
DurableObjectState,
|
|
528
|
-
{
|
|
529
|
-
// TODO(sam): is this needed when we have Effect?
|
|
530
|
-
// waitUntil(promise: Promise<any>): Effect.Effect<void>;
|
|
531
|
-
|
|
532
|
-
// TODO(sam): what are these? Where do they come from?
|
|
533
|
-
// readonly props: Props;
|
|
534
|
-
|
|
535
|
-
readonly id: cf.DurableObjectId;
|
|
536
|
-
readonly storage: DurableObjectStorage;
|
|
537
|
-
// TODO(sam): effect-native interface for container
|
|
538
|
-
container?: cf.Container;
|
|
539
|
-
blockConcurrencyWhile<T>(
|
|
540
|
-
callback: () => Effect.Effect<T>,
|
|
541
|
-
): Effect.Effect<T>;
|
|
542
|
-
acceptWebSocket(ws: DurableWebSocket, tags?: string[]): Effect.Effect<void>;
|
|
543
|
-
getWebSockets(tag?: string): Effect.Effect<DurableWebSocket[]>;
|
|
544
|
-
setWebSocketAutoResponse(
|
|
545
|
-
maybeReqResp?: cf.WebSocketRequestResponsePair,
|
|
546
|
-
): Effect.Effect<void>;
|
|
547
|
-
getWebSocketAutoResponse(): Effect.Effect<cf.WebSocketRequestResponsePair | null>;
|
|
548
|
-
getWebSocketAutoResponseTimestamp(
|
|
549
|
-
ws: cf.WebSocket,
|
|
550
|
-
): Effect.Effect<Date | null>;
|
|
551
|
-
setHibernatableWebSocketEventTimeout(
|
|
552
|
-
timeoutMs?: number,
|
|
553
|
-
): Effect.Effect<void>;
|
|
554
|
-
getHibernatableWebSocketEventTimeout(): Effect.Effect<number | null>;
|
|
555
|
-
getTags(ws: cf.WebSocket): Effect.Effect<string[]>;
|
|
556
|
-
abort(reason?: string): Effect.Effect<void>;
|
|
557
|
-
}
|
|
558
|
-
>()("Cloudflare.DurableObjectState") {}
|
|
559
|
-
|
|
560
|
-
export interface DurableObjectTransaction {
|
|
561
|
-
get<T = unknown>(
|
|
562
|
-
key: string,
|
|
563
|
-
options?: cf.DurableObjectGetOptions,
|
|
564
|
-
): Effect.Effect<T | undefined>;
|
|
565
|
-
get<T = unknown>(
|
|
566
|
-
keys: string[],
|
|
567
|
-
options?: cf.DurableObjectGetOptions,
|
|
568
|
-
): Effect.Effect<Map<string, T>>;
|
|
569
|
-
list<T = unknown>(
|
|
570
|
-
options?: cf.DurableObjectListOptions,
|
|
571
|
-
): Effect.Effect<Map<string, T>>;
|
|
572
|
-
put<T>(
|
|
573
|
-
key: string,
|
|
574
|
-
value: T,
|
|
575
|
-
options?: cf.DurableObjectPutOptions,
|
|
576
|
-
): Effect.Effect<void>;
|
|
577
|
-
put<T>(
|
|
578
|
-
entries: Record<string, T>,
|
|
579
|
-
options?: cf.DurableObjectPutOptions,
|
|
580
|
-
): Effect.Effect<void>;
|
|
581
|
-
delete(
|
|
582
|
-
key: string,
|
|
583
|
-
options?: cf.DurableObjectPutOptions,
|
|
584
|
-
): Effect.Effect<boolean>;
|
|
585
|
-
delete(
|
|
586
|
-
keys: string[],
|
|
587
|
-
options?: cf.DurableObjectPutOptions,
|
|
588
|
-
): Effect.Effect<number>;
|
|
589
|
-
rollback(): Effect.Effect<void>;
|
|
590
|
-
getAlarm(
|
|
591
|
-
options?: cf.DurableObjectGetAlarmOptions,
|
|
592
|
-
): Effect.Effect<number | null>;
|
|
593
|
-
setAlarm(
|
|
594
|
-
scheduledTime: number | Date,
|
|
595
|
-
options?: cf.DurableObjectSetAlarmOptions,
|
|
596
|
-
): Effect.Effect<void>;
|
|
597
|
-
deleteAlarm(options?: cf.DurableObjectSetAlarmOptions): Effect.Effect<void>;
|
|
598
|
-
}
|
|
599
|
-
export interface DurableObjectStorage {
|
|
600
|
-
get<T = unknown>(
|
|
601
|
-
key: string,
|
|
602
|
-
options?: cf.DurableObjectGetOptions,
|
|
603
|
-
): Effect.Effect<T | undefined>;
|
|
604
|
-
get<T = unknown>(
|
|
605
|
-
keys: string[],
|
|
606
|
-
options?: cf.DurableObjectGetOptions,
|
|
607
|
-
): Effect.Effect<Map<string, T>>;
|
|
608
|
-
list<T = unknown>(
|
|
609
|
-
options?: cf.DurableObjectListOptions,
|
|
610
|
-
): Effect.Effect<Map<string, T>>;
|
|
611
|
-
put<T>(
|
|
612
|
-
key: string,
|
|
613
|
-
value: T,
|
|
614
|
-
options?: cf.DurableObjectPutOptions,
|
|
615
|
-
): Effect.Effect<void>;
|
|
616
|
-
put<T>(
|
|
617
|
-
entries: Record<string, T>,
|
|
618
|
-
options?: cf.DurableObjectPutOptions,
|
|
619
|
-
): Effect.Effect<void>;
|
|
620
|
-
delete(
|
|
621
|
-
key: string,
|
|
622
|
-
options?: cf.DurableObjectPutOptions,
|
|
623
|
-
): Effect.Effect<boolean>;
|
|
624
|
-
delete(
|
|
625
|
-
keys: string[],
|
|
626
|
-
options?: cf.DurableObjectPutOptions,
|
|
627
|
-
): Effect.Effect<number>;
|
|
628
|
-
deleteAll(options?: cf.DurableObjectPutOptions): Effect.Effect<void>;
|
|
629
|
-
transaction<T>(
|
|
630
|
-
closure: (txn: DurableObjectTransaction) => Effect.Effect<T>,
|
|
631
|
-
): Effect.Effect<T>;
|
|
632
|
-
getAlarm(
|
|
633
|
-
options?: cf.DurableObjectGetAlarmOptions,
|
|
634
|
-
): Effect.Effect<number | null>;
|
|
635
|
-
setAlarm(
|
|
636
|
-
scheduledTime: number | Date,
|
|
637
|
-
options?: cf.DurableObjectSetAlarmOptions,
|
|
638
|
-
): Effect.Effect<void>;
|
|
639
|
-
deleteAlarm(options?: cf.DurableObjectSetAlarmOptions): Effect.Effect<void>;
|
|
640
|
-
sync(): Effect.Effect<void>;
|
|
641
|
-
sql: cf.SqlStorage;
|
|
642
|
-
kv: cf.SyncKvStorage;
|
|
643
|
-
transactionSync<T>(closure: () => T): T;
|
|
644
|
-
getCurrentBookmark(): Effect.Effect<string>;
|
|
645
|
-
getBookmarkForTime(timestamp: number | Date): Effect.Effect<string>;
|
|
646
|
-
onNextSessionRestoreBookmark(bookmark: string): Effect.Effect<string>;
|
|
647
|
-
}
|
|
648
|
-
|
|
649
|
-
const fromDurableObjectState = (
|
|
650
|
-
state: cf.DurableObjectState,
|
|
651
|
-
): DurableObjectState["Service"] => ({
|
|
652
|
-
id: state.id,
|
|
653
|
-
container: state.container,
|
|
654
|
-
storage: fromDurableObjectStorage(state.storage),
|
|
655
|
-
blockConcurrencyWhile: <T>(callback: () => Effect.Effect<T>) =>
|
|
656
|
-
Effect.tryPromise(() =>
|
|
657
|
-
state.blockConcurrencyWhile(() => Effect.runPromise(callback())),
|
|
658
|
-
),
|
|
659
|
-
acceptWebSocket: (ws: DurableWebSocket, tags?: string[]) =>
|
|
660
|
-
Effect.sync(() => state.acceptWebSocket(ws.ws, tags)),
|
|
661
|
-
getWebSockets: (tag?: string) =>
|
|
662
|
-
Effect.sync(() => state.getWebSockets(tag).map(fromWebSocket)),
|
|
663
|
-
setWebSocketAutoResponse: (maybeReqResp?: cf.WebSocketRequestResponsePair) =>
|
|
664
|
-
Effect.sync(() => state.setWebSocketAutoResponse(maybeReqResp)),
|
|
665
|
-
getWebSocketAutoResponse: () =>
|
|
666
|
-
Effect.sync(() => state.getWebSocketAutoResponse()),
|
|
667
|
-
getWebSocketAutoResponseTimestamp: (ws: cf.WebSocket) =>
|
|
668
|
-
Effect.sync(() => state.getWebSocketAutoResponseTimestamp(ws)),
|
|
669
|
-
setHibernatableWebSocketEventTimeout: (timeoutMs?: number) =>
|
|
670
|
-
Effect.sync(() => state.setHibernatableWebSocketEventTimeout(timeoutMs)),
|
|
671
|
-
getHibernatableWebSocketEventTimeout: () =>
|
|
672
|
-
Effect.sync(() => state.getHibernatableWebSocketEventTimeout()),
|
|
673
|
-
getTags: (ws: cf.WebSocket) => Effect.sync(() => state.getTags(ws)),
|
|
674
|
-
abort: (reason?: string) => Effect.sync(() => state.abort(reason)),
|
|
675
|
-
});
|
|
676
|
-
|
|
677
|
-
const fromDurableObjectTransaction = (
|
|
678
|
-
txn: cf.DurableObjectTransaction,
|
|
679
|
-
): DurableObjectTransaction => ({
|
|
680
|
-
get: ((keyOrKeys: string | string[], options?: cf.DurableObjectGetOptions) =>
|
|
681
|
-
Effect.tryPromise(() => txn.get(keyOrKeys as any, options))) as any,
|
|
682
|
-
list: (options?: cf.DurableObjectListOptions) =>
|
|
683
|
-
Effect.tryPromise(() => txn.list(options)),
|
|
684
|
-
put: ((
|
|
685
|
-
keyOrEntries: string | Record<string, unknown>,
|
|
686
|
-
valueOrOptions?: unknown,
|
|
687
|
-
maybeOptions?: cf.DurableObjectPutOptions,
|
|
688
|
-
) =>
|
|
689
|
-
typeof keyOrEntries === "string"
|
|
690
|
-
? Effect.tryPromise(() =>
|
|
691
|
-
txn.put(keyOrEntries, valueOrOptions, maybeOptions),
|
|
692
|
-
)
|
|
693
|
-
: Effect.tryPromise(() =>
|
|
694
|
-
txn.put(
|
|
695
|
-
keyOrEntries,
|
|
696
|
-
valueOrOptions as cf.DurableObjectPutOptions | undefined,
|
|
697
|
-
),
|
|
698
|
-
)) as any,
|
|
699
|
-
delete: ((
|
|
700
|
-
keyOrKeys: string | string[],
|
|
701
|
-
options?: cf.DurableObjectPutOptions,
|
|
702
|
-
) => Effect.tryPromise(() => txn.delete(keyOrKeys as any, options))) as any,
|
|
703
|
-
rollback: () => Effect.sync(() => txn.rollback()),
|
|
704
|
-
getAlarm: (options?: cf.DurableObjectGetAlarmOptions) =>
|
|
705
|
-
Effect.tryPromise(() => txn.getAlarm(options)),
|
|
706
|
-
setAlarm: (
|
|
707
|
-
scheduledTime: number | Date,
|
|
708
|
-
options?: cf.DurableObjectSetAlarmOptions,
|
|
709
|
-
) => Effect.tryPromise(() => txn.setAlarm(scheduledTime, options)),
|
|
710
|
-
deleteAlarm: (options?: cf.DurableObjectSetAlarmOptions) =>
|
|
711
|
-
Effect.tryPromise(() => txn.deleteAlarm(options)),
|
|
712
|
-
});
|
|
713
|
-
|
|
714
|
-
const fromDurableObjectStorage = (
|
|
715
|
-
storage: cf.DurableObjectStorage,
|
|
716
|
-
): DurableObjectStorage => ({
|
|
717
|
-
get: ((keyOrKeys: string | string[], options?: cf.DurableObjectGetOptions) =>
|
|
718
|
-
Effect.tryPromise(() => storage.get(keyOrKeys as any, options))) as any,
|
|
719
|
-
list: (options?: cf.DurableObjectListOptions) =>
|
|
720
|
-
Effect.tryPromise(() => storage.list(options)),
|
|
721
|
-
put: ((
|
|
722
|
-
keyOrEntries: string | Record<string, unknown>,
|
|
723
|
-
valueOrOptions?: unknown,
|
|
724
|
-
maybeOptions?: cf.DurableObjectPutOptions,
|
|
725
|
-
) =>
|
|
726
|
-
typeof keyOrEntries === "string"
|
|
727
|
-
? Effect.tryPromise(() =>
|
|
728
|
-
storage.put(keyOrEntries, valueOrOptions, maybeOptions),
|
|
729
|
-
)
|
|
730
|
-
: Effect.tryPromise(() =>
|
|
731
|
-
storage.put(
|
|
732
|
-
keyOrEntries,
|
|
733
|
-
valueOrOptions as cf.DurableObjectPutOptions | undefined,
|
|
734
|
-
),
|
|
735
|
-
)) as any,
|
|
736
|
-
delete: ((
|
|
737
|
-
keyOrKeys: string | string[],
|
|
738
|
-
options?: cf.DurableObjectPutOptions,
|
|
739
|
-
) =>
|
|
740
|
-
Effect.tryPromise(() => storage.delete(keyOrKeys as any, options))) as any,
|
|
741
|
-
deleteAll: (options?: cf.DurableObjectPutOptions) =>
|
|
742
|
-
Effect.tryPromise(() => storage.deleteAll(options)),
|
|
743
|
-
transaction: <T>(
|
|
744
|
-
closure: (txn: DurableObjectTransaction) => Effect.Effect<T>,
|
|
745
|
-
) =>
|
|
746
|
-
Effect.tryPromise(() =>
|
|
747
|
-
storage.transaction((txn) =>
|
|
748
|
-
Effect.runPromise(closure(fromDurableObjectTransaction(txn))),
|
|
749
|
-
),
|
|
750
|
-
),
|
|
751
|
-
getAlarm: (options?: cf.DurableObjectGetAlarmOptions) =>
|
|
752
|
-
Effect.tryPromise(() => storage.getAlarm(options)),
|
|
753
|
-
setAlarm: (
|
|
754
|
-
scheduledTime: number | Date,
|
|
755
|
-
options?: cf.DurableObjectSetAlarmOptions,
|
|
756
|
-
) => Effect.tryPromise(() => storage.setAlarm(scheduledTime, options)),
|
|
757
|
-
deleteAlarm: (options?: cf.DurableObjectSetAlarmOptions) =>
|
|
758
|
-
Effect.tryPromise(() => storage.deleteAlarm(options)),
|
|
759
|
-
sync: () => Effect.tryPromise(() => storage.sync()),
|
|
760
|
-
sql: storage.sql,
|
|
761
|
-
kv: storage.kv,
|
|
762
|
-
transactionSync: <T>(closure: () => T) => storage.transactionSync(closure),
|
|
763
|
-
getCurrentBookmark: () =>
|
|
764
|
-
Effect.tryPromise(() => storage.getCurrentBookmark()),
|
|
765
|
-
getBookmarkForTime: (timestamp: number | Date) =>
|
|
766
|
-
Effect.tryPromise(() => storage.getBookmarkForTime(timestamp)),
|
|
767
|
-
onNextSessionRestoreBookmark: (bookmark: string) =>
|
|
768
|
-
Effect.tryPromise(() => storage.onNextSessionRestoreBookmark(bookmark)),
|
|
769
|
-
});
|