@listen-fire/engine-contracts 0.12.1 → 0.12.3

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.
@@ -87,10 +87,15 @@ export interface InstanceIdentityDescriptor {
87
87
  constructionConfig?: Record<string, string>;
88
88
  }
89
89
  /** The serialised `SourceRead` — just the instance identity behind it. The live
90
- * `adapter` + the `edgeFieldId` closure are rebound from `instanceName` on
91
- * rehydrate. */
90
+ * `adapter` + the `edgeFieldId` closure are rebound on rehydrate: from
91
+ * `instance` when the park carries it, else from `instanceName` in the root
92
+ * program's scope (a park written before `instance`). */
92
93
  export interface SourceReadDescriptor {
93
94
  instanceName: string;
95
+ /** The system the record was read from (the Rust engine writes it): a
96
+ * record a library returned names a connection the root program's scope
97
+ * does not hold. */
98
+ instance?: InstanceIdentityDescriptor;
94
99
  }
95
100
  /** A serialised `ExtractEmission` — its `children` Map flattened to a record of
96
101
  * arrays (JSON has no Map). The emission is pure data (the extraction ran). */
@@ -1,5 +1,5 @@
1
1
  import { z } from 'zod';
2
- export declare const MOVEMENTS_METHODS: readonly ["movements.list", "movements.read", "movements.write"];
2
+ export declare const MOVEMENTS_METHODS: readonly ["movements.list", "movements.read", "movements.write", "movements.watch"];
3
3
  /** A file's path under the movements folder: `/`-separated, ending `.mvt`,
4
4
  * no segment empty, `.` or `..`, and no `\` (`orders/sync.mvt`). */
5
5
  export declare const MovementPath: z.ZodString;
@@ -39,3 +39,39 @@ export declare const MovementsWriteAnswer: z.ZodDiscriminatedUnion<[z.ZodObject<
39
39
  reason: z.ZodString;
40
40
  }, z.core.$strip>], "kind">;
41
41
  export type MovementsWriteAnswerShape = z.infer<typeof MovementsWriteAnswer>;
42
+ /** One change `movements.watch` reports. `version` is the one `read` answers; a module that can change its files gives it on `added` and `changed`. */
43
+ export declare const MovementsChange: z.ZodDiscriminatedUnion<[z.ZodObject<{
44
+ kind: z.ZodLiteral<"added">;
45
+ path: z.ZodString;
46
+ version: z.ZodOptional<z.ZodString>;
47
+ }, z.core.$strip>, z.ZodObject<{
48
+ kind: z.ZodLiteral<"changed">;
49
+ path: z.ZodString;
50
+ version: z.ZodOptional<z.ZodString>;
51
+ }, z.core.$strip>, z.ZodObject<{
52
+ kind: z.ZodLiteral<"removed">;
53
+ path: z.ZodString;
54
+ }, z.core.$strip>], "kind">;
55
+ export type MovementsChangeShape = z.infer<typeof MovementsChange>;
56
+ export declare const MovementsWatchRequest: z.ZodObject<{
57
+ cursor: z.ZodOptional<z.ZodString>;
58
+ waitMs: z.ZodNumber;
59
+ }, z.core.$strip>;
60
+ export declare const MovementsWatchAnswer: z.ZodUnion<readonly [z.ZodObject<{
61
+ cursor: z.ZodString;
62
+ events: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
63
+ kind: z.ZodLiteral<"added">;
64
+ path: z.ZodString;
65
+ version: z.ZodOptional<z.ZodString>;
66
+ }, z.core.$strip>, z.ZodObject<{
67
+ kind: z.ZodLiteral<"changed">;
68
+ path: z.ZodString;
69
+ version: z.ZodOptional<z.ZodString>;
70
+ }, z.core.$strip>, z.ZodObject<{
71
+ kind: z.ZodLiteral<"removed">;
72
+ path: z.ZodString;
73
+ }, z.core.$strip>], "kind">>;
74
+ }, z.core.$strip>, z.ZodObject<{
75
+ resync: z.ZodLiteral<true>;
76
+ }, z.core.$strip>]>;
77
+ export type MovementsWatchAnswerShape = z.infer<typeof MovementsWatchAnswer>;
@@ -4,10 +4,11 @@
4
4
  // the movements folder, reads one, and writes one by compare-and-swap on its
