@fdcn/sourcefed 0.2.2 → 0.2.4
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 +2 -2
- package/dist/chunk-SKEBKW2L.js +12083 -0
- package/dist/chunk-UOTCX4ME.js +3963 -0
- package/dist/cli.js +19214 -5288
- package/dist/daemon.js +6911 -2
- package/dist/data/core/SKILL.md +10 -0
- package/dist/data/core/references/commands.md +1 -0
- package/dist/mcp.js +1 -1
- package/dist/opencode.js +1 -1
- package/dist/pi.js +1 -1
- package/dist/tui-compiled.mjs +4 -3650
- package/dist.dts/packages/cli/src/commands/daemon.d.ts +1 -0
- package/dist.dts/packages/cli/src/commands/mcp.d.ts +1 -0
- package/dist.dts/packages/cli/src/commands/monitor/ack.d.ts +2 -0
- package/dist.dts/packages/cli/src/commands/monitor/create.d.ts +2 -0
- package/dist.dts/packages/cli/src/commands/monitor/events.d.ts +2 -0
- package/dist.dts/packages/cli/src/commands/monitor/follow.d.ts +2 -0
- package/dist.dts/packages/cli/src/commands/monitor/index.d.ts +10 -0
- package/dist.dts/packages/cli/src/commands/monitor/list.d.ts +2 -0
- package/dist.dts/packages/cli/src/commands/monitor/logs.d.ts +2 -0
- package/dist.dts/packages/cli/src/commands/monitor/remove.d.ts +2 -0
- package/dist.dts/packages/cli/src/commands/monitor/sources.d.ts +2 -0
- package/dist.dts/packages/cli/src/commands/monitor/start.d.ts +2 -0
- package/dist.dts/packages/cli/src/commands/monitor/status.d.ts +2 -0
- package/dist.dts/packages/cli/src/commands/monitor/stop.d.ts +2 -0
- package/dist.dts/packages/cli/src/commands/monitor.d.ts +1 -0
- package/dist.dts/packages/cli/src/commands/setup.d.ts +1 -0
- package/dist.dts/packages/cli/src/follow.test.d.ts +1 -0
- package/dist.dts/packages/cli/src/utils/daemon.d.ts +2 -0
- package/dist.dts/packages/cli/src/utils/flags.d.ts +1 -0
- package/dist.dts/packages/cli/src/utils/format.d.ts +8 -0
- package/dist.dts/packages/cli/src/utils/net.d.ts +1 -0
- package/dist.dts/packages/cli/src/utils/setup.d.ts +2 -0
- package/dist.dts/packages/cli/src/utils/webhooks.d.ts +2 -0
- package/dist.dts/providers/github/src/utils/html-to-markdown.d.ts +1 -0
- package/dist.dts/providers/github/src/utils/html-to-markdown.test.d.ts +1 -0
- package/package.json +1 -1
package/dist/tui-compiled.mjs
CHANGED
|
@@ -8,3654 +8,7 @@ import { setProp as _$setProp2 } from "opentui:runtime-module:%40opentui%2Fsolid
|
|
|
8
8
|
import { createElement as _$createElement2 } from "opentui:runtime-module:%40opentui%2Fsolid";
|
|
9
9
|
import { createComponent as _$createComponent2 } from "opentui:runtime-module:%40opentui%2Fsolid";
|
|
10
10
|
import { createMemo as createMemo2, Show as Show2 } from "opentui:runtime-module:solid-js";
|
|
11
|
-
|
|
12
|
-
// packages/daemon/dist/index.js
|
|
13
|
-
import { link, mkdir, open, readFile, rename, rm, writeFile } from "node:fs/promises";
|
|
14
|
-
import os from "node:os";
|
|
15
|
-
import path from "node:path";
|
|
16
|
-
import { link as link2, mkdir as mkdir2, open as open2, readFile as readFile2, rename as rename2, rm as rm2, writeFile as writeFile2 } from "node:fs/promises";
|
|
17
|
-
import os2 from "node:os";
|
|
18
|
-
import path2 from "node:path";
|
|
19
|
-
import { inflateRawSync } from "node:zlib";
|
|
20
|
-
import { createHmac, timingSafeEqual } from "node:crypto";
|
|
21
|
-
import { link as link3, mkdir as mkdir3, open as open3, readFile as readFile3, rename as rename3, rm as rm3, writeFile as writeFile3 } from "node:fs/promises";
|
|
22
|
-
import os3 from "node:os";
|
|
23
|
-
import path3 from "node:path";
|
|
24
|
-
import { link as link4, mkdir as mkdir4, open as open4, readFile as readFile4, rename as rename4, rm as rm4, writeFile as writeFile4 } from "node:fs/promises";
|
|
25
|
-
import os4 from "node:os";
|
|
26
|
-
import path4 from "node:path";
|
|
27
|
-
import { createHmac as createHmac2 } from "node:crypto";
|
|
28
|
-
import { timingSafeEqual as timingSafeEqual2 } from "node:crypto";
|
|
29
|
-
import os5 from "node:os";
|
|
30
|
-
import path5 from "node:path";
|
|
31
|
-
import { createServer } from "node:http";
|
|
32
|
-
import { Readable } from "node:stream";
|
|
33
|
-
import { spawn } from "node:child_process";
|
|
34
|
-
import path6 from "node:path";
|
|
35
|
-
var EMOJI_REGEX = new RegExp("^(?:[\\u{1F1E6}-\\u{1F1FF}]{2}|\\u{1F3F4}[\\u{E0061}-\\u{E007A}]{2}[\\u{E0030}-\\u{E0039}\\u{E0061}-\\u{E007A}]{1,3}\\u{E007F}|(?:\\p{Emoji}\\uFE0F\\u20E3?|\\p{Emoji_Modifier_Base}\\p{Emoji_Modifier}?|(?![\\p{Emoji_Modifier_Base}\\u{1F1E6}-\\u{1F1FF}])\\p{Emoji_Presentation})(?:\\u200D(?:\\p{Emoji}\\uFE0F\\u20E3?|\\p{Emoji_Modifier_Base}\\p{Emoji_Modifier}?|(?![\\p{Emoji_Modifier_Base}\\u{1F1E6}-\\u{1F1FF}])\\p{Emoji_Presentation}))*)+$", "u");
|
|
36
|
-
var MAX_WEBHOOK_BODY_BYTES = 1024 * 1024;
|
|
37
|
-
var store$42;
|
|
38
|
-
var DEFAULT_CONFIG2 = {
|
|
39
|
-
lang: void 0,
|
|
40
|
-
message: void 0,
|
|
41
|
-
abortEarly: void 0,
|
|
42
|
-
abortPipeEarly: void 0
|
|
43
|
-
};
|
|
44
|
-
// @__NO_SIDE_EFFECTS__
|
|
45
|
-
function getGlobalConfig2(config$1) {
|
|
46
|
-
if (!config$1 && !store$42) return DEFAULT_CONFIG2;
|
|
47
|
-
return {
|
|
48
|
-
lang: config$1?.lang ?? store$42?.lang,
|
|
49
|
-
message: config$1?.message,
|
|
50
|
-
abortEarly: config$1?.abortEarly ?? store$42?.abortEarly,
|
|
51
|
-
abortPipeEarly: config$1?.abortPipeEarly ?? store$42?.abortPipeEarly
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
var store$32;
|
|
55
|
-
// @__NO_SIDE_EFFECTS__
|
|
56
|
-
function getGlobalMessage2(lang) {
|
|
57
|
-
return store$32?.get(lang);
|
|
58
|
-
}
|
|
59
|
-
var store$22;
|
|
60
|
-
// @__NO_SIDE_EFFECTS__
|
|
61
|
-
function getSchemaMessage2(lang) {
|
|
62
|
-
return store$22?.get(lang);
|
|
63
|
-
}
|
|
64
|
-
var store$12;
|
|
65
|
-
// @__NO_SIDE_EFFECTS__
|
|
66
|
-
function getSpecificMessage2(reference, lang) {
|
|
67
|
-
return store$12?.get(reference)?.get(lang);
|
|
68
|
-
}
|
|
69
|
-
// @__NO_SIDE_EFFECTS__
|
|
70
|
-
function _stringify2(input) {
|
|
71
|
-
const type = typeof input;
|
|
72
|
-
if (type === "string") return `"${input}"`;
|
|
73
|
-
if (type === "number" || type === "bigint" || type === "boolean") return `${input}`;
|
|
74
|
-
if (type === "object" || type === "function") return (input && Object.getPrototypeOf(input)?.constructor?.name) ?? "null";
|
|
75
|
-
return type;
|
|
76
|
-
}
|
|
77
|
-
function _addIssue2(context, label, dataset, config$1, other) {
|
|
78
|
-
const input = other && "input" in other ? other.input : dataset.value;
|
|
79
|
-
const expected = other?.expected ?? context.expects ?? null;
|
|
80
|
-
const received = other?.received ?? /* @__PURE__ */ _stringify2(input);
|
|
81
|
-
const issue = {
|
|
82
|
-
kind: context.kind,
|
|
83
|
-
type: context.type,
|
|
84
|
-
input,
|
|
85
|
-
expected,
|
|
86
|
-
received,
|
|
87
|
-
message: `Invalid ${label}: ${expected ? `Expected ${expected} but r` : "R"}eceived ${received}`,
|
|
88
|
-
requirement: context.requirement,
|
|
89
|
-
path: other?.path,
|
|
90
|
-
issues: other?.issues,
|
|
91
|
-
lang: config$1.lang,
|
|
92
|
-
abortEarly: config$1.abortEarly,
|
|
93
|
-
abortPipeEarly: config$1.abortPipeEarly
|
|
94
|
-
};
|
|
95
|
-
const isSchema = context.kind === "schema";
|
|
96
|
-
const message$1 = other?.message ?? context.message ?? /* @__PURE__ */ getSpecificMessage2(context.reference, issue.lang) ?? (isSchema ? /* @__PURE__ */ getSchemaMessage2(issue.lang) : null) ?? config$1.message ?? /* @__PURE__ */ getGlobalMessage2(issue.lang);
|
|
97
|
-
if (message$1 !== void 0) issue.message = typeof message$1 === "function" ? message$1(issue) : message$1;
|
|
98
|
-
if (isSchema) dataset.typed = false;
|
|
99
|
-
if (dataset.issues) dataset.issues.push(issue);
|
|
100
|
-
else dataset.issues = [issue];
|
|
101
|
-
}
|
|
102
|
-
var _standardCache2 = /* @__PURE__ */ new WeakMap();
|
|
103
|
-
// @__NO_SIDE_EFFECTS__
|
|
104
|
-
function _getStandardProps2(context) {
|
|
105
|
-
let cached = _standardCache2.get(context);
|
|
106
|
-
if (!cached) {
|
|
107
|
-
cached = {
|
|
108
|
-
version: 1,
|
|
109
|
-
vendor: "valibot",
|
|
110
|
-
validate(value$1) {
|
|
111
|
-
return context["~run"]({ value: value$1 }, /* @__PURE__ */ getGlobalConfig2());
|
|
112
|
-
}
|
|
113
|
-
};
|
|
114
|
-
_standardCache2.set(context, cached);
|
|
115
|
-
}
|
|
116
|
-
return cached;
|
|
117
|
-
}
|
|
118
|
-
var EMOJI_REGEX2 = new RegExp("^(?:[\\u{1F1E6}-\\u{1F1FF}]{2}|\\u{1F3F4}[\\u{E0061}-\\u{E007A}]{2}[\\u{E0030}-\\u{E0039}\\u{E0061}-\\u{E007A}]{1,3}\\u{E007F}|(?:\\p{Emoji}\\uFE0F\\u20E3?|\\p{Emoji_Modifier_Base}\\p{Emoji_Modifier}?|(?![\\p{Emoji_Modifier_Base}\\u{1F1E6}-\\u{1F1FF}])\\p{Emoji_Presentation})(?:\\u200D(?:\\p{Emoji}\\uFE0F\\u20E3?|\\p{Emoji_Modifier_Base}\\p{Emoji_Modifier}?|(?![\\p{Emoji_Modifier_Base}\\u{1F1E6}-\\u{1F1FF}])\\p{Emoji_Presentation}))*)+$", "u");
|
|
119
|
-
// @__NO_SIDE_EFFECTS__
|
|
120
|
-
function getFallback2(schema, dataset, config$1) {
|
|
121
|
-
return typeof schema.fallback === "function" ? schema.fallback(dataset, config$1) : schema.fallback;
|
|
122
|
-
}
|
|
123
|
-
// @__NO_SIDE_EFFECTS__
|
|
124
|
-
function getDefault2(schema, dataset, config$1) {
|
|
125
|
-
return typeof schema.default === "function" ? schema.default(dataset, config$1) : schema.default;
|
|
126
|
-
}
|
|
127
|
-
// @__NO_SIDE_EFFECTS__
|
|
128
|
-
function array2(item, message$1) {
|
|
129
|
-
return {
|
|
130
|
-
kind: "schema",
|
|
131
|
-
type: "array",
|
|
132
|
-
reference: array2,
|
|
133
|
-
expects: "Array",
|
|
134
|
-
async: false,
|
|
135
|
-
item,
|
|
136
|
-
message: message$1,
|
|
137
|
-
get "~standard"() {
|
|
138
|
-
return /* @__PURE__ */ _getStandardProps2(this);
|
|
139
|
-
},
|
|
140
|
-
"~run"(dataset, config$1) {
|
|
141
|
-
const input = dataset.value;
|
|
142
|
-
if (Array.isArray(input)) {
|
|
143
|
-
dataset.typed = true;
|
|
144
|
-
dataset.value = [];
|
|
145
|
-
for (let key = 0; key < input.length; key++) {
|
|
146
|
-
const value$1 = input[key];
|
|
147
|
-
const itemDataset = this.item["~run"]({ value: value$1 }, config$1);
|
|
148
|
-
if (itemDataset.issues) {
|
|
149
|
-
const pathItem = {
|
|
150
|
-
type: "array",
|
|
151
|
-
origin: "value",
|
|
152
|
-
input,
|
|
153
|
-
key,
|
|
154
|
-
value: value$1
|
|
155
|
-
};
|
|
156
|
-
for (const issue of itemDataset.issues) {
|
|
157
|
-
if (issue.path) issue.path.unshift(pathItem);
|
|
158
|
-
else issue.path = [pathItem];
|
|
159
|
-
dataset.issues?.push(issue);
|
|
160
|
-
}
|
|
161
|
-
if (!dataset.issues) dataset.issues = itemDataset.issues;
|
|
162
|
-
if (config$1.abortEarly) {
|
|
163
|
-
dataset.typed = false;
|
|
164
|
-
break;
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
if (!itemDataset.typed) dataset.typed = false;
|
|
168
|
-
dataset.value.push(itemDataset.value);
|
|
169
|
-
}
|
|
170
|
-
} else _addIssue2(this, "type", dataset, config$1);
|
|
171
|
-
return dataset;
|
|
172
|
-
}
|
|
173
|
-
};
|
|
174
|
-
}
|
|
175
|
-
// @__NO_SIDE_EFFECTS__
|
|
176
|
-
function boolean2(message$1) {
|
|
177
|
-
return {
|
|
178
|
-
kind: "schema",
|
|
179
|
-
type: "boolean",
|
|
180
|
-
reference: boolean2,
|
|
181
|
-
expects: "boolean",
|
|
182
|
-
async: false,
|
|
183
|
-
message: message$1,
|
|
184
|
-
get "~standard"() {
|
|
185
|
-
return /* @__PURE__ */ _getStandardProps2(this);
|
|
186
|
-
},
|
|
187
|
-
"~run"(dataset, config$1) {
|
|
188
|
-
if (typeof dataset.value === "boolean") dataset.typed = true;
|
|
189
|
-
else _addIssue2(this, "type", dataset, config$1);
|
|
190
|
-
return dataset;
|
|
191
|
-
}
|
|
192
|
-
};
|
|
193
|
-
}
|
|
194
|
-
// @__NO_SIDE_EFFECTS__
|
|
195
|
-
function object2(entries$1, message$1) {
|
|
196
|
-
return {
|
|
197
|
-
kind: "schema",
|
|
198
|
-
type: "object",
|
|
199
|
-
reference: object2,
|
|
200
|
-
expects: "Object",
|
|
201
|
-
async: false,
|
|
202
|
-
entries: entries$1,
|
|
203
|
-
message: message$1,
|
|
204
|
-
get "~standard"() {
|
|
205
|
-
return /* @__PURE__ */ _getStandardProps2(this);
|
|
206
|
-
},
|
|
207
|
-
"~run"(dataset, config$1) {
|
|
208
|
-
const input = dataset.value;
|
|
209
|
-
if (input && typeof input === "object") {
|
|
210
|
-
dataset.typed = true;
|
|
211
|
-
dataset.value = {};
|
|
212
|
-
for (const key in this.entries) {
|
|
213
|
-
const valueSchema = this.entries[key];
|
|
214
|
-
if (key in input || (valueSchema.type === "exact_optional" || valueSchema.type === "optional" || valueSchema.type === "nullish") && valueSchema.default !== void 0) {
|
|
215
|
-
const value$1 = key in input ? input[key] : /* @__PURE__ */ getDefault2(valueSchema);
|
|
216
|
-
const valueDataset = valueSchema["~run"]({ value: value$1 }, config$1);
|
|
217
|
-
if (valueDataset.issues) {
|
|
218
|
-
const pathItem = {
|
|
219
|
-
type: "object",
|
|
220
|
-
origin: "value",
|
|
221
|
-
input,
|
|
222
|
-
key,
|
|
223
|
-
value: value$1
|
|
224
|
-
};
|
|
225
|
-
for (const issue of valueDataset.issues) {
|
|
226
|
-
if (issue.path) issue.path.unshift(pathItem);
|
|
227
|
-
else issue.path = [pathItem];
|
|
228
|
-
dataset.issues?.push(issue);
|
|
229
|
-
}
|
|
230
|
-
if (!dataset.issues) dataset.issues = valueDataset.issues;
|
|
231
|
-
if (config$1.abortEarly) {
|
|
232
|
-
dataset.typed = false;
|
|
233
|
-
break;
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
if (!valueDataset.typed) dataset.typed = false;
|
|
237
|
-
dataset.value[key] = valueDataset.value;
|
|
238
|
-
} else if (valueSchema.fallback !== void 0) dataset.value[key] = /* @__PURE__ */ getFallback2(valueSchema);
|
|
239
|
-
else if (valueSchema.type !== "exact_optional" && valueSchema.type !== "optional" && valueSchema.type !== "nullish") {
|
|
240
|
-
_addIssue2(this, "key", dataset, config$1, {
|
|
241
|
-
input: void 0,
|
|
242
|
-
expected: `"${key}"`,
|
|
243
|
-
path: [{
|
|
244
|
-
type: "object",
|
|
245
|
-
origin: "key",
|
|
246
|
-
input,
|
|
247
|
-
key,
|
|
248
|
-
value: input[key]
|
|
249
|
-
}]
|
|
250
|
-
});
|
|
251
|
-
if (config$1.abortEarly) break;
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
} else _addIssue2(this, "type", dataset, config$1);
|
|
255
|
-
return dataset;
|
|
256
|
-
}
|
|
257
|
-
};
|
|
258
|
-
}
|
|
259
|
-
// @__NO_SIDE_EFFECTS__
|
|
260
|
-
function optional(wrapped, default_) {
|
|
261
|
-
return {
|
|
262
|
-
kind: "schema",
|
|
263
|
-
type: "optional",
|
|
264
|
-
reference: optional,
|
|
265
|
-
expects: `(${wrapped.expects} | undefined)`,
|
|
266
|
-
async: false,
|
|
267
|
-
wrapped,
|
|
268
|
-
default: default_,
|
|
269
|
-
get "~standard"() {
|
|
270
|
-
return /* @__PURE__ */ _getStandardProps2(this);
|
|
271
|
-
},
|
|
272
|
-
"~run"(dataset, config$1) {
|
|
273
|
-
if (dataset.value === void 0) {
|
|
274
|
-
if (this.default !== void 0) dataset.value = /* @__PURE__ */ getDefault2(this, dataset, config$1);
|
|
275
|
-
if (dataset.value === void 0) {
|
|
276
|
-
dataset.typed = true;
|
|
277
|
-
return dataset;
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
return this.wrapped["~run"](dataset, config$1);
|
|
281
|
-
}
|
|
282
|
-
};
|
|
283
|
-
}
|
|
284
|
-
// @__NO_SIDE_EFFECTS__
|
|
285
|
-
function string2(message$1) {
|
|
286
|
-
return {
|
|
287
|
-
kind: "schema",
|
|
288
|
-
type: "string",
|
|
289
|
-
reference: string2,
|
|
290
|
-
expects: "string",
|
|
291
|
-
async: false,
|
|
292
|
-
message: message$1,
|
|
293
|
-
get "~standard"() {
|
|
294
|
-
return /* @__PURE__ */ _getStandardProps2(this);
|
|
295
|
-
},
|
|
296
|
-
"~run"(dataset, config$1) {
|
|
297
|
-
if (typeof dataset.value === "string") dataset.typed = true;
|
|
298
|
-
else _addIssue2(this, "type", dataset, config$1);
|
|
299
|
-
return dataset;
|
|
300
|
-
}
|
|
301
|
-
};
|
|
302
|
-
}
|
|
303
|
-
// @__NO_SIDE_EFFECTS__
|
|
304
|
-
function unknown2() {
|
|
305
|
-
return {
|
|
306
|
-
kind: "schema",
|
|
307
|
-
type: "unknown",
|
|
308
|
-
reference: unknown2,
|
|
309
|
-
expects: "unknown",
|
|
310
|
-
async: false,
|
|
311
|
-
get "~standard"() {
|
|
312
|
-
return /* @__PURE__ */ _getStandardProps2(this);
|
|
313
|
-
},
|
|
314
|
-
"~run"(dataset) {
|
|
315
|
-
dataset.typed = true;
|
|
316
|
-
return dataset;
|
|
317
|
-
}
|
|
318
|
-
};
|
|
319
|
-
}
|
|
320
|
-
// @__NO_SIDE_EFFECTS__
|
|
321
|
-
function safeParse2(schema, input, config$1) {
|
|
322
|
-
const dataset = schema["~run"]({ value: input }, /* @__PURE__ */ getGlobalConfig2(config$1));
|
|
323
|
-
return {
|
|
324
|
-
typed: dataset.typed,
|
|
325
|
-
success: !dataset.issues,
|
|
326
|
-
output: dataset.value,
|
|
327
|
-
issues: dataset.issues
|
|
328
|
-
};
|
|
329
|
-
}
|
|
330
|
-
var Monitor = class {
|
|
331
|
-
type;
|
|
332
|
-
schema;
|
|
333
|
-
poll;
|
|
334
|
-
webhook;
|
|
335
|
-
constructor(options) {
|
|
336
|
-
this.type = options.type;
|
|
337
|
-
this.schema = options.schema;
|
|
338
|
-
}
|
|
339
|
-
validateSource(source) {
|
|
340
|
-
const result = /* @__PURE__ */ safeParse2(this.schema, source);
|
|
341
|
-
if (result.success) return result.output;
|
|
342
|
-
throw new Error(`invalid ${this.type} monitor source`);
|
|
343
|
-
}
|
|
344
|
-
initialDelivery(source) {
|
|
345
|
-
this.validateSource(source);
|
|
346
|
-
if (this.webhook && this.webhook.preferred && this.webhook.configured()) return "webhook";
|
|
347
|
-
if (this.poll) return "poll";
|
|
348
|
-
if (this.webhook) return "webhook";
|
|
349
|
-
throw new Error(`source ${this.type} has no configured transport`);
|
|
350
|
-
}
|
|
351
|
-
resolveDelivery(monitor) {
|
|
352
|
-
let webhookHealthy = false;
|
|
353
|
-
if (this.webhook) webhookHealthy = this.webhook.isHealthy(monitor);
|
|
354
|
-
if (monitor.delivery === "webhook") {
|
|
355
|
-
if (this.webhook && webhookHealthy) return "webhook";
|
|
356
|
-
if (this.poll) return "poll";
|
|
357
|
-
if (this.webhook) return "webhook";
|
|
358
|
-
return void 0;
|
|
359
|
-
}
|
|
360
|
-
if (this.webhook && webhookHealthy) return "webhook";
|
|
361
|
-
if (this.poll) return "poll";
|
|
362
|
-
if (this.webhook) return "webhook";
|
|
363
|
-
return void 0;
|
|
364
|
-
}
|
|
365
|
-
async tick(context, record2) {
|
|
366
|
-
const fresh = await context.service.get(record2.id);
|
|
367
|
-
if (!fresh || !fresh.enabled) return 0;
|
|
368
|
-
if (this.webhook) await this.webhook.retryPending(context, this, fresh);
|
|
369
|
-
const current = await context.service.get(record2.id);
|
|
370
|
-
if (!current || !current.enabled) return 0;
|
|
371
|
-
const nextDelivery = this.resolveDelivery(current);
|
|
372
|
-
if (!nextDelivery) return 0;
|
|
373
|
-
if (nextDelivery !== current.delivery) {
|
|
374
|
-
await context.service.setDelivery(current.id, nextDelivery);
|
|
375
|
-
current.delivery = nextDelivery;
|
|
376
|
-
}
|
|
377
|
-
if (current.delivery !== "poll" || !this.poll) return 0;
|
|
378
|
-
const lastAttemptAt = Number(current.cursors.__lastAttemptAt ?? current.cursors.__lastPolledAt ?? 0);
|
|
379
|
-
const pollIntervalSec = current.pollIntervalSec || 60;
|
|
380
|
-
if (lastAttemptAt && Date.now() - lastAttemptAt < pollIntervalSec * 1e3) return 0;
|
|
381
|
-
return this.poll.run(context, this, current);
|
|
382
|
-
}
|
|
383
|
-
async deliver(context, record2, event, deliveryId) {
|
|
384
|
-
if (!this.webhook) return 0;
|
|
385
|
-
return this.webhook.deliver(context, this, record2, event, deliveryId);
|
|
386
|
-
}
|
|
387
|
-
unresponsive(record2, now = Date.now()) {
|
|
388
|
-
if (!record2.enabled) return false;
|
|
389
|
-
if (record2.delivery === "poll") {
|
|
390
|
-
if (!this.poll) return true;
|
|
391
|
-
return this.poll.isUnresponsive(record2, now);
|
|
392
|
-
}
|
|
393
|
-
if (!this.webhook) return true;
|
|
394
|
-
return this.webhook.isUnresponsive(record2, now);
|
|
395
|
-
}
|
|
396
|
-
};
|
|
397
|
-
var RoutedEventCursorSchema = /* @__PURE__ */ array2(/* @__PURE__ */ string2());
|
|
398
|
-
function eventDeliveryId(event) {
|
|
399
|
-
if (event.id) return event.id;
|
|
400
|
-
return `${event.kind}:${event.at}:${event.summary}`;
|
|
401
|
-
}
|
|
402
|
-
var activePolls = /* @__PURE__ */ new Set();
|
|
403
|
-
var PollMonitor = class {
|
|
404
|
-
constructor(options) {
|
|
405
|
-
this.options = options;
|
|
406
|
-
}
|
|
407
|
-
async run(context, source, record2) {
|
|
408
|
-
if (activePolls.has(record2.id)) return 0;
|
|
409
|
-
activePolls.add(record2.id);
|
|
410
|
-
try {
|
|
411
|
-
const fresh = await context.service.get(record2.id);
|
|
412
|
-
if (!fresh) return 0;
|
|
413
|
-
const sourceRecord = source.validateSource(fresh.source);
|
|
414
|
-
const cursorKey = source.key(sourceRecord);
|
|
415
|
-
const result = await this.options.run(sourceRecord, fresh.cursors[cursorKey]);
|
|
416
|
-
const current = await context.service.get(record2.id);
|
|
417
|
-
if (!current || !current.enabled) return 0;
|
|
418
|
-
const parsedRoutedIds = /* @__PURE__ */ safeParse2(RoutedEventCursorSchema, fresh.cursors.__routedEventIds);
|
|
419
|
-
let routedIds = [];
|
|
420
|
-
if (parsedRoutedIds.success) routedIds = parsedRoutedIds.output;
|
|
421
|
-
let routeFailed = false;
|
|
422
|
-
for (const event of result.events) {
|
|
423
|
-
const eventId = eventDeliveryId(event);
|
|
424
|
-
if (routedIds.includes(eventId)) continue;
|
|
425
|
-
const routed = await context.sink.deliver({ monitor: fresh, event });
|
|
426
|
-
if (!routed.ok) {
|
|
427
|
-
routeFailed = true;
|
|
428
|
-
console.error(`[sourcefed] route failed for ${fresh.id}: ${routed.error}`);
|
|
429
|
-
continue;
|
|
430
|
-
}
|
|
431
|
-
if (!routedIds.includes(eventId)) routedIds.push(eventId);
|
|
432
|
-
}
|
|
433
|
-
if (routeFailed) {
|
|
434
|
-
await context.service.updateCursor(fresh, "__routedEventIds", routedIds);
|
|
435
|
-
return 0;
|
|
436
|
-
}
|
|
437
|
-
await context.service.updateCursorValue(fresh, cursorKey, (current2) => {
|
|
438
|
-
if (this.options.mergeCursor) return this.options.mergeCursor(current2, result.cursor);
|
|
439
|
-
return result.cursor;
|
|
440
|
-
});
|
|
441
|
-
await context.service.updateCursor(fresh, "__routedEventIds", []);
|
|
442
|
-
if (result.terminal) await context.service.remove(fresh.id);
|
|
443
|
-
await context.service.updateCursor(fresh, "__lastPolledAt", Date.now());
|
|
444
|
-
return result.events.length;
|
|
445
|
-
} finally {
|
|
446
|
-
activePolls.delete(record2.id);
|
|
447
|
-
}
|
|
448
|
-
}
|
|
449
|
-
isUnresponsive(record2, now) {
|
|
450
|
-
const intervalMs = Math.max((record2.pollIntervalSec || 60) * 3e3, 12e4);
|
|
451
|
-
const lastPolledAt = Number(record2.cursors.__lastPolledAt ?? 0);
|
|
452
|
-
if (lastPolledAt > 0) return now - lastPolledAt > intervalMs;
|
|
453
|
-
return now - Date.parse(record2.createdAt) > intervalMs;
|
|
454
|
-
}
|
|
455
|
-
};
|
|
456
|
-
function isRecord(value) {
|
|
457
|
-
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
458
|
-
}
|
|
459
|
-
function mergeCursors(current, result) {
|
|
460
|
-
if (Array.isArray(current) && Array.isArray(result)) {
|
|
461
|
-
return [.../* @__PURE__ */ new Set([...current, ...result])];
|
|
462
|
-
}
|
|
463
|
-
if (isRecord(current) && isRecord(result)) {
|
|
464
|
-
const merged = { ...current };
|
|
465
|
-
for (const [key, value] of Object.entries(result)) {
|
|
466
|
-
if (value === void 0) continue;
|
|
467
|
-
merged[key] = key in current ? mergeCursors(current[key], value) : value;
|
|
468
|
-
}
|
|
469
|
-
return merged;
|
|
470
|
-
}
|
|
471
|
-
return result === void 0 ? current : result;
|
|
472
|
-
}
|
|
473
|
-
var WEBHOOK_STALE_MS = 9e4;
|
|
474
|
-
var WEBHOOK_STARTUP_GRACE_MS = 12e4;
|
|
475
|
-
var PendingWebhookEventSchema = /* @__PURE__ */ object2({
|
|
476
|
-
deliveryId: /* @__PURE__ */ string2(),
|
|
477
|
-
event: /* @__PURE__ */ object2({
|
|
478
|
-
source: /* @__PURE__ */ unknown2(),
|
|
479
|
-
kind: /* @__PURE__ */ string2(),
|
|
480
|
-
id: /* @__PURE__ */ optional(/* @__PURE__ */ string2()),
|
|
481
|
-
at: /* @__PURE__ */ string2(),
|
|
482
|
-
summary: /* @__PURE__ */ string2(),
|
|
483
|
-
body: /* @__PURE__ */ optional(/* @__PURE__ */ string2()),
|
|
484
|
-
actionable: /* @__PURE__ */ boolean2(),
|
|
485
|
-
terminal: /* @__PURE__ */ optional(/* @__PURE__ */ boolean2())
|
|
486
|
-
})
|
|
487
|
-
});
|
|
488
|
-
var PendingWebhookEventsSchema = /* @__PURE__ */ array2(PendingWebhookEventSchema);
|
|
489
|
-
var pendingDeliveries = /* @__PURE__ */ new Set();
|
|
490
|
-
var PENDING_WEBHOOK_EVENTS = "__pendingWebhookEvents";
|
|
491
|
-
var WebhookMonitor = class {
|
|
492
|
-
path;
|
|
493
|
-
preferred;
|
|
494
|
-
configured;
|
|
495
|
-
verify;
|
|
496
|
-
acknowledgeBeforeDelivery;
|
|
497
|
-
challenge;
|
|
498
|
-
deliveryId;
|
|
499
|
-
eventName;
|
|
500
|
-
parse;
|
|
501
|
-
updateCursor;
|
|
502
|
-
constructor(options) {
|
|
503
|
-
this.path = options.path;
|
|
504
|
-
this.preferred = options.preferred ?? true;
|
|
505
|
-
this.configured = options.configured;
|
|
506
|
-
this.verify = options.verify;
|
|
507
|
-
this.acknowledgeBeforeDelivery = options.acknowledgeBeforeDelivery ?? false;
|
|
508
|
-
this.challenge = options.challenge;
|
|
509
|
-
this.deliveryId = options.deliveryId;
|
|
510
|
-
this.eventName = options.eventName;
|
|
511
|
-
this.parse = options.parse;
|
|
512
|
-
this.updateCursor = options.updateCursor;
|
|
513
|
-
}
|
|
514
|
-
isHealthy(record2) {
|
|
515
|
-
if (!this.preferred || !this.configured()) return false;
|
|
516
|
-
const heartbeatAt = Number(record2.cursors.__webhookHeartbeatAt ?? 0);
|
|
517
|
-
if (heartbeatAt > 0) return Date.now() - heartbeatAt <= WEBHOOK_STALE_MS;
|
|
518
|
-
return Date.now() - Date.parse(record2.createdAt) <= WEBHOOK_STARTUP_GRACE_MS;
|
|
519
|
-
}
|
|
520
|
-
isUnresponsive(record2, now) {
|
|
521
|
-
const heartbeatAt = Number(record2.cursors.__webhookHeartbeatAt ?? 0);
|
|
522
|
-
if (heartbeatAt > 0) return now - heartbeatAt > WEBHOOK_STALE_MS;
|
|
523
|
-
return now - Date.parse(record2.createdAt) > WEBHOOK_STARTUP_GRACE_MS;
|
|
524
|
-
}
|
|
525
|
-
async retryPending(context, source, record2) {
|
|
526
|
-
const fresh = await context.service.get(record2.id);
|
|
527
|
-
if (!fresh || !fresh.enabled) return 0;
|
|
528
|
-
const parsed = /* @__PURE__ */ safeParse2(PendingWebhookEventsSchema, fresh.cursors[PENDING_WEBHOOK_EVENTS]);
|
|
529
|
-
if (!parsed.success) return 0;
|
|
530
|
-
let delivered = 0;
|
|
531
|
-
for (const pending of parsed.output) {
|
|
532
|
-
const current = await context.service.get(record2.id);
|
|
533
|
-
if (!current || !current.enabled) break;
|
|
534
|
-
const cursorKey = `webhook:${pending.deliveryId}`;
|
|
535
|
-
if (current.cursors[cursorKey]) {
|
|
536
|
-
await this.removePending(context, current, pending.deliveryId);
|
|
537
|
-
continue;
|
|
538
|
-
}
|
|
539
|
-
delivered += await this.deliver(context, source, current, pending.event, pending.deliveryId);
|
|
540
|
-
}
|
|
541
|
-
return delivered;
|
|
542
|
-
}
|
|
543
|
-
async addPending(context, monitor, deliveryId, event) {
|
|
544
|
-
await context.service.updateCursorValue(monitor, PENDING_WEBHOOK_EVENTS, (cursor) => {
|
|
545
|
-
const parsed = /* @__PURE__ */ safeParse2(PendingWebhookEventsSchema, cursor);
|
|
546
|
-
let pending = [];
|
|
547
|
-
if (parsed.success) pending = parsed.output;
|
|
548
|
-
if (pending.some((entry) => entry.deliveryId === deliveryId)) return pending;
|
|
549
|
-
pending.push({ deliveryId, event });
|
|
550
|
-
return pending;
|
|
551
|
-
});
|
|
552
|
-
}
|
|
553
|
-
async removePending(context, monitor, deliveryId) {
|
|
554
|
-
await context.service.updateCursorValue(monitor, PENDING_WEBHOOK_EVENTS, (cursor) => {
|
|
555
|
-
const parsed = /* @__PURE__ */ safeParse2(PendingWebhookEventsSchema, cursor);
|
|
556
|
-
if (!parsed.success) return [];
|
|
557
|
-
return parsed.output.filter((entry) => entry.deliveryId !== deliveryId);
|
|
558
|
-
});
|
|
559
|
-
}
|
|
560
|
-
async deliver(context, source, record2, event, deliveryId) {
|
|
561
|
-
const fresh = await context.service.get(record2.id);
|
|
562
|
-
if (!fresh || !fresh.enabled) return 0;
|
|
563
|
-
const freshSource = source.validateSource(fresh.source);
|
|
564
|
-
const eventSource = source.validateSource(event.source);
|
|
565
|
-
if (source.key(freshSource) !== source.key(eventSource)) return 0;
|
|
566
|
-
if (event.kind === "ci" && !event.actionable) return 0;
|
|
567
|
-
const cursorKey = `webhook:${deliveryId}`;
|
|
568
|
-
const reservationKey = `${fresh.id}:${deliveryId}`;
|
|
569
|
-
if (pendingDeliveries.has(reservationKey)) return 0;
|
|
570
|
-
if (fresh.cursors[cursorKey]) {
|
|
571
|
-
await this.removePending(context, fresh, deliveryId);
|
|
572
|
-
return 0;
|
|
573
|
-
}
|
|
574
|
-
pendingDeliveries.add(reservationKey);
|
|
575
|
-
try {
|
|
576
|
-
await this.addPending(context, fresh, deliveryId, event);
|
|
577
|
-
if (this.updateCursor) {
|
|
578
|
-
const sourceCursorKey = source.key(freshSource);
|
|
579
|
-
await context.service.updateCursorValue(fresh, sourceCursorKey, (cursor) => this.updateCursor(event, cursor));
|
|
580
|
-
}
|
|
581
|
-
const result = await context.sink.deliver({ monitor: fresh, event });
|
|
582
|
-
if (!result.ok) {
|
|
583
|
-
console.error(`[sourcefed] webhook route failed for ${fresh.id}: ${result.error}`);
|
|
584
|
-
return 0;
|
|
585
|
-
}
|
|
586
|
-
await context.service.setDelivery(fresh.id, "webhook");
|
|
587
|
-
await context.service.updateCursor(fresh, cursorKey, true);
|
|
588
|
-
await this.removePending(context, fresh, deliveryId);
|
|
589
|
-
if (event.terminal) await context.service.remove(fresh.id);
|
|
590
|
-
return 1;
|
|
591
|
-
} finally {
|
|
592
|
-
pendingDeliveries.delete(reservationKey);
|
|
593
|
-
}
|
|
594
|
-
}
|
|
595
|
-
};
|
|
596
|
-
var MAX_WEBHOOK_BODY_BYTES2 = 1024 * 1024;
|
|
597
|
-
function toMonitorEvent(event, source) {
|
|
598
|
-
return {
|
|
599
|
-
source,
|
|
600
|
-
kind: event.kind,
|
|
601
|
-
id: event.id,
|
|
602
|
-
at: event.at,
|
|
603
|
-
summary: event.summary,
|
|
604
|
-
body: event.body,
|
|
605
|
-
actionable: event.actionable,
|
|
606
|
-
terminal: event.terminal
|
|
607
|
-
};
|
|
608
|
-
}
|
|
609
|
-
var store$422;
|
|
610
|
-
var DEFAULT_CONFIG22 = {
|
|
611
|
-
lang: void 0,
|
|
612
|
-
message: void 0,
|
|
613
|
-
abortEarly: void 0,
|
|
614
|
-
abortPipeEarly: void 0
|
|
615
|
-
};
|
|
616
|
-
// @__NO_SIDE_EFFECTS__
|
|
617
|
-
function getGlobalConfig22(config$1) {
|
|
618
|
-
if (!config$1 && !store$422) return DEFAULT_CONFIG22;
|
|
619
|
-
return {
|
|
620
|
-
lang: config$1?.lang ?? store$422?.lang,
|
|
621
|
-
message: config$1?.message,
|
|
622
|
-
abortEarly: config$1?.abortEarly ?? store$422?.abortEarly,
|
|
623
|
-
abortPipeEarly: config$1?.abortPipeEarly ?? store$422?.abortPipeEarly
|
|
624
|
-
};
|
|
625
|
-
}
|
|
626
|
-
var store$322;
|
|
627
|
-
// @__NO_SIDE_EFFECTS__
|
|
628
|
-
function getGlobalMessage22(lang) {
|
|
629
|
-
return store$322?.get(lang);
|
|
630
|
-
}
|
|
631
|
-
var store$222;
|
|
632
|
-
// @__NO_SIDE_EFFECTS__
|
|
633
|
-
function getSchemaMessage22(lang) {
|
|
634
|
-
return store$222?.get(lang);
|
|
635
|
-
}
|
|
636
|
-
var store$122;
|
|
637
|
-
// @__NO_SIDE_EFFECTS__
|
|
638
|
-
function getSpecificMessage22(reference, lang) {
|
|
639
|
-
return store$122?.get(reference)?.get(lang);
|
|
640
|
-
}
|
|
641
|
-
// @__NO_SIDE_EFFECTS__
|
|
642
|
-
function _stringify22(input) {
|
|
643
|
-
const type = typeof input;
|
|
644
|
-
if (type === "string") return `"${input}"`;
|
|
645
|
-
if (type === "number" || type === "bigint" || type === "boolean") return `${input}`;
|
|
646
|
-
if (type === "object" || type === "function") return (input && Object.getPrototypeOf(input)?.constructor?.name) ?? "null";
|
|
647
|
-
return type;
|
|
648
|
-
}
|
|
649
|
-
function _addIssue22(context, label, dataset, config$1, other) {
|
|
650
|
-
const input = other && "input" in other ? other.input : dataset.value;
|
|
651
|
-
const expected = other?.expected ?? context.expects ?? null;
|
|
652
|
-
const received = other?.received ?? /* @__PURE__ */ _stringify22(input);
|
|
653
|
-
const issue = {
|
|
654
|
-
kind: context.kind,
|
|
655
|
-
type: context.type,
|
|
656
|
-
input,
|
|
657
|
-
expected,
|
|
658
|
-
received,
|
|
659
|
-
message: `Invalid ${label}: ${expected ? `Expected ${expected} but r` : "R"}eceived ${received}`,
|
|
660
|
-
requirement: context.requirement,
|
|
661
|
-
path: other?.path,
|
|
662
|
-
issues: other?.issues,
|
|
663
|
-
lang: config$1.lang,
|
|
664
|
-
abortEarly: config$1.abortEarly,
|
|
665
|
-
abortPipeEarly: config$1.abortPipeEarly
|
|
666
|
-
};
|
|
667
|
-
const isSchema = context.kind === "schema";
|
|
668
|
-
const message$1 = other?.message ?? context.message ?? /* @__PURE__ */ getSpecificMessage22(context.reference, issue.lang) ?? (isSchema ? /* @__PURE__ */ getSchemaMessage22(issue.lang) : null) ?? config$1.message ?? /* @__PURE__ */ getGlobalMessage22(issue.lang);
|
|
669
|
-
if (message$1 !== void 0) issue.message = typeof message$1 === "function" ? message$1(issue) : message$1;
|
|
670
|
-
if (isSchema) dataset.typed = false;
|
|
671
|
-
if (dataset.issues) dataset.issues.push(issue);
|
|
672
|
-
else dataset.issues = [issue];
|
|
673
|
-
}
|
|
674
|
-
var _standardCache22 = /* @__PURE__ */ new WeakMap();
|
|
675
|
-
// @__NO_SIDE_EFFECTS__
|
|
676
|
-
function _getStandardProps22(context) {
|
|
677
|
-
let cached = _standardCache22.get(context);
|
|
678
|
-
if (!cached) {
|
|
679
|
-
cached = {
|
|
680
|
-
version: 1,
|
|
681
|
-
vendor: "valibot",
|
|
682
|
-
validate(value$1) {
|
|
683
|
-
return context["~run"]({ value: value$1 }, /* @__PURE__ */ getGlobalConfig22());
|
|
684
|
-
}
|
|
685
|
-
};
|
|
686
|
-
_standardCache22.set(context, cached);
|
|
687
|
-
}
|
|
688
|
-
return cached;
|
|
689
|
-
}
|
|
690
|
-
var EMOJI_REGEX22 = new RegExp("^(?:[\\u{1F1E6}-\\u{1F1FF}]{2}|\\u{1F3F4}[\\u{E0061}-\\u{E007A}]{2}[\\u{E0030}-\\u{E0039}\\u{E0061}-\\u{E007A}]{1,3}\\u{E007F}|(?:\\p{Emoji}\\uFE0F\\u20E3?|\\p{Emoji_Modifier_Base}\\p{Emoji_Modifier}?|(?![\\p{Emoji_Modifier_Base}\\u{1F1E6}-\\u{1F1FF}])\\p{Emoji_Presentation})(?:\\u200D(?:\\p{Emoji}\\uFE0F\\u20E3?|\\p{Emoji_Modifier_Base}\\p{Emoji_Modifier}?|(?![\\p{Emoji_Modifier_Base}\\u{1F1E6}-\\u{1F1FF}])\\p{Emoji_Presentation}))*)+$", "u");
|
|
691
|
-
// @__NO_SIDE_EFFECTS__
|
|
692
|
-
function getFallback22(schema, dataset, config$1) {
|
|
693
|
-
return typeof schema.fallback === "function" ? schema.fallback(dataset, config$1) : schema.fallback;
|
|
694
|
-
}
|
|
695
|
-
// @__NO_SIDE_EFFECTS__
|
|
696
|
-
function getDefault22(schema, dataset, config$1) {
|
|
697
|
-
return typeof schema.default === "function" ? schema.default(dataset, config$1) : schema.default;
|
|
698
|
-
}
|
|
699
|
-
// @__NO_SIDE_EFFECTS__
|
|
700
|
-
function array22(item, message$1) {
|
|
701
|
-
return {
|
|
702
|
-
kind: "schema",
|
|
703
|
-
type: "array",
|
|
704
|
-
reference: array22,
|
|
705
|
-
expects: "Array",
|
|
706
|
-
async: false,
|
|
707
|
-
item,
|
|
708
|
-
message: message$1,
|
|
709
|
-
get "~standard"() {
|
|
710
|
-
return /* @__PURE__ */ _getStandardProps22(this);
|
|
711
|
-
},
|
|
712
|
-
"~run"(dataset, config$1) {
|
|
713
|
-
const input = dataset.value;
|
|
714
|
-
if (Array.isArray(input)) {
|
|
715
|
-
dataset.typed = true;
|
|
716
|
-
dataset.value = [];
|
|
717
|
-
for (let key = 0; key < input.length; key++) {
|
|
718
|
-
const value$1 = input[key];
|
|
719
|
-
const itemDataset = this.item["~run"]({ value: value$1 }, config$1);
|
|
720
|
-
if (itemDataset.issues) {
|
|
721
|
-
const pathItem = {
|
|
722
|
-
type: "array",
|
|
723
|
-
origin: "value",
|
|
724
|
-
input,
|
|
725
|
-
key,
|
|
726
|
-
value: value$1
|
|
727
|
-
};
|
|
728
|
-
for (const issue of itemDataset.issues) {
|
|
729
|
-
if (issue.path) issue.path.unshift(pathItem);
|
|
730
|
-
else issue.path = [pathItem];
|
|
731
|
-
dataset.issues?.push(issue);
|
|
732
|
-
}
|
|
733
|
-
if (!dataset.issues) dataset.issues = itemDataset.issues;
|
|
734
|
-
if (config$1.abortEarly) {
|
|
735
|
-
dataset.typed = false;
|
|
736
|
-
break;
|
|
737
|
-
}
|
|
738
|
-
}
|
|
739
|
-
if (!itemDataset.typed) dataset.typed = false;
|
|
740
|
-
dataset.value.push(itemDataset.value);
|
|
741
|
-
}
|
|
742
|
-
} else _addIssue22(this, "type", dataset, config$1);
|
|
743
|
-
return dataset;
|
|
744
|
-
}
|
|
745
|
-
};
|
|
746
|
-
}
|
|
747
|
-
// @__NO_SIDE_EFFECTS__
|
|
748
|
-
function boolean22(message$1) {
|
|
749
|
-
return {
|
|
750
|
-
kind: "schema",
|
|
751
|
-
type: "boolean",
|
|
752
|
-
reference: boolean22,
|
|
753
|
-
expects: "boolean",
|
|
754
|
-
async: false,
|
|
755
|
-
message: message$1,
|
|
756
|
-
get "~standard"() {
|
|
757
|
-
return /* @__PURE__ */ _getStandardProps22(this);
|
|
758
|
-
},
|
|
759
|
-
"~run"(dataset, config$1) {
|
|
760
|
-
if (typeof dataset.value === "boolean") dataset.typed = true;
|
|
761
|
-
else _addIssue22(this, "type", dataset, config$1);
|
|
762
|
-
return dataset;
|
|
763
|
-
}
|
|
764
|
-
};
|
|
765
|
-
}
|
|
766
|
-
// @__NO_SIDE_EFFECTS__
|
|
767
|
-
function literal(literal_, message$1) {
|
|
768
|
-
return {
|
|
769
|
-
kind: "schema",
|
|
770
|
-
type: "literal",
|
|
771
|
-
reference: literal,
|
|
772
|
-
expects: /* @__PURE__ */ _stringify22(literal_),
|
|
773
|
-
async: false,
|
|
774
|
-
literal: literal_,
|
|
775
|
-
message: message$1,
|
|
776
|
-
get "~standard"() {
|
|
777
|
-
return /* @__PURE__ */ _getStandardProps22(this);
|
|
778
|
-
},
|
|
779
|
-
"~run"(dataset, config$1) {
|
|
780
|
-
if (dataset.value === this.literal) dataset.typed = true;
|
|
781
|
-
else _addIssue22(this, "type", dataset, config$1);
|
|
782
|
-
return dataset;
|
|
783
|
-
}
|
|
784
|
-
};
|
|
785
|
-
}
|
|
786
|
-
// @__NO_SIDE_EFFECTS__
|
|
787
|
-
function number2(message$1) {
|
|
788
|
-
return {
|
|
789
|
-
kind: "schema",
|
|
790
|
-
type: "number",
|
|
791
|
-
reference: number2,
|
|
792
|
-
expects: "number",
|
|
793
|
-
async: false,
|
|
794
|
-
message: message$1,
|
|
795
|
-
get "~standard"() {
|
|
796
|
-
return /* @__PURE__ */ _getStandardProps22(this);
|
|
797
|
-
},
|
|
798
|
-
"~run"(dataset, config$1) {
|
|
799
|
-
if (typeof dataset.value === "number" && !isNaN(dataset.value)) dataset.typed = true;
|
|
800
|
-
else _addIssue22(this, "type", dataset, config$1);
|
|
801
|
-
return dataset;
|
|
802
|
-
}
|
|
803
|
-
};
|
|
804
|
-
}
|
|
805
|
-
// @__NO_SIDE_EFFECTS__
|
|
806
|
-
function object22(entries$1, message$1) {
|
|
807
|
-
return {
|
|
808
|
-
kind: "schema",
|
|
809
|
-
type: "object",
|
|
810
|
-
reference: object22,
|
|
811
|
-
expects: "Object",
|
|
812
|
-
async: false,
|
|
813
|
-
entries: entries$1,
|
|
814
|
-
message: message$1,
|
|
815
|
-
get "~standard"() {
|
|
816
|
-
return /* @__PURE__ */ _getStandardProps22(this);
|
|
817
|
-
},
|
|
818
|
-
"~run"(dataset, config$1) {
|
|
819
|
-
const input = dataset.value;
|
|
820
|
-
if (input && typeof input === "object") {
|
|
821
|
-
dataset.typed = true;
|
|
822
|
-
dataset.value = {};
|
|
823
|
-
for (const key in this.entries) {
|
|
824
|
-
const valueSchema = this.entries[key];
|
|
825
|
-
if (key in input || (valueSchema.type === "exact_optional" || valueSchema.type === "optional" || valueSchema.type === "nullish") && valueSchema.default !== void 0) {
|
|
826
|
-
const value$1 = key in input ? input[key] : /* @__PURE__ */ getDefault22(valueSchema);
|
|
827
|
-
const valueDataset = valueSchema["~run"]({ value: value$1 }, config$1);
|
|
828
|
-
if (valueDataset.issues) {
|
|
829
|
-
const pathItem = {
|
|
830
|
-
type: "object",
|
|
831
|
-
origin: "value",
|
|
832
|
-
input,
|
|
833
|
-
key,
|
|
834
|
-
value: value$1
|
|
835
|
-
};
|
|
836
|
-
for (const issue of valueDataset.issues) {
|
|
837
|
-
if (issue.path) issue.path.unshift(pathItem);
|
|
838
|
-
else issue.path = [pathItem];
|
|
839
|
-
dataset.issues?.push(issue);
|
|
840
|
-
}
|
|
841
|
-
if (!dataset.issues) dataset.issues = valueDataset.issues;
|
|
842
|
-
if (config$1.abortEarly) {
|
|
843
|
-
dataset.typed = false;
|
|
844
|
-
break;
|
|
845
|
-
}
|
|
846
|
-
}
|
|
847
|
-
if (!valueDataset.typed) dataset.typed = false;
|
|
848
|
-
dataset.value[key] = valueDataset.value;
|
|
849
|
-
} else if (valueSchema.fallback !== void 0) dataset.value[key] = /* @__PURE__ */ getFallback22(valueSchema);
|
|
850
|
-
else if (valueSchema.type !== "exact_optional" && valueSchema.type !== "optional" && valueSchema.type !== "nullish") {
|
|
851
|
-
_addIssue22(this, "key", dataset, config$1, {
|
|
852
|
-
input: void 0,
|
|
853
|
-
expected: `"${key}"`,
|
|
854
|
-
path: [{
|
|
855
|
-
type: "object",
|
|
856
|
-
origin: "key",
|
|
857
|
-
input,
|
|
858
|
-
key,
|
|
859
|
-
value: input[key]
|
|
860
|
-
}]
|
|
861
|
-
});
|
|
862
|
-
if (config$1.abortEarly) break;
|
|
863
|
-
}
|
|
864
|
-
}
|
|
865
|
-
} else _addIssue22(this, "type", dataset, config$1);
|
|
866
|
-
return dataset;
|
|
867
|
-
}
|
|
868
|
-
};
|
|
869
|
-
}
|
|
870
|
-
// @__NO_SIDE_EFFECTS__
|
|
871
|
-
function optional2(wrapped, default_) {
|
|
872
|
-
return {
|
|
873
|
-
kind: "schema",
|
|
874
|
-
type: "optional",
|
|
875
|
-
reference: optional2,
|
|
876
|
-
expects: `(${wrapped.expects} | undefined)`,
|
|
877
|
-
async: false,
|
|
878
|
-
wrapped,
|
|
879
|
-
default: default_,
|
|
880
|
-
get "~standard"() {
|
|
881
|
-
return /* @__PURE__ */ _getStandardProps22(this);
|
|
882
|
-
},
|
|
883
|
-
"~run"(dataset, config$1) {
|
|
884
|
-
if (dataset.value === void 0) {
|
|
885
|
-
if (this.default !== void 0) dataset.value = /* @__PURE__ */ getDefault22(this, dataset, config$1);
|
|
886
|
-
if (dataset.value === void 0) {
|
|
887
|
-
dataset.typed = true;
|
|
888
|
-
return dataset;
|
|
889
|
-
}
|
|
890
|
-
}
|
|
891
|
-
return this.wrapped["~run"](dataset, config$1);
|
|
892
|
-
}
|
|
893
|
-
};
|
|
894
|
-
}
|
|
895
|
-
// @__NO_SIDE_EFFECTS__
|
|
896
|
-
function string22(message$1) {
|
|
897
|
-
return {
|
|
898
|
-
kind: "schema",
|
|
899
|
-
type: "string",
|
|
900
|
-
reference: string22,
|
|
901
|
-
expects: "string",
|
|
902
|
-
async: false,
|
|
903
|
-
message: message$1,
|
|
904
|
-
get "~standard"() {
|
|
905
|
-
return /* @__PURE__ */ _getStandardProps22(this);
|
|
906
|
-
},
|
|
907
|
-
"~run"(dataset, config$1) {
|
|
908
|
-
if (typeof dataset.value === "string") dataset.typed = true;
|
|
909
|
-
else _addIssue22(this, "type", dataset, config$1);
|
|
910
|
-
return dataset;
|
|
911
|
-
}
|
|
912
|
-
};
|
|
913
|
-
}
|
|
914
|
-
// @__NO_SIDE_EFFECTS__
|
|
915
|
-
function safeParse22(schema, input, config$1) {
|
|
916
|
-
const dataset = schema["~run"]({ value: input }, /* @__PURE__ */ getGlobalConfig22(config$1));
|
|
917
|
-
return {
|
|
918
|
-
typed: dataset.typed,
|
|
919
|
-
success: !dataset.issues,
|
|
920
|
-
output: dataset.value,
|
|
921
|
-
issues: dataset.issues
|
|
922
|
-
};
|
|
923
|
-
}
|
|
924
|
-
var GithubSourceSchema = /* @__PURE__ */ object22({
|
|
925
|
-
type: /* @__PURE__ */ literal("github"),
|
|
926
|
-
repo: /* @__PURE__ */ string22(),
|
|
927
|
-
prNumber: /* @__PURE__ */ number2()
|
|
928
|
-
});
|
|
929
|
-
var GithubCursorSchema = /* @__PURE__ */ object22({
|
|
930
|
-
reviewIds: /* @__PURE__ */ array22(/* @__PURE__ */ string22()),
|
|
931
|
-
commentIds: /* @__PURE__ */ array22(/* @__PURE__ */ string22()),
|
|
932
|
-
historyPrimed: /* @__PURE__ */ optional2(/* @__PURE__ */ boolean22(), false),
|
|
933
|
-
lineCommentsPrimed: /* @__PURE__ */ optional2(/* @__PURE__ */ boolean22(), false),
|
|
934
|
-
conversationCommentsPrimed: /* @__PURE__ */ optional2(/* @__PURE__ */ boolean22(), false),
|
|
935
|
-
ciState: /* @__PURE__ */ string22(),
|
|
936
|
-
ciFailureState: /* @__PURE__ */ optional2(/* @__PURE__ */ string22(), ""),
|
|
937
|
-
mergeable: /* @__PURE__ */ string22(),
|
|
938
|
-
prState: /* @__PURE__ */ string22()
|
|
939
|
-
});
|
|
940
|
-
function failureRunIds(failed) {
|
|
941
|
-
const runIds = /* @__PURE__ */ new Set();
|
|
942
|
-
for (const check of failed) {
|
|
943
|
-
const details = check.detailsUrl ?? check.targetUrl ?? "";
|
|
944
|
-
const runId = String(details).match(/\/actions\/runs\/(\d+)/)?.[1];
|
|
945
|
-
if (runId) runIds.add(runId);
|
|
946
|
-
}
|
|
947
|
-
return runIds;
|
|
948
|
-
}
|
|
949
|
-
var ANSI_ESCAPE = /\u001B(?:\[[0-?]*[ -/]*[@-~]|\][^\u0007]*(?:\u0007|\u001B\\))/g;
|
|
950
|
-
var LOG_PREFIX = /^.*?\b\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z(?:\s+(?:stdout|stderr))?\s*(?:\|\s*)?/;
|
|
951
|
-
function cleanCiLog(raw) {
|
|
952
|
-
return raw.replace(/\r/g, "").replace(ANSI_ESCAPE, "").split("\n").map((line) => line.replace(LOG_PREFIX, "").trimEnd()).filter((line) => !/\bis in dev mode\. Not recommended for production!/i.test(line)).join("\n").replace(/\n{3,}/g, "\n\n").trim();
|
|
953
|
-
}
|
|
954
|
-
var API = "https://api.github.com";
|
|
955
|
-
var GRAPHQL = "https://api.github.com/graphql";
|
|
956
|
-
function githubToken() {
|
|
957
|
-
return process.env.GH_TOKEN ?? process.env.GITHUB_TOKEN;
|
|
958
|
-
}
|
|
959
|
-
async function githubJson(path22) {
|
|
960
|
-
const token = githubToken();
|
|
961
|
-
if (!token) return void 0;
|
|
962
|
-
try {
|
|
963
|
-
const response = await fetch(`${API}${path22}`, {
|
|
964
|
-
headers: { authorization: `Bearer ${token}`, "user-agent": "sourcefed", accept: "application/vnd.github+json" }
|
|
965
|
-
});
|
|
966
|
-
if (!response.ok) return void 0;
|
|
967
|
-
return await response.json();
|
|
968
|
-
} catch {
|
|
969
|
-
return void 0;
|
|
970
|
-
}
|
|
971
|
-
}
|
|
972
|
-
async function githubGraphQL(query, variables) {
|
|
973
|
-
const token = githubToken();
|
|
974
|
-
if (!token) return void 0;
|
|
975
|
-
try {
|
|
976
|
-
const response = await fetch(GRAPHQL, {
|
|
977
|
-
method: "POST",
|
|
978
|
-
headers: { authorization: `Bearer ${token}`, "user-agent": "sourcefed", "content-type": "application/json" },
|
|
979
|
-
body: JSON.stringify({ query, variables })
|
|
980
|
-
});
|
|
981
|
-
const body = await response.json();
|
|
982
|
-
if (!response.ok || body.errors) return void 0;
|
|
983
|
-
return body.data;
|
|
984
|
-
} catch {
|
|
985
|
-
return void 0;
|
|
986
|
-
}
|
|
987
|
-
}
|
|
988
|
-
var MAX_COMMENT_PAGES = 10;
|
|
989
|
-
async function fetchGithubComments(path22) {
|
|
990
|
-
const comments = [];
|
|
991
|
-
for (let page = 1; page <= MAX_COMMENT_PAGES; page++) {
|
|
992
|
-
const batch = await githubJson(`/${path22}?per_page=100&page=${page}`);
|
|
993
|
-
if (!Array.isArray(batch)) return void 0;
|
|
994
|
-
comments.push(...batch);
|
|
995
|
-
if (batch.length < 100) return comments;
|
|
996
|
-
}
|
|
997
|
-
return comments;
|
|
998
|
-
}
|
|
999
|
-
var API2 = "https://api.github.com";
|
|
1000
|
-
var MAX_LOG_BYTES = 1e7;
|
|
1001
|
-
var MAX_ENTRY_BYTES = 5e6;
|
|
1002
|
-
var MAX_TOTAL_BYTES = 5e7;
|
|
1003
|
-
async function fetchRunLog(repo, runId) {
|
|
1004
|
-
const token = githubToken();
|
|
1005
|
-
if (!token) return void 0;
|
|
1006
|
-
try {
|
|
1007
|
-
const response = await fetch(`${API2}/repos/${repo}/actions/runs/${runId}/logs`, {
|
|
1008
|
-
headers: { authorization: `Bearer ${token}`, "user-agent": "sourcefed", accept: "application/vnd.github+json" }
|
|
1009
|
-
});
|
|
1010
|
-
if (!response.ok || !response.body) return void 0;
|
|
1011
|
-
const length = Number(response.headers.get("content-length") ?? 0);
|
|
1012
|
-
if (length > MAX_LOG_BYTES) return void 0;
|
|
1013
|
-
const reader = response.body.getReader();
|
|
1014
|
-
const chunks = [];
|
|
1015
|
-
let total = 0;
|
|
1016
|
-
while (true) {
|
|
1017
|
-
const { done, value } = await reader.read();
|
|
1018
|
-
if (done) break;
|
|
1019
|
-
total += value.byteLength;
|
|
1020
|
-
if (total > MAX_LOG_BYTES) return void 0;
|
|
1021
|
-
chunks.push(value);
|
|
1022
|
-
}
|
|
1023
|
-
const buffer = concatChunks(chunks);
|
|
1024
|
-
const entries = extractZipEntries(buffer);
|
|
1025
|
-
return entries.map((entry) => new TextDecoder().decode(entry.content)).join("\n");
|
|
1026
|
-
} catch {
|
|
1027
|
-
return void 0;
|
|
1028
|
-
}
|
|
1029
|
-
}
|
|
1030
|
-
function concatChunks(chunks) {
|
|
1031
|
-
const total = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
|
|
1032
|
-
const result = new Uint8Array(total);
|
|
1033
|
-
let offset = 0;
|
|
1034
|
-
for (const chunk of chunks) {
|
|
1035
|
-
result.set(chunk, offset);
|
|
1036
|
-
offset += chunk.length;
|
|
1037
|
-
}
|
|
1038
|
-
return result;
|
|
1039
|
-
}
|
|
1040
|
-
function extractZipEntries(buffer) {
|
|
1041
|
-
const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
1042
|
-
let end = -1;
|
|
1043
|
-
const scanStart = Math.max(0, buffer.length - 65557);
|
|
1044
|
-
for (let offset = buffer.length - 22; offset >= scanStart; offset--) {
|
|
1045
|
-
if (view.getUint32(offset, true) === 101010256) {
|
|
1046
|
-
end = offset;
|
|
1047
|
-
break;
|
|
1048
|
-
}
|
|
1049
|
-
}
|
|
1050
|
-
if (end < 0) return [];
|
|
1051
|
-
const entryCount = view.getUint16(end + 10, true);
|
|
1052
|
-
let cursor = view.getUint32(end + 16, true);
|
|
1053
|
-
const entries = [];
|
|
1054
|
-
let totalBytes = 0;
|
|
1055
|
-
for (let index = 0; index < entryCount; index++) {
|
|
1056
|
-
if (view.getUint32(cursor, true) !== 33639248) break;
|
|
1057
|
-
const method = view.getUint16(cursor + 10, true);
|
|
1058
|
-
const compressedSize = view.getUint32(cursor + 20, true);
|
|
1059
|
-
const nameLength = view.getUint16(cursor + 28, true);
|
|
1060
|
-
const extraLength = view.getUint16(cursor + 30, true);
|
|
1061
|
-
const commentLength = view.getUint16(cursor + 32, true);
|
|
1062
|
-
const localOffset = view.getUint32(cursor + 42, true);
|
|
1063
|
-
const name = new TextDecoder().decode(buffer.slice(cursor + 46, cursor + 46 + nameLength));
|
|
1064
|
-
const localNameLength = view.getUint16(localOffset + 26, true);
|
|
1065
|
-
const localExtraLength = view.getUint16(localOffset + 28, true);
|
|
1066
|
-
const dataStart = localOffset + 30 + localNameLength + localExtraLength;
|
|
1067
|
-
const compressed = buffer.slice(dataStart, dataStart + compressedSize);
|
|
1068
|
-
let content;
|
|
1069
|
-
if (method === 8) {
|
|
1070
|
-
const declaredSize = view.getUint32(localOffset + 22, true);
|
|
1071
|
-
if (declaredSize > MAX_ENTRY_BYTES) {
|
|
1072
|
-
cursor += 46 + nameLength + extraLength + commentLength;
|
|
1073
|
-
continue;
|
|
1074
|
-
}
|
|
1075
|
-
try {
|
|
1076
|
-
content = inflateRawSync(compressed);
|
|
1077
|
-
} catch {
|
|
1078
|
-
content = compressed;
|
|
1079
|
-
}
|
|
1080
|
-
} else {
|
|
1081
|
-
content = compressed;
|
|
1082
|
-
}
|
|
1083
|
-
totalBytes += content.length;
|
|
1084
|
-
if (totalBytes > MAX_TOTAL_BYTES) break;
|
|
1085
|
-
entries.push({ name, content });
|
|
1086
|
-
cursor += 46 + nameLength + extraLength + commentLength;
|
|
1087
|
-
}
|
|
1088
|
-
return entries;
|
|
1089
|
-
}
|
|
1090
|
-
var PR_DATA_QUERY = `
|
|
1091
|
-
query PullRequestData($owner: String!, $name: String!, $number: Int!, $reviewsAfter: String, $contextsAfter: String) {
|
|
1092
|
-
repository(owner: $owner, name: $name) {
|
|
1093
|
-
pullRequest(number: $number) {
|
|
1094
|
-
state
|
|
1095
|
-
mergeable
|
|
1096
|
-
mergeStateStatus
|
|
1097
|
-
reviews(first: 100, after: $reviewsAfter) {
|
|
1098
|
-
nodes {
|
|
1099
|
-
databaseId
|
|
1100
|
-
author { login }
|
|
1101
|
-
state
|
|
1102
|
-
submittedAt
|
|
1103
|
-
body
|
|
1104
|
-
}
|
|
1105
|
-
pageInfo {
|
|
1106
|
-
hasNextPage
|
|
1107
|
-
endCursor
|
|
1108
|
-
}
|
|
1109
|
-
}
|
|
1110
|
-
statusCheckRollup {
|
|
1111
|
-
contexts(first: 100, after: $contextsAfter) {
|
|
1112
|
-
nodes {
|
|
1113
|
-
... on StatusContext {
|
|
1114
|
-
context
|
|
1115
|
-
state
|
|
1116
|
-
targetUrl
|
|
1117
|
-
}
|
|
1118
|
-
... on CheckRun {
|
|
1119
|
-
name
|
|
1120
|
-
conclusion
|
|
1121
|
-
detailsUrl
|
|
1122
|
-
}
|
|
1123
|
-
}
|
|
1124
|
-
pageInfo {
|
|
1125
|
-
hasNextPage
|
|
1126
|
-
endCursor
|
|
1127
|
-
}
|
|
1128
|
-
}
|
|
1129
|
-
}
|
|
1130
|
-
}
|
|
1131
|
-
}
|
|
1132
|
-
}`;
|
|
1133
|
-
var MAX_REVIEW_PAGES = 300;
|
|
1134
|
-
async function fetchPrData(repo, prNumber) {
|
|
1135
|
-
const [owner, name] = repo.split("/");
|
|
1136
|
-
if (!owner || !name) return void 0;
|
|
1137
|
-
const data = await githubGraphQL(PR_DATA_QUERY, { owner, name, number: prNumber, reviewsAfter: void 0, contextsAfter: void 0 });
|
|
1138
|
-
const pullRequest = data?.repository?.pullRequest;
|
|
1139
|
-
if (!pullRequest) return void 0;
|
|
1140
|
-
const reviews = [];
|
|
1141
|
-
let page = pullRequest.reviews;
|
|
1142
|
-
while (page?.nodes && page.nodes.length > 0) {
|
|
1143
|
-
reviews.push(...page.nodes.map((node) => ({
|
|
1144
|
-
id: node.databaseId,
|
|
1145
|
-
author: node.author,
|
|
1146
|
-
state: node.state,
|
|
1147
|
-
submittedAt: node.submittedAt,
|
|
1148
|
-
body: node.body
|
|
1149
|
-
})));
|
|
1150
|
-
if (!page.pageInfo?.hasNextPage || reviews.length >= MAX_REVIEW_PAGES) break;
|
|
1151
|
-
const next = await githubGraphQL(PR_DATA_QUERY, { owner, name, number: prNumber, reviewsAfter: page.pageInfo.endCursor, contextsAfter: void 0 });
|
|
1152
|
-
page = next?.repository?.pullRequest?.reviews;
|
|
1153
|
-
}
|
|
1154
|
-
const statusCheckRollup = [];
|
|
1155
|
-
let contextsPage = pullRequest.statusCheckRollup?.contexts;
|
|
1156
|
-
while (contextsPage?.nodes && contextsPage.nodes.length > 0) {
|
|
1157
|
-
statusCheckRollup.push(...contextsPage.nodes);
|
|
1158
|
-
if (!contextsPage.pageInfo?.hasNextPage) break;
|
|
1159
|
-
const next = await githubGraphQL(PR_DATA_QUERY, { owner, name, number: prNumber, reviewsAfter: void 0, contextsAfter: contextsPage.pageInfo.endCursor });
|
|
1160
|
-
contextsPage = next?.repository?.pullRequest?.statusCheckRollup?.contexts;
|
|
1161
|
-
}
|
|
1162
|
-
return {
|
|
1163
|
-
reviews,
|
|
1164
|
-
statusCheckRollup,
|
|
1165
|
-
mergeable: pullRequest.mergeable,
|
|
1166
|
-
mergeStateStatus: pullRequest.mergeStateStatus,
|
|
1167
|
-
state: pullRequest.state
|
|
1168
|
-
};
|
|
1169
|
-
}
|
|
1170
|
-
async function failureRunLog(repo, runId) {
|
|
1171
|
-
const log = await fetchRunLog(repo, runId);
|
|
1172
|
-
if (!log || !log.trim()) return void 0;
|
|
1173
|
-
const tail = cleanCiLog(log).split("\n").slice(-60).join("\n");
|
|
1174
|
-
return `
|
|
1175
|
-
### Failing log (run ${runId})
|
|
1176
|
-
\`\`\`
|
|
1177
|
-
${tail}
|
|
1178
|
-
\`\`\``;
|
|
1179
|
-
}
|
|
1180
|
-
function formatFailedCheck(check) {
|
|
1181
|
-
let name = check.name;
|
|
1182
|
-
if (!name) name = check.context;
|
|
1183
|
-
if (!name) name = "check";
|
|
1184
|
-
let conclusion = check.conclusion;
|
|
1185
|
-
if (!conclusion) conclusion = check.state;
|
|
1186
|
-
if (!conclusion) conclusion = "FAILURE";
|
|
1187
|
-
return `- ${name}: ${conclusion}`;
|
|
1188
|
-
}
|
|
1189
|
-
async function ciFailureDetail(repo, failed) {
|
|
1190
|
-
const lines = failed.map(formatFailedCheck);
|
|
1191
|
-
const runIds = failureRunIds(failed);
|
|
1192
|
-
for (const runId of [...runIds].slice(0, 3)) {
|
|
1193
|
-
const log = await failureRunLog(repo, runId);
|
|
1194
|
-
if (log) lines.push(log);
|
|
1195
|
-
}
|
|
1196
|
-
return lines.join("\n");
|
|
1197
|
-
}
|
|
1198
|
-
async function confirmStillFailing(repo, prNumber, failed) {
|
|
1199
|
-
const data = await fetchPrData(repo, prNumber);
|
|
1200
|
-
if (!data) return failed;
|
|
1201
|
-
const rollup = data.statusCheckRollup ?? [];
|
|
1202
|
-
const current = /* @__PURE__ */ new Map();
|
|
1203
|
-
for (const check of rollup) {
|
|
1204
|
-
let name = check.name;
|
|
1205
|
-
if (!name) name = check.context;
|
|
1206
|
-
if (!name) name = "check";
|
|
1207
|
-
let state = check.conclusion;
|
|
1208
|
-
if (!state) state = check.state;
|
|
1209
|
-
if (!state) state = "PENDING";
|
|
1210
|
-
current.set(name, String(state).toUpperCase());
|
|
1211
|
-
}
|
|
1212
|
-
return failed.filter((check) => {
|
|
1213
|
-
let name = check.name;
|
|
1214
|
-
if (!name) name = check.context;
|
|
1215
|
-
if (!name) name = "check";
|
|
1216
|
-
const state = current.get(name);
|
|
1217
|
-
if (state === void 0) return false;
|
|
1218
|
-
return /FAIL|ERROR|CANCEL/i.test(state);
|
|
1219
|
-
});
|
|
1220
|
-
}
|
|
1221
|
-
async function appendGithubCiEvent(repo, prNumber, cursor, events, rollup) {
|
|
1222
|
-
const ciState = rollup.map((check) => check.conclusion ?? check.state ?? "PENDING").sort().join(",");
|
|
1223
|
-
if (!ciState || ciState === cursor.ciState) return;
|
|
1224
|
-
const previousCiState = cursor.ciState;
|
|
1225
|
-
cursor.ciState = ciState;
|
|
1226
|
-
if (previousCiState === void 0) return;
|
|
1227
|
-
let failed = rollup.filter((check) => /FAIL|ERROR|CANCEL/i.test(check.conclusion ?? ""));
|
|
1228
|
-
failed = await confirmStillFailing(repo, prNumber, failed);
|
|
1229
|
-
const failureState = failed.map((check) => `${check.name ?? check.context ?? "check"}:${check.conclusion ?? check.state ?? "FAILURE"}`).sort().join(",");
|
|
1230
|
-
if (failed.length > 0 && failureState !== cursor.ciFailureState) {
|
|
1231
|
-
const names = failed.map((check) => check.name ?? check.context ?? "check").join(", ");
|
|
1232
|
-
events.push({
|
|
1233
|
-
kind: "ci",
|
|
1234
|
-
id: `ci:${failureState}`,
|
|
1235
|
-
repo,
|
|
1236
|
-
prNumber,
|
|
1237
|
-
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1238
|
-
summary: `CI failed on #${prNumber}: ${names}`,
|
|
1239
|
-
body: await ciFailureDetail(repo, failed),
|
|
1240
|
-
actionable: true
|
|
1241
|
-
});
|
|
1242
|
-
}
|
|
1243
|
-
cursor.ciFailureState = failureState;
|
|
1244
|
-
}
|
|
1245
|
-
function appendGithubConflictEvent(repo, prNumber, cursor, events, mergeable) {
|
|
1246
|
-
if (mergeable === cursor.mergeable) return;
|
|
1247
|
-
const previousMergeable = cursor.mergeable;
|
|
1248
|
-
cursor.mergeable = mergeable;
|
|
1249
|
-
if (previousMergeable === void 0) return;
|
|
1250
|
-
if (mergeable !== "CONFLICTING" && mergeable !== "DIRTY") return;
|
|
1251
|
-
events.push({
|
|
1252
|
-
kind: "conflict",
|
|
1253
|
-
id: `conflict:${mergeable}`,
|
|
1254
|
-
repo,
|
|
1255
|
-
prNumber,
|
|
1256
|
-
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1257
|
-
summary: `PR #${prNumber} now has merge conflicts with its base (${mergeable})`,
|
|
1258
|
-
actionable: true
|
|
1259
|
-
});
|
|
1260
|
-
}
|
|
1261
|
-
function appendGithubReviews(repo, prNumber, cursor, events, reviews, historyPrimed) {
|
|
1262
|
-
const ref = `#${prNumber}`;
|
|
1263
|
-
for (const review of reviews) {
|
|
1264
|
-
const id2 = "rev:" + String(review.id ?? `${review.author?.login}-${review.submittedAt}`);
|
|
1265
|
-
if (cursor.reviewIds.includes(id2)) continue;
|
|
1266
|
-
cursor.reviewIds.push(id2);
|
|
1267
|
-
if (review.state === "PENDING" || !historyPrimed) continue;
|
|
1268
|
-
if (!review.body?.trim()) continue;
|
|
1269
|
-
let actionable = false;
|
|
1270
|
-
if (review.state === "CHANGES_REQUESTED") actionable = true;
|
|
1271
|
-
if (review.state === "COMMENTED" && review.body?.trim()) actionable = true;
|
|
1272
|
-
events.push({
|
|
1273
|
-
kind: "review",
|
|
1274
|
-
id: id2,
|
|
1275
|
-
repo,
|
|
1276
|
-
prNumber,
|
|
1277
|
-
at: review.submittedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
1278
|
-
summary: `Review by ${review.author?.login ?? "someone"} [${review.state}] on ${ref}`,
|
|
1279
|
-
body: review.body,
|
|
1280
|
-
actionable
|
|
1281
|
-
});
|
|
1282
|
-
}
|
|
1283
|
-
}
|
|
1284
|
-
function appendGithubStateEvent(repo, prNumber, cursor, events, prState) {
|
|
1285
|
-
const isTerminal = prState === "MERGED" || prState === "CLOSED";
|
|
1286
|
-
if (prState === cursor.prState) return isTerminal;
|
|
1287
|
-
const previousPrState = cursor.prState;
|
|
1288
|
-
cursor.prState = prState;
|
|
1289
|
-
if (previousPrState !== void 0 && isTerminal) {
|
|
1290
|
-
let summary = `PR #${prNumber} was CLOSED without merging`;
|
|
1291
|
-
if (prState === "MERGED") summary = `PR #${prNumber} was MERGED`;
|
|
1292
|
-
events.push({
|
|
1293
|
-
kind: "merged",
|
|
1294
|
-
id: `state:${prState}`,
|
|
1295
|
-
repo,
|
|
1296
|
-
prNumber,
|
|
1297
|
-
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1298
|
-
summary,
|
|
1299
|
-
actionable: prState === "MERGED",
|
|
1300
|
-
terminal: isTerminal
|
|
1301
|
-
});
|
|
1302
|
-
}
|
|
1303
|
-
return isTerminal;
|
|
1304
|
-
}
|
|
1305
|
-
function appendComments(repo, prNumber, cursor, events, comments, idPrefix, historyPrimed, summary, body) {
|
|
1306
|
-
for (const comment of comments) {
|
|
1307
|
-
const id2 = idPrefix + String(comment.id);
|
|
1308
|
-
if (cursor.commentIds.includes(id2)) continue;
|
|
1309
|
-
cursor.commentIds.push(id2);
|
|
1310
|
-
if (!historyPrimed) continue;
|
|
1311
|
-
const text = body(comment);
|
|
1312
|
-
events.push({
|
|
1313
|
-
kind: "comment",
|
|
1314
|
-
id: id2,
|
|
1315
|
-
repo,
|
|
1316
|
-
prNumber,
|
|
1317
|
-
at: comment.created_at ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
1318
|
-
summary: summary(comment),
|
|
1319
|
-
body: text,
|
|
1320
|
-
actionable: Boolean(text.trim())
|
|
1321
|
-
});
|
|
1322
|
-
}
|
|
1323
|
-
}
|
|
1324
|
-
function emptyGithubCursor() {
|
|
1325
|
-
return {
|
|
1326
|
-
reviewIds: [],
|
|
1327
|
-
commentIds: [],
|
|
1328
|
-
historyPrimed: false,
|
|
1329
|
-
lineCommentsPrimed: false,
|
|
1330
|
-
conversationCommentsPrimed: false,
|
|
1331
|
-
ciState: "",
|
|
1332
|
-
ciFailureState: "",
|
|
1333
|
-
mergeable: "",
|
|
1334
|
-
prState: ""
|
|
1335
|
-
};
|
|
1336
|
-
}
|
|
1337
|
-
var warnedMissingToken = false;
|
|
1338
|
-
async function pollGithub(repo, prNumber, cursorRaw) {
|
|
1339
|
-
const parsedCursor = /* @__PURE__ */ safeParse22(GithubCursorSchema, cursorRaw);
|
|
1340
|
-
let cursor = emptyGithubCursor();
|
|
1341
|
-
if (parsedCursor.success) cursor = parsedCursor.output;
|
|
1342
|
-
const events = [];
|
|
1343
|
-
const ref = `#${prNumber}`;
|
|
1344
|
-
if (!githubToken()) {
|
|
1345
|
-
if (!warnedMissingToken) {
|
|
1346
|
-
warnedMissingToken = true;
|
|
1347
|
-
console.warn("[sourcefed] GH_TOKEN or GITHUB_TOKEN is not set; GitHub monitors will not poll");
|
|
1348
|
-
}
|
|
1349
|
-
return { events, cursor, terminal: false };
|
|
1350
|
-
}
|
|
1351
|
-
const data = await fetchPrData(repo, prNumber);
|
|
1352
|
-
if (!data) return { events, cursor, terminal: false };
|
|
1353
|
-
let historyPrimed = cursor.historyPrimed;
|
|
1354
|
-
if (!historyPrimed) historyPrimed = Boolean(cursor.reviewIds.length || cursor.commentIds.length || cursor.ciState || cursor.mergeable || cursor.prState);
|
|
1355
|
-
const lineCommentsPrimed = cursor.lineCommentsPrimed;
|
|
1356
|
-
const conversationCommentsPrimed = cursor.conversationCommentsPrimed;
|
|
1357
|
-
appendGithubReviews(repo, prNumber, cursor, events, data.reviews ?? [], historyPrimed);
|
|
1358
|
-
if (!cursor.historyPrimed) cursor.historyPrimed = true;
|
|
1359
|
-
const lineComments = await fetchGithubComments(`repos/${repo}/pulls/${prNumber}/comments`);
|
|
1360
|
-
if (lineComments) {
|
|
1361
|
-
appendComments(
|
|
1362
|
-
repo,
|
|
1363
|
-
prNumber,
|
|
1364
|
-
cursor,
|
|
1365
|
-
events,
|
|
1366
|
-
lineComments,
|
|
1367
|
-
"c:",
|
|
1368
|
-
lineCommentsPrimed,
|
|
1369
|
-
(comment) => `Comment by ${comment.user?.login ?? "someone"} on ${comment.path ?? ref}`,
|
|
1370
|
-
(comment) => {
|
|
1371
|
-
let location = comment.path ?? "";
|
|
1372
|
-
if (comment.line) location += `:${comment.line}`;
|
|
1373
|
-
return `${location} \u2014 ${comment.body ?? ""}`;
|
|
1374
|
-
}
|
|
1375
|
-
);
|
|
1376
|
-
cursor.lineCommentsPrimed = true;
|
|
1377
|
-
}
|
|
1378
|
-
const conversationComments = await fetchGithubComments(`repos/${repo}/issues/${prNumber}/comments`);
|
|
1379
|
-
if (conversationComments) {
|
|
1380
|
-
appendComments(
|
|
1381
|
-
repo,
|
|
1382
|
-
prNumber,
|
|
1383
|
-
cursor,
|
|
1384
|
-
events,
|
|
1385
|
-
conversationComments,
|
|
1386
|
-
"issue:",
|
|
1387
|
-
conversationCommentsPrimed,
|
|
1388
|
-
(comment) => `Comment by ${comment.user?.login ?? "someone"} on ${ref}`,
|
|
1389
|
-
(comment) => comment.body ?? ""
|
|
1390
|
-
);
|
|
1391
|
-
cursor.conversationCommentsPrimed = true;
|
|
1392
|
-
}
|
|
1393
|
-
await appendGithubCiEvent(repo, prNumber, cursor, events, data.statusCheckRollup ?? []);
|
|
1394
|
-
const mergeable = data.mergeable ?? data.mergeStateStatus ?? "UNKNOWN";
|
|
1395
|
-
appendGithubConflictEvent(repo, prNumber, cursor, events, mergeable);
|
|
1396
|
-
const prState = data.state ?? "OPEN";
|
|
1397
|
-
const terminal = appendGithubStateEvent(repo, prNumber, cursor, events, prState);
|
|
1398
|
-
return { events, cursor, terminal };
|
|
1399
|
-
}
|
|
1400
|
-
var githubPollMonitor = new PollMonitor({
|
|
1401
|
-
run: async (source, cursor) => {
|
|
1402
|
-
const result = await pollGithub(source.repo, source.prNumber, cursor);
|
|
1403
|
-
return {
|
|
1404
|
-
cursor: result.cursor,
|
|
1405
|
-
events: result.events.map((event) => toMonitorEvent(event, source)),
|
|
1406
|
-
terminal: result.terminal
|
|
1407
|
-
};
|
|
1408
|
-
},
|
|
1409
|
-
mergeCursor: mergeCursors
|
|
1410
|
-
});
|
|
1411
|
-
function updateGithubCursor(event, cursorRaw) {
|
|
1412
|
-
const parsed = /* @__PURE__ */ safeParse22(GithubCursorSchema, cursorRaw);
|
|
1413
|
-
let cursor = emptyGithubCursor();
|
|
1414
|
-
if (parsed.success) cursor = parsed.output;
|
|
1415
|
-
if (event.id?.startsWith("review:")) {
|
|
1416
|
-
const id2 = `rev:${event.id.slice("review:".length)}`;
|
|
1417
|
-
if (!cursor.reviewIds.includes(id2)) cursor.reviewIds.push(id2);
|
|
1418
|
-
}
|
|
1419
|
-
if (event.id?.startsWith("c:") || event.id?.startsWith("issue:")) {
|
|
1420
|
-
if (!cursor.commentIds.includes(event.id)) cursor.commentIds.push(event.id);
|
|
1421
|
-
}
|
|
1422
|
-
if (event.kind === "merged") cursor.prState = "MERGED";
|
|
1423
|
-
if (event.kind === "closed") cursor.prState = "CLOSED";
|
|
1424
|
-
if (event.kind === "conflict") cursor.mergeable = "CONFLICTING";
|
|
1425
|
-
return cursor;
|
|
1426
|
-
}
|
|
1427
|
-
function fallbackGithubEvent({ payload, actor, repo, prNumber, eventName }) {
|
|
1428
|
-
return {
|
|
1429
|
-
kind: eventName,
|
|
1430
|
-
summary: `GitHub ${eventName} ${payload.action ?? "changed"} by ${actor} on ${repo}#${prNumber}`,
|
|
1431
|
-
actionable: true
|
|
1432
|
-
};
|
|
1433
|
-
}
|
|
1434
|
-
function parseCheckRun({ payload, repo, prNumber }) {
|
|
1435
|
-
const conclusion = payload.check_run?.conclusion ?? payload.check_run?.status ?? "changed";
|
|
1436
|
-
return {
|
|
1437
|
-
kind: "ci",
|
|
1438
|
-
summary: `GitHub CI ${conclusion} on ${repo}#${prNumber}`,
|
|
1439
|
-
body: payload.check_run?.output?.text ?? payload.check_run?.name,
|
|
1440
|
-
actionable: /FAIL|ERROR|CANCEL/i.test(String(conclusion))
|
|
1441
|
-
};
|
|
1442
|
-
}
|
|
1443
|
-
function parseCheckSuite({ payload, repo, prNumber }) {
|
|
1444
|
-
const conclusion = payload.check_suite?.conclusion ?? payload.check_suite?.status ?? "changed";
|
|
1445
|
-
return {
|
|
1446
|
-
kind: "ci",
|
|
1447
|
-
summary: `GitHub CI ${conclusion} on ${repo}#${prNumber}`,
|
|
1448
|
-
body: payload.check_suite?.latest_check_runs?.map((check) => check.name).join(", "),
|
|
1449
|
-
actionable: /FAIL|ERROR|CANCEL/i.test(String(conclusion))
|
|
1450
|
-
};
|
|
1451
|
-
}
|
|
1452
|
-
function parseGithubComment({ payload, actor, repo, prNumber, eventName }) {
|
|
1453
|
-
return {
|
|
1454
|
-
kind: "comment",
|
|
1455
|
-
id: payload.comment?.id === void 0 ? void 0 : `${eventName === "issue_comment" ? "issue:" : "c:"}${payload.comment.id}`,
|
|
1456
|
-
summary: `GitHub comment by ${actor} on ${repo}#${prNumber}`,
|
|
1457
|
-
body: payload.comment?.body,
|
|
1458
|
-
actionable: true
|
|
1459
|
-
};
|
|
1460
|
-
}
|
|
1461
|
-
function parsePullRequest({ payload, repo, prNumber }) {
|
|
1462
|
-
const merged = payload.action === "closed" && payload.pull_request?.merged === true;
|
|
1463
|
-
let kind = payload.action ?? "changed";
|
|
1464
|
-
if (payload.action === "synchronize") kind = "commit";
|
|
1465
|
-
if (merged) kind = "merged";
|
|
1466
|
-
let summary = `GitHub PR ${payload.action ?? "changed"}`;
|
|
1467
|
-
if (merged) summary += " and merged";
|
|
1468
|
-
summary += ` on ${repo}#${prNumber}`;
|
|
1469
|
-
let body = payload.pull_request?.body;
|
|
1470
|
-
if (merged) body = void 0;
|
|
1471
|
-
let id2;
|
|
1472
|
-
if (merged) id2 = "pr:MERGED";
|
|
1473
|
-
if (payload.action === "closed" && !merged) id2 = "pr:CLOSED";
|
|
1474
|
-
return { kind, id: id2, summary, body, actionable: true };
|
|
1475
|
-
}
|
|
1476
|
-
function parsePullRequestReview({ payload, actor, repo, prNumber }) {
|
|
1477
|
-
let actionable = false;
|
|
1478
|
-
if (["changes_requested", "commented"].includes(String(payload.review?.state ?? "").toLowerCase())) actionable = true;
|
|
1479
|
-
return {
|
|
1480
|
-
kind: "review",
|
|
1481
|
-
id: payload.review?.id === void 0 ? void 0 : `review:${payload.review.id}`,
|
|
1482
|
-
summary: `GitHub review ${payload.action ?? "changed"} by ${actor} on ${repo}#${prNumber}`,
|
|
1483
|
-
body: payload.review?.body,
|
|
1484
|
-
actionable
|
|
1485
|
-
};
|
|
1486
|
-
}
|
|
1487
|
-
var githubEventHandlers = {
|
|
1488
|
-
pull_request_review: parsePullRequestReview,
|
|
1489
|
-
pull_request_review_comment: parseGithubComment,
|
|
1490
|
-
issue_comment: parseGithubComment,
|
|
1491
|
-
check_run: parseCheckRun,
|
|
1492
|
-
check_suite: parseCheckSuite,
|
|
1493
|
-
pull_request: parsePullRequest
|
|
1494
|
-
};
|
|
1495
|
-
function githubPullRequestNumber(payload, eventName) {
|
|
1496
|
-
let value = payload.pull_request?.number;
|
|
1497
|
-
if (value === void 0) value = payload.issue?.number;
|
|
1498
|
-
if (value === void 0 && eventName === "check_run") value = payload.check_run?.pull_requests?.[0]?.number;
|
|
1499
|
-
if (value === void 0 && eventName === "check_suite") value = payload.check_suite?.pull_requests?.[0]?.number;
|
|
1500
|
-
if (value === void 0) return void 0;
|
|
1501
|
-
const number22 = Number(value);
|
|
1502
|
-
if (!Number.isInteger(number22)) return void 0;
|
|
1503
|
-
return number22;
|
|
1504
|
-
}
|
|
1505
|
-
function parseGithubWebhook(payload, eventName, _deliveryId) {
|
|
1506
|
-
const repo = payload.repository?.full_name;
|
|
1507
|
-
const prNumber = githubPullRequestNumber(payload, eventName);
|
|
1508
|
-
if (!repo || prNumber === void 0) return void 0;
|
|
1509
|
-
if (eventName === "pull_request" && payload.action === "edited") return void 0;
|
|
1510
|
-
const handler = githubEventHandlers[eventName] ?? fallbackGithubEvent;
|
|
1511
|
-
const actor = payload.sender?.login ?? payload.review?.user?.login ?? "someone";
|
|
1512
|
-
const shape = handler({ payload, actor, repo, prNumber, eventName });
|
|
1513
|
-
if (eventName === "pull_request_review" && !shape.body?.trim()) return void 0;
|
|
1514
|
-
let body = shape.body;
|
|
1515
|
-
if (shape.kind === "merged") body = "";
|
|
1516
|
-
const event = {
|
|
1517
|
-
source: { type: "github", repo, prNumber },
|
|
1518
|
-
kind: shape.kind,
|
|
1519
|
-
id: shape.id,
|
|
1520
|
-
at: payload.repository?.updated_at ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
1521
|
-
summary: shape.summary,
|
|
1522
|
-
body: body || void 0,
|
|
1523
|
-
actionable: shape.actionable,
|
|
1524
|
-
terminal: shape.kind === "merged" || shape.kind === "closed"
|
|
1525
|
-
};
|
|
1526
|
-
return event;
|
|
1527
|
-
}
|
|
1528
|
-
function verifyHmac(body, signature, secret) {
|
|
1529
|
-
if (!secret || !signature) return false;
|
|
1530
|
-
const expected = `sha256=${createHmac("sha256", secret).update(body).digest("hex")}`;
|
|
1531
|
-
const actual = Buffer.from(signature);
|
|
1532
|
-
const wanted = Buffer.from(expected);
|
|
1533
|
-
return actual.length === wanted.length && timingSafeEqual(actual, wanted);
|
|
1534
|
-
}
|
|
1535
|
-
function verifyGithubWebhook(body, request) {
|
|
1536
|
-
return verifyHmac(body, request.headers.get("x-hub-signature-256"), process.env.SOURCEFED_GITHUB_WEBHOOK_SECRET);
|
|
1537
|
-
}
|
|
1538
|
-
var githubWebhookMonitor = new WebhookMonitor({
|
|
1539
|
-
path: "/webhooks/github",
|
|
1540
|
-
preferred: true,
|
|
1541
|
-
configured: () => Boolean(process.env.SOURCEFED_GITHUB_WEBHOOK_SECRET),
|
|
1542
|
-
verify: verifyGithubWebhook,
|
|
1543
|
-
deliveryId: (request) => request.headers.get("x-github-delivery") ?? void 0,
|
|
1544
|
-
eventName: (request) => request.headers.get("x-github-event") ?? "github",
|
|
1545
|
-
parse: parseGithubWebhook,
|
|
1546
|
-
updateCursor: updateGithubCursor
|
|
1547
|
-
});
|
|
1548
|
-
var GithubMonitor = class extends Monitor {
|
|
1549
|
-
poll = githubPollMonitor;
|
|
1550
|
-
webhook = githubWebhookMonitor;
|
|
1551
|
-
constructor() {
|
|
1552
|
-
super({ type: "github", schema: GithubSourceSchema });
|
|
1553
|
-
}
|
|
1554
|
-
key = (source) => `github:${source.repo}#${source.prNumber}`;
|
|
1555
|
-
icon = "\u{F02A4}";
|
|
1556
|
-
label = (source) => `#${source.prNumber}`;
|
|
1557
|
-
detail = (source) => ` ${source.repo}#${source.prNumber}`;
|
|
1558
|
-
describe = (source) => `GitHub ${source.repo}#${source.prNumber}`;
|
|
1559
|
-
build(input) {
|
|
1560
|
-
if (input.repo && input.prNumber) return { type: "github", repo: input.repo, prNumber: input.prNumber };
|
|
1561
|
-
return { error: "repo and prNumber are required for a github monitor" };
|
|
1562
|
-
}
|
|
1563
|
-
};
|
|
1564
|
-
var store$43;
|
|
1565
|
-
var DEFAULT_CONFIG3 = {
|
|
1566
|
-
lang: void 0,
|
|
1567
|
-
message: void 0,
|
|
1568
|
-
abortEarly: void 0,
|
|
1569
|
-
abortPipeEarly: void 0
|
|
1570
|
-
};
|
|
1571
|
-
// @__NO_SIDE_EFFECTS__
|
|
1572
|
-
function getGlobalConfig3(config$1) {
|
|
1573
|
-
if (!config$1 && !store$43) return DEFAULT_CONFIG3;
|
|
1574
|
-
return {
|
|
1575
|
-
lang: config$1?.lang ?? store$43?.lang,
|
|
1576
|
-
message: config$1?.message,
|
|
1577
|
-
abortEarly: config$1?.abortEarly ?? store$43?.abortEarly,
|
|
1578
|
-
abortPipeEarly: config$1?.abortPipeEarly ?? store$43?.abortPipeEarly
|
|
1579
|
-
};
|
|
1580
|
-
}
|
|
1581
|
-
var store$33;
|
|
1582
|
-
// @__NO_SIDE_EFFECTS__
|
|
1583
|
-
function getGlobalMessage3(lang) {
|
|
1584
|
-
return store$33?.get(lang);
|
|
1585
|
-
}
|
|
1586
|
-
var store$23;
|
|
1587
|
-
// @__NO_SIDE_EFFECTS__
|
|
1588
|
-
function getSchemaMessage3(lang) {
|
|
1589
|
-
return store$23?.get(lang);
|
|
1590
|
-
}
|
|
1591
|
-
var store$13;
|
|
1592
|
-
// @__NO_SIDE_EFFECTS__
|
|
1593
|
-
function getSpecificMessage3(reference, lang) {
|
|
1594
|
-
return store$13?.get(reference)?.get(lang);
|
|
1595
|
-
}
|
|
1596
|
-
// @__NO_SIDE_EFFECTS__
|
|
1597
|
-
function _stringify3(input) {
|
|
1598
|
-
const type = typeof input;
|
|
1599
|
-
if (type === "string") return `"${input}"`;
|
|
1600
|
-
if (type === "number" || type === "bigint" || type === "boolean") return `${input}`;
|
|
1601
|
-
if (type === "object" || type === "function") return (input && Object.getPrototypeOf(input)?.constructor?.name) ?? "null";
|
|
1602
|
-
return type;
|
|
1603
|
-
}
|
|
1604
|
-
function _addIssue3(context, label, dataset, config$1, other) {
|
|
1605
|
-
const input = other && "input" in other ? other.input : dataset.value;
|
|
1606
|
-
const expected = other?.expected ?? context.expects ?? null;
|
|
1607
|
-
const received = other?.received ?? /* @__PURE__ */ _stringify3(input);
|
|
1608
|
-
const issue = {
|
|
1609
|
-
kind: context.kind,
|
|
1610
|
-
type: context.type,
|
|
1611
|
-
input,
|
|
1612
|
-
expected,
|
|
1613
|
-
received,
|
|
1614
|
-
message: `Invalid ${label}: ${expected ? `Expected ${expected} but r` : "R"}eceived ${received}`,
|
|
1615
|
-
requirement: context.requirement,
|
|
1616
|
-
path: other?.path,
|
|
1617
|
-
issues: other?.issues,
|
|
1618
|
-
lang: config$1.lang,
|
|
1619
|
-
abortEarly: config$1.abortEarly,
|
|
1620
|
-
abortPipeEarly: config$1.abortPipeEarly
|
|
1621
|
-
};
|
|
1622
|
-
const isSchema = context.kind === "schema";
|
|
1623
|
-
const message$1 = other?.message ?? context.message ?? /* @__PURE__ */ getSpecificMessage3(context.reference, issue.lang) ?? (isSchema ? /* @__PURE__ */ getSchemaMessage3(issue.lang) : null) ?? config$1.message ?? /* @__PURE__ */ getGlobalMessage3(issue.lang);
|
|
1624
|
-
if (message$1 !== void 0) issue.message = typeof message$1 === "function" ? message$1(issue) : message$1;
|
|
1625
|
-
if (isSchema) dataset.typed = false;
|
|
1626
|
-
if (dataset.issues) dataset.issues.push(issue);
|
|
1627
|
-
else dataset.issues = [issue];
|
|
1628
|
-
}
|
|
1629
|
-
var _standardCache3 = /* @__PURE__ */ new WeakMap();
|
|
1630
|
-
// @__NO_SIDE_EFFECTS__
|
|
1631
|
-
function _getStandardProps3(context) {
|
|
1632
|
-
let cached = _standardCache3.get(context);
|
|
1633
|
-
if (!cached) {
|
|
1634
|
-
cached = {
|
|
1635
|
-
version: 1,
|
|
1636
|
-
vendor: "valibot",
|
|
1637
|
-
validate(value$1) {
|
|
1638
|
-
return context["~run"]({ value: value$1 }, /* @__PURE__ */ getGlobalConfig3());
|
|
1639
|
-
}
|
|
1640
|
-
};
|
|
1641
|
-
_standardCache3.set(context, cached);
|
|
1642
|
-
}
|
|
1643
|
-
return cached;
|
|
1644
|
-
}
|
|
1645
|
-
var EMOJI_REGEX3 = new RegExp("^(?:[\\u{1F1E6}-\\u{1F1FF}]{2}|\\u{1F3F4}[\\u{E0061}-\\u{E007A}]{2}[\\u{E0030}-\\u{E0039}\\u{E0061}-\\u{E007A}]{1,3}\\u{E007F}|(?:\\p{Emoji}\\uFE0F\\u20E3?|\\p{Emoji_Modifier_Base}\\p{Emoji_Modifier}?|(?![\\p{Emoji_Modifier_Base}\\u{1F1E6}-\\u{1F1FF}])\\p{Emoji_Presentation})(?:\\u200D(?:\\p{Emoji}\\uFE0F\\u20E3?|\\p{Emoji_Modifier_Base}\\p{Emoji_Modifier}?|(?![\\p{Emoji_Modifier_Base}\\u{1F1E6}-\\u{1F1FF}])\\p{Emoji_Presentation}))*)+$", "u");
|
|
1646
|
-
// @__NO_SIDE_EFFECTS__
|
|
1647
|
-
function array3(item, message$1) {
|
|
1648
|
-
return {
|
|
1649
|
-
kind: "schema",
|
|
1650
|
-
type: "array",
|
|
1651
|
-
reference: array3,
|
|
1652
|
-
expects: "Array",
|
|
1653
|
-
async: false,
|
|
1654
|
-
item,
|
|
1655
|
-
message: message$1,
|
|
1656
|
-
get "~standard"() {
|
|
1657
|
-
return /* @__PURE__ */ _getStandardProps3(this);
|
|
1658
|
-
},
|
|
1659
|
-
"~run"(dataset, config$1) {
|
|
1660
|
-
const input = dataset.value;
|
|
1661
|
-
if (Array.isArray(input)) {
|
|
1662
|
-
dataset.typed = true;
|
|
1663
|
-
dataset.value = [];
|
|
1664
|
-
for (let key = 0; key < input.length; key++) {
|
|
1665
|
-
const value$1 = input[key];
|
|
1666
|
-
const itemDataset = this.item["~run"]({ value: value$1 }, config$1);
|
|
1667
|
-
if (itemDataset.issues) {
|
|
1668
|
-
const pathItem = {
|
|
1669
|
-
type: "array",
|
|
1670
|
-
origin: "value",
|
|
1671
|
-
input,
|
|
1672
|
-
key,
|
|
1673
|
-
value: value$1
|
|
1674
|
-
};
|
|
1675
|
-
for (const issue of itemDataset.issues) {
|
|
1676
|
-
if (issue.path) issue.path.unshift(pathItem);
|
|
1677
|
-
else issue.path = [pathItem];
|
|
1678
|
-
dataset.issues?.push(issue);
|
|
1679
|
-
}
|
|
1680
|
-
if (!dataset.issues) dataset.issues = itemDataset.issues;
|
|
1681
|
-
if (config$1.abortEarly) {
|
|
1682
|
-
dataset.typed = false;
|
|
1683
|
-
break;
|
|
1684
|
-
}
|
|
1685
|
-
}
|
|
1686
|
-
if (!itemDataset.typed) dataset.typed = false;
|
|
1687
|
-
dataset.value.push(itemDataset.value);
|
|
1688
|
-
}
|
|
1689
|
-
} else _addIssue3(this, "type", dataset, config$1);
|
|
1690
|
-
return dataset;
|
|
1691
|
-
}
|
|
1692
|
-
};
|
|
1693
|
-
}
|
|
1694
|
-
// @__NO_SIDE_EFFECTS__
|
|
1695
|
-
function string3(message$1) {
|
|
1696
|
-
return {
|
|
1697
|
-
kind: "schema",
|
|
1698
|
-
type: "string",
|
|
1699
|
-
reference: string3,
|
|
1700
|
-
expects: "string",
|
|
1701
|
-
async: false,
|
|
1702
|
-
message: message$1,
|
|
1703
|
-
get "~standard"() {
|
|
1704
|
-
return /* @__PURE__ */ _getStandardProps3(this);
|
|
1705
|
-
},
|
|
1706
|
-
"~run"(dataset, config$1) {
|
|
1707
|
-
if (typeof dataset.value === "string") dataset.typed = true;
|
|
1708
|
-
else _addIssue3(this, "type", dataset, config$1);
|
|
1709
|
-
return dataset;
|
|
1710
|
-
}
|
|
1711
|
-
};
|
|
1712
|
-
}
|
|
1713
|
-
// @__NO_SIDE_EFFECTS__
|
|
1714
|
-
function safeParse3(schema, input, config$1) {
|
|
1715
|
-
const dataset = schema["~run"]({ value: input }, /* @__PURE__ */ getGlobalConfig3(config$1));
|
|
1716
|
-
return {
|
|
1717
|
-
typed: dataset.typed,
|
|
1718
|
-
success: !dataset.issues,
|
|
1719
|
-
output: dataset.value,
|
|
1720
|
-
issues: dataset.issues
|
|
1721
|
-
};
|
|
1722
|
-
}
|
|
1723
|
-
var Monitor2 = class {
|
|
1724
|
-
type;
|
|
1725
|
-
schema;
|
|
1726
|
-
poll;
|
|
1727
|
-
webhook;
|
|
1728
|
-
constructor(options) {
|
|
1729
|
-
this.type = options.type;
|
|
1730
|
-
this.schema = options.schema;
|
|
1731
|
-
}
|
|
1732
|
-
validateSource(source) {
|
|
1733
|
-
const result = /* @__PURE__ */ safeParse3(this.schema, source);
|
|
1734
|
-
if (result.success) return result.output;
|
|
1735
|
-
throw new Error(`invalid ${this.type} monitor source`);
|
|
1736
|
-
}
|
|
1737
|
-
initialDelivery(source) {
|
|
1738
|
-
this.validateSource(source);
|
|
1739
|
-
if (this.webhook && this.webhook.preferred && this.webhook.configured()) return "webhook";
|
|
1740
|
-
if (this.poll) return "poll";
|
|
1741
|
-
if (this.webhook) return "webhook";
|
|
1742
|
-
throw new Error(`source ${this.type} has no configured transport`);
|
|
1743
|
-
}
|
|
1744
|
-
resolveDelivery(monitor) {
|
|
1745
|
-
let webhookHealthy = false;
|
|
1746
|
-
if (this.webhook) webhookHealthy = this.webhook.isHealthy(monitor);
|
|
1747
|
-
if (monitor.delivery === "webhook") {
|
|
1748
|
-
if (this.webhook && webhookHealthy) return "webhook";
|
|
1749
|
-
if (this.poll) return "poll";
|
|
1750
|
-
if (this.webhook) return "webhook";
|
|
1751
|
-
return void 0;
|
|
1752
|
-
}
|
|
1753
|
-
if (this.webhook && webhookHealthy) return "webhook";
|
|
1754
|
-
if (this.poll) return "poll";
|
|
1755
|
-
if (this.webhook) return "webhook";
|
|
1756
|
-
return void 0;
|
|
1757
|
-
}
|
|
1758
|
-
async tick(context, record2) {
|
|
1759
|
-
const fresh = await context.service.get(record2.id);
|
|
1760
|
-
if (!fresh || !fresh.enabled) return 0;
|
|
1761
|
-
if (this.webhook) await this.webhook.retryPending(context, this, fresh);
|
|
1762
|
-
const current = await context.service.get(record2.id);
|
|
1763
|
-
if (!current || !current.enabled) return 0;
|
|
1764
|
-
const nextDelivery = this.resolveDelivery(current);
|
|
1765
|
-
if (!nextDelivery) return 0;
|
|
1766
|
-
if (nextDelivery !== current.delivery) {
|
|
1767
|
-
await context.service.setDelivery(current.id, nextDelivery);
|
|
1768
|
-
current.delivery = nextDelivery;
|
|
1769
|
-
}
|
|
1770
|
-
if (current.delivery !== "poll" || !this.poll) return 0;
|
|
1771
|
-
const lastAttemptAt = Number(current.cursors.__lastAttemptAt ?? current.cursors.__lastPolledAt ?? 0);
|
|
1772
|
-
const pollIntervalSec = current.pollIntervalSec || 60;
|
|
1773
|
-
if (lastAttemptAt && Date.now() - lastAttemptAt < pollIntervalSec * 1e3) return 0;
|
|
1774
|
-
return this.poll.run(context, this, current);
|
|
1775
|
-
}
|
|
1776
|
-
async deliver(context, record2, event, deliveryId) {
|
|
1777
|
-
if (!this.webhook) return 0;
|
|
1778
|
-
return this.webhook.deliver(context, this, record2, event, deliveryId);
|
|
1779
|
-
}
|
|
1780
|
-
unresponsive(record2, now = Date.now()) {
|
|
1781
|
-
if (!record2.enabled) return false;
|
|
1782
|
-
if (record2.delivery === "poll") {
|
|
1783
|
-
if (!this.poll) return true;
|
|
1784
|
-
return this.poll.isUnresponsive(record2, now);
|
|
1785
|
-
}
|
|
1786
|
-
if (!this.webhook) return true;
|
|
1787
|
-
return this.webhook.isUnresponsive(record2, now);
|
|
1788
|
-
}
|
|
1789
|
-
};
|
|
1790
|
-
var RoutedEventCursorSchema2 = /* @__PURE__ */ array3(/* @__PURE__ */ string3());
|
|
1791
|
-
function eventDeliveryId2(event) {
|
|
1792
|
-
if (event.id) return event.id;
|
|
1793
|
-
return `${event.kind}:${event.at}:${event.summary}`;
|
|
1794
|
-
}
|
|
1795
|
-
var activePolls2 = /* @__PURE__ */ new Set();
|
|
1796
|
-
var PollMonitor2 = class {
|
|
1797
|
-
constructor(options) {
|
|
1798
|
-
this.options = options;
|
|
1799
|
-
}
|
|
1800
|
-
async run(context, source, record2) {
|
|
1801
|
-
if (activePolls2.has(record2.id)) return 0;
|
|
1802
|
-
activePolls2.add(record2.id);
|
|
1803
|
-
try {
|
|
1804
|
-
const fresh = await context.service.get(record2.id);
|
|
1805
|
-
if (!fresh) return 0;
|
|
1806
|
-
const sourceRecord = source.validateSource(fresh.source);
|
|
1807
|
-
const cursorKey = source.key(sourceRecord);
|
|
1808
|
-
const result = await this.options.run(sourceRecord, fresh.cursors[cursorKey]);
|
|
1809
|
-
const current = await context.service.get(record2.id);
|
|
1810
|
-
if (!current || !current.enabled) return 0;
|
|
1811
|
-
const parsedRoutedIds = /* @__PURE__ */ safeParse3(RoutedEventCursorSchema2, fresh.cursors.__routedEventIds);
|
|
1812
|
-
let routedIds = [];
|
|
1813
|
-
if (parsedRoutedIds.success) routedIds = parsedRoutedIds.output;
|
|
1814
|
-
let routeFailed = false;
|
|
1815
|
-
for (const event of result.events) {
|
|
1816
|
-
const eventId = eventDeliveryId2(event);
|
|
1817
|
-
if (routedIds.includes(eventId)) continue;
|
|
1818
|
-
const routed = await context.sink.deliver({ monitor: fresh, event });
|
|
1819
|
-
if (!routed.ok) {
|
|
1820
|
-
routeFailed = true;
|
|
1821
|
-
console.error(`[sourcefed] route failed for ${fresh.id}: ${routed.error}`);
|
|
1822
|
-
continue;
|
|
1823
|
-
}
|
|
1824
|
-
if (!routedIds.includes(eventId)) routedIds.push(eventId);
|
|
1825
|
-
}
|
|
1826
|
-
if (routeFailed) {
|
|
1827
|
-
await context.service.updateCursor(fresh, "__routedEventIds", routedIds);
|
|
1828
|
-
return 0;
|
|
1829
|
-
}
|
|
1830
|
-
await context.service.updateCursorValue(fresh, cursorKey, (current2) => {
|
|
1831
|
-
if (this.options.mergeCursor) return this.options.mergeCursor(current2, result.cursor);
|
|
1832
|
-
return result.cursor;
|
|
1833
|
-
});
|
|
1834
|
-
await context.service.updateCursor(fresh, "__routedEventIds", []);
|
|
1835
|
-
if (result.terminal) await context.service.remove(fresh.id);
|
|
1836
|
-
await context.service.updateCursor(fresh, "__lastPolledAt", Date.now());
|
|
1837
|
-
return result.events.length;
|
|
1838
|
-
} finally {
|
|
1839
|
-
activePolls2.delete(record2.id);
|
|
1840
|
-
}
|
|
1841
|
-
}
|
|
1842
|
-
isUnresponsive(record2, now) {
|
|
1843
|
-
const intervalMs = Math.max((record2.pollIntervalSec || 60) * 3e3, 12e4);
|
|
1844
|
-
const lastPolledAt = Number(record2.cursors.__lastPolledAt ?? 0);
|
|
1845
|
-
if (lastPolledAt > 0) return now - lastPolledAt > intervalMs;
|
|
1846
|
-
return now - Date.parse(record2.createdAt) > intervalMs;
|
|
1847
|
-
}
|
|
1848
|
-
};
|
|
1849
|
-
var MAX_WEBHOOK_BODY_BYTES3 = 1024 * 1024;
|
|
1850
|
-
function toMonitorEvent2(event, source) {
|
|
1851
|
-
return {
|
|
1852
|
-
source,
|
|
1853
|
-
kind: event.kind,
|
|
1854
|
-
id: event.id,
|
|
1855
|
-
at: event.at,
|
|
1856
|
-
summary: event.summary,
|
|
1857
|
-
body: event.body,
|
|
1858
|
-
actionable: event.actionable,
|
|
1859
|
-
terminal: event.terminal
|
|
1860
|
-
};
|
|
1861
|
-
}
|
|
1862
|
-
var store$423;
|
|
1863
|
-
var DEFAULT_CONFIG23 = {
|
|
1864
|
-
lang: void 0,
|
|
1865
|
-
message: void 0,
|
|
1866
|
-
abortEarly: void 0,
|
|
1867
|
-
abortPipeEarly: void 0
|
|
1868
|
-
};
|
|
1869
|
-
// @__NO_SIDE_EFFECTS__
|
|
1870
|
-
function getGlobalConfig23(config$1) {
|
|
1871
|
-
if (!config$1 && !store$423) return DEFAULT_CONFIG23;
|
|
1872
|
-
return {
|
|
1873
|
-
lang: config$1?.lang ?? store$423?.lang,
|
|
1874
|
-
message: config$1?.message,
|
|
1875
|
-
abortEarly: config$1?.abortEarly ?? store$423?.abortEarly,
|
|
1876
|
-
abortPipeEarly: config$1?.abortPipeEarly ?? store$423?.abortPipeEarly
|
|
1877
|
-
};
|
|
1878
|
-
}
|
|
1879
|
-
var store$323;
|
|
1880
|
-
// @__NO_SIDE_EFFECTS__
|
|
1881
|
-
function getGlobalMessage23(lang) {
|
|
1882
|
-
return store$323?.get(lang);
|
|
1883
|
-
}
|
|
1884
|
-
var store$223;
|
|
1885
|
-
// @__NO_SIDE_EFFECTS__
|
|
1886
|
-
function getSchemaMessage23(lang) {
|
|
1887
|
-
return store$223?.get(lang);
|
|
1888
|
-
}
|
|
1889
|
-
var store$123;
|
|
1890
|
-
// @__NO_SIDE_EFFECTS__
|
|
1891
|
-
function getSpecificMessage23(reference, lang) {
|
|
1892
|
-
return store$123?.get(reference)?.get(lang);
|
|
1893
|
-
}
|
|
1894
|
-
// @__NO_SIDE_EFFECTS__
|
|
1895
|
-
function _stringify23(input) {
|
|
1896
|
-
const type = typeof input;
|
|
1897
|
-
if (type === "string") return `"${input}"`;
|
|
1898
|
-
if (type === "number" || type === "bigint" || type === "boolean") return `${input}`;
|
|
1899
|
-
if (type === "object" || type === "function") return (input && Object.getPrototypeOf(input)?.constructor?.name) ?? "null";
|
|
1900
|
-
return type;
|
|
1901
|
-
}
|
|
1902
|
-
function _addIssue23(context, label, dataset, config$1, other) {
|
|
1903
|
-
const input = other && "input" in other ? other.input : dataset.value;
|
|
1904
|
-
const expected = other?.expected ?? context.expects ?? null;
|
|
1905
|
-
const received = other?.received ?? /* @__PURE__ */ _stringify23(input);
|
|
1906
|
-
const issue = {
|
|
1907
|
-
kind: context.kind,
|
|
1908
|
-
type: context.type,
|
|
1909
|
-
input,
|
|
1910
|
-
expected,
|
|
1911
|
-
received,
|
|
1912
|
-
message: `Invalid ${label}: ${expected ? `Expected ${expected} but r` : "R"}eceived ${received}`,
|
|
1913
|
-
requirement: context.requirement,
|
|
1914
|
-
path: other?.path,
|
|
1915
|
-
issues: other?.issues,
|
|
1916
|
-
lang: config$1.lang,
|
|
1917
|
-
abortEarly: config$1.abortEarly,
|
|
1918
|
-
abortPipeEarly: config$1.abortPipeEarly
|
|
1919
|
-
};
|
|
1920
|
-
const isSchema = context.kind === "schema";
|
|
1921
|
-
const message$1 = other?.message ?? context.message ?? /* @__PURE__ */ getSpecificMessage23(context.reference, issue.lang) ?? (isSchema ? /* @__PURE__ */ getSchemaMessage23(issue.lang) : null) ?? config$1.message ?? /* @__PURE__ */ getGlobalMessage23(issue.lang);
|
|
1922
|
-
if (message$1 !== void 0) issue.message = typeof message$1 === "function" ? message$1(issue) : message$1;
|
|
1923
|
-
if (isSchema) dataset.typed = false;
|
|
1924
|
-
if (dataset.issues) dataset.issues.push(issue);
|
|
1925
|
-
else dataset.issues = [issue];
|
|
1926
|
-
}
|
|
1927
|
-
var _standardCache23 = /* @__PURE__ */ new WeakMap();
|
|
1928
|
-
// @__NO_SIDE_EFFECTS__
|
|
1929
|
-
function _getStandardProps23(context) {
|
|
1930
|
-
let cached = _standardCache23.get(context);
|
|
1931
|
-
if (!cached) {
|
|
1932
|
-
cached = {
|
|
1933
|
-
version: 1,
|
|
1934
|
-
vendor: "valibot",
|
|
1935
|
-
validate(value$1) {
|
|
1936
|
-
return context["~run"]({ value: value$1 }, /* @__PURE__ */ getGlobalConfig23());
|
|
1937
|
-
}
|
|
1938
|
-
};
|
|
1939
|
-
_standardCache23.set(context, cached);
|
|
1940
|
-
}
|
|
1941
|
-
return cached;
|
|
1942
|
-
}
|
|
1943
|
-
var EMOJI_REGEX23 = new RegExp("^(?:[\\u{1F1E6}-\\u{1F1FF}]{2}|\\u{1F3F4}[\\u{E0061}-\\u{E007A}]{2}[\\u{E0030}-\\u{E0039}\\u{E0061}-\\u{E007A}]{1,3}\\u{E007F}|(?:\\p{Emoji}\\uFE0F\\u20E3?|\\p{Emoji_Modifier_Base}\\p{Emoji_Modifier}?|(?![\\p{Emoji_Modifier_Base}\\u{1F1E6}-\\u{1F1FF}])\\p{Emoji_Presentation})(?:\\u200D(?:\\p{Emoji}\\uFE0F\\u20E3?|\\p{Emoji_Modifier_Base}\\p{Emoji_Modifier}?|(?![\\p{Emoji_Modifier_Base}\\u{1F1E6}-\\u{1F1FF}])\\p{Emoji_Presentation}))*)+$", "u");
|
|
1944
|
-
// @__NO_SIDE_EFFECTS__
|
|
1945
|
-
function getFallback3(schema, dataset, config$1) {
|
|
1946
|
-
return typeof schema.fallback === "function" ? schema.fallback(dataset, config$1) : schema.fallback;
|
|
1947
|
-
}
|
|
1948
|
-
// @__NO_SIDE_EFFECTS__
|
|
1949
|
-
function getDefault3(schema, dataset, config$1) {
|
|
1950
|
-
return typeof schema.default === "function" ? schema.default(dataset, config$1) : schema.default;
|
|
1951
|
-
}
|
|
1952
|
-
// @__NO_SIDE_EFFECTS__
|
|
1953
|
-
function array23(item, message$1) {
|
|
1954
|
-
return {
|
|
1955
|
-
kind: "schema",
|
|
1956
|
-
type: "array",
|
|
1957
|
-
reference: array23,
|
|
1958
|
-
expects: "Array",
|
|
1959
|
-
async: false,
|
|
1960
|
-
item,
|
|
1961
|
-
message: message$1,
|
|
1962
|
-
get "~standard"() {
|
|
1963
|
-
return /* @__PURE__ */ _getStandardProps23(this);
|
|
1964
|
-
},
|
|
1965
|
-
"~run"(dataset, config$1) {
|
|
1966
|
-
const input = dataset.value;
|
|
1967
|
-
if (Array.isArray(input)) {
|
|
1968
|
-
dataset.typed = true;
|
|
1969
|
-
dataset.value = [];
|
|
1970
|
-
for (let key = 0; key < input.length; key++) {
|
|
1971
|
-
const value$1 = input[key];
|
|
1972
|
-
const itemDataset = this.item["~run"]({ value: value$1 }, config$1);
|
|
1973
|
-
if (itemDataset.issues) {
|
|
1974
|
-
const pathItem = {
|
|
1975
|
-
type: "array",
|
|
1976
|
-
origin: "value",
|
|
1977
|
-
input,
|
|
1978
|
-
key,
|
|
1979
|
-
value: value$1
|
|
1980
|
-
};
|
|
1981
|
-
for (const issue of itemDataset.issues) {
|
|
1982
|
-
if (issue.path) issue.path.unshift(pathItem);
|
|
1983
|
-
else issue.path = [pathItem];
|
|
1984
|
-
dataset.issues?.push(issue);
|
|
1985
|
-
}
|
|
1986
|
-
if (!dataset.issues) dataset.issues = itemDataset.issues;
|
|
1987
|
-
if (config$1.abortEarly) {
|
|
1988
|
-
dataset.typed = false;
|
|
1989
|
-
break;
|
|
1990
|
-
}
|
|
1991
|
-
}
|
|
1992
|
-
if (!itemDataset.typed) dataset.typed = false;
|
|
1993
|
-
dataset.value.push(itemDataset.value);
|
|
1994
|
-
}
|
|
1995
|
-
} else _addIssue23(this, "type", dataset, config$1);
|
|
1996
|
-
return dataset;
|
|
1997
|
-
}
|
|
1998
|
-
};
|
|
1999
|
-
}
|
|
2000
|
-
// @__NO_SIDE_EFFECTS__
|
|
2001
|
-
function literal2(literal_, message$1) {
|
|
2002
|
-
return {
|
|
2003
|
-
kind: "schema",
|
|
2004
|
-
type: "literal",
|
|
2005
|
-
reference: literal2,
|
|
2006
|
-
expects: /* @__PURE__ */ _stringify23(literal_),
|
|
2007
|
-
async: false,
|
|
2008
|
-
literal: literal_,
|
|
2009
|
-
message: message$1,
|
|
2010
|
-
get "~standard"() {
|
|
2011
|
-
return /* @__PURE__ */ _getStandardProps23(this);
|
|
2012
|
-
},
|
|
2013
|
-
"~run"(dataset, config$1) {
|
|
2014
|
-
if (dataset.value === this.literal) dataset.typed = true;
|
|
2015
|
-
else _addIssue23(this, "type", dataset, config$1);
|
|
2016
|
-
return dataset;
|
|
2017
|
-
}
|
|
2018
|
-
};
|
|
2019
|
-
}
|
|
2020
|
-
// @__NO_SIDE_EFFECTS__
|
|
2021
|
-
function number3(message$1) {
|
|
2022
|
-
return {
|
|
2023
|
-
kind: "schema",
|
|
2024
|
-
type: "number",
|
|
2025
|
-
reference: number3,
|
|
2026
|
-
expects: "number",
|
|
2027
|
-
async: false,
|
|
2028
|
-
message: message$1,
|
|
2029
|
-
get "~standard"() {
|
|
2030
|
-
return /* @__PURE__ */ _getStandardProps23(this);
|
|
2031
|
-
},
|
|
2032
|
-
"~run"(dataset, config$1) {
|
|
2033
|
-
if (typeof dataset.value === "number" && !isNaN(dataset.value)) dataset.typed = true;
|
|
2034
|
-
else _addIssue23(this, "type", dataset, config$1);
|
|
2035
|
-
return dataset;
|
|
2036
|
-
}
|
|
2037
|
-
};
|
|
2038
|
-
}
|
|
2039
|
-
// @__NO_SIDE_EFFECTS__
|
|
2040
|
-
function object3(entries$1, message$1) {
|
|
2041
|
-
return {
|
|
2042
|
-
kind: "schema",
|
|
2043
|
-
type: "object",
|
|
2044
|
-
reference: object3,
|
|
2045
|
-
expects: "Object",
|
|
2046
|
-
async: false,
|
|
2047
|
-
entries: entries$1,
|
|
2048
|
-
message: message$1,
|
|
2049
|
-
get "~standard"() {
|
|
2050
|
-
return /* @__PURE__ */ _getStandardProps23(this);
|
|
2051
|
-
},
|
|
2052
|
-
"~run"(dataset, config$1) {
|
|
2053
|
-
const input = dataset.value;
|
|
2054
|
-
if (input && typeof input === "object") {
|
|
2055
|
-
dataset.typed = true;
|
|
2056
|
-
dataset.value = {};
|
|
2057
|
-
for (const key in this.entries) {
|
|
2058
|
-
const valueSchema = this.entries[key];
|
|
2059
|
-
if (key in input || (valueSchema.type === "exact_optional" || valueSchema.type === "optional" || valueSchema.type === "nullish") && valueSchema.default !== void 0) {
|
|
2060
|
-
const value$1 = key in input ? input[key] : /* @__PURE__ */ getDefault3(valueSchema);
|
|
2061
|
-
const valueDataset = valueSchema["~run"]({ value: value$1 }, config$1);
|
|
2062
|
-
if (valueDataset.issues) {
|
|
2063
|
-
const pathItem = {
|
|
2064
|
-
type: "object",
|
|
2065
|
-
origin: "value",
|
|
2066
|
-
input,
|
|
2067
|
-
key,
|
|
2068
|
-
value: value$1
|
|
2069
|
-
};
|
|
2070
|
-
for (const issue of valueDataset.issues) {
|
|
2071
|
-
if (issue.path) issue.path.unshift(pathItem);
|
|
2072
|
-
else issue.path = [pathItem];
|
|
2073
|
-
dataset.issues?.push(issue);
|
|
2074
|
-
}
|
|
2075
|
-
if (!dataset.issues) dataset.issues = valueDataset.issues;
|
|
2076
|
-
if (config$1.abortEarly) {
|
|
2077
|
-
dataset.typed = false;
|
|
2078
|
-
break;
|
|
2079
|
-
}
|
|
2080
|
-
}
|
|
2081
|
-
if (!valueDataset.typed) dataset.typed = false;
|
|
2082
|
-
dataset.value[key] = valueDataset.value;
|
|
2083
|
-
} else if (valueSchema.fallback !== void 0) dataset.value[key] = /* @__PURE__ */ getFallback3(valueSchema);
|
|
2084
|
-
else if (valueSchema.type !== "exact_optional" && valueSchema.type !== "optional" && valueSchema.type !== "nullish") {
|
|
2085
|
-
_addIssue23(this, "key", dataset, config$1, {
|
|
2086
|
-
input: void 0,
|
|
2087
|
-
expected: `"${key}"`,
|
|
2088
|
-
path: [{
|
|
2089
|
-
type: "object",
|
|
2090
|
-
origin: "key",
|
|
2091
|
-
input,
|
|
2092
|
-
key,
|
|
2093
|
-
value: input[key]
|
|
2094
|
-
}]
|
|
2095
|
-
});
|
|
2096
|
-
if (config$1.abortEarly) break;
|
|
2097
|
-
}
|
|
2098
|
-
}
|
|
2099
|
-
} else _addIssue23(this, "type", dataset, config$1);
|
|
2100
|
-
return dataset;
|
|
2101
|
-
}
|
|
2102
|
-
};
|
|
2103
|
-
}
|
|
2104
|
-
// @__NO_SIDE_EFFECTS__
|
|
2105
|
-
function optional3(wrapped, default_) {
|
|
2106
|
-
return {
|
|
2107
|
-
kind: "schema",
|
|
2108
|
-
type: "optional",
|
|
2109
|
-
reference: optional3,
|
|
2110
|
-
expects: `(${wrapped.expects} | undefined)`,
|
|
2111
|
-
async: false,
|
|
2112
|
-
wrapped,
|
|
2113
|
-
default: default_,
|
|
2114
|
-
get "~standard"() {
|
|
2115
|
-
return /* @__PURE__ */ _getStandardProps23(this);
|
|
2116
|
-
},
|
|
2117
|
-
"~run"(dataset, config$1) {
|
|
2118
|
-
if (dataset.value === void 0) {
|
|
2119
|
-
if (this.default !== void 0) dataset.value = /* @__PURE__ */ getDefault3(this, dataset, config$1);
|
|
2120
|
-
if (dataset.value === void 0) {
|
|
2121
|
-
dataset.typed = true;
|
|
2122
|
-
return dataset;
|
|
2123
|
-
}
|
|
2124
|
-
}
|
|
2125
|
-
return this.wrapped["~run"](dataset, config$1);
|
|
2126
|
-
}
|
|
2127
|
-
};
|
|
2128
|
-
}
|
|
2129
|
-
// @__NO_SIDE_EFFECTS__
|
|
2130
|
-
function string23(message$1) {
|
|
2131
|
-
return {
|
|
2132
|
-
kind: "schema",
|
|
2133
|
-
type: "string",
|
|
2134
|
-
reference: string23,
|
|
2135
|
-
expects: "string",
|
|
2136
|
-
async: false,
|
|
2137
|
-
message: message$1,
|
|
2138
|
-
get "~standard"() {
|
|
2139
|
-
return /* @__PURE__ */ _getStandardProps23(this);
|
|
2140
|
-
},
|
|
2141
|
-
"~run"(dataset, config$1) {
|
|
2142
|
-
if (typeof dataset.value === "string") dataset.typed = true;
|
|
2143
|
-
else _addIssue23(this, "type", dataset, config$1);
|
|
2144
|
-
return dataset;
|
|
2145
|
-
}
|
|
2146
|
-
};
|
|
2147
|
-
}
|
|
2148
|
-
// @__NO_SIDE_EFFECTS__
|
|
2149
|
-
function safeParse23(schema, input, config$1) {
|
|
2150
|
-
const dataset = schema["~run"]({ value: input }, /* @__PURE__ */ getGlobalConfig23(config$1));
|
|
2151
|
-
return {
|
|
2152
|
-
typed: dataset.typed,
|
|
2153
|
-
success: !dataset.issues,
|
|
2154
|
-
output: dataset.value,
|
|
2155
|
-
issues: dataset.issues
|
|
2156
|
-
};
|
|
2157
|
-
}
|
|
2158
|
-
var JiraSourceSchema = /* @__PURE__ */ object3({
|
|
2159
|
-
type: /* @__PURE__ */ literal2("jira"),
|
|
2160
|
-
issueKey: /* @__PURE__ */ string23()
|
|
2161
|
-
});
|
|
2162
|
-
var JiraCursorSchema = /* @__PURE__ */ object3({
|
|
2163
|
-
commentIds: /* @__PURE__ */ array23(/* @__PURE__ */ number3()),
|
|
2164
|
-
descriptionVersion: /* @__PURE__ */ optional3(/* @__PURE__ */ string23()),
|
|
2165
|
-
changelogCount: /* @__PURE__ */ number3()
|
|
2166
|
-
});
|
|
2167
|
-
function jiraChangeValue(item, side) {
|
|
2168
|
-
let value = item.toString ?? item.to;
|
|
2169
|
-
if (side === "from") value = item.fromString ?? item.from;
|
|
2170
|
-
if (value === void 0 || value === null || value === "") return "none";
|
|
2171
|
-
return String(value);
|
|
2172
|
-
}
|
|
2173
|
-
function formatJiraChangelogItem(item) {
|
|
2174
|
-
return `${item.field}: ${jiraChangeValue(item, "from")} \u2192 ${jiraChangeValue(item, "to")}`;
|
|
2175
|
-
}
|
|
2176
|
-
function isTerminalStatus(status) {
|
|
2177
|
-
if (typeof status !== "string") return false;
|
|
2178
|
-
const terminalStatus = process.env.SOURCEFED_JIRA_TERMINAL_STATUS;
|
|
2179
|
-
if (!terminalStatus) return false;
|
|
2180
|
-
return status.trim().toLowerCase() === terminalStatus.trim().toLowerCase();
|
|
2181
|
-
}
|
|
2182
|
-
var TRACKED_CHANGE_FIELDS = /* @__PURE__ */ new Set(["summary", "status", "assignee", "priority", "labels"]);
|
|
2183
|
-
function meaningfulChangelogItems(items) {
|
|
2184
|
-
return items.filter((item) => {
|
|
2185
|
-
if (!TRACKED_CHANGE_FIELDS.has(String(item.field))) return false;
|
|
2186
|
-
return jiraChangeValue(item, "from") !== jiraChangeValue(item, "to");
|
|
2187
|
-
});
|
|
2188
|
-
}
|
|
2189
|
-
function jiraChangelogEvent(issueKey, history) {
|
|
2190
|
-
const changes = meaningfulChangelogItems(history.items ?? []);
|
|
2191
|
-
const items = changes.map(formatJiraChangelogItem).join("; ");
|
|
2192
|
-
if (!items) return void 0;
|
|
2193
|
-
const terminal = changes.some((item) => item.field === "status" && isTerminalStatus(jiraChangeValue(item, "to")));
|
|
2194
|
-
return {
|
|
2195
|
-
kind: "changelog",
|
|
2196
|
-
id: `history:${history.id ?? history.created ?? items}`,
|
|
2197
|
-
issueKey,
|
|
2198
|
-
at: history.created ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
2199
|
-
summary: `Jira ${issueKey} ${items}`,
|
|
2200
|
-
body: items,
|
|
2201
|
-
author: history.author?.displayName,
|
|
2202
|
-
actionable: true,
|
|
2203
|
-
terminal
|
|
2204
|
-
};
|
|
2205
|
-
}
|
|
2206
|
-
function appendJiraChangelog(issueKey, cursor, events, histories) {
|
|
2207
|
-
const total = histories.length;
|
|
2208
|
-
if (cursor.changelogCount !== 0 && total > cursor.changelogCount) {
|
|
2209
|
-
for (const history of histories.slice(cursor.changelogCount)) {
|
|
2210
|
-
const event = jiraChangelogEvent(issueKey, history);
|
|
2211
|
-
if (event) events.push(event);
|
|
2212
|
-
}
|
|
2213
|
-
}
|
|
2214
|
-
cursor.changelogCount = total;
|
|
2215
|
-
}
|
|
2216
|
-
function adfText(node) {
|
|
2217
|
-
if (!node || typeof node !== "object") return "";
|
|
2218
|
-
if (typeof node.text === "string") return node.text;
|
|
2219
|
-
if (Array.isArray(node.content)) return node.content.map(adfText).join("");
|
|
2220
|
-
return "";
|
|
2221
|
-
}
|
|
2222
|
-
function appendJiraComments(issueKey, cursor, events, comments) {
|
|
2223
|
-
const freshComments = [];
|
|
2224
|
-
for (const comment of comments) {
|
|
2225
|
-
const id2 = Number(comment.id);
|
|
2226
|
-
if (cursor.commentIds.includes(id2)) continue;
|
|
2227
|
-
freshComments.push(comment);
|
|
2228
|
-
}
|
|
2229
|
-
if (cursor.commentIds.length === 0) {
|
|
2230
|
-
cursor.commentIds = freshComments.map((comment) => Number(comment.id));
|
|
2231
|
-
return;
|
|
2232
|
-
}
|
|
2233
|
-
for (const comment of freshComments) {
|
|
2234
|
-
const body = adfText(comment.body);
|
|
2235
|
-
events.push({
|
|
2236
|
-
kind: "comment",
|
|
2237
|
-
id: `comment:${comment.id}`,
|
|
2238
|
-
issueKey,
|
|
2239
|
-
at: comment.created ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
2240
|
-
summary: `Jira ${issueKey} comment by ${comment.author?.displayName ?? "someone"}`,
|
|
2241
|
-
body,
|
|
2242
|
-
author: comment.author?.displayName,
|
|
2243
|
-
actionable: true
|
|
2244
|
-
});
|
|
2245
|
-
cursor.commentIds.push(Number(comment.id));
|
|
2246
|
-
}
|
|
2247
|
-
}
|
|
2248
|
-
function appendJiraDescription(issueKey, cursor, events, description) {
|
|
2249
|
-
let descriptionVersion = "none";
|
|
2250
|
-
if (description) descriptionVersion = JSON.stringify(description).slice(0, 40);
|
|
2251
|
-
if (cursor.descriptionVersion !== void 0 && descriptionVersion !== cursor.descriptionVersion) {
|
|
2252
|
-
events.push({
|
|
2253
|
-
kind: "description",
|
|
2254
|
-
id: `description:${descriptionVersion}`,
|
|
2255
|
-
issueKey,
|
|
2256
|
-
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2257
|
-
summary: `Jira ${issueKey} description updated`,
|
|
2258
|
-
body: adfText(description),
|
|
2259
|
-
actionable: true
|
|
2260
|
-
});
|
|
2261
|
-
}
|
|
2262
|
-
cursor.descriptionVersion = descriptionVersion;
|
|
2263
|
-
}
|
|
2264
|
-
function emptyJiraCursor() {
|
|
2265
|
-
return { commentIds: [], descriptionVersion: void 0, changelogCount: 0 };
|
|
2266
|
-
}
|
|
2267
|
-
function jiraAuth() {
|
|
2268
|
-
const email = process.env.ATLASSIAN_EMAIL;
|
|
2269
|
-
const key = process.env.ATLASSIAN_API_KEY;
|
|
2270
|
-
if (!email || !key) throw new Error("ATLASSIAN_EMAIL / ATLASSIAN_API_KEY not set");
|
|
2271
|
-
return "Basic " + Buffer.from(`${email}:${key}`).toString("base64");
|
|
2272
|
-
}
|
|
2273
|
-
var JIRA_BASE = process.env.SOURCEFED_JIRA_BASE_URL;
|
|
2274
|
-
async function jiraFetch(path22) {
|
|
2275
|
-
if (!JIRA_BASE) throw new Error("SOURCEFED_JIRA_BASE_URL is required for Jira monitors");
|
|
2276
|
-
const response = await fetch(`${JIRA_BASE}/rest/api/3${path22}`, {
|
|
2277
|
-
headers: { Authorization: jiraAuth(), Accept: "application/json" }
|
|
2278
|
-
});
|
|
2279
|
-
if (!response.ok) throw new Error(`Jira ${response.status} for ${path22}`);
|
|
2280
|
-
return response.json();
|
|
2281
|
-
}
|
|
2282
|
-
async function pollJira(issueKey, cursorRaw) {
|
|
2283
|
-
const parsedCursor = /* @__PURE__ */ safeParse23(JiraCursorSchema, cursorRaw);
|
|
2284
|
-
let cursor = emptyJiraCursor();
|
|
2285
|
-
if (parsedCursor.success) cursor = parsedCursor.output;
|
|
2286
|
-
const events = [];
|
|
2287
|
-
const comments = await jiraFetch(`/issue/${issueKey}/comment?maxResults=50&orderBy=-created`);
|
|
2288
|
-
appendJiraComments(issueKey, cursor, events, comments.comments ?? []);
|
|
2289
|
-
const issue = await jiraFetch(`/issue/${issueKey}?expand=changelog&fields=status,description`);
|
|
2290
|
-
const statusName = issue.fields?.status?.name;
|
|
2291
|
-
appendJiraDescription(issueKey, cursor, events, issue.fields?.description);
|
|
2292
|
-
const changelog = issue.changelog?.histories ?? [];
|
|
2293
|
-
appendJiraChangelog(issueKey, cursor, events, changelog);
|
|
2294
|
-
return { events, cursor, terminal: isTerminalStatus(statusName) };
|
|
2295
|
-
}
|
|
2296
|
-
var jiraPollMonitor = new PollMonitor2({
|
|
2297
|
-
run: async (source, cursor) => {
|
|
2298
|
-
const result = await pollJira(source.issueKey, cursor);
|
|
2299
|
-
return {
|
|
2300
|
-
cursor: result.cursor,
|
|
2301
|
-
events: result.events.map((event) => toMonitorEvent2(event, source)),
|
|
2302
|
-
terminal: result.terminal
|
|
2303
|
-
};
|
|
2304
|
-
}
|
|
2305
|
-
});
|
|
2306
|
-
var JiraMonitor = class extends Monitor2 {
|
|
2307
|
-
poll = jiraPollMonitor;
|
|
2308
|
-
constructor() {
|
|
2309
|
-
super({ type: "jira", schema: JiraSourceSchema });
|
|
2310
|
-
}
|
|
2311
|
-
key = (source) => `jira:${source.issueKey}`;
|
|
2312
|
-
icon = "\u{F0303}";
|
|
2313
|
-
label = (source) => source.issueKey;
|
|
2314
|
-
detail = (source) => ` ${source.issueKey}`;
|
|
2315
|
-
describe = (source) => `Jira ${source.issueKey}`;
|
|
2316
|
-
build(input) {
|
|
2317
|
-
if (input.issueKey) return { type: "jira", issueKey: input.issueKey };
|
|
2318
|
-
return { error: "issueKey is required for a jira monitor" };
|
|
2319
|
-
}
|
|
2320
|
-
};
|
|
2321
|
-
var store$44;
|
|
2322
|
-
var DEFAULT_CONFIG4 = {
|
|
2323
|
-
lang: void 0,
|
|
2324
|
-
message: void 0,
|
|
2325
|
-
abortEarly: void 0,
|
|
2326
|
-
abortPipeEarly: void 0
|
|
2327
|
-
};
|
|
2328
|
-
// @__NO_SIDE_EFFECTS__
|
|
2329
|
-
function getGlobalConfig4(config$1) {
|
|
2330
|
-
if (!config$1 && !store$44) return DEFAULT_CONFIG4;
|
|
2331
|
-
return {
|
|
2332
|
-
lang: config$1?.lang ?? store$44?.lang,
|
|
2333
|
-
message: config$1?.message,
|
|
2334
|
-
abortEarly: config$1?.abortEarly ?? store$44?.abortEarly,
|
|
2335
|
-
abortPipeEarly: config$1?.abortPipeEarly ?? store$44?.abortPipeEarly
|
|
2336
|
-
};
|
|
2337
|
-
}
|
|
2338
|
-
var store$34;
|
|
2339
|
-
// @__NO_SIDE_EFFECTS__
|
|
2340
|
-
function getGlobalMessage4(lang) {
|
|
2341
|
-
return store$34?.get(lang);
|
|
2342
|
-
}
|
|
2343
|
-
var store$24;
|
|
2344
|
-
// @__NO_SIDE_EFFECTS__
|
|
2345
|
-
function getSchemaMessage4(lang) {
|
|
2346
|
-
return store$24?.get(lang);
|
|
2347
|
-
}
|
|
2348
|
-
var store$14;
|
|
2349
|
-
// @__NO_SIDE_EFFECTS__
|
|
2350
|
-
function getSpecificMessage4(reference, lang) {
|
|
2351
|
-
return store$14?.get(reference)?.get(lang);
|
|
2352
|
-
}
|
|
2353
|
-
// @__NO_SIDE_EFFECTS__
|
|
2354
|
-
function _stringify4(input) {
|
|
2355
|
-
const type = typeof input;
|
|
2356
|
-
if (type === "string") return `"${input}"`;
|
|
2357
|
-
if (type === "number" || type === "bigint" || type === "boolean") return `${input}`;
|
|
2358
|
-
if (type === "object" || type === "function") return (input && Object.getPrototypeOf(input)?.constructor?.name) ?? "null";
|
|
2359
|
-
return type;
|
|
2360
|
-
}
|
|
2361
|
-
function _addIssue4(context, label, dataset, config$1, other) {
|
|
2362
|
-
const input = other && "input" in other ? other.input : dataset.value;
|
|
2363
|
-
const expected = other?.expected ?? context.expects ?? null;
|
|
2364
|
-
const received = other?.received ?? /* @__PURE__ */ _stringify4(input);
|
|
2365
|
-
const issue = {
|
|
2366
|
-
kind: context.kind,
|
|
2367
|
-
type: context.type,
|
|
2368
|
-
input,
|
|
2369
|
-
expected,
|
|
2370
|
-
received,
|
|
2371
|
-
message: `Invalid ${label}: ${expected ? `Expected ${expected} but r` : "R"}eceived ${received}`,
|
|
2372
|
-
requirement: context.requirement,
|
|
2373
|
-
path: other?.path,
|
|
2374
|
-
issues: other?.issues,
|
|
2375
|
-
lang: config$1.lang,
|
|
2376
|
-
abortEarly: config$1.abortEarly,
|
|
2377
|
-
abortPipeEarly: config$1.abortPipeEarly
|
|
2378
|
-
};
|
|
2379
|
-
const isSchema = context.kind === "schema";
|
|
2380
|
-
const message$1 = other?.message ?? context.message ?? /* @__PURE__ */ getSpecificMessage4(context.reference, issue.lang) ?? (isSchema ? /* @__PURE__ */ getSchemaMessage4(issue.lang) : null) ?? config$1.message ?? /* @__PURE__ */ getGlobalMessage4(issue.lang);
|
|
2381
|
-
if (message$1 !== void 0) issue.message = typeof message$1 === "function" ? message$1(issue) : message$1;
|
|
2382
|
-
if (isSchema) dataset.typed = false;
|
|
2383
|
-
if (dataset.issues) dataset.issues.push(issue);
|
|
2384
|
-
else dataset.issues = [issue];
|
|
2385
|
-
}
|
|
2386
|
-
var _standardCache4 = /* @__PURE__ */ new WeakMap();
|
|
2387
|
-
// @__NO_SIDE_EFFECTS__
|
|
2388
|
-
function _getStandardProps4(context) {
|
|
2389
|
-
let cached = _standardCache4.get(context);
|
|
2390
|
-
if (!cached) {
|
|
2391
|
-
cached = {
|
|
2392
|
-
version: 1,
|
|
2393
|
-
vendor: "valibot",
|
|
2394
|
-
validate(value$1) {
|
|
2395
|
-
return context["~run"]({ value: value$1 }, /* @__PURE__ */ getGlobalConfig4());
|
|
2396
|
-
}
|
|
2397
|
-
};
|
|
2398
|
-
_standardCache4.set(context, cached);
|
|
2399
|
-
}
|
|
2400
|
-
return cached;
|
|
2401
|
-
}
|
|
2402
|
-
var EMOJI_REGEX4 = new RegExp("^(?:[\\u{1F1E6}-\\u{1F1FF}]{2}|\\u{1F3F4}[\\u{E0061}-\\u{E007A}]{2}[\\u{E0030}-\\u{E0039}\\u{E0061}-\\u{E007A}]{1,3}\\u{E007F}|(?:\\p{Emoji}\\uFE0F\\u20E3?|\\p{Emoji_Modifier_Base}\\p{Emoji_Modifier}?|(?![\\p{Emoji_Modifier_Base}\\u{1F1E6}-\\u{1F1FF}])\\p{Emoji_Presentation})(?:\\u200D(?:\\p{Emoji}\\uFE0F\\u20E3?|\\p{Emoji_Modifier_Base}\\p{Emoji_Modifier}?|(?![\\p{Emoji_Modifier_Base}\\u{1F1E6}-\\u{1F1FF}])\\p{Emoji_Presentation}))*)+$", "u");
|
|
2403
|
-
// @__NO_SIDE_EFFECTS__
|
|
2404
|
-
function getFallback4(schema, dataset, config$1) {
|
|
2405
|
-
return typeof schema.fallback === "function" ? schema.fallback(dataset, config$1) : schema.fallback;
|
|
2406
|
-
}
|
|
2407
|
-
// @__NO_SIDE_EFFECTS__
|
|
2408
|
-
function getDefault4(schema, dataset, config$1) {
|
|
2409
|
-
return typeof schema.default === "function" ? schema.default(dataset, config$1) : schema.default;
|
|
2410
|
-
}
|
|
2411
|
-
// @__NO_SIDE_EFFECTS__
|
|
2412
|
-
function array4(item, message$1) {
|
|
2413
|
-
return {
|
|
2414
|
-
kind: "schema",
|
|
2415
|
-
type: "array",
|
|
2416
|
-
reference: array4,
|
|
2417
|
-
expects: "Array",
|
|
2418
|
-
async: false,
|
|
2419
|
-
item,
|
|
2420
|
-
message: message$1,
|
|
2421
|
-
get "~standard"() {
|
|
2422
|
-
return /* @__PURE__ */ _getStandardProps4(this);
|
|
2423
|
-
},
|
|
2424
|
-
"~run"(dataset, config$1) {
|
|
2425
|
-
const input = dataset.value;
|
|
2426
|
-
if (Array.isArray(input)) {
|
|
2427
|
-
dataset.typed = true;
|
|
2428
|
-
dataset.value = [];
|
|
2429
|
-
for (let key = 0; key < input.length; key++) {
|
|
2430
|
-
const value$1 = input[key];
|
|
2431
|
-
const itemDataset = this.item["~run"]({ value: value$1 }, config$1);
|
|
2432
|
-
if (itemDataset.issues) {
|
|
2433
|
-
const pathItem = {
|
|
2434
|
-
type: "array",
|
|
2435
|
-
origin: "value",
|
|
2436
|
-
input,
|
|
2437
|
-
key,
|
|
2438
|
-
value: value$1
|
|
2439
|
-
};
|
|
2440
|
-
for (const issue of itemDataset.issues) {
|
|
2441
|
-
if (issue.path) issue.path.unshift(pathItem);
|
|
2442
|
-
else issue.path = [pathItem];
|
|
2443
|
-
dataset.issues?.push(issue);
|
|
2444
|
-
}
|
|
2445
|
-
if (!dataset.issues) dataset.issues = itemDataset.issues;
|
|
2446
|
-
if (config$1.abortEarly) {
|
|
2447
|
-
dataset.typed = false;
|
|
2448
|
-
break;
|
|
2449
|
-
}
|
|
2450
|
-
}
|
|
2451
|
-
if (!itemDataset.typed) dataset.typed = false;
|
|
2452
|
-
dataset.value.push(itemDataset.value);
|
|
2453
|
-
}
|
|
2454
|
-
} else _addIssue4(this, "type", dataset, config$1);
|
|
2455
|
-
return dataset;
|
|
2456
|
-
}
|
|
2457
|
-
};
|
|
2458
|
-
}
|
|
2459
|
-
// @__NO_SIDE_EFFECTS__
|
|
2460
|
-
function boolean3(message$1) {
|
|
2461
|
-
return {
|
|
2462
|
-
kind: "schema",
|
|
2463
|
-
type: "boolean",
|
|
2464
|
-
reference: boolean3,
|
|
2465
|
-
expects: "boolean",
|
|
2466
|
-
async: false,
|
|
2467
|
-
message: message$1,
|
|
2468
|
-
get "~standard"() {
|
|
2469
|
-
return /* @__PURE__ */ _getStandardProps4(this);
|
|
2470
|
-
},
|
|
2471
|
-
"~run"(dataset, config$1) {
|
|
2472
|
-
if (typeof dataset.value === "boolean") dataset.typed = true;
|
|
2473
|
-
else _addIssue4(this, "type", dataset, config$1);
|
|
2474
|
-
return dataset;
|
|
2475
|
-
}
|
|
2476
|
-
};
|
|
2477
|
-
}
|
|
2478
|
-
// @__NO_SIDE_EFFECTS__
|
|
2479
|
-
function object4(entries$1, message$1) {
|
|
2480
|
-
return {
|
|
2481
|
-
kind: "schema",
|
|
2482
|
-
type: "object",
|
|
2483
|
-
reference: object4,
|
|
2484
|
-
expects: "Object",
|
|
2485
|
-
async: false,
|
|
2486
|
-
entries: entries$1,
|
|
2487
|
-
message: message$1,
|
|
2488
|
-
get "~standard"() {
|
|
2489
|
-
return /* @__PURE__ */ _getStandardProps4(this);
|
|
2490
|
-
},
|
|
2491
|
-
"~run"(dataset, config$1) {
|
|
2492
|
-
const input = dataset.value;
|
|
2493
|
-
if (input && typeof input === "object") {
|
|
2494
|
-
dataset.typed = true;
|
|
2495
|
-
dataset.value = {};
|
|
2496
|
-
for (const key in this.entries) {
|
|
2497
|
-
const valueSchema = this.entries[key];
|
|
2498
|
-
if (key in input || (valueSchema.type === "exact_optional" || valueSchema.type === "optional" || valueSchema.type === "nullish") && valueSchema.default !== void 0) {
|
|
2499
|
-
const value$1 = key in input ? input[key] : /* @__PURE__ */ getDefault4(valueSchema);
|
|
2500
|
-
const valueDataset = valueSchema["~run"]({ value: value$1 }, config$1);
|
|
2501
|
-
if (valueDataset.issues) {
|
|
2502
|
-
const pathItem = {
|
|
2503
|
-
type: "object",
|
|
2504
|
-
origin: "value",
|
|
2505
|
-
input,
|
|
2506
|
-
key,
|
|
2507
|
-
value: value$1
|
|
2508
|
-
};
|
|
2509
|
-
for (const issue of valueDataset.issues) {
|
|
2510
|
-
if (issue.path) issue.path.unshift(pathItem);
|
|
2511
|
-
else issue.path = [pathItem];
|
|
2512
|
-
dataset.issues?.push(issue);
|
|
2513
|
-
}
|
|
2514
|
-
if (!dataset.issues) dataset.issues = valueDataset.issues;
|
|
2515
|
-
if (config$1.abortEarly) {
|
|
2516
|
-
dataset.typed = false;
|
|
2517
|
-
break;
|
|
2518
|
-
}
|
|
2519
|
-
}
|
|
2520
|
-
if (!valueDataset.typed) dataset.typed = false;
|
|
2521
|
-
dataset.value[key] = valueDataset.value;
|
|
2522
|
-
} else if (valueSchema.fallback !== void 0) dataset.value[key] = /* @__PURE__ */ getFallback4(valueSchema);
|
|
2523
|
-
else if (valueSchema.type !== "exact_optional" && valueSchema.type !== "optional" && valueSchema.type !== "nullish") {
|
|
2524
|
-
_addIssue4(this, "key", dataset, config$1, {
|
|
2525
|
-
input: void 0,
|
|
2526
|
-
expected: `"${key}"`,
|
|
2527
|
-
path: [{
|
|
2528
|
-
type: "object",
|
|
2529
|
-
origin: "key",
|
|
2530
|
-
input,
|
|
2531
|
-
key,
|
|
2532
|
-
value: input[key]
|
|
2533
|
-
}]
|
|
2534
|
-
});
|
|
2535
|
-
if (config$1.abortEarly) break;
|
|
2536
|
-
}
|
|
2537
|
-
}
|
|
2538
|
-
} else _addIssue4(this, "type", dataset, config$1);
|
|
2539
|
-
return dataset;
|
|
2540
|
-
}
|
|
2541
|
-
};
|
|
2542
|
-
}
|
|
2543
|
-
// @__NO_SIDE_EFFECTS__
|
|
2544
|
-
function optional4(wrapped, default_) {
|
|
2545
|
-
return {
|
|
2546
|
-
kind: "schema",
|
|
2547
|
-
type: "optional",
|
|
2548
|
-
reference: optional4,
|
|
2549
|
-
expects: `(${wrapped.expects} | undefined)`,
|
|
2550
|
-
async: false,
|
|
2551
|
-
wrapped,
|
|
2552
|
-
default: default_,
|
|
2553
|
-
get "~standard"() {
|
|
2554
|
-
return /* @__PURE__ */ _getStandardProps4(this);
|
|
2555
|
-
},
|
|
2556
|
-
"~run"(dataset, config$1) {
|
|
2557
|
-
if (dataset.value === void 0) {
|
|
2558
|
-
if (this.default !== void 0) dataset.value = /* @__PURE__ */ getDefault4(this, dataset, config$1);
|
|
2559
|
-
if (dataset.value === void 0) {
|
|
2560
|
-
dataset.typed = true;
|
|
2561
|
-
return dataset;
|
|
2562
|
-
}
|
|
2563
|
-
}
|
|
2564
|
-
return this.wrapped["~run"](dataset, config$1);
|
|
2565
|
-
}
|
|
2566
|
-
};
|
|
2567
|
-
}
|
|
2568
|
-
// @__NO_SIDE_EFFECTS__
|
|
2569
|
-
function string4(message$1) {
|
|
2570
|
-
return {
|
|
2571
|
-
kind: "schema",
|
|
2572
|
-
type: "string",
|
|
2573
|
-
reference: string4,
|
|
2574
|
-
expects: "string",
|
|
2575
|
-
async: false,
|
|
2576
|
-
message: message$1,
|
|
2577
|
-
get "~standard"() {
|
|
2578
|
-
return /* @__PURE__ */ _getStandardProps4(this);
|
|
2579
|
-
},
|
|
2580
|
-
"~run"(dataset, config$1) {
|
|
2581
|
-
if (typeof dataset.value === "string") dataset.typed = true;
|
|
2582
|
-
else _addIssue4(this, "type", dataset, config$1);
|
|
2583
|
-
return dataset;
|
|
2584
|
-
}
|
|
2585
|
-
};
|
|
2586
|
-
}
|
|
2587
|
-
// @__NO_SIDE_EFFECTS__
|
|
2588
|
-
function unknown3() {
|
|
2589
|
-
return {
|
|
2590
|
-
kind: "schema",
|
|
2591
|
-
type: "unknown",
|
|
2592
|
-
reference: unknown3,
|
|
2593
|
-
expects: "unknown",
|
|
2594
|
-
async: false,
|
|
2595
|
-
get "~standard"() {
|
|
2596
|
-
return /* @__PURE__ */ _getStandardProps4(this);
|
|
2597
|
-
},
|
|
2598
|
-
"~run"(dataset) {
|
|
2599
|
-
dataset.typed = true;
|
|
2600
|
-
return dataset;
|
|
2601
|
-
}
|
|
2602
|
-
};
|
|
2603
|
-
}
|
|
2604
|
-
// @__NO_SIDE_EFFECTS__
|
|
2605
|
-
function safeParse4(schema, input, config$1) {
|
|
2606
|
-
const dataset = schema["~run"]({ value: input }, /* @__PURE__ */ getGlobalConfig4(config$1));
|
|
2607
|
-
return {
|
|
2608
|
-
typed: dataset.typed,
|
|
2609
|
-
success: !dataset.issues,
|
|
2610
|
-
output: dataset.value,
|
|
2611
|
-
issues: dataset.issues
|
|
2612
|
-
};
|
|
2613
|
-
}
|
|
2614
|
-
var Monitor3 = class {
|
|
2615
|
-
type;
|
|
2616
|
-
schema;
|
|
2617
|
-
poll;
|
|
2618
|
-
webhook;
|
|
2619
|
-
constructor(options) {
|
|
2620
|
-
this.type = options.type;
|
|
2621
|
-
this.schema = options.schema;
|
|
2622
|
-
}
|
|
2623
|
-
validateSource(source) {
|
|
2624
|
-
const result = /* @__PURE__ */ safeParse4(this.schema, source);
|
|
2625
|
-
if (result.success) return result.output;
|
|
2626
|
-
throw new Error(`invalid ${this.type} monitor source`);
|
|
2627
|
-
}
|
|
2628
|
-
initialDelivery(source) {
|
|
2629
|
-
this.validateSource(source);
|
|
2630
|
-
if (this.webhook && this.webhook.preferred && this.webhook.configured()) return "webhook";
|
|
2631
|
-
if (this.poll) return "poll";
|
|
2632
|
-
if (this.webhook) return "webhook";
|
|
2633
|
-
throw new Error(`source ${this.type} has no configured transport`);
|
|
2634
|
-
}
|
|
2635
|
-
resolveDelivery(monitor) {
|
|
2636
|
-
let webhookHealthy = false;
|
|
2637
|
-
if (this.webhook) webhookHealthy = this.webhook.isHealthy(monitor);
|
|
2638
|
-
if (monitor.delivery === "webhook") {
|
|
2639
|
-
if (this.webhook && webhookHealthy) return "webhook";
|
|
2640
|
-
if (this.poll) return "poll";
|
|
2641
|
-
if (this.webhook) return "webhook";
|
|
2642
|
-
return void 0;
|
|
2643
|
-
}
|
|
2644
|
-
if (this.webhook && webhookHealthy) return "webhook";
|
|
2645
|
-
if (this.poll) return "poll";
|
|
2646
|
-
if (this.webhook) return "webhook";
|
|
2647
|
-
return void 0;
|
|
2648
|
-
}
|
|
2649
|
-
async tick(context, record2) {
|
|
2650
|
-
const fresh = await context.service.get(record2.id);
|
|
2651
|
-
if (!fresh || !fresh.enabled) return 0;
|
|
2652
|
-
if (this.webhook) await this.webhook.retryPending(context, this, fresh);
|
|
2653
|
-
const current = await context.service.get(record2.id);
|
|
2654
|
-
if (!current || !current.enabled) return 0;
|
|
2655
|
-
const nextDelivery = this.resolveDelivery(current);
|
|
2656
|
-
if (!nextDelivery) return 0;
|
|
2657
|
-
if (nextDelivery !== current.delivery) {
|
|
2658
|
-
await context.service.setDelivery(current.id, nextDelivery);
|
|
2659
|
-
current.delivery = nextDelivery;
|
|
2660
|
-
}
|
|
2661
|
-
if (current.delivery !== "poll" || !this.poll) return 0;
|
|
2662
|
-
const lastAttemptAt = Number(current.cursors.__lastAttemptAt ?? current.cursors.__lastPolledAt ?? 0);
|
|
2663
|
-
const pollIntervalSec = current.pollIntervalSec || 60;
|
|
2664
|
-
if (lastAttemptAt && Date.now() - lastAttemptAt < pollIntervalSec * 1e3) return 0;
|
|
2665
|
-
return this.poll.run(context, this, current);
|
|
2666
|
-
}
|
|
2667
|
-
async deliver(context, record2, event, deliveryId) {
|
|
2668
|
-
if (!this.webhook) return 0;
|
|
2669
|
-
return this.webhook.deliver(context, this, record2, event, deliveryId);
|
|
2670
|
-
}
|
|
2671
|
-
unresponsive(record2, now = Date.now()) {
|
|
2672
|
-
if (!record2.enabled) return false;
|
|
2673
|
-
if (record2.delivery === "poll") {
|
|
2674
|
-
if (!this.poll) return true;
|
|
2675
|
-
return this.poll.isUnresponsive(record2, now);
|
|
2676
|
-
}
|
|
2677
|
-
if (!this.webhook) return true;
|
|
2678
|
-
return this.webhook.isUnresponsive(record2, now);
|
|
2679
|
-
}
|
|
2680
|
-
};
|
|
2681
|
-
var RoutedEventCursorSchema3 = /* @__PURE__ */ array4(/* @__PURE__ */ string4());
|
|
2682
|
-
function eventDeliveryId3(event) {
|
|
2683
|
-
if (event.id) return event.id;
|
|
2684
|
-
return `${event.kind}:${event.at}:${event.summary}`;
|
|
2685
|
-
}
|
|
2686
|
-
var activePolls3 = /* @__PURE__ */ new Set();
|
|
2687
|
-
var PollMonitor3 = class {
|
|
2688
|
-
constructor(options) {
|
|
2689
|
-
this.options = options;
|
|
2690
|
-
}
|
|
2691
|
-
async run(context, source, record2) {
|
|
2692
|
-
if (activePolls3.has(record2.id)) return 0;
|
|
2693
|
-
activePolls3.add(record2.id);
|
|
2694
|
-
try {
|
|
2695
|
-
const fresh = await context.service.get(record2.id);
|
|
2696
|
-
if (!fresh) return 0;
|
|
2697
|
-
const sourceRecord = source.validateSource(fresh.source);
|
|
2698
|
-
const cursorKey = source.key(sourceRecord);
|
|
2699
|
-
const result = await this.options.run(sourceRecord, fresh.cursors[cursorKey]);
|
|
2700
|
-
const current = await context.service.get(record2.id);
|
|
2701
|
-
if (!current || !current.enabled) return 0;
|
|
2702
|
-
const parsedRoutedIds = /* @__PURE__ */ safeParse4(RoutedEventCursorSchema3, fresh.cursors.__routedEventIds);
|
|
2703
|
-
let routedIds = [];
|
|
2704
|
-
if (parsedRoutedIds.success) routedIds = parsedRoutedIds.output;
|
|
2705
|
-
let routeFailed = false;
|
|
2706
|
-
for (const event of result.events) {
|
|
2707
|
-
const eventId = eventDeliveryId3(event);
|
|
2708
|
-
if (routedIds.includes(eventId)) continue;
|
|
2709
|
-
const routed = await context.sink.deliver({ monitor: fresh, event });
|
|
2710
|
-
if (!routed.ok) {
|
|
2711
|
-
routeFailed = true;
|
|
2712
|
-
console.error(`[sourcefed] route failed for ${fresh.id}: ${routed.error}`);
|
|
2713
|
-
continue;
|
|
2714
|
-
}
|
|
2715
|
-
if (!routedIds.includes(eventId)) routedIds.push(eventId);
|
|
2716
|
-
}
|
|
2717
|
-
if (routeFailed) {
|
|
2718
|
-
await context.service.updateCursor(fresh, "__routedEventIds", routedIds);
|
|
2719
|
-
return 0;
|
|
2720
|
-
}
|
|
2721
|
-
await context.service.updateCursorValue(fresh, cursorKey, (current2) => {
|
|
2722
|
-
if (this.options.mergeCursor) return this.options.mergeCursor(current2, result.cursor);
|
|
2723
|
-
return result.cursor;
|
|
2724
|
-
});
|
|
2725
|
-
await context.service.updateCursor(fresh, "__routedEventIds", []);
|
|
2726
|
-
if (result.terminal) await context.service.remove(fresh.id);
|
|
2727
|
-
await context.service.updateCursor(fresh, "__lastPolledAt", Date.now());
|
|
2728
|
-
return result.events.length;
|
|
2729
|
-
} finally {
|
|
2730
|
-
activePolls3.delete(record2.id);
|
|
2731
|
-
}
|
|
2732
|
-
}
|
|
2733
|
-
isUnresponsive(record2, now) {
|
|
2734
|
-
const intervalMs = Math.max((record2.pollIntervalSec || 60) * 3e3, 12e4);
|
|
2735
|
-
const lastPolledAt = Number(record2.cursors.__lastPolledAt ?? 0);
|
|
2736
|
-
if (lastPolledAt > 0) return now - lastPolledAt > intervalMs;
|
|
2737
|
-
return now - Date.parse(record2.createdAt) > intervalMs;
|
|
2738
|
-
}
|
|
2739
|
-
};
|
|
2740
|
-
var WEBHOOK_STALE_MS2 = 9e4;
|
|
2741
|
-
var WEBHOOK_STARTUP_GRACE_MS2 = 12e4;
|
|
2742
|
-
var PendingWebhookEventSchema2 = /* @__PURE__ */ object4({
|
|
2743
|
-
deliveryId: /* @__PURE__ */ string4(),
|
|
2744
|
-
event: /* @__PURE__ */ object4({
|
|
2745
|
-
source: /* @__PURE__ */ unknown3(),
|
|
2746
|
-
kind: /* @__PURE__ */ string4(),
|
|
2747
|
-
id: /* @__PURE__ */ optional4(/* @__PURE__ */ string4()),
|
|
2748
|
-
at: /* @__PURE__ */ string4(),
|
|
2749
|
-
summary: /* @__PURE__ */ string4(),
|
|
2750
|
-
body: /* @__PURE__ */ optional4(/* @__PURE__ */ string4()),
|
|
2751
|
-
actionable: /* @__PURE__ */ boolean3(),
|
|
2752
|
-
terminal: /* @__PURE__ */ optional4(/* @__PURE__ */ boolean3())
|
|
2753
|
-
})
|
|
2754
|
-
});
|
|
2755
|
-
var PendingWebhookEventsSchema2 = /* @__PURE__ */ array4(PendingWebhookEventSchema2);
|
|
2756
|
-
var pendingDeliveries2 = /* @__PURE__ */ new Set();
|
|
2757
|
-
var PENDING_WEBHOOK_EVENTS2 = "__pendingWebhookEvents";
|
|
2758
|
-
var WebhookMonitor2 = class {
|
|
2759
|
-
path;
|
|
2760
|
-
preferred;
|
|
2761
|
-
configured;
|
|
2762
|
-
verify;
|
|
2763
|
-
acknowledgeBeforeDelivery;
|
|
2764
|
-
challenge;
|
|
2765
|
-
deliveryId;
|
|
2766
|
-
eventName;
|
|
2767
|
-
parse;
|
|
2768
|
-
updateCursor;
|
|
2769
|
-
constructor(options) {
|
|
2770
|
-
this.path = options.path;
|
|
2771
|
-
this.preferred = options.preferred ?? true;
|
|
2772
|
-
this.configured = options.configured;
|
|
2773
|
-
this.verify = options.verify;
|
|
2774
|
-
this.acknowledgeBeforeDelivery = options.acknowledgeBeforeDelivery ?? false;
|
|
2775
|
-
this.challenge = options.challenge;
|
|
2776
|
-
this.deliveryId = options.deliveryId;
|
|
2777
|
-
this.eventName = options.eventName;
|
|
2778
|
-
this.parse = options.parse;
|
|
2779
|
-
this.updateCursor = options.updateCursor;
|
|
2780
|
-
}
|
|
2781
|
-
isHealthy(record2) {
|
|
2782
|
-
if (!this.preferred || !this.configured()) return false;
|
|
2783
|
-
const heartbeatAt = Number(record2.cursors.__webhookHeartbeatAt ?? 0);
|
|
2784
|
-
if (heartbeatAt > 0) return Date.now() - heartbeatAt <= WEBHOOK_STALE_MS2;
|
|
2785
|
-
return Date.now() - Date.parse(record2.createdAt) <= WEBHOOK_STARTUP_GRACE_MS2;
|
|
2786
|
-
}
|
|
2787
|
-
isUnresponsive(record2, now) {
|
|
2788
|
-
const heartbeatAt = Number(record2.cursors.__webhookHeartbeatAt ?? 0);
|
|
2789
|
-
if (heartbeatAt > 0) return now - heartbeatAt > WEBHOOK_STALE_MS2;
|
|
2790
|
-
return now - Date.parse(record2.createdAt) > WEBHOOK_STARTUP_GRACE_MS2;
|
|
2791
|
-
}
|
|
2792
|
-
async retryPending(context, source, record2) {
|
|
2793
|
-
const fresh = await context.service.get(record2.id);
|
|
2794
|
-
if (!fresh || !fresh.enabled) return 0;
|
|
2795
|
-
const parsed = /* @__PURE__ */ safeParse4(PendingWebhookEventsSchema2, fresh.cursors[PENDING_WEBHOOK_EVENTS2]);
|
|
2796
|
-
if (!parsed.success) return 0;
|
|
2797
|
-
let delivered = 0;
|
|
2798
|
-
for (const pending of parsed.output) {
|
|
2799
|
-
const current = await context.service.get(record2.id);
|
|
2800
|
-
if (!current || !current.enabled) break;
|
|
2801
|
-
const cursorKey = `webhook:${pending.deliveryId}`;
|
|
2802
|
-
if (current.cursors[cursorKey]) {
|
|
2803
|
-
await this.removePending(context, current, pending.deliveryId);
|
|
2804
|
-
continue;
|
|
2805
|
-
}
|
|
2806
|
-
delivered += await this.deliver(context, source, current, pending.event, pending.deliveryId);
|
|
2807
|
-
}
|
|
2808
|
-
return delivered;
|
|
2809
|
-
}
|
|
2810
|
-
async addPending(context, monitor, deliveryId, event) {
|
|
2811
|
-
await context.service.updateCursorValue(monitor, PENDING_WEBHOOK_EVENTS2, (cursor) => {
|
|
2812
|
-
const parsed = /* @__PURE__ */ safeParse4(PendingWebhookEventsSchema2, cursor);
|
|
2813
|
-
let pending = [];
|
|
2814
|
-
if (parsed.success) pending = parsed.output;
|
|
2815
|
-
if (pending.some((entry) => entry.deliveryId === deliveryId)) return pending;
|
|
2816
|
-
pending.push({ deliveryId, event });
|
|
2817
|
-
return pending;
|
|
2818
|
-
});
|
|
2819
|
-
}
|
|
2820
|
-
async removePending(context, monitor, deliveryId) {
|
|
2821
|
-
await context.service.updateCursorValue(monitor, PENDING_WEBHOOK_EVENTS2, (cursor) => {
|
|
2822
|
-
const parsed = /* @__PURE__ */ safeParse4(PendingWebhookEventsSchema2, cursor);
|
|
2823
|
-
if (!parsed.success) return [];
|
|
2824
|
-
return parsed.output.filter((entry) => entry.deliveryId !== deliveryId);
|
|
2825
|
-
});
|
|
2826
|
-
}
|
|
2827
|
-
async deliver(context, source, record2, event, deliveryId) {
|
|
2828
|
-
const fresh = await context.service.get(record2.id);
|
|
2829
|
-
if (!fresh || !fresh.enabled) return 0;
|
|
2830
|
-
const freshSource = source.validateSource(fresh.source);
|
|
2831
|
-
const eventSource = source.validateSource(event.source);
|
|
2832
|
-
if (source.key(freshSource) !== source.key(eventSource)) return 0;
|
|
2833
|
-
if (event.kind === "ci" && !event.actionable) return 0;
|
|
2834
|
-
const cursorKey = `webhook:${deliveryId}`;
|
|
2835
|
-
const reservationKey = `${fresh.id}:${deliveryId}`;
|
|
2836
|
-
if (pendingDeliveries2.has(reservationKey)) return 0;
|
|
2837
|
-
if (fresh.cursors[cursorKey]) {
|
|
2838
|
-
await this.removePending(context, fresh, deliveryId);
|
|
2839
|
-
return 0;
|
|
2840
|
-
}
|
|
2841
|
-
pendingDeliveries2.add(reservationKey);
|
|
2842
|
-
try {
|
|
2843
|
-
await this.addPending(context, fresh, deliveryId, event);
|
|
2844
|
-
if (this.updateCursor) {
|
|
2845
|
-
const sourceCursorKey = source.key(freshSource);
|
|
2846
|
-
await context.service.updateCursorValue(fresh, sourceCursorKey, (cursor) => this.updateCursor(event, cursor));
|
|
2847
|
-
}
|
|
2848
|
-
const result = await context.sink.deliver({ monitor: fresh, event });
|
|
2849
|
-
if (!result.ok) {
|
|
2850
|
-
console.error(`[sourcefed] webhook route failed for ${fresh.id}: ${result.error}`);
|
|
2851
|
-
return 0;
|
|
2852
|
-
}
|
|
2853
|
-
await context.service.setDelivery(fresh.id, "webhook");
|
|
2854
|
-
await context.service.updateCursor(fresh, cursorKey, true);
|
|
2855
|
-
await this.removePending(context, fresh, deliveryId);
|
|
2856
|
-
if (event.terminal) await context.service.remove(fresh.id);
|
|
2857
|
-
return 1;
|
|
2858
|
-
} finally {
|
|
2859
|
-
pendingDeliveries2.delete(reservationKey);
|
|
2860
|
-
}
|
|
2861
|
-
}
|
|
2862
|
-
};
|
|
2863
|
-
var MAX_WEBHOOK_BODY_BYTES4 = 1024 * 1024;
|
|
2864
|
-
function toMonitorEvent3(event, source) {
|
|
2865
|
-
return {
|
|
2866
|
-
source,
|
|
2867
|
-
kind: event.kind,
|
|
2868
|
-
id: event.id,
|
|
2869
|
-
at: event.at,
|
|
2870
|
-
summary: event.summary,
|
|
2871
|
-
body: event.body,
|
|
2872
|
-
actionable: event.actionable,
|
|
2873
|
-
terminal: event.terminal
|
|
2874
|
-
};
|
|
2875
|
-
}
|
|
2876
|
-
var store$424;
|
|
2877
|
-
var DEFAULT_CONFIG24 = {
|
|
2878
|
-
lang: void 0,
|
|
2879
|
-
message: void 0,
|
|
2880
|
-
abortEarly: void 0,
|
|
2881
|
-
abortPipeEarly: void 0
|
|
2882
|
-
};
|
|
2883
|
-
// @__NO_SIDE_EFFECTS__
|
|
2884
|
-
function getGlobalConfig24(config$1) {
|
|
2885
|
-
if (!config$1 && !store$424) return DEFAULT_CONFIG24;
|
|
2886
|
-
return {
|
|
2887
|
-
lang: config$1?.lang ?? store$424?.lang,
|
|
2888
|
-
message: config$1?.message,
|
|
2889
|
-
abortEarly: config$1?.abortEarly ?? store$424?.abortEarly,
|
|
2890
|
-
abortPipeEarly: config$1?.abortPipeEarly ?? store$424?.abortPipeEarly
|
|
2891
|
-
};
|
|
2892
|
-
}
|
|
2893
|
-
var store$324;
|
|
2894
|
-
// @__NO_SIDE_EFFECTS__
|
|
2895
|
-
function getGlobalMessage24(lang) {
|
|
2896
|
-
return store$324?.get(lang);
|
|
2897
|
-
}
|
|
2898
|
-
var store$224;
|
|
2899
|
-
// @__NO_SIDE_EFFECTS__
|
|
2900
|
-
function getSchemaMessage24(lang) {
|
|
2901
|
-
return store$224?.get(lang);
|
|
2902
|
-
}
|
|
2903
|
-
var store$124;
|
|
2904
|
-
// @__NO_SIDE_EFFECTS__
|
|
2905
|
-
function getSpecificMessage24(reference, lang) {
|
|
2906
|
-
return store$124?.get(reference)?.get(lang);
|
|
2907
|
-
}
|
|
2908
|
-
// @__NO_SIDE_EFFECTS__
|
|
2909
|
-
function _stringify24(input) {
|
|
2910
|
-
const type = typeof input;
|
|
2911
|
-
if (type === "string") return `"${input}"`;
|
|
2912
|
-
if (type === "number" || type === "bigint" || type === "boolean") return `${input}`;
|
|
2913
|
-
if (type === "object" || type === "function") return (input && Object.getPrototypeOf(input)?.constructor?.name) ?? "null";
|
|
2914
|
-
return type;
|
|
2915
|
-
}
|
|
2916
|
-
function _addIssue24(context, label, dataset, config$1, other) {
|
|
2917
|
-
const input = other && "input" in other ? other.input : dataset.value;
|
|
2918
|
-
const expected = other?.expected ?? context.expects ?? null;
|
|
2919
|
-
const received = other?.received ?? /* @__PURE__ */ _stringify24(input);
|
|
2920
|
-
const issue = {
|
|
2921
|
-
kind: context.kind,
|
|
2922
|
-
type: context.type,
|
|
2923
|
-
input,
|
|
2924
|
-
expected,
|
|
2925
|
-
received,
|
|
2926
|
-
message: `Invalid ${label}: ${expected ? `Expected ${expected} but r` : "R"}eceived ${received}`,
|
|
2927
|
-
requirement: context.requirement,
|
|
2928
|
-
path: other?.path,
|
|
2929
|
-
issues: other?.issues,
|
|
2930
|
-
lang: config$1.lang,
|
|
2931
|
-
abortEarly: config$1.abortEarly,
|
|
2932
|
-
abortPipeEarly: config$1.abortPipeEarly
|
|
2933
|
-
};
|
|
2934
|
-
const isSchema = context.kind === "schema";
|
|
2935
|
-
const message$1 = other?.message ?? context.message ?? /* @__PURE__ */ getSpecificMessage24(context.reference, issue.lang) ?? (isSchema ? /* @__PURE__ */ getSchemaMessage24(issue.lang) : null) ?? config$1.message ?? /* @__PURE__ */ getGlobalMessage24(issue.lang);
|
|
2936
|
-
if (message$1 !== void 0) issue.message = typeof message$1 === "function" ? message$1(issue) : message$1;
|
|
2937
|
-
if (isSchema) dataset.typed = false;
|
|
2938
|
-
if (dataset.issues) dataset.issues.push(issue);
|
|
2939
|
-
else dataset.issues = [issue];
|
|
2940
|
-
}
|
|
2941
|
-
var _standardCache24 = /* @__PURE__ */ new WeakMap();
|
|
2942
|
-
// @__NO_SIDE_EFFECTS__
|
|
2943
|
-
function _getStandardProps24(context) {
|
|
2944
|
-
let cached = _standardCache24.get(context);
|
|
2945
|
-
if (!cached) {
|
|
2946
|
-
cached = {
|
|
2947
|
-
version: 1,
|
|
2948
|
-
vendor: "valibot",
|
|
2949
|
-
validate(value$1) {
|
|
2950
|
-
return context["~run"]({ value: value$1 }, /* @__PURE__ */ getGlobalConfig24());
|
|
2951
|
-
}
|
|
2952
|
-
};
|
|
2953
|
-
_standardCache24.set(context, cached);
|
|
2954
|
-
}
|
|
2955
|
-
return cached;
|
|
2956
|
-
}
|
|
2957
|
-
var EMOJI_REGEX24 = new RegExp("^(?:[\\u{1F1E6}-\\u{1F1FF}]{2}|\\u{1F3F4}[\\u{E0061}-\\u{E007A}]{2}[\\u{E0030}-\\u{E0039}\\u{E0061}-\\u{E007A}]{1,3}\\u{E007F}|(?:\\p{Emoji}\\uFE0F\\u20E3?|\\p{Emoji_Modifier_Base}\\p{Emoji_Modifier}?|(?![\\p{Emoji_Modifier_Base}\\u{1F1E6}-\\u{1F1FF}])\\p{Emoji_Presentation})(?:\\u200D(?:\\p{Emoji}\\uFE0F\\u20E3?|\\p{Emoji_Modifier_Base}\\p{Emoji_Modifier}?|(?![\\p{Emoji_Modifier_Base}\\u{1F1E6}-\\u{1F1FF}])\\p{Emoji_Presentation}))*)+$", "u");
|
|
2958
|
-
// @__NO_SIDE_EFFECTS__
|
|
2959
|
-
function getFallback23(schema, dataset, config$1) {
|
|
2960
|
-
return typeof schema.fallback === "function" ? schema.fallback(dataset, config$1) : schema.fallback;
|
|
2961
|
-
}
|
|
2962
|
-
// @__NO_SIDE_EFFECTS__
|
|
2963
|
-
function getDefault23(schema, dataset, config$1) {
|
|
2964
|
-
return typeof schema.default === "function" ? schema.default(dataset, config$1) : schema.default;
|
|
2965
|
-
}
|
|
2966
|
-
// @__NO_SIDE_EFFECTS__
|
|
2967
|
-
function array24(item, message$1) {
|
|
2968
|
-
return {
|
|
2969
|
-
kind: "schema",
|
|
2970
|
-
type: "array",
|
|
2971
|
-
reference: array24,
|
|
2972
|
-
expects: "Array",
|
|
2973
|
-
async: false,
|
|
2974
|
-
item,
|
|
2975
|
-
message: message$1,
|
|
2976
|
-
get "~standard"() {
|
|
2977
|
-
return /* @__PURE__ */ _getStandardProps24(this);
|
|
2978
|
-
},
|
|
2979
|
-
"~run"(dataset, config$1) {
|
|
2980
|
-
const input = dataset.value;
|
|
2981
|
-
if (Array.isArray(input)) {
|
|
2982
|
-
dataset.typed = true;
|
|
2983
|
-
dataset.value = [];
|
|
2984
|
-
for (let key = 0; key < input.length; key++) {
|
|
2985
|
-
const value$1 = input[key];
|
|
2986
|
-
const itemDataset = this.item["~run"]({ value: value$1 }, config$1);
|
|
2987
|
-
if (itemDataset.issues) {
|
|
2988
|
-
const pathItem = {
|
|
2989
|
-
type: "array",
|
|
2990
|
-
origin: "value",
|
|
2991
|
-
input,
|
|
2992
|
-
key,
|
|
2993
|
-
value: value$1
|
|
2994
|
-
};
|
|
2995
|
-
for (const issue of itemDataset.issues) {
|
|
2996
|
-
if (issue.path) issue.path.unshift(pathItem);
|
|
2997
|
-
else issue.path = [pathItem];
|
|
2998
|
-
dataset.issues?.push(issue);
|
|
2999
|
-
}
|
|
3000
|
-
if (!dataset.issues) dataset.issues = itemDataset.issues;
|
|
3001
|
-
if (config$1.abortEarly) {
|
|
3002
|
-
dataset.typed = false;
|
|
3003
|
-
break;
|
|
3004
|
-
}
|
|
3005
|
-
}
|
|
3006
|
-
if (!itemDataset.typed) dataset.typed = false;
|
|
3007
|
-
dataset.value.push(itemDataset.value);
|
|
3008
|
-
}
|
|
3009
|
-
} else _addIssue24(this, "type", dataset, config$1);
|
|
3010
|
-
return dataset;
|
|
3011
|
-
}
|
|
3012
|
-
};
|
|
3013
|
-
}
|
|
3014
|
-
// @__NO_SIDE_EFFECTS__
|
|
3015
|
-
function boolean23(message$1) {
|
|
3016
|
-
return {
|
|
3017
|
-
kind: "schema",
|
|
3018
|
-
type: "boolean",
|
|
3019
|
-
reference: boolean23,
|
|
3020
|
-
expects: "boolean",
|
|
3021
|
-
async: false,
|
|
3022
|
-
message: message$1,
|
|
3023
|
-
get "~standard"() {
|
|
3024
|
-
return /* @__PURE__ */ _getStandardProps24(this);
|
|
3025
|
-
},
|
|
3026
|
-
"~run"(dataset, config$1) {
|
|
3027
|
-
if (typeof dataset.value === "boolean") dataset.typed = true;
|
|
3028
|
-
else _addIssue24(this, "type", dataset, config$1);
|
|
3029
|
-
return dataset;
|
|
3030
|
-
}
|
|
3031
|
-
};
|
|
3032
|
-
}
|
|
3033
|
-
// @__NO_SIDE_EFFECTS__
|
|
3034
|
-
function literal3(literal_, message$1) {
|
|
3035
|
-
return {
|
|
3036
|
-
kind: "schema",
|
|
3037
|
-
type: "literal",
|
|
3038
|
-
reference: literal3,
|
|
3039
|
-
expects: /* @__PURE__ */ _stringify24(literal_),
|
|
3040
|
-
async: false,
|
|
3041
|
-
literal: literal_,
|
|
3042
|
-
message: message$1,
|
|
3043
|
-
get "~standard"() {
|
|
3044
|
-
return /* @__PURE__ */ _getStandardProps24(this);
|
|
3045
|
-
},
|
|
3046
|
-
"~run"(dataset, config$1) {
|
|
3047
|
-
if (dataset.value === this.literal) dataset.typed = true;
|
|
3048
|
-
else _addIssue24(this, "type", dataset, config$1);
|
|
3049
|
-
return dataset;
|
|
3050
|
-
}
|
|
3051
|
-
};
|
|
3052
|
-
}
|
|
3053
|
-
// @__NO_SIDE_EFFECTS__
|
|
3054
|
-
function object23(entries$1, message$1) {
|
|
3055
|
-
return {
|
|
3056
|
-
kind: "schema",
|
|
3057
|
-
type: "object",
|
|
3058
|
-
reference: object23,
|
|
3059
|
-
expects: "Object",
|
|
3060
|
-
async: false,
|
|
3061
|
-
entries: entries$1,
|
|
3062
|
-
message: message$1,
|
|
3063
|
-
get "~standard"() {
|
|
3064
|
-
return /* @__PURE__ */ _getStandardProps24(this);
|
|
3065
|
-
},
|
|
3066
|
-
"~run"(dataset, config$1) {
|
|
3067
|
-
const input = dataset.value;
|
|
3068
|
-
if (input && typeof input === "object") {
|
|
3069
|
-
dataset.typed = true;
|
|
3070
|
-
dataset.value = {};
|
|
3071
|
-
for (const key in this.entries) {
|
|
3072
|
-
const valueSchema = this.entries[key];
|
|
3073
|
-
if (key in input || (valueSchema.type === "exact_optional" || valueSchema.type === "optional" || valueSchema.type === "nullish") && valueSchema.default !== void 0) {
|
|
3074
|
-
const value$1 = key in input ? input[key] : /* @__PURE__ */ getDefault23(valueSchema);
|
|
3075
|
-
const valueDataset = valueSchema["~run"]({ value: value$1 }, config$1);
|
|
3076
|
-
if (valueDataset.issues) {
|
|
3077
|
-
const pathItem = {
|
|
3078
|
-
type: "object",
|
|
3079
|
-
origin: "value",
|
|
3080
|
-
input,
|
|
3081
|
-
key,
|
|
3082
|
-
value: value$1
|
|
3083
|
-
};
|
|
3084
|
-
for (const issue of valueDataset.issues) {
|
|
3085
|
-
if (issue.path) issue.path.unshift(pathItem);
|
|
3086
|
-
else issue.path = [pathItem];
|
|
3087
|
-
dataset.issues?.push(issue);
|
|
3088
|
-
}
|
|
3089
|
-
if (!dataset.issues) dataset.issues = valueDataset.issues;
|
|
3090
|
-
if (config$1.abortEarly) {
|
|
3091
|
-
dataset.typed = false;
|
|
3092
|
-
break;
|
|
3093
|
-
}
|
|
3094
|
-
}
|
|
3095
|
-
if (!valueDataset.typed) dataset.typed = false;
|
|
3096
|
-
dataset.value[key] = valueDataset.value;
|
|
3097
|
-
} else if (valueSchema.fallback !== void 0) dataset.value[key] = /* @__PURE__ */ getFallback23(valueSchema);
|
|
3098
|
-
else if (valueSchema.type !== "exact_optional" && valueSchema.type !== "optional" && valueSchema.type !== "nullish") {
|
|
3099
|
-
_addIssue24(this, "key", dataset, config$1, {
|
|
3100
|
-
input: void 0,
|
|
3101
|
-
expected: `"${key}"`,
|
|
3102
|
-
path: [{
|
|
3103
|
-
type: "object",
|
|
3104
|
-
origin: "key",
|
|
3105
|
-
input,
|
|
3106
|
-
key,
|
|
3107
|
-
value: input[key]
|
|
3108
|
-
}]
|
|
3109
|
-
});
|
|
3110
|
-
if (config$1.abortEarly) break;
|
|
3111
|
-
}
|
|
3112
|
-
}
|
|
3113
|
-
} else _addIssue24(this, "type", dataset, config$1);
|
|
3114
|
-
return dataset;
|
|
3115
|
-
}
|
|
3116
|
-
};
|
|
3117
|
-
}
|
|
3118
|
-
// @__NO_SIDE_EFFECTS__
|
|
3119
|
-
function optional22(wrapped, default_) {
|
|
3120
|
-
return {
|
|
3121
|
-
kind: "schema",
|
|
3122
|
-
type: "optional",
|
|
3123
|
-
reference: optional22,
|
|
3124
|
-
expects: `(${wrapped.expects} | undefined)`,
|
|
3125
|
-
async: false,
|
|
3126
|
-
wrapped,
|
|
3127
|
-
default: default_,
|
|
3128
|
-
get "~standard"() {
|
|
3129
|
-
return /* @__PURE__ */ _getStandardProps24(this);
|
|
3130
|
-
},
|
|
3131
|
-
"~run"(dataset, config$1) {
|
|
3132
|
-
if (dataset.value === void 0) {
|
|
3133
|
-
if (this.default !== void 0) dataset.value = /* @__PURE__ */ getDefault23(this, dataset, config$1);
|
|
3134
|
-
if (dataset.value === void 0) {
|
|
3135
|
-
dataset.typed = true;
|
|
3136
|
-
return dataset;
|
|
3137
|
-
}
|
|
3138
|
-
}
|
|
3139
|
-
return this.wrapped["~run"](dataset, config$1);
|
|
3140
|
-
}
|
|
3141
|
-
};
|
|
3142
|
-
}
|
|
3143
|
-
// @__NO_SIDE_EFFECTS__
|
|
3144
|
-
function string24(message$1) {
|
|
3145
|
-
return {
|
|
3146
|
-
kind: "schema",
|
|
3147
|
-
type: "string",
|
|
3148
|
-
reference: string24,
|
|
3149
|
-
expects: "string",
|
|
3150
|
-
async: false,
|
|
3151
|
-
message: message$1,
|
|
3152
|
-
get "~standard"() {
|
|
3153
|
-
return /* @__PURE__ */ _getStandardProps24(this);
|
|
3154
|
-
},
|
|
3155
|
-
"~run"(dataset, config$1) {
|
|
3156
|
-
if (typeof dataset.value === "string") dataset.typed = true;
|
|
3157
|
-
else _addIssue24(this, "type", dataset, config$1);
|
|
3158
|
-
return dataset;
|
|
3159
|
-
}
|
|
3160
|
-
};
|
|
3161
|
-
}
|
|
3162
|
-
// @__NO_SIDE_EFFECTS__
|
|
3163
|
-
function safeParse24(schema, input, config$1) {
|
|
3164
|
-
const dataset = schema["~run"]({ value: input }, /* @__PURE__ */ getGlobalConfig24(config$1));
|
|
3165
|
-
return {
|
|
3166
|
-
typed: dataset.typed,
|
|
3167
|
-
success: !dataset.issues,
|
|
3168
|
-
output: dataset.value,
|
|
3169
|
-
issues: dataset.issues
|
|
3170
|
-
};
|
|
3171
|
-
}
|
|
3172
|
-
var SlackSourceSchema = /* @__PURE__ */ object23({
|
|
3173
|
-
type: /* @__PURE__ */ literal3("slack"),
|
|
3174
|
-
channelId: /* @__PURE__ */ string24(),
|
|
3175
|
-
threadTs: /* @__PURE__ */ string24()
|
|
3176
|
-
});
|
|
3177
|
-
var SlackCursorSchema = /* @__PURE__ */ object23({
|
|
3178
|
-
primed: /* @__PURE__ */ boolean23(),
|
|
3179
|
-
messageIds: /* @__PURE__ */ array24(/* @__PURE__ */ string24()),
|
|
3180
|
-
latestTs: /* @__PURE__ */ optional22(/* @__PURE__ */ string24())
|
|
3181
|
-
});
|
|
3182
|
-
function messageTimestamp(ts) {
|
|
3183
|
-
const value = Number(ts ?? 0);
|
|
3184
|
-
if (Number.isFinite(value)) return value;
|
|
3185
|
-
return 0;
|
|
3186
|
-
}
|
|
3187
|
-
function messageAt(ts) {
|
|
3188
|
-
const value = messageTimestamp(ts);
|
|
3189
|
-
if (value > 0) return new Date(value * 1e3).toISOString();
|
|
3190
|
-
return (/* @__PURE__ */ new Date()).toISOString();
|
|
3191
|
-
}
|
|
3192
|
-
function parseSlackReadResult(result, cursorRaw) {
|
|
3193
|
-
const parsedCursor = /* @__PURE__ */ safeParse24(SlackCursorSchema, cursorRaw);
|
|
3194
|
-
let previous = {};
|
|
3195
|
-
if (parsedCursor.success) previous = parsedCursor.output;
|
|
3196
|
-
const cursor = {
|
|
3197
|
-
primed: previous.primed ?? false,
|
|
3198
|
-
messageIds: previous.messageIds ?? [],
|
|
3199
|
-
latestTs: previous.latestTs
|
|
3200
|
-
};
|
|
3201
|
-
const users = new Map((result.users ?? []).map((user) => [user.id, user.real_name ?? user.name ?? user.id ?? "someone"]));
|
|
3202
|
-
const messages = (result.messages ?? []).filter((message) => message.ts);
|
|
3203
|
-
const freshMessages = messages.filter((message) => {
|
|
3204
|
-
if (cursor.messageIds.includes(message.ts)) return false;
|
|
3205
|
-
if (!cursor.latestTs) return true;
|
|
3206
|
-
return messageTimestamp(message.ts) > messageTimestamp(cursor.latestTs);
|
|
3207
|
-
});
|
|
3208
|
-
let events = [];
|
|
3209
|
-
if (cursor.primed) {
|
|
3210
|
-
events = freshMessages.map((message) => {
|
|
3211
|
-
let text = "[message without text]";
|
|
3212
|
-
if (message.text?.trim()) text = message.text.trim();
|
|
3213
|
-
let author = users.get(message.user);
|
|
3214
|
-
if (!author) author = message.user;
|
|
3215
|
-
if (!author) author = "someone";
|
|
3216
|
-
return {
|
|
3217
|
-
kind: "message",
|
|
3218
|
-
id: `message:${message.ts}`,
|
|
3219
|
-
at: messageAt(message.ts),
|
|
3220
|
-
summary: `Slack thread message by ${author}`,
|
|
3221
|
-
body: text,
|
|
3222
|
-
actionable: true
|
|
3223
|
-
};
|
|
3224
|
-
});
|
|
3225
|
-
}
|
|
3226
|
-
cursor.primed = true;
|
|
3227
|
-
cursor.messageIds = [.../* @__PURE__ */ new Set([...cursor.messageIds, ...messages.map((message) => message.ts)])].slice(-500);
|
|
3228
|
-
let latestTs = cursor.latestTs;
|
|
3229
|
-
for (const message of messages) {
|
|
3230
|
-
if (messageTimestamp(message.ts) > messageTimestamp(latestTs)) latestTs = message.ts;
|
|
3231
|
-
}
|
|
3232
|
-
cursor.latestTs = latestTs;
|
|
3233
|
-
return { events, cursor };
|
|
3234
|
-
}
|
|
3235
|
-
var SLACK_API = "https://slack.com/api";
|
|
3236
|
-
var warnedMissingToken2 = false;
|
|
3237
|
-
function slackToken() {
|
|
3238
|
-
return process.env.SOURCEFED_SLACK_TOKEN;
|
|
3239
|
-
}
|
|
3240
|
-
async function fetchSlackThread(channelId, threadTs) {
|
|
3241
|
-
const messages = [];
|
|
3242
|
-
let cursor = "";
|
|
3243
|
-
let received = false;
|
|
3244
|
-
do {
|
|
3245
|
-
const page = await slackApi("conversations.replies", {
|
|
3246
|
-
channel: channelId,
|
|
3247
|
-
ts: threadTs,
|
|
3248
|
-
limit: "1000",
|
|
3249
|
-
inclusive: "false",
|
|
3250
|
-
...cursor ? { cursor } : {}
|
|
3251
|
-
});
|
|
3252
|
-
if (!page) break;
|
|
3253
|
-
received = true;
|
|
3254
|
-
if (Array.isArray(page.messages)) messages.push(...page.messages);
|
|
3255
|
-
cursor = page.response_metadata?.next_cursor ?? "";
|
|
3256
|
-
if (messages.length >= 1e4) break;
|
|
3257
|
-
} while (cursor);
|
|
3258
|
-
if (!received) return void 0;
|
|
3259
|
-
const users = [];
|
|
3260
|
-
let usersCursor = "";
|
|
3261
|
-
do {
|
|
3262
|
-
const page = await slackApi("users.list", { limit: "200", ...usersCursor ? { cursor: usersCursor } : {} });
|
|
3263
|
-
if (!page) break;
|
|
3264
|
-
if (Array.isArray(page.members)) {
|
|
3265
|
-
users.push(...page.members.map((member) => ({
|
|
3266
|
-
id: member.id,
|
|
3267
|
-
name: member.name,
|
|
3268
|
-
real_name: member.real_name
|
|
3269
|
-
})));
|
|
3270
|
-
}
|
|
3271
|
-
usersCursor = page.response_metadata?.next_cursor ?? "";
|
|
3272
|
-
} while (usersCursor);
|
|
3273
|
-
const result = { messages, users };
|
|
3274
|
-
return result;
|
|
3275
|
-
}
|
|
3276
|
-
async function slackApi(method, params) {
|
|
3277
|
-
const token = slackToken();
|
|
3278
|
-
if (!token) {
|
|
3279
|
-
if (!warnedMissingToken2) {
|
|
3280
|
-
warnedMissingToken2 = true;
|
|
3281
|
-
console.warn("[sourcefed] SOURCEFED_SLACK_TOKEN is not set; Slack monitors will not poll");
|
|
3282
|
-
}
|
|
3283
|
-
return void 0;
|
|
3284
|
-
}
|
|
3285
|
-
try {
|
|
3286
|
-
const response = await fetch(`${SLACK_API}/${method}`, {
|
|
3287
|
-
method: "POST",
|
|
3288
|
-
headers: { authorization: `Bearer ${token}`, "content-type": "application/x-www-form-urlencoded" },
|
|
3289
|
-
body: new URLSearchParams(params)
|
|
3290
|
-
});
|
|
3291
|
-
const result = await response.json();
|
|
3292
|
-
if (!response.ok || result?.ok !== true) return void 0;
|
|
3293
|
-
return result;
|
|
3294
|
-
} catch {
|
|
3295
|
-
return void 0;
|
|
3296
|
-
}
|
|
3297
|
-
}
|
|
3298
|
-
async function pollSlack(source, cursorRaw) {
|
|
3299
|
-
const result = await fetchSlackThread(source.channelId, source.threadTs);
|
|
3300
|
-
if (!result) throw new Error("slack API request failed; check SOURCEFED_SLACK_TOKEN");
|
|
3301
|
-
const parsed = parseSlackReadResult(result, cursorRaw);
|
|
3302
|
-
return { ...parsed, terminal: false };
|
|
3303
|
-
}
|
|
3304
|
-
var slackPollMonitor = new PollMonitor3({
|
|
3305
|
-
run: async (source, cursor) => {
|
|
3306
|
-
const result = await pollSlack(source, cursor);
|
|
3307
|
-
return {
|
|
3308
|
-
cursor: result.cursor,
|
|
3309
|
-
events: result.events.map((event) => toMonitorEvent3(event, source)),
|
|
3310
|
-
terminal: result.terminal
|
|
3311
|
-
};
|
|
3312
|
-
}
|
|
3313
|
-
});
|
|
3314
|
-
function parseSlackWebhook(payload, _eventName, deliveryId) {
|
|
3315
|
-
const event = payload.event;
|
|
3316
|
-
const channelId = event?.channel;
|
|
3317
|
-
const threadTs = event?.thread_ts;
|
|
3318
|
-
if (payload.type !== "event_callback" || event?.type !== "message" || !channelId || !threadTs) return void 0;
|
|
3319
|
-
let text = "[message without text]";
|
|
3320
|
-
if (event.text?.trim()) text = event.text.trim();
|
|
3321
|
-
let author = event.username;
|
|
3322
|
-
if (!author) author = event.user;
|
|
3323
|
-
if (!author) author = event.bot_id;
|
|
3324
|
-
if (!author) author = "someone";
|
|
3325
|
-
let at = messageAt(event.event_ts);
|
|
3326
|
-
if (!event.event_ts) at = messageAt(event.ts);
|
|
3327
|
-
return {
|
|
3328
|
-
source: { type: "slack", channelId, threadTs },
|
|
3329
|
-
kind: "message",
|
|
3330
|
-
id: event.ts === void 0 ? void 0 : `message:${event.ts}`,
|
|
3331
|
-
at,
|
|
3332
|
-
summary: `Slack thread message by ${author}`,
|
|
3333
|
-
body: `${text}
|
|
3334
|
-
|
|
3335
|
-
Slack event: ${deliveryId}`,
|
|
3336
|
-
actionable: true
|
|
3337
|
-
};
|
|
3338
|
-
}
|
|
3339
|
-
function slackSignature(body, timestamp, secret) {
|
|
3340
|
-
return `v0=${createHmac2("sha256", secret).update(`v0:${timestamp}:${body}`).digest("hex")}`;
|
|
3341
|
-
}
|
|
3342
|
-
function validSlackSignature(body, request, secret = process.env.SOURCEFED_SLACK_SIGNING_SECRET) {
|
|
3343
|
-
const timestamp = request.headers.get("x-slack-request-timestamp");
|
|
3344
|
-
const signature = request.headers.get("x-slack-signature");
|
|
3345
|
-
const timestampValue = Number(timestamp);
|
|
3346
|
-
if (!timestamp || !signature || !secret || !Number.isFinite(timestampValue) || Math.abs(Date.now() / 1e3 - timestampValue) > 300) return false;
|
|
3347
|
-
const expected = slackSignature(body, timestamp, secret);
|
|
3348
|
-
const actual = Buffer.from(signature);
|
|
3349
|
-
const wanted = Buffer.from(expected);
|
|
3350
|
-
return actual.length === wanted.length && timingSafeEqual2(actual, wanted);
|
|
3351
|
-
}
|
|
3352
|
-
function updateSlackCursor(event, cursorRaw) {
|
|
3353
|
-
const parsed = /* @__PURE__ */ safeParse24(SlackCursorSchema, cursorRaw);
|
|
3354
|
-
let cursor = { primed: false, messageIds: [], latestTs: void 0 };
|
|
3355
|
-
if (parsed.success) cursor = parsed.output;
|
|
3356
|
-
if (event.id?.startsWith("message:")) {
|
|
3357
|
-
const messageId = event.id.slice("message:".length);
|
|
3358
|
-
if (!cursor.messageIds.includes(messageId)) cursor.messageIds.push(messageId);
|
|
3359
|
-
if (messageTimestamp(messageId) > messageTimestamp(cursor.latestTs)) cursor.latestTs = messageId;
|
|
3360
|
-
}
|
|
3361
|
-
cursor.primed = true;
|
|
3362
|
-
return cursor;
|
|
3363
|
-
}
|
|
3364
|
-
var slackWebhookMonitor = new WebhookMonitor2({
|
|
3365
|
-
path: "/webhooks/slack",
|
|
3366
|
-
preferred: true,
|
|
3367
|
-
configured: () => Boolean(process.env.SOURCEFED_SLACK_SIGNING_SECRET),
|
|
3368
|
-
verify: (body, request) => validSlackSignature(body, request),
|
|
3369
|
-
acknowledgeBeforeDelivery: true,
|
|
3370
|
-
challenge: (payload) => {
|
|
3371
|
-
if (payload.type === "url_verification" && payload.challenge) return { challenge: payload.challenge };
|
|
3372
|
-
return void 0;
|
|
3373
|
-
},
|
|
3374
|
-
deliveryId: (_request, payload) => payload.event_id,
|
|
3375
|
-
eventName: () => "slack",
|
|
3376
|
-
parse: parseSlackWebhook,
|
|
3377
|
-
updateCursor: updateSlackCursor
|
|
3378
|
-
});
|
|
3379
|
-
var SlackMonitor = class extends Monitor3 {
|
|
3380
|
-
poll = slackPollMonitor;
|
|
3381
|
-
webhook = slackWebhookMonitor;
|
|
3382
|
-
constructor() {
|
|
3383
|
-
super({ type: "slack", schema: SlackSourceSchema });
|
|
3384
|
-
}
|
|
3385
|
-
key = (source) => `slack:${source.channelId}#${source.threadTs}`;
|
|
3386
|
-
icon = "\u{F04B1}";
|
|
3387
|
-
label = () => "thread";
|
|
3388
|
-
detail = (source) => ` ${source.channelId}`;
|
|
3389
|
-
describe = (source) => `Slack ${source.channelId} thread ${source.threadTs}`;
|
|
3390
|
-
build(input) {
|
|
3391
|
-
if (input.channelId && input.threadTs) return { type: "slack", channelId: input.channelId, threadTs: input.threadTs };
|
|
3392
|
-
if (!input.threadUrl) return { error: "channelId + threadTs or threadUrl is required for a slack monitor" };
|
|
3393
|
-
let url;
|
|
3394
|
-
try {
|
|
3395
|
-
url = new URL(input.threadUrl);
|
|
3396
|
-
} catch {
|
|
3397
|
-
return { error: "threadUrl must be a valid Slack URL" };
|
|
3398
|
-
}
|
|
3399
|
-
const channelId = url.pathname.match(/\/archives\/([^/]+)/)?.[1];
|
|
3400
|
-
const pathTimestamp = url.pathname.match(/\/p(\d{10,})/)?.[1];
|
|
3401
|
-
let threadTs = url.searchParams.get("thread_ts") ?? void 0;
|
|
3402
|
-
if (!threadTs && pathTimestamp) threadTs = `${pathTimestamp.slice(0, -6)}.${pathTimestamp.slice(-6)}`;
|
|
3403
|
-
if (channelId && threadTs) return { type: "slack", channelId, threadTs };
|
|
3404
|
-
return { error: "threadUrl does not contain a Slack channel and thread timestamp" };
|
|
3405
|
-
}
|
|
3406
|
-
};
|
|
3407
|
-
var SOURCE_MAP = {
|
|
3408
|
-
jira: new JiraMonitor(),
|
|
3409
|
-
github: new GithubMonitor(),
|
|
3410
|
-
slack: new SlackMonitor()
|
|
3411
|
-
};
|
|
3412
|
-
var SOURCE_TYPES = Object.keys(SOURCE_MAP);
|
|
3413
|
-
var RequestRouter = class {
|
|
3414
|
-
pending = /* @__PURE__ */ new Map();
|
|
3415
|
-
cursor = 1;
|
|
3416
|
-
nextID() {
|
|
3417
|
-
return this.cursor++;
|
|
3418
|
-
}
|
|
3419
|
-
register(id2) {
|
|
3420
|
-
return new Promise((resolve, reject) => {
|
|
3421
|
-
this.pending.set(id2, { resolve, reject });
|
|
3422
|
-
});
|
|
3423
|
-
}
|
|
3424
|
-
settle(id2, frame) {
|
|
3425
|
-
const pending = this.pending.get(id2);
|
|
3426
|
-
if (!pending) return;
|
|
3427
|
-
this.pending.delete(id2);
|
|
3428
|
-
if (frame.error) pending.reject(new Error(frame.error));
|
|
3429
|
-
else pending.resolve(frame.result);
|
|
3430
|
-
}
|
|
3431
|
-
rejectAll(error) {
|
|
3432
|
-
for (const { reject } of this.pending.values()) reject(error);
|
|
3433
|
-
this.pending.clear();
|
|
3434
|
-
}
|
|
3435
|
-
};
|
|
3436
|
-
function defaultDaemonUrl() {
|
|
3437
|
-
const port = process.env.SOURCEFED_DAEMON_PORT ?? 18787;
|
|
3438
|
-
return `http://127.0.0.1:${port}`;
|
|
3439
|
-
}
|
|
3440
|
-
function sleep(ms) {
|
|
3441
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
3442
|
-
}
|
|
3443
|
-
async function withTimeout(promise, ms, message) {
|
|
3444
|
-
let timer;
|
|
3445
|
-
try {
|
|
3446
|
-
return await Promise.race([
|
|
3447
|
-
promise,
|
|
3448
|
-
new Promise((_resolve, reject) => {
|
|
3449
|
-
timer = setTimeout(() => reject(new Error(message)), ms);
|
|
3450
|
-
})
|
|
3451
|
-
]);
|
|
3452
|
-
} finally {
|
|
3453
|
-
if (timer) clearTimeout(timer);
|
|
3454
|
-
}
|
|
3455
|
-
}
|
|
3456
|
-
function encodeTarget(target) {
|
|
3457
|
-
return Buffer.from(JSON.stringify(target), "utf8").toString("base64url");
|
|
3458
|
-
}
|
|
3459
|
-
function targetKey(target) {
|
|
3460
|
-
return JSON.stringify(target);
|
|
3461
|
-
}
|
|
3462
|
-
function parseDaemonFrame(line) {
|
|
3463
|
-
try {
|
|
3464
|
-
return JSON.parse(line);
|
|
3465
|
-
} catch {
|
|
3466
|
-
return void 0;
|
|
3467
|
-
}
|
|
3468
|
-
}
|
|
3469
|
-
async function connectDaemonClient(options) {
|
|
3470
|
-
const url = options.url ?? process.env.SOURCEFED_DAEMON_URL ?? defaultDaemonUrl();
|
|
3471
|
-
return new HttpDaemonClient(url, options.token ?? process.env.SOURCEFED_DAEMON_TOKEN);
|
|
3472
|
-
}
|
|
3473
|
-
var HttpDaemonClient = class {
|
|
3474
|
-
baseURL;
|
|
3475
|
-
token;
|
|
3476
|
-
router = new RequestRouter();
|
|
3477
|
-
listeners = /* @__PURE__ */ new Map();
|
|
3478
|
-
streams = /* @__PURE__ */ new Set();
|
|
3479
|
-
constructor(baseURL, token) {
|
|
3480
|
-
this.baseURL = baseURL.replace(/\/+$/, "");
|
|
3481
|
-
this.token = token;
|
|
3482
|
-
}
|
|
3483
|
-
headers() {
|
|
3484
|
-
return this.token ? { authorization: `Bearer ${this.token}` } : {};
|
|
3485
|
-
}
|
|
3486
|
-
async request(method, params) {
|
|
3487
|
-
const id2 = this.router.nextID();
|
|
3488
|
-
const promise = this.router.register(id2);
|
|
3489
|
-
try {
|
|
3490
|
-
const response = await fetch(`${this.baseURL}/rpc`, {
|
|
3491
|
-
method: "POST",
|
|
3492
|
-
headers: { "content-type": "application/json", ...this.headers() },
|
|
3493
|
-
body: JSON.stringify({ id: id2, method, params })
|
|
3494
|
-
});
|
|
3495
|
-
const frame = await response.json();
|
|
3496
|
-
if (!response.ok || frame.error) throw new Error(frame.error ?? `daemon request failed: ${response.status}`);
|
|
3497
|
-
this.router.settle(id2, { result: frame.result });
|
|
3498
|
-
} catch (error) {
|
|
3499
|
-
this.router.settle(id2, { error: error instanceof Error ? error.message : String(error) });
|
|
3500
|
-
}
|
|
3501
|
-
return promise;
|
|
3502
|
-
}
|
|
3503
|
-
async subscribe(target, onEvents) {
|
|
3504
|
-
const key = targetKey(target);
|
|
3505
|
-
let callbacks = this.listeners.get(key);
|
|
3506
|
-
if (!callbacks) {
|
|
3507
|
-
callbacks = /* @__PURE__ */ new Set();
|
|
3508
|
-
this.listeners.set(key, callbacks);
|
|
3509
|
-
}
|
|
3510
|
-
callbacks.add(onEvents);
|
|
3511
|
-
const controller = new AbortController();
|
|
3512
|
-
this.streams.add(controller);
|
|
3513
|
-
const url = `${this.baseURL}/events?target=${encodeTarget(target)}`;
|
|
3514
|
-
let markSubscribed;
|
|
3515
|
-
const subscribed = new Promise((resolve) => {
|
|
3516
|
-
markSubscribed = () => resolve();
|
|
3517
|
-
});
|
|
3518
|
-
let drainComplete = false;
|
|
3519
|
-
let draining = false;
|
|
3520
|
-
let redrainRequested = false;
|
|
3521
|
-
let retryTimer;
|
|
3522
|
-
let markDrained;
|
|
3523
|
-
const drained = new Promise((resolve) => {
|
|
3524
|
-
markDrained = resolve;
|
|
3525
|
-
});
|
|
3526
|
-
let buffered = [];
|
|
3527
|
-
let delivering = Promise.resolve();
|
|
3528
|
-
const deliver = (events) => {
|
|
3529
|
-
if (!callbacks?.has(onEvents) || events.length === 0) return Promise.resolve();
|
|
3530
|
-
delivering = delivering.then(() => deliverWithRetry(events, 0)).catch((error) => {
|
|
3531
|
-
console.error(`[sourcefed] event delivery failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
3532
|
-
});
|
|
3533
|
-
return delivering;
|
|
3534
|
-
};
|
|
3535
|
-
const deliverWithRetry = async (events, attempt) => {
|
|
3536
|
-
try {
|
|
3537
|
-
await onEvents(events);
|
|
3538
|
-
} catch (error) {
|
|
3539
|
-
if (attempt >= 2) {
|
|
3540
|
-
console.error(`[sourcefed] event delivery failed after retries; re-draining queue: ${error instanceof Error ? error.message : String(error)}`);
|
|
3541
|
-
redrainRequested = true;
|
|
3542
|
-
void performDrain();
|
|
3543
|
-
return;
|
|
3544
|
-
}
|
|
3545
|
-
await sleep(250 * (attempt + 1));
|
|
3546
|
-
await deliverWithRetry(events, attempt + 1);
|
|
3547
|
-
}
|
|
3548
|
-
};
|
|
3549
|
-
const performDrain = async () => {
|
|
3550
|
-
if (draining) {
|
|
3551
|
-
redrainRequested = true;
|
|
3552
|
-
return;
|
|
3553
|
-
}
|
|
3554
|
-
draining = true;
|
|
3555
|
-
try {
|
|
3556
|
-
let passes = 0;
|
|
3557
|
-
do {
|
|
3558
|
-
redrainRequested = false;
|
|
3559
|
-
passes += 1;
|
|
3560
|
-
try {
|
|
3561
|
-
const drainResult = await this.request("monitor.events", { target });
|
|
3562
|
-
drainComplete = true;
|
|
3563
|
-
const drainedIds = new Set((drainResult.events ?? []).map((event) => event.id));
|
|
3564
|
-
if (drainResult.events && drainResult.events.length > 0) await deliver(drainResult.events);
|
|
3565
|
-
for (const batch of buffered) {
|
|
3566
|
-
const fresh = batch.filter((event) => !drainedIds.has(event.id));
|
|
3567
|
-
if (fresh.length > 0) await deliver(fresh);
|
|
3568
|
-
}
|
|
3569
|
-
buffered = [];
|
|
3570
|
-
markDrained();
|
|
3571
|
-
} catch (error) {
|
|
3572
|
-
console.error(`[sourcefed] event drain failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
3573
|
-
redrainRequested = true;
|
|
3574
|
-
}
|
|
3575
|
-
} while (redrainRequested && passes < 3);
|
|
3576
|
-
if (redrainRequested) markDrained();
|
|
3577
|
-
} finally {
|
|
3578
|
-
draining = false;
|
|
3579
|
-
}
|
|
3580
|
-
};
|
|
3581
|
-
const runStream = async () => {
|
|
3582
|
-
try {
|
|
3583
|
-
const response = await fetch(url, { signal: controller.signal, headers: this.headers() });
|
|
3584
|
-
if (!response.ok || !response.body) throw new Error(`event stream failed: ${response.status}`);
|
|
3585
|
-
const reader = response.body.getReader();
|
|
3586
|
-
const decoder = new TextDecoder();
|
|
3587
|
-
let buffer = "";
|
|
3588
|
-
while (true) {
|
|
3589
|
-
const { done, value } = await reader.read();
|
|
3590
|
-
if (done) break;
|
|
3591
|
-
buffer += decoder.decode(value, { stream: true });
|
|
3592
|
-
const frames = buffer.split("\n\n");
|
|
3593
|
-
buffer = frames.pop() ?? "";
|
|
3594
|
-
for (const chunk of frames) {
|
|
3595
|
-
for (const line of chunk.split("\n")) {
|
|
3596
|
-
if (!line.startsWith("data: ")) continue;
|
|
3597
|
-
const frame = parseDaemonFrame(line.slice(6));
|
|
3598
|
-
if (!frame || !("type" in frame)) continue;
|
|
3599
|
-
if (frame.type === "subscribed") {
|
|
3600
|
-
markSubscribed();
|
|
3601
|
-
drainComplete = false;
|
|
3602
|
-
void performDrain();
|
|
3603
|
-
}
|
|
3604
|
-
if (frame.type === "event") {
|
|
3605
|
-
if (drainComplete) void deliver(frame.events);
|
|
3606
|
-
else buffered.push(frame.events);
|
|
3607
|
-
}
|
|
3608
|
-
}
|
|
3609
|
-
}
|
|
3610
|
-
}
|
|
3611
|
-
consecutiveFailures = 0;
|
|
3612
|
-
} catch (error) {
|
|
3613
|
-
if (!controller.signal.aborted) {
|
|
3614
|
-
consecutiveFailures += 1;
|
|
3615
|
-
if (consecutiveFailures === 1) {
|
|
3616
|
-
console.error(`[sourcefed] event stream ended: ${error instanceof Error ? error.message : String(error)}`);
|
|
3617
|
-
}
|
|
3618
|
-
}
|
|
3619
|
-
}
|
|
3620
|
-
};
|
|
3621
|
-
let consecutiveFailures = 0;
|
|
3622
|
-
void (async () => {
|
|
3623
|
-
while (!controller.signal.aborted && callbacks?.has(onEvents)) {
|
|
3624
|
-
await runStream();
|
|
3625
|
-
if (controller.signal.aborted) break;
|
|
3626
|
-
await sleep(500);
|
|
3627
|
-
}
|
|
3628
|
-
})();
|
|
3629
|
-
try {
|
|
3630
|
-
await withTimeout(subscribed, 15e3, `sourcefed event stream did not subscribe at ${url}`);
|
|
3631
|
-
await withTimeout(drained, 15e3, "sourcefed initial event drain timed out");
|
|
3632
|
-
} catch (error) {
|
|
3633
|
-
if (retryTimer) clearTimeout(retryTimer);
|
|
3634
|
-
const callbacks2 = this.listeners.get(key);
|
|
3635
|
-
callbacks2?.delete(onEvents);
|
|
3636
|
-
if (callbacks2 && callbacks2.size === 0) this.listeners.delete(key);
|
|
3637
|
-
controller.abort();
|
|
3638
|
-
this.streams.delete(controller);
|
|
3639
|
-
throw error;
|
|
3640
|
-
}
|
|
3641
|
-
return {
|
|
3642
|
-
close: async () => {
|
|
3643
|
-
if (retryTimer) clearTimeout(retryTimer);
|
|
3644
|
-
const callbacks2 = this.listeners.get(key);
|
|
3645
|
-
callbacks2?.delete(onEvents);
|
|
3646
|
-
if (callbacks2 && callbacks2.size === 0) this.listeners.delete(key);
|
|
3647
|
-
controller.abort();
|
|
3648
|
-
this.streams.delete(controller);
|
|
3649
|
-
}
|
|
3650
|
-
};
|
|
3651
|
-
}
|
|
3652
|
-
async close() {
|
|
3653
|
-
for (const controller of this.streams) controller.abort();
|
|
3654
|
-
this.streams.clear();
|
|
3655
|
-
this.router.rejectAll(new Error("daemon closed"));
|
|
3656
|
-
this.listeners.clear();
|
|
3657
|
-
}
|
|
3658
|
-
};
|
|
11
|
+
import { connectDaemonClient as connectDaemonClient2, defaultDaemonUrl as defaultDaemonUrl2 } from "@fdcn/sourcefed/daemon";
|
|
3659
12
|
|
|
3660
13
|
// .tui-build/tui/sidebar.mjs
|
|
3661
14
|
import { memo as _$memo } from "opentui:runtime-module:%40opentui%2Fsolid";
|
|
@@ -3667,6 +20,7 @@ import { insertNode as _$insertNode } from "opentui:runtime-module:%40opentui%2F
|
|
|
3667
20
|
import { setProp as _$setProp } from "opentui:runtime-module:%40opentui%2Fsolid";
|
|
3668
21
|
import { createElement as _$createElement } from "opentui:runtime-module:%40opentui%2Fsolid";
|
|
3669
22
|
import { Show, createMemo, createSignal, onCleanup } from "opentui:runtime-module:solid-js";
|
|
23
|
+
import { connectDaemonClient, defaultDaemonUrl } from "@fdcn/sourcefed/daemon";
|
|
3670
24
|
var REFRESH_MS = 3e3;
|
|
3671
25
|
function Sidebar(props) {
|
|
3672
26
|
const [monitors, setMonitors] = createSignal([]);
|
|
@@ -3807,9 +161,9 @@ var sourcefedTui = async (api) => {
|
|
|
3807
161
|
};
|
|
3808
162
|
const getClient = async () => {
|
|
3809
163
|
if (client) return client;
|
|
3810
|
-
client = await
|
|
164
|
+
client = await connectDaemonClient2({
|
|
3811
165
|
name: "sourcefed-opencode-tui",
|
|
3812
|
-
url: process.env.SOURCEFED_DAEMON_URL ??
|
|
166
|
+
url: process.env.SOURCEFED_DAEMON_URL ?? defaultDaemonUrl2()
|
|
3813
167
|
});
|
|
3814
168
|
return client;
|
|
3815
169
|
};
|