@bluewombat/manager-github 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 +162 -0
- package/SPECS.md +126 -0
- package/dist/adapter/github/fetch-issue.d.ts +29 -0
- package/dist/adapter/github/fetch-issue.d.ts.map +1 -0
- package/dist/adapter/github/fetch-issue.js +34 -0
- package/dist/adapter/github/fetch-issue.js.map +1 -0
- package/dist/adapter/normalize/body.d.ts +24 -0
- package/dist/adapter/normalize/body.d.ts.map +1 -0
- package/dist/adapter/normalize/body.js +104 -0
- package/dist/adapter/normalize/body.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/intent.d.ts +27 -0
- package/dist/adapter/normalize/intent.d.ts.map +1 -0
- package/dist/adapter/normalize/intent.js +57 -0
- package/dist/adapter/normalize/intent.js.map +1 -0
- package/dist/adapter/normalize/labels.d.ts +17 -0
- package/dist/adapter/normalize/labels.d.ts.map +1 -0
- package/dist/adapter/normalize/labels.js +43 -0
- package/dist/adapter/normalize/labels.js.map +1 -0
- package/dist/adapter/normalize/noise.d.ts +13 -0
- package/dist/adapter/normalize/noise.d.ts.map +1 -0
- package/dist/adapter/normalize/noise.js +28 -0
- package/dist/adapter/normalize/noise.js.map +1 -0
- package/dist/adapter/normalize/normalize.d.ts +22 -0
- package/dist/adapter/normalize/normalize.d.ts.map +1 -0
- package/dist/adapter/normalize/normalize.js +216 -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/raw/unwrap.d.ts +12 -0
- package/dist/adapter/raw/unwrap.d.ts.map +1 -0
- package/dist/adapter/raw/unwrap.js +19 -0
- package/dist/adapter/raw/unwrap.js.map +1 -0
- package/dist/adapter/run/run-adapter.d.ts +28 -0
- package/dist/adapter/run/run-adapter.d.ts.map +1 -0
- package/dist/adapter/run/run-adapter.js +131 -0
- package/dist/adapter/run/run-adapter.js.map +1 -0
- package/dist/adapter/types.d.ts +69 -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 +94 -0
- package/dist/emitter/event/field-matrix.js.map +1 -0
- package/dist/emitter/github/comments.d.ts +14 -0
- package/dist/emitter/github/comments.d.ts.map +1 -0
- package/dist/emitter/github/comments.js +69 -0
- package/dist/emitter/github/comments.js.map +1 -0
- package/dist/emitter/github/labels.d.ts +18 -0
- package/dist/emitter/github/labels.d.ts.map +1 -0
- package/dist/emitter/github/labels.js +81 -0
- package/dist/emitter/github/labels.js.map +1 -0
- package/dist/emitter/github/result.d.ts +19 -0
- package/dist/emitter/github/result.d.ts.map +1 -0
- package/dist/emitter/github/result.js +2 -0
- package/dist/emitter/github/result.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 +20 -0
- package/dist/emitter/render/render-event.d.ts.map +1 -0
- package/dist/emitter/render/render-event.js +293 -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 +27 -0
- package/dist/emitter/run/run-emitter.d.ts.map +1 -0
- package/dist/emitter/run/run-emitter.js +121 -0
- package/dist/emitter/run/run-emitter.js.map +1 -0
- package/dist/emitter/thread/marker.d.ts +15 -0
- package/dist/emitter/thread/marker.d.ts.map +1 -0
- package/dist/emitter/thread/marker.js +37 -0
- package/dist/emitter/thread/marker.js.map +1 -0
- package/dist/emitter/types.d.ts +64 -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/github/client.d.ts +63 -0
- package/dist/github/client.d.ts.map +1 -0
- package/dist/github/client.js +96 -0
- package/dist/github/client.js.map +1 -0
- package/dist/index.d.ts +55 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +357 -0
- package/dist/index.js.map +1 -0
- package/dist/issue-number.d.ts +5 -0
- package/dist/issue-number.d.ts.map +1 -0
- package/dist/issue-number.js +32 -0
- package/dist/issue-number.js.map +1 -0
- package/dist/labels.d.ts +3 -0
- package/dist/labels.d.ts.map +1 -0
- package/dist/labels.js +24 -0
- package/dist/labels.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/github/list-issues.d.ts +30 -0
- package/dist/listener/github/list-issues.d.ts.map +1 -0
- package/dist/listener/github/list-issues.js +36 -0
- package/dist/listener/github/list-issues.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 +35 -0
- package/dist/listener/run/run-listener.d.ts.map +1 -0
- package/dist/listener/run/run-listener.js +217 -0
- package/dist/listener/run/run-listener.js.map +1 -0
- package/dist/listener/source/select-events.d.ts +46 -0
- package/dist/listener/source/select-events.d.ts.map +1 -0
- package/dist/listener/source/select-events.js +102 -0
- package/dist/listener/source/select-events.js.map +1 -0
- package/dist/listener/types.d.ts +56 -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 +29 -0
- package/dist/manager.d.ts.map +1 -0
- package/dist/manager.js +256 -0
- package/dist/manager.js.map +1 -0
- package/dist/probe/probe-issue.d.ts +20 -0
- package/dist/probe/probe-issue.d.ts.map +1 -0
- package/dist/probe/probe-issue.js +45 -0
- package/dist/probe/probe-issue.js.map +1 -0
- package/dist/repo.d.ts +6 -0
- package/dist/repo.d.ts.map +1 -0
- package/dist/repo.js +14 -0
- package/dist/repo.js.map +1 -0
- package/dist/setup.d.ts +43 -0
- package/dist/setup.d.ts.map +1 -0
- package/dist/setup.js +281 -0
- package/dist/setup.js.map +1 -0
- package/dist/submission/submission.d.ts +44 -0
- package/dist/submission/submission.d.ts.map +1 -0
- package/dist/submission/submission.js +189 -0
- package/dist/submission/submission.js.map +1 -0
- package/dist/written-fingerprint.d.ts +7 -0
- package/dist/written-fingerprint.d.ts.map +1 -0
- package/dist/written-fingerprint.js +38 -0
- package/dist/written-fingerprint.js.map +1 -0
- package/package.json +51 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"labels.d.ts","sourceRoot":"","sources":["../src/labels.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAqBxF"}
|
package/dist/labels.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/** Whether a GitHub-shaped payload carries this label, ignoring case. */
|
|
2
|
+
export function payloadHasLabel(payload, label) {
|
|
3
|
+
const labels = payload.labels;
|
|
4
|
+
if (!Array.isArray(labels)) {
|
|
5
|
+
return false;
|
|
6
|
+
}
|
|
7
|
+
const wanted = label.toLowerCase();
|
|
8
|
+
for (const entry of labels) {
|
|
9
|
+
if (typeof entry === "string") {
|
|
10
|
+
if (entry.trim().toLowerCase() === wanted) {
|
|
11
|
+
return true;
|
|
12
|
+
}
|
|
13
|
+
continue;
|
|
14
|
+
}
|
|
15
|
+
if (entry !== null && typeof entry === "object" && "name" in entry) {
|
|
16
|
+
const name = entry.name;
|
|
17
|
+
if (typeof name === "string" && name.trim().toLowerCase() === wanted) {
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=labels.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"labels.js","sourceRoot":"","sources":["../src/labels.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,MAAM,UAAU,eAAe,CAAC,OAAgC,EAAE,KAAa;IAC7E,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAC9B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3B,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,MAAM,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;IACnC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,KAAK,MAAM,EAAE,CAAC;gBAC1C,OAAO,IAAI,CAAC;YACd,CAAC;YACD,SAAS;QACX,CAAC;QACD,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,IAAI,KAAK,EAAE,CAAC;YACnE,MAAM,IAAI,GAAI,KAA4B,CAAC,IAAI,CAAC;YAChD,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,KAAK,MAAM,EAAE,CAAC;gBACrE,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Run --on-intention for one Delivery. The result is deliberately dropped:
|
|
3
|
+
* a non-zero exit, a missing command, or a hang never changes the run outcome
|
|
4
|
+
* and never rolls the Cursor back.
|
|
5
|
+
*/
|
|
6
|
+
/** `cwd` undefined lets the hook inherit the caller's directory. */
|
|
7
|
+
export declare function runHook(argv: string[], cwd: string | undefined): Promise<void>;
|
|
8
|
+
//# sourceMappingURL=run-hook.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-hook.d.ts","sourceRoot":"","sources":["../../../src/listener/delivery/run-hook.ts"],"names":[],"mappings":"AAKA;;;;GAIG;AACH,oEAAoE;AACpE,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAyC9E"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
/** Soft cap: --on-intention must not hold the subscription open forever. */
|
|
3
|
+
const HOOK_TIMEOUT_MS = 5_000;
|
|
4
|
+
/**
|
|
5
|
+
* Run --on-intention for one Delivery. The result is deliberately dropped:
|
|
6
|
+
* a non-zero exit, a missing command, or a hang never changes the run outcome
|
|
7
|
+
* and never rolls the Cursor back.
|
|
8
|
+
*/
|
|
9
|
+
/** `cwd` undefined lets the hook inherit the caller's directory. */
|
|
10
|
+
export function runHook(argv, cwd) {
|
|
11
|
+
return new Promise((resolve) => {
|
|
12
|
+
const [file, ...args] = argv;
|
|
13
|
+
if (file === undefined) {
|
|
14
|
+
resolve();
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
let settled = false;
|
|
18
|
+
let timer;
|
|
19
|
+
const finish = () => {
|
|
20
|
+
if (settled) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
settled = true;
|
|
24
|
+
if (timer !== undefined) {
|
|
25
|
+
clearTimeout(timer);
|
|
26
|
+
}
|
|
27
|
+
resolve();
|
|
28
|
+
};
|
|
29
|
+
let child;
|
|
30
|
+
try {
|
|
31
|
+
child = spawn(file, args, { cwd, stdio: ["ignore", "ignore", "ignore"] });
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
finish();
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
timer = setTimeout(() => {
|
|
38
|
+
try {
|
|
39
|
+
child.kill("SIGKILL");
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
// already gone
|
|
43
|
+
}
|
|
44
|
+
finish();
|
|
45
|
+
}, HOOK_TIMEOUT_MS);
|
|
46
|
+
child.on("error", finish);
|
|
47
|
+
child.on("close", finish);
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=run-hook.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-hook.js","sourceRoot":"","sources":["../../../src/listener/delivery/run-hook.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE9D,4EAA4E;AAC5E,MAAM,eAAe,GAAG,KAAK,CAAC;AAE9B;;;;GAIG;AACH,oEAAoE;AACpE,MAAM,UAAU,OAAO,CAAC,IAAc,EAAE,GAAuB;IAC7D,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;QAC7B,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACvB,OAAO,EAAE,CAAC;YACV,OAAO;QACT,CAAC;QAED,IAAI,OAAO,GAAG,KAAK,CAAC;QACpB,IAAI,KAAiC,CAAC;QACtC,MAAM,MAAM,GAAG,GAAS,EAAE;YACxB,IAAI,OAAO,EAAE,CAAC;gBACZ,OAAO;YACT,CAAC;YACD,OAAO,GAAG,IAAI,CAAC;YACf,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACxB,YAAY,CAAC,KAAK,CAAC,CAAC;YACtB,CAAC;YACD,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC;QAEF,IAAI,KAAmB,CAAC;QACxB,IAAI,CAAC;YACH,KAAK,GAAG,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC;QAC5E,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,EAAE,CAAC;YACT,OAAO;QACT,CAAC;QAED,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YACtB,IAAI,CAAC;gBACH,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACxB,CAAC;YAAC,MAAM,CAAC;gBACP,eAAe;YACjB,CAAC;YACD,MAAM,EAAE,CAAC;QACX,CAAC,EAAE,eAAe,CAAC,CAAC;QAEpB,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC1B,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type GithubClient } from "../../github/client.js";
|
|
2
|
+
import type { Invocation } from "../types.js";
|
|
3
|
+
export type ListResult = {
|
|
4
|
+
ok: true;
|
|
5
|
+
entries: unknown[];
|
|
6
|
+
lastPageReached: boolean;
|
|
7
|
+
}
|
|
8
|
+
/** The Source stopped being readable: a refusal, or nobody answered in the budget. */
|
|
9
|
+
| {
|
|
10
|
+
ok: false;
|
|
11
|
+
interrupted: boolean;
|
|
12
|
+
detail: string;
|
|
13
|
+
};
|
|
14
|
+
export type ListRequest = {
|
|
15
|
+
invocation: Invocation;
|
|
16
|
+
github: GithubClient;
|
|
17
|
+
/** Deliver only what moved at or after this instant; the Cursor drops the rest. */
|
|
18
|
+
sinceIso: string | undefined;
|
|
19
|
+
page: number;
|
|
20
|
+
deadlineMs: number;
|
|
21
|
+
now: () => number;
|
|
22
|
+
shouldInterrupt: () => boolean;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* One page of the Source. Ascending on `updated`, so a scan walks the
|
|
26
|
+
* repository in the order the Cursor is built from. Never writes: this Block
|
|
27
|
+
* only reads.
|
|
28
|
+
*/
|
|
29
|
+
export declare function listIssues(request: ListRequest): Promise<ListResult>;
|
|
30
|
+
//# sourceMappingURL=list-issues.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list-issues.d.ts","sourceRoot":"","sources":["../../../src/listener/github/list-issues.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,YAAY,EAAe,MAAM,wBAAwB,CAAC;AACpF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,MAAM,MAAM,UAAU,GAClB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,OAAO,EAAE,CAAC;IAAC,eAAe,EAAE,OAAO,CAAA;CAAE;AAC5D,sFAAsF;GACpF;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,WAAW,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAExD,MAAM,MAAM,WAAW,GAAG;IACxB,UAAU,EAAE,UAAU,CAAC;IACvB,MAAM,EAAE,YAAY,CAAC;IACrB,mFAAmF;IACnF,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,EAAE,MAAM,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,OAAO,CAAC;CAChC,CAAC;AAEF;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CA0B1E"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { callSignal, readFailure } from "../../github/client.js";
|
|
2
|
+
/**
|
|
3
|
+
* One page of the Source. Ascending on `updated`, so a scan walks the
|
|
4
|
+
* repository in the order the Cursor is built from. Never writes: this Block
|
|
5
|
+
* only reads.
|
|
6
|
+
*/
|
|
7
|
+
export async function listIssues(request) {
|
|
8
|
+
const { invocation } = request;
|
|
9
|
+
const call = callSignal(request.deadlineMs, request.now, request.shouldInterrupt);
|
|
10
|
+
try {
|
|
11
|
+
const response = await request.github.request("GET /repos/{owner}/{repo}/issues", {
|
|
12
|
+
owner: invocation.repo.owner,
|
|
13
|
+
repo: invocation.repo.name,
|
|
14
|
+
state: invocation.state,
|
|
15
|
+
sort: "updated",
|
|
16
|
+
direction: "asc",
|
|
17
|
+
per_page: invocation.perPage,
|
|
18
|
+
page: request.page,
|
|
19
|
+
...(invocation.labels.length > 0 ? { labels: invocation.labels.join(",") } : {}),
|
|
20
|
+
...(request.sinceIso !== undefined ? { since: request.sinceIso } : {}),
|
|
21
|
+
request: { signal: call.signal },
|
|
22
|
+
});
|
|
23
|
+
const entries = response.data;
|
|
24
|
+
return { ok: true, entries, lastPageReached: entries.length < invocation.perPage };
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
if (request.shouldInterrupt()) {
|
|
28
|
+
return { ok: false, interrupted: true, detail: "Stopped by a signal." };
|
|
29
|
+
}
|
|
30
|
+
return { ok: false, interrupted: false, detail: readFailure(error).detail };
|
|
31
|
+
}
|
|
32
|
+
finally {
|
|
33
|
+
call.release();
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=list-issues.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list-issues.js","sourceRoot":"","sources":["../../../src/listener/github/list-issues.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAqB,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAmBpF;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,OAAoB;IACnD,MAAM,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC;IAC/B,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC;IAClF,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,kCAAkC,EAAE;YAChF,KAAK,EAAE,UAAU,CAAC,IAAI,CAAC,KAAK;YAC5B,IAAI,EAAE,UAAU,CAAC,IAAI,CAAC,IAAI;YAC1B,KAAK,EAAE,UAAU,CAAC,KAAK;YACvB,IAAI,EAAE,SAAS;YACf,SAAS,EAAE,KAAK;YAChB,QAAQ,EAAE,UAAU,CAAC,OAAO;YAC5B,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAChF,GAAG,CAAC,OAAO,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACtE,OAAO,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE;SACjC,CAAC,CAAC;QACH,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAiB,CAAC;QAC3C,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,eAAe,EAAE,OAAO,CAAC,MAAM,GAAG,UAAU,CAAC,OAAO,EAAE,CAAC;IACrF,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC;YAC9B,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,sBAAsB,EAAE,CAAC;QAC1E,CAAC;QACD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC;IAC9E,CAAC;YAAS,CAAC;QACT,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emit.d.ts","sourceRoot":"","sources":["../../../src/listener/progress/emit.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,cAAc,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;AAErE,wBAAgB,0BAA0B,IAAI,cAAc,CAI3D"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emit.js","sourceRoot":"","sources":["../../../src/listener/progress/emit.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,0BAA0B;IACxC,OAAO,CAAC,IAAI,EAAE,EAAE;QACd,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpD,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { GithubClient } from "../../github/client.js";
|
|
2
|
+
import type { ProgressWriter } from "../progress/emit.js";
|
|
3
|
+
import type { Invocation, RunOutcome, StopReason } from "../types.js";
|
|
4
|
+
export type RunResult = {
|
|
5
|
+
outcome: RunOutcome;
|
|
6
|
+
/** Absent on invalid-invocation: nothing ran, so nothing stopped. */
|
|
7
|
+
stopReason?: StopReason;
|
|
8
|
+
/** Last committed Cursor; absent when no Event was consumed. */
|
|
9
|
+
cursor?: string;
|
|
10
|
+
delivered: number;
|
|
11
|
+
skipped: number;
|
|
12
|
+
scans: number;
|
|
13
|
+
pages: number;
|
|
14
|
+
exitCode: number;
|
|
15
|
+
};
|
|
16
|
+
export type RunOptions = {
|
|
17
|
+
invocation: Invocation;
|
|
18
|
+
/** The authenticated channel to the Source. The CLI builds it from a token. */
|
|
19
|
+
github: GithubClient;
|
|
20
|
+
write?: ProgressWriter;
|
|
21
|
+
/** Injectable clock for tests. */
|
|
22
|
+
now?: () => number;
|
|
23
|
+
/** When set, polled for interrupt; otherwise the run is never interrupted. */
|
|
24
|
+
interruptFlag?: {
|
|
25
|
+
interrupted: boolean;
|
|
26
|
+
};
|
|
27
|
+
/** Working directory for the --on-intention child. Undefined lets it inherit. */
|
|
28
|
+
cwd?: string;
|
|
29
|
+
};
|
|
30
|
+
export declare function invalidInvocationResult(write: ProgressWriter, reason: string): RunResult;
|
|
31
|
+
/**
|
|
32
|
+
* Run one FeatureListener invocation to a run outcome.
|
|
33
|
+
*/
|
|
34
|
+
export declare function runListener(options: RunOptions): Promise<RunResult>;
|
|
35
|
+
//# sourceMappingURL=run-listener.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-listener.d.ts","sourceRoot":"","sources":["../../../src/listener/run/run-listener.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAG3D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEtE,MAAM,MAAM,SAAS,GAAG;IACtB,OAAO,EAAE,UAAU,CAAC;IACpB,qEAAqE;IACrE,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,gEAAgE;IAChE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,UAAU,EAAE,UAAU,CAAC;IACvB,+EAA+E;IAC/E,MAAM,EAAE,YAAY,CAAC;IACrB,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,kCAAkC;IAClC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,8EAA8E;IAC9E,aAAa,CAAC,EAAE;QAAE,WAAW,EAAE,OAAO,CAAA;KAAE,CAAC;IACzC,iFAAiF;IACjF,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAeF,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,CAkBxF;AAmBD;;GAEG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC,CAazE"}
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import { runHook } from "../delivery/run-hook.js";
|
|
2
|
+
import { listIssues } from "../github/list-issues.js";
|
|
3
|
+
import { parseCursor, selectEvents } from "../source/select-events.js";
|
|
4
|
+
function exitCodeFor(outcome) {
|
|
5
|
+
switch (outcome) {
|
|
6
|
+
case "completed":
|
|
7
|
+
return 0;
|
|
8
|
+
case "source-lost":
|
|
9
|
+
return 1;
|
|
10
|
+
case "invalid-invocation":
|
|
11
|
+
return 2;
|
|
12
|
+
case "interrupted":
|
|
13
|
+
return 130;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export function invalidInvocationResult(write, reason) {
|
|
17
|
+
write({
|
|
18
|
+
event: "run-finished",
|
|
19
|
+
outcome: "invalid-invocation",
|
|
20
|
+
delivered: 0,
|
|
21
|
+
skipped: 0,
|
|
22
|
+
scans: 0,
|
|
23
|
+
pages: 0,
|
|
24
|
+
detail: reason,
|
|
25
|
+
});
|
|
26
|
+
return {
|
|
27
|
+
outcome: "invalid-invocation",
|
|
28
|
+
delivered: 0,
|
|
29
|
+
skipped: 0,
|
|
30
|
+
scans: 0,
|
|
31
|
+
pages: 0,
|
|
32
|
+
exitCode: exitCodeFor("invalid-invocation"),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/** Sleep that gives up early on a stop signal or on the duration clock. */
|
|
36
|
+
async function waitPoll(input) {
|
|
37
|
+
const until = input.now() + input.ms;
|
|
38
|
+
while (input.now() < until) {
|
|
39
|
+
if (input.shouldInterrupt() || input.now() >= input.deadlineMs) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const slice = Math.min(20, until - input.now());
|
|
43
|
+
await new Promise((resolve) => setTimeout(resolve, Math.max(1, slice)));
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Run one FeatureListener invocation to a run outcome.
|
|
48
|
+
*/
|
|
49
|
+
export async function runListener(options) {
|
|
50
|
+
const write = options.write ?? (() => { });
|
|
51
|
+
const now = options.now ?? (() => Date.now());
|
|
52
|
+
const interruptState = options.interruptFlag ?? { interrupted: false };
|
|
53
|
+
return await runLoop({
|
|
54
|
+
invocation: options.invocation,
|
|
55
|
+
github: options.github,
|
|
56
|
+
write,
|
|
57
|
+
now,
|
|
58
|
+
shouldInterrupt: () => interruptState.interrupted,
|
|
59
|
+
cwd: options.cwd,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
async function runLoop(input) {
|
|
63
|
+
const { invocation, write, now, shouldInterrupt } = input;
|
|
64
|
+
const deadlineMs = now() + invocation.durationMs;
|
|
65
|
+
const repo = `${invocation.repo.owner}/${invocation.repo.name}`;
|
|
66
|
+
let cursor = invocation.since;
|
|
67
|
+
let delivered = 0;
|
|
68
|
+
let skipped = 0;
|
|
69
|
+
let scans = 0;
|
|
70
|
+
let pages = 0;
|
|
71
|
+
const finish = (outcome, stopReason, detail) => {
|
|
72
|
+
const line = {
|
|
73
|
+
event: "run-finished",
|
|
74
|
+
manager: invocation.manager,
|
|
75
|
+
repo,
|
|
76
|
+
outcome,
|
|
77
|
+
stop_reason: stopReason,
|
|
78
|
+
delivered,
|
|
79
|
+
skipped,
|
|
80
|
+
scans,
|
|
81
|
+
pages,
|
|
82
|
+
};
|
|
83
|
+
if (cursor !== undefined) {
|
|
84
|
+
line.cursor = cursor;
|
|
85
|
+
}
|
|
86
|
+
if (detail !== undefined) {
|
|
87
|
+
line.detail = detail;
|
|
88
|
+
}
|
|
89
|
+
write(line);
|
|
90
|
+
const result = {
|
|
91
|
+
outcome,
|
|
92
|
+
stopReason,
|
|
93
|
+
delivered,
|
|
94
|
+
skipped,
|
|
95
|
+
scans,
|
|
96
|
+
pages,
|
|
97
|
+
exitCode: exitCodeFor(outcome),
|
|
98
|
+
};
|
|
99
|
+
if (cursor !== undefined) {
|
|
100
|
+
result.cursor = cursor;
|
|
101
|
+
}
|
|
102
|
+
return result;
|
|
103
|
+
};
|
|
104
|
+
// Consumed Events, delivered or skipped: both cost a read of the listing.
|
|
105
|
+
const consumed = () => delivered + skipped;
|
|
106
|
+
for (;;) {
|
|
107
|
+
if (shouldInterrupt()) {
|
|
108
|
+
return finish("interrupted", "signal");
|
|
109
|
+
}
|
|
110
|
+
if (now() >= deadlineMs) {
|
|
111
|
+
return finish("completed", "duration");
|
|
112
|
+
}
|
|
113
|
+
// The whole scan resumes from the Cursor it started with; what the scan
|
|
114
|
+
// itself delivers is dropped again by selectEvents, page after page.
|
|
115
|
+
const sinceIso = cursor === undefined ? undefined : parseCursor(cursor)?.updatedAt;
|
|
116
|
+
scans += 1;
|
|
117
|
+
write({
|
|
118
|
+
event: "scan",
|
|
119
|
+
manager: invocation.manager,
|
|
120
|
+
repo,
|
|
121
|
+
...(cursor !== undefined ? { since: cursor } : {}),
|
|
122
|
+
});
|
|
123
|
+
let page = 1;
|
|
124
|
+
let bounded = false;
|
|
125
|
+
for (;;) {
|
|
126
|
+
const listed = await listIssues({
|
|
127
|
+
invocation,
|
|
128
|
+
github: input.github,
|
|
129
|
+
sinceIso,
|
|
130
|
+
page,
|
|
131
|
+
deadlineMs,
|
|
132
|
+
now,
|
|
133
|
+
shouldInterrupt,
|
|
134
|
+
});
|
|
135
|
+
if (!listed.ok) {
|
|
136
|
+
if (listed.interrupted) {
|
|
137
|
+
return finish("interrupted", "signal");
|
|
138
|
+
}
|
|
139
|
+
return finish("source-lost", "source-lost", listed.detail);
|
|
140
|
+
}
|
|
141
|
+
pages += 1;
|
|
142
|
+
const selections = selectEvents(listed.entries, cursor);
|
|
143
|
+
write({
|
|
144
|
+
event: "page",
|
|
145
|
+
manager: invocation.manager,
|
|
146
|
+
repo,
|
|
147
|
+
page,
|
|
148
|
+
pending: selections.length,
|
|
149
|
+
});
|
|
150
|
+
for (const selection of selections) {
|
|
151
|
+
if (shouldInterrupt()) {
|
|
152
|
+
return finish("interrupted", "signal");
|
|
153
|
+
}
|
|
154
|
+
if (consumed() >= invocation.maxEvents) {
|
|
155
|
+
bounded = true;
|
|
156
|
+
break;
|
|
157
|
+
}
|
|
158
|
+
if (now() >= deadlineMs) {
|
|
159
|
+
return finish("completed", "duration");
|
|
160
|
+
}
|
|
161
|
+
if (selection.kind === "skip") {
|
|
162
|
+
// No Cursor to commit: a malformed entry is reported, not consumed.
|
|
163
|
+
write({
|
|
164
|
+
event: "skipped",
|
|
165
|
+
manager: invocation.manager,
|
|
166
|
+
repo,
|
|
167
|
+
reason: selection.reason,
|
|
168
|
+
detail: selection.detail,
|
|
169
|
+
});
|
|
170
|
+
skipped += 1;
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
const body = JSON.stringify(selection.payload);
|
|
174
|
+
write({
|
|
175
|
+
event: "intention",
|
|
176
|
+
manager: invocation.manager,
|
|
177
|
+
repo,
|
|
178
|
+
cursor: selection.cursor,
|
|
179
|
+
observed_at: new Date(now()).toISOString(),
|
|
180
|
+
bytes: Buffer.byteLength(body, "utf8"),
|
|
181
|
+
payload: selection.payload,
|
|
182
|
+
});
|
|
183
|
+
// Commit only once the Delivery is on stdout: at-least-once, never at-most-once.
|
|
184
|
+
cursor = selection.cursor;
|
|
185
|
+
delivered += 1;
|
|
186
|
+
if (invocation.onIntentionArgv !== undefined) {
|
|
187
|
+
await runHook([
|
|
188
|
+
...invocation.onIntentionArgv,
|
|
189
|
+
"--manager",
|
|
190
|
+
invocation.manager,
|
|
191
|
+
"--cursor",
|
|
192
|
+
selection.cursor,
|
|
193
|
+
"--payload",
|
|
194
|
+
body,
|
|
195
|
+
], input.cwd);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
if (bounded || listed.lastPageReached) {
|
|
199
|
+
break;
|
|
200
|
+
}
|
|
201
|
+
page += 1;
|
|
202
|
+
}
|
|
203
|
+
if (consumed() >= invocation.maxEvents) {
|
|
204
|
+
return finish("completed", "max-events");
|
|
205
|
+
}
|
|
206
|
+
if (!invocation.follow) {
|
|
207
|
+
return finish("completed", "drained");
|
|
208
|
+
}
|
|
209
|
+
await waitPoll({
|
|
210
|
+
ms: invocation.pollIntervalMs ?? 1,
|
|
211
|
+
now,
|
|
212
|
+
deadlineMs,
|
|
213
|
+
shouldInterrupt,
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
//# 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":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAEtD,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AA6BvE,SAAS,WAAW,CAAC,OAAmB;IACtC,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,WAAW;YACd,OAAO,CAAC,CAAC;QACX,KAAK,aAAa;YAChB,OAAO,CAAC,CAAC;QACX,KAAK,oBAAoB;YACvB,OAAO,CAAC,CAAC;QACX,KAAK,aAAa;YAChB,OAAO,GAAG,CAAC;IACf,CAAC;AACH,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,KAAqB,EAAE,MAAc;IAC3E,KAAK,CAAC;QACJ,KAAK,EAAE,cAAc;QACrB,OAAO,EAAE,oBAAoB;QAC7B,SAAS,EAAE,CAAC;QACZ,OAAO,EAAE,CAAC;QACV,KAAK,EAAE,CAAC;QACR,KAAK,EAAE,CAAC;QACR,MAAM,EAAE,MAAM;KACf,CAAC,CAAC;IACH,OAAO;QACL,OAAO,EAAE,oBAAoB;QAC7B,SAAS,EAAE,CAAC;QACZ,OAAO,EAAE,CAAC;QACV,KAAK,EAAE,CAAC;QACR,KAAK,EAAE,CAAC;QACR,QAAQ,EAAE,WAAW,CAAC,oBAAoB,CAAC;KAC5C,CAAC;AACJ,CAAC;AAED,2EAA2E;AAC3E,KAAK,UAAU,QAAQ,CAAC,KAKvB;IACC,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,EAAE,CAAC;IACrC,OAAO,KAAK,CAAC,GAAG,EAAE,GAAG,KAAK,EAAE,CAAC;QAC3B,IAAI,KAAK,CAAC,eAAe,EAAE,IAAI,KAAK,CAAC,GAAG,EAAE,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;YAC/D,OAAO;QACT,CAAC;QACD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC;QAChD,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;IAC1E,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAAmB;IACnD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IAC1C,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IAC9C,MAAM,cAAc,GAAG,OAAO,CAAC,aAAa,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC;IAEvE,OAAO,MAAM,OAAO,CAAC;QACnB,UAAU,EAAE,OAAO,CAAC,UAAU;QAC9B,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,KAAK;QACL,GAAG;QACH,eAAe,EAAE,GAAG,EAAE,CAAC,cAAc,CAAC,WAAW;QACjD,GAAG,EAAE,OAAO,CAAC,GAAG;KACjB,CAAC,CAAC;AACL,CAAC;AAWD,KAAK,UAAU,OAAO,CAAC,KAAgB;IACrC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,GAAG,EAAE,eAAe,EAAE,GAAG,KAAK,CAAC;IAC1D,MAAM,UAAU,GAAG,GAAG,EAAE,GAAG,UAAU,CAAC,UAAU,CAAC;IACjD,MAAM,IAAI,GAAG,GAAG,UAAU,CAAC,IAAI,CAAC,KAAK,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;IAEhE,IAAI,MAAM,GAAG,UAAU,CAAC,KAAK,CAAC;IAC9B,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,KAAK,GAAG,CAAC,CAAC;IAEd,MAAM,MAAM,GAAG,CAAC,OAAmB,EAAE,UAAsB,EAAE,MAAe,EAAa,EAAE;QACzF,MAAM,IAAI,GAA4B;YACpC,KAAK,EAAE,cAAc;YACrB,OAAO,EAAE,UAAU,CAAC,OAAO;YAC3B,IAAI;YACJ,OAAO;YACP,WAAW,EAAE,UAAU;YACvB,SAAS;YACT,OAAO;YACP,KAAK;YACL,KAAK;SACN,CAAC;QACF,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACvB,CAAC;QACD,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACvB,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,CAAC;QAEZ,MAAM,MAAM,GAAc;YACxB,OAAO;YACP,UAAU;YACV,SAAS;YACT,OAAO;YACP,KAAK;YACL,KAAK;YACL,QAAQ,EAAE,WAAW,CAAC,OAAO,CAAC;SAC/B,CAAC;QACF,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC;QACzB,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC;IAEF,0EAA0E;IAC1E,MAAM,QAAQ,GAAG,GAAW,EAAE,CAAC,SAAS,GAAG,OAAO,CAAC;IAEnD,SAAS,CAAC;QACR,IAAI,eAAe,EAAE,EAAE,CAAC;YACtB,OAAO,MAAM,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;QACzC,CAAC;QACD,IAAI,GAAG,EAAE,IAAI,UAAU,EAAE,CAAC;YACxB,OAAO,MAAM,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;QACzC,CAAC;QAED,wEAAwE;QACxE,qEAAqE;QACrE,MAAM,QAAQ,GAAG,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,SAAS,CAAC;QACnF,KAAK,IAAI,CAAC,CAAC;QACX,KAAK,CAAC;YACJ,KAAK,EAAE,MAAM;YACb,OAAO,EAAE,UAAU,CAAC,OAAO;YAC3B,IAAI;YACJ,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACnD,CAAC,CAAC;QAEH,IAAI,IAAI,GAAG,CAAC,CAAC;QACb,IAAI,OAAO,GAAG,KAAK,CAAC;QACpB,SAAS,CAAC;YACR,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC;gBAC9B,UAAU;gBACV,MAAM,EAAE,KAAK,CAAC,MAAM;gBACpB,QAAQ;gBACR,IAAI;gBACJ,UAAU;gBACV,GAAG;gBACH,eAAe;aAChB,CAAC,CAAC;YACH,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;gBACf,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;oBACvB,OAAO,MAAM,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;gBACzC,CAAC;gBACD,OAAO,MAAM,CAAC,aAAa,EAAE,aAAa,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;YAC7D,CAAC;YAED,KAAK,IAAI,CAAC,CAAC;YACX,MAAM,UAAU,GAAG,YAAY,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YACxD,KAAK,CAAC;gBACJ,KAAK,EAAE,MAAM;gBACb,OAAO,EAAE,UAAU,CAAC,OAAO;gBAC3B,IAAI;gBACJ,IAAI;gBACJ,OAAO,EAAE,UAAU,CAAC,MAAM;aAC3B,CAAC,CAAC;YAEH,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;gBACnC,IAAI,eAAe,EAAE,EAAE,CAAC;oBACtB,OAAO,MAAM,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;gBACzC,CAAC;gBACD,IAAI,QAAQ,EAAE,IAAI,UAAU,CAAC,SAAS,EAAE,CAAC;oBACvC,OAAO,GAAG,IAAI,CAAC;oBACf,MAAM;gBACR,CAAC;gBACD,IAAI,GAAG,EAAE,IAAI,UAAU,EAAE,CAAC;oBACxB,OAAO,MAAM,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;gBACzC,CAAC;gBAED,IAAI,SAAS,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;oBAC9B,oEAAoE;oBACpE,KAAK,CAAC;wBACJ,KAAK,EAAE,SAAS;wBAChB,OAAO,EAAE,UAAU,CAAC,OAAO;wBAC3B,IAAI;wBACJ,MAAM,EAAE,SAAS,CAAC,MAAM;wBACxB,MAAM,EAAE,SAAS,CAAC,MAAM;qBACzB,CAAC,CAAC;oBACH,OAAO,IAAI,CAAC,CAAC;oBACb,SAAS;gBACX,CAAC;gBAED,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;gBAC/C,KAAK,CAAC;oBACJ,KAAK,EAAE,WAAW;oBAClB,OAAO,EAAE,UAAU,CAAC,OAAO;oBAC3B,IAAI;oBACJ,MAAM,EAAE,SAAS,CAAC,MAAM;oBACxB,WAAW,EAAE,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,WAAW,EAAE;oBAC1C,KAAK,EAAE,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC;oBACtC,OAAO,EAAE,SAAS,CAAC,OAAO;iBAC3B,CAAC,CAAC;gBACH,iFAAiF;gBACjF,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC;gBAC1B,SAAS,IAAI,CAAC,CAAC;gBACf,IAAI,UAAU,CAAC,eAAe,KAAK,SAAS,EAAE,CAAC;oBAC7C,MAAM,OAAO,CACX;wBACE,GAAG,UAAU,CAAC,eAAe;wBAC7B,WAAW;wBACX,UAAU,CAAC,OAAO;wBAClB,UAAU;wBACV,SAAS,CAAC,MAAM;wBAChB,WAAW;wBACX,IAAI;qBACL,EACD,KAAK,CAAC,GAAG,CACV,CAAC;gBACJ,CAAC;YACH,CAAC;YAED,IAAI,OAAO,IAAI,MAAM,CAAC,eAAe,EAAE,CAAC;gBACtC,MAAM;YACR,CAAC;YACD,IAAI,IAAI,CAAC,CAAC;QACZ,CAAC;QAED,IAAI,QAAQ,EAAE,IAAI,UAAU,CAAC,SAAS,EAAE,CAAC;YACvC,OAAO,MAAM,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;QAC3C,CAAC;QACD,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC;YACvB,OAAO,MAAM,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;QACxC,CAAC;QAED,MAAM,QAAQ,CAAC;YACb,EAAE,EAAE,UAAU,CAAC,cAAc,IAAI,CAAC;YAClC,GAAG;YACH,UAAU;YACV,eAAe;SAChB,CAAC,CAAC;IACL,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cursor arithmetic over what the Source listed. Pure: no request is made here,
|
|
3
|
+
* so ordering, cursor filtering, and the pull-request filter are testable from
|
|
4
|
+
* a list of objects.
|
|
5
|
+
*/
|
|
6
|
+
import type { Cursor, SkipReason } from "../types.js";
|
|
7
|
+
export declare const CURSOR_SEPARATOR = "#";
|
|
8
|
+
/** `<updated_at>#<number>`: when the issue last moved, then which issue it is. */
|
|
9
|
+
export declare function formatCursor(cursor: Cursor): string;
|
|
10
|
+
export declare function parseCursor(text: string): Cursor | null;
|
|
11
|
+
/**
|
|
12
|
+
* Order two Cursors: by the timestamp first, then by the issue number. The
|
|
13
|
+
* timestamp compares byte-wise because GitHub renders every one of them the
|
|
14
|
+
* same way; the number compares as a number, since `#9` precedes `#10`.
|
|
15
|
+
*/
|
|
16
|
+
export declare function compareCursors(left: Cursor, right: Cursor): number;
|
|
17
|
+
/**
|
|
18
|
+
* A pull request is not an Event of this Source. GitHub lists both under
|
|
19
|
+
* `/issues`, and only the tracker half is what this Block subscribes to.
|
|
20
|
+
*/
|
|
21
|
+
export declare function isPullRequest(entry: Record<string, unknown>): boolean;
|
|
22
|
+
export type CursorOfResult = {
|
|
23
|
+
ok: true;
|
|
24
|
+
cursor: Cursor;
|
|
25
|
+
} | {
|
|
26
|
+
ok: false;
|
|
27
|
+
reason: SkipReason;
|
|
28
|
+
detail: string;
|
|
29
|
+
};
|
|
30
|
+
/** The two fields an Event must carry to be placed in the order. */
|
|
31
|
+
export declare function cursorOf(entry: Record<string, unknown>): CursorOfResult;
|
|
32
|
+
export type Selection = {
|
|
33
|
+
kind: "event";
|
|
34
|
+
cursor: string;
|
|
35
|
+
payload: Record<string, unknown>;
|
|
36
|
+
} | {
|
|
37
|
+
kind: "skip";
|
|
38
|
+
reason: SkipReason;
|
|
39
|
+
detail: string;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* What one scan consumes, in the order it consumes it. A malformed entry has
|
|
43
|
+
* no Cursor to place it in the order, so it is reported before the Deliveries.
|
|
44
|
+
*/
|
|
45
|
+
export declare function selectEvents(entries: unknown[], since: string | undefined): Selection[];
|
|
46
|
+
//# 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;;;;GAIG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEtD,eAAO,MAAM,gBAAgB,MAAM,CAAC;AAEpC,kFAAkF;AAClF,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAWvD;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAQlE;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAErE;AAED,MAAM,MAAM,cAAc,GACtB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC5B;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,UAAU,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtD,oEAAoE;AACpE,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,cAAc,CAUvE;AAED,MAAM,MAAM,SAAS,GACjB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GACnE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,UAAU,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzD;;;GAGG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,EAAE,CAoCvF"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cursor arithmetic over what the Source listed. Pure: no request is made here,
|
|
3
|
+
* so ordering, cursor filtering, and the pull-request filter are testable from
|
|
4
|
+
* a list of objects.
|
|
5
|
+
*/
|
|
6
|
+
export const CURSOR_SEPARATOR = "#";
|
|
7
|
+
/** `<updated_at>#<number>`: when the issue last moved, then which issue it is. */
|
|
8
|
+
export function formatCursor(cursor) {
|
|
9
|
+
return `${cursor.updatedAt}${CURSOR_SEPARATOR}${cursor.number}`;
|
|
10
|
+
}
|
|
11
|
+
export function parseCursor(text) {
|
|
12
|
+
const separator = text.lastIndexOf(CURSOR_SEPARATOR);
|
|
13
|
+
if (separator <= 0 || separator === text.length - 1) {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
const updatedAt = text.slice(0, separator);
|
|
17
|
+
const number = text.slice(separator + 1);
|
|
18
|
+
if (!/^\d+$/.test(number) || Number.isNaN(Date.parse(updatedAt))) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
return { updatedAt, number: Number(number) };
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Order two Cursors: by the timestamp first, then by the issue number. The
|
|
25
|
+
* timestamp compares byte-wise because GitHub renders every one of them the
|
|
26
|
+
* same way; the number compares as a number, since `#9` precedes `#10`.
|
|
27
|
+
*/
|
|
28
|
+
export function compareCursors(left, right) {
|
|
29
|
+
if (left.updatedAt < right.updatedAt) {
|
|
30
|
+
return -1;
|
|
31
|
+
}
|
|
32
|
+
if (left.updatedAt > right.updatedAt) {
|
|
33
|
+
return 1;
|
|
34
|
+
}
|
|
35
|
+
return left.number - right.number;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* A pull request is not an Event of this Source. GitHub lists both under
|
|
39
|
+
* `/issues`, and only the tracker half is what this Block subscribes to.
|
|
40
|
+
*/
|
|
41
|
+
export function isPullRequest(entry) {
|
|
42
|
+
return entry.pull_request !== undefined;
|
|
43
|
+
}
|
|
44
|
+
/** The two fields an Event must carry to be placed in the order. */
|
|
45
|
+
export function cursorOf(entry) {
|
|
46
|
+
const number = entry.number;
|
|
47
|
+
const updatedAt = entry.updated_at;
|
|
48
|
+
if (typeof number !== "number" || !Number.isInteger(number)) {
|
|
49
|
+
return { ok: false, reason: "no-cursor", detail: 'The issue carries no integer "number".' };
|
|
50
|
+
}
|
|
51
|
+
if (typeof updatedAt !== "string" || Number.isNaN(Date.parse(updatedAt))) {
|
|
52
|
+
return { ok: false, reason: "no-cursor", detail: `Issue #${number} carries no "updated_at".` };
|
|
53
|
+
}
|
|
54
|
+
return { ok: true, cursor: { updatedAt, number } };
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* What one scan consumes, in the order it consumes it. A malformed entry has
|
|
58
|
+
* no Cursor to place it in the order, so it is reported before the Deliveries.
|
|
59
|
+
*/
|
|
60
|
+
export function selectEvents(entries, since) {
|
|
61
|
+
const floor = since === undefined ? null : parseCursor(since);
|
|
62
|
+
const skips = [];
|
|
63
|
+
const events = [];
|
|
64
|
+
for (const entry of entries) {
|
|
65
|
+
if (entry === null || typeof entry !== "object" || Array.isArray(entry)) {
|
|
66
|
+
skips.push({
|
|
67
|
+
kind: "skip",
|
|
68
|
+
reason: "not-object",
|
|
69
|
+
detail: `The Source listed ${describe(entry)}, not an issue.`,
|
|
70
|
+
});
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
const issue = entry;
|
|
74
|
+
if (isPullRequest(issue)) {
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
const cursor = cursorOf(issue);
|
|
78
|
+
if (!cursor.ok) {
|
|
79
|
+
skips.push({ kind: "skip", reason: cursor.reason, detail: cursor.detail });
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
if (floor !== null && compareCursors(cursor.cursor, floor) <= 0) {
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
events.push({ cursor: cursor.cursor, text: formatCursor(cursor.cursor), payload: issue });
|
|
86
|
+
}
|
|
87
|
+
events.sort((left, right) => compareCursors(left.cursor, right.cursor));
|
|
88
|
+
return [
|
|
89
|
+
...skips,
|
|
90
|
+
...events.map((event) => ({ kind: "event", cursor: event.text, payload: event.payload })),
|
|
91
|
+
];
|
|
92
|
+
}
|
|
93
|
+
function describe(value) {
|
|
94
|
+
if (value === null) {
|
|
95
|
+
return "null";
|
|
96
|
+
}
|
|
97
|
+
if (Array.isArray(value)) {
|
|
98
|
+
return "an array";
|
|
99
|
+
}
|
|
100
|
+
return `a ${typeof value}`;
|
|
101
|
+
}
|
|
102
|
+
//# 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":"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"}
|