5
5
  // version. `lf.yaml` and the externals folder stay local files.
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.MovementsWriteAnswer = exports.MovementsWriteRequest = exports.MovementsReadRequest = exports.MovementsReadAnswer = exports.MovementsListAnswer = exports.MovementsListed = exports.MovementPath = exports.MOVEMENTS_METHODS = void 0;
7
+ exports.MovementsWatchAnswer = exports.MovementsWatchRequest = exports.MovementsChange = exports.MovementsWriteAnswer = exports.MovementsWriteRequest = exports.MovementsReadRequest = exports.MovementsReadAnswer = exports.MovementsListAnswer = exports.MovementsListed = exports.MovementPath = exports.MOVEMENTS_METHODS = void 0;
8
8
  exports.isMovementPath = isMovementPath;
9
9
  const zod_1 = require("zod");
10
- exports.MOVEMENTS_METHODS = ['movements.list', 'movements.read', 'movements.write'];
10
+ const wire_1 = require("./wire");
11
+ exports.MOVEMENTS_METHODS = ['movements.list', 'movements.read', 'movements.write', 'movements.watch'];
11
12
  /** A file's path under the movements folder: `/`-separated, ending `.mvt`,
12
13
  * no segment empty, `.` or `..`, and no `\` (`orders/sync.mvt`). */
13
14
  exports.MovementPath = zod_1.z.string().refine(isMovementPath, 'a movement path: relative to the movements folder, `/`-separated, ending .mvt');
@@ -36,3 +37,11 @@ exports.MovementsWriteAnswer = zod_1.z.discriminatedUnion('kind', [
36
37
  /** The module keeps the project's movements where `lf` cannot change them. */
37
38
  zod_1.z.object({ kind: zod_1.z.literal('read_only'), reason: zod_1.z.string().min(1) }),
38
39
  ]);
