effect-cf 0.35.0 → 0.37.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 +14 -0
- package/README.md +2 -0
- package/dist/ComputerWorkspace.d.mts +1 -1
- package/dist/ComputerWorkspace.mjs +1 -1
- package/dist/DurableObjectState-CpgAmFqo.d.mts +244 -0
- package/dist/{DurableObjectState-DcqElJ4e.mjs → DurableObjectState-DLL0YgBd.mjs} +3 -60
- package/dist/Mcp.d.mts +122 -0
- package/dist/Mcp.mjs +270 -0
- package/dist/Vitest.d.mts +2 -2
- package/dist/Vitest.mjs +2 -1
- package/dist/{DurableObjectState-DpYdNZgT.d.mts → Worker-Dl6_Pijl.d.mts} +2 -242
- package/dist/Worker-XsGJsCJX.mjs +885 -0
- package/dist/WorkerContext-Yobnfw-K.mjs +60 -0
- package/dist/{WorkflowBinding-Cn3AuUyP.d.mts → WorkflowBinding-CvJT9hB5.d.mts} +1 -1
- package/dist/index.d.mts +22 -3
- package/dist/index.mjs +114 -979
- package/package.json +12 -1
- package/src/DurableObjectAlarm.ts +80 -30
- package/src/Mcp.ts +531 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "effect-cf",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.37.0",
|
|
4
4
|
"description": "Effect-native primitives for Cloudflare Workers and bindings.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -27,6 +27,11 @@
|
|
|
27
27
|
"import": "./dist/HyperdrivePg.mjs",
|
|
28
28
|
"default": "./dist/HyperdrivePg.mjs"
|
|
29
29
|
},
|
|
30
|
+
"./mcp": {
|
|
31
|
+
"types": "./dist/Mcp.d.mts",
|
|
32
|
+
"import": "./dist/Mcp.mjs",
|
|
33
|
+
"default": "./dist/Mcp.mjs"
|
|
34
|
+
},
|
|
30
35
|
"./computer-artifacts": {
|
|
31
36
|
"types": "./dist/ComputerArtifacts.d.mts",
|
|
32
37
|
"import": "./dist/ComputerArtifacts.mjs",
|
|
@@ -75,6 +80,8 @@
|
|
|
75
80
|
"@effect/sql-pg": "catalog:",
|
|
76
81
|
"@effect/sql-sqlite-do": "catalog:",
|
|
77
82
|
"@effect/vitest": "catalog:",
|
|
83
|
+
"@modelcontextprotocol/client": "^2.0.0",
|
|
84
|
+
"@modelcontextprotocol/server": "^2.0.0",
|
|
78
85
|
"@platformatic/vfs": "^0.4.0",
|
|
79
86
|
"effect": "catalog:",
|
|
80
87
|
"esbuild": "^0.28.1",
|
|
@@ -89,6 +96,7 @@
|
|
|
89
96
|
"@effect/sql-d1": "^4.0.0-rc.110",
|
|
90
97
|
"@effect/sql-pg": "^4.0.0-rc.110",
|
|
91
98
|
"@effect/sql-sqlite-do": "^4.0.0-rc.110",
|
|
99
|
+
"@modelcontextprotocol/server": "^2.0.0",
|
|
92
100
|
"effect": "^4.0.0-rc.110"
|
|
93
101
|
},
|
|
94
102
|
"peerDependenciesMeta": {
|
|
@@ -106,6 +114,9 @@
|
|
|
106
114
|
},
|
|
107
115
|
"@effect/sql-pg": {
|
|
108
116
|
"optional": true
|
|
117
|
+
},
|
|
118
|
+
"@modelcontextprotocol/server": {
|
|
119
|
+
"optional": true
|
|
109
120
|
}
|
|
110
121
|
}
|
|
111
122
|
}
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
} from "effect";
|
|
13
13
|
|
|
14
14
|
import { DurableObjectState } from "./DurableObjectState";
|
|
15
|
-
import type
|
|
15
|
+
import { type SqlStorageValue, StorageOperationError } from "./DurableObjectStorage";
|
|
16
16
|
import * as ErrorMessage from "./internal/ErrorMessage";
|
|
17
17
|
|
|
18
18
|
const INIT_TABLE_SQL = `
|
|
@@ -177,8 +177,30 @@ export type ProcessDueAlarmsHandler<R = never, E = never> = (
|
|
|
177
177
|
event: DurableObjectAlarmEvent,
|
|
178
178
|
) => Effect.Effect<void, E, R>;
|
|
179
179
|
|
|
180
|
+
/**
|
|
181
|
+
* Alarm mutations owned by one transaction callback. Run them in the callback's
|
|
182
|
+
* fiber; forked work and use after the callback ends fail with StorageOperationError.
|
|
183
|
+
*/
|
|
184
|
+
export type AlarmTransaction = Pick<AlarmScheduler, "scheduleAlarm" | "cancelAlarm">;
|
|
185
|
+
|
|
180
186
|
/** Own `storage.setAlarm()` exclusively: a Durable Object has one platform alarm timestamp. */
|
|
181
187
|
export type AlarmScheduler = {
|
|
188
|
+
/**
|
|
189
|
+
* Commits local application storage and logical alarms in one native SQLite
|
|
190
|
+
* Durable Object transaction, reconciling the native alarm before commit.
|
|
191
|
+
* Use the supplied mutations, not standalone alarm methods or nested transactions.
|
|
192
|
+
* SqlClient queries must use this same Durable Object's storage.
|
|
193
|
+
*
|
|
194
|
+
* Failure, defects and interruption before commit roll back. A lost reply or
|
|
195
|
+
* interruption after commit does not undo committed state. Keep RPC and other
|
|
196
|
+
* external effects outside; atomically pre-arm a later wake before fallible work.
|
|
197
|
+
* Cloudflare's native retries are bounded; composition does not remove the
|
|
198
|
+
* pre-arm requirement or promise infinite retry liveness.
|
|
199
|
+
*/
|
|
200
|
+
readonly transaction: <A, E, R>(
|
|
201
|
+
closure: (alarms: AlarmTransaction) => Effect.Effect<A, E, R>,
|
|
202
|
+
) => Effect.Effect<A, E | StorageOperationError, R>;
|
|
203
|
+
|
|
182
204
|
readonly cancelAlarm: (
|
|
183
205
|
input: AlarmRef,
|
|
184
206
|
) => Effect.Effect<void, InvalidAlarmRefError | StorageOperationError>;
|
|
@@ -523,17 +545,9 @@ export class DurableObjectAlarm extends Context.Service<DurableObjectAlarm, Alar
|
|
|
523
545
|
const cancelAlarm = Effect.fn("DurableObjectAlarm.cancelAlarm")(function* (input: AlarmRef) {
|
|
524
546
|
const ref = yield* decodeAlarmRef(input);
|
|
525
547
|
|
|
526
|
-
yield* state.storage.
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
yield* state.storage.sql
|
|
530
|
-
.exec(
|
|
531
|
-
`DELETE FROM effect_cf_scheduled_alarms WHERE storage_id = ?`,
|
|
532
|
-
getScheduledEventId(ref),
|
|
533
|
-
)
|
|
534
|
-
.pipe(Effect.asVoid);
|
|
535
|
-
yield* reconcileAlarm();
|
|
536
|
-
}),
|
|
548
|
+
yield* state.storage.sql.exec(
|
|
549
|
+
`DELETE FROM effect_cf_scheduled_alarms WHERE storage_id = ?`,
|
|
550
|
+
getScheduledEventId(ref),
|
|
537
551
|
);
|
|
538
552
|
});
|
|
539
553
|
|
|
@@ -545,27 +559,62 @@ export class DurableObjectAlarm extends Context.Service<DurableObjectAlarm, Alar
|
|
|
545
559
|
const payload = yield* encodeStoredPayload(input.payload);
|
|
546
560
|
const runAt = DateTime.toEpochMillis(input.runAt);
|
|
547
561
|
|
|
548
|
-
yield* state.storage.
|
|
549
|
-
|
|
550
|
-
yield* ensureTable(state);
|
|
551
|
-
yield* state.storage.sql
|
|
552
|
-
.exec(
|
|
553
|
-
`INSERT OR REPLACE INTO effect_cf_scheduled_alarms
|
|
562
|
+
yield* state.storage.sql.exec(
|
|
563
|
+
`INSERT OR REPLACE INTO effect_cf_scheduled_alarms
|
|
554
564
|
(storage_id, alarm_id, tag, run_at, repeat_every_ms, payload)
|
|
555
565
|
VALUES (?, ?, ?, ?, ?, ?)`,
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
)
|
|
563
|
-
.pipe(Effect.asVoid);
|
|
564
|
-
yield* reconcileAlarm();
|
|
565
|
-
}),
|
|
566
|
+
getScheduledEventId(ref),
|
|
567
|
+
ref.id,
|
|
568
|
+
ref.tag,
|
|
569
|
+
runAt,
|
|
570
|
+
repeatEveryMillis,
|
|
571
|
+
payload,
|
|
566
572
|
);
|
|
567
573
|
});
|
|
568
574
|
|
|
575
|
+
const transaction: AlarmScheduler["transaction"] = (closure) =>
|
|
576
|
+
state.storage.transaction(() =>
|
|
577
|
+
Effect.withFiber((owner) => {
|
|
578
|
+
let active = true;
|
|
579
|
+
|
|
580
|
+
// A callback-owned handle cannot escape via a returned Effect or a
|
|
581
|
+
// detached fiber and write after reconciliation or rollback.
|
|
582
|
+
const requireActive = <A, E>(effect: Effect.Effect<A, E>) =>
|
|
583
|
+
Effect.withFiber<A, E | StorageOperationError>((fiber) =>
|
|
584
|
+
active && fiber === owner
|
|
585
|
+
? effect
|
|
586
|
+
: Effect.fail(
|
|
587
|
+
new StorageOperationError({
|
|
588
|
+
operation: "alarm.transaction",
|
|
589
|
+
cause: new Error(
|
|
590
|
+
"Alarm mutations require their active transaction callback",
|
|
591
|
+
),
|
|
592
|
+
}),
|
|
593
|
+
),
|
|
594
|
+
);
|
|
595
|
+
|
|
596
|
+
return Effect.gen(function* () {
|
|
597
|
+
yield* ensureTable(state);
|
|
598
|
+
const result = yield* Effect.suspend(() =>
|
|
599
|
+
closure({
|
|
600
|
+
cancelAlarm: (input) => requireActive(cancelAlarm(input)),
|
|
601
|
+
scheduleAlarm: (input) => requireActive(scheduleAlarm(input)),
|
|
602
|
+
}),
|
|
603
|
+
).pipe(
|
|
604
|
+
Effect.ensuring(
|
|
605
|
+
Effect.sync(() => {
|
|
606
|
+
active = false;
|
|
607
|
+
}),
|
|
608
|
+
),
|
|
609
|
+
);
|
|
610
|
+
|
|
611
|
+
yield* reconcileAlarm();
|
|
612
|
+
|
|
613
|
+
return result;
|
|
614
|
+
});
|
|
615
|
+
}),
|
|
616
|
+
);
|
|
617
|
+
|
|
569
618
|
const processDueAlarms = Effect.fn("DurableObjectAlarm.processDueAlarms")(function* <
|
|
570
619
|
R,
|
|
571
620
|
E,
|
|
@@ -669,9 +718,10 @@ export class DurableObjectAlarm extends Context.Service<DurableObjectAlarm, Alar
|
|
|
669
718
|
});
|
|
670
719
|
|
|
671
720
|
return DurableObjectAlarm.of({
|
|
672
|
-
cancelAlarm,
|
|
721
|
+
cancelAlarm: (input) => transaction((alarms) => alarms.cancelAlarm(input)),
|
|
673
722
|
processDueAlarms,
|
|
674
|
-
scheduleAlarm,
|
|
723
|
+
scheduleAlarm: (input) => transaction((alarms) => alarms.scheduleAlarm(input)),
|
|
724
|
+
transaction,
|
|
675
725
|
});
|
|
676
726
|
}).pipe(Effect.withSpan("DurableObjectAlarm.layer")),
|
|
677
727
|
);
|