@swirls/looms 0.3.0 → 0.5.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 +64 -0
- package/dist/actor/cell.d.ts +21 -2
- package/dist/actor/cell.js +15 -3
- package/dist/actor/host.d.ts +10 -2
- package/dist/actor/host.js +27 -4
- package/dist/actor/index.d.ts +2 -1
- package/dist/actor/index.js +1 -1
- package/dist/actor/routing.d.ts +3 -0
- package/dist/actor/routing.js +13 -2
- package/dist/agent/debugger/agent-chat.js +3 -30
- package/dist/agent/debugger/streaming-text.d.ts +6 -0
- package/dist/agent/debugger/streaming-text.js +33 -0
- package/dist/agent/definitions-store.d.ts +1 -1
- package/dist/agent/definitions-store.js +1 -1
- package/dist/agent/definitions.d.ts +48 -0
- package/dist/agent/definitions.js +44 -0
- package/dist/agent/effects.d.ts +184 -0
- package/dist/agent/effects.js +172 -40
- package/dist/agent/events.d.ts +89 -0
- package/dist/agent/events.js +25 -0
- package/dist/agent/module.d.ts +819 -407
- package/dist/agent/module.js +5 -1
- package/dist/agent/scope.d.ts +88 -0
- package/dist/agent/threads.js +39 -3
- package/dist/agent/types.d.ts +4 -0
- package/dist/approval/effects.d.ts +40 -0
- package/dist/approval/module.d.ts +80 -0
- package/dist/client/client.d.ts +468 -119
- package/dist/client/client.js +214 -21
- package/dist/client/index.d.ts +1 -1
- package/dist/client/sse.d.ts +1 -1
- package/dist/client/sse.js +2 -2
- package/dist/cloudflare/durable-object.d.ts +66 -2
- package/dist/cloudflare/durable-object.js +96 -1
- package/dist/cloudflare/event-store.d.ts +7 -3
- package/dist/cloudflare/event-store.js +16 -3
- package/dist/cloudflare/index.d.ts +7 -1
- package/dist/cloudflare/index.js +7 -1
- package/dist/cloudflare/memory-queue.d.ts +18 -0
- package/dist/cloudflare/memory-queue.js +53 -0
- package/dist/cloudflare/queue-consumer.d.ts +52 -0
- package/dist/cloudflare/queue-consumer.js +102 -0
- package/dist/cloudflare/queue-message.d.ts +31 -0
- package/dist/cloudflare/queue-message.js +33 -0
- package/dist/cloudflare/queue-pull.d.ts +62 -0
- package/dist/cloudflare/queue-pull.js +130 -0
- package/dist/cloudflare/queue-worker.d.ts +39 -0
- package/dist/cloudflare/queue-worker.js +62 -0
- package/dist/cloudflare/r2-blob-store.d.ts +33 -0
- package/dist/cloudflare/r2-blob-store.js +60 -0
- package/dist/cloudflare/router.d.ts +4 -1
- package/dist/cloudflare/router.js +8 -3
- package/dist/cloudflare/websocket.d.ts +27 -0
- package/dist/cloudflare/websocket.js +215 -0
- package/dist/core/attempts.d.ts +8 -0
- package/dist/core/attempts.js +27 -0
- package/dist/core/blob-offload.d.ts +21 -0
- package/dist/core/blob-offload.js +143 -0
- package/dist/core/blob-store.d.ts +45 -0
- package/dist/core/blob-store.js +164 -0
- package/dist/core/blobs.d.ts +37 -0
- package/dist/core/blobs.js +160 -0
- package/dist/core/definition-resolver.d.ts +40 -0
- package/dist/core/definition-resolver.js +129 -0
- package/dist/core/definition-store.d.ts +6 -0
- package/dist/core/definition-store.js +37 -1
- package/dist/core/effects.d.ts +86 -3
- package/dist/core/effects.js +99 -3
- package/dist/core/envelope.d.ts +9 -0
- package/dist/core/envelope.js +4 -0
- package/dist/core/event-codec.js +3 -0
- package/dist/core/fold.js +83 -1
- package/dist/core/ids.d.ts +2 -0
- package/dist/core/ids.js +4 -0
- package/dist/core/index.d.ts +10 -0
- package/dist/core/index.js +9 -0
- package/dist/core/launcher.d.ts +97 -0
- package/dist/core/launcher.js +67 -0
- package/dist/core/module-scope.d.ts +7 -3
- package/dist/core/module-scope.js +3 -0
- package/dist/core/module.d.ts +10 -0
- package/dist/core/projection.d.ts +5 -4
- package/dist/core/projection.js +4 -0
- package/dist/core/protocol.d.ts +36 -1
- package/dist/core/protocol.js +35 -0
- package/dist/core/published.d.ts +2 -0
- package/dist/core/published.js +4 -1
- package/dist/{react → core}/register.d.ts +9 -8
- package/dist/core/replay.d.ts +96 -0
- package/dist/core/run-context.d.ts +33 -0
- package/dist/core/run-context.js +23 -0
- package/dist/core/sqlite-store.js +57 -5
- package/dist/core/state.d.ts +60 -0
- package/dist/core/state.js +19 -0
- package/dist/core/store.d.ts +6 -0
- package/dist/core/store.js +7 -0
- package/dist/core/subscription.d.ts +97 -0
- package/dist/core/subscription.js +224 -0
- package/dist/core/thread.d.ts +7 -0
- package/dist/core/thread.js +1 -0
- package/dist/core/trace.d.ts +21 -0
- package/dist/core/trace.js +45 -0
- package/dist/core/worker-callback.d.ts +25 -1
- package/dist/debugger/app/assets/{index-CgDzWJg7.css → index-B7GdT1UA.css} +1 -1
- package/dist/debugger/app/assets/index-C31SnCuN.js +22 -0
- package/dist/debugger/app/assets/routes-DPA3O5AF.js +47 -0
- package/dist/debugger/app/index.html +2 -2
- package/dist/debugger/components/event-inspector.d.ts +3 -1
- package/dist/debugger/components/event-inspector.js +25 -4
- package/dist/debugger/components/event-stream.d.ts +4 -1
- package/dist/debugger/components/event-stream.js +2 -2
- package/dist/debugger/components/run-tree.d.ts +5 -2
- package/dist/debugger/components/run-tree.js +10 -4
- package/dist/debugger/context.d.ts +8 -1
- package/dist/debugger/context.js +15 -3
- package/dist/debugger/events/protocol-summarize.js +18 -3
- package/dist/debugger/index.d.ts +1 -1
- package/dist/debugger/index.js +1 -1
- package/dist/debugger/shell/debugger-shell.js +1 -1
- package/dist/debugger/shell/events-pane.js +4 -3
- package/dist/debugger/styles.css +1 -0
- package/dist/evaluator/definitions-store.d.ts +3 -4
- package/dist/evaluator/definitions-store.js +3 -3
- package/dist/evaluator/definitions.d.ts +4 -1
- package/dist/evaluator/definitions.js +5 -2
- package/dist/evaluator/effects.d.ts +41 -0
- package/dist/evaluator/effects.js +6 -2
- package/dist/evaluator/module.d.ts +84 -0
- package/dist/evaluator/module.js +7 -3
- package/dist/evaluator/threads.d.ts +2 -0
- package/dist/evaluator/threads.js +4 -0
- package/dist/projectors/event-log.d.ts +87 -0
- package/dist/projectors/event-log.js +396 -0
- package/dist/projectors/index-model.d.ts +12 -0
- package/dist/projectors/index-model.js +12 -3
- package/dist/projectors/memory.js +7 -0
- package/dist/projectors/postgres.d.ts +1 -0
- package/dist/projectors/postgres.js +32 -15
- package/dist/projectors/schema.d.ts +5 -0
- package/dist/projectors/schema.js +26 -1
- package/dist/projectors/sqlite.js +47 -19
- package/dist/projectors/with-projectors.d.ts +7 -1
- package/dist/projectors/with-projectors.js +13 -3
- package/dist/react/derived.d.ts +26 -8
- package/dist/react/derived.js +23 -26
- package/dist/react/index.d.ts +3 -3
- package/dist/react/index.js +2 -2
- package/dist/react/materialize.js +5 -1
- package/dist/react/react.d.ts +16 -9
- package/dist/react/react.js +47 -23
- package/dist/react/store.d.ts +14 -6
- package/dist/react/store.js +104 -12
- package/dist/react/tables.d.ts +4 -1
- package/dist/runtime/cancellation.d.ts +2 -1
- package/dist/runtime/cancellation.js +35 -2
- package/dist/runtime/child-run.d.ts +10 -0
- package/dist/runtime/child-run.js +58 -0
- package/dist/runtime/deadline-transition-planner.js +11 -2
- package/dist/runtime/dispatch-effect.d.ts +2 -2
- package/dist/runtime/dispatch-effect.js +43 -19
- package/dist/runtime/errors.d.ts +14 -1
- package/dist/runtime/errors.js +10 -0
- package/dist/runtime/filesystem-blob-store.d.ts +6 -0
- package/dist/runtime/filesystem-blob-store.js +59 -0
- package/dist/runtime/helpers.d.ts +15 -6
- package/dist/runtime/helpers.js +46 -6
- package/dist/runtime/index.d.ts +4 -2
- package/dist/runtime/index.js +3 -1
- package/dist/runtime/local-effect-executor.d.ts +11 -2
- package/dist/runtime/local-effect-executor.js +80 -4
- package/dist/runtime/looms.d.ts +38 -4
- package/dist/runtime/looms.js +17 -3
- package/dist/runtime/repository.d.ts +5 -4
- package/dist/runtime/repository.js +5 -2
- package/dist/runtime/retry-policy.d.ts +5 -0
- package/dist/runtime/retry-policy.js +10 -2
- package/dist/runtime/run-start.d.ts +1 -1
- package/dist/runtime/run-start.js +10 -0
- package/dist/runtime/runtime.d.ts +2 -2
- package/dist/runtime/runtime.js +191 -68
- package/dist/runtime/server/auth.d.ts +3 -0
- package/dist/runtime/server/fetch-handler.d.ts +2 -2
- package/dist/runtime/server/fetch-handler.js +35 -4
- package/dist/runtime/server/grant.d.ts +49 -0
- package/dist/runtime/server/grant.js +177 -0
- package/dist/runtime/server/routes/effects.js +47 -5
- package/dist/runtime/server/routes/runs.js +6 -1
- package/dist/runtime/server/run-route.d.ts +18 -0
- package/dist/runtime/server/run-route.js +26 -0
- package/dist/runtime/server.d.ts +3 -1
- package/dist/runtime/server.js +3 -1
- package/dist/runtime/sse.js +26 -4
- package/dist/runtime/subscription.d.ts +8 -0
- package/dist/runtime/subscription.js +23 -0
- package/dist/runtime/types.d.ts +87 -8
- package/dist/runtime/wake-engine.d.ts +4 -2
- package/dist/runtime/wake-engine.js +57 -6
- package/dist/runtime/worker-callbacks.d.ts +12 -2
- package/dist/runtime/worker-callbacks.js +102 -72
- package/dist/runtime/worker-effect-dispatch.d.ts +14 -5
- package/dist/runtime/worker-effect-dispatch.js +84 -18
- package/dist/schedule/debugger/index.d.ts +4 -0
- package/dist/schedule/debugger/index.js +11 -0
- package/dist/schedule/debugger/schedule-view.d.ts +3 -0
- package/dist/schedule/debugger/schedule-view.js +68 -0
- package/dist/schedule/debugger/summarize.d.ts +2 -0
- package/dist/schedule/debugger/summarize.js +43 -0
- package/dist/schedule/definitions-store.d.ts +10 -0
- package/dist/schedule/definitions-store.js +8 -0
- package/dist/schedule/definitions.d.ts +57 -0
- package/dist/schedule/definitions.js +30 -0
- package/dist/schedule/effects.d.ts +756 -0
- package/dist/schedule/effects.js +244 -0
- package/dist/schedule/ensure.d.ts +55 -0
- package/dist/schedule/ensure.js +109 -0
- package/dist/schedule/events.d.ts +116 -0
- package/dist/schedule/events.js +49 -0
- package/dist/schedule/index.d.ts +11 -0
- package/dist/schedule/index.js +11 -0
- package/dist/schedule/module.d.ts +1474 -0
- package/dist/schedule/module.js +22 -0
- package/dist/schedule/projections.d.ts +55 -0
- package/dist/schedule/projections.js +88 -0
- package/dist/schedule/scope.d.ts +121 -0
- package/dist/schedule/scope.js +7 -0
- package/dist/schedule/signals.d.ts +25 -0
- package/dist/schedule/signals.js +33 -0
- package/dist/schedule/specs.d.ts +59 -0
- package/dist/schedule/specs.js +231 -0
- package/dist/schedule/threads.d.ts +25 -0
- package/dist/schedule/threads.js +259 -0
- package/dist/testing/corpus-module.d.ts +34 -0
- package/dist/testing/corpus-module.js +87 -0
- package/dist/testing/index.d.ts +2 -0
- package/dist/testing/index.js +5 -6
- package/dist/testing/replay-corpus.d.ts +22 -0
- package/dist/testing/replay-corpus.js +50 -0
- package/dist/workflow/definitions-store.d.ts +1 -1
- package/dist/workflow/definitions-store.js +1 -1
- package/dist/workflow/definitions.d.ts +14 -0
- package/dist/workflow/effects.d.ts +122 -0
- package/dist/workflow/effects.js +16 -6
- package/dist/workflow/events.d.ts +42 -0
- package/dist/workflow/events.js +4 -0
- package/dist/workflow/module.d.ts +345 -32
- package/dist/workflow/module.js +7 -3
- package/dist/workflow/scope.d.ts +42 -0
- package/dist/workflow/threads.d.ts +72 -0
- package/dist/workflow/threads.js +106 -38
- package/package.json +11 -2
- package/dist/debugger/app/assets/index-BevQYa-U.js +0 -22
- package/dist/debugger/app/assets/routes-B17Om93i.js +0 -47
- /package/dist/{react → core}/register.js +0 -0
|
@@ -1,21 +1,54 @@
|
|
|
1
1
|
import { Database } from 'bun:sqlite';
|
|
2
2
|
import { createIndexProjector, } from './index-model.js';
|
|
3
3
|
import { runProjectorSync } from './projector.js';
|
|
4
|
-
import {
|
|
4
|
+
import { SQLITE_ADDED_ACTOR_COLUMNS, SQLITE_INDEXES_SQL, SQLITE_TABLES_SQL } from './schema.js';
|
|
5
5
|
export { SQLITE_SCHEMA_SQL } from './schema.js';
|
|
6
|
+
const ACTOR_COLUMNS = `run_id, actor_id, kind, status, definition_name, parent_actor_id,
|
|
7
|
+
launched_by_run_id, launched_by_effect_id, correlation_id, updated_at`;
|
|
6
8
|
function hasDb(options) {
|
|
7
9
|
return 'db' in options;
|
|
8
10
|
}
|
|
11
|
+
function actorFromRow(row) {
|
|
12
|
+
return {
|
|
13
|
+
runId: row.run_id,
|
|
14
|
+
actorId: row.actor_id,
|
|
15
|
+
kind: row.kind,
|
|
16
|
+
status: row.status,
|
|
17
|
+
definitionName: row.definition_name,
|
|
18
|
+
parentActorId: row.parent_actor_id,
|
|
19
|
+
launchedByRunId: row.launched_by_run_id,
|
|
20
|
+
launchedByEffectId: row.launched_by_effect_id,
|
|
21
|
+
correlationId: row.correlation_id,
|
|
22
|
+
updatedAt: row.updated_at,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
/** Creates the tables, adds columns a database from an earlier release lacks, then indexes them. */
|
|
26
|
+
function migrate(db) {
|
|
27
|
+
db.exec(SQLITE_TABLES_SQL);
|
|
28
|
+
const existing = new Set(db
|
|
29
|
+
.query('PRAGMA table_info(looms_run_actors)')
|
|
30
|
+
.all()
|
|
31
|
+
.map((column) => column.name));
|
|
32
|
+
for (const column of SQLITE_ADDED_ACTOR_COLUMNS) {
|
|
33
|
+
if (!existing.has(column)) {
|
|
34
|
+
db.exec(`ALTER TABLE looms_run_actors ADD COLUMN ${column} TEXT`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
db.exec(SQLITE_INDEXES_SQL);
|
|
38
|
+
}
|
|
9
39
|
function applyOp(db, op) {
|
|
10
40
|
switch (op.type) {
|
|
11
41
|
case 'upsertActor':
|
|
12
|
-
db.run(`INSERT INTO looms_run_actors (
|
|
13
|
-
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
42
|
+
db.run(`INSERT INTO looms_run_actors (${ACTOR_COLUMNS})
|
|
43
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
14
44
|
ON CONFLICT (run_id, actor_id) DO UPDATE SET
|
|
15
45
|
kind = excluded.kind,
|
|
16
46
|
status = excluded.status,
|
|
17
47
|
definition_name = excluded.definition_name,
|
|
18
48
|
parent_actor_id = excluded.parent_actor_id,
|
|
49
|
+
launched_by_run_id = excluded.launched_by_run_id,
|
|
50
|
+
launched_by_effect_id = excluded.launched_by_effect_id,
|
|
51
|
+
correlation_id = excluded.correlation_id,
|
|
19
52
|
updated_at = excluded.updated_at`, [
|
|
20
53
|
op.runId,
|
|
21
54
|
op.actorId,
|
|
@@ -23,6 +56,9 @@ function applyOp(db, op) {
|
|
|
23
56
|
op.status,
|
|
24
57
|
op.definitionName,
|
|
25
58
|
op.parentActorId,
|
|
59
|
+
op.launchedByRunId,
|
|
60
|
+
op.launchedByEffectId,
|
|
61
|
+
op.correlationId,
|
|
26
62
|
op.updatedAt,
|
|
27
63
|
]);
|
|
28
64
|
return;
|
|
@@ -53,9 +89,7 @@ export function sqlite(options = {}) {
|
|
|
53
89
|
const createdDb = !hasDb(options);
|
|
54
90
|
const db = hasDb(options) ? options.db : new Database(options.path ?? ':memory:');
|
|
55
91
|
const backend = {
|
|
56
|
-
init: () => runProjectorSync('sqlite', () =>
|
|
57
|
-
db.exec(SQLITE_SCHEMA_SQL);
|
|
58
|
-
}),
|
|
92
|
+
init: () => runProjectorSync('sqlite', () => migrate(db)),
|
|
59
93
|
applyOps: (ops) => runProjectorSync('sqlite', () => {
|
|
60
94
|
const apply = db.transaction((batch) => {
|
|
61
95
|
for (const op of batch) {
|
|
@@ -66,21 +100,15 @@ export function sqlite(options = {}) {
|
|
|
66
100
|
}),
|
|
67
101
|
getActor: (runId, actorId) => runProjectorSync('sqlite', () => {
|
|
68
102
|
const row = db
|
|
69
|
-
.query(`SELECT run_id
|
|
70
|
-
FROM looms_run_actors WHERE run_id = ? AND actor_id = ?`)
|
|
103
|
+
.query(`SELECT ${ACTOR_COLUMNS} FROM looms_run_actors WHERE run_id = ? AND actor_id = ?`)
|
|
71
104
|
.get(runId, actorId);
|
|
72
|
-
return row
|
|
73
|
-
? {
|
|
74
|
-
runId: row.run_id,
|
|
75
|
-
actorId: row.actor_id,
|
|
76
|
-
kind: row.kind,
|
|
77
|
-
status: row.status,
|
|
78
|
-
definitionName: row.definition_name,
|
|
79
|
-
parentActorId: row.parent_actor_id,
|
|
80
|
-
updatedAt: row.updated_at,
|
|
81
|
-
}
|
|
82
|
-
: null;
|
|
105
|
+
return row ? actorFromRow(row) : null;
|
|
83
106
|
}),
|
|
107
|
+
listLaunched: (runId) => runProjectorSync('sqlite', () => db
|
|
108
|
+
.query(`SELECT ${ACTOR_COLUMNS} FROM looms_run_actors
|
|
109
|
+
WHERE launched_by_run_id = ? AND actor_id = run_id ORDER BY updated_at`)
|
|
110
|
+
.all(runId)
|
|
111
|
+
.map(actorFromRow)),
|
|
84
112
|
listReviews: (runId) => runProjectorSync('sqlite', () => {
|
|
85
113
|
const rows = runId
|
|
86
114
|
? db
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Layer } from 'effect';
|
|
1
|
+
import { Effect, Layer } from 'effect';
|
|
2
2
|
import { EventStoreTag, type EventStore, type EventEnvelope } from '@swirls/looms/core';
|
|
3
3
|
import type { ProjectorDelivery } from './delivery';
|
|
4
4
|
import { type Projector, type ProjectorErrorHandler } from './projector';
|
|
@@ -6,6 +6,12 @@ export interface WithProjectorsOptions {
|
|
|
6
6
|
onError?: ProjectorErrorHandler;
|
|
7
7
|
/** Durable cursor runner. When present, appends trigger catch-up from its persisted cursor. */
|
|
8
8
|
delivery?: ProjectorDelivery;
|
|
9
|
+
/**
|
|
10
|
+
* Runs projection after the append commits, without making the append wait.
|
|
11
|
+
* The callback has to keep the effect alive, for example with a Durable Object's `waitUntil`.
|
|
12
|
+
* Without it, projection still finishes before `append` returns.
|
|
13
|
+
*/
|
|
14
|
+
scheduleDelivery?: (runId: string, delivery: Effect.Effect<void>) => void;
|
|
9
15
|
}
|
|
10
16
|
/**
|
|
11
17
|
* Wrap an EventStore so every successful append is also projected.
|
|
@@ -16,6 +16,7 @@ function logDeliveryFailure(runId, cause) {
|
|
|
16
16
|
export function withProjectors(store, projectors, options) {
|
|
17
17
|
const onError = options?.onError ?? defaultOnError;
|
|
18
18
|
const delivery = options?.delivery;
|
|
19
|
+
const scheduleDelivery = options?.scheduleDelivery;
|
|
19
20
|
const project = (runId, sequences) => {
|
|
20
21
|
if (delivery) {
|
|
21
22
|
return delivery.deliver(runId).pipe(Effect.catch((cause) => logDeliveryFailure(runId, cause)));
|
|
@@ -29,9 +30,18 @@ export function withProjectors(store, projectors, options) {
|
|
|
29
30
|
}))), { concurrency: 'unbounded', discard: true })), Effect.catch((cause) => logDeliveryFailure(runId, cause)));
|
|
30
31
|
};
|
|
31
32
|
const wrapped = {
|
|
32
|
-
append: (runId, events, appendOptions) => store
|
|
33
|
-
.
|
|
34
|
-
|
|
33
|
+
append: (runId, events, appendOptions) => store.append(runId, events, appendOptions).pipe(Effect.tap((result) => {
|
|
34
|
+
if (projectors.length === 0) {
|
|
35
|
+
return Effect.void;
|
|
36
|
+
}
|
|
37
|
+
const work = project(runId, result.sequences);
|
|
38
|
+
if (!scheduleDelivery) {
|
|
39
|
+
return work;
|
|
40
|
+
}
|
|
41
|
+
return Effect.sync(() => {
|
|
42
|
+
scheduleDelivery(runId, work);
|
|
43
|
+
});
|
|
44
|
+
})),
|
|
35
45
|
read: (runId, readOptions) => store.read(runId, readOptions),
|
|
36
46
|
tail: (runId) => store.tail(runId),
|
|
37
47
|
bounds: store.bounds ? (runId) => store.bounds(runId) : undefined,
|
package/dist/react/derived.d.ts
CHANGED
|
@@ -1,19 +1,37 @@
|
|
|
1
|
-
import { type EventEnvelope, type ProjectionDefinition } from '@swirls/looms/core';
|
|
2
|
-
import type { AnyEventEnvelope, RegisteredEvent } from './register';
|
|
3
|
-
export type { AnyEventEnvelope } from './register';
|
|
1
|
+
import { type AnyEventEnvelope, type EventEnvelope, type InferSchemaOutput, type ProjectionDefinition, type RegisteredEvent, type SchemaInput } from '@swirls/looms/core';
|
|
4
2
|
export { EventIndex, eventThreadKey } from '@swirls/looms/core';
|
|
5
|
-
export interface
|
|
3
|
+
export interface LiveFoldDefinition<S, TEvent extends AnyEventEnvelope = RegisteredEvent> {
|
|
4
|
+
readonly kind: 'liveFold';
|
|
6
5
|
readonly name?: string;
|
|
6
|
+
readonly shape?: unknown;
|
|
7
7
|
readonly initialState: S;
|
|
8
8
|
reduce(state: S, event: TEvent): S;
|
|
9
|
-
readonly includeEphemeral?: boolean;
|
|
10
9
|
}
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
/**
|
|
11
|
+
* Client-side fold that sees ephemeral events, which projections skip. Ephemeral events from an
|
|
12
|
+
* effect attempt that the runtime later retried never reach the reducer. The reducer still owns
|
|
13
|
+
* resets on domain events, such as the durable message that replaces streamed text. Use a
|
|
14
|
+
* projection for anything else.
|
|
15
|
+
*/
|
|
16
|
+
export declare function defineLiveFold<S, TEvent extends AnyEventEnvelope = RegisteredEvent>(def: {
|
|
17
|
+
readonly name?: string;
|
|
18
|
+
readonly shape?: undefined;
|
|
19
|
+
readonly initialState: S;
|
|
20
|
+
reduce(state: S, event: TEvent): S;
|
|
21
|
+
}): LiveFoldDefinition<S, TEvent>;
|
|
22
|
+
export declare function defineLiveFold<TShape extends SchemaInput, TEvent extends AnyEventEnvelope = RegisteredEvent>(def: {
|
|
23
|
+
readonly name?: string;
|
|
24
|
+
readonly shape: TShape;
|
|
25
|
+
readonly initialState: InferSchemaOutput<TShape>;
|
|
26
|
+
reduce(state: NoInfer<InferSchemaOutput<TShape>>, event: TEvent): InferSchemaOutput<TShape>;
|
|
27
|
+
}): LiveFoldDefinition<InferSchemaOutput<TShape>, TEvent>;
|
|
28
|
+
/** Fold events through a live fold, as `useLiveFold` does, including ephemeral events. */
|
|
29
|
+
export declare function foldLive<S, TEvent extends AnyEventEnvelope = RegisteredEvent>(definition: LiveFoldDefinition<S, TEvent>, events: readonly TEvent[]): S;
|
|
13
30
|
export declare class ProjectionCache {
|
|
14
31
|
private projectionCache;
|
|
15
32
|
private foldCache;
|
|
16
33
|
project<S>(definition: ProjectionDefinition<S>, events: readonly EventEnvelope[]): S;
|
|
17
|
-
|
|
34
|
+
/** A retry can supersede events already folded, so a batch containing one refolds from scratch. */
|
|
35
|
+
fold<S, TEvent extends AnyEventEnvelope = RegisteredEvent>(definition: LiveFoldDefinition<S, TEvent>, events: readonly TEvent[]): S;
|
|
18
36
|
clear(): void;
|
|
19
37
|
}
|
package/dist/react/derived.js
CHANGED
|
@@ -1,37 +1,33 @@
|
|
|
1
|
-
import { project } from '@swirls/looms/core';
|
|
1
|
+
import { dropSupersededAttempts, project, retriedEffectId, } from '@swirls/looms/core';
|
|
2
2
|
export { EventIndex, eventThreadKey } from '@swirls/looms/core';
|
|
3
|
-
export function
|
|
4
|
-
return def;
|
|
3
|
+
export function defineLiveFold(def) {
|
|
4
|
+
return { ...def, kind: 'liveFold' };
|
|
5
5
|
}
|
|
6
|
-
|
|
7
|
-
let state = from
|
|
8
|
-
const
|
|
9
|
-
for (const event of events) {
|
|
10
|
-
if (event.ephemeral && !includeEphemeral) {
|
|
11
|
-
continue;
|
|
12
|
-
}
|
|
6
|
+
function foldFrom(definition, events, from) {
|
|
7
|
+
let state = from;
|
|
8
|
+
for (const event of dropSupersededAttempts(events)) {
|
|
13
9
|
state = definition.reduce(state, event);
|
|
14
10
|
}
|
|
15
11
|
return state;
|
|
16
12
|
}
|
|
17
|
-
|
|
18
|
-
|
|
13
|
+
/** Fold events through a live fold, as `useLiveFold` does, including ephemeral events. */
|
|
14
|
+
export function foldLive(definition, events) {
|
|
15
|
+
return foldFrom(definition, events, definition.initialState);
|
|
16
|
+
}
|
|
17
|
+
function hasNoRetries(batch) {
|
|
18
|
+
return !batch.some((event) => retriedEffectId(event) !== undefined);
|
|
19
|
+
}
|
|
20
|
+
/** Folds only the events appended since the last call, unless `canAppend` rejects them. */
|
|
21
|
+
function advanceCache(cache, definition, events, compute, canAppend = () => true) {
|
|
19
22
|
const cached = cache.get(definition);
|
|
20
|
-
if (
|
|
21
|
-
const state = compute(definition, events);
|
|
22
|
-
cache.set(definition, { state, upTo: total });
|
|
23
|
-
return state;
|
|
24
|
-
}
|
|
25
|
-
if (cached.upTo === total) {
|
|
23
|
+
if (cached?.upTo === events.length) {
|
|
26
24
|
return cached.state;
|
|
27
25
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
}
|
|
33
|
-
const state = compute(definition, events);
|
|
34
|
-
cache.set(definition, { state, upTo: total });
|
|
26
|
+
const batch = cached && cached.upTo < events.length ? events.slice(cached.upTo) : undefined;
|
|
27
|
+
const state = cached && batch && canAppend(batch)
|
|
28
|
+
? compute(definition, batch, cached.state)
|
|
29
|
+
: compute(definition, events, definition.initialState);
|
|
30
|
+
cache.set(definition, { state, upTo: events.length });
|
|
35
31
|
return state;
|
|
36
32
|
}
|
|
37
33
|
export class ProjectionCache {
|
|
@@ -40,8 +36,9 @@ export class ProjectionCache {
|
|
|
40
36
|
project(definition, events) {
|
|
41
37
|
return advanceCache(this.projectionCache, definition, events, project);
|
|
42
38
|
}
|
|
39
|
+
/** A retry can supersede events already folded, so a batch containing one refolds from scratch. */
|
|
43
40
|
fold(definition, events) {
|
|
44
|
-
return advanceCache(this.foldCache, definition, events,
|
|
41
|
+
return advanceCache(this.foldCache, definition, events, foldFrom, hasNoRetries);
|
|
45
42
|
}
|
|
46
43
|
clear() {
|
|
47
44
|
this.projectionCache = new WeakMap();
|
package/dist/react/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { createLoomsStore, type LoomsClientStore, type LoomsClientStoreOptions, type LoomsConnectionStatus, type LoomsStoreQuery, type CoalesceOption, type StoreListener, } from './store';
|
|
2
|
-
export {
|
|
2
|
+
export { defineLiveFold, foldLive, EventIndex, eventThreadKey, type LiveFoldDefinition, } from './derived';
|
|
3
3
|
export { materializeEvents } from './materialize';
|
|
4
4
|
export { emptyTables, type MaterializedTables, type RunRow, type ThreadRow } from './tables';
|
|
5
|
-
export type { LoomsRegister, RegisteredEvent, AnyEventEnvelope } from '
|
|
6
|
-
export { LoomsProvider, useRunStore, useProjection, useRunSelector, useRunSummary, useRunEvents, useThreadTree, useEventCounts, useEventBySeq, useLatestEvent,
|
|
5
|
+
export type { LoomsRegister, RegisteredEvent, AnyEventEnvelope } from '@swirls/looms/core';
|
|
6
|
+
export { LoomsProvider, useRunStore, useProjection, useRunSelector, useRunSummary, useRunEvents, useThreadTree, useEventCounts, useEventBySeq, useLatestEvent, useLiveFold, type LoomsProviderProps, type UseRunStoreOptions, type RunSummary, } from './react';
|
package/dist/react/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { createLoomsStore, } from './store.js';
|
|
2
|
-
export {
|
|
2
|
+
export { defineLiveFold, foldLive, EventIndex, eventThreadKey, } from './derived.js';
|
|
3
3
|
export { materializeEvents } from './materialize.js';
|
|
4
4
|
export { emptyTables } from './tables.js';
|
|
5
|
-
export { LoomsProvider, useRunStore, useProjection, useRunSelector, useRunSummary, useRunEvents, useThreadTree, useEventCounts, useEventBySeq, useLatestEvent,
|
|
5
|
+
export { LoomsProvider, useRunStore, useProjection, useRunSelector, useRunSummary, useRunEvents, useThreadTree, useEventCounts, useEventBySeq, useLatestEvent, useLiveFold, } from './react.js';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { completedRunStatus, isJsonObject, isJsonString, } from '@swirls/looms/core';
|
|
1
|
+
import { completedRunStatus, isJsonObject, isJsonString, readAttributes, readRunLaunchSource, } from '@swirls/looms/core';
|
|
2
2
|
import { emptyTables } from './tables.js';
|
|
3
3
|
function payloadObject(event) {
|
|
4
4
|
return isJsonObject(event.payload) ? event.payload : {};
|
|
@@ -15,6 +15,8 @@ function setRunStatus(tables, runId, status) {
|
|
|
15
15
|
rootThreadId: existing?.rootThreadId ?? null,
|
|
16
16
|
kind: existing?.kind ?? null,
|
|
17
17
|
definitionName: existing?.definitionName ?? null,
|
|
18
|
+
launchedBy: existing?.launchedBy ?? null,
|
|
19
|
+
attributes: existing?.attributes ?? {},
|
|
18
20
|
});
|
|
19
21
|
}
|
|
20
22
|
export function materializeEvents(events, from = emptyTables()) {
|
|
@@ -34,6 +36,8 @@ export function materializeEvents(events, from = emptyTables()) {
|
|
|
34
36
|
rootThreadId,
|
|
35
37
|
kind: readString(payload, 'kind') ?? existing?.kind ?? null,
|
|
36
38
|
definitionName: readString(payload, 'definitionName') ?? existing?.definitionName ?? null,
|
|
39
|
+
launchedBy: readRunLaunchSource(payload.launchedBy) ?? existing?.launchedBy ?? null,
|
|
40
|
+
attributes: readAttributes(payload.attributes),
|
|
37
41
|
};
|
|
38
42
|
tables.runs.set(event.runId, next);
|
|
39
43
|
break;
|
package/dist/react/react.d.ts
CHANGED
|
@@ -1,23 +1,27 @@
|
|
|
1
1
|
import { type ReactNode } from 'react';
|
|
2
|
-
import { type ProjectionDefinition, type RunStatus, type ThreadTree } from '@swirls/looms/core';
|
|
3
|
-
import {
|
|
4
|
-
import type { AnyEventEnvelope, RegisteredEvent } from './register';
|
|
2
|
+
import { type AnyEventEnvelope, type ProjectionDefinition, type RegisteredEvent, type RunAttributes, type RunLaunchSource, type RunStatus, type SubscriptionTransport, type ThreadTree } from '@swirls/looms/core';
|
|
3
|
+
import { defineLiveFold, foldLive, type LiveFoldDefinition } from './derived';
|
|
5
4
|
import { createLoomsStore, type CoalesceOption, type LoomsClientStore, type LoomsConnectionStatus } from './store';
|
|
6
5
|
export interface LoomsProviderProps {
|
|
7
6
|
children: ReactNode;
|
|
8
7
|
endpoint?: string;
|
|
9
8
|
coalesce?: CoalesceOption;
|
|
9
|
+
transport?: SubscriptionTransport;
|
|
10
10
|
}
|
|
11
11
|
interface ProviderContextValue {
|
|
12
12
|
endpoint: string;
|
|
13
13
|
coalesce?: CoalesceOption;
|
|
14
|
+
transport?: SubscriptionTransport;
|
|
14
15
|
}
|
|
15
16
|
/** Root provider that supplies the Looms host endpoint to run stores. */
|
|
16
|
-
export declare function LoomsProvider({ children, endpoint, coalesce }: LoomsProviderProps): import("react").FunctionComponentElement<import("react").ProviderProps<ProviderContextValue>>;
|
|
17
|
+
export declare function LoomsProvider({ children, endpoint, coalesce, transport, }: LoomsProviderProps): import("react").FunctionComponentElement<import("react").ProviderProps<ProviderContextValue>>;
|
|
17
18
|
export interface UseRunStoreOptions {
|
|
18
19
|
endpoint?: string;
|
|
19
20
|
reconnectDelayMs?: number;
|
|
20
21
|
coalesce?: CoalesceOption;
|
|
22
|
+
transport?: SubscriptionTransport;
|
|
23
|
+
threadId?: string;
|
|
24
|
+
includeEphemeral?: boolean;
|
|
21
25
|
}
|
|
22
26
|
/**
|
|
23
27
|
* Acquires a non-subscribing handle to the run store.
|
|
@@ -39,6 +43,9 @@ export interface RunSummary {
|
|
|
39
43
|
readonly definitionName: string | undefined;
|
|
40
44
|
readonly rootThreadId: string | undefined;
|
|
41
45
|
readonly startedAt: number | undefined;
|
|
46
|
+
/** The effect in another run that launched this one. */
|
|
47
|
+
readonly launchedBy: RunLaunchSource | undefined;
|
|
48
|
+
readonly attributes: RunAttributes;
|
|
42
49
|
readonly connection: LoomsConnectionStatus;
|
|
43
50
|
}
|
|
44
51
|
/** Lightweight subscription to top-level run metadata and connection status. */
|
|
@@ -55,10 +62,10 @@ export declare function useEventCounts<TEvent extends AnyEventEnvelope = Registe
|
|
|
55
62
|
export declare function useEventBySeq<TEvent extends AnyEventEnvelope = RegisteredEvent>(store: LoomsClientStore<TEvent>, seq: number | undefined): TEvent | undefined;
|
|
56
63
|
/** Subscribe to the latest event of a given type. */
|
|
57
64
|
export declare function useLatestEvent<TEvent extends AnyEventEnvelope = RegisteredEvent>(store: LoomsClientStore<TEvent>, type: string): TEvent | undefined;
|
|
58
|
-
/** Subscribe to a
|
|
59
|
-
export declare function
|
|
65
|
+
/** Subscribe to a live fold, which includes ephemeral events. */
|
|
66
|
+
export declare function useLiveFold<S, TEvent extends AnyEventEnvelope = RegisteredEvent>(store: LoomsClientStore<TEvent>, fold: LiveFoldDefinition<S, TEvent>): S;
|
|
60
67
|
export { createLoomsStore };
|
|
61
|
-
export {
|
|
68
|
+
export { defineLiveFold, foldLive };
|
|
62
69
|
export type { LoomsClientStore, LoomsClientStoreOptions, LoomsConnectionStatus, LoomsStoreQuery, CoalesceOption, StoreListener, } from './store';
|
|
63
|
-
export type {
|
|
64
|
-
export type { LoomsRegister, RegisteredEvent, AnyEventEnvelope } from '
|
|
70
|
+
export type { LiveFoldDefinition } from './derived';
|
|
71
|
+
export type { LoomsRegister, RegisteredEvent, AnyEventEnvelope } from '@swirls/looms/core';
|
package/dist/react/react.js
CHANGED
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
import { Effect, Fiber } from 'effect';
|
|
2
2
|
import { createContext, createElement, useCallback, useContext, useEffect, useMemo, useRef, useSyncExternalStore, } from 'react';
|
|
3
|
-
import { isTerminalStatus, threadTree, toThreadTree, } from '@swirls/looms/core';
|
|
4
|
-
import {
|
|
3
|
+
import { isTerminalStatus, sameStringRecord, threadTree, toThreadTree, } from '@swirls/looms/core';
|
|
4
|
+
import { defineLiveFold, foldLive } from './derived.js';
|
|
5
5
|
import { createLoomsStore, } from './store.js';
|
|
6
6
|
const LoomsContext = createContext({ endpoint: '' });
|
|
7
7
|
const GRACE_MS = 5_000;
|
|
8
8
|
const registry = new Map();
|
|
9
|
-
function registryKey(
|
|
10
|
-
return
|
|
9
|
+
function registryKey(runId, identity) {
|
|
10
|
+
return [
|
|
11
|
+
identity.endpoint,
|
|
12
|
+
runId,
|
|
13
|
+
identity.transport ?? '',
|
|
14
|
+
identity.threadId ?? '',
|
|
15
|
+
identity.includeEphemeral === false ? '0' : '1',
|
|
16
|
+
].join('\0');
|
|
11
17
|
}
|
|
12
18
|
function disposeEntry(key) {
|
|
13
19
|
const entry = registry.get(key);
|
|
@@ -20,17 +26,20 @@ function disposeEntry(key) {
|
|
|
20
26
|
function scheduleDisposal(key) {
|
|
21
27
|
return Effect.runFork(Effect.sleep(GRACE_MS).pipe(Effect.andThen(Effect.sync(() => disposeEntry(key)))));
|
|
22
28
|
}
|
|
23
|
-
function peekStore(runId,
|
|
24
|
-
const key = registryKey(
|
|
29
|
+
function peekStore(runId, identity) {
|
|
30
|
+
const key = registryKey(runId, identity);
|
|
25
31
|
const existing = registry.get(key);
|
|
26
32
|
if (existing) {
|
|
27
33
|
return existing.store;
|
|
28
34
|
}
|
|
29
35
|
const store = createLoomsStore({
|
|
30
36
|
storeId: runId,
|
|
31
|
-
endpoint,
|
|
32
|
-
reconnectDelayMs,
|
|
33
|
-
coalesce,
|
|
37
|
+
endpoint: identity.endpoint,
|
|
38
|
+
reconnectDelayMs: identity.reconnectDelayMs,
|
|
39
|
+
coalesce: identity.coalesce,
|
|
40
|
+
transport: identity.transport,
|
|
41
|
+
threadId: identity.threadId,
|
|
42
|
+
includeEphemeral: identity.includeEphemeral,
|
|
34
43
|
});
|
|
35
44
|
registry.set(key, {
|
|
36
45
|
store,
|
|
@@ -39,9 +48,9 @@ function peekStore(runId, endpoint, reconnectDelayMs, coalesce) {
|
|
|
39
48
|
});
|
|
40
49
|
return store;
|
|
41
50
|
}
|
|
42
|
-
function retainStore(runId,
|
|
43
|
-
const key = registryKey(
|
|
44
|
-
peekStore(runId,
|
|
51
|
+
function retainStore(runId, identity) {
|
|
52
|
+
const key = registryKey(runId, identity);
|
|
53
|
+
peekStore(runId, identity);
|
|
45
54
|
const entry = registry.get(key);
|
|
46
55
|
if (!entry) {
|
|
47
56
|
return;
|
|
@@ -52,8 +61,8 @@ function retainStore(runId, endpoint, reconnectDelayMs, coalesce) {
|
|
|
52
61
|
entry.disposal = undefined;
|
|
53
62
|
}
|
|
54
63
|
}
|
|
55
|
-
function releaseStore(runId,
|
|
56
|
-
const key = registryKey(
|
|
64
|
+
function releaseStore(runId, identity) {
|
|
65
|
+
const key = registryKey(runId, identity);
|
|
57
66
|
const entry = registry.get(key);
|
|
58
67
|
if (!entry) {
|
|
59
68
|
return;
|
|
@@ -64,8 +73,8 @@ function releaseStore(runId, endpoint) {
|
|
|
64
73
|
}
|
|
65
74
|
}
|
|
66
75
|
/** Root provider that supplies the Looms host endpoint to run stores. */
|
|
67
|
-
export function LoomsProvider({ children, endpoint = '', coalesce }) {
|
|
68
|
-
const value = useMemo(() => ({ endpoint, coalesce }), [endpoint, coalesce]);
|
|
76
|
+
export function LoomsProvider({ children, endpoint = '', coalesce, transport, }) {
|
|
77
|
+
const value = useMemo(() => ({ endpoint, coalesce, transport }), [endpoint, coalesce, transport]);
|
|
69
78
|
return createElement(LoomsContext.Provider, { value, children });
|
|
70
79
|
}
|
|
71
80
|
/**
|
|
@@ -78,11 +87,22 @@ export function useRunStore(runId, options) {
|
|
|
78
87
|
const endpoint = options?.endpoint ?? context.endpoint;
|
|
79
88
|
const reconnectDelayMs = options?.reconnectDelayMs;
|
|
80
89
|
const coalesce = options?.coalesce ?? context.coalesce;
|
|
81
|
-
const
|
|
90
|
+
const transport = options?.transport ?? context.transport;
|
|
91
|
+
const threadId = options?.threadId;
|
|
92
|
+
const includeEphemeral = options?.includeEphemeral;
|
|
93
|
+
const identity = {
|
|
94
|
+
endpoint,
|
|
95
|
+
reconnectDelayMs,
|
|
96
|
+
coalesce,
|
|
97
|
+
transport,
|
|
98
|
+
threadId,
|
|
99
|
+
includeEphemeral,
|
|
100
|
+
};
|
|
101
|
+
const store = peekStore(runId, identity);
|
|
82
102
|
useEffect(() => {
|
|
83
|
-
retainStore(runId,
|
|
84
|
-
return () => releaseStore(runId,
|
|
85
|
-
}, [runId, endpoint, reconnectDelayMs, coalesce]);
|
|
103
|
+
retainStore(runId, identity);
|
|
104
|
+
return () => releaseStore(runId, identity);
|
|
105
|
+
}, [runId, endpoint, reconnectDelayMs, coalesce, transport, threadId, includeEphemeral]);
|
|
86
106
|
return store;
|
|
87
107
|
}
|
|
88
108
|
function useStoreSnapshot(store, getSnapshot) {
|
|
@@ -119,6 +139,8 @@ function shallowEqualSummary(a, b) {
|
|
|
119
139
|
a.definitionName === b.definitionName &&
|
|
120
140
|
a.rootThreadId === b.rootThreadId &&
|
|
121
141
|
a.startedAt === b.startedAt &&
|
|
142
|
+
a.launchedBy === b.launchedBy &&
|
|
143
|
+
sameStringRecord(a.attributes, b.attributes) &&
|
|
122
144
|
a.connection === b.connection);
|
|
123
145
|
}
|
|
124
146
|
/** Lightweight subscription to top-level run metadata and connection status. */
|
|
@@ -134,6 +156,8 @@ export function useRunSummary(store) {
|
|
|
134
156
|
definitionName: run?.definitionName ?? undefined,
|
|
135
157
|
rootThreadId: run?.rootThreadId ?? undefined,
|
|
136
158
|
startedAt: s.query.startedAt(),
|
|
159
|
+
launchedBy: run?.launchedBy ?? undefined,
|
|
160
|
+
attributes: run?.attributes ?? {},
|
|
137
161
|
connection: s.status(),
|
|
138
162
|
};
|
|
139
163
|
}, []);
|
|
@@ -165,10 +189,10 @@ export function useLatestEvent(store, type) {
|
|
|
165
189
|
const selector = useCallback((s) => s.query.latest(type), [type]);
|
|
166
190
|
return useRunSelector(store, selector);
|
|
167
191
|
}
|
|
168
|
-
/** Subscribe to a
|
|
169
|
-
export function
|
|
192
|
+
/** Subscribe to a live fold, which includes ephemeral events. */
|
|
193
|
+
export function useLiveFold(store, fold) {
|
|
170
194
|
const getSnapshot = useCallback(() => store.fold(fold), [store, fold]);
|
|
171
195
|
return useStoreSnapshot(store, getSnapshot);
|
|
172
196
|
}
|
|
173
197
|
export { createLoomsStore };
|
|
174
|
-
export {
|
|
198
|
+
export { defineLiveFold, foldLive };
|
package/dist/react/store.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { type
|
|
1
|
+
import type { SubscriptionSocketConstructor } from '@swirls/looms/client';
|
|
2
|
+
import { type AnyEventEnvelope, type EventInput, type ProjectionDefinition, type RegisteredEvent, type SubscriptionTransport } from '@swirls/looms/core';
|
|
3
|
+
import { type LiveFoldDefinition } from './derived';
|
|
3
4
|
import { type CoalesceOption } from './notify';
|
|
4
|
-
import type { AnyEventEnvelope, RegisteredEvent } from './register';
|
|
5
5
|
import { type MaterializedTables } from './tables';
|
|
6
6
|
export type { CoalesceOption } from './notify';
|
|
7
7
|
/** Fired after the store version bumps. Re-read via `events()` / `getState()` / `query`. */
|
|
@@ -15,10 +15,18 @@ export interface LoomsClientStoreOptions {
|
|
|
15
15
|
* Opens `${endpoint}/runs/:id/events?live=true` as an SSE stream.
|
|
16
16
|
*/
|
|
17
17
|
endpoint: string;
|
|
18
|
-
/** Backoff between SSE
|
|
18
|
+
/** Backoff between reconnects. The delay stays fixed, matching the SSE client. */
|
|
19
19
|
reconnectDelayMs?: number;
|
|
20
20
|
fetch?: typeof fetch;
|
|
21
21
|
coalesce?: CoalesceOption;
|
|
22
|
+
/**
|
|
23
|
+
* `undefined` keeps the current SSE path. `websocket` and `auto` use a hibernating
|
|
24
|
+
* socket when a constructor is available.
|
|
25
|
+
*/
|
|
26
|
+
transport?: SubscriptionTransport;
|
|
27
|
+
threadId?: string;
|
|
28
|
+
includeEphemeral?: boolean;
|
|
29
|
+
webSocket?: SubscriptionSocketConstructor;
|
|
22
30
|
}
|
|
23
31
|
export interface LoomsStoreQuery<TEvent extends AnyEventEnvelope = RegisteredEvent> {
|
|
24
32
|
events: (options?: {
|
|
@@ -30,7 +38,7 @@ export interface LoomsStoreQuery<TEvent extends AnyEventEnvelope = RegisteredEve
|
|
|
30
38
|
bySeq: (seq: number) => TEvent | undefined;
|
|
31
39
|
startedAt: () => number | undefined;
|
|
32
40
|
latest: (type: string) => TEvent | undefined;
|
|
33
|
-
fold: <S>(def:
|
|
41
|
+
fold: <S>(def: LiveFoldDefinition<S, TEvent>) => S;
|
|
34
42
|
}
|
|
35
43
|
export interface LoomsClientStore<TEvent extends AnyEventEnvelope = RegisteredEvent> {
|
|
36
44
|
storeId: string;
|
|
@@ -43,7 +51,7 @@ export interface LoomsClientStore<TEvent extends AnyEventEnvelope = RegisteredEv
|
|
|
43
51
|
query: LoomsStoreQuery<TEvent>;
|
|
44
52
|
subscribe: (listener: StoreListener) => () => void;
|
|
45
53
|
project<S>(definition: ProjectionDefinition<S>): S;
|
|
46
|
-
fold<S>(definition:
|
|
54
|
+
fold<S>(definition: LiveFoldDefinition<S, TEvent>): S;
|
|
47
55
|
flush: () => void;
|
|
48
56
|
commit: (event: EventInput | readonly EventInput[]) => Promise<void>;
|
|
49
57
|
sync: () => Promise<void>;
|