@awsless/cli 0.1.7 → 0.1.9
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/dist/bin.js +779 -134
- package/dist/handlers/icon.js +1 -15
- package/dist/handlers/pubsub-publisher.js +3 -17
- package/dist/handlers/pubsub-server.js +26 -48
- package/dist/test-global-setup.js +1 -5
- package/package.json +12 -12
package/dist/bin.js
CHANGED
|
@@ -6,60 +6,39 @@ var __defProp = Object.defineProperty;
|
|
|
6
6
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
7
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
8
8
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
-
function __accessProp(key) {
|
|
10
|
-
return this[key];
|
|
11
|
-
}
|
|
12
|
-
var __toESMCache_node;
|
|
13
|
-
var __toESMCache_esm;
|
|
14
9
|
var __toESM = (mod, isNodeMode, target) => {
|
|
15
|
-
var canCache = mod != null && typeof mod === "object";
|
|
16
|
-
if (canCache) {
|
|
17
|
-
var cache = isNodeMode ? __toESMCache_node ??= new WeakMap : __toESMCache_esm ??= new WeakMap;
|
|
18
|
-
var cached = cache.get(mod);
|
|
19
|
-
if (cached)
|
|
20
|
-
return cached;
|
|
21
|
-
}
|
|
22
10
|
target = mod != null ? __create(__getProtoOf(mod)) : {};
|
|
23
11
|
const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
|
|
24
12
|
for (let key of __getOwnPropNames(mod))
|
|
25
13
|
if (!__hasOwnProp.call(to, key))
|
|
26
14
|
__defProp(to, key, {
|
|
27
|
-
get:
|
|
15
|
+
get: () => mod[key],
|
|
28
16
|
enumerable: true
|
|
29
17
|
});
|
|
30
|
-
if (canCache)
|
|
31
|
-
cache.set(mod, to);
|
|
32
18
|
return to;
|
|
33
19
|
};
|
|
20
|
+
var __moduleCache = /* @__PURE__ */ new WeakMap;
|
|
34
21
|
var __toCommonJS = (from) => {
|
|
35
|
-
var entry =
|
|
22
|
+
var entry = __moduleCache.get(from), desc;
|
|
36
23
|
if (entry)
|
|
37
24
|
return entry;
|
|
38
25
|
entry = __defProp({}, "__esModule", { value: true });
|
|
39
|
-
if (from && typeof from === "object" || typeof from === "function")
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
45
|
-
});
|
|
46
|
-
}
|
|
26
|
+
if (from && typeof from === "object" || typeof from === "function")
|
|
27
|
+
__getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, {
|
|
28
|
+
get: () => from[key],
|
|
29
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
30
|
+
}));
|
|
47
31
|
__moduleCache.set(from, entry);
|
|
48
32
|
return entry;
|
|
49
33
|
};
|
|
50
|
-
var __moduleCache;
|
|
51
34
|
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
52
|
-
var __returnValue = (v) => v;
|
|
53
|
-
function __exportSetter(name, newValue) {
|
|
54
|
-
this[name] = __returnValue.bind(null, newValue);
|
|
55
|
-
}
|
|
56
35
|
var __export = (target, all) => {
|
|
57
36
|
for (var name in all)
|
|
58
37
|
__defProp(target, name, {
|
|
59
38
|
get: all[name],
|
|
60
39
|
enumerable: true,
|
|
61
40
|
configurable: true,
|
|
62
|
-
set:
|
|
41
|
+
set: (newValue) => all[name] = () => newValue
|
|
63
42
|
});
|
|
64
43
|
};
|
|
65
44
|
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
@@ -853,7 +832,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
853
832
|
this._exitCallback = (err) => {
|
|
854
833
|
if (err.code !== "commander.executeSubCommandAsync") {
|
|
855
834
|
throw err;
|
|
856
|
-
}
|
|
835
|
+
} else {}
|
|
857
836
|
};
|
|
858
837
|
}
|
|
859
838
|
return this;
|
|
@@ -3090,7 +3069,7 @@ var require_cell = __commonJS((exports, module) => {
|
|
|
3090
3069
|
let content = utils.truncate(this.content, 10, this.truncate);
|
|
3091
3070
|
if (!lineNum) {
|
|
3092
3071
|
info(`${this.y}-${this.x}: ${this.rowSpan - lineNum}x${this.colSpan} Cell ${content}`);
|
|
3093
|
-
}
|
|
3072
|
+
} else {}
|
|
3094
3073
|
let padLen = Math.max(this.height - this.lines.length, 0);
|
|
3095
3074
|
let padTop;
|
|
3096
3075
|
switch (this.vAlign) {
|
|
@@ -26859,7 +26838,7 @@ var require_node_gyp_build_optional_packages = __commonJS((exports, module) => {
|
|
|
26859
26838
|
|
|
26860
26839
|
// ../../node_modules/.pnpm/msgpackr-extract@3.0.4/node_modules/msgpackr-extract/index.js
|
|
26861
26840
|
var require_msgpackr_extract = __commonJS((exports, module) => {
|
|
26862
|
-
var __dirname = "/Users/
|
|
26841
|
+
var __dirname = "/Users/ivandasilveira/Sites/@awsless/node_modules/.pnpm/msgpackr-extract@3.0.4/node_modules/msgpackr-extract";
|
|
26863
26842
|
module.exports = require_node_gyp_build_optional_packages()(__dirname);
|
|
26864
26843
|
});
|
|
26865
26844
|
|
|
@@ -39727,7 +39706,7 @@ var require_src3 = __commonJS((exports) => {
|
|
|
39727
39706
|
|
|
39728
39707
|
// ../../node_modules/.pnpm/@grpc+grpc-js@1.12.6/node_modules/@grpc/grpc-js/build/src/channelz.js
|
|
39729
39708
|
var require_channelz = __commonJS((exports) => {
|
|
39730
|
-
var __dirname = "/Users/
|
|
39709
|
+
var __dirname = "/Users/ivandasilveira/Sites/@awsless/node_modules/.pnpm/@grpc+grpc-js@1.12.6/node_modules/@grpc/grpc-js/build/src";
|
|
39731
39710
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39732
39711
|
exports.registerChannelzSocket = exports.registerChannelzServer = exports.registerChannelzSubchannel = exports.registerChannelzChannel = exports.ChannelzCallTrackerStub = exports.ChannelzCallTracker = exports.ChannelzChildrenTrackerStub = exports.ChannelzChildrenTracker = exports.ChannelzTrace = exports.ChannelzTraceStub = undefined;
|
|
39733
39712
|
exports.unregisterChannelzRef = unregisterChannelzRef;
|
|
@@ -57231,7 +57210,7 @@ var require_zipEntries = __commonJS((exports, module) => {
|
|
|
57231
57210
|
if (this.centralDirRecords !== this.files.length) {
|
|
57232
57211
|
if (this.centralDirRecords !== 0 && this.files.length === 0) {
|
|
57233
57212
|
throw new Error("Corrupted zip or bug: expected " + this.centralDirRecords + " records in central dir, got " + this.files.length);
|
|
57234
|
-
}
|
|
57213
|
+
} else {}
|
|
57235
57214
|
}
|
|
57236
57215
|
},
|
|
57237
57216
|
readEndOfCentral: function() {
|
|
@@ -74452,7 +74431,7 @@ WD9f
|
|
|
74452
74431
|
|
|
74453
74432
|
// ../../node_modules/.pnpm/ioredis@5.10.1_supports-color@8.1.1/node_modules/ioredis/built/utils/index.js
|
|
74454
74433
|
var require_utils5 = __commonJS((exports) => {
|
|
74455
|
-
var __dirname = "/Users/
|
|
74434
|
+
var __dirname = "/Users/ivandasilveira/Sites/@awsless/node_modules/.pnpm/ioredis@5.10.1_supports-color@8.1.1/node_modules/ioredis/built/utils";
|
|
74456
74435
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
74457
74436
|
exports.noop = exports.defaults = exports.Debug = exports.getPackageMeta = exports.zipMap = exports.CONNECTION_CLOSED_ERROR_MSG = exports.shuffle = exports.sample = exports.resolveTLSProfile = exports.parseURL = exports.optimizeErrorStack = exports.toArg = exports.convertMapToArray = exports.convertObjectToArray = exports.timeout = exports.packObject = exports.isInt = exports.wrapMultiResult = exports.convertBufferToString = undefined;
|
|
74458
74437
|
var fs_1 = __require("fs");
|
|
@@ -74738,7 +74717,7 @@ var require_argumentParsers = __commonJS((exports) => {
|
|
|
74738
74717
|
|
|
74739
74718
|
// ../../node_modules/.pnpm/ioredis@5.10.1_supports-color@8.1.1/node_modules/ioredis/built/Command.js
|
|
74740
74719
|
var require_Command = __commonJS((exports) => {
|
|
74741
|
-
var __dirname = "/Users/
|
|
74720
|
+
var __dirname = "/Users/ivandasilveira/Sites/@awsless/node_modules/.pnpm/ioredis@5.10.1_supports-color@8.1.1/node_modules/ioredis/built";
|
|
74742
74721
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
74743
74722
|
var commands_1 = require_built();
|
|
74744
74723
|
var calculateSlot = require_lib4();
|
|
@@ -95385,7 +95364,7 @@ var require_db_util = __commonJS((exports) => {
|
|
|
95385
95364
|
|
|
95386
95365
|
// ../../node_modules/.pnpm/redis-memory-server@0.16.1_supports-color@8.1.1/node_modules/redis-memory-server/lib/util/RedisInstance.js
|
|
95387
95366
|
var require_RedisInstance = __commonJS((exports) => {
|
|
95388
|
-
var __dirname = "/Users/
|
|
95367
|
+
var __dirname = "/Users/ivandasilveira/Sites/@awsless/node_modules/.pnpm/redis-memory-server@0.16.1_supports-color@8.1.1/node_modules/redis-memory-server/lib/util";
|
|
95389
95368
|
var __awaiter = exports && exports.__awaiter || function(thisArg, _arguments, P3, generator) {
|
|
95390
95369
|
function adopt(value) {
|
|
95391
95370
|
return value instanceof P3 ? value : new P3(function(resolve3) {
|
|
@@ -99153,15 +99132,15 @@ var require_pack = __commonJS((exports, module) => {
|
|
|
99153
99132
|
process.nextTick(callback);
|
|
99154
99133
|
return new Void;
|
|
99155
99134
|
}
|
|
99156
|
-
var
|
|
99157
|
-
this._stream =
|
|
99158
|
-
eos(
|
|
99135
|
+
var sink3 = new Sink(this);
|
|
99136
|
+
this._stream = sink3;
|
|
99137
|
+
eos(sink3, function(err) {
|
|
99159
99138
|
self2._stream = null;
|
|
99160
99139
|
if (err) {
|
|
99161
99140
|
self2.destroy();
|
|
99162
99141
|
return callback(err);
|
|
99163
99142
|
}
|
|
99164
|
-
if (
|
|
99143
|
+
if (sink3.written !== header.size) {
|
|
99165
99144
|
self2.destroy();
|
|
99166
99145
|
return callback(new Error("size mismatch"));
|
|
99167
99146
|
}
|
|
@@ -99170,7 +99149,7 @@ var require_pack = __commonJS((exports, module) => {
|
|
|
99170
99149
|
self2.finalize();
|
|
99171
99150
|
callback();
|
|
99172
99151
|
});
|
|
99173
|
-
return
|
|
99152
|
+
return sink3;
|
|
99174
99153
|
};
|
|
99175
99154
|
Pack.prototype.finalize = function() {
|
|
99176
99155
|
if (this._stream) {
|
|
@@ -101299,7 +101278,7 @@ var require_unbzip2_stream = __commonJS((exports, module) => {
|
|
|
101299
101278
|
stream2.queue(d5);
|
|
101300
101279
|
if (d5 !== null) {
|
|
101301
101280
|
outlength += d5.length;
|
|
101302
|
-
}
|
|
101281
|
+
} else {}
|
|
101303
101282
|
});
|
|
101304
101283
|
} catch (e4) {
|
|
101305
101284
|
stream2.emit("error", e4);
|
|
@@ -103168,7 +103147,15 @@ var import_decompress, import_sleep_await, mock, searchClient = (options = {}, s
|
|
|
103168
103147
|
return Object.entries(settings).map(([key, value]) => {
|
|
103169
103148
|
return ["-E", `${key}=${value}`];
|
|
103170
103149
|
}).flat();
|
|
103171
|
-
}, launch = ({
|
|
103150
|
+
}, launch = ({
|
|
103151
|
+
path: path6,
|
|
103152
|
+
host,
|
|
103153
|
+
port,
|
|
103154
|
+
version: version2,
|
|
103155
|
+
debug: debug4,
|
|
103156
|
+
onExit: onDied,
|
|
103157
|
+
onOutput
|
|
103158
|
+
}) => {
|
|
103172
103159
|
return new Promise(async (resolve22, reject) => {
|
|
103173
103160
|
const cache3 = join32(path6, "cache", String(port));
|
|
103174
103161
|
const cleanUp = async () => {
|
|
@@ -103206,7 +103193,9 @@ ${output.join("")}`);
|
|
|
103206
103193
|
done();
|
|
103207
103194
|
}
|
|
103208
103195
|
};
|
|
103196
|
+
let stopping = false;
|
|
103209
103197
|
const kill = async () => {
|
|
103198
|
+
stopping = true;
|
|
103210
103199
|
if (child.exitCode === null && !child.killed) {
|
|
103211
103200
|
await new Promise((resolve32) => {
|
|
103212
103201
|
child.once(`exit`, () => {
|
|
@@ -103235,6 +103224,23 @@ ${output.join("")}`);
|
|
|
103235
103224
|
};
|
|
103236
103225
|
const done = async () => {
|
|
103237
103226
|
off();
|
|
103227
|
+
child.once("exit", (code, signal) => {
|
|
103228
|
+
if (!stopping) {
|
|
103229
|
+
onDied?.(code, signal);
|
|
103230
|
+
}
|
|
103231
|
+
});
|
|
103232
|
+
if (onOutput) {
|
|
103233
|
+
const capture = (chunk3) => {
|
|
103234
|
+
for (const line of chunk3.toString().split(`
|
|
103235
|
+
`)) {
|
|
103236
|
+
if (line.trim() !== "") {
|
|
103237
|
+
onOutput(line);
|
|
103238
|
+
}
|
|
103239
|
+
}
|
|
103240
|
+
};
|
|
103241
|
+
child.stdout.on("data", capture);
|
|
103242
|
+
child.stderr.on("data", capture);
|
|
103243
|
+
}
|
|
103238
103244
|
resolve22(kill);
|
|
103239
103245
|
};
|
|
103240
103246
|
const fail = async (error3) => {
|
|
@@ -108467,6 +108473,10 @@ var clearDebugLog = () => {
|
|
|
108467
108473
|
ready = true;
|
|
108468
108474
|
} catch (_) {}
|
|
108469
108475
|
};
|
|
108476
|
+
var sink;
|
|
108477
|
+
var setDebugSink = (listener) => {
|
|
108478
|
+
sink = listener;
|
|
108479
|
+
};
|
|
108470
108480
|
var write = (type, message) => {
|
|
108471
108481
|
try {
|
|
108472
108482
|
if (!ready) {
|
|
@@ -108474,6 +108484,7 @@ var write = (type, message) => {
|
|
|
108474
108484
|
}
|
|
108475
108485
|
appendFileSync(debugLogFile, `${new Date().toISOString()} [${type}] ${message}
|
|
108476
108486
|
`);
|
|
108487
|
+
sink?.(type, message);
|
|
108477
108488
|
} catch (_) {}
|
|
108478
108489
|
};
|
|
108479
108490
|
var format = (parts) => {
|
|
@@ -114483,7 +114494,7 @@ var getSanitizedDevTypeScriptVersion = (version2 = "") => {
|
|
|
114483
114494
|
};
|
|
114484
114495
|
|
|
114485
114496
|
// ../../node_modules/.pnpm/@aws-sdk+util-user-agent-node@3.973.14_aws-crt@1.30.0_supports-color@8.1.1_/node_modules/@aws-sdk/util-user-agent-node/dist-es/getTypeScriptUserAgentPair.js
|
|
114486
|
-
var __dirname = "/Users/
|
|
114497
|
+
var __dirname = "/Users/ivandasilveira/Sites/@awsless/node_modules/.pnpm/@aws-sdk+util-user-agent-node@3.973.14_aws-crt@1.30.0_supports-color@8.1.1_/node_modules/@aws-sdk/util-user-agent-node/dist-es";
|
|
114487
114498
|
var tscVersion;
|
|
114488
114499
|
var TS_PACKAGE_JSON = join7("node_modules", "typescript", "package.json");
|
|
114489
114500
|
var getTypeScriptUserAgentPair = async () => {
|
|
@@ -131560,17 +131571,6 @@ var $forEachNodeInTopologicalOrder = sort.forEachNodeInTopologicalOrder;
|
|
|
131560
131571
|
var $topologicalSort = sort.topologicalSort;
|
|
131561
131572
|
var $topologicalGenerations = sort.topologicalGenerations;
|
|
131562
131573
|
var $forEachTopologicalGeneration = sort.forEachTopologicalGeneration;
|
|
131563
|
-
// ../../node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm/sha1.js
|
|
131564
|
-
import { createHash as createHash3 } from "crypto";
|
|
131565
|
-
function sha1(bytes) {
|
|
131566
|
-
if (Array.isArray(bytes)) {
|
|
131567
|
-
bytes = Buffer.from(bytes);
|
|
131568
|
-
} else if (typeof bytes === "string") {
|
|
131569
|
-
bytes = Buffer.from(bytes, "utf8");
|
|
131570
|
-
}
|
|
131571
|
-
return createHash3("sha1").update(bytes).digest();
|
|
131572
|
-
}
|
|
131573
|
-
var sha1_default = sha1;
|
|
131574
131574
|
|
|
131575
131575
|
// ../../node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm/regex.js
|
|
131576
131576
|
var regex_default = /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/i;
|
|
@@ -131636,6 +131636,18 @@ function v35(version2, hash, value, namespace, buf, offset) {
|
|
|
131636
131636
|
return unsafeStringify(bytes);
|
|
131637
131637
|
}
|
|
131638
131638
|
|
|
131639
|
+
// ../../node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm/sha1.js
|
|
131640
|
+
import { createHash as createHash3 } from "crypto";
|
|
131641
|
+
function sha1(bytes) {
|
|
131642
|
+
if (Array.isArray(bytes)) {
|
|
131643
|
+
bytes = Buffer.from(bytes);
|
|
131644
|
+
} else if (typeof bytes === "string") {
|
|
131645
|
+
bytes = Buffer.from(bytes, "utf8");
|
|
131646
|
+
}
|
|
131647
|
+
return createHash3("sha1").update(bytes).digest();
|
|
131648
|
+
}
|
|
131649
|
+
var sha1_default = sha1;
|
|
131650
|
+
|
|
131639
131651
|
// ../../node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm/v5.js
|
|
131640
131652
|
function v5(value, namespace, buf, offset) {
|
|
131641
131653
|
return v35(80, sha1_default, value, namespace, buf, offset);
|
|
@@ -132327,13 +132339,13 @@ var consoleSink = (group4, ...args) => {
|
|
|
132327
132339
|
console.log(`${group4}:`, ...args);
|
|
132328
132340
|
console.log();
|
|
132329
132341
|
};
|
|
132330
|
-
var
|
|
132342
|
+
var sink2;
|
|
132331
132343
|
var enableDebug = (customSink) => {
|
|
132332
|
-
|
|
132344
|
+
sink2 = customSink ?? consoleSink;
|
|
132333
132345
|
};
|
|
132334
132346
|
var createDebugger = (group4) => {
|
|
132335
132347
|
return (...args) => {
|
|
132336
|
-
|
|
132348
|
+
sink2?.(group4, ...args);
|
|
132337
132349
|
};
|
|
132338
132350
|
};
|
|
132339
132351
|
var AlreadyLockedError = class extends Error {
|
|
@@ -141101,6 +141113,8 @@ if (!nativeAccelerationDisabled) {
|
|
|
141101
141113
|
try {
|
|
141102
141114
|
if (true)
|
|
141103
141115
|
extractor = require_msgpackr_extract();
|
|
141116
|
+
else
|
|
141117
|
+
;
|
|
141104
141118
|
if (extractor)
|
|
141105
141119
|
setExtractor(extractor.extractStrings);
|
|
141106
141120
|
} catch (error3) {}
|
|
@@ -154054,6 +154068,7 @@ var __export3 = (target2, all5) => {
|
|
|
154054
154068
|
var RedisServer = class {
|
|
154055
154069
|
client;
|
|
154056
154070
|
process;
|
|
154071
|
+
stopping = false;
|
|
154057
154072
|
async start(port, version2 = "7.2.4", args = []) {
|
|
154058
154073
|
if (this.process) {
|
|
154059
154074
|
throw new Error(`Redis server is already listening on port: ${await this.process.getPort()}`);
|
|
@@ -154061,6 +154076,7 @@ var RedisServer = class {
|
|
|
154061
154076
|
if (port && (port < 0 || port >= 65536)) {
|
|
154062
154077
|
throw new RangeError(`Port should be >= 0 and < 65536. Received ${port}.`);
|
|
154063
154078
|
}
|
|
154079
|
+
this.stopping = false;
|
|
154064
154080
|
this.process = await import_redis_memory_server.RedisMemoryServer.create({
|
|
154065
154081
|
instance: {
|
|
154066
154082
|
port,
|
|
@@ -154069,8 +154085,30 @@ var RedisServer = class {
|
|
|
154069
154085
|
binary: { version: version2 }
|
|
154070
154086
|
});
|
|
154071
154087
|
}
|
|
154088
|
+
onExit(handler) {
|
|
154089
|
+
const child = this.process?.instanceInfoSync?.childProcess;
|
|
154090
|
+
child?.once("exit", (code, signal) => {
|
|
154091
|
+
if (!this.stopping) {
|
|
154092
|
+
handler(code, signal);
|
|
154093
|
+
}
|
|
154094
|
+
});
|
|
154095
|
+
}
|
|
154096
|
+
onOutput(handler) {
|
|
154097
|
+
const child = this.process?.instanceInfoSync?.childProcess;
|
|
154098
|
+
const capture = (chunk3) => {
|
|
154099
|
+
for (const line of chunk3.toString().split(`
|
|
154100
|
+
`)) {
|
|
154101
|
+
if (line.trim() !== "") {
|
|
154102
|
+
handler(line);
|
|
154103
|
+
}
|
|
154104
|
+
}
|
|
154105
|
+
};
|
|
154106
|
+
child?.stdout?.on("data", capture);
|
|
154107
|
+
child?.stderr?.on("data", capture);
|
|
154108
|
+
}
|
|
154072
154109
|
async kill() {
|
|
154073
154110
|
if (this.process) {
|
|
154111
|
+
this.stopping = true;
|
|
154074
154112
|
await this.client?.disconnect();
|
|
154075
154113
|
await this.process.stop();
|
|
154076
154114
|
this.process = undefined;
|
|
@@ -154852,12 +154890,31 @@ var cacheOnDev = async (ctx) => {
|
|
|
154852
154890
|
return;
|
|
154853
154891
|
}
|
|
154854
154892
|
for (const { stackName, id } of caches) {
|
|
154855
|
-
const port = await ctx.keep(`cache:${stackName}:${id}`, null, async () => {
|
|
154893
|
+
const { port, sink: sink3 } = await ctx.keep(`cache:${stackName}:${id}`, null, async () => {
|
|
154856
154894
|
const server = new RedisServer;
|
|
154857
154895
|
await server.start();
|
|
154858
154896
|
await server.ping();
|
|
154859
|
-
|
|
154897
|
+
const sink4 = { tail: [] };
|
|
154898
|
+
server.onExit((code, signal) => {
|
|
154899
|
+
sink4.crashed = code !== null ? `exited with code ${code}` : `killed by ${signal}`;
|
|
154900
|
+
sink4.health?.("down", sink4.crashed);
|
|
154901
|
+
});
|
|
154902
|
+
server.onOutput((line) => {
|
|
154903
|
+
sink4.tail.push(line);
|
|
154904
|
+
while (sink4.tail.length > 20) {
|
|
154905
|
+
sink4.tail.shift();
|
|
154906
|
+
}
|
|
154907
|
+
sink4.log?.(line);
|
|
154908
|
+
});
|
|
154909
|
+
return { value: { port: await server.getPort(), sink: sink4 }, stop: () => server.kill() };
|
|
154860
154910
|
});
|
|
154911
|
+
const channel = `cache:${stackName}:${id}`;
|
|
154912
|
+
sink3.health = (status2, detail) => ctx.reportHealth(`cache ${stackName}/${id}`, status2, detail);
|
|
154913
|
+
sink3.health(sink3.crashed ? "down" : "up", sink3.crashed);
|
|
154914
|
+
sink3.log = (line) => ctx.emitEvent(channel, { date: Date.now(), line });
|
|
154915
|
+
for (const line of sink3.tail) {
|
|
154916
|
+
ctx.emitEvent(channel, { date: Date.now(), line });
|
|
154917
|
+
}
|
|
154861
154918
|
const prefix = `CACHE_${constantCase(stackName)}_${constantCase(id)}`;
|
|
154862
154919
|
ctx.addEnv(`${prefix}_HOST`, "localhost");
|
|
154863
154920
|
ctx.addEnv(`${prefix}_PORT`, String(port));
|
|
@@ -154867,7 +154924,8 @@ var cacheOnDev = async (ctx) => {
|
|
|
154867
154924
|
kind: "cache",
|
|
154868
154925
|
stack: stackName,
|
|
154869
154926
|
id,
|
|
154870
|
-
detail: `localhost:${port}
|
|
154927
|
+
detail: `localhost:${port}`,
|
|
154928
|
+
channel
|
|
154871
154929
|
});
|
|
154872
154930
|
}
|
|
154873
154931
|
};
|
|
@@ -157300,13 +157358,18 @@ var parseQueryPublish = (body) => {
|
|
|
157300
157358
|
MessageAttributes: attributes
|
|
157301
157359
|
};
|
|
157302
157360
|
};
|
|
157303
|
-
var createSnsServer = () => {
|
|
157361
|
+
var createSnsServer = (props) => {
|
|
157304
157362
|
let server;
|
|
157305
157363
|
let closeServer;
|
|
157306
157364
|
let dispatch;
|
|
157307
157365
|
let reportFailure;
|
|
157308
157366
|
const publish2 = (input) => {
|
|
157309
157367
|
const messageId = randomUUID4();
|
|
157368
|
+
for (const capture of props?.captures ?? []) {
|
|
157369
|
+
if (capture(input)) {
|
|
157370
|
+
return messageId;
|
|
157371
|
+
}
|
|
157372
|
+
}
|
|
157310
157373
|
const attributes = {};
|
|
157311
157374
|
for (const [name, attribute] of Object.entries(input.MessageAttributes ?? {})) {
|
|
157312
157375
|
attributes[name] = {
|
|
@@ -157414,22 +157477,29 @@ var pubsubOnDev = async (ctx) => {
|
|
|
157414
157477
|
declared.add(event);
|
|
157415
157478
|
}
|
|
157416
157479
|
}
|
|
157417
|
-
const { redisPort, sns, snsPort, wsPort } = await ctx.keep(`pubsub-core:${id}`, null, async () => {
|
|
157480
|
+
const { redisPort, sns, snsPort, wsPort, redisSink } = await ctx.keep(`pubsub-core:${id}`, null, async () => {
|
|
157418
157481
|
const redis = new RedisServer;
|
|
157419
157482
|
await redis.start();
|
|
157420
157483
|
await redis.ping();
|
|
157484
|
+
const redisSink2 = {};
|
|
157485
|
+
redis.onExit((code, signal) => {
|
|
157486
|
+
redisSink2.crashed = code !== null ? `exited with code ${code}` : `killed by ${signal}`;
|
|
157487
|
+
redisSink2.health?.("down", redisSink2.crashed);
|
|
157488
|
+
});
|
|
157421
157489
|
const redisPort2 = await redis.getPort();
|
|
157422
157490
|
const sns2 = createSnsServer();
|
|
157423
157491
|
const snsPort2 = await sns2.listen();
|
|
157424
157492
|
const wsPort2 = await findFreePort();
|
|
157425
157493
|
return {
|
|
157426
|
-
value: { redisPort: redisPort2, sns: sns2, snsPort: snsPort2, wsPort: wsPort2 },
|
|
157494
|
+
value: { redisPort: redisPort2, sns: sns2, snsPort: snsPort2, wsPort: wsPort2, redisSink: redisSink2 },
|
|
157427
157495
|
stop: async () => {
|
|
157428
157496
|
await sns2.stop();
|
|
157429
157497
|
await redis.kill();
|
|
157430
157498
|
}
|
|
157431
157499
|
};
|
|
157432
157500
|
});
|
|
157501
|
+
redisSink.health = (status2, detail) => ctx.reportHealth(`pubsub ${id} redis`, status2, detail);
|
|
157502
|
+
redisSink.health(redisSink.crashed ? "down" : "up", redisSink.crashed);
|
|
157433
157503
|
ctx.retain(`pubsub-ws:${id}`);
|
|
157434
157504
|
const channel = `pubsub:${id}`;
|
|
157435
157505
|
const publisherRoute = formatRouteKey("base", "pubsub", `${id}-publisher`);
|
|
@@ -157511,7 +157581,10 @@ var pubsubOnDev = async (ctx) => {
|
|
|
157511
157581
|
}
|
|
157512
157582
|
return dispatch(event);
|
|
157513
157583
|
}, reportFailure);
|
|
157514
|
-
await ctx.keep(`pubsub-ws:${id}`, { wsPort, redisPort, snsPort }, async () => {
|
|
157584
|
+
const ws = await ctx.keep(`pubsub-ws:${id}`, { wsPort, redisPort, snsPort }, async () => {
|
|
157585
|
+
const sink3 = {
|
|
157586
|
+
stopping: false
|
|
157587
|
+
};
|
|
157515
157588
|
const runtime = join24(dirname12(fileURLToPath8(import.meta.url)), "handlers", "pubsub-server.js");
|
|
157516
157589
|
const child = spawn2(process.execPath, [runtime], {
|
|
157517
157590
|
stdio: ["ignore", "ignore", "pipe"],
|
|
@@ -157536,9 +157609,23 @@ var pubsubOnDev = async (ctx) => {
|
|
|
157536
157609
|
}
|
|
157537
157610
|
});
|
|
157538
157611
|
child.stderr?.on("data", (chunk3) => process.stderr.write(chunk3));
|
|
157612
|
+
child.on("exit", (code, signal) => {
|
|
157613
|
+
if (!sink3.stopping) {
|
|
157614
|
+
sink3.health?.("down", code !== null ? `exited with code ${code}` : `killed by ${signal}`);
|
|
157615
|
+
}
|
|
157616
|
+
});
|
|
157539
157617
|
await waitForHealth(wsPort, 30000);
|
|
157540
|
-
return {
|
|
157618
|
+
return {
|
|
157619
|
+
value: { child, sink: sink3 },
|
|
157620
|
+
stop: async () => {
|
|
157621
|
+
sink3.stopping = true;
|
|
157622
|
+
await stopChild(child);
|
|
157623
|
+
}
|
|
157624
|
+
};
|
|
157541
157625
|
});
|
|
157626
|
+
ws.sink.health = (status2, detail) => ctx.reportHealth(`pubsub ${id}`, status2, detail);
|
|
157627
|
+
ws.sink.stopping = false;
|
|
157628
|
+
ws.sink.health(ws.child.exitCode === null ? "up" : "down");
|
|
157542
157629
|
},
|
|
157543
157630
|
async stop() {
|
|
157544
157631
|
feed?.disconnect();
|
|
@@ -158756,19 +158843,37 @@ var searchOnDev = async (ctx) => {
|
|
|
158756
158843
|
if (indexes.length === 0) {
|
|
158757
158844
|
return;
|
|
158758
158845
|
}
|
|
158759
|
-
const { port } = await ctx.keep("opensearch", null, async () => {
|
|
158846
|
+
const { port, sink: sink3 } = await ctx.keep("opensearch", null, async () => {
|
|
158760
158847
|
const port2 = await findFreePort();
|
|
158761
158848
|
const path6 = await download(VERSION_3_5_0_MIN);
|
|
158849
|
+
const sink4 = { tail: [] };
|
|
158762
158850
|
const kill = await launch({
|
|
158763
158851
|
path: path6,
|
|
158764
158852
|
port: port2,
|
|
158765
158853
|
host: "localhost",
|
|
158766
158854
|
version: VERSION_3_5_0_MIN,
|
|
158767
|
-
debug: false
|
|
158855
|
+
debug: false,
|
|
158856
|
+
onExit(code, signal) {
|
|
158857
|
+
sink4.crashed = code !== null ? `exited with code ${code}` : `killed by ${signal}`;
|
|
158858
|
+
sink4.health?.("down", sink4.crashed);
|
|
158859
|
+
},
|
|
158860
|
+
onOutput(line) {
|
|
158861
|
+
sink4.tail.push(line);
|
|
158862
|
+
while (sink4.tail.length > 20) {
|
|
158863
|
+
sink4.tail.shift();
|
|
158864
|
+
}
|
|
158865
|
+
sink4.log?.(line);
|
|
158866
|
+
}
|
|
158768
158867
|
});
|
|
158769
158868
|
await waitForSearch(port2, 60000);
|
|
158770
|
-
return { value: { port: port2 }, stop: kill };
|
|
158869
|
+
return { value: { port: port2, sink: sink4 }, stop: kill };
|
|
158771
158870
|
});
|
|
158871
|
+
sink3.health = (status2, detail) => ctx.reportHealth("search", status2, detail);
|
|
158872
|
+
sink3.health(sink3.crashed ? "down" : "up", sink3.crashed);
|
|
158873
|
+
sink3.log = (line) => ctx.emitEvent("search", { date: Date.now(), line });
|
|
158874
|
+
for (const line of sink3.tail) {
|
|
158875
|
+
ctx.emitEvent("search", { date: Date.now(), line });
|
|
158876
|
+
}
|
|
158772
158877
|
ctx.addEnv("SEARCH_DOMAIN", `localhost:${port}`);
|
|
158773
158878
|
const client = new Client5({ node: `http://localhost:${port}` });
|
|
158774
158879
|
for (const { stackName, id, props } of indexes) {
|
|
@@ -158781,7 +158886,8 @@ var searchOnDev = async (ctx) => {
|
|
|
158781
158886
|
kind: "search",
|
|
158782
158887
|
stack: stackName,
|
|
158783
158888
|
id,
|
|
158784
|
-
detail: `localhost:${port}
|
|
158889
|
+
detail: `localhost:${port}`,
|
|
158890
|
+
channel: "search"
|
|
158785
158891
|
});
|
|
158786
158892
|
}
|
|
158787
158893
|
};
|
|
@@ -159014,7 +159120,7 @@ var siteOnDev = async (ctx) => {
|
|
|
159014
159120
|
const value = await ctx.keep(key, { command: command3, port, env: env4 }, async () => {
|
|
159015
159121
|
const [bin, ...args] = command3.split(" ");
|
|
159016
159122
|
const cwd2 = join33(directories.root, dirname16(stackConfig.file));
|
|
159017
|
-
const
|
|
159123
|
+
const sink3 = {
|
|
159018
159124
|
emit: () => {},
|
|
159019
159125
|
stopping: false
|
|
159020
159126
|
};
|
|
@@ -159032,7 +159138,7 @@ var siteOnDev = async (ctx) => {
|
|
|
159032
159138
|
continue;
|
|
159033
159139
|
}
|
|
159034
159140
|
tail.push(line);
|
|
159035
|
-
|
|
159141
|
+
sink3.emit({ date: Date.now(), line });
|
|
159036
159142
|
}
|
|
159037
159143
|
while (tail.length > 20) {
|
|
159038
159144
|
tail.shift();
|
|
@@ -159040,24 +159146,30 @@ var siteOnDev = async (ctx) => {
|
|
|
159040
159146
|
};
|
|
159041
159147
|
child.stdout?.on("data", capture);
|
|
159042
159148
|
child.stderr?.on("data", capture);
|
|
159043
|
-
child.on("exit", (code) => {
|
|
159044
|
-
if (
|
|
159149
|
+
child.on("exit", (code, signal) => {
|
|
159150
|
+
if (sink3.stopping) {
|
|
159151
|
+
return;
|
|
159152
|
+
}
|
|
159153
|
+
if (code !== null && code !== 0) {
|
|
159045
159154
|
logs_exports.error(`The site "${id}" dev server exited with code ${code}:
|
|
159046
159155
|
${tail.join(`
|
|
159047
159156
|
`)}`);
|
|
159048
|
-
|
|
159157
|
+
sink3.emit({ date: Date.now(), line: `Exited with code ${code}` });
|
|
159049
159158
|
}
|
|
159159
|
+
sink3.health?.("down", code !== null ? `exited with code ${code}` : `killed by ${signal}`);
|
|
159050
159160
|
});
|
|
159051
159161
|
return {
|
|
159052
|
-
value: { port, tail, sink:
|
|
159162
|
+
value: { port, tail, sink: sink3, child },
|
|
159053
159163
|
stop: async () => {
|
|
159054
|
-
|
|
159164
|
+
sink3.stopping = true;
|
|
159055
159165
|
await stopChild(child);
|
|
159056
159166
|
}
|
|
159057
159167
|
};
|
|
159058
159168
|
});
|
|
159059
159169
|
value.sink.emit = (data) => ctx.emitEvent(channel, data);
|
|
159170
|
+
value.sink.health = (status2, detail) => ctx.reportHealth(`site ${id}`, status2, detail);
|
|
159060
159171
|
value.sink.stopping = false;
|
|
159172
|
+
value.sink.health(value.child.exitCode === null ? "up" : "down");
|
|
159061
159173
|
for (const line of value.tail) {
|
|
159062
159174
|
ctx.emitEvent(channel, { date: Date.now(), line });
|
|
159063
159175
|
}
|
|
@@ -160173,18 +160285,7 @@ var topicFeature = defineFeature({
|
|
|
160173
160285
|
});
|
|
160174
160286
|
}
|
|
160175
160287
|
}
|
|
160176
|
-
|
|
160177
|
-
const server2 = createSnsServer();
|
|
160178
|
-
const port2 = await server2.listen();
|
|
160179
|
-
return { value: { server: server2, port: port2 }, stop: () => server2.stop() };
|
|
160180
|
-
});
|
|
160181
|
-
ctx.addEnv("AWS_ENDPOINT_URL_SNS", `http://127.0.0.1:${port}`);
|
|
160182
|
-
ctx.registerServer({
|
|
160183
|
-
name: "sns",
|
|
160184
|
-
start({ dispatch, reportFailure }) {
|
|
160185
|
-
server.connect(dispatch, reportFailure);
|
|
160186
|
-
}
|
|
160187
|
-
});
|
|
160288
|
+
await ctx.useSns();
|
|
160188
160289
|
},
|
|
160189
160290
|
async onTypeGen(ctx) {
|
|
160190
160291
|
const gen = new TypeFile("awsless");
|
|
@@ -160382,6 +160483,7 @@ var vpcFeature = defineFeature({
|
|
|
160382
160483
|
});
|
|
160383
160484
|
|
|
160384
160485
|
// src/feature/alert/index.ts
|
|
160486
|
+
import { randomUUID as randomUUID7 } from "crypto";
|
|
160385
160487
|
var typeGenCode10 = `
|
|
160386
160488
|
import type { PublishOptions } from '@awsless/sns'
|
|
160387
160489
|
import type { Mock } from 'vitest'
|
|
@@ -160400,6 +160502,44 @@ type TestMockEntry = MockBuilder & Mock<(payload: unknown) => unknown>
|
|
|
160400
160502
|
`;
|
|
160401
160503
|
var alertFeature = defineFeature({
|
|
160402
160504
|
name: "alert",
|
|
160505
|
+
async onDev(ctx) {
|
|
160506
|
+
const ids = Object.keys(ctx.appConfig.alerts ?? {});
|
|
160507
|
+
if (ids.length === 0) {
|
|
160508
|
+
return;
|
|
160509
|
+
}
|
|
160510
|
+
const { captures, alerts } = await ctx.useSns();
|
|
160511
|
+
const names = new Map(ids.map((id) => [
|
|
160512
|
+
formatGlobalResourceName({
|
|
160513
|
+
appName: ctx.appConfig.name,
|
|
160514
|
+
resourceType: "alert",
|
|
160515
|
+
resourceName: id
|
|
160516
|
+
}),
|
|
160517
|
+
id
|
|
160518
|
+
]));
|
|
160519
|
+
captures.push((input) => {
|
|
160520
|
+
const id = names.get(input.TopicArn?.split(":").at(-1) ?? "");
|
|
160521
|
+
if (!id) {
|
|
160522
|
+
return false;
|
|
160523
|
+
}
|
|
160524
|
+
alerts.unshift({
|
|
160525
|
+
id: randomUUID7(),
|
|
160526
|
+
date: Date.now(),
|
|
160527
|
+
alert: id,
|
|
160528
|
+
subject: input.Subject,
|
|
160529
|
+
message: input.Message
|
|
160530
|
+
});
|
|
160531
|
+
ctx.emitEvent("problems", {
|
|
160532
|
+
date: Date.now(),
|
|
160533
|
+
kind: "alert",
|
|
160534
|
+
title: input.Subject ?? id,
|
|
160535
|
+
detail: id
|
|
160536
|
+
});
|
|
160537
|
+
return true;
|
|
160538
|
+
});
|
|
160539
|
+
for (const [name, id] of names) {
|
|
160540
|
+
ctx.registerResource({ kind: "alert", id, detail: name });
|
|
160541
|
+
}
|
|
160542
|
+
},
|
|
160403
160543
|
async onTypeGen(ctx) {
|
|
160404
160544
|
const gen = new TypeFile("awsless");
|
|
160405
160545
|
const resources = new TypeObject(1);
|
|
@@ -161457,6 +161597,7 @@ var instanceOnDev = async (ctx) => {
|
|
|
161457
161597
|
async start({ env: env4 }) {
|
|
161458
161598
|
const tail = [];
|
|
161459
161599
|
boot = () => {
|
|
161600
|
+
ctx.reportHealth(`instance ${id}`, "up");
|
|
161460
161601
|
child = spawn5("bun", [file2], {
|
|
161461
161602
|
cwd: cwd2,
|
|
161462
161603
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -161485,13 +161626,17 @@ var instanceOnDev = async (ctx) => {
|
|
|
161485
161626
|
};
|
|
161486
161627
|
child.stdout?.on("data", capture);
|
|
161487
161628
|
child.stderr?.on("data", capture);
|
|
161488
|
-
child.on("exit", (code) => {
|
|
161489
|
-
if (
|
|
161629
|
+
child.on("exit", (code, signal) => {
|
|
161630
|
+
if (stopping) {
|
|
161631
|
+
return;
|
|
161632
|
+
}
|
|
161633
|
+
if (code !== null && code !== 0) {
|
|
161490
161634
|
logs_exports.error(`The instance "${id}" exited with code ${code}:
|
|
161491
161635
|
${tail.join(`
|
|
161492
161636
|
`)}`);
|
|
161493
161637
|
ctx.emitEvent(channel, { date: Date.now(), line: `Exited with code ${code}`, error: true });
|
|
161494
161638
|
}
|
|
161639
|
+
ctx.reportHealth(`instance ${id}`, "down", code !== null ? `exited with code ${code}` : `killed by ${signal}`);
|
|
161495
161640
|
});
|
|
161496
161641
|
};
|
|
161497
161642
|
boot();
|
|
@@ -166580,7 +166725,7 @@ var createS3Server = (props) => {
|
|
|
166580
166725
|
};
|
|
166581
166726
|
|
|
166582
166727
|
// src/dev/servers/sqs.ts
|
|
166583
|
-
import { createHash as createHash23, randomUUID as
|
|
166728
|
+
import { createHash as createHash23, randomUUID as randomUUID8 } from "crypto";
|
|
166584
166729
|
import { createServer as createServer8 } from "http";
|
|
166585
166730
|
var md5 = (value) => createHash23("md5").update(value).digest("hex");
|
|
166586
166731
|
var md5OfAttributes = (attributes) => {
|
|
@@ -166655,7 +166800,7 @@ var createSqsServer = (props) => {
|
|
|
166655
166800
|
Records: [
|
|
166656
166801
|
{
|
|
166657
166802
|
messageId,
|
|
166658
|
-
receiptHandle:
|
|
166803
|
+
receiptHandle: randomUUID8(),
|
|
166659
166804
|
body: input.MessageBody,
|
|
166660
166805
|
attributes: {
|
|
166661
166806
|
ApproximateReceiveCount: "1",
|
|
@@ -166723,7 +166868,7 @@ var createSqsServer = (props) => {
|
|
|
166723
166868
|
if (!queue) {
|
|
166724
166869
|
throw new Error(`Unknown local queue: ${input.QueueUrl}`);
|
|
166725
166870
|
}
|
|
166726
|
-
const messageId =
|
|
166871
|
+
const messageId = randomUUID8();
|
|
166727
166872
|
deliver(queue, input, messageId);
|
|
166728
166873
|
return sendResult(input, messageId);
|
|
166729
166874
|
},
|
|
@@ -166734,7 +166879,7 @@ var createSqsServer = (props) => {
|
|
|
166734
166879
|
}
|
|
166735
166880
|
return {
|
|
166736
166881
|
Successful: (input.Entries ?? []).map((entry) => {
|
|
166737
|
-
const messageId =
|
|
166882
|
+
const messageId = randomUUID8();
|
|
166738
166883
|
deliver(queue, entry, messageId);
|
|
166739
166884
|
return {
|
|
166740
166885
|
Id: entry.Id,
|
|
@@ -166758,7 +166903,7 @@ var createSqsServer = (props) => {
|
|
|
166758
166903
|
const batch2 = visible.slice(0, Math.max(1, input.MaxNumberOfMessages ?? 1));
|
|
166759
166904
|
return {
|
|
166760
166905
|
Messages: batch2.map((message4) => {
|
|
166761
|
-
message4.receipt =
|
|
166906
|
+
message4.receipt = randomUUID8();
|
|
166762
166907
|
message4.receiveCount += 1;
|
|
166763
166908
|
message4.firstReceivedAt ??= now;
|
|
166764
166909
|
message4.visibleAt = now + (input.VisibilityTimeout ?? 30) * 1000;
|
|
@@ -166915,6 +167060,12 @@ var createDevContext = (props) => {
|
|
|
166915
167060
|
const servers = [];
|
|
166916
167061
|
const restartPaths = [];
|
|
166917
167062
|
const resources = [];
|
|
167063
|
+
const health = new Map;
|
|
167064
|
+
const reportHealth = (id, status2, detail) => {
|
|
167065
|
+
const entry = { id, status: status2, detail, date: Date.now() };
|
|
167066
|
+
health.set(id, entry);
|
|
167067
|
+
events.emit("health", entry);
|
|
167068
|
+
};
|
|
166918
167069
|
const listeners2 = new Map;
|
|
166919
167070
|
const replays = new Map;
|
|
166920
167071
|
const events = {
|
|
@@ -167012,12 +167163,37 @@ var createDevContext = (props) => {
|
|
|
167012
167163
|
})();
|
|
167013
167164
|
return sqs;
|
|
167014
167165
|
};
|
|
167166
|
+
let sns;
|
|
167167
|
+
const useSns = () => {
|
|
167168
|
+
sns ??= (async () => {
|
|
167169
|
+
const value = await props.pool.keep("shim:sns", null, async () => {
|
|
167170
|
+
const captures = [];
|
|
167171
|
+
const server = createSnsServer({ captures });
|
|
167172
|
+
const port = await server.listen();
|
|
167173
|
+
return {
|
|
167174
|
+
value: { server, port, captures, alerts: [] },
|
|
167175
|
+
stop: () => server.stop()
|
|
167176
|
+
};
|
|
167177
|
+
});
|
|
167178
|
+
value.captures.splice(0, value.captures.length);
|
|
167179
|
+
env4["AWS_ENDPOINT_URL_SNS"] = `http://127.0.0.1:${value.port}`;
|
|
167180
|
+
servers.push({
|
|
167181
|
+
name: "sns",
|
|
167182
|
+
start({ dispatch, reportFailure }) {
|
|
167183
|
+
value.server.connect(dispatch, reportFailure);
|
|
167184
|
+
}
|
|
167185
|
+
});
|
|
167186
|
+
return { port: value.port, captures: value.captures, alerts: value.alerts };
|
|
167187
|
+
})();
|
|
167188
|
+
return sns;
|
|
167189
|
+
};
|
|
167015
167190
|
return {
|
|
167016
167191
|
env: env4,
|
|
167017
167192
|
routes,
|
|
167018
167193
|
servers,
|
|
167019
167194
|
restartPaths,
|
|
167020
167195
|
resources,
|
|
167196
|
+
health,
|
|
167021
167197
|
events,
|
|
167022
167198
|
context: {
|
|
167023
167199
|
appConfig: props.appConfig,
|
|
@@ -167036,6 +167212,7 @@ var createDevContext = (props) => {
|
|
|
167036
167212
|
useDynamo,
|
|
167037
167213
|
useStore,
|
|
167038
167214
|
useSqs,
|
|
167215
|
+
useSns,
|
|
167039
167216
|
addEnv(name, value) {
|
|
167040
167217
|
if (name in env4 && env4[name] !== value) {
|
|
167041
167218
|
throw new Error(`The env var "${name}" is defined multiple times with different values, while all bundled functions share the same env.`);
|
|
@@ -167055,7 +167232,8 @@ var createDevContext = (props) => {
|
|
|
167055
167232
|
resources.push(resource);
|
|
167056
167233
|
},
|
|
167057
167234
|
log: props.log,
|
|
167058
|
-
emitEvent: events.emit
|
|
167235
|
+
emitEvent: events.emit,
|
|
167236
|
+
reportHealth
|
|
167059
167237
|
}
|
|
167060
167238
|
};
|
|
167061
167239
|
};
|
|
@@ -167112,7 +167290,7 @@ ${logs}`));
|
|
|
167112
167290
|
var import_ioredis5 = __toESM(require_built3(), 1);
|
|
167113
167291
|
import { DynamoDBClient as DynamoDBClient5 } from "@aws-sdk/client-dynamodb";
|
|
167114
167292
|
import { DynamoDBDocumentClient, ScanCommand as ScanCommand2 } from "@aws-sdk/lib-dynamodb";
|
|
167115
|
-
import { randomUUID as
|
|
167293
|
+
import { randomUUID as randomUUID9 } from "crypto";
|
|
167116
167294
|
import { readdir as readdir9, readFile as readFile22, stat as stat8, writeFile as writeFile14 } from "fs/promises";
|
|
167117
167295
|
import { createServer as createServer9 } from "http";
|
|
167118
167296
|
import { join as join55, relative as relative11, sep as sep5 } from "path";
|
|
@@ -167321,6 +167499,7 @@ var createBundleWorker = (props) => {
|
|
|
167321
167499
|
return run;
|
|
167322
167500
|
};
|
|
167323
167501
|
return {
|
|
167502
|
+
size: () => workers.length,
|
|
167324
167503
|
start: () => serialize(doStart),
|
|
167325
167504
|
stop: () => serialize(doStop),
|
|
167326
167505
|
restart: () => serialize(async () => {
|
|
@@ -167364,7 +167543,7 @@ var dashboardHtml = `<!doctype html>
|
|
|
167364
167543
|
--border: #262b36;
|
|
167365
167544
|
--text: #d7dae0;
|
|
167366
167545
|
--muted: #7d8590;
|
|
167367
|
-
--accent: #
|
|
167546
|
+
--accent: #ff9000;
|
|
167368
167547
|
--good: #3fb950;
|
|
167369
167548
|
--bad: #f85149;
|
|
167370
167549
|
font-size: 14px;
|
|
@@ -167426,18 +167605,34 @@ var dashboardHtml = `<!doctype html>
|
|
|
167426
167605
|
.logs .entry { padding: 4px 0; }
|
|
167427
167606
|
.logs .entry + .entry, .logs .line + .entry, .logs .entry + .line { border-top: 1px solid var(--border); }
|
|
167428
167607
|
.logs .entry .meta { display: flex; gap: 8px; margin-bottom: 2px; }
|
|
167429
|
-
|
|
167430
|
-
|
|
167431
|
-
|
|
167432
|
-
.config-form
|
|
167608
|
+
/* Every group is its own card, with a shared grid inside: the name
|
|
167609
|
+
column grows to the longest name (capped), so nothing truncates &
|
|
167610
|
+
the inputs line up. */
|
|
167611
|
+
.config-form { display: flex; flex-direction: column; gap: 14px; max-width: 720px; margin-top: 14px; }
|
|
167612
|
+
.config-group {
|
|
167433
167613
|
background: var(--panel);
|
|
167614
|
+
border: 1px solid var(--border);
|
|
167615
|
+
border-radius: 8px;
|
|
167616
|
+
padding: 14px 16px;
|
|
167617
|
+
}
|
|
167618
|
+
.config-group h3 { margin: 0 0 12px; }
|
|
167619
|
+
.config-fields {
|
|
167620
|
+
display: grid;
|
|
167621
|
+
grid-template-columns: fit-content(340px) 1fr;
|
|
167622
|
+
gap: 10px 16px;
|
|
167623
|
+
align-items: center;
|
|
167624
|
+
}
|
|
167625
|
+
.config-fields .field { display: contents; }
|
|
167626
|
+
.config-fields .name { color: var(--muted); overflow-wrap: anywhere; }
|
|
167627
|
+
.config-fields input {
|
|
167628
|
+
background: var(--bg);
|
|
167434
167629
|
color: var(--text);
|
|
167435
167630
|
border: 1px solid var(--border);
|
|
167436
167631
|
border-radius: 6px;
|
|
167437
167632
|
padding: 6px 10px;
|
|
167438
167633
|
font: inherit;
|
|
167439
167634
|
}
|
|
167440
|
-
.config-
|
|
167635
|
+
.config-fields input::placeholder { color: var(--muted); }
|
|
167441
167636
|
.groups { display: flex; flex-wrap: wrap; gap: 4px 16px; }
|
|
167442
167637
|
.groups .group { display: flex; align-items: center; gap: 4px; cursor: pointer; }
|
|
167443
167638
|
nav {
|
|
@@ -167448,10 +167643,13 @@ var dashboardHtml = `<!doctype html>
|
|
|
167448
167643
|
nav h1 {
|
|
167449
167644
|
font-size: 15px;
|
|
167450
167645
|
margin: 4px 8px 16px;
|
|
167451
|
-
color: var(--accent);
|
|
167452
167646
|
cursor: pointer;
|
|
167453
167647
|
}
|
|
167454
|
-
|
|
167648
|
+
/* The same two-tone logo as the cli: bold AWS in the brand orange,
|
|
167649
|
+
LESS dimmed, the command muted. */
|
|
167650
|
+
nav h1 .logo { color: var(--accent); font-weight: bold; }
|
|
167651
|
+
nav h1 .logo .dim { color: #a35d00; }
|
|
167652
|
+
nav h1 .cmd { color: var(--muted); font-weight: normal; }
|
|
167455
167653
|
nav h3 {
|
|
167456
167654
|
font-size: 10px;
|
|
167457
167655
|
text-transform: uppercase;
|
|
@@ -167544,6 +167742,24 @@ var dashboardHtml = `<!doctype html>
|
|
|
167544
167742
|
cursor: pointer;
|
|
167545
167743
|
}
|
|
167546
167744
|
.row:hover { background: var(--panel); }
|
|
167745
|
+
a.row { text-decoration: none; }
|
|
167746
|
+
.health { display: flex; flex-wrap: wrap; gap: 8px; margin: 12px 0 4px; }
|
|
167747
|
+
.health .chip {
|
|
167748
|
+
display: inline-flex;
|
|
167749
|
+
align-items: center;
|
|
167750
|
+
gap: 7px;
|
|
167751
|
+
background: var(--panel);
|
|
167752
|
+
border: 1px solid var(--border);
|
|
167753
|
+
border-radius: 999px;
|
|
167754
|
+
padding: 4px 12px;
|
|
167755
|
+
font-size: 12px;
|
|
167756
|
+
}
|
|
167757
|
+
.health .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--good); flex-shrink: 0; }
|
|
167758
|
+
.health .chip.down { border-color: var(--bad); }
|
|
167759
|
+
.health .chip.down .dot { background: var(--bad); }
|
|
167760
|
+
.health .chip .detail-text { color: var(--muted); }
|
|
167761
|
+
.row.problem .id { color: var(--bad); }
|
|
167762
|
+
.empty.good { color: var(--good); }
|
|
167547
167763
|
.row .stack {
|
|
167548
167764
|
color: var(--muted);
|
|
167549
167765
|
min-width: 90px;
|
|
@@ -167675,9 +167891,10 @@ const GROUPS = [
|
|
|
167675
167891
|
['store', 'Stores'],
|
|
167676
167892
|
['config', 'Config'],
|
|
167677
167893
|
['auth', 'Auth'],
|
|
167894
|
+
['alert', 'Alerts'],
|
|
167678
167895
|
['email', 'Emails'],
|
|
167679
167896
|
['worker', 'Logs'],
|
|
167680
|
-
['route', '
|
|
167897
|
+
['route', 'Routers'],
|
|
167681
167898
|
]
|
|
167682
167899
|
|
|
167683
167900
|
// The nav renders the features in scannable sections - a section only
|
|
@@ -167687,7 +167904,7 @@ const SECTIONS = [
|
|
|
167687
167904
|
['Compute', ['function', 'cron', 'task', 'instance']],
|
|
167688
167905
|
['Messaging', ['queue', 'topic', 'subscriber', 'pubsub']],
|
|
167689
167906
|
['Storage', ['table', 'cache', 'search', 'store']],
|
|
167690
|
-
['App', ['config', 'auth', 'email', 'worker']],
|
|
167907
|
+
['App', ['config', 'auth', 'alert', 'email', 'worker']],
|
|
167691
167908
|
]
|
|
167692
167909
|
|
|
167693
167910
|
const svg = inner =>
|
|
@@ -167710,6 +167927,7 @@ const ICONS = {
|
|
|
167710
167927
|
cache: svg('<ellipse cx="12" cy="5" rx="9" ry="3"/><path d="M21 12c0 1.66-4 3-9 3s-9-1.34-9-3"/><path d="M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5"/>'),
|
|
167711
167928
|
search: svg('<circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/>'),
|
|
167712
167929
|
store: svg('<path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/>'),
|
|
167930
|
+
alert: svg('<path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/>'),
|
|
167713
167931
|
email: svg('<rect x="2" y="4" width="20" height="16" rx="2"/><path d="m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7"/>'),
|
|
167714
167932
|
config: svg('<line x1="4" y1="21" x2="4" y2="14"/><line x1="4" y1="10" x2="4" y2="3"/><line x1="12" y1="21" x2="12" y2="12"/><line x1="12" y1="8" x2="12" y2="3"/><line x1="20" y1="21" x2="20" y2="16"/><line x1="20" y1="12" x2="20" y2="3"/><line x1="1" y1="14" x2="7" y2="14"/><line x1="9" y1="8" x2="15" y2="8"/><line x1="17" y1="16" x2="23" y2="16"/>'),
|
|
167715
167933
|
route: svg('<circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/>'),
|
|
@@ -167728,7 +167946,7 @@ const icon = kind => {
|
|
|
167728
167946
|
let state
|
|
167729
167947
|
let cleanupPanel
|
|
167730
167948
|
const view = { kind: null, resource: null }
|
|
167731
|
-
const filter = { query: '', stack: '' }
|
|
167949
|
+
const filter = { query: '', stack: '', router: '' }
|
|
167732
167950
|
|
|
167733
167951
|
const label = r => (r.stack ? r.stack + ' / ' + r.id : r.id)
|
|
167734
167952
|
const groupTitle = kind => GROUPS.find(([k]) => k === kind)?.[1] ?? kind
|
|
@@ -167744,6 +167962,7 @@ const filterParams = () => {
|
|
|
167744
167962
|
const params = new URLSearchParams()
|
|
167745
167963
|
if (filter.query) params.set('q', filter.query)
|
|
167746
167964
|
if (filter.stack) params.set('stack', filter.stack)
|
|
167965
|
+
if (filter.router) params.set('router', filter.router)
|
|
167747
167966
|
return params.toString()
|
|
167748
167967
|
}
|
|
167749
167968
|
|
|
@@ -167764,6 +167983,7 @@ const selectKind = kind => {
|
|
|
167764
167983
|
view.resource = null
|
|
167765
167984
|
filter.query = ''
|
|
167766
167985
|
filter.stack = ''
|
|
167986
|
+
filter.router = ''
|
|
167767
167987
|
history.pushState(null, '', listUrl(kind))
|
|
167768
167988
|
render()
|
|
167769
167989
|
}
|
|
@@ -167789,6 +168009,7 @@ const applyLocation = () => {
|
|
|
167789
168009
|
view.resource = null
|
|
167790
168010
|
filter.query = params.get('q') ?? ''
|
|
167791
168011
|
filter.stack = params.get('stack') ?? ''
|
|
168012
|
+
filter.router = params.get('router') ?? ''
|
|
167792
168013
|
|
|
167793
168014
|
if (view.kind && segments.length >= 3) {
|
|
167794
168015
|
const router = params.get('router')
|
|
@@ -168175,6 +168396,11 @@ const cachePanel = async (main, r) => {
|
|
|
168175
168396
|
const holder = $('div', {}, $('p', { className: 'empty' }, 'Scanning...'))
|
|
168176
168397
|
main.append(holder)
|
|
168177
168398
|
|
|
168399
|
+
// The redis server's own output, streamed live.
|
|
168400
|
+
if (r.channel) {
|
|
168401
|
+
cleanupPanel = attachLogFeed(main, r.channel, undefined, 'Server logs')
|
|
168402
|
+
}
|
|
168403
|
+
|
|
168178
168404
|
try {
|
|
168179
168405
|
const data = await api('/api/cache?target=' + encodeURIComponent(r.detail))
|
|
168180
168406
|
holder.innerHTML = ''
|
|
@@ -168255,6 +168481,11 @@ const searchPanel = async (main, r) => {
|
|
|
168255
168481
|
result,
|
|
168256
168482
|
)
|
|
168257
168483
|
|
|
168484
|
+
// The opensearch server's own output, streamed live.
|
|
168485
|
+
if (r.channel) {
|
|
168486
|
+
cleanupPanel = attachLogFeed(main, r.channel, undefined, 'Server logs')
|
|
168487
|
+
}
|
|
168488
|
+
|
|
168258
168489
|
try {
|
|
168259
168490
|
const { data } = await proxy('/_cat/indices?format=json&h=index,health,docs.count,store.size&s=index')
|
|
168260
168491
|
const rows = data.filter(entry => !entry.index.startsWith('.'))
|
|
@@ -168309,6 +168540,59 @@ const storePanel = async (main, r) => {
|
|
|
168309
168540
|
|
|
168310
168541
|
// Every email sent through Email.send during this session - captured
|
|
168311
168542
|
// by the local ses shim instead of being delivered.
|
|
168543
|
+
const alertPanel = async (main) => {
|
|
168544
|
+
const holder = $('div', {})
|
|
168545
|
+
main.append(holder)
|
|
168546
|
+
|
|
168547
|
+
const render = async () => {
|
|
168548
|
+
const data = await api('/api/alerts')
|
|
168549
|
+
const alerts = data.alerts ?? []
|
|
168550
|
+
holder.innerHTML = ''
|
|
168551
|
+
|
|
168552
|
+
const refresh = $('button', { className: 'primary', textContent: 'Refresh' })
|
|
168553
|
+
refresh.onclick = render
|
|
168554
|
+
holder.append($('div', { className: 'actions' }, [refresh]))
|
|
168555
|
+
|
|
168556
|
+
if (alerts.length === 0) {
|
|
168557
|
+
holder.append($('p', { className: 'empty' }, 'No alerts sent yet.'))
|
|
168558
|
+
return
|
|
168559
|
+
}
|
|
168560
|
+
|
|
168561
|
+
const rows = $('div', { className: 'rows' })
|
|
168562
|
+
|
|
168563
|
+
for (const alert of alerts) {
|
|
168564
|
+
const row = $('button', { className: 'row' }, [
|
|
168565
|
+
$('span', { className: 'stack' }, new Date(alert.date).toLocaleTimeString()),
|
|
168566
|
+
$('span', { className: 'id' }, alert.subject ?? '(no subject)'),
|
|
168567
|
+
$('span', { className: 'info' }, alert.alert),
|
|
168568
|
+
])
|
|
168569
|
+
row.onclick = () => {
|
|
168570
|
+
holder.innerHTML = ''
|
|
168571
|
+
|
|
168572
|
+
const back = $('button', { className: 'back', textContent: '\u2190 Alerts' })
|
|
168573
|
+
back.onclick = render
|
|
168574
|
+
|
|
168575
|
+
let message = alert.message ?? '(no payload)'
|
|
168576
|
+
try {
|
|
168577
|
+
message = JSON.stringify(JSON.parse(alert.message), null, 2)
|
|
168578
|
+
} catch (_) {}
|
|
168579
|
+
|
|
168580
|
+
holder.append(
|
|
168581
|
+
back,
|
|
168582
|
+
$('h2', {}, alert.subject ?? '(no subject)'),
|
|
168583
|
+
$('p', { className: 'detail' }, alert.alert + ' \xB7 ' + new Date(alert.date).toLocaleString()),
|
|
168584
|
+
$('pre', { className: 'result' }, message),
|
|
168585
|
+
)
|
|
168586
|
+
}
|
|
168587
|
+
rows.append(row)
|
|
168588
|
+
}
|
|
168589
|
+
|
|
168590
|
+
holder.append(rows)
|
|
168591
|
+
}
|
|
168592
|
+
|
|
168593
|
+
render()
|
|
168594
|
+
}
|
|
168595
|
+
|
|
168312
168596
|
const emailPanel = async (main) => {
|
|
168313
168597
|
const holder = $('div', {})
|
|
168314
168598
|
main.append(holder)
|
|
@@ -168371,7 +168655,34 @@ const configPanel = async (main) => {
|
|
|
168371
168655
|
const inputs = new Map()
|
|
168372
168656
|
const form = $('div', { className: 'config-form' })
|
|
168373
168657
|
|
|
168658
|
+
// Configs group by the first segment of their name: alphapo-api-key
|
|
168659
|
+
// & alphapo-host read as one "alphapo" block with the prefix
|
|
168660
|
+
// stripped from the rows. A prefix needs at least two members to
|
|
168661
|
+
// form a group - the loners keep their full name under "other".
|
|
168662
|
+
const byPrefix = new Map()
|
|
168663
|
+
|
|
168374
168664
|
for (const name of names) {
|
|
168665
|
+
const prefix = name.split('-')[0]
|
|
168666
|
+
if (!byPrefix.has(prefix)) byPrefix.set(prefix, [])
|
|
168667
|
+
byPrefix.get(prefix).push(name)
|
|
168668
|
+
}
|
|
168669
|
+
|
|
168670
|
+
const sections = []
|
|
168671
|
+
const other = []
|
|
168672
|
+
|
|
168673
|
+
for (const [prefix, members] of byPrefix) {
|
|
168674
|
+
if (members.length > 1) {
|
|
168675
|
+
sections.push([prefix, members])
|
|
168676
|
+
} else {
|
|
168677
|
+
other.push(members[0])
|
|
168678
|
+
}
|
|
168679
|
+
}
|
|
168680
|
+
|
|
168681
|
+
if (other.length > 0) {
|
|
168682
|
+
sections.push(['other', other])
|
|
168683
|
+
}
|
|
168684
|
+
|
|
168685
|
+
const addField = (grid, name) => {
|
|
168375
168686
|
// An empty input falls through to the value pulled from ssm on
|
|
168376
168687
|
// boot - the placeholder shows whether the pull provided one.
|
|
168377
168688
|
const input = $('input', {
|
|
@@ -168380,7 +168691,21 @@ const configPanel = async (main) => {
|
|
|
168380
168691
|
spellcheck: false,
|
|
168381
168692
|
})
|
|
168382
168693
|
inputs.set(name, input)
|
|
168383
|
-
|
|
168694
|
+
grid.append($('label', { className: 'field' }, [$('span', { className: 'name' }, name), input]))
|
|
168695
|
+
}
|
|
168696
|
+
|
|
168697
|
+
for (const [prefix, members] of sections) {
|
|
168698
|
+
const grid = $('div', { className: 'config-fields' })
|
|
168699
|
+
|
|
168700
|
+
for (const name of members) {
|
|
168701
|
+
addField(grid, name)
|
|
168702
|
+
}
|
|
168703
|
+
|
|
168704
|
+
// A lone unlabeled group skips its header - the card alone
|
|
168705
|
+
// carries the grouping.
|
|
168706
|
+
const header = sections.length > 1 || other.length === 0 ? [$('h3', {}, prefix)] : []
|
|
168707
|
+
|
|
168708
|
+
form.append($('div', { className: 'config-group' }, [...header, grid]))
|
|
168384
168709
|
}
|
|
168385
168710
|
|
|
168386
168711
|
if (names.length === 0) {
|
|
@@ -168549,7 +168874,9 @@ const authPanel = async (main, r) => {
|
|
|
168549
168874
|
|
|
168550
168875
|
const renderResource = main => {
|
|
168551
168876
|
const r = view.resource
|
|
168552
|
-
|
|
168877
|
+
// A route's back button lands on its router's route list, one level
|
|
168878
|
+
// below the Routers tab itself.
|
|
168879
|
+
const back = $('button', { className: 'back' }, '\u2190 ' + (r.kind === 'route' ? 'Routes' : groupTitle(r.kind)))
|
|
168553
168880
|
|
|
168554
168881
|
back.onclick = () => {
|
|
168555
168882
|
view.resource = null
|
|
@@ -168596,7 +168923,49 @@ const renderList = main => {
|
|
|
168596
168923
|
const items = state.resources.filter(r => r.kind === view.kind)
|
|
168597
168924
|
const stacks = [...new Set(items.map(r => r.stack).filter(Boolean))].sort()
|
|
168598
168925
|
|
|
168599
|
-
|
|
168926
|
+
// The routes view drills down per router: every router runs as its
|
|
168927
|
+
// own local server (like its own domain in production), so a flat
|
|
168928
|
+
// list mixing every router's routes would only confuse.
|
|
168929
|
+
if (view.kind === 'route' && !filter.router) {
|
|
168930
|
+
main.append($('h2', {}, 'Routers'))
|
|
168931
|
+
|
|
168932
|
+
const rows = $('div', { className: 'rows' })
|
|
168933
|
+
|
|
168934
|
+
for (const [id, port] of Object.entries(state.routerPorts)) {
|
|
168935
|
+
const count = items.filter(r => r.router === id).length
|
|
168936
|
+
const row = $('button', { className: 'row' }, [
|
|
168937
|
+
$('span', { className: 'stack' }, id),
|
|
168938
|
+
$('span', { className: 'id' }, 'http://localhost:' + port),
|
|
168939
|
+
$('span', { className: 'info' }, count + (count === 1 ? ' route' : ' routes')),
|
|
168940
|
+
])
|
|
168941
|
+
row.onclick = () => {
|
|
168942
|
+
filter.router = id
|
|
168943
|
+
history.pushState(null, '', listUrl('route'))
|
|
168944
|
+
render()
|
|
168945
|
+
}
|
|
168946
|
+
rows.append(row)
|
|
168947
|
+
}
|
|
168948
|
+
|
|
168949
|
+
main.append(rows)
|
|
168950
|
+
return
|
|
168951
|
+
}
|
|
168952
|
+
|
|
168953
|
+
if (view.kind === 'route') {
|
|
168954
|
+
const back = $('button', { className: 'back' }, '\u2190 Routers')
|
|
168955
|
+
back.onclick = () => {
|
|
168956
|
+
filter.router = ''
|
|
168957
|
+
history.pushState(null, '', listUrl('route'))
|
|
168958
|
+
render()
|
|
168959
|
+
}
|
|
168960
|
+
|
|
168961
|
+
main.append(
|
|
168962
|
+
back,
|
|
168963
|
+
$('h2', {}, 'Routes'),
|
|
168964
|
+
$('p', { className: 'detail' }, filter.router + ' \xB7 http://localhost:' + state.routerPorts[filter.router]),
|
|
168965
|
+
)
|
|
168966
|
+
} else {
|
|
168967
|
+
main.append($('h2', {}, groupTitle(view.kind)))
|
|
168968
|
+
}
|
|
168600
168969
|
|
|
168601
168970
|
// The config page is a single form over every defined value,
|
|
168602
168971
|
// instead of a resource list.
|
|
@@ -168609,15 +168978,27 @@ const renderList = main => {
|
|
|
168609
168978
|
return emailPanel(main)
|
|
168610
168979
|
}
|
|
168611
168980
|
|
|
168981
|
+
// The alert page lists every captured alert of the session.
|
|
168982
|
+
if (view.kind === 'alert') {
|
|
168983
|
+
return alertPanel(main)
|
|
168984
|
+
}
|
|
168985
|
+
|
|
168612
168986
|
// The worker page streams the bundle worker output directly,
|
|
168613
168987
|
// instead of listing its single resource.
|
|
168614
168988
|
if (view.kind === 'worker') {
|
|
168615
|
-
|
|
168989
|
+
const workerFeed = attachLogFeed(main, 'worker', undefined, 'Worker output')
|
|
168990
|
+
const debugFeed = attachLogFeed(main, 'debug', undefined, 'Dev server')
|
|
168991
|
+
|
|
168992
|
+
cleanupPanel = () => {
|
|
168993
|
+
workerFeed?.()
|
|
168994
|
+
debugFeed?.()
|
|
168995
|
+
}
|
|
168616
168996
|
return
|
|
168617
168997
|
}
|
|
168618
168998
|
|
|
168619
168999
|
const matches = r => {
|
|
168620
169000
|
if (filter.stack && r.stack !== filter.stack) return false
|
|
169001
|
+
if (filter.router && r.router !== filter.router) return false
|
|
168621
169002
|
if (!filter.query) return true
|
|
168622
169003
|
|
|
168623
169004
|
return (r.stack + ' ' + r.id + ' ' + (r.detail ?? ''))
|
|
@@ -168691,11 +169072,14 @@ const render = () => {
|
|
|
168691
169072
|
cleanupPanel = undefined
|
|
168692
169073
|
|
|
168693
169074
|
const nav = document.getElementById('nav')
|
|
168694
|
-
nav.innerHTML = '<h1>
|
|
169075
|
+
nav.innerHTML = '<h1><span class="logo">AWS<span class="dim">LESS</span></span> <span class="cmd">dev</span></h1>'
|
|
168695
169076
|
nav.querySelector('h1').onclick = showHome
|
|
168696
169077
|
|
|
168697
169078
|
const navButton = kind => {
|
|
168698
|
-
|
|
169079
|
+
// The Routers tab lists routers, so its count follows suit.
|
|
169080
|
+
const count = kind === 'route'
|
|
169081
|
+
? Object.keys(state.routerPorts).length
|
|
169082
|
+
: state.resources.filter(r => r.kind === kind).length
|
|
168699
169083
|
if (count === 0) return null
|
|
168700
169084
|
|
|
168701
169085
|
// The email outbox is a single feed, so a count of registered
|
|
@@ -168703,7 +169087,7 @@ const render = () => {
|
|
|
168703
169087
|
const button = $('button', { className: view.kind === kind ? 'active' : '' }, [
|
|
168704
169088
|
icon(kind),
|
|
168705
169089
|
groupTitle(kind),
|
|
168706
|
-
kind === 'email' || kind === 'worker' ? '' : $('span', { className: 'count' }, String(count)),
|
|
169090
|
+
kind === 'email' || kind === 'worker' || kind === 'alert' ? '' : $('span', { className: 'count' }, String(count)),
|
|
168707
169091
|
])
|
|
168708
169092
|
button.onclick = () => selectKind(kind)
|
|
168709
169093
|
return button
|
|
@@ -168775,7 +169159,192 @@ const render = () => {
|
|
|
168775
169159
|
} else if (view.kind) {
|
|
168776
169160
|
renderList(main)
|
|
168777
169161
|
} else {
|
|
168778
|
-
main
|
|
169162
|
+
renderHome(main)
|
|
169163
|
+
}
|
|
169164
|
+
}
|
|
169165
|
+
|
|
169166
|
+
// ------------------------------------------------------------------
|
|
169167
|
+
// Homepage: the session at a glance - endpoints, problems & the live
|
|
169168
|
+
// activity feed of everything running through the bundle.
|
|
169169
|
+
|
|
169170
|
+
const timeAgo = ms => {
|
|
169171
|
+
const s = Math.max(0, Math.round(ms / 1000))
|
|
169172
|
+
if (s < 60) return s + 's'
|
|
169173
|
+
if (s < 3600) return Math.round(s / 60) + 'm'
|
|
169174
|
+
return Math.floor(s / 3600) + 'h ' + (Math.round(s / 60) % 60) + 'm'
|
|
169175
|
+
}
|
|
169176
|
+
|
|
169177
|
+
const renderHome = main => {
|
|
169178
|
+
const session = state.session ?? {}
|
|
169179
|
+
|
|
169180
|
+
const uptime = $('span', {}, '')
|
|
169181
|
+
const updateUptime = () => {
|
|
169182
|
+
uptime.textContent = session.startedAt ? 'up ' + timeAgo(Date.now() - session.startedAt) : ''
|
|
169183
|
+
}
|
|
169184
|
+
updateUptime()
|
|
169185
|
+
const uptimeTimer = setInterval(updateUptime, 1000)
|
|
169186
|
+
|
|
169187
|
+
main.append(
|
|
169188
|
+
$('h2', {}, state.app),
|
|
169189
|
+
$('p', { className: 'detail' }, [
|
|
169190
|
+
uptime,
|
|
169191
|
+
session.workers ? ' \\u00b7 ' + session.workers + ' workers' : '',
|
|
169192
|
+
]),
|
|
169193
|
+
)
|
|
169194
|
+
|
|
169195
|
+
// ----------------------------------------------------------------
|
|
169196
|
+
// Health: one chip per moving part, live.
|
|
169197
|
+
|
|
169198
|
+
const chips = $('div', { className: 'health' })
|
|
169199
|
+
const chipEls = new Map()
|
|
169200
|
+
|
|
169201
|
+
const renderChip = entry => {
|
|
169202
|
+
let chip = chipEls.get(entry.id)
|
|
169203
|
+
|
|
169204
|
+
if (!chip) {
|
|
169205
|
+
chip = $('span', { className: 'chip' })
|
|
169206
|
+
chipEls.set(entry.id, chip)
|
|
169207
|
+
chips.append(chip)
|
|
169208
|
+
}
|
|
169209
|
+
|
|
169210
|
+
chip.className = 'chip' + (entry.status === 'down' ? ' down' : '')
|
|
169211
|
+
chip.innerHTML = ''
|
|
169212
|
+
chip.append(
|
|
169213
|
+
$('span', { className: 'dot' }),
|
|
169214
|
+
entry.id,
|
|
169215
|
+
entry.detail ? $('span', { className: 'detail-text' }, '\xB7 ' + entry.detail) : '',
|
|
169216
|
+
)
|
|
169217
|
+
}
|
|
169218
|
+
|
|
169219
|
+
for (const entry of state.health ?? []) renderChip(entry)
|
|
169220
|
+
|
|
169221
|
+
const healthSource = new EventSource('/api/events?channel=health')
|
|
169222
|
+
healthSource.onmessage = message => {
|
|
169223
|
+
try {
|
|
169224
|
+
renderChip(JSON.parse(message.data))
|
|
169225
|
+
} catch (_) {}
|
|
169226
|
+
}
|
|
169227
|
+
|
|
169228
|
+
if ((state.health ?? []).length > 0) {
|
|
169229
|
+
main.append(chips)
|
|
169230
|
+
}
|
|
169231
|
+
|
|
169232
|
+
// ----------------------------------------------------------------
|
|
169233
|
+
// Endpoints
|
|
169234
|
+
|
|
169235
|
+
main.append($('h3', {}, 'Endpoints'))
|
|
169236
|
+
|
|
169237
|
+
const endpoints = $('div', { className: 'rows' })
|
|
169238
|
+
|
|
169239
|
+
for (const [id, port] of Object.entries(state.routerPorts ?? {})) {
|
|
169240
|
+
const url = 'http://localhost:' + port
|
|
169241
|
+
const row = $('a', { className: 'row', href: url, target: '_blank' }, [
|
|
169242
|
+
$('span', { className: 'stack' }, 'router ' + id),
|
|
169243
|
+
$('span', { className: 'id' }, url),
|
|
169244
|
+
$('span', { className: 'info' }, ''),
|
|
169245
|
+
])
|
|
169246
|
+
endpoints.append(row)
|
|
169247
|
+
}
|
|
169248
|
+
|
|
169249
|
+
main.append(endpoints)
|
|
169250
|
+
|
|
169251
|
+
// ----------------------------------------------------------------
|
|
169252
|
+
// Problems: failures, route errors & fired alerts, newest first.
|
|
169253
|
+
|
|
169254
|
+
main.append($('h3', {}, 'Problems'))
|
|
169255
|
+
|
|
169256
|
+
const problems = $('div', { className: 'rows' })
|
|
169257
|
+
const calm = $('p', { className: 'empty good' }, 'No problems - everything runs clean.')
|
|
169258
|
+
main.append(calm, problems)
|
|
169259
|
+
|
|
169260
|
+
const problemRows = []
|
|
169261
|
+
|
|
169262
|
+
const problemRow = data => {
|
|
169263
|
+
calm.hidden = true
|
|
169264
|
+
|
|
169265
|
+
const row = $('button', { className: 'row problem' }, [
|
|
169266
|
+
$('span', { className: 'stack' }, new Date(data.date).toLocaleTimeString() + ' \\u00b7 ' + data.kind),
|
|
169267
|
+
$('span', { className: 'id' }, data.title ?? ''),
|
|
169268
|
+
$('span', { className: 'info' }, (data.detail ?? '').slice(0, 120)),
|
|
169269
|
+
])
|
|
169270
|
+
|
|
169271
|
+
row.onclick = () => {
|
|
169272
|
+
if (data.kind === 'alert') {
|
|
169273
|
+
selectKind('alert')
|
|
169274
|
+
return
|
|
169275
|
+
}
|
|
169276
|
+
|
|
169277
|
+
const resource = state.resources.find(r => r.routeKey === data.title)
|
|
169278
|
+
if (resource) selectResource(resource)
|
|
169279
|
+
}
|
|
169280
|
+
|
|
169281
|
+
problems.prepend(row)
|
|
169282
|
+
problemRows.push(row)
|
|
169283
|
+
|
|
169284
|
+
while (problemRows.length > 20) {
|
|
169285
|
+
problemRows.shift().remove()
|
|
169286
|
+
}
|
|
169287
|
+
}
|
|
169288
|
+
|
|
169289
|
+
const problemSource = new EventSource('/api/events?channel=problems')
|
|
169290
|
+
problemSource.onmessage = message => {
|
|
169291
|
+
try {
|
|
169292
|
+
problemRow(JSON.parse(message.data))
|
|
169293
|
+
} catch (_) {}
|
|
169294
|
+
}
|
|
169295
|
+
|
|
169296
|
+
// ----------------------------------------------------------------
|
|
169297
|
+
// Activity: every dispatch through the bundle, newest first.
|
|
169298
|
+
|
|
169299
|
+
main.append($('h3', {}, 'Activity'))
|
|
169300
|
+
|
|
169301
|
+
const activity = $('div', { className: 'rows' })
|
|
169302
|
+
const idle = $('p', { className: 'empty' }, 'Nothing ran yet.')
|
|
169303
|
+
main.append(idle, activity)
|
|
169304
|
+
|
|
169305
|
+
const activityRows = []
|
|
169306
|
+
|
|
169307
|
+
const activityRow = data => {
|
|
169308
|
+
idle.hidden = true
|
|
169309
|
+
|
|
169310
|
+
const resource = state.resources.find(r => r.routeKey === data.route)
|
|
169311
|
+
const row = $('button', { className: 'row' + (data.ok ? '' : ' problem') }, [
|
|
169312
|
+
$('span', { className: 'stack' }, new Date(data.date).toLocaleTimeString()),
|
|
169313
|
+
$('span', { className: 'id' }, (data.ok ? '' : '\\u2717 ') + data.route),
|
|
169314
|
+
$('span', { className: 'info' }, data.ok ? data.ms + 'ms' : (data.error ?? 'failed').slice(0, 80)),
|
|
169315
|
+
])
|
|
169316
|
+
|
|
169317
|
+
if (resource) {
|
|
169318
|
+
row.onclick = () => selectResource(resource)
|
|
169319
|
+
}
|
|
169320
|
+
|
|
169321
|
+
activity.prepend(row)
|
|
169322
|
+
activityRows.push(row)
|
|
169323
|
+
|
|
169324
|
+
while (activityRows.length > 50) {
|
|
169325
|
+
activityRows.shift().remove()
|
|
169326
|
+
}
|
|
169327
|
+
}
|
|
169328
|
+
|
|
169329
|
+
const activitySource = new EventSource('/api/events?channel=activity')
|
|
169330
|
+
activitySource.onmessage = message => {
|
|
169331
|
+
try {
|
|
169332
|
+
activityRow(JSON.parse(message.data))
|
|
169333
|
+
} catch (_) {}
|
|
169334
|
+
}
|
|
169335
|
+
|
|
169336
|
+
// ----------------------------------------------------------------
|
|
169337
|
+
// Logs: the handlers' own console output, live - the full feed
|
|
169338
|
+
// (incl. the dev server stream) lives on the Logs tab.
|
|
169339
|
+
|
|
169340
|
+
const logsFeed = attachLogFeed(main, 'worker', undefined, 'Logs')
|
|
169341
|
+
|
|
169342
|
+
cleanupPanel = () => {
|
|
169343
|
+
clearInterval(uptimeTimer)
|
|
169344
|
+
healthSource.close()
|
|
169345
|
+
problemSource.close()
|
|
169346
|
+
activitySource.close()
|
|
169347
|
+
logsFeed?.()
|
|
168779
169348
|
}
|
|
168780
169349
|
}
|
|
168781
169350
|
|
|
@@ -168796,14 +169365,15 @@ try {
|
|
|
168796
169365
|
document.title = state.app + ' \xB7 awsless dev'
|
|
168797
169366
|
state.resources = [
|
|
168798
169367
|
...state.resources,
|
|
168799
|
-
//
|
|
168800
|
-
//
|
|
168801
|
-
|
|
169368
|
+
// The full route table per router, like the deployed router: both
|
|
169369
|
+
// bundle routes & proxy mounts (site dev servers, the pubsub
|
|
169370
|
+
// websocket). Only the raw per-file static asset routes stay out.
|
|
169371
|
+
...state.routes.filter(route => !route.rawKey).map(route => ({
|
|
168802
169372
|
kind: 'route',
|
|
168803
169373
|
id: route.pattern,
|
|
168804
|
-
stack: route.routeKey.split(':')[0],
|
|
169374
|
+
stack: route.routeKey ? route.routeKey.split(':')[0] : undefined,
|
|
168805
169375
|
router: route.routerId,
|
|
168806
|
-
detail: route.routeKey,
|
|
169376
|
+
detail: route.routeKey ?? ('proxy \u2192 ' + route.proxy),
|
|
168807
169377
|
url: 'http://localhost:' + state.routerPorts[route.routerId] + route.pattern.split('{')[0].replace(/\\*$/, ''),
|
|
168808
169378
|
})),
|
|
168809
169379
|
]
|
|
@@ -168863,7 +169433,9 @@ var createDashboardServer = (props) => {
|
|
|
168863
169433
|
routerPorts: props.routerPorts,
|
|
168864
169434
|
resources: props.resources,
|
|
168865
169435
|
routes: props.routes,
|
|
168866
|
-
seeds: Boolean(props.runSeeds)
|
|
169436
|
+
seeds: Boolean(props.runSeeds),
|
|
169437
|
+
session: props.getSession?.() ?? null,
|
|
169438
|
+
health: props.getHealth?.() ?? []
|
|
168867
169439
|
}).replaceAll("<", "\\u003c");
|
|
168868
169440
|
return { status: 200, body: dashboardHtml.replace("__STATE__", () => state), type: "text/html" };
|
|
168869
169441
|
}
|
|
@@ -168881,7 +169453,7 @@ var createDashboardServer = (props) => {
|
|
|
168881
169453
|
EventVersion: "1.0",
|
|
168882
169454
|
Sns: {
|
|
168883
169455
|
Type: "Notification",
|
|
168884
|
-
MessageId:
|
|
169456
|
+
MessageId: randomUUID9(),
|
|
168885
169457
|
TopicArn: `arn:aws:sns:${props.region}:000000000000:${topic}`,
|
|
168886
169458
|
Message: typeof message4 === "string" ? message4 : JSON.stringify(message4 ?? {}),
|
|
168887
169459
|
Timestamp: new Date().toISOString(),
|
|
@@ -169032,6 +169604,9 @@ var createDashboardServer = (props) => {
|
|
|
169032
169604
|
if (url.pathname === "/api/emails") {
|
|
169033
169605
|
return { status: 200, body: JSON.stringify({ emails: props.getEmails?.() ?? [] }) };
|
|
169034
169606
|
}
|
|
169607
|
+
if (url.pathname === "/api/alerts") {
|
|
169608
|
+
return { status: 200, body: JSON.stringify({ alerts: props.getAlerts?.() ?? [] }) };
|
|
169609
|
+
}
|
|
169035
169610
|
if (url.pathname.startsWith("/api/auth") && props.auth) {
|
|
169036
169611
|
const auth2 = props.auth;
|
|
169037
169612
|
try {
|
|
@@ -169145,13 +169720,13 @@ var createDashboardServer = (props) => {
|
|
|
169145
169720
|
// src/dev/failure.ts
|
|
169146
169721
|
import { stringify as stringify5 } from "@awsless/json";
|
|
169147
169722
|
import { formatRouteKey as formatRouteKey2, formatRoutePayload as formatRoutePayload2 } from "awsless";
|
|
169148
|
-
import { randomUUID as
|
|
169723
|
+
import { randomUUID as randomUUID10 } from "crypto";
|
|
169149
169724
|
var CONSUMER_ROUTE = formatRouteKey2("base", "on-failure", "consumer");
|
|
169150
169725
|
var createFailureReporter = (props) => {
|
|
169151
169726
|
const format4 = (report) => {
|
|
169152
169727
|
const error3 = report.error;
|
|
169153
169728
|
const base = {
|
|
169154
|
-
id:
|
|
169729
|
+
id: randomUUID10(),
|
|
169155
169730
|
date: new Date,
|
|
169156
169731
|
payload: report.event
|
|
169157
169732
|
};
|
|
@@ -169191,6 +169766,7 @@ var createFailureReporter = (props) => {
|
|
|
169191
169766
|
return (report) => {
|
|
169192
169767
|
const message4 = report.error instanceof Error ? report.error.message : String(report.error);
|
|
169193
169768
|
props.log(`${report.routeKey ?? report.queue?.name ?? "async invoke"} failed: ${message4}`);
|
|
169769
|
+
props.onReport?.(report);
|
|
169194
169770
|
if (!props.enabled) {
|
|
169195
169771
|
return;
|
|
169196
169772
|
}
|
|
@@ -169383,6 +169959,7 @@ var startDev = async (props) => {
|
|
|
169383
169959
|
const log = props.onLog ?? (() => {});
|
|
169384
169960
|
const phase = props.phase ?? (async ({ start }, fn) => (log(start), fn(() => {})));
|
|
169385
169961
|
const { appConfig, stackConfigs } = props;
|
|
169962
|
+
const startedAt = Date.now();
|
|
169386
169963
|
useDevBuildDir();
|
|
169387
169964
|
const { builders, appId, ready: ready2 } = createApp({
|
|
169388
169965
|
appConfig,
|
|
@@ -169400,6 +169977,9 @@ var startDev = async (props) => {
|
|
|
169400
169977
|
props.pool.begin();
|
|
169401
169978
|
await props.pool.keep("session", null, async () => ({ value: true, stop: () => {} }));
|
|
169402
169979
|
const dev = createDevContext({ appConfig, stackConfigs, appId, routerPorts, log, pool: props.pool });
|
|
169980
|
+
setDebugSink((type2, message4) => {
|
|
169981
|
+
dev.events.emit("debug", { date: Date.now(), line: message4, error: type2 === "error" });
|
|
169982
|
+
});
|
|
169403
169983
|
const bundleName = getBundleFunctionName(appConfig.name);
|
|
169404
169984
|
const buildDir = getBuildPath("bundle", bundleName, ".");
|
|
169405
169985
|
const { env: env4, lambda } = await phase({ start: "Preparing the local resources...", done: "Prepared the local resources" }, async (detail) => {
|
|
@@ -169511,12 +170091,14 @@ var startDev = async (props) => {
|
|
|
169511
170091
|
restartNeeded = true;
|
|
169512
170092
|
await worker.restart();
|
|
169513
170093
|
restartNeeded = false;
|
|
170094
|
+
dev.context.reportHealth("workers", "up", String(worker.size()));
|
|
169514
170095
|
log(`Reloaded the bundle in ${Date.now() - started}ms (build ${built - started}ms, worker ${Date.now() - built}ms)`);
|
|
169515
170096
|
} else if (!changed) {
|
|
169516
170097
|
debug(`Rebuild found no changes in ${Date.now() - started}ms`);
|
|
169517
170098
|
}
|
|
169518
170099
|
} catch (error3) {
|
|
169519
170100
|
dirty = true;
|
|
170101
|
+
dev.context.reportHealth("workers", "down", error3 instanceof Error ? error3.message : String(error3));
|
|
169520
170102
|
throw error3;
|
|
169521
170103
|
} finally {
|
|
169522
170104
|
fresh = undefined;
|
|
@@ -169524,14 +170106,62 @@ var startDev = async (props) => {
|
|
|
169524
170106
|
})();
|
|
169525
170107
|
await fresh;
|
|
169526
170108
|
};
|
|
170109
|
+
const describeDispatch = (event) => {
|
|
170110
|
+
const payload = event;
|
|
170111
|
+
const route = payload?.["$awsless-route"];
|
|
170112
|
+
if (typeof route === "string") {
|
|
170113
|
+
return route;
|
|
170114
|
+
}
|
|
170115
|
+
const record = payload?.Records?.[0];
|
|
170116
|
+
if (record?.eventSource === "aws:sqs") {
|
|
170117
|
+
return "queue " + String(record.eventSourceARN ?? "").split(":").at(-1);
|
|
170118
|
+
}
|
|
170119
|
+
if (record?.EventSource === "aws:sns") {
|
|
170120
|
+
return "topic " + String(record.Sns?.TopicArn ?? "").split(":").at(-1);
|
|
170121
|
+
}
|
|
170122
|
+
if (record?.eventSource === "aws:s3") {
|
|
170123
|
+
return "store " + String(record.s3?.bucket?.name ?? "");
|
|
170124
|
+
}
|
|
170125
|
+
if (String(record?.eventSourceARN ?? "").includes(":dynamodb:")) {
|
|
170126
|
+
return "stream " + (String(record.eventSourceARN).split("table/")[1]?.split("/")[0] ?? "table");
|
|
170127
|
+
}
|
|
170128
|
+
const header = payload?.headers?.[ROUTE_HEADER];
|
|
170129
|
+
if (typeof header === "string") {
|
|
170130
|
+
return header;
|
|
170131
|
+
}
|
|
170132
|
+
return "invoke";
|
|
170133
|
+
};
|
|
169527
170134
|
const dispatch = async (event) => {
|
|
169528
170135
|
await ensureFresh();
|
|
169529
|
-
|
|
170136
|
+
const started = Date.now();
|
|
170137
|
+
const route = describeDispatch(event);
|
|
170138
|
+
try {
|
|
170139
|
+
const result = await worker.dispatch(event);
|
|
170140
|
+
dev.events.emit("activity", { date: started, route, ms: Date.now() - started, ok: true });
|
|
170141
|
+
return result;
|
|
170142
|
+
} catch (error3) {
|
|
170143
|
+
dev.events.emit("activity", {
|
|
170144
|
+
date: started,
|
|
170145
|
+
route,
|
|
170146
|
+
ms: Date.now() - started,
|
|
170147
|
+
ok: false,
|
|
170148
|
+
error: error3 instanceof Error ? error3.message : String(error3)
|
|
170149
|
+
});
|
|
170150
|
+
throw error3;
|
|
170151
|
+
}
|
|
169530
170152
|
};
|
|
169531
170153
|
const reportFailure = createFailureReporter({
|
|
169532
170154
|
enabled: Boolean(appConfig.onFailure),
|
|
169533
170155
|
dispatch,
|
|
169534
|
-
log
|
|
170156
|
+
log,
|
|
170157
|
+
onReport(report) {
|
|
170158
|
+
dev.events.emit("problems", {
|
|
170159
|
+
date: Date.now(),
|
|
170160
|
+
kind: report.kind,
|
|
170161
|
+
title: report.routeKey ?? report.queue?.name ?? "async invoke",
|
|
170162
|
+
detail: report.error instanceof Error ? report.error.message : String(report.error)
|
|
170163
|
+
});
|
|
170164
|
+
}
|
|
169535
170165
|
});
|
|
169536
170166
|
lambda.connect(dispatch, reportFailure);
|
|
169537
170167
|
await phase({ start: "Starting the local servers...", done: "Started the local servers" }, async (detail) => {
|
|
@@ -169546,9 +170176,11 @@ var startDev = async (props) => {
|
|
|
169546
170176
|
await phase({ start: "Starting the bundle worker...", done: "Started the bundle worker" }, async (detail) => {
|
|
169547
170177
|
try {
|
|
169548
170178
|
await worker.start();
|
|
170179
|
+
dev.context.reportHealth("workers", "up", String(worker.size()));
|
|
169549
170180
|
} catch (error3) {
|
|
169550
170181
|
detail("FAILED - the next invoke retries");
|
|
169551
170182
|
log(`The bundle worker failed to start: ${error3 instanceof Error ? error3.message : String(error3)}`);
|
|
170183
|
+
dev.context.reportHealth("workers", "down", error3 instanceof Error ? error3.message : String(error3));
|
|
169552
170184
|
dirty = true;
|
|
169553
170185
|
restartNeeded = true;
|
|
169554
170186
|
}
|
|
@@ -169583,6 +170215,12 @@ var startDev = async (props) => {
|
|
|
169583
170215
|
process.stderr.write(`Route ${routeKey} failed: ${detail}
|
|
169584
170216
|
`);
|
|
169585
170217
|
emitWorkerLine(`Route ${routeKey} failed: ${detail}`, true, routeKey);
|
|
170218
|
+
dev.events.emit("problems", {
|
|
170219
|
+
date: Date.now(),
|
|
170220
|
+
kind: "route",
|
|
170221
|
+
title: routeKey,
|
|
170222
|
+
detail: error3 instanceof Error ? error3.message : String(error3)
|
|
170223
|
+
});
|
|
169586
170224
|
}
|
|
169587
170225
|
}));
|
|
169588
170226
|
}
|
|
@@ -169601,6 +170239,9 @@ var startDev = async (props) => {
|
|
|
169601
170239
|
storeRoot: join57(directories.output, "local", "store"),
|
|
169602
170240
|
configFile: join57(directories.output, "local", "config.json"),
|
|
169603
170241
|
getEmails: () => props.pool.peek("shim:ses-email")?.server.list() ?? [],
|
|
170242
|
+
getAlerts: () => props.pool.peek("shim:sns")?.alerts ?? [],
|
|
170243
|
+
getSession: () => ({ startedAt, workers: worker.size() }),
|
|
170244
|
+
getHealth: () => [...dev.health.values()],
|
|
169604
170245
|
configPulled: Object.keys(props.pool.peek("config:pull") ?? {}),
|
|
169605
170246
|
auth: createAuthAdmin({
|
|
169606
170247
|
appConfig,
|
|
@@ -169630,9 +170271,13 @@ var startDev = async (props) => {
|
|
|
169630
170271
|
if (stopping) {
|
|
169631
170272
|
return;
|
|
169632
170273
|
}
|
|
169633
|
-
worker.restart().then(() =>
|
|
170274
|
+
worker.restart().then(() => {
|
|
170275
|
+
dev.context.reportHealth("workers", "up", String(worker.size()));
|
|
170276
|
+
log("Restarted the bundle worker.");
|
|
170277
|
+
}).catch((error3) => {
|
|
169634
170278
|
restartNeeded = true;
|
|
169635
170279
|
dirty = true;
|
|
170280
|
+
dev.context.reportHealth("workers", "down", error3 instanceof Error ? error3.message : String(error3));
|
|
169636
170281
|
log(`The bundle worker failed to restart: ${error3 instanceof Error ? error3.message : String(error3)}`);
|
|
169637
170282
|
});
|
|
169638
170283
|
});
|
|
@@ -177005,7 +177650,7 @@ ${job.error.stack.split(`
|
|
|
177005
177650
|
stream2.shift();
|
|
177006
177651
|
} else if (stream2.length > 0) {
|
|
177007
177652
|
this._BOMseen = true;
|
|
177008
|
-
}
|
|
177653
|
+
} else {}
|
|
177009
177654
|
}
|
|
177010
177655
|
return codePointsToString(stream2);
|
|
177011
177656
|
}
|
|
@@ -185685,7 +186330,7 @@ var formatLog = (level, date2, origin, message4) => {
|
|
|
185685
186330
|
import { DeleteObjectsCommand, ListObjectsV2Command, S3Client as S3Client5 } from "@aws-sdk/client-s3";
|
|
185686
186331
|
|
|
185687
186332
|
// src/formation/cloudfront.ts
|
|
185688
|
-
import { randomUUID as
|
|
186333
|
+
import { randomUUID as randomUUID11 } from "crypto";
|
|
185689
186334
|
var createInvalidationForDistributionTenants = async (client, props) => {
|
|
185690
186335
|
let cursor;
|
|
185691
186336
|
do {
|
|
@@ -185705,7 +186350,7 @@ var createInvalidationForDistributionTenants = async (client, props) => {
|
|
|
185705
186350
|
Quantity: props.paths.length,
|
|
185706
186351
|
Items: props.paths
|
|
185707
186352
|
},
|
|
185708
|
-
CallerReference:
|
|
186353
|
+
CallerReference: randomUUID11()
|
|
185709
186354
|
}
|
|
185710
186355
|
}));
|
|
185711
186356
|
}
|