@bluewombat/manager-fake 0.1.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/README.md +58 -0
- package/SPECS.md +65 -0
- package/dist/adapter/fetch/run-fetch.d.ts +24 -0
- package/dist/adapter/fetch/run-fetch.d.ts.map +1 -0
- package/dist/adapter/fetch/run-fetch.js +119 -0
- package/dist/adapter/fetch/run-fetch.js.map +1 -0
- package/dist/adapter/normalize/fingerprint.d.ts +8 -0
- package/dist/adapter/normalize/fingerprint.d.ts.map +1 -0
- package/dist/adapter/normalize/fingerprint.js +26 -0
- package/dist/adapter/normalize/fingerprint.js.map +1 -0
- package/dist/adapter/normalize/normalize.d.ts +17 -0
- package/dist/adapter/normalize/normalize.d.ts.map +1 -0
- package/dist/adapter/normalize/normalize.js +199 -0
- package/dist/adapter/normalize/normalize.js.map +1 -0
- package/dist/adapter/progress/emit.d.ts +3 -0
- package/dist/adapter/progress/emit.d.ts.map +1 -0
- package/dist/adapter/progress/emit.js +6 -0
- package/dist/adapter/progress/emit.js.map +1 -0
- package/dist/adapter/raw/parse-raw.d.ts +14 -0
- package/dist/adapter/raw/parse-raw.d.ts.map +1 -0
- package/dist/adapter/raw/parse-raw.js +47 -0
- package/dist/adapter/raw/parse-raw.js.map +1 -0
- package/dist/adapter/run/run-adapter.d.ts +25 -0
- package/dist/adapter/run/run-adapter.d.ts.map +1 -0
- package/dist/adapter/run/run-adapter.js +125 -0
- package/dist/adapter/run/run-adapter.js.map +1 -0
- package/dist/adapter/types.d.ts +51 -0
- package/dist/adapter/types.d.ts.map +1 -0
- package/dist/adapter/types.js +3 -0
- package/dist/adapter/types.js.map +1 -0
- package/dist/emitter/event/field-matrix.d.ts +29 -0
- package/dist/emitter/event/field-matrix.d.ts.map +1 -0
- package/dist/emitter/event/field-matrix.js +93 -0
- package/dist/emitter/event/field-matrix.js.map +1 -0
- package/dist/emitter/progress/emit.d.ts +3 -0
- package/dist/emitter/progress/emit.d.ts.map +1 -0
- package/dist/emitter/progress/emit.js +6 -0
- package/dist/emitter/progress/emit.js.map +1 -0
- package/dist/emitter/render/render-event.d.ts +14 -0
- package/dist/emitter/render/render-event.d.ts.map +1 -0
- package/dist/emitter/render/render-event.js +116 -0
- package/dist/emitter/render/render-event.js.map +1 -0
- package/dist/emitter/render/truncate.d.ts +9 -0
- package/dist/emitter/render/truncate.d.ts.map +1 -0
- package/dist/emitter/render/truncate.js +10 -0
- package/dist/emitter/render/truncate.js.map +1 -0
- package/dist/emitter/run/run-emitter.d.ts +21 -0
- package/dist/emitter/run/run-emitter.d.ts.map +1 -0
- package/dist/emitter/run/run-emitter.js +89 -0
- package/dist/emitter/run/run-emitter.js.map +1 -0
- package/dist/emitter/thread/slug.d.ts +7 -0
- package/dist/emitter/thread/slug.d.ts.map +1 -0
- package/dist/emitter/thread/slug.js +18 -0
- package/dist/emitter/thread/slug.js.map +1 -0
- package/dist/emitter/thread/thread.d.ts +32 -0
- package/dist/emitter/thread/thread.d.ts.map +1 -0
- package/dist/emitter/thread/thread.js +58 -0
- package/dist/emitter/thread/thread.js.map +1 -0
- package/dist/emitter/types.d.ts +45 -0
- package/dist/emitter/types.d.ts.map +1 -0
- package/dist/emitter/types.js +3 -0
- package/dist/emitter/types.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +98 -0
- package/dist/index.js.map +1 -0
- package/dist/listener/delivery/run-hook.d.ts +8 -0
- package/dist/listener/delivery/run-hook.d.ts.map +1 -0
- package/dist/listener/delivery/run-hook.js +50 -0
- package/dist/listener/delivery/run-hook.js.map +1 -0
- package/dist/listener/progress/emit.d.ts +3 -0
- package/dist/listener/progress/emit.d.ts.map +1 -0
- package/dist/listener/progress/emit.js +6 -0
- package/dist/listener/progress/emit.js.map +1 -0
- package/dist/listener/run/run-listener.d.ts +31 -0
- package/dist/listener/run/run-listener.d.ts.map +1 -0
- package/dist/listener/run/run-listener.js +173 -0
- package/dist/listener/run/run-listener.js.map +1 -0
- package/dist/listener/source/list-source.d.ts +13 -0
- package/dist/listener/source/list-source.d.ts.map +1 -0
- package/dist/listener/source/list-source.js +35 -0
- package/dist/listener/source/list-source.js.map +1 -0
- package/dist/listener/source/read-event.d.ts +7 -0
- package/dist/listener/source/read-event.d.ts.map +1 -0
- package/dist/listener/source/read-event.js +47 -0
- package/dist/listener/source/read-event.js.map +1 -0
- package/dist/listener/source/select-events.d.ts +13 -0
- package/dist/listener/source/select-events.d.ts.map +1 -0
- package/dist/listener/source/select-events.js +23 -0
- package/dist/listener/source/select-events.js.map +1 -0
- package/dist/listener/types.d.ts +42 -0
- package/dist/listener/types.d.ts.map +1 -0
- package/dist/listener/types.js +3 -0
- package/dist/listener/types.js.map +1 -0
- package/dist/manager.d.ts +17 -0
- package/dist/manager.d.ts.map +1 -0
- package/dist/manager.js +114 -0
- package/dist/manager.js.map +1 -0
- package/package.json +47 -0
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { runHook } from "../delivery/run-hook.js";
|
|
2
|
+
import { listSource } from "../source/list-source.js";
|
|
3
|
+
import { readEvent } from "../source/read-event.js";
|
|
4
|
+
import { selectEvents } from "../source/select-events.js";
|
|
5
|
+
function exitCodeFor(outcome) {
|
|
6
|
+
switch (outcome) {
|
|
7
|
+
case "completed":
|
|
8
|
+
return 0;
|
|
9
|
+
case "source-lost":
|
|
10
|
+
return 1;
|
|
11
|
+
case "invalid-invocation":
|
|
12
|
+
return 2;
|
|
13
|
+
case "interrupted":
|
|
14
|
+
return 130;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
export function invalidInvocationResult(write, reason) {
|
|
18
|
+
write({
|
|
19
|
+
event: "run-finished",
|
|
20
|
+
outcome: "invalid-invocation",
|
|
21
|
+
delivered: 0,
|
|
22
|
+
skipped: 0,
|
|
23
|
+
scans: 0,
|
|
24
|
+
detail: reason,
|
|
25
|
+
});
|
|
26
|
+
return {
|
|
27
|
+
outcome: "invalid-invocation",
|
|
28
|
+
delivered: 0,
|
|
29
|
+
skipped: 0,
|
|
30
|
+
scans: 0,
|
|
31
|
+
exitCode: exitCodeFor("invalid-invocation"),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
/** Sleep that gives up early on a stop signal or on the duration clock. */
|
|
35
|
+
async function waitPoll(input) {
|
|
36
|
+
const until = input.now() + input.ms;
|
|
37
|
+
while (input.now() < until) {
|
|
38
|
+
if (input.shouldInterrupt() || input.now() >= input.deadlineMs) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const slice = Math.min(20, until - input.now());
|
|
42
|
+
await new Promise((resolve) => setTimeout(resolve, Math.max(1, slice)));
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Run one FeatureListener invocation to a run outcome.
|
|
47
|
+
*/
|
|
48
|
+
export async function runListener(options) {
|
|
49
|
+
const { invocation } = options;
|
|
50
|
+
const write = options.write ?? (() => { });
|
|
51
|
+
const now = options.now ?? (() => Date.now());
|
|
52
|
+
const interruptState = options.interruptFlag ?? { interrupted: false };
|
|
53
|
+
const shouldInterrupt = () => interruptState.interrupted;
|
|
54
|
+
return await runLoop({ invocation, write, now, shouldInterrupt, cwd: options.cwd });
|
|
55
|
+
}
|
|
56
|
+
async function runLoop(input) {
|
|
57
|
+
const { invocation, write, now, shouldInterrupt } = input;
|
|
58
|
+
const deadlineMs = now() + invocation.durationMs;
|
|
59
|
+
let cursor = invocation.since;
|
|
60
|
+
let delivered = 0;
|
|
61
|
+
let skipped = 0;
|
|
62
|
+
let scans = 0;
|
|
63
|
+
const finish = (outcome, stopReason, detail) => {
|
|
64
|
+
const line = {
|
|
65
|
+
event: "run-finished",
|
|
66
|
+
manager: invocation.manager,
|
|
67
|
+
outcome,
|
|
68
|
+
stop_reason: stopReason,
|
|
69
|
+
delivered,
|
|
70
|
+
skipped,
|
|
71
|
+
scans,
|
|
72
|
+
};
|
|
73
|
+
if (cursor !== undefined) {
|
|
74
|
+
line.cursor = cursor;
|
|
75
|
+
}
|
|
76
|
+
if (detail !== undefined) {
|
|
77
|
+
line.detail = detail;
|
|
78
|
+
}
|
|
79
|
+
write(line);
|
|
80
|
+
const result = {
|
|
81
|
+
outcome,
|
|
82
|
+
stopReason,
|
|
83
|
+
delivered,
|
|
84
|
+
skipped,
|
|
85
|
+
scans,
|
|
86
|
+
exitCode: exitCodeFor(outcome),
|
|
87
|
+
};
|
|
88
|
+
if (cursor !== undefined) {
|
|
89
|
+
result.cursor = cursor;
|
|
90
|
+
}
|
|
91
|
+
return result;
|
|
92
|
+
};
|
|
93
|
+
// Consumed Events, delivered or skipped: both cost a read and both burn a Cursor.
|
|
94
|
+
const consumed = () => delivered + skipped;
|
|
95
|
+
for (;;) {
|
|
96
|
+
if (shouldInterrupt()) {
|
|
97
|
+
return finish("interrupted", "signal");
|
|
98
|
+
}
|
|
99
|
+
if (now() >= deadlineMs) {
|
|
100
|
+
return finish("completed", "duration");
|
|
101
|
+
}
|
|
102
|
+
const listed = listSource(invocation.source);
|
|
103
|
+
if (!listed.ok) {
|
|
104
|
+
return finish("source-lost", "source-lost", listed.detail);
|
|
105
|
+
}
|
|
106
|
+
const pending = selectEvents(listed.names, cursor);
|
|
107
|
+
scans += 1;
|
|
108
|
+
write({
|
|
109
|
+
event: "scan",
|
|
110
|
+
manager: invocation.manager,
|
|
111
|
+
pending: pending.length,
|
|
112
|
+
});
|
|
113
|
+
for (const name of pending) {
|
|
114
|
+
if (shouldInterrupt()) {
|
|
115
|
+
return finish("interrupted", "signal");
|
|
116
|
+
}
|
|
117
|
+
if (consumed() >= invocation.maxEvents) {
|
|
118
|
+
return finish("completed", "max-events");
|
|
119
|
+
}
|
|
120
|
+
if (now() >= deadlineMs) {
|
|
121
|
+
return finish("completed", "duration");
|
|
122
|
+
}
|
|
123
|
+
const read = readEvent(invocation.source, name);
|
|
124
|
+
if (read.ok) {
|
|
125
|
+
write({
|
|
126
|
+
event: "intention",
|
|
127
|
+
manager: invocation.manager,
|
|
128
|
+
cursor: name,
|
|
129
|
+
observed_at: new Date(now()).toISOString(),
|
|
130
|
+
bytes: read.bytes,
|
|
131
|
+
payload: read.payload,
|
|
132
|
+
});
|
|
133
|
+
// Commit only once the Delivery is on stdout: at-least-once, never at-most-once.
|
|
134
|
+
cursor = name;
|
|
135
|
+
delivered += 1;
|
|
136
|
+
if (invocation.onIntentionArgv !== undefined) {
|
|
137
|
+
await runHook([
|
|
138
|
+
...invocation.onIntentionArgv,
|
|
139
|
+
"--manager",
|
|
140
|
+
invocation.manager,
|
|
141
|
+
"--cursor",
|
|
142
|
+
name,
|
|
143
|
+
"--payload",
|
|
144
|
+
JSON.stringify(read.payload),
|
|
145
|
+
], input.cwd);
|
|
146
|
+
}
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
write({
|
|
150
|
+
event: "skipped",
|
|
151
|
+
manager: invocation.manager,
|
|
152
|
+
cursor: name,
|
|
153
|
+
reason: read.reason,
|
|
154
|
+
detail: read.detail,
|
|
155
|
+
});
|
|
156
|
+
cursor = name;
|
|
157
|
+
skipped += 1;
|
|
158
|
+
}
|
|
159
|
+
if (consumed() >= invocation.maxEvents) {
|
|
160
|
+
return finish("completed", "max-events");
|
|
161
|
+
}
|
|
162
|
+
if (!invocation.follow) {
|
|
163
|
+
return finish("completed", "drained");
|
|
164
|
+
}
|
|
165
|
+
await waitPoll({
|
|
166
|
+
ms: invocation.pollIntervalMs ?? 1,
|
|
167
|
+
now,
|
|
168
|
+
deadlineMs,
|
|
169
|
+
shouldInterrupt,
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
//# sourceMappingURL=run-listener.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-listener.js","sourceRoot":"","sources":["../../../src/listener/run/run-listener.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export type ListResult = {
|
|
2
|
+
ok: true;
|
|
3
|
+
names: string[];
|
|
4
|
+
} | {
|
|
5
|
+
ok: false;
|
|
6
|
+
detail: string;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Names of regular files directly under the Source. Sub-directories, and
|
|
10
|
+
* symlinks that do not resolve to a file, are not Events.
|
|
11
|
+
*/
|
|
12
|
+
export declare function listSource(source: string): ListResult;
|
|
13
|
+
//# sourceMappingURL=list-source.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list-source.d.ts","sourceRoot":"","sources":["../../../src/listener/source/list-source.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,UAAU,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvF;;;GAGG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,CA0BrD"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { readdirSync, statSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
/**
|
|
4
|
+
* Names of regular files directly under the Source. Sub-directories, and
|
|
5
|
+
* symlinks that do not resolve to a file, are not Events.
|
|
6
|
+
*/
|
|
7
|
+
export function listSource(source) {
|
|
8
|
+
let entries;
|
|
9
|
+
try {
|
|
10
|
+
entries = readdirSync(source, { withFileTypes: true });
|
|
11
|
+
}
|
|
12
|
+
catch (error) {
|
|
13
|
+
return { ok: false, detail: error instanceof Error ? error.message : String(error) };
|
|
14
|
+
}
|
|
15
|
+
const names = [];
|
|
16
|
+
for (const entry of entries) {
|
|
17
|
+
if (entry.isFile()) {
|
|
18
|
+
names.push(entry.name);
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
if (!entry.isSymbolicLink()) {
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
try {
|
|
25
|
+
if (statSync(join(source, entry.name)).isFile()) {
|
|
26
|
+
names.push(entry.name);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
// A link pointing nowhere is not an Event.
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return { ok: true, names };
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=list-source.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list-source.js","sourceRoot":"","sources":["../../../src/listener/source/list-source.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,WAAW,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC7D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAIjC;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,MAAc;IACvC,IAAI,OAAyB,CAAC;IAC9B,IAAI,CAAC;QACH,OAAO,GAAG,WAAW,CAAC,MAAM,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IACzD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;IACvF,CAAC;IAED,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;YACnB,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACvB,SAAS;QACX,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,cAAc,EAAE,EAAE,CAAC;YAC5B,SAAS;QACX,CAAC;QACD,IAAI,CAAC;YACH,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;gBAChD,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACzB,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,2CAA2C;QAC7C,CAAC;IACH,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;AAC7B,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ReadEventResult } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Read one Event. Never retried: a file caught mid-write is a publisher that
|
|
4
|
+
* did not rename atomically, and this Block does not guess at write durations.
|
|
5
|
+
*/
|
|
6
|
+
export declare function readEvent(source: string, name: string): ReadEventResult;
|
|
7
|
+
//# sourceMappingURL=read-event.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read-event.d.ts","sourceRoot":"","sources":["../../../src/listener/source/read-event.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD;;;GAGG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,eAAe,CA+BvE"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
/**
|
|
4
|
+
* Read one Event. Never retried: a file caught mid-write is a publisher that
|
|
5
|
+
* did not rename atomically, and this Block does not guess at write durations.
|
|
6
|
+
*/
|
|
7
|
+
export function readEvent(source, name) {
|
|
8
|
+
let raw;
|
|
9
|
+
let bytes;
|
|
10
|
+
try {
|
|
11
|
+
const buffer = readFileSync(join(source, name));
|
|
12
|
+
bytes = buffer.byteLength;
|
|
13
|
+
raw = buffer.toString("utf8");
|
|
14
|
+
}
|
|
15
|
+
catch (error) {
|
|
16
|
+
return {
|
|
17
|
+
ok: false,
|
|
18
|
+
reason: "unreadable",
|
|
19
|
+
detail: error instanceof Error ? error.message : String(error),
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
let parsed;
|
|
23
|
+
try {
|
|
24
|
+
parsed = JSON.parse(raw);
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
return {
|
|
28
|
+
ok: false,
|
|
29
|
+
reason: "not-json",
|
|
30
|
+
detail: error instanceof Error ? error.message : String(error),
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
34
|
+
return { ok: false, reason: "not-object", detail: `Parsed to ${describe(parsed)}.` };
|
|
35
|
+
}
|
|
36
|
+
return { ok: true, payload: parsed, bytes };
|
|
37
|
+
}
|
|
38
|
+
function describe(value) {
|
|
39
|
+
if (value === null) {
|
|
40
|
+
return "null";
|
|
41
|
+
}
|
|
42
|
+
if (Array.isArray(value)) {
|
|
43
|
+
return "an array";
|
|
44
|
+
}
|
|
45
|
+
return `a ${typeof value}`;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=read-event.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read-event.js","sourceRoot":"","sources":["../../../src/listener/source/read-event.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,MAAc,EAAE,IAAY;IACpD,IAAI,GAAW,CAAC;IAChB,IAAI,KAAa,CAAC;IAClB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC;QAChD,KAAK,GAAG,MAAM,CAAC,UAAU,CAAC;QAC1B,GAAG,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IAChC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,YAAY;YACpB,MAAM,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;SAC/D,CAAC;IACJ,CAAC;IAED,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,UAAU;YAClB,MAAM,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;SAC/D,CAAC;IACJ,CAAC;IAED,IAAI,MAAM,KAAK,IAAI,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3E,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,aAAa,QAAQ,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC;IACvF,CAAC;IAED,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,MAAiC,EAAE,KAAK,EAAE,CAAC;AACzE,CAAC;AAED,SAAS,QAAQ,CAAC,KAAc;IAC9B,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACnB,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,UAAU,CAAC;IACpB,CAAC;IACD,OAAO,KAAK,OAAO,KAAK,EAAE,CAAC;AAC7B,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cursor arithmetic over Source file names. Pure: no directory is touched here,
|
|
3
|
+
* so ordering and cursor filtering are testable from a list of names.
|
|
4
|
+
*/
|
|
5
|
+
/** Byte-wise comparison, so ordering does not depend on a locale. */
|
|
6
|
+
export declare function compareCursors(left: string, right: string): number;
|
|
7
|
+
/** A name the Source protocol publishes an Event under. */
|
|
8
|
+
export declare function isEventName(name: string): boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Selected Event names, ordered, keeping only those strictly after the Cursor.
|
|
11
|
+
*/
|
|
12
|
+
export declare function selectEvents(names: string[], cursor: string | undefined): string[];
|
|
13
|
+
//# sourceMappingURL=select-events.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"select-events.d.ts","sourceRoot":"","sources":["../../../src/listener/source/select-events.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,qEAAqE;AACrE,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAElE;AAED,2DAA2D;AAC3D,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEjD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,EAAE,CAMlF"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cursor arithmetic over Source file names. Pure: no directory is touched here,
|
|
3
|
+
* so ordering and cursor filtering are testable from a list of names.
|
|
4
|
+
*/
|
|
5
|
+
/** Byte-wise comparison, so ordering does not depend on a locale. */
|
|
6
|
+
export function compareCursors(left, right) {
|
|
7
|
+
return Buffer.compare(Buffer.from(left, "utf8"), Buffer.from(right, "utf8"));
|
|
8
|
+
}
|
|
9
|
+
/** A name the Source protocol publishes an Event under. */
|
|
10
|
+
export function isEventName(name) {
|
|
11
|
+
return name.endsWith(".json") && !name.startsWith(".");
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Selected Event names, ordered, keeping only those strictly after the Cursor.
|
|
15
|
+
*/
|
|
16
|
+
export function selectEvents(names, cursor) {
|
|
17
|
+
const selected = names.filter(isEventName).sort(compareCursors);
|
|
18
|
+
if (cursor === undefined) {
|
|
19
|
+
return selected;
|
|
20
|
+
}
|
|
21
|
+
return selected.filter((name) => compareCursors(name, cursor) > 0);
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=select-events.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"select-events.js","sourceRoot":"","sources":["../../../src/listener/source/select-events.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,qEAAqE;AACrE,MAAM,UAAU,cAAc,CAAC,IAAY,EAAE,KAAa;IACxD,OAAO,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;AAC/E,CAAC;AAED,2DAA2D;AAC3D,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,OAAO,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;AACzD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,KAAe,EAAE,MAA0B;IACtE,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAChE,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,cAAc,CAAC,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;AACrE,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/** Domain types owned by FeatureListener. Names match the Block perimeter only. */
|
|
2
|
+
export type RunOutcome = "completed" | "source-lost" | "invalid-invocation" | "interrupted";
|
|
3
|
+
export type StopReason = "drained" | "max-events" | "duration" | "source-lost" | "signal";
|
|
4
|
+
export type SkipReason = "unreadable" | "not-json" | "not-object";
|
|
5
|
+
export type Invocation = {
|
|
6
|
+
manager: string;
|
|
7
|
+
source: string;
|
|
8
|
+
/** Deliver only Events whose Cursor is strictly greater. */
|
|
9
|
+
since?: string;
|
|
10
|
+
follow: boolean;
|
|
11
|
+
pollIntervalMs?: number;
|
|
12
|
+
maxEvents: number;
|
|
13
|
+
durationMs: number;
|
|
14
|
+
onIntentionArgv?: string[];
|
|
15
|
+
};
|
|
16
|
+
export type ParseResult = {
|
|
17
|
+
ok: true;
|
|
18
|
+
invocation: Invocation;
|
|
19
|
+
} | {
|
|
20
|
+
ok: false;
|
|
21
|
+
reason: string;
|
|
22
|
+
};
|
|
23
|
+
export type Delivery = {
|
|
24
|
+
cursor: string;
|
|
25
|
+
bytes: number;
|
|
26
|
+
payload: Record<string, unknown>;
|
|
27
|
+
};
|
|
28
|
+
export type Skip = {
|
|
29
|
+
cursor: string;
|
|
30
|
+
reason: SkipReason;
|
|
31
|
+
detail: string;
|
|
32
|
+
};
|
|
33
|
+
export type ReadEventResult = {
|
|
34
|
+
ok: true;
|
|
35
|
+
payload: Record<string, unknown>;
|
|
36
|
+
bytes: number;
|
|
37
|
+
} | {
|
|
38
|
+
ok: false;
|
|
39
|
+
reason: SkipReason;
|
|
40
|
+
detail: string;
|
|
41
|
+
};
|
|
42
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/listener/types.ts"],"names":[],"mappings":"AAAA,mFAAmF;AAEnF,MAAM,MAAM,UAAU,GAAG,WAAW,GAAG,aAAa,GAAG,oBAAoB,GAAG,aAAa,CAAC;AAE5F,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,YAAY,GAAG,UAAU,GAAG,aAAa,GAAG,QAAQ,CAAC;AAE1F,MAAM,MAAM,UAAU,GAAG,YAAY,GAAG,UAAU,GAAG,YAAY,CAAC;AAElE,MAAM,MAAM,UAAU,GAAG;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,4DAA4D;IAC5D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,UAAU,EAAE,UAAU,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE/F,MAAM,MAAM,QAAQ,GAAG;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,IAAI,GAAG;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,UAAU,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,eAAe,GACvB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC7D;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,UAAU,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/listener/types.ts"],"names":[],"mappings":"AAAA,mFAAmF"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ManagerPort } from "@bluewombat/manager-kit";
|
|
2
|
+
export type FakeManagerOptions = {
|
|
3
|
+
/** Directory holding one JSON file per raw intention. Must exist. */
|
|
4
|
+
source: string;
|
|
5
|
+
/** Directory the Thread `<slug>.ndjson` files are appended to. */
|
|
6
|
+
emitterTarget: string;
|
|
7
|
+
durationMs: number;
|
|
8
|
+
interruptFlag: {
|
|
9
|
+
interrupted: boolean;
|
|
10
|
+
};
|
|
11
|
+
defaultPriority?: number;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Directory Source + directory Thread. The wiring that needs no account.
|
|
15
|
+
*/
|
|
16
|
+
export declare function createFakeManager(options: FakeManagerOptions): ManagerPort;
|
|
17
|
+
//# sourceMappingURL=manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../src/manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAA6B,WAAW,EAAe,MAAM,yBAAyB,CAAC;AAcnG,MAAM,MAAM,kBAAkB,GAAG;IAC/B,qEAAqE;IACrE,MAAM,EAAE,MAAM,CAAC;IACf,kEAAkE;IAClE,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE;QAAE,WAAW,EAAE,OAAO,CAAA;KAAE,CAAC;IACxC,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,kBAAkB,GAAG,WAAW,CA8E1E"}
|
package/dist/manager.js
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { fingerprintOf } from "./adapter/normalize/fingerprint.js";
|
|
2
|
+
import { runAdapter } from "./adapter/run/run-adapter.js";
|
|
3
|
+
import { runEmitter } from "./emitter/run/run-emitter.js";
|
|
4
|
+
import { runListener } from "./listener/run/run-listener.js";
|
|
5
|
+
const silent = () => { };
|
|
6
|
+
const MANAGER = "fake";
|
|
7
|
+
const UNKNOWN_PROJECT = "unknown";
|
|
8
|
+
const DEFAULT_PRIORITY = 50;
|
|
9
|
+
const DEFAULT_MAX_EVENTS = 10_000;
|
|
10
|
+
const DEFAULT_MAX_RAW_BYTES = 65_536;
|
|
11
|
+
const MAX_REPORT_CHARS = 8_000;
|
|
12
|
+
/**
|
|
13
|
+
* Directory Source + directory Thread. The wiring that needs no account.
|
|
14
|
+
*/
|
|
15
|
+
export function createFakeManager(options) {
|
|
16
|
+
const defaultPriority = options.defaultPriority ?? DEFAULT_PRIORITY;
|
|
17
|
+
return {
|
|
18
|
+
async listen(input) {
|
|
19
|
+
const deliveries = [];
|
|
20
|
+
const listenerInvocation = {
|
|
21
|
+
manager: MANAGER,
|
|
22
|
+
source: options.source,
|
|
23
|
+
follow: false,
|
|
24
|
+
maxEvents: DEFAULT_MAX_EVENTS,
|
|
25
|
+
durationMs: options.durationMs,
|
|
26
|
+
};
|
|
27
|
+
if (input.since !== undefined) {
|
|
28
|
+
listenerInvocation.since = input.since;
|
|
29
|
+
}
|
|
30
|
+
const listened = await runListener({
|
|
31
|
+
invocation: listenerInvocation,
|
|
32
|
+
write: (line) => {
|
|
33
|
+
if (line.event === "intention" &&
|
|
34
|
+
typeof line.cursor === "string" &&
|
|
35
|
+
isObject(line.payload)) {
|
|
36
|
+
deliveries.push({ cursor: line.cursor, payload: line.payload });
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
interruptFlag: options.interruptFlag,
|
|
40
|
+
});
|
|
41
|
+
return { outcome: listened.outcome, deliveries };
|
|
42
|
+
},
|
|
43
|
+
async adapt(payload) {
|
|
44
|
+
const adapted = await runAdapter({
|
|
45
|
+
invocation: {
|
|
46
|
+
manager: MANAGER,
|
|
47
|
+
defaultPriority,
|
|
48
|
+
maxRawBytes: DEFAULT_MAX_RAW_BYTES,
|
|
49
|
+
},
|
|
50
|
+
raw: JSON.stringify(payload),
|
|
51
|
+
write: silent,
|
|
52
|
+
interruptFlag: options.interruptFlag,
|
|
53
|
+
});
|
|
54
|
+
if (adapted.outcome === "invalid" && adapted.invalid !== undefined) {
|
|
55
|
+
return {
|
|
56
|
+
outcome: "invalid",
|
|
57
|
+
invalid: adapted.invalid,
|
|
58
|
+
key: keyFromRaw(payload),
|
|
59
|
+
project: projectFromRaw(payload),
|
|
60
|
+
fingerprint: fingerprintOf(payload),
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
if (adapted.outcome === "unavailable" || adapted.outcome === "interrupted") {
|
|
64
|
+
return { outcome: adapted.outcome };
|
|
65
|
+
}
|
|
66
|
+
if (adapted.outcome !== "converted" || adapted.feature === undefined) {
|
|
67
|
+
return { outcome: "unavailable" };
|
|
68
|
+
}
|
|
69
|
+
return { outcome: "converted", feature: adapted.feature };
|
|
70
|
+
},
|
|
71
|
+
async report(input) {
|
|
72
|
+
const result = runEmitter({
|
|
73
|
+
invocation: {
|
|
74
|
+
target: options.emitterTarget,
|
|
75
|
+
event: input.event,
|
|
76
|
+
key: input.key,
|
|
77
|
+
project: input.project,
|
|
78
|
+
at: new Date().toISOString(),
|
|
79
|
+
fields: input.fields,
|
|
80
|
+
...(input.eventId === undefined ? {} : { eventId: input.eventId }),
|
|
81
|
+
maxReportChars: MAX_REPORT_CHARS,
|
|
82
|
+
dryRun: false,
|
|
83
|
+
},
|
|
84
|
+
write: silent,
|
|
85
|
+
});
|
|
86
|
+
return result.outcome === "reported";
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
function keyFromRaw(payload) {
|
|
91
|
+
const id = rawId(payload);
|
|
92
|
+
return id === undefined ? `${MANAGER}:unconvertible` : `${MANAGER}:${id}`;
|
|
93
|
+
}
|
|
94
|
+
function rawId(payload) {
|
|
95
|
+
const value = payload.id;
|
|
96
|
+
if (typeof value === "string" && value.trim().length > 0) {
|
|
97
|
+
return value.trim();
|
|
98
|
+
}
|
|
99
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
100
|
+
return String(value);
|
|
101
|
+
}
|
|
102
|
+
return undefined;
|
|
103
|
+
}
|
|
104
|
+
function projectFromRaw(payload) {
|
|
105
|
+
const value = payload.project;
|
|
106
|
+
if (typeof value === "string" && value.trim().length > 0) {
|
|
107
|
+
return value.trim();
|
|
108
|
+
}
|
|
109
|
+
return UNKNOWN_PROJECT;
|
|
110
|
+
}
|
|
111
|
+
function isObject(value) {
|
|
112
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manager.js","sourceRoot":"","sources":["../src/manager.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@bluewombat/manager-fake",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "File-based FeatureManager: JSON intentions in, Threads out. No account.",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"mason",
|
|
8
|
+
"bluewombat",
|
|
9
|
+
"mason-manager"
|
|
10
|
+
],
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"homepage": "https://github.com/tilap/bluewombat/tree/main/packages/plugins/manager-fake#readme",
|
|
13
|
+
"bugs": "https://github.com/tilap/bluewombat/issues",
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "git+https://github.com/tilap/bluewombat.git",
|
|
17
|
+
"directory": "packages/plugins/manager-fake"
|
|
18
|
+
},
|
|
19
|
+
"exports": {
|
|
20
|
+
".": {
|
|
21
|
+
"types": "./dist/index.d.ts",
|
|
22
|
+
"import": "./dist/index.js"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"types": "./dist/index.d.ts",
|
|
26
|
+
"files": [
|
|
27
|
+
"dist",
|
|
28
|
+
"README.md",
|
|
29
|
+
"SPECS.md"
|
|
30
|
+
],
|
|
31
|
+
"publishConfig": {
|
|
32
|
+
"access": "public"
|
|
33
|
+
},
|
|
34
|
+
"engines": {
|
|
35
|
+
"node": ">=24.20.0"
|
|
36
|
+
},
|
|
37
|
+
"scripts": {
|
|
38
|
+
"lint": "biome check .",
|
|
39
|
+
"format": "biome check --write .",
|
|
40
|
+
"tsc": "tsc --noEmit",
|
|
41
|
+
"test": "tsx --test $(find src -name '*.test.ts')",
|
|
42
|
+
"build": "tsc -p tsconfig.build.json"
|
|
43
|
+
},
|
|
44
|
+
"dependencies": {
|
|
45
|
+
"@bluewombat/manager-kit": "^0.1.0"
|
|
46
|
+
}
|
|
47
|
+
}
|