@awsless/cli 0.1.7 → 0.1.8
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/app.json +1 -1
- package/dist/app.stage.json +1 -1
- package/dist/bin.js +790 -182
- package/dist/handlers/icon.js +1 -15
- package/dist/handlers/pubsub-publisher.js +24 -38
- 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) => {
|
|
@@ -108402,7 +108408,6 @@ import { join, normalize, relative } from "path";
|
|
|
108402
108408
|
var root = process.cwd();
|
|
108403
108409
|
var directories = {
|
|
108404
108410
|
root,
|
|
108405
|
-
buildFolder: "build",
|
|
108406
108411
|
get output() {
|
|
108407
108412
|
return join(this.root, ".awsless");
|
|
108408
108413
|
},
|
|
@@ -108413,7 +108418,7 @@ var directories = {
|
|
|
108413
108418
|
return join(this.output, "state");
|
|
108414
108419
|
},
|
|
108415
108420
|
get build() {
|
|
108416
|
-
return join(this.output,
|
|
108421
|
+
return join(this.output, "build");
|
|
108417
108422
|
},
|
|
108418
108423
|
get types() {
|
|
108419
108424
|
return join(this.output, "types");
|
|
@@ -108428,9 +108433,6 @@ var directories = {
|
|
|
108428
108433
|
var setRoot = (path = root) => {
|
|
108429
108434
|
directories.root = path;
|
|
108430
108435
|
};
|
|
108431
|
-
var useDevBuildDir = () => {
|
|
108432
|
-
directories.buildFolder = "build-dev";
|
|
108433
|
-
};
|
|
108434
108436
|
var findRootDir = async (path, configFiles, level = 5) => {
|
|
108435
108437
|
if (!level) {
|
|
108436
108438
|
throw new TypeError("No awsless project found");
|
|
@@ -108467,6 +108469,10 @@ var clearDebugLog = () => {
|
|
|
108467
108469
|
ready = true;
|
|
108468
108470
|
} catch (_) {}
|
|
108469
108471
|
};
|
|
108472
|
+
var sink;
|
|
108473
|
+
var setDebugSink = (listener) => {
|
|
108474
|
+
sink = listener;
|
|
108475
|
+
};
|
|
108470
108476
|
var write = (type, message) => {
|
|
108471
108477
|
try {
|
|
108472
108478
|
if (!ready) {
|
|
@@ -108474,6 +108480,7 @@ var write = (type, message) => {
|
|
|
108474
108480
|
}
|
|
108475
108481
|
appendFileSync(debugLogFile, `${new Date().toISOString()} [${type}] ${message}
|
|
108476
108482
|
`);
|
|
108483
|
+
sink?.(type, message);
|
|
108477
108484
|
} catch (_) {}
|
|
108478
108485
|
};
|
|
108479
108486
|
var format = (parts) => {
|
|
@@ -114483,7 +114490,7 @@ var getSanitizedDevTypeScriptVersion = (version2 = "") => {
|
|
|
114483
114490
|
};
|
|
114484
114491
|
|
|
114485
114492
|
// ../../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/
|
|
114493
|
+
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
114494
|
var tscVersion;
|
|
114488
114495
|
var TS_PACKAGE_JSON = join7("node_modules", "typescript", "package.json");
|
|
114489
114496
|
var getTypeScriptUserAgentPair = async () => {
|
|
@@ -131560,17 +131567,6 @@ var $forEachNodeInTopologicalOrder = sort.forEachNodeInTopologicalOrder;
|
|
|
131560
131567
|
var $topologicalSort = sort.topologicalSort;
|
|
131561
131568
|
var $topologicalGenerations = sort.topologicalGenerations;
|
|
131562
131569
|
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
131570
|
|
|
131575
131571
|
// ../../node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm/regex.js
|
|
131576
131572
|
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 +131632,18 @@ function v35(version2, hash, value, namespace, buf, offset) {
|
|
|
131636
131632
|
return unsafeStringify(bytes);
|
|
131637
131633
|
}
|
|
131638
131634
|
|
|
131635
|
+
// ../../node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm/sha1.js
|
|
131636
|
+
import { createHash as createHash3 } from "crypto";
|
|
131637
|
+
function sha1(bytes) {
|
|
131638
|
+
if (Array.isArray(bytes)) {
|
|
131639
|
+
bytes = Buffer.from(bytes);
|
|
131640
|
+
} else if (typeof bytes === "string") {
|
|
131641
|
+
bytes = Buffer.from(bytes, "utf8");
|
|
131642
|
+
}
|
|
131643
|
+
return createHash3("sha1").update(bytes).digest();
|
|
131644
|
+
}
|
|
131645
|
+
var sha1_default = sha1;
|
|
131646
|
+
|
|
131639
131647
|
// ../../node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm/v5.js
|
|
131640
131648
|
function v5(value, namespace, buf, offset) {
|
|
131641
131649
|
return v35(80, sha1_default, value, namespace, buf, offset);
|
|
@@ -132327,13 +132335,13 @@ var consoleSink = (group4, ...args) => {
|
|
|
132327
132335
|
console.log(`${group4}:`, ...args);
|
|
132328
132336
|
console.log();
|
|
132329
132337
|
};
|
|
132330
|
-
var
|
|
132338
|
+
var sink2;
|
|
132331
132339
|
var enableDebug = (customSink) => {
|
|
132332
|
-
|
|
132340
|
+
sink2 = customSink ?? consoleSink;
|
|
132333
132341
|
};
|
|
132334
132342
|
var createDebugger = (group4) => {
|
|
132335
132343
|
return (...args) => {
|
|
132336
|
-
|
|
132344
|
+
sink2?.(group4, ...args);
|
|
132337
132345
|
};
|
|
132338
132346
|
};
|
|
132339
132347
|
var AlreadyLockedError = class extends Error {
|
|
@@ -141101,6 +141109,8 @@ if (!nativeAccelerationDisabled) {
|
|
|
141101
141109
|
try {
|
|
141102
141110
|
if (true)
|
|
141103
141111
|
extractor = require_msgpackr_extract();
|
|
141112
|
+
else
|
|
141113
|
+
;
|
|
141104
141114
|
if (extractor)
|
|
141105
141115
|
setExtractor(extractor.extractStrings);
|
|
141106
141116
|
} catch (error3) {}
|
|
@@ -143961,14 +143971,6 @@ var createOpenSearchProvider = ({ credentials: credentials2, region }) => {
|
|
|
143961
143971
|
async updateResource(props) {
|
|
143962
143972
|
return apply(props.proposedState);
|
|
143963
143973
|
},
|
|
143964
|
-
async planResourceChange(props) {
|
|
143965
|
-
const prior = props.priorState;
|
|
143966
|
-
const proposed = props.proposedState;
|
|
143967
|
-
return {
|
|
143968
|
-
state: props.proposedState,
|
|
143969
|
-
requiresReplacement: !!prior && (prior.endpoint !== proposed?.endpoint || prior.index !== proposed?.index)
|
|
143970
|
-
};
|
|
143971
|
-
},
|
|
143972
143974
|
async deleteResource(props) {
|
|
143973
143975
|
const state = inputSchema.parse(props.state);
|
|
143974
143976
|
await getClient(state.endpoint).indices.delete({ index: state.index }, { ignore: [404] });
|
|
@@ -151138,7 +151140,7 @@ var JobDefaultSchema = exports_external.object({
|
|
|
151138
151140
|
|
|
151139
151141
|
// src/feature/search/schema.ts
|
|
151140
151142
|
var VersionSchema = exports_external.union([
|
|
151141
|
-
exports_external.enum(["
|
|
151143
|
+
exports_external.enum(["2.13", "2.11", "2.9", "2.7", "2.5", "2.3", "1.3"]),
|
|
151142
151144
|
exports_external.string()
|
|
151143
151145
|
]).describe("Specify the OpenSearch engine version.");
|
|
151144
151146
|
var TypeSchema = exports_external.union([
|
|
@@ -151180,7 +151182,7 @@ var StorageSizeSchema = SizeSchema.refine(sizeMin(gibibytes(10)), "Minimum stora
|
|
|
151180
151182
|
var SearchDefaultSchema = exports_external.object({
|
|
151181
151183
|
type: TypeSchema.default("t3.small"),
|
|
151182
151184
|
count: CountSchema.default(1),
|
|
151183
|
-
version: VersionSchema.default("
|
|
151185
|
+
version: VersionSchema.default("2.13"),
|
|
151184
151186
|
storage: StorageSizeSchema.default("10 GB")
|
|
151185
151187
|
}).strict().default({}).describe("Configure the shared OpenSearch domain that backs every search index in your app.");
|
|
151186
151188
|
var IndexNameSchema = exports_external.string().regex(/^[a-z0-9][a-z0-9\-_.]*$/, 'Index names must be lowercase & start with a letter or number, like "users" or "game-events".');
|
|
@@ -154054,6 +154056,7 @@ var __export3 = (target2, all5) => {
|
|
|
154054
154056
|
var RedisServer = class {
|
|
154055
154057
|
client;
|
|
154056
154058
|
process;
|
|
154059
|
+
stopping = false;
|
|
154057
154060
|
async start(port, version2 = "7.2.4", args = []) {
|
|
154058
154061
|
if (this.process) {
|
|
154059
154062
|
throw new Error(`Redis server is already listening on port: ${await this.process.getPort()}`);
|
|
@@ -154061,6 +154064,7 @@ var RedisServer = class {
|
|
|
154061
154064
|
if (port && (port < 0 || port >= 65536)) {
|
|
154062
154065
|
throw new RangeError(`Port should be >= 0 and < 65536. Received ${port}.`);
|
|
154063
154066
|
}
|
|
154067
|
+
this.stopping = false;
|
|
154064
154068
|
this.process = await import_redis_memory_server.RedisMemoryServer.create({
|
|
154065
154069
|
instance: {
|
|
154066
154070
|
port,
|
|
@@ -154069,8 +154073,30 @@ var RedisServer = class {
|
|
|
154069
154073
|
binary: { version: version2 }
|
|
154070
154074
|
});
|
|
154071
154075
|
}
|
|
154076
|
+
onExit(handler) {
|
|
154077
|
+
const child = this.process?.instanceInfoSync?.childProcess;
|
|
154078
|
+
child?.once("exit", (code, signal) => {
|
|
154079
|
+
if (!this.stopping) {
|
|
154080
|
+
handler(code, signal);
|
|
154081
|
+
}
|
|
154082
|
+
});
|
|
154083
|
+
}
|
|
154084
|
+
onOutput(handler) {
|
|
154085
|
+
const child = this.process?.instanceInfoSync?.childProcess;
|
|
154086
|
+
const capture = (chunk3) => {
|
|
154087
|
+
for (const line of chunk3.toString().split(`
|
|
154088
|
+
`)) {
|
|
154089
|
+
if (line.trim() !== "") {
|
|
154090
|
+
handler(line);
|
|
154091
|
+
}
|
|
154092
|
+
}
|
|
154093
|
+
};
|
|
154094
|
+
child?.stdout?.on("data", capture);
|
|
154095
|
+
child?.stderr?.on("data", capture);
|
|
154096
|
+
}
|
|
154072
154097
|
async kill() {
|
|
154073
154098
|
if (this.process) {
|
|
154099
|
+
this.stopping = true;
|
|
154074
154100
|
await this.client?.disconnect();
|
|
154075
154101
|
await this.process.stop();
|
|
154076
154102
|
this.process = undefined;
|
|
@@ -154852,12 +154878,31 @@ var cacheOnDev = async (ctx) => {
|
|
|
154852
154878
|
return;
|
|
154853
154879
|
}
|
|
154854
154880
|
for (const { stackName, id } of caches) {
|
|
154855
|
-
const port = await ctx.keep(`cache:${stackName}:${id}`, null, async () => {
|
|
154881
|
+
const { port, sink: sink3 } = await ctx.keep(`cache:${stackName}:${id}`, null, async () => {
|
|
154856
154882
|
const server = new RedisServer;
|
|
154857
154883
|
await server.start();
|
|
154858
154884
|
await server.ping();
|
|
154859
|
-
|
|
154885
|
+
const sink4 = { tail: [] };
|
|
154886
|
+
server.onExit((code, signal) => {
|
|
154887
|
+
sink4.crashed = code !== null ? `exited with code ${code}` : `killed by ${signal}`;
|
|
154888
|
+
sink4.health?.("down", sink4.crashed);
|
|
154889
|
+
});
|
|
154890
|
+
server.onOutput((line) => {
|
|
154891
|
+
sink4.tail.push(line);
|
|
154892
|
+
while (sink4.tail.length > 20) {
|
|
154893
|
+
sink4.tail.shift();
|
|
154894
|
+
}
|
|
154895
|
+
sink4.log?.(line);
|
|
154896
|
+
});
|
|
154897
|
+
return { value: { port: await server.getPort(), sink: sink4 }, stop: () => server.kill() };
|
|
154860
154898
|
});
|
|
154899
|
+
const channel = `cache:${stackName}:${id}`;
|
|
154900
|
+
sink3.health = (status2, detail) => ctx.reportHealth(`cache ${stackName}/${id}`, status2, detail);
|
|
154901
|
+
sink3.health(sink3.crashed ? "down" : "up", sink3.crashed);
|
|
154902
|
+
sink3.log = (line) => ctx.emitEvent(channel, { date: Date.now(), line });
|
|
154903
|
+
for (const line of sink3.tail) {
|
|
154904
|
+
ctx.emitEvent(channel, { date: Date.now(), line });
|
|
154905
|
+
}
|
|
154861
154906
|
const prefix = `CACHE_${constantCase(stackName)}_${constantCase(id)}`;
|
|
154862
154907
|
ctx.addEnv(`${prefix}_HOST`, "localhost");
|
|
154863
154908
|
ctx.addEnv(`${prefix}_PORT`, String(port));
|
|
@@ -154867,7 +154912,8 @@ var cacheOnDev = async (ctx) => {
|
|
|
154867
154912
|
kind: "cache",
|
|
154868
154913
|
stack: stackName,
|
|
154869
154914
|
id,
|
|
154870
|
-
detail: `localhost:${port}
|
|
154915
|
+
detail: `localhost:${port}`,
|
|
154916
|
+
channel
|
|
154871
154917
|
});
|
|
154872
154918
|
}
|
|
154873
154919
|
};
|
|
@@ -155655,8 +155701,7 @@ var createDnsValidatedCertificate = (group4, id, props) => {
|
|
|
155655
155701
|
}, {
|
|
155656
155702
|
...props.dependsOn ? { dependsOn: props.dependsOn } : {},
|
|
155657
155703
|
...props.provider ? { provider: props.provider } : {},
|
|
155658
|
-
replaceOnChanges: ["certificateArn", "validationRecordFqdns"]
|
|
155659
|
-
createBeforeReplace: true
|
|
155704
|
+
replaceOnChanges: ["certificateArn", "validationRecordFqdns"]
|
|
155660
155705
|
});
|
|
155661
155706
|
return validation;
|
|
155662
155707
|
};
|
|
@@ -157300,13 +157345,18 @@ var parseQueryPublish = (body) => {
|
|
|
157300
157345
|
MessageAttributes: attributes
|
|
157301
157346
|
};
|
|
157302
157347
|
};
|
|
157303
|
-
var createSnsServer = () => {
|
|
157348
|
+
var createSnsServer = (props) => {
|
|
157304
157349
|
let server;
|
|
157305
157350
|
let closeServer;
|
|
157306
157351
|
let dispatch;
|
|
157307
157352
|
let reportFailure;
|
|
157308
157353
|
const publish2 = (input) => {
|
|
157309
157354
|
const messageId = randomUUID4();
|
|
157355
|
+
for (const capture of props?.captures ?? []) {
|
|
157356
|
+
if (capture(input)) {
|
|
157357
|
+
return messageId;
|
|
157358
|
+
}
|
|
157359
|
+
}
|
|
157310
157360
|
const attributes = {};
|
|
157311
157361
|
for (const [name, attribute] of Object.entries(input.MessageAttributes ?? {})) {
|
|
157312
157362
|
attributes[name] = {
|
|
@@ -157414,22 +157464,29 @@ var pubsubOnDev = async (ctx) => {
|
|
|
157414
157464
|
declared.add(event);
|
|
157415
157465
|
}
|
|
157416
157466
|
}
|
|
157417
|
-
const { redisPort, sns, snsPort, wsPort } = await ctx.keep(`pubsub-core:${id}`, null, async () => {
|
|
157467
|
+
const { redisPort, sns, snsPort, wsPort, redisSink } = await ctx.keep(`pubsub-core:${id}`, null, async () => {
|
|
157418
157468
|
const redis = new RedisServer;
|
|
157419
157469
|
await redis.start();
|
|
157420
157470
|
await redis.ping();
|
|
157471
|
+
const redisSink2 = {};
|
|
157472
|
+
redis.onExit((code, signal) => {
|
|
157473
|
+
redisSink2.crashed = code !== null ? `exited with code ${code}` : `killed by ${signal}`;
|
|
157474
|
+
redisSink2.health?.("down", redisSink2.crashed);
|
|
157475
|
+
});
|
|
157421
157476
|
const redisPort2 = await redis.getPort();
|
|
157422
157477
|
const sns2 = createSnsServer();
|
|
157423
157478
|
const snsPort2 = await sns2.listen();
|
|
157424
157479
|
const wsPort2 = await findFreePort();
|
|
157425
157480
|
return {
|
|
157426
|
-
value: { redisPort: redisPort2, sns: sns2, snsPort: snsPort2, wsPort: wsPort2 },
|
|
157481
|
+
value: { redisPort: redisPort2, sns: sns2, snsPort: snsPort2, wsPort: wsPort2, redisSink: redisSink2 },
|
|
157427
157482
|
stop: async () => {
|
|
157428
157483
|
await sns2.stop();
|
|
157429
157484
|
await redis.kill();
|
|
157430
157485
|
}
|
|
157431
157486
|
};
|
|
157432
157487
|
});
|
|
157488
|
+
redisSink.health = (status2, detail) => ctx.reportHealth(`pubsub ${id} redis`, status2, detail);
|
|
157489
|
+
redisSink.health(redisSink.crashed ? "down" : "up", redisSink.crashed);
|
|
157433
157490
|
ctx.retain(`pubsub-ws:${id}`);
|
|
157434
157491
|
const channel = `pubsub:${id}`;
|
|
157435
157492
|
const publisherRoute = formatRouteKey("base", "pubsub", `${id}-publisher`);
|
|
@@ -157511,7 +157568,10 @@ var pubsubOnDev = async (ctx) => {
|
|
|
157511
157568
|
}
|
|
157512
157569
|
return dispatch(event);
|
|
157513
157570
|
}, reportFailure);
|
|
157514
|
-
await ctx.keep(`pubsub-ws:${id}`, { wsPort, redisPort, snsPort }, async () => {
|
|
157571
|
+
const ws = await ctx.keep(`pubsub-ws:${id}`, { wsPort, redisPort, snsPort }, async () => {
|
|
157572
|
+
const sink3 = {
|
|
157573
|
+
stopping: false
|
|
157574
|
+
};
|
|
157515
157575
|
const runtime = join24(dirname12(fileURLToPath8(import.meta.url)), "handlers", "pubsub-server.js");
|
|
157516
157576
|
const child = spawn2(process.execPath, [runtime], {
|
|
157517
157577
|
stdio: ["ignore", "ignore", "pipe"],
|
|
@@ -157536,9 +157596,23 @@ var pubsubOnDev = async (ctx) => {
|
|
|
157536
157596
|
}
|
|
157537
157597
|
});
|
|
157538
157598
|
child.stderr?.on("data", (chunk3) => process.stderr.write(chunk3));
|
|
157599
|
+
child.on("exit", (code, signal) => {
|
|
157600
|
+
if (!sink3.stopping) {
|
|
157601
|
+
sink3.health?.("down", code !== null ? `exited with code ${code}` : `killed by ${signal}`);
|
|
157602
|
+
}
|
|
157603
|
+
});
|
|
157539
157604
|
await waitForHealth(wsPort, 30000);
|
|
157540
|
-
return {
|
|
157605
|
+
return {
|
|
157606
|
+
value: { child, sink: sink3 },
|
|
157607
|
+
stop: async () => {
|
|
157608
|
+
sink3.stopping = true;
|
|
157609
|
+
await stopChild(child);
|
|
157610
|
+
}
|
|
157611
|
+
};
|
|
157541
157612
|
});
|
|
157613
|
+
ws.sink.health = (status2, detail) => ctx.reportHealth(`pubsub ${id}`, status2, detail);
|
|
157614
|
+
ws.sink.stopping = false;
|
|
157615
|
+
ws.sink.health(ws.child.exitCode === null ? "up" : "down");
|
|
157542
157616
|
},
|
|
157543
157617
|
async stop() {
|
|
157544
157618
|
feed?.disconnect();
|
|
@@ -158756,19 +158830,37 @@ var searchOnDev = async (ctx) => {
|
|
|
158756
158830
|
if (indexes.length === 0) {
|
|
158757
158831
|
return;
|
|
158758
158832
|
}
|
|
158759
|
-
const { port } = await ctx.keep("opensearch", null, async () => {
|
|
158833
|
+
const { port, sink: sink3 } = await ctx.keep("opensearch", null, async () => {
|
|
158760
158834
|
const port2 = await findFreePort();
|
|
158761
158835
|
const path6 = await download(VERSION_3_5_0_MIN);
|
|
158836
|
+
const sink4 = { tail: [] };
|
|
158762
158837
|
const kill = await launch({
|
|
158763
158838
|
path: path6,
|
|
158764
158839
|
port: port2,
|
|
158765
158840
|
host: "localhost",
|
|
158766
158841
|
version: VERSION_3_5_0_MIN,
|
|
158767
|
-
debug: false
|
|
158842
|
+
debug: false,
|
|
158843
|
+
onExit(code, signal) {
|
|
158844
|
+
sink4.crashed = code !== null ? `exited with code ${code}` : `killed by ${signal}`;
|
|
158845
|
+
sink4.health?.("down", sink4.crashed);
|
|
158846
|
+
},
|
|
158847
|
+
onOutput(line) {
|
|
158848
|
+
sink4.tail.push(line);
|
|
158849
|
+
while (sink4.tail.length > 20) {
|
|
158850
|
+
sink4.tail.shift();
|
|
158851
|
+
}
|
|
158852
|
+
sink4.log?.(line);
|
|
158853
|
+
}
|
|
158768
158854
|
});
|
|
158769
158855
|
await waitForSearch(port2, 60000);
|
|
158770
|
-
return { value: { port: port2 }, stop: kill };
|
|
158856
|
+
return { value: { port: port2, sink: sink4 }, stop: kill };
|
|
158771
158857
|
});
|
|
158858
|
+
sink3.health = (status2, detail) => ctx.reportHealth("search", status2, detail);
|
|
158859
|
+
sink3.health(sink3.crashed ? "down" : "up", sink3.crashed);
|
|
158860
|
+
sink3.log = (line) => ctx.emitEvent("search", { date: Date.now(), line });
|
|
158861
|
+
for (const line of sink3.tail) {
|
|
158862
|
+
ctx.emitEvent("search", { date: Date.now(), line });
|
|
158863
|
+
}
|
|
158772
158864
|
ctx.addEnv("SEARCH_DOMAIN", `localhost:${port}`);
|
|
158773
158865
|
const client = new Client5({ node: `http://localhost:${port}` });
|
|
158774
158866
|
for (const { stackName, id, props } of indexes) {
|
|
@@ -158781,7 +158873,8 @@ var searchOnDev = async (ctx) => {
|
|
|
158781
158873
|
kind: "search",
|
|
158782
158874
|
stack: stackName,
|
|
158783
158875
|
id,
|
|
158784
|
-
detail: `localhost:${port}
|
|
158876
|
+
detail: `localhost:${port}`,
|
|
158877
|
+
channel: "search"
|
|
158785
158878
|
});
|
|
158786
158879
|
}
|
|
158787
158880
|
};
|
|
@@ -158870,8 +158963,7 @@ var searchFeature = defineFeature({
|
|
|
158870
158963
|
})
|
|
158871
158964
|
}, {
|
|
158872
158965
|
retainOnDelete: ctx.appConfig.removal === "retain",
|
|
158873
|
-
import: ctx.import ? name : undefined
|
|
158874
|
-
replaceOnChanges: ["engineVersion", "domainName"]
|
|
158966
|
+
import: ctx.import ? name : undefined
|
|
158875
158967
|
});
|
|
158876
158968
|
ctx.addEnv("SEARCH_DOMAIN", openSearch.endpointV2);
|
|
158877
158969
|
ctx.addPermission({
|
|
@@ -158885,8 +158977,7 @@ var searchFeature = defineFeature({
|
|
|
158885
158977
|
mappings: JSON.stringify(resolveSearchMappings(indexProps) ?? {}),
|
|
158886
158978
|
settings: JSON.stringify(indexProps.settings ?? {})
|
|
158887
158979
|
}, {
|
|
158888
|
-
retainOnDelete: ctx.appConfig.removal === "retain"
|
|
158889
|
-
replaceOnChanges: ["endpoint", "index"]
|
|
158980
|
+
retainOnDelete: ctx.appConfig.removal === "retain"
|
|
158890
158981
|
});
|
|
158891
158982
|
}
|
|
158892
158983
|
}
|
|
@@ -159014,7 +159105,7 @@ var siteOnDev = async (ctx) => {
|
|
|
159014
159105
|
const value = await ctx.keep(key, { command: command3, port, env: env4 }, async () => {
|
|
159015
159106
|
const [bin, ...args] = command3.split(" ");
|
|
159016
159107
|
const cwd2 = join33(directories.root, dirname16(stackConfig.file));
|
|
159017
|
-
const
|
|
159108
|
+
const sink3 = {
|
|
159018
159109
|
emit: () => {},
|
|
159019
159110
|
stopping: false
|
|
159020
159111
|
};
|
|
@@ -159032,7 +159123,7 @@ var siteOnDev = async (ctx) => {
|
|
|
159032
159123
|
continue;
|
|
159033
159124
|
}
|
|
159034
159125
|
tail.push(line);
|
|
159035
|
-
|
|
159126
|
+
sink3.emit({ date: Date.now(), line });
|
|
159036
159127
|
}
|
|
159037
159128
|
while (tail.length > 20) {
|
|
159038
159129
|
tail.shift();
|
|
@@ -159040,24 +159131,30 @@ var siteOnDev = async (ctx) => {
|
|
|
159040
159131
|
};
|
|
159041
159132
|
child.stdout?.on("data", capture);
|
|
159042
159133
|
child.stderr?.on("data", capture);
|
|
159043
|
-
child.on("exit", (code) => {
|
|
159044
|
-
if (
|
|
159134
|
+
child.on("exit", (code, signal) => {
|
|
159135
|
+
if (sink3.stopping) {
|
|
159136
|
+
return;
|
|
159137
|
+
}
|
|
159138
|
+
if (code !== null && code !== 0) {
|
|
159045
159139
|
logs_exports.error(`The site "${id}" dev server exited with code ${code}:
|
|
159046
159140
|
${tail.join(`
|
|
159047
159141
|
`)}`);
|
|
159048
|
-
|
|
159142
|
+
sink3.emit({ date: Date.now(), line: `Exited with code ${code}` });
|
|
159049
159143
|
}
|
|
159144
|
+
sink3.health?.("down", code !== null ? `exited with code ${code}` : `killed by ${signal}`);
|
|
159050
159145
|
});
|
|
159051
159146
|
return {
|
|
159052
|
-
value: { port, tail, sink:
|
|
159147
|
+
value: { port, tail, sink: sink3, child },
|
|
159053
159148
|
stop: async () => {
|
|
159054
|
-
|
|
159149
|
+
sink3.stopping = true;
|
|
159055
159150
|
await stopChild(child);
|
|
159056
159151
|
}
|
|
159057
159152
|
};
|
|
159058
159153
|
});
|
|
159059
159154
|
value.sink.emit = (data) => ctx.emitEvent(channel, data);
|
|
159155
|
+
value.sink.health = (status2, detail) => ctx.reportHealth(`site ${id}`, status2, detail);
|
|
159060
159156
|
value.sink.stopping = false;
|
|
159157
|
+
value.sink.health(value.child.exitCode === null ? "up" : "down");
|
|
159061
159158
|
for (const line of value.tail) {
|
|
159062
159159
|
ctx.emitEvent(channel, { date: Date.now(), line });
|
|
159063
159160
|
}
|
|
@@ -160173,18 +160270,7 @@ var topicFeature = defineFeature({
|
|
|
160173
160270
|
});
|
|
160174
160271
|
}
|
|
160175
160272
|
}
|
|
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
|
-
});
|
|
160273
|
+
await ctx.useSns();
|
|
160188
160274
|
},
|
|
160189
160275
|
async onTypeGen(ctx) {
|
|
160190
160276
|
const gen = new TypeFile("awsless");
|
|
@@ -160382,6 +160468,7 @@ var vpcFeature = defineFeature({
|
|
|
160382
160468
|
});
|
|
160383
160469
|
|
|
160384
160470
|
// src/feature/alert/index.ts
|
|
160471
|
+
import { randomUUID as randomUUID7 } from "crypto";
|
|
160385
160472
|
var typeGenCode10 = `
|
|
160386
160473
|
import type { PublishOptions } from '@awsless/sns'
|
|
160387
160474
|
import type { Mock } from 'vitest'
|
|
@@ -160400,6 +160487,44 @@ type TestMockEntry = MockBuilder & Mock<(payload: unknown) => unknown>
|
|
|
160400
160487
|
`;
|
|
160401
160488
|
var alertFeature = defineFeature({
|
|
160402
160489
|
name: "alert",
|
|
160490
|
+
async onDev(ctx) {
|
|
160491
|
+
const ids = Object.keys(ctx.appConfig.alerts ?? {});
|
|
160492
|
+
if (ids.length === 0) {
|
|
160493
|
+
return;
|
|
160494
|
+
}
|
|
160495
|
+
const { captures, alerts } = await ctx.useSns();
|
|
160496
|
+
const names = new Map(ids.map((id) => [
|
|
160497
|
+
formatGlobalResourceName({
|
|
160498
|
+
appName: ctx.appConfig.name,
|
|
160499
|
+
resourceType: "alert",
|
|
160500
|
+
resourceName: id
|
|
160501
|
+
}),
|
|
160502
|
+
id
|
|
160503
|
+
]));
|
|
160504
|
+
captures.push((input) => {
|
|
160505
|
+
const id = names.get(input.TopicArn?.split(":").at(-1) ?? "");
|
|
160506
|
+
if (!id) {
|
|
160507
|
+
return false;
|
|
160508
|
+
}
|
|
160509
|
+
alerts.unshift({
|
|
160510
|
+
id: randomUUID7(),
|
|
160511
|
+
date: Date.now(),
|
|
160512
|
+
alert: id,
|
|
160513
|
+
subject: input.Subject,
|
|
160514
|
+
message: input.Message
|
|
160515
|
+
});
|
|
160516
|
+
ctx.emitEvent("problems", {
|
|
160517
|
+
date: Date.now(),
|
|
160518
|
+
kind: "alert",
|
|
160519
|
+
title: input.Subject ?? id,
|
|
160520
|
+
detail: id
|
|
160521
|
+
});
|
|
160522
|
+
return true;
|
|
160523
|
+
});
|
|
160524
|
+
for (const [name, id] of names) {
|
|
160525
|
+
ctx.registerResource({ kind: "alert", id, detail: name });
|
|
160526
|
+
}
|
|
160527
|
+
},
|
|
160403
160528
|
async onTypeGen(ctx) {
|
|
160404
160529
|
const gen = new TypeFile("awsless");
|
|
160405
160530
|
const resources = new TypeObject(1);
|
|
@@ -161457,6 +161582,7 @@ var instanceOnDev = async (ctx) => {
|
|
|
161457
161582
|
async start({ env: env4 }) {
|
|
161458
161583
|
const tail = [];
|
|
161459
161584
|
boot = () => {
|
|
161585
|
+
ctx.reportHealth(`instance ${id}`, "up");
|
|
161460
161586
|
child = spawn5("bun", [file2], {
|
|
161461
161587
|
cwd: cwd2,
|
|
161462
161588
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -161485,13 +161611,17 @@ var instanceOnDev = async (ctx) => {
|
|
|
161485
161611
|
};
|
|
161486
161612
|
child.stdout?.on("data", capture);
|
|
161487
161613
|
child.stderr?.on("data", capture);
|
|
161488
|
-
child.on("exit", (code) => {
|
|
161489
|
-
if (
|
|
161614
|
+
child.on("exit", (code, signal) => {
|
|
161615
|
+
if (stopping) {
|
|
161616
|
+
return;
|
|
161617
|
+
}
|
|
161618
|
+
if (code !== null && code !== 0) {
|
|
161490
161619
|
logs_exports.error(`The instance "${id}" exited with code ${code}:
|
|
161491
161620
|
${tail.join(`
|
|
161492
161621
|
`)}`);
|
|
161493
161622
|
ctx.emitEvent(channel, { date: Date.now(), line: `Exited with code ${code}`, error: true });
|
|
161494
161623
|
}
|
|
161624
|
+
ctx.reportHealth(`instance ${id}`, "down", code !== null ? `exited with code ${code}` : `killed by ${signal}`);
|
|
161495
161625
|
});
|
|
161496
161626
|
};
|
|
161497
161627
|
boot();
|
|
@@ -164584,16 +164714,11 @@ var startTest = async (props) => {
|
|
|
164584
164714
|
}
|
|
164585
164715
|
for (const error3 of module.errors()) {
|
|
164586
164716
|
const stack = error3.stacks?.[0];
|
|
164587
|
-
const { code, syscall, address, port } = error3;
|
|
164588
164717
|
errors3.push({
|
|
164589
164718
|
type: error3.name,
|
|
164590
164719
|
message: error3.message,
|
|
164591
164720
|
location: stack ? { line: stack.line, column: stack.column } : undefined,
|
|
164592
|
-
stack: error3.stack
|
|
164593
|
-
code,
|
|
164594
|
-
syscall,
|
|
164595
|
-
address,
|
|
164596
|
-
port
|
|
164721
|
+
stack: error3.stack
|
|
164597
164722
|
});
|
|
164598
164723
|
}
|
|
164599
164724
|
}
|
|
@@ -164689,11 +164814,6 @@ var logTestErrors = (event) => {
|
|
|
164689
164814
|
}
|
|
164690
164815
|
}
|
|
164691
164816
|
};
|
|
164692
|
-
var formatModuleError = (error3) => {
|
|
164693
|
-
const syscall = [error3.syscall, error3.address, error3.port && `port ${error3.port}`].filter(Boolean).join(" ");
|
|
164694
|
-
return [error3.message, syscall && `(${syscall})`, `
|
|
164695
|
-
`, error3.stack ?? "(no stack captured)"].filter(Boolean).join(" ");
|
|
164696
|
-
};
|
|
164697
164817
|
var runTest = async (stack, dir, filters, workspace, opts) => {
|
|
164698
164818
|
await mkdir8(directories.test, { recursive: true });
|
|
164699
164819
|
const file2 = join49(directories.test, `${stack}.json`);
|
|
@@ -164721,26 +164841,15 @@ var runTest = async (stack, dir, filters, workspace, opts) => {
|
|
|
164721
164841
|
initialMessage: `Run tests for the ${color2.info(stack)} stack`,
|
|
164722
164842
|
errorMessage: `Running tests for the ${color2.info(stack)} stack failed`,
|
|
164723
164843
|
async task(ctx) {
|
|
164724
|
-
const
|
|
164725
|
-
let result2 = await startTest({
|
|
164844
|
+
const result2 = await startTest({
|
|
164726
164845
|
dir,
|
|
164727
164846
|
filters,
|
|
164728
164847
|
env: opts.env
|
|
164729
164848
|
});
|
|
164730
|
-
if (result2.errors.length > 0 && result2.errors.every(transient)) {
|
|
164731
|
-
for (const error3 of result2.errors) {
|
|
164732
|
-
debug(`Transient module error in ${stack} tests, retrying once: ${formatModuleError(error3)}`);
|
|
164733
|
-
}
|
|
164734
|
-
await new Promise((resolve5) => setTimeout(resolve5, 1000));
|
|
164735
|
-
result2 = await startTest({
|
|
164736
|
-
dir,
|
|
164737
|
-
filters,
|
|
164738
|
-
env: opts.env
|
|
164739
|
-
});
|
|
164740
|
-
}
|
|
164741
164849
|
if (result2.errors.length > 0) {
|
|
164742
164850
|
for (const error3 of result2.errors) {
|
|
164743
|
-
debug(`Module error in ${stack} tests: ${
|
|
164851
|
+
debug(`Module error in ${stack} tests: ${error3.message}
|
|
164852
|
+
${error3.stack ?? "(no stack captured)"}`);
|
|
164744
164853
|
}
|
|
164745
164854
|
throw result2.errors.map((error3) => new ExpectedError(error3.type && error3.type !== "Error" ? `${error3.type}: ${error3.message}` : error3.message));
|
|
164746
164855
|
}
|
|
@@ -166580,7 +166689,7 @@ var createS3Server = (props) => {
|
|
|
166580
166689
|
};
|
|
166581
166690
|
|
|
166582
166691
|
// src/dev/servers/sqs.ts
|
|
166583
|
-
import { createHash as createHash23, randomUUID as
|
|
166692
|
+
import { createHash as createHash23, randomUUID as randomUUID8 } from "crypto";
|
|
166584
166693
|
import { createServer as createServer8 } from "http";
|
|
166585
166694
|
var md5 = (value) => createHash23("md5").update(value).digest("hex");
|
|
166586
166695
|
var md5OfAttributes = (attributes) => {
|
|
@@ -166655,7 +166764,7 @@ var createSqsServer = (props) => {
|
|
|
166655
166764
|
Records: [
|
|
166656
166765
|
{
|
|
166657
166766
|
messageId,
|
|
166658
|
-
receiptHandle:
|
|
166767
|
+
receiptHandle: randomUUID8(),
|
|
166659
166768
|
body: input.MessageBody,
|
|
166660
166769
|
attributes: {
|
|
166661
166770
|
ApproximateReceiveCount: "1",
|
|
@@ -166723,7 +166832,7 @@ var createSqsServer = (props) => {
|
|
|
166723
166832
|
if (!queue) {
|
|
166724
166833
|
throw new Error(`Unknown local queue: ${input.QueueUrl}`);
|
|
166725
166834
|
}
|
|
166726
|
-
const messageId =
|
|
166835
|
+
const messageId = randomUUID8();
|
|
166727
166836
|
deliver(queue, input, messageId);
|
|
166728
166837
|
return sendResult(input, messageId);
|
|
166729
166838
|
},
|
|
@@ -166734,7 +166843,7 @@ var createSqsServer = (props) => {
|
|
|
166734
166843
|
}
|
|
166735
166844
|
return {
|
|
166736
166845
|
Successful: (input.Entries ?? []).map((entry) => {
|
|
166737
|
-
const messageId =
|
|
166846
|
+
const messageId = randomUUID8();
|
|
166738
166847
|
deliver(queue, entry, messageId);
|
|
166739
166848
|
return {
|
|
166740
166849
|
Id: entry.Id,
|
|
@@ -166758,7 +166867,7 @@ var createSqsServer = (props) => {
|
|
|
166758
166867
|
const batch2 = visible.slice(0, Math.max(1, input.MaxNumberOfMessages ?? 1));
|
|
166759
166868
|
return {
|
|
166760
166869
|
Messages: batch2.map((message4) => {
|
|
166761
|
-
message4.receipt =
|
|
166870
|
+
message4.receipt = randomUUID8();
|
|
166762
166871
|
message4.receiveCount += 1;
|
|
166763
166872
|
message4.firstReceivedAt ??= now;
|
|
166764
166873
|
message4.visibleAt = now + (input.VisibilityTimeout ?? 30) * 1000;
|
|
@@ -166915,6 +167024,12 @@ var createDevContext = (props) => {
|
|
|
166915
167024
|
const servers = [];
|
|
166916
167025
|
const restartPaths = [];
|
|
166917
167026
|
const resources = [];
|
|
167027
|
+
const health = new Map;
|
|
167028
|
+
const reportHealth = (id, status2, detail) => {
|
|
167029
|
+
const entry = { id, status: status2, detail, date: Date.now() };
|
|
167030
|
+
health.set(id, entry);
|
|
167031
|
+
events.emit("health", entry);
|
|
167032
|
+
};
|
|
166918
167033
|
const listeners2 = new Map;
|
|
166919
167034
|
const replays = new Map;
|
|
166920
167035
|
const events = {
|
|
@@ -167012,12 +167127,37 @@ var createDevContext = (props) => {
|
|
|
167012
167127
|
})();
|
|
167013
167128
|
return sqs;
|
|
167014
167129
|
};
|
|
167130
|
+
let sns;
|
|
167131
|
+
const useSns = () => {
|
|
167132
|
+
sns ??= (async () => {
|
|
167133
|
+
const value = await props.pool.keep("shim:sns", null, async () => {
|
|
167134
|
+
const captures = [];
|
|
167135
|
+
const server = createSnsServer({ captures });
|
|
167136
|
+
const port = await server.listen();
|
|
167137
|
+
return {
|
|
167138
|
+
value: { server, port, captures, alerts: [] },
|
|
167139
|
+
stop: () => server.stop()
|
|
167140
|
+
};
|
|
167141
|
+
});
|
|
167142
|
+
value.captures.splice(0, value.captures.length);
|
|
167143
|
+
env4["AWS_ENDPOINT_URL_SNS"] = `http://127.0.0.1:${value.port}`;
|
|
167144
|
+
servers.push({
|
|
167145
|
+
name: "sns",
|
|
167146
|
+
start({ dispatch, reportFailure }) {
|
|
167147
|
+
value.server.connect(dispatch, reportFailure);
|
|
167148
|
+
}
|
|
167149
|
+
});
|
|
167150
|
+
return { port: value.port, captures: value.captures, alerts: value.alerts };
|
|
167151
|
+
})();
|
|
167152
|
+
return sns;
|
|
167153
|
+
};
|
|
167015
167154
|
return {
|
|
167016
167155
|
env: env4,
|
|
167017
167156
|
routes,
|
|
167018
167157
|
servers,
|
|
167019
167158
|
restartPaths,
|
|
167020
167159
|
resources,
|
|
167160
|
+
health,
|
|
167021
167161
|
events,
|
|
167022
167162
|
context: {
|
|
167023
167163
|
appConfig: props.appConfig,
|
|
@@ -167036,6 +167176,7 @@ var createDevContext = (props) => {
|
|
|
167036
167176
|
useDynamo,
|
|
167037
167177
|
useStore,
|
|
167038
167178
|
useSqs,
|
|
167179
|
+
useSns,
|
|
167039
167180
|
addEnv(name, value) {
|
|
167040
167181
|
if (name in env4 && env4[name] !== value) {
|
|
167041
167182
|
throw new Error(`The env var "${name}" is defined multiple times with different values, while all bundled functions share the same env.`);
|
|
@@ -167055,7 +167196,8 @@ var createDevContext = (props) => {
|
|
|
167055
167196
|
resources.push(resource);
|
|
167056
167197
|
},
|
|
167057
167198
|
log: props.log,
|
|
167058
|
-
emitEvent: events.emit
|
|
167199
|
+
emitEvent: events.emit,
|
|
167200
|
+
reportHealth
|
|
167059
167201
|
}
|
|
167060
167202
|
};
|
|
167061
167203
|
};
|
|
@@ -167112,7 +167254,7 @@ ${logs}`));
|
|
|
167112
167254
|
var import_ioredis5 = __toESM(require_built3(), 1);
|
|
167113
167255
|
import { DynamoDBClient as DynamoDBClient5 } from "@aws-sdk/client-dynamodb";
|
|
167114
167256
|
import { DynamoDBDocumentClient, ScanCommand as ScanCommand2 } from "@aws-sdk/lib-dynamodb";
|
|
167115
|
-
import { randomUUID as
|
|
167257
|
+
import { randomUUID as randomUUID9 } from "crypto";
|
|
167116
167258
|
import { readdir as readdir9, readFile as readFile22, stat as stat8, writeFile as writeFile14 } from "fs/promises";
|
|
167117
167259
|
import { createServer as createServer9 } from "http";
|
|
167118
167260
|
import { join as join55, relative as relative11, sep as sep5 } from "path";
|
|
@@ -167321,6 +167463,7 @@ var createBundleWorker = (props) => {
|
|
|
167321
167463
|
return run;
|
|
167322
167464
|
};
|
|
167323
167465
|
return {
|
|
167466
|
+
size: () => workers.length,
|
|
167324
167467
|
start: () => serialize(doStart),
|
|
167325
167468
|
stop: () => serialize(doStop),
|
|
167326
167469
|
restart: () => serialize(async () => {
|
|
@@ -167364,7 +167507,7 @@ var dashboardHtml = `<!doctype html>
|
|
|
167364
167507
|
--border: #262b36;
|
|
167365
167508
|
--text: #d7dae0;
|
|
167366
167509
|
--muted: #7d8590;
|
|
167367
|
-
--accent: #
|
|
167510
|
+
--accent: #ff9000;
|
|
167368
167511
|
--good: #3fb950;
|
|
167369
167512
|
--bad: #f85149;
|
|
167370
167513
|
font-size: 14px;
|
|
@@ -167426,18 +167569,34 @@ var dashboardHtml = `<!doctype html>
|
|
|
167426
167569
|
.logs .entry { padding: 4px 0; }
|
|
167427
167570
|
.logs .entry + .entry, .logs .line + .entry, .logs .entry + .line { border-top: 1px solid var(--border); }
|
|
167428
167571
|
.logs .entry .meta { display: flex; gap: 8px; margin-bottom: 2px; }
|
|
167429
|
-
|
|
167430
|
-
|
|
167431
|
-
|
|
167432
|
-
.config-form
|
|
167572
|
+
/* Every group is its own card, with a shared grid inside: the name
|
|
167573
|
+
column grows to the longest name (capped), so nothing truncates &
|
|
167574
|
+
the inputs line up. */
|
|
167575
|
+
.config-form { display: flex; flex-direction: column; gap: 14px; max-width: 720px; margin-top: 14px; }
|
|
167576
|
+
.config-group {
|
|
167433
167577
|
background: var(--panel);
|
|
167578
|
+
border: 1px solid var(--border);
|
|
167579
|
+
border-radius: 8px;
|
|
167580
|
+
padding: 14px 16px;
|
|
167581
|
+
}
|
|
167582
|
+
.config-group h3 { margin: 0 0 12px; }
|
|
167583
|
+
.config-fields {
|
|
167584
|
+
display: grid;
|
|
167585
|
+
grid-template-columns: fit-content(340px) 1fr;
|
|
167586
|
+
gap: 10px 16px;
|
|
167587
|
+
align-items: center;
|
|
167588
|
+
}
|
|
167589
|
+
.config-fields .field { display: contents; }
|
|
167590
|
+
.config-fields .name { color: var(--muted); overflow-wrap: anywhere; }
|
|
167591
|
+
.config-fields input {
|
|
167592
|
+
background: var(--bg);
|
|
167434
167593
|
color: var(--text);
|
|
167435
167594
|
border: 1px solid var(--border);
|
|
167436
167595
|
border-radius: 6px;
|
|
167437
167596
|
padding: 6px 10px;
|
|
167438
167597
|
font: inherit;
|
|
167439
167598
|
}
|
|
167440
|
-
.config-
|
|
167599
|
+
.config-fields input::placeholder { color: var(--muted); }
|
|
167441
167600
|
.groups { display: flex; flex-wrap: wrap; gap: 4px 16px; }
|
|
167442
167601
|
.groups .group { display: flex; align-items: center; gap: 4px; cursor: pointer; }
|
|
167443
167602
|
nav {
|
|
@@ -167448,10 +167607,13 @@ var dashboardHtml = `<!doctype html>
|
|
|
167448
167607
|
nav h1 {
|
|
167449
167608
|
font-size: 15px;
|
|
167450
167609
|
margin: 4px 8px 16px;
|
|
167451
|
-
color: var(--accent);
|
|
167452
167610
|
cursor: pointer;
|
|
167453
167611
|
}
|
|
167454
|
-
|
|
167612
|
+
/* The same two-tone logo as the cli: bold AWS in the brand orange,
|
|
167613
|
+
LESS dimmed, the command muted. */
|
|
167614
|
+
nav h1 .logo { color: var(--accent); font-weight: bold; }
|
|
167615
|
+
nav h1 .logo .dim { color: #a35d00; }
|
|
167616
|
+
nav h1 .cmd { color: var(--muted); font-weight: normal; }
|
|
167455
167617
|
nav h3 {
|
|
167456
167618
|
font-size: 10px;
|
|
167457
167619
|
text-transform: uppercase;
|
|
@@ -167544,6 +167706,24 @@ var dashboardHtml = `<!doctype html>
|
|
|
167544
167706
|
cursor: pointer;
|
|
167545
167707
|
}
|
|
167546
167708
|
.row:hover { background: var(--panel); }
|
|
167709
|
+
a.row { text-decoration: none; }
|
|
167710
|
+
.health { display: flex; flex-wrap: wrap; gap: 8px; margin: 12px 0 4px; }
|
|
167711
|
+
.health .chip {
|
|
167712
|
+
display: inline-flex;
|
|
167713
|
+
align-items: center;
|
|
167714
|
+
gap: 7px;
|
|
167715
|
+
background: var(--panel);
|
|
167716
|
+
border: 1px solid var(--border);
|
|
167717
|
+
border-radius: 999px;
|
|
167718
|
+
padding: 4px 12px;
|
|
167719
|
+
font-size: 12px;
|
|
167720
|
+
}
|
|
167721
|
+
.health .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--good); flex-shrink: 0; }
|
|
167722
|
+
.health .chip.down { border-color: var(--bad); }
|
|
167723
|
+
.health .chip.down .dot { background: var(--bad); }
|
|
167724
|
+
.health .chip .detail-text { color: var(--muted); }
|
|
167725
|
+
.row.problem .id { color: var(--bad); }
|
|
167726
|
+
.empty.good { color: var(--good); }
|
|
167547
167727
|
.row .stack {
|
|
167548
167728
|
color: var(--muted);
|
|
167549
167729
|
min-width: 90px;
|
|
@@ -167675,9 +167855,10 @@ const GROUPS = [
|
|
|
167675
167855
|
['store', 'Stores'],
|
|
167676
167856
|
['config', 'Config'],
|
|
167677
167857
|
['auth', 'Auth'],
|
|
167858
|
+
['alert', 'Alerts'],
|
|
167678
167859
|
['email', 'Emails'],
|
|
167679
167860
|
['worker', 'Logs'],
|
|
167680
|
-
['route', '
|
|
167861
|
+
['route', 'Routers'],
|
|
167681
167862
|
]
|
|
167682
167863
|
|
|
167683
167864
|
// The nav renders the features in scannable sections - a section only
|
|
@@ -167687,7 +167868,7 @@ const SECTIONS = [
|
|
|
167687
167868
|
['Compute', ['function', 'cron', 'task', 'instance']],
|
|
167688
167869
|
['Messaging', ['queue', 'topic', 'subscriber', 'pubsub']],
|
|
167689
167870
|
['Storage', ['table', 'cache', 'search', 'store']],
|
|
167690
|
-
['App', ['config', 'auth', 'email', 'worker']],
|
|
167871
|
+
['App', ['config', 'auth', 'alert', 'email', 'worker']],
|
|
167691
167872
|
]
|
|
167692
167873
|
|
|
167693
167874
|
const svg = inner =>
|
|
@@ -167710,12 +167891,13 @@ const ICONS = {
|
|
|
167710
167891
|
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
167892
|
search: svg('<circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/>'),
|
|
167712
167893
|
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"/>'),
|
|
167894
|
+
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
167895
|
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
167896
|
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
167897
|
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"/>'),
|
|
167716
167898
|
site: svg('<rect x="2" y="3" width="20" height="14" rx="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/>'),
|
|
167717
167899
|
seed: svg('<path d="M12 22V8"/><path d="M12 8C12 5 9 2 5 2c0 4 3 6 7 6z"/><path d="M12 12c0-3 3-6 7-6 0 4-3 6-7 6z"/>'),
|
|
167718
|
-
auth: svg('<
|
|
167900
|
+
auth: svg('<path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/>'),
|
|
167719
167901
|
worker: svg('<polyline points="4 17 10 11 4 5"/><line x1="12" y1="19" x2="20" y2="19"/>'),
|
|
167720
167902
|
}
|
|
167721
167903
|
|
|
@@ -167728,7 +167910,7 @@ const icon = kind => {
|
|
|
167728
167910
|
let state
|
|
167729
167911
|
let cleanupPanel
|
|
167730
167912
|
const view = { kind: null, resource: null }
|
|
167731
|
-
const filter = { query: '', stack: '' }
|
|
167913
|
+
const filter = { query: '', stack: '', router: '' }
|
|
167732
167914
|
|
|
167733
167915
|
const label = r => (r.stack ? r.stack + ' / ' + r.id : r.id)
|
|
167734
167916
|
const groupTitle = kind => GROUPS.find(([k]) => k === kind)?.[1] ?? kind
|
|
@@ -167744,6 +167926,7 @@ const filterParams = () => {
|
|
|
167744
167926
|
const params = new URLSearchParams()
|
|
167745
167927
|
if (filter.query) params.set('q', filter.query)
|
|
167746
167928
|
if (filter.stack) params.set('stack', filter.stack)
|
|
167929
|
+
if (filter.router) params.set('router', filter.router)
|
|
167747
167930
|
return params.toString()
|
|
167748
167931
|
}
|
|
167749
167932
|
|
|
@@ -167764,6 +167947,7 @@ const selectKind = kind => {
|
|
|
167764
167947
|
view.resource = null
|
|
167765
167948
|
filter.query = ''
|
|
167766
167949
|
filter.stack = ''
|
|
167950
|
+
filter.router = ''
|
|
167767
167951
|
history.pushState(null, '', listUrl(kind))
|
|
167768
167952
|
render()
|
|
167769
167953
|
}
|
|
@@ -167789,6 +167973,7 @@ const applyLocation = () => {
|
|
|
167789
167973
|
view.resource = null
|
|
167790
167974
|
filter.query = params.get('q') ?? ''
|
|
167791
167975
|
filter.stack = params.get('stack') ?? ''
|
|
167976
|
+
filter.router = params.get('router') ?? ''
|
|
167792
167977
|
|
|
167793
167978
|
if (view.kind && segments.length >= 3) {
|
|
167794
167979
|
const router = params.get('router')
|
|
@@ -168175,6 +168360,11 @@ const cachePanel = async (main, r) => {
|
|
|
168175
168360
|
const holder = $('div', {}, $('p', { className: 'empty' }, 'Scanning...'))
|
|
168176
168361
|
main.append(holder)
|
|
168177
168362
|
|
|
168363
|
+
// The redis server's own output, streamed live.
|
|
168364
|
+
if (r.channel) {
|
|
168365
|
+
cleanupPanel = attachLogFeed(main, r.channel, undefined, 'Server logs')
|
|
168366
|
+
}
|
|
168367
|
+
|
|
168178
168368
|
try {
|
|
168179
168369
|
const data = await api('/api/cache?target=' + encodeURIComponent(r.detail))
|
|
168180
168370
|
holder.innerHTML = ''
|
|
@@ -168255,6 +168445,11 @@ const searchPanel = async (main, r) => {
|
|
|
168255
168445
|
result,
|
|
168256
168446
|
)
|
|
168257
168447
|
|
|
168448
|
+
// The opensearch server's own output, streamed live.
|
|
168449
|
+
if (r.channel) {
|
|
168450
|
+
cleanupPanel = attachLogFeed(main, r.channel, undefined, 'Server logs')
|
|
168451
|
+
}
|
|
168452
|
+
|
|
168258
168453
|
try {
|
|
168259
168454
|
const { data } = await proxy('/_cat/indices?format=json&h=index,health,docs.count,store.size&s=index')
|
|
168260
168455
|
const rows = data.filter(entry => !entry.index.startsWith('.'))
|
|
@@ -168309,6 +168504,59 @@ const storePanel = async (main, r) => {
|
|
|
168309
168504
|
|
|
168310
168505
|
// Every email sent through Email.send during this session - captured
|
|
168311
168506
|
// by the local ses shim instead of being delivered.
|
|
168507
|
+
const alertPanel = async (main) => {
|
|
168508
|
+
const holder = $('div', {})
|
|
168509
|
+
main.append(holder)
|
|
168510
|
+
|
|
168511
|
+
const render = async () => {
|
|
168512
|
+
const data = await api('/api/alerts')
|
|
168513
|
+
const alerts = data.alerts ?? []
|
|
168514
|
+
holder.innerHTML = ''
|
|
168515
|
+
|
|
168516
|
+
const refresh = $('button', { className: 'primary', textContent: 'Refresh' })
|
|
168517
|
+
refresh.onclick = render
|
|
168518
|
+
holder.append($('div', { className: 'actions' }, [refresh]))
|
|
168519
|
+
|
|
168520
|
+
if (alerts.length === 0) {
|
|
168521
|
+
holder.append($('p', { className: 'empty' }, 'No alerts sent yet.'))
|
|
168522
|
+
return
|
|
168523
|
+
}
|
|
168524
|
+
|
|
168525
|
+
const rows = $('div', { className: 'rows' })
|
|
168526
|
+
|
|
168527
|
+
for (const alert of alerts) {
|
|
168528
|
+
const row = $('button', { className: 'row' }, [
|
|
168529
|
+
$('span', { className: 'stack' }, new Date(alert.date).toLocaleTimeString()),
|
|
168530
|
+
$('span', { className: 'id' }, alert.subject ?? '(no subject)'),
|
|
168531
|
+
$('span', { className: 'info' }, alert.alert),
|
|
168532
|
+
])
|
|
168533
|
+
row.onclick = () => {
|
|
168534
|
+
holder.innerHTML = ''
|
|
168535
|
+
|
|
168536
|
+
const back = $('button', { className: 'back', textContent: '\u2190 Alerts' })
|
|
168537
|
+
back.onclick = render
|
|
168538
|
+
|
|
168539
|
+
let message = alert.message ?? '(no payload)'
|
|
168540
|
+
try {
|
|
168541
|
+
message = JSON.stringify(JSON.parse(alert.message), null, 2)
|
|
168542
|
+
} catch (_) {}
|
|
168543
|
+
|
|
168544
|
+
holder.append(
|
|
168545
|
+
back,
|
|
168546
|
+
$('h2', {}, alert.subject ?? '(no subject)'),
|
|
168547
|
+
$('p', { className: 'detail' }, alert.alert + ' \xB7 ' + new Date(alert.date).toLocaleString()),
|
|
168548
|
+
$('pre', { className: 'result' }, message),
|
|
168549
|
+
)
|
|
168550
|
+
}
|
|
168551
|
+
rows.append(row)
|
|
168552
|
+
}
|
|
168553
|
+
|
|
168554
|
+
holder.append(rows)
|
|
168555
|
+
}
|
|
168556
|
+
|
|
168557
|
+
render()
|
|
168558
|
+
}
|
|
168559
|
+
|
|
168312
168560
|
const emailPanel = async (main) => {
|
|
168313
168561
|
const holder = $('div', {})
|
|
168314
168562
|
main.append(holder)
|
|
@@ -168371,7 +168619,34 @@ const configPanel = async (main) => {
|
|
|
168371
168619
|
const inputs = new Map()
|
|
168372
168620
|
const form = $('div', { className: 'config-form' })
|
|
168373
168621
|
|
|
168622
|
+
// Configs group by the first segment of their name: alphapo-api-key
|
|
168623
|
+
// & alphapo-host read as one "alphapo" block with the prefix
|
|
168624
|
+
// stripped from the rows. A prefix needs at least two members to
|
|
168625
|
+
// form a group - the loners keep their full name under "other".
|
|
168626
|
+
const byPrefix = new Map()
|
|
168627
|
+
|
|
168374
168628
|
for (const name of names) {
|
|
168629
|
+
const prefix = name.split('-')[0]
|
|
168630
|
+
if (!byPrefix.has(prefix)) byPrefix.set(prefix, [])
|
|
168631
|
+
byPrefix.get(prefix).push(name)
|
|
168632
|
+
}
|
|
168633
|
+
|
|
168634
|
+
const sections = []
|
|
168635
|
+
const other = []
|
|
168636
|
+
|
|
168637
|
+
for (const [prefix, members] of byPrefix) {
|
|
168638
|
+
if (members.length > 1) {
|
|
168639
|
+
sections.push([prefix, members])
|
|
168640
|
+
} else {
|
|
168641
|
+
other.push(members[0])
|
|
168642
|
+
}
|
|
168643
|
+
}
|
|
168644
|
+
|
|
168645
|
+
if (other.length > 0) {
|
|
168646
|
+
sections.push(['other', other])
|
|
168647
|
+
}
|
|
168648
|
+
|
|
168649
|
+
const addField = (grid, name) => {
|
|
168375
168650
|
// An empty input falls through to the value pulled from ssm on
|
|
168376
168651
|
// boot - the placeholder shows whether the pull provided one.
|
|
168377
168652
|
const input = $('input', {
|
|
@@ -168380,7 +168655,21 @@ const configPanel = async (main) => {
|
|
|
168380
168655
|
spellcheck: false,
|
|
168381
168656
|
})
|
|
168382
168657
|
inputs.set(name, input)
|
|
168383
|
-
|
|
168658
|
+
grid.append($('label', { className: 'field' }, [$('span', { className: 'name' }, name), input]))
|
|
168659
|
+
}
|
|
168660
|
+
|
|
168661
|
+
for (const [prefix, members] of sections) {
|
|
168662
|
+
const grid = $('div', { className: 'config-fields' })
|
|
168663
|
+
|
|
168664
|
+
for (const name of members) {
|
|
168665
|
+
addField(grid, name)
|
|
168666
|
+
}
|
|
168667
|
+
|
|
168668
|
+
// A lone unlabeled group skips its header - the card alone
|
|
168669
|
+
// carries the grouping.
|
|
168670
|
+
const header = sections.length > 1 || other.length === 0 ? [$('h3', {}, prefix)] : []
|
|
168671
|
+
|
|
168672
|
+
form.append($('div', { className: 'config-group' }, [...header, grid]))
|
|
168384
168673
|
}
|
|
168385
168674
|
|
|
168386
168675
|
if (names.length === 0) {
|
|
@@ -168549,7 +168838,9 @@ const authPanel = async (main, r) => {
|
|
|
168549
168838
|
|
|
168550
168839
|
const renderResource = main => {
|
|
168551
168840
|
const r = view.resource
|
|
168552
|
-
|
|
168841
|
+
// A route's back button lands on its router's route list, one level
|
|
168842
|
+
// below the Routers tab itself.
|
|
168843
|
+
const back = $('button', { className: 'back' }, '\u2190 ' + (r.kind === 'route' ? 'Routes' : groupTitle(r.kind)))
|
|
168553
168844
|
|
|
168554
168845
|
back.onclick = () => {
|
|
168555
168846
|
view.resource = null
|
|
@@ -168596,7 +168887,49 @@ const renderList = main => {
|
|
|
168596
168887
|
const items = state.resources.filter(r => r.kind === view.kind)
|
|
168597
168888
|
const stacks = [...new Set(items.map(r => r.stack).filter(Boolean))].sort()
|
|
168598
168889
|
|
|
168599
|
-
|
|
168890
|
+
// The routes view drills down per router: every router runs as its
|
|
168891
|
+
// own local server (like its own domain in production), so a flat
|
|
168892
|
+
// list mixing every router's routes would only confuse.
|
|
168893
|
+
if (view.kind === 'route' && !filter.router) {
|
|
168894
|
+
main.append($('h2', {}, 'Routers'))
|
|
168895
|
+
|
|
168896
|
+
const rows = $('div', { className: 'rows' })
|
|
168897
|
+
|
|
168898
|
+
for (const [id, port] of Object.entries(state.routerPorts)) {
|
|
168899
|
+
const count = items.filter(r => r.router === id).length
|
|
168900
|
+
const row = $('button', { className: 'row' }, [
|
|
168901
|
+
$('span', { className: 'stack' }, id),
|
|
168902
|
+
$('span', { className: 'id' }, 'http://localhost:' + port),
|
|
168903
|
+
$('span', { className: 'info' }, count + (count === 1 ? ' route' : ' routes')),
|
|
168904
|
+
])
|
|
168905
|
+
row.onclick = () => {
|
|
168906
|
+
filter.router = id
|
|
168907
|
+
history.pushState(null, '', listUrl('route'))
|
|
168908
|
+
render()
|
|
168909
|
+
}
|
|
168910
|
+
rows.append(row)
|
|
168911
|
+
}
|
|
168912
|
+
|
|
168913
|
+
main.append(rows)
|
|
168914
|
+
return
|
|
168915
|
+
}
|
|
168916
|
+
|
|
168917
|
+
if (view.kind === 'route') {
|
|
168918
|
+
const back = $('button', { className: 'back' }, '\u2190 Routers')
|
|
168919
|
+
back.onclick = () => {
|
|
168920
|
+
filter.router = ''
|
|
168921
|
+
history.pushState(null, '', listUrl('route'))
|
|
168922
|
+
render()
|
|
168923
|
+
}
|
|
168924
|
+
|
|
168925
|
+
main.append(
|
|
168926
|
+
back,
|
|
168927
|
+
$('h2', {}, 'Routes'),
|
|
168928
|
+
$('p', { className: 'detail' }, filter.router + ' \xB7 http://localhost:' + state.routerPorts[filter.router]),
|
|
168929
|
+
)
|
|
168930
|
+
} else {
|
|
168931
|
+
main.append($('h2', {}, groupTitle(view.kind)))
|
|
168932
|
+
}
|
|
168600
168933
|
|
|
168601
168934
|
// The config page is a single form over every defined value,
|
|
168602
168935
|
// instead of a resource list.
|
|
@@ -168609,15 +168942,27 @@ const renderList = main => {
|
|
|
168609
168942
|
return emailPanel(main)
|
|
168610
168943
|
}
|
|
168611
168944
|
|
|
168945
|
+
// The alert page lists every captured alert of the session.
|
|
168946
|
+
if (view.kind === 'alert') {
|
|
168947
|
+
return alertPanel(main)
|
|
168948
|
+
}
|
|
168949
|
+
|
|
168612
168950
|
// The worker page streams the bundle worker output directly,
|
|
168613
168951
|
// instead of listing its single resource.
|
|
168614
168952
|
if (view.kind === 'worker') {
|
|
168615
|
-
|
|
168953
|
+
const workerFeed = attachLogFeed(main, 'worker', undefined, 'Worker output')
|
|
168954
|
+
const debugFeed = attachLogFeed(main, 'debug', undefined, 'Dev server')
|
|
168955
|
+
|
|
168956
|
+
cleanupPanel = () => {
|
|
168957
|
+
workerFeed?.()
|
|
168958
|
+
debugFeed?.()
|
|
168959
|
+
}
|
|
168616
168960
|
return
|
|
168617
168961
|
}
|
|
168618
168962
|
|
|
168619
168963
|
const matches = r => {
|
|
168620
168964
|
if (filter.stack && r.stack !== filter.stack) return false
|
|
168965
|
+
if (filter.router && r.router !== filter.router) return false
|
|
168621
168966
|
if (!filter.query) return true
|
|
168622
168967
|
|
|
168623
168968
|
return (r.stack + ' ' + r.id + ' ' + (r.detail ?? ''))
|
|
@@ -168691,11 +169036,14 @@ const render = () => {
|
|
|
168691
169036
|
cleanupPanel = undefined
|
|
168692
169037
|
|
|
168693
169038
|
const nav = document.getElementById('nav')
|
|
168694
|
-
nav.innerHTML = '<h1>
|
|
169039
|
+
nav.innerHTML = '<h1><span class="logo">AWS<span class="dim">LESS</span></span> <span class="cmd">dev</span></h1>'
|
|
168695
169040
|
nav.querySelector('h1').onclick = showHome
|
|
168696
169041
|
|
|
168697
169042
|
const navButton = kind => {
|
|
168698
|
-
|
|
169043
|
+
// The Routers tab lists routers, so its count follows suit.
|
|
169044
|
+
const count = kind === 'route'
|
|
169045
|
+
? Object.keys(state.routerPorts).length
|
|
169046
|
+
: state.resources.filter(r => r.kind === kind).length
|
|
168699
169047
|
if (count === 0) return null
|
|
168700
169048
|
|
|
168701
169049
|
// The email outbox is a single feed, so a count of registered
|
|
@@ -168703,7 +169051,7 @@ const render = () => {
|
|
|
168703
169051
|
const button = $('button', { className: view.kind === kind ? 'active' : '' }, [
|
|
168704
169052
|
icon(kind),
|
|
168705
169053
|
groupTitle(kind),
|
|
168706
|
-
kind === 'email' || kind === 'worker' ? '' : $('span', { className: 'count' }, String(count)),
|
|
169054
|
+
kind === 'email' || kind === 'worker' || kind === 'alert' ? '' : $('span', { className: 'count' }, String(count)),
|
|
168707
169055
|
])
|
|
168708
169056
|
button.onclick = () => selectKind(kind)
|
|
168709
169057
|
return button
|
|
@@ -168775,7 +169123,192 @@ const render = () => {
|
|
|
168775
169123
|
} else if (view.kind) {
|
|
168776
169124
|
renderList(main)
|
|
168777
169125
|
} else {
|
|
168778
|
-
main
|
|
169126
|
+
renderHome(main)
|
|
169127
|
+
}
|
|
169128
|
+
}
|
|
169129
|
+
|
|
169130
|
+
// ------------------------------------------------------------------
|
|
169131
|
+
// Homepage: the session at a glance - endpoints, problems & the live
|
|
169132
|
+
// activity feed of everything running through the bundle.
|
|
169133
|
+
|
|
169134
|
+
const timeAgo = ms => {
|
|
169135
|
+
const s = Math.max(0, Math.round(ms / 1000))
|
|
169136
|
+
if (s < 60) return s + 's'
|
|
169137
|
+
if (s < 3600) return Math.round(s / 60) + 'm'
|
|
169138
|
+
return Math.floor(s / 3600) + 'h ' + (Math.round(s / 60) % 60) + 'm'
|
|
169139
|
+
}
|
|
169140
|
+
|
|
169141
|
+
const renderHome = main => {
|
|
169142
|
+
const session = state.session ?? {}
|
|
169143
|
+
|
|
169144
|
+
const uptime = $('span', {}, '')
|
|
169145
|
+
const updateUptime = () => {
|
|
169146
|
+
uptime.textContent = session.startedAt ? 'up ' + timeAgo(Date.now() - session.startedAt) : ''
|
|
169147
|
+
}
|
|
169148
|
+
updateUptime()
|
|
169149
|
+
const uptimeTimer = setInterval(updateUptime, 1000)
|
|
169150
|
+
|
|
169151
|
+
main.append(
|
|
169152
|
+
$('h2', {}, state.app),
|
|
169153
|
+
$('p', { className: 'detail' }, [
|
|
169154
|
+
uptime,
|
|
169155
|
+
session.workers ? ' \\u00b7 ' + session.workers + ' workers' : '',
|
|
169156
|
+
]),
|
|
169157
|
+
)
|
|
169158
|
+
|
|
169159
|
+
// ----------------------------------------------------------------
|
|
169160
|
+
// Health: one chip per moving part, live.
|
|
169161
|
+
|
|
169162
|
+
const chips = $('div', { className: 'health' })
|
|
169163
|
+
const chipEls = new Map()
|
|
169164
|
+
|
|
169165
|
+
const renderChip = entry => {
|
|
169166
|
+
let chip = chipEls.get(entry.id)
|
|
169167
|
+
|
|
169168
|
+
if (!chip) {
|
|
169169
|
+
chip = $('span', { className: 'chip' })
|
|
169170
|
+
chipEls.set(entry.id, chip)
|
|
169171
|
+
chips.append(chip)
|
|
169172
|
+
}
|
|
169173
|
+
|
|
169174
|
+
chip.className = 'chip' + (entry.status === 'down' ? ' down' : '')
|
|
169175
|
+
chip.innerHTML = ''
|
|
169176
|
+
chip.append(
|
|
169177
|
+
$('span', { className: 'dot' }),
|
|
169178
|
+
entry.id,
|
|
169179
|
+
entry.detail ? $('span', { className: 'detail-text' }, '\xB7 ' + entry.detail) : '',
|
|
169180
|
+
)
|
|
169181
|
+
}
|
|
169182
|
+
|
|
169183
|
+
for (const entry of state.health ?? []) renderChip(entry)
|
|
169184
|
+
|
|
169185
|
+
const healthSource = new EventSource('/api/events?channel=health')
|
|
169186
|
+
healthSource.onmessage = message => {
|
|
169187
|
+
try {
|
|
169188
|
+
renderChip(JSON.parse(message.data))
|
|
169189
|
+
} catch (_) {}
|
|
169190
|
+
}
|
|
169191
|
+
|
|
169192
|
+
if ((state.health ?? []).length > 0) {
|
|
169193
|
+
main.append(chips)
|
|
169194
|
+
}
|
|
169195
|
+
|
|
169196
|
+
// ----------------------------------------------------------------
|
|
169197
|
+
// Endpoints
|
|
169198
|
+
|
|
169199
|
+
main.append($('h3', {}, 'Endpoints'))
|
|
169200
|
+
|
|
169201
|
+
const endpoints = $('div', { className: 'rows' })
|
|
169202
|
+
|
|
169203
|
+
for (const [id, port] of Object.entries(state.routerPorts ?? {})) {
|
|
169204
|
+
const url = 'http://localhost:' + port
|
|
169205
|
+
const row = $('a', { className: 'row', href: url, target: '_blank' }, [
|
|
169206
|
+
$('span', { className: 'stack' }, 'router ' + id),
|
|
169207
|
+
$('span', { className: 'id' }, url),
|
|
169208
|
+
$('span', { className: 'info' }, ''),
|
|
169209
|
+
])
|
|
169210
|
+
endpoints.append(row)
|
|
169211
|
+
}
|
|
169212
|
+
|
|
169213
|
+
main.append(endpoints)
|
|
169214
|
+
|
|
169215
|
+
// ----------------------------------------------------------------
|
|
169216
|
+
// Problems: failures, route errors & fired alerts, newest first.
|
|
169217
|
+
|
|
169218
|
+
main.append($('h3', {}, 'Problems'))
|
|
169219
|
+
|
|
169220
|
+
const problems = $('div', { className: 'rows' })
|
|
169221
|
+
const calm = $('p', { className: 'empty good' }, 'No problems - everything runs clean.')
|
|
169222
|
+
main.append(calm, problems)
|
|
169223
|
+
|
|
169224
|
+
const problemRows = []
|
|
169225
|
+
|
|
169226
|
+
const problemRow = data => {
|
|
169227
|
+
calm.hidden = true
|
|
169228
|
+
|
|
169229
|
+
const row = $('button', { className: 'row problem' }, [
|
|
169230
|
+
$('span', { className: 'stack' }, new Date(data.date).toLocaleTimeString() + ' \\u00b7 ' + data.kind),
|
|
169231
|
+
$('span', { className: 'id' }, data.title ?? ''),
|
|
169232
|
+
$('span', { className: 'info' }, (data.detail ?? '').slice(0, 120)),
|
|
169233
|
+
])
|
|
169234
|
+
|
|
169235
|
+
row.onclick = () => {
|
|
169236
|
+
if (data.kind === 'alert') {
|
|
169237
|
+
selectKind('alert')
|
|
169238
|
+
return
|
|
169239
|
+
}
|
|
169240
|
+
|
|
169241
|
+
const resource = state.resources.find(r => r.routeKey === data.title)
|
|
169242
|
+
if (resource) selectResource(resource)
|
|
169243
|
+
}
|
|
169244
|
+
|
|
169245
|
+
problems.prepend(row)
|
|
169246
|
+
problemRows.push(row)
|
|
169247
|
+
|
|
169248
|
+
while (problemRows.length > 20) {
|
|
169249
|
+
problemRows.shift().remove()
|
|
169250
|
+
}
|
|
169251
|
+
}
|
|
169252
|
+
|
|
169253
|
+
const problemSource = new EventSource('/api/events?channel=problems')
|
|
169254
|
+
problemSource.onmessage = message => {
|
|
169255
|
+
try {
|
|
169256
|
+
problemRow(JSON.parse(message.data))
|
|
169257
|
+
} catch (_) {}
|
|
169258
|
+
}
|
|
169259
|
+
|
|
169260
|
+
// ----------------------------------------------------------------
|
|
169261
|
+
// Activity: every dispatch through the bundle, newest first.
|
|
169262
|
+
|
|
169263
|
+
main.append($('h3', {}, 'Activity'))
|
|
169264
|
+
|
|
169265
|
+
const activity = $('div', { className: 'rows' })
|
|
169266
|
+
const idle = $('p', { className: 'empty' }, 'Nothing ran yet.')
|
|
169267
|
+
main.append(idle, activity)
|
|
169268
|
+
|
|
169269
|
+
const activityRows = []
|
|
169270
|
+
|
|
169271
|
+
const activityRow = data => {
|
|
169272
|
+
idle.hidden = true
|
|
169273
|
+
|
|
169274
|
+
const resource = state.resources.find(r => r.routeKey === data.route)
|
|
169275
|
+
const row = $('button', { className: 'row' + (data.ok ? '' : ' problem') }, [
|
|
169276
|
+
$('span', { className: 'stack' }, new Date(data.date).toLocaleTimeString()),
|
|
169277
|
+
$('span', { className: 'id' }, (data.ok ? '' : '\\u2717 ') + data.route),
|
|
169278
|
+
$('span', { className: 'info' }, data.ok ? data.ms + 'ms' : (data.error ?? 'failed').slice(0, 80)),
|
|
169279
|
+
])
|
|
169280
|
+
|
|
169281
|
+
if (resource) {
|
|
169282
|
+
row.onclick = () => selectResource(resource)
|
|
169283
|
+
}
|
|
169284
|
+
|
|
169285
|
+
activity.prepend(row)
|
|
169286
|
+
activityRows.push(row)
|
|
169287
|
+
|
|
169288
|
+
while (activityRows.length > 50) {
|
|
169289
|
+
activityRows.shift().remove()
|
|
169290
|
+
}
|
|
169291
|
+
}
|
|
169292
|
+
|
|
169293
|
+
const activitySource = new EventSource('/api/events?channel=activity')
|
|
169294
|
+
activitySource.onmessage = message => {
|
|
169295
|
+
try {
|
|
169296
|
+
activityRow(JSON.parse(message.data))
|
|
169297
|
+
} catch (_) {}
|
|
169298
|
+
}
|
|
169299
|
+
|
|
169300
|
+
// ----------------------------------------------------------------
|
|
169301
|
+
// Logs: the handlers' own console output, live - the full feed
|
|
169302
|
+
// (incl. the dev server stream) lives on the Logs tab.
|
|
169303
|
+
|
|
169304
|
+
const logsFeed = attachLogFeed(main, 'worker', undefined, 'Logs')
|
|
169305
|
+
|
|
169306
|
+
cleanupPanel = () => {
|
|
169307
|
+
clearInterval(uptimeTimer)
|
|
169308
|
+
healthSource.close()
|
|
169309
|
+
problemSource.close()
|
|
169310
|
+
activitySource.close()
|
|
169311
|
+
logsFeed?.()
|
|
168779
169312
|
}
|
|
168780
169313
|
}
|
|
168781
169314
|
|
|
@@ -168796,14 +169329,15 @@ try {
|
|
|
168796
169329
|
document.title = state.app + ' \xB7 awsless dev'
|
|
168797
169330
|
state.resources = [
|
|
168798
169331
|
...state.resources,
|
|
168799
|
-
//
|
|
168800
|
-
//
|
|
168801
|
-
|
|
169332
|
+
// The full route table per router, like the deployed router: both
|
|
169333
|
+
// bundle routes & proxy mounts (site dev servers, the pubsub
|
|
169334
|
+
// websocket). Only the raw per-file static asset routes stay out.
|
|
169335
|
+
...state.routes.filter(route => !route.rawKey).map(route => ({
|
|
168802
169336
|
kind: 'route',
|
|
168803
169337
|
id: route.pattern,
|
|
168804
|
-
stack: route.routeKey.split(':')[0],
|
|
169338
|
+
stack: route.routeKey ? route.routeKey.split(':')[0] : undefined,
|
|
168805
169339
|
router: route.routerId,
|
|
168806
|
-
detail: route.routeKey,
|
|
169340
|
+
detail: route.routeKey ?? ('proxy \u2192 ' + route.proxy),
|
|
168807
169341
|
url: 'http://localhost:' + state.routerPorts[route.routerId] + route.pattern.split('{')[0].replace(/\\*$/, ''),
|
|
168808
169342
|
})),
|
|
168809
169343
|
]
|
|
@@ -168863,7 +169397,9 @@ var createDashboardServer = (props) => {
|
|
|
168863
169397
|
routerPorts: props.routerPorts,
|
|
168864
169398
|
resources: props.resources,
|
|
168865
169399
|
routes: props.routes,
|
|
168866
|
-
seeds: Boolean(props.runSeeds)
|
|
169400
|
+
seeds: Boolean(props.runSeeds),
|
|
169401
|
+
session: props.getSession?.() ?? null,
|
|
169402
|
+
health: props.getHealth?.() ?? []
|
|
168867
169403
|
}).replaceAll("<", "\\u003c");
|
|
168868
169404
|
return { status: 200, body: dashboardHtml.replace("__STATE__", () => state), type: "text/html" };
|
|
168869
169405
|
}
|
|
@@ -168881,7 +169417,7 @@ var createDashboardServer = (props) => {
|
|
|
168881
169417
|
EventVersion: "1.0",
|
|
168882
169418
|
Sns: {
|
|
168883
169419
|
Type: "Notification",
|
|
168884
|
-
MessageId:
|
|
169420
|
+
MessageId: randomUUID9(),
|
|
168885
169421
|
TopicArn: `arn:aws:sns:${props.region}:000000000000:${topic}`,
|
|
168886
169422
|
Message: typeof message4 === "string" ? message4 : JSON.stringify(message4 ?? {}),
|
|
168887
169423
|
Timestamp: new Date().toISOString(),
|
|
@@ -169032,6 +169568,9 @@ var createDashboardServer = (props) => {
|
|
|
169032
169568
|
if (url.pathname === "/api/emails") {
|
|
169033
169569
|
return { status: 200, body: JSON.stringify({ emails: props.getEmails?.() ?? [] }) };
|
|
169034
169570
|
}
|
|
169571
|
+
if (url.pathname === "/api/alerts") {
|
|
169572
|
+
return { status: 200, body: JSON.stringify({ alerts: props.getAlerts?.() ?? [] }) };
|
|
169573
|
+
}
|
|
169035
169574
|
if (url.pathname.startsWith("/api/auth") && props.auth) {
|
|
169036
169575
|
const auth2 = props.auth;
|
|
169037
169576
|
try {
|
|
@@ -169145,13 +169684,13 @@ var createDashboardServer = (props) => {
|
|
|
169145
169684
|
// src/dev/failure.ts
|
|
169146
169685
|
import { stringify as stringify5 } from "@awsless/json";
|
|
169147
169686
|
import { formatRouteKey as formatRouteKey2, formatRoutePayload as formatRoutePayload2 } from "awsless";
|
|
169148
|
-
import { randomUUID as
|
|
169687
|
+
import { randomUUID as randomUUID10 } from "crypto";
|
|
169149
169688
|
var CONSUMER_ROUTE = formatRouteKey2("base", "on-failure", "consumer");
|
|
169150
169689
|
var createFailureReporter = (props) => {
|
|
169151
169690
|
const format4 = (report) => {
|
|
169152
169691
|
const error3 = report.error;
|
|
169153
169692
|
const base = {
|
|
169154
|
-
id:
|
|
169693
|
+
id: randomUUID10(),
|
|
169155
169694
|
date: new Date,
|
|
169156
169695
|
payload: report.event
|
|
169157
169696
|
};
|
|
@@ -169191,6 +169730,7 @@ var createFailureReporter = (props) => {
|
|
|
169191
169730
|
return (report) => {
|
|
169192
169731
|
const message4 = report.error instanceof Error ? report.error.message : String(report.error);
|
|
169193
169732
|
props.log(`${report.routeKey ?? report.queue?.name ?? "async invoke"} failed: ${message4}`);
|
|
169733
|
+
props.onReport?.(report);
|
|
169194
169734
|
if (!props.enabled) {
|
|
169195
169735
|
return;
|
|
169196
169736
|
}
|
|
@@ -169383,7 +169923,7 @@ var startDev = async (props) => {
|
|
|
169383
169923
|
const log = props.onLog ?? (() => {});
|
|
169384
169924
|
const phase = props.phase ?? (async ({ start }, fn) => (log(start), fn(() => {})));
|
|
169385
169925
|
const { appConfig, stackConfigs } = props;
|
|
169386
|
-
|
|
169926
|
+
const startedAt = Date.now();
|
|
169387
169927
|
const { builders, appId, ready: ready2 } = createApp({
|
|
169388
169928
|
appConfig,
|
|
169389
169929
|
stackConfigs,
|
|
@@ -169400,6 +169940,9 @@ var startDev = async (props) => {
|
|
|
169400
169940
|
props.pool.begin();
|
|
169401
169941
|
await props.pool.keep("session", null, async () => ({ value: true, stop: () => {} }));
|
|
169402
169942
|
const dev = createDevContext({ appConfig, stackConfigs, appId, routerPorts, log, pool: props.pool });
|
|
169943
|
+
setDebugSink((type2, message4) => {
|
|
169944
|
+
dev.events.emit("debug", { date: Date.now(), line: message4, error: type2 === "error" });
|
|
169945
|
+
});
|
|
169403
169946
|
const bundleName = getBundleFunctionName(appConfig.name);
|
|
169404
169947
|
const buildDir = getBuildPath("bundle", bundleName, ".");
|
|
169405
169948
|
const { env: env4, lambda } = await phase({ start: "Preparing the local resources...", done: "Prepared the local resources" }, async (detail) => {
|
|
@@ -169511,12 +170054,14 @@ var startDev = async (props) => {
|
|
|
169511
170054
|
restartNeeded = true;
|
|
169512
170055
|
await worker.restart();
|
|
169513
170056
|
restartNeeded = false;
|
|
170057
|
+
dev.context.reportHealth("workers", "up", String(worker.size()));
|
|
169514
170058
|
log(`Reloaded the bundle in ${Date.now() - started}ms (build ${built - started}ms, worker ${Date.now() - built}ms)`);
|
|
169515
170059
|
} else if (!changed) {
|
|
169516
170060
|
debug(`Rebuild found no changes in ${Date.now() - started}ms`);
|
|
169517
170061
|
}
|
|
169518
170062
|
} catch (error3) {
|
|
169519
170063
|
dirty = true;
|
|
170064
|
+
dev.context.reportHealth("workers", "down", error3 instanceof Error ? error3.message : String(error3));
|
|
169520
170065
|
throw error3;
|
|
169521
170066
|
} finally {
|
|
169522
170067
|
fresh = undefined;
|
|
@@ -169524,14 +170069,62 @@ var startDev = async (props) => {
|
|
|
169524
170069
|
})();
|
|
169525
170070
|
await fresh;
|
|
169526
170071
|
};
|
|
170072
|
+
const describeDispatch = (event) => {
|
|
170073
|
+
const payload = event;
|
|
170074
|
+
const route = payload?.["$awsless-route"];
|
|
170075
|
+
if (typeof route === "string") {
|
|
170076
|
+
return route;
|
|
170077
|
+
}
|
|
170078
|
+
const record = payload?.Records?.[0];
|
|
170079
|
+
if (record?.eventSource === "aws:sqs") {
|
|
170080
|
+
return "queue " + String(record.eventSourceARN ?? "").split(":").at(-1);
|
|
170081
|
+
}
|
|
170082
|
+
if (record?.EventSource === "aws:sns") {
|
|
170083
|
+
return "topic " + String(record.Sns?.TopicArn ?? "").split(":").at(-1);
|
|
170084
|
+
}
|
|
170085
|
+
if (record?.eventSource === "aws:s3") {
|
|
170086
|
+
return "store " + String(record.s3?.bucket?.name ?? "");
|
|
170087
|
+
}
|
|
170088
|
+
if (String(record?.eventSourceARN ?? "").includes(":dynamodb:")) {
|
|
170089
|
+
return "stream " + (String(record.eventSourceARN).split("table/")[1]?.split("/")[0] ?? "table");
|
|
170090
|
+
}
|
|
170091
|
+
const header = payload?.headers?.[ROUTE_HEADER];
|
|
170092
|
+
if (typeof header === "string") {
|
|
170093
|
+
return header;
|
|
170094
|
+
}
|
|
170095
|
+
return "invoke";
|
|
170096
|
+
};
|
|
169527
170097
|
const dispatch = async (event) => {
|
|
169528
170098
|
await ensureFresh();
|
|
169529
|
-
|
|
170099
|
+
const started = Date.now();
|
|
170100
|
+
const route = describeDispatch(event);
|
|
170101
|
+
try {
|
|
170102
|
+
const result = await worker.dispatch(event);
|
|
170103
|
+
dev.events.emit("activity", { date: started, route, ms: Date.now() - started, ok: true });
|
|
170104
|
+
return result;
|
|
170105
|
+
} catch (error3) {
|
|
170106
|
+
dev.events.emit("activity", {
|
|
170107
|
+
date: started,
|
|
170108
|
+
route,
|
|
170109
|
+
ms: Date.now() - started,
|
|
170110
|
+
ok: false,
|
|
170111
|
+
error: error3 instanceof Error ? error3.message : String(error3)
|
|
170112
|
+
});
|
|
170113
|
+
throw error3;
|
|
170114
|
+
}
|
|
169530
170115
|
};
|
|
169531
170116
|
const reportFailure = createFailureReporter({
|
|
169532
170117
|
enabled: Boolean(appConfig.onFailure),
|
|
169533
170118
|
dispatch,
|
|
169534
|
-
log
|
|
170119
|
+
log,
|
|
170120
|
+
onReport(report) {
|
|
170121
|
+
dev.events.emit("problems", {
|
|
170122
|
+
date: Date.now(),
|
|
170123
|
+
kind: report.kind,
|
|
170124
|
+
title: report.routeKey ?? report.queue?.name ?? "async invoke",
|
|
170125
|
+
detail: report.error instanceof Error ? report.error.message : String(report.error)
|
|
170126
|
+
});
|
|
170127
|
+
}
|
|
169535
170128
|
});
|
|
169536
170129
|
lambda.connect(dispatch, reportFailure);
|
|
169537
170130
|
await phase({ start: "Starting the local servers...", done: "Started the local servers" }, async (detail) => {
|
|
@@ -169546,9 +170139,11 @@ var startDev = async (props) => {
|
|
|
169546
170139
|
await phase({ start: "Starting the bundle worker...", done: "Started the bundle worker" }, async (detail) => {
|
|
169547
170140
|
try {
|
|
169548
170141
|
await worker.start();
|
|
170142
|
+
dev.context.reportHealth("workers", "up", String(worker.size()));
|
|
169549
170143
|
} catch (error3) {
|
|
169550
170144
|
detail("FAILED - the next invoke retries");
|
|
169551
170145
|
log(`The bundle worker failed to start: ${error3 instanceof Error ? error3.message : String(error3)}`);
|
|
170146
|
+
dev.context.reportHealth("workers", "down", error3 instanceof Error ? error3.message : String(error3));
|
|
169552
170147
|
dirty = true;
|
|
169553
170148
|
restartNeeded = true;
|
|
169554
170149
|
}
|
|
@@ -169583,6 +170178,12 @@ var startDev = async (props) => {
|
|
|
169583
170178
|
process.stderr.write(`Route ${routeKey} failed: ${detail}
|
|
169584
170179
|
`);
|
|
169585
170180
|
emitWorkerLine(`Route ${routeKey} failed: ${detail}`, true, routeKey);
|
|
170181
|
+
dev.events.emit("problems", {
|
|
170182
|
+
date: Date.now(),
|
|
170183
|
+
kind: "route",
|
|
170184
|
+
title: routeKey,
|
|
170185
|
+
detail: error3 instanceof Error ? error3.message : String(error3)
|
|
170186
|
+
});
|
|
169586
170187
|
}
|
|
169587
170188
|
}));
|
|
169588
170189
|
}
|
|
@@ -169601,6 +170202,9 @@ var startDev = async (props) => {
|
|
|
169601
170202
|
storeRoot: join57(directories.output, "local", "store"),
|
|
169602
170203
|
configFile: join57(directories.output, "local", "config.json"),
|
|
169603
170204
|
getEmails: () => props.pool.peek("shim:ses-email")?.server.list() ?? [],
|
|
170205
|
+
getAlerts: () => props.pool.peek("shim:sns")?.alerts ?? [],
|
|
170206
|
+
getSession: () => ({ startedAt, workers: worker.size() }),
|
|
170207
|
+
getHealth: () => [...dev.health.values()],
|
|
169604
170208
|
configPulled: Object.keys(props.pool.peek("config:pull") ?? {}),
|
|
169605
170209
|
auth: createAuthAdmin({
|
|
169606
170210
|
appConfig,
|
|
@@ -169630,9 +170234,13 @@ var startDev = async (props) => {
|
|
|
169630
170234
|
if (stopping) {
|
|
169631
170235
|
return;
|
|
169632
170236
|
}
|
|
169633
|
-
worker.restart().then(() =>
|
|
170237
|
+
worker.restart().then(() => {
|
|
170238
|
+
dev.context.reportHealth("workers", "up", String(worker.size()));
|
|
170239
|
+
log("Restarted the bundle worker.");
|
|
170240
|
+
}).catch((error3) => {
|
|
169634
170241
|
restartNeeded = true;
|
|
169635
170242
|
dirty = true;
|
|
170243
|
+
dev.context.reportHealth("workers", "down", error3 instanceof Error ? error3.message : String(error3));
|
|
169636
170244
|
log(`The bundle worker failed to restart: ${error3 instanceof Error ? error3.message : String(error3)}`);
|
|
169637
170245
|
});
|
|
169638
170246
|
});
|
|
@@ -177005,7 +177613,7 @@ ${job.error.stack.split(`
|
|
|
177005
177613
|
stream2.shift();
|
|
177006
177614
|
} else if (stream2.length > 0) {
|
|
177007
177615
|
this._BOMseen = true;
|
|
177008
|
-
}
|
|
177616
|
+
} else {}
|
|
177009
177617
|
}
|
|
177010
177618
|
return codePointsToString(stream2);
|
|
177011
177619
|
}
|
|
@@ -185685,7 +186293,7 @@ var formatLog = (level, date2, origin, message4) => {
|
|
|
185685
186293
|
import { DeleteObjectsCommand, ListObjectsV2Command, S3Client as S3Client5 } from "@aws-sdk/client-s3";
|
|
185686
186294
|
|
|
185687
186295
|
// src/formation/cloudfront.ts
|
|
185688
|
-
import { randomUUID as
|
|
186296
|
+
import { randomUUID as randomUUID11 } from "crypto";
|
|
185689
186297
|
var createInvalidationForDistributionTenants = async (client, props) => {
|
|
185690
186298
|
let cursor;
|
|
185691
186299
|
do {
|
|
@@ -185705,7 +186313,7 @@ var createInvalidationForDistributionTenants = async (client, props) => {
|
|
|
185705
186313
|
Quantity: props.paths.length,
|
|
185706
186314
|
Items: props.paths
|
|
185707
186315
|
},
|
|
185708
|
-
CallerReference:
|
|
186316
|
+
CallerReference: randomUUID11()
|
|
185709
186317
|
}
|
|
185710
186318
|
}));
|
|
185711
186319
|
}
|