40
+ /** One change `movements.watch` reports. `version` is the one `read` answers; a module that can change its files gives it on `added` and `changed`. */
41
+ exports.MovementsChange = zod_1.z.discriminatedUnion('kind', [
42
+ zod_1.z.object({ kind: zod_1.z.literal('added'), path: exports.MovementPath, version: Version.optional() }),
43
+ zod_1.z.object({ kind: zod_1.z.literal('changed'), path: exports.MovementPath, version: Version.optional() }),
44
+ zod_1.z.object({ kind: zod_1.z.literal('removed'), path: exports.MovementPath }),
45
+ ]);
46
+ exports.MovementsWatchRequest = wire_1.WatchRequest;
47
+ exports.MovementsWatchAnswer = (0, wire_1.watchAnswer)(exports.MovementsChange);
@@ -47,3 +47,33 @@ export declare const WireSlotManifest: z.ZodObject<{
47
47
  export type WireSlotManifestShape = z.infer<typeof WireSlotManifest>;
48
48
  /** The error code a store answers when a fenced write finds the run's lease gone. */
49
49
  export declare const RUN_LEASE_LOST_CODE = "run_lease_lost";
50
+ /** The most a module must hold a `<slot>.watch` request: lf asks for at most
51
+ * this, and a module honours at most this whatever `waitMs` says. */
52
+ export declare const WATCH_WAIT_CAP_MS = 30000;
53
+ /**
54
+ * The generic change feed any slot may adopt (`<slot>.watch`, the adapter
55
+ * protocol's "Watching for changes"). The caller holds a cursor and asks for
56
+ * what happened after it; the module holds the request up to `waitMs`, then
57
+ * answers.
58
+ *
59
+ * - An absent cursor answers the module's current cursor and no events.
60
+ * - `waitMs` is a non-negative integer; a module honours at most
61
+ * `WATCH_WAIT_CAP_MS` and may answer sooner, at once with `events: []`.
62
+ * - A cursor the module never gave, or can no longer serve, answers
63
+ * `{ resync: true }`: the caller lists afresh and asks without a cursor.
64
+ * - Events from one cursor are in order, and a cursor a module has answered is
65
+ * never answered again with fewer events.
66
+ * - Cursors are positions in the module's log, not per caller: every caller
67
+ * holding a cursor sees every event after it.
68
+ */
69
+ export declare const WatchRequest: z.ZodObject<{
70
+ cursor: z.ZodOptional<z.ZodString>;
71
+ waitMs: z.ZodNumber;
72
+ }, z.core.$strip>;
73
+ export type WatchRequestShape = z.infer<typeof WatchRequest>;
74
+ export declare function watchAnswer<E extends z.ZodType>(event: E): z.ZodUnion<readonly [z.ZodObject<{
75
+ cursor: z.ZodString;
76
+ events: z.ZodArray<E>;
77
+ }, z.core.$strip>, z.ZodObject<{
78
+ resync: z.ZodLiteral<true>;
79
+ }, z.core.$strip>]>;
@@ -13,7 +13,8 @@
13
13
  // The shapes only: a Node client, server and starter are module-runtime's
14
14
  // `module-wire`.
15
15
  Object.defineProperty(exports, "__esModule", { value: true });
16
- exports.RUN_LEASE_LOST_CODE = exports.WireSlotManifest = exports.SlotAnswerEnvelope = exports.SlotError = exports.SlotRequestEnvelope = void 0;
16
+ exports.WatchRequest = exports.WATCH_WAIT_CAP_MS = exports.RUN_LEASE_LOST_CODE = exports.WireSlotManifest = exports.SlotAnswerEnvelope = exports.SlotError = exports.SlotRequestEnvelope = void 0;
17
+ exports.watchAnswer = watchAnswer;
17
18
  const zod_1 = require("zod");
18
19
  const protocol_1 = require("../protocol");
19
20
  exports.SlotRequestEnvelope = zod_1.z.object({
@@ -44,3 +45,26 @@ exports.WireSlotManifest = zod_1.z.object({
44
45
  });
45
46
  /** The error code a store answers when a fenced write finds the run's lease gone. */
46
47
  exports.RUN_LEASE_LOST_CODE = 'run_lease_lost';
48
+ /** The most a module must hold a `<slot>.watch` request: lf asks for at most
49
+ * this, and a module honours at most this whatever `waitMs` says. */
50
+ exports.WATCH_WAIT_CAP_MS = 30_000;
51
+ /**
52
+ * The generic change feed any slot may adopt (`<slot>.watch`, the adapter
53
+ * protocol's "Watching for changes"). The caller holds a cursor and asks for
54
+ * what happened after it; the module holds the request up to `waitMs`, then
55
+ * answers.
56
+ *
57
+ * - An absent cursor answers the module's current cursor and no events.
58
+ * - `waitMs` is a non-negative integer; a module honours at most
59
+ * `WATCH_WAIT_CAP_MS` and may answer sooner, at once with `events: []`.
60
+ * - A cursor the module never gave, or can no longer serve, answers
61
+ * `{ resync: true }`: the caller lists afresh and asks without a cursor.
62
+ * - Events from one cursor are in order, and a cursor a module has answered is
63
+ * never answered again with fewer events.
64
+ * - Cursors are positions in the module's log, not per caller: every caller
65
+ * holding a cursor sees every event after it.
66
+ */
67
+ exports.WatchRequest = zod_1.z.object({ cursor: zod_1.z.string().min(1).optional(), waitMs: zod_1.z.number().int().min(0) });
68
+ function watchAnswer(event) {
69
+ return zod_1.z.union([zod_1.z.object({ cursor: zod_1.z.string().min(1), events: zod_1.z.array(event) }), zod_1.z.object({ resync: zod_1.z.literal(true) })]);
70
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@listen-fire/engine-contracts",
3
3
  "license": "Apache-2.0",
4
- "version": "0.12.1",
4
+ "version": "0.12.3",
5
5
  "description": "The contracts the movement engine speaks: the tenant id, the host families and entry-point inputs, the parked state, file descriptors, the adapter protocol, the adapter contract and its manifest, the catalog's schema types and positions, the Expression vocabulary, plugins as data and the model names. Runtime-neutral: no Node import, no ambient types.",
6
6
  "engines": {
7
7
  "node": ">=22.23.4 <23"
@@ -30,7 +30,7 @@
30
30
  "type": "commonjs",
31
31
  "dependencies": {
32
32
  "zod": "4.1.12",
33
- "@listen-fire/movement-lang": "^0.12.1"
33
+ "@listen-fire/movement-lang": "^0.12.3"
34
34
  },
35
35
  "devDependencies": {
36
36
  "@types/node": "20.16.5",