@awsless/cli 0.1.11 → 0.1.13

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 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: __accessProp.bind(mod, key),
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 = (__moduleCache ??= new WeakMap).get(from), desc;
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
- for (var key of __getOwnPropNames(from))
41
- if (!__hasOwnProp.call(entry, key))
42
- __defProp(entry, key, {
43
- get: __accessProp.bind(from, key),
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: __exportSetter.bind(all, name)
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/work/Code/awsless/node_modules/.pnpm/msgpackr-extract@3.0.4/node_modules/msgpackr-extract";
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/work/Code/awsless/node_modules/.pnpm/@grpc+grpc-js@1.12.6/node_modules/@grpc/grpc-js/build/src";
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/work/Code/awsless/node_modules/.pnpm/ioredis@5.10.1_supports-color@8.1.1/node_modules/ioredis/built/utils";
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/work/Code/awsless/node_modules/.pnpm/ioredis@5.10.1_supports-color@8.1.1/node_modules/ioredis/built";
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/work/Code/awsless/node_modules/.pnpm/redis-memory-server@0.16.1_supports-color@8.1.1/node_modules/redis-memory-server/lib/util";
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) {
@@ -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);
@@ -114515,7 +114494,7 @@ var getSanitizedDevTypeScriptVersion = (version2 = "") => {
114515
114494
  };
114516
114495
 
114517
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
114518
- var __dirname = "/Users/work/Code/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";
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";
114519
114498
  var tscVersion;
114520
114499
  var TS_PACKAGE_JSON = join7("node_modules", "typescript", "package.json");
114521
114500
  var getTypeScriptUserAgentPair = async () => {
@@ -131592,17 +131571,6 @@ var $forEachNodeInTopologicalOrder = sort.forEachNodeInTopologicalOrder;
131592
131571
  var $topologicalSort = sort.topologicalSort;
131593
131572
  var $topologicalGenerations = sort.topologicalGenerations;
131594
131573
  var $forEachTopologicalGeneration = sort.forEachTopologicalGeneration;
131595
- // ../../node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm/sha1.js
131596
- import { createHash as createHash3 } from "crypto";
131597
- function sha1(bytes) {
131598
- if (Array.isArray(bytes)) {
131599
- bytes = Buffer.from(bytes);
131600
- } else if (typeof bytes === "string") {
131601
- bytes = Buffer.from(bytes, "utf8");
131602
- }
131603
- return createHash3("sha1").update(bytes).digest();
131604
- }
131605
- var sha1_default = sha1;
131606
131574
 
131607
131575
  // ../../node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm/regex.js
131608
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;
@@ -131668,6 +131636,18 @@ function v35(version2, hash, value, namespace, buf, offset) {
131668
131636
  return unsafeStringify(bytes);
131669
131637
  }
131670
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
+
131671
131651
  // ../../node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm/v5.js
131672
131652
  function v5(value, namespace, buf, offset) {
131673
131653
  return v35(80, sha1_default, value, namespace, buf, offset);
@@ -141133,6 +141113,8 @@ if (!nativeAccelerationDisabled) {
141133
141113
  try {
141134
141114
  if (true)
141135
141115
  extractor = require_msgpackr_extract();
141116
+ else
141117
+ ;
141136
141118
  if (extractor)
141137
141119
  setExtractor(extractor.extractStrings);
141138
141120
  } catch (error3) {}
@@ -155087,8 +155069,19 @@ import { readFile as readFile12 } from "fs/promises";
155087
155069
  import { createServer as createServer2 } from "http";
155088
155070
 
155089
155071
  // src/dev/util.ts
155072
+ import { randomBytes } from "crypto";
155090
155073
  import { createServer } from "net";
155091
155074
  var LOCAL_ACCOUNT_ID = "000000000000";
155075
+ var TRACE_HEADER = "x-awsless-trace";
155076
+ var traceId = () => randomBytes(4).toString("hex");
155077
+ var formatTraceHeader = (trace) => `${trace.traceId}:${trace.spanId}`;
155078
+ var parseTraceHeader = (value) => {
155079
+ if (typeof value !== "string") {
155080
+ return;
155081
+ }
155082
+ const [traceId2, spanId] = value.split(":");
155083
+ return traceId2 && spanId ? { traceId: traceId2, spanId } : undefined;
155084
+ };
155092
155085
  var readBody = (req) => {
155093
155086
  return new Promise((resolve3, reject) => {
155094
155087
  const chunks = [];
@@ -157381,7 +157374,7 @@ var createSnsServer = (props) => {
157381
157374
  let closeServer;
157382
157375
  let dispatch;
157383
157376
  let reportFailure;
157384
- const publish2 = (input) => {
157377
+ const publish2 = (input, trace) => {
157385
157378
  const messageId = randomUUID4();
157386
157379
  for (const capture of props?.captures ?? []) {
157387
157380
  if (capture(input)) {
@@ -157414,7 +157407,7 @@ var createSnsServer = (props) => {
157414
157407
  ]
157415
157408
  };
157416
157409
  setImmediate(() => {
157417
- dispatch?.(event).catch((error3) => {
157410
+ dispatch?.(event, trace).catch((error3) => {
157418
157411
  reportFailure?.({ kind: "async", event, error: error3 });
157419
157412
  });
157420
157413
  });
@@ -157445,7 +157438,7 @@ var createSnsServer = (props) => {
157445
157438
  res.end(`The local dev sns emulator only supports Publish, got: ${action}`);
157446
157439
  return;
157447
157440
  }
157448
- const messageId = publish2(input);
157441
+ const messageId = publish2(input, parseTraceHeader(req.headers[TRACE_HEADER]));
157449
157442
  if (isJson) {
157450
157443
  res.writeHead(200, { "content-type": "application/x-amz-json-1.0" });
157451
157444
  res.end(JSON.stringify({ MessageId: messageId }));
@@ -158283,7 +158276,7 @@ var startDevRouter = async (props) => {
158283
158276
  const sourceIp = server2.requestIP(request)?.address ?? "127.0.0.1";
158284
158277
  let result;
158285
158278
  try {
158286
- result = await props.dispatch(formatWebEvent(request, route, body, url, sourceIp));
158279
+ result = await props.dispatch(formatWebEvent(request, route, body, url, sourceIp), parseTraceHeader(request.headers.get(TRACE_HEADER)));
158287
158280
  } catch (error3) {
158288
158281
  props.onError?.(error3, route.routeKey);
158289
158282
  const detail = error3 instanceof Error ? error3.stack ?? error3.message : String(error3);
@@ -158445,7 +158438,7 @@ var createRestServer = (props) => {
158445
158438
  },
158446
158439
  body: body.length > 0 ? body.toString("base64") : undefined,
158447
158440
  isBase64Encoded: body.length > 0
158448
- });
158441
+ }, parseTraceHeader(req.headers[TRACE_HEADER]));
158449
158442
  writeWebResponse(res, result);
158450
158443
  };
158451
158444
  return {
@@ -159802,12 +159795,12 @@ var tableOnDev = async (ctx) => {
159802
159795
  if (props.stream) {
159803
159796
  const routeKey = formatRouteKey(stackName, "table", id);
159804
159797
  const eventSourceARN = `arn:aws:dynamodb:${ctx.appConfig.region}:000000000000:table/${name}/stream/local`;
159805
- const unsubscribe = server.onStreamRecord(name, (record) => {
159798
+ const unsubscribe = server.onStreamRecord(name, (record, context) => {
159806
159799
  if (isWiping()) {
159807
159800
  return;
159808
159801
  }
159809
159802
  const event = { Records: [{ ...record, eventSourceARN }] };
159810
- dispatch(event).catch((error3) => {
159803
+ dispatch(event, parseTraceHeader(context)).catch((error3) => {
159811
159804
  reportFailure({
159812
159805
  kind: "stream",
159813
159806
  routeKey,
@@ -160026,8 +160019,9 @@ var createSchedulerServer = () => {
160026
160019
  const name = decodeURIComponent(match3[1]);
160027
160020
  const input = JSON.parse(body.toString() || "{}");
160028
160021
  const payload = input.Target?.Input ? JSON.parse(input.Target.Input) : {};
160022
+ const trace = parseTraceHeader(req.headers[TRACE_HEADER]);
160029
160023
  setImmediate(() => {
160030
- dispatch?.(payload).catch((error3) => {
160024
+ dispatch?.(payload, trace).catch((error3) => {
160031
160025
  const routeKey = payload?.["$awsless-route"];
160032
160026
  reportFailure?.({
160033
160027
  kind: "async",
@@ -166599,7 +166593,7 @@ var createS3Server = (props) => {
166599
166593
  let closeServer;
166600
166594
  let dispatch;
166601
166595
  let reportFailure;
166602
- const notify = (eventName, bucket, key, size2, eTag) => {
166596
+ const notify = (eventName, bucket, key, size2, eTag, trace) => {
166603
166597
  for (const rule of props.rules) {
166604
166598
  const matches = rule.events.some((event2) => {
166605
166599
  const type2 = event2.replace(/^s3:/, "");
@@ -166634,7 +166628,7 @@ var createS3Server = (props) => {
166634
166628
  }
166635
166629
  ]
166636
166630
  };
166637
- dispatch?.(event).catch((error3) => {
166631
+ dispatch?.(event, trace).catch((error3) => {
166638
166632
  reportFailure?.({ kind: "async", routeKey: rule.id, event, error: error3 });
166639
166633
  });
166640
166634
  }
@@ -166701,7 +166695,7 @@ var createS3Server = (props) => {
166701
166695
  const eTag = createHash22("md5").update(body).digest("hex");
166702
166696
  res.writeHead(200, { etag: `"${eTag}"` });
166703
166697
  res.end();
166704
- notify("ObjectCreated:Put", bucket, key, body.length, eTag);
166698
+ notify("ObjectCreated:Put", bucket, key, body.length, eTag, parseTraceHeader(req.headers[TRACE_HEADER]));
166705
166699
  return;
166706
166700
  }
166707
166701
  if (req.method === "GET" || req.method === "HEAD") {
@@ -166724,7 +166718,7 @@ var createS3Server = (props) => {
166724
166718
  await rm10(file2, { force: true });
166725
166719
  res.writeHead(204);
166726
166720
  res.end();
166727
- notify("ObjectRemoved:Delete", bucket, key, 0, "");
166721
+ notify("ObjectRemoved:Delete", bucket, key, 0, "", parseTraceHeader(req.headers[TRACE_HEADER]));
166728
166722
  return;
166729
166723
  }
166730
166724
  res.writeHead(501, { "content-type": "application/xml" });
@@ -166814,7 +166808,7 @@ var createSqsServer = (props) => {
166814
166808
  }
166815
166809
  return stores.get(queue);
166816
166810
  };
166817
- const deliver = (queue, input, messageId) => {
166811
+ const deliver = (queue, input, messageId, trace) => {
166818
166812
  const now = Date.now();
166819
166813
  if (props.queues.get(queue) === undefined) {
166820
166814
  storeOf(queue).push({
@@ -166848,7 +166842,7 @@ var createSqsServer = (props) => {
166848
166842
  ]
166849
166843
  };
166850
166844
  const send = () => {
166851
- dispatch?.(event).catch((error3) => {
166845
+ dispatch?.(event, trace).catch((error3) => {
166852
166846
  let body = input.MessageBody;
166853
166847
  try {
166854
166848
  body = JSON.parse(input.MessageBody ?? "");
@@ -166894,16 +166888,16 @@ var createSqsServer = (props) => {
166894
166888
  QueueUrl: queueUrl(input.QueueName)
166895
166889
  };
166896
166890
  },
166897
- SendMessage(input) {
166891
+ SendMessage(input, _signal, trace) {
166898
166892
  const queue = queueFromUrl(input.QueueUrl);
166899
166893
  if (!queue) {
166900
166894
  throw new Error(`Unknown local queue: ${input.QueueUrl}`);
166901
166895
  }
166902
166896
  const messageId = randomUUID8();
166903
- deliver(queue, input, messageId);
166897
+ deliver(queue, input, messageId, trace);
166904
166898
  return sendResult(input, messageId);
166905
166899
  },
166906
- SendMessageBatch(input) {
166900
+ SendMessageBatch(input, _signal, trace) {
166907
166901
  const queue = queueFromUrl(input.QueueUrl);
166908
166902
  if (!queue) {
166909
166903
  throw new Error(`Unknown local queue: ${input.QueueUrl}`);
@@ -166911,7 +166905,7 @@ var createSqsServer = (props) => {
166911
166905
  return {
166912
166906
  Successful: (input.Entries ?? []).map((entry) => {
166913
166907
  const messageId = randomUUID8();
166914
- deliver(queue, entry, messageId);
166908
+ deliver(queue, entry, messageId, trace);
166915
166909
  return {
166916
166910
  Id: entry.Id,
166917
166911
  ...sendResult(entry, messageId)
@@ -167043,7 +167037,7 @@ var createSqsServer = (props) => {
167043
167037
  if (!action) {
167044
167038
  throw new Error(`The local dev sqs emulator does not support: ${target2}`);
167045
167039
  }
167046
- const result = await action(JSON.parse(body.toString() || "{}"), abort.signal);
167040
+ const result = await action(JSON.parse(body.toString() || "{}"), abort.signal, parseTraceHeader(req.headers[TRACE_HEADER]));
167047
167041
  if (res.writableEnded || res.destroyed) {
167048
167042
  return;
167049
167043
  }
@@ -167341,12 +167335,90 @@ class WorkerError extends Error {
167341
167335
  }
167342
167336
  }
167343
167337
  }
167344
- var WORKER_ENTRY = `import { createServer } from 'node:http'
167338
+ var WORKER_ENTRY = `import { AsyncLocalStorage } from 'node:async_hooks'
167339
+ import http from 'node:http'
167340
+ import https from 'node:https'
167341
+ import { createServer } from 'node:http'
167342
+ import { syncBuiltinESMExports } from 'node:module'
167345
167343
  import { format } from 'node:util'
167346
167344
 
167347
167345
  let handler
167348
167346
  let getCurrentRoute = () => undefined
167349
167347
 
167348
+ // The trace of the running invocation, set per dispatch by the dev
167349
+ // server. The async context keeps it accurate under concurrent
167350
+ // requests, exactly like the route context.
167351
+ const traceContext = new AsyncLocalStorage()
167352
+
167353
+ const isLoopback = host => host === '127.0.0.1' || host === 'localhost' || host === '::1'
167354
+
167355
+ // Outgoing requests to the local emulators carry the active trace as a
167356
+ // header, so a queue send or task invoke made by a handler links the
167357
+ // dispatch it causes back to this invocation. Only loopback targets:
167358
+ // a request to a real external api must never see the header.
167359
+ const injectTrace = module => {
167360
+ const original = module.request
167361
+
167362
+ module.request = function (...args) {
167363
+ const trace = traceContext.getStore()
167364
+
167365
+ if (trace) {
167366
+ // request(url[, options][, callback]) or request(options[, callback])
167367
+ const index = typeof args[0] === 'string' || args[0] instanceof URL ? 1 : 0
167368
+ let url
167369
+
167370
+ try {
167371
+ url = index === 1 ? new URL(String(args[0])) : undefined
167372
+ } catch (_) {}
167373
+
167374
+ let options = args[index]
167375
+
167376
+ if (typeof options === 'function' || options === undefined) {
167377
+ args.splice(index, 0, {})
167378
+ options = args[index]
167379
+ }
167380
+
167381
+ const host = String(url?.hostname ?? options.hostname ?? options.host ?? '').split(':')[0]
167382
+
167383
+ if (isLoopback(host)) {
167384
+ args[index] = { ...options, headers: { ...options.headers, 'x-awsless-trace': trace } }
167385
+ }
167386
+ }
167387
+
167388
+ return original.apply(this, args)
167389
+ }
167390
+ }
167391
+
167392
+ injectTrace(http)
167393
+ injectTrace(https)
167394
+
167395
+ // The aws sdk grabs request via ESM named imports (like
167396
+ // "const { request } = await import('node:http')"), and ESM named
167397
+ // exports of builtins are snapshots - the sync pushes the patched
167398
+ // functions into those bindings too.
167399
+ syncBuiltinESMExports()
167400
+
167401
+ const originalFetch = globalThis.fetch
167402
+
167403
+ globalThis.fetch = (input, init) => {
167404
+ const trace = traceContext.getStore()
167405
+
167406
+ if (trace) {
167407
+ try {
167408
+ const url = new URL(input instanceof Request ? input.url : String(input))
167409
+
167410
+ if (isLoopback(url.hostname)) {
167411
+ const headers = new Headers(init?.headers ?? (input instanceof Request ? input.headers : undefined))
167412
+
167413
+ headers.set('x-awsless-trace', trace)
167414
+ init = { ...init, headers }
167415
+ }
167416
+ } catch (_) {}
167417
+ }
167418
+
167419
+ return originalFetch(input, init)
167420
+ }
167421
+
167350
167422
  // Every console call writes ONE framed record: an invisible \\x1f
167351
167423
  // marker with the active bundle route & the json-encoded text, so
167352
167424
  // multi-line output stays a single log entry downstream. The route
@@ -167392,12 +167464,12 @@ const server = createServer((req, res) => {
167392
167464
  let response
167393
167465
 
167394
167466
  try {
167395
- const { event, context } = JSON.parse(Buffer.concat(chunks).toString())
167467
+ const { event, context, trace } = JSON.parse(Buffer.concat(chunks).toString())
167396
167468
 
167397
167469
  // Fabricate the parts of the lambda context that only exist
167398
167470
  // at runtime, like the remaining time counter.
167399
167471
  const started = Date.now()
167400
- const result = await handler(event, {
167472
+ const run = () => handler(event, {
167401
167473
  functionName: process.env.AWS_LAMBDA_FUNCTION_NAME,
167402
167474
  functionVersion: process.env.AWS_LAMBDA_FUNCTION_VERSION,
167403
167475
  memoryLimitInMB: '512',
@@ -167406,6 +167478,8 @@ const server = createServer((req, res) => {
167406
167478
  ...context,
167407
167479
  })
167408
167480
 
167481
+ const result = await (trace ? traceContext.run(trace, run) : run())
167482
+
167409
167483
  response = { result: typeof result === 'undefined' ? null : result }
167410
167484
  } catch (error) {
167411
167485
  response = {
@@ -167537,7 +167611,7 @@ var createBundleWorker = (props) => {
167537
167611
  await doStop();
167538
167612
  await doStart();
167539
167613
  }),
167540
- async dispatch(event) {
167614
+ async dispatch(event, trace) {
167541
167615
  if (workers.length === 0) {
167542
167616
  throw new Error("The bundle worker is not running.");
167543
167617
  }
@@ -167546,7 +167620,7 @@ var createBundleWorker = (props) => {
167546
167620
  try {
167547
167621
  const res = await fetch(`http://127.0.0.1:${worker.port}`, {
167548
167622
  method: "POST",
167549
- body: JSON.stringify({ event, context })
167623
+ body: JSON.stringify({ event, context, trace })
167550
167624
  });
167551
167625
  const body = await res.json();
167552
167626
  if (body.error) {
@@ -167569,36 +167643,51 @@ var dashboardHtml = `<!doctype html>
167569
167643
  <title>awsless dev</title>
167570
167644
  <style>
167571
167645
  :root {
167572
- --bg: #0f1115;
167573
- --panel: #171a21;
167574
- --border: #262b36;
167575
- --text: #d7dae0;
167576
- --muted: #7d8590;
167646
+ --bg: hsl(220 20% 5% / 1);
167647
+ --panel: hsl(220 20% 8%);
167648
+ --hover: hsl(220 20% 12%);
167649
+ --border: hsl(220 18% 15%);
167650
+ --border-strong: hsl(220 16% 22%);
167651
+ --text: #ecedf2;
167652
+ --muted: #8b90a1;
167577
167653
  --accent: #ff9000;
167578
- --good: #3fb950;
167579
- --bad: #f85149;
167654
+ --good: #3dd68c;
167655
+ --bad: #ff6166;
167656
+ --font-sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Inter', Helvetica, Arial, sans-serif;
167657
+ --font-mono: ui-monospace, 'SF Mono', SFMono-Regular, Menlo, Consolas, monospace;
167580
167658
  font-size: 14px;
167659
+ color-scheme: dark;
167581
167660
  }
167582
167661
  * { box-sizing: border-box; }
167662
+ ::selection { background: rgb(255 144 0 / 25%); }
167663
+ ::-webkit-scrollbar { width: 8px; height: 8px; }
167664
+ ::-webkit-scrollbar-track { background: transparent; }
167665
+ ::-webkit-scrollbar-thumb { background: rgb(255 255 255 / 10%); border-radius: 999px; }
167666
+ ::-webkit-scrollbar-thumb:hover { background: rgb(255 255 255 / 18%); }
167667
+ :focus-visible { outline: 2px solid rgb(255 144 0 / 55%); outline-offset: 1px; }
167583
167668
  body {
167584
167669
  margin: 0;
167585
- font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
167670
+ font-family: var(--font-sans);
167671
+ -webkit-font-smoothing: antialiased;
167586
167672
  background: var(--bg);
167587
167673
  color: var(--text);
167588
167674
  display: grid;
167589
- grid-template-columns: 220px 1fr;
167675
+ grid-template-columns: 232px 1fr;
167590
167676
  height: 100vh;
167591
167677
  }
167592
- body.with-events { grid-template-columns: 220px 1fr 320px; }
167678
+ body.with-events { grid-template-columns: 232px 1fr 320px; }
167679
+ button { transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease; }
167680
+ input, select, textarea { transition: border-color 0.15s ease, box-shadow 0.15s ease; }
167593
167681
  aside {
167594
167682
  border-left: 1px solid var(--border);
167595
167683
  overflow-y: auto;
167596
167684
  padding: 12px;
167597
167685
  }
167598
167686
  aside h3 {
167599
- font-size: 11px;
167687
+ font-size: 10px;
167688
+ font-weight: 500;
167600
167689
  text-transform: uppercase;
167601
- letter-spacing: 1px;
167690
+ letter-spacing: 0.08em;
167602
167691
  color: var(--muted);
167603
167692
  margin: 8px 8px 12px;
167604
167693
  }
@@ -167606,34 +167695,45 @@ var dashboardHtml = `<!doctype html>
167606
167695
  border-bottom: 1px solid var(--border);
167607
167696
  padding: 8px;
167608
167697
  font-size: 12px;
167698
+ font-family: var(--font-mono);
167609
167699
  }
167700
+ aside .event:last-child { border-bottom: none; }
167610
167701
  aside .event .head { display: flex; gap: 8px; align-items: baseline; }
167611
167702
  aside .event .time { color: var(--muted); }
167612
- aside .event .topic { font-weight: bold; }
167703
+ aside .event .topic { font-weight: 600; }
167613
167704
  aside .event .type { color: var(--muted); }
167614
167705
  aside .event .body {
167615
167706
  color: var(--muted);
167616
167707
  margin-top: 4px;
167617
- word-break: break-word;
167708
+ white-space: nowrap;
167709
+ overflow: hidden;
167710
+ text-overflow: ellipsis;
167711
+ }
167712
+ /* Hovering an event unfolds its payload in place, fully wrapped -
167713
+ the same behavior as the activity feed. */
167714
+ aside .event:hover .body {
167618
167715
  white-space: pre-wrap;
167716
+ overflow: visible;
167717
+ word-break: break-word;
167619
167718
  }
167620
167719
  aside .empty { padding: 8px; }
167621
167720
  .logs {
167622
167721
  background: var(--panel);
167623
167722
  border: 1px solid var(--border);
167624
- border-radius: 6px;
167625
- padding: 8px;
167723
+ border-radius: 10px;
167724
+ padding: 10px 12px;
167626
167725
  margin-top: 8px;
167627
167726
  max-height: 420px;
167628
167727
  overflow-y: auto;
167629
167728
  font-size: 12px;
167729
+ font-family: var(--font-mono);
167630
167730
  }
167631
167731
  .logs .line { display: flex; gap: 8px; padding: 1px 0; }
167632
167732
  .logs .time { color: var(--muted); flex-shrink: 0; }
167633
167733
  .logs .route { color: var(--accent); word-break: break-all; }
167634
167734
  .logs .text { white-space: pre-wrap; word-break: break-word; }
167635
167735
  .logs .line.error .text, .logs .entry.error .text { color: var(--bad); }
167636
- .logs .entry { padding: 4px 0; }
167736
+ .logs .entry { padding: 6px 0; }
167637
167737
  .logs .entry + .entry, .logs .line + .entry, .logs .entry + .line { border-top: 1px solid var(--border); }
167638
167738
  .logs .entry .meta { display: flex; gap: 8px; margin-bottom: 2px; }
167639
167739
  /* Every group is its own card, with a shared grid inside: the name
@@ -167643,8 +167743,8 @@ var dashboardHtml = `<!doctype html>
167643
167743
  .config-group {
167644
167744
  background: var(--panel);
167645
167745
  border: 1px solid var(--border);
167646
- border-radius: 8px;
167647
- padding: 14px 16px;
167746
+ border-radius: 10px;
167747
+ padding: 16px 18px;
167648
167748
  }
167649
167749
  .config-group h3 { margin: 0 0 12px; }
167650
167750
  .config-fields {
@@ -167654,7 +167754,7 @@ var dashboardHtml = `<!doctype html>
167654
167754
  align-items: center;
167655
167755
  }
167656
167756
  .config-fields .field { display: contents; }
167657
- .config-fields .name { color: var(--muted); overflow-wrap: anywhere; }
167757
+ .config-fields .name { color: var(--muted); overflow-wrap: anywhere; font-family: var(--font-mono); font-size: 12.5px; }
167658
167758
  .config-fields input {
167659
167759
  background: var(--bg);
167660
167760
  color: var(--text);
@@ -167663,17 +167763,23 @@ var dashboardHtml = `<!doctype html>
167663
167763
  padding: 6px 10px;
167664
167764
  font: inherit;
167665
167765
  }
167766
+ .config-fields input:hover { border-color: var(--border-strong); }
167767
+ .config-fields input:focus { border-color: #5b6272; box-shadow: 0 0 0 3px rgb(255 255 255 / 14%); outline: none; }
167666
167768
  .config-fields input::placeholder { color: var(--muted); }
167667
167769
  .groups { display: flex; flex-wrap: wrap; gap: 4px 16px; }
167668
167770
  .groups .group { display: flex; align-items: center; gap: 4px; cursor: pointer; }
167669
167771
  nav {
167670
167772
  border-right: 1px solid var(--border);
167671
167773
  overflow-y: auto;
167672
- padding: 12px;
167774
+ padding: 14px 12px;
167775
+ /* The menu scrolls, but never shows a permanent scrollbar. */
167776
+ scrollbar-width: none;
167673
167777
  }
167778
+ nav::-webkit-scrollbar { display: none; }
167674
167779
  nav h1 {
167675
167780
  font-size: 15px;
167676
- margin: 4px 8px 16px;
167781
+ font-family: var(--font-mono);
167782
+ margin: 4px 8px 18px;
167677
167783
  cursor: pointer;
167678
167784
  }
167679
167785
  /* The same two-tone logo as the cli: bold AWS in the brand orange,
@@ -167683,25 +167789,27 @@ var dashboardHtml = `<!doctype html>
167683
167789
  nav h1 .cmd { color: var(--muted); font-weight: normal; }
167684
167790
  nav h3 {
167685
167791
  font-size: 10px;
167792
+ font-weight: 500;
167686
167793
  text-transform: uppercase;
167687
- letter-spacing: 1px;
167794
+ letter-spacing: 0.08em;
167688
167795
  color: var(--muted);
167689
- margin: 14px 8px 4px;
167796
+ margin: 18px 8px 6px;
167690
167797
  }
167691
167798
  nav button {
167692
167799
  display: flex;
167693
167800
  align-items: center;
167694
- gap: 8px;
167801
+ gap: 9px;
167695
167802
  width: 100%;
167696
167803
  background: none;
167697
167804
  border: none;
167698
- color: var(--text);
167805
+ color: var(--muted);
167699
167806
  font: inherit;
167807
+ font-size: 13.5px;
167700
167808
  padding: 6px 8px;
167701
167809
  border-radius: 6px;
167702
167810
  cursor: pointer;
167703
167811
  }
167704
- nav button .count { margin-left: auto; }
167812
+ nav button .count { margin-left: auto; font-size: 12px; }
167705
167813
  nav button.reseed { margin-top: auto; color: var(--muted); }
167706
167814
  nav button.reseed:disabled { cursor: default; }
167707
167815
  .icon {
@@ -167710,34 +167818,37 @@ var dashboardHtml = `<!doctype html>
167710
167818
  flex-shrink: 0;
167711
167819
  display: inline-flex;
167712
167820
  color: var(--muted);
167821
+ transition: color 0.15s ease;
167713
167822
  }
167714
167823
  .icon svg { width: 100%; height: 100%; }
167715
167824
  nav button.active .icon, .row:hover .icon { color: var(--accent); }
167716
- main h2 { display: flex; align-items: center; gap: 8px; }
167717
- main h2 .icon { width: 17px; height: 17px; }
167718
- nav button:hover { background: var(--panel); }
167719
- nav button.active { background: var(--panel); color: var(--accent); }
167825
+ main h2 { display: flex; align-items: center; gap: 9px; }
167826
+ main h2 .icon { width: 18px; height: 18px; }
167827
+ nav button:hover { background: var(--hover); color: var(--text); }
167828
+ nav button.active { background: var(--hover); color: var(--text); }
167720
167829
  nav button .count { color: var(--muted); }
167721
- main { padding: 20px 24px; overflow-y: auto; }
167722
- main h2 { margin: 0 0 4px; font-size: 16px; }
167723
- main .detail { color: var(--muted); margin-bottom: 16px; word-break: break-all; }
167830
+ main { padding: 24px 28px; overflow-y: auto; }
167831
+ main h2 { margin: 0 0 4px; font-size: 18px; font-weight: 600; letter-spacing: -0.01em; }
167832
+ main .detail { color: var(--muted); margin-bottom: 16px; word-break: break-all; font-size: 13px; }
167724
167833
  main .back {
167725
167834
  display: inline-block;
167726
167835
  background: none;
167727
167836
  border: none;
167728
167837
  color: var(--muted);
167729
167838
  font: inherit;
167839
+ font-size: 13px;
167730
167840
  padding: 0;
167731
167841
  margin-bottom: 12px;
167732
167842
  cursor: pointer;
167733
167843
  }
167734
- main .back:hover { color: var(--accent); }
167844
+ main .back:hover { color: var(--text); }
167735
167845
  main h3 {
167736
167846
  font-size: 11px;
167847
+ font-weight: 500;
167737
167848
  text-transform: uppercase;
167738
- letter-spacing: 1px;
167849
+ letter-spacing: 0.08em;
167739
167850
  color: var(--muted);
167740
- margin: 24px 0 8px;
167851
+ margin: 26px 0 8px;
167741
167852
  }
167742
167853
  .feed .row { cursor: default; }
167743
167854
  .feed .empty { padding: 8px; }
@@ -167750,9 +167861,15 @@ var dashboardHtml = `<!doctype html>
167750
167861
  padding: 6px 10px;
167751
167862
  font: inherit;
167752
167863
  }
167864
+ .filters input:hover, .filters select:hover { border-color: var(--border-strong); }
167865
+ .filters input:focus, .filters select:focus {
167866
+ border-color: #5b6272;
167867
+ box-shadow: 0 0 0 3px rgb(255 255 255 / 14%);
167868
+ outline: none;
167869
+ }
167753
167870
  .filters input { flex: 1; }
167754
167871
  .filters input::placeholder { color: var(--muted); }
167755
- .filters .count { color: var(--muted); align-self: center; white-space: nowrap; }
167872
+ .filters .count { color: var(--muted); align-self: center; white-space: nowrap; font-size: 13px; }
167756
167873
  /* The stack & name columns share one grid across every row, so the
167757
167874
  names line up no matter how long each stack name is. */
167758
167875
  .rows { display: grid; grid-template-columns: fit-content(280px) 1fr auto; }
@@ -167766,15 +167883,29 @@ var dashboardHtml = `<!doctype html>
167766
167883
  text-align: left;
167767
167884
  background: none;
167768
167885
  border: none;
167769
- border-bottom: 1px solid var(--border);
167770
167886
  color: var(--text);
167771
167887
  font: inherit;
167772
- padding: 8px;
167888
+ padding: 9px 10px;
167773
167889
  cursor: pointer;
167890
+ border-radius: 8px;
167891
+ position: relative;
167892
+ transition: background 0.15s ease;
167893
+ }
167894
+ /* The separator is its own straight hairline instead of a border,
167895
+ so the rounded hover highlight never bends the line at the ends. */
167896
+ .row::after {
167897
+ content: '';
167898
+ position: absolute;
167899
+ left: 0;
167900
+ right: 0;
167901
+ bottom: 0;
167902
+ height: 1px;
167903
+ background: var(--border);
167774
167904
  }
167775
- .row:hover { background: var(--panel); }
167905
+ .row:last-child::after { display: none; }
167906
+ .row:hover { background: var(--hover); }
167776
167907
  a.row { text-decoration: none; }
167777
- .health { display: flex; flex-wrap: wrap; gap: 8px; margin: 12px 0 4px; }
167908
+ .health { display: flex; flex-wrap: wrap; gap: 8px; margin: 14px 0 4px; }
167778
167909
  .health .chip {
167779
167910
  display: inline-flex;
167780
167911
  align-items: center;
@@ -167784,9 +167915,16 @@ var dashboardHtml = `<!doctype html>
167784
167915
  border-radius: 999px;
167785
167916
  padding: 4px 12px;
167786
167917
  font-size: 12px;
167918
+ font-family: var(--font-mono);
167787
167919
  }
167788
- .health .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--good); flex-shrink: 0; }
167789
- .health .chip.down { border-color: var(--bad); }
167920
+ .health .dot {
167921
+ width: 7px;
167922
+ height: 7px;
167923
+ border-radius: 50%;
167924
+ background: var(--good);
167925
+ flex-shrink: 0;
167926
+ }
167927
+ .health .chip.down { border-color: rgb(255 97 102 / 45%); background: rgb(255 97 102 / 8%); }
167790
167928
  .health .chip.down .dot { background: var(--bad); }
167791
167929
  .health .chip .detail-text { color: var(--muted); }
167792
167930
  .home-cols {
@@ -167795,20 +167933,68 @@ var dashboardHtml = `<!doctype html>
167795
167933
  gap: 0 20px;
167796
167934
  align-items: start;
167797
167935
  }
167798
- /* The activity feed reads like the log cards. */
167799
- .activity-card {
167936
+ .logs .route.link { cursor: pointer; }
167937
+ .logs .route.link:hover { text-decoration: underline; }
167938
+ .logs .took { color: var(--muted); margin-left: auto; flex-shrink: 0; }
167939
+ .logs .payload {
167940
+ color: var(--muted);
167941
+ white-space: nowrap;
167942
+ overflow: hidden;
167943
+ text-overflow: ellipsis;
167944
+ }
167945
+ /* Hovering an entry unfolds its payload in place, fully wrapped. */
167946
+ .logs .entry:hover .payload {
167947
+ white-space: pre-wrap;
167948
+ overflow: visible;
167949
+ word-break: break-word;
167950
+ }
167951
+ /* The trace chip appears once a dispatch has trace siblings & opens
167952
+ the trace tree of the whole request chain. */
167953
+ .logs .trace-link {
167954
+ color: var(--accent);
167955
+ cursor: pointer;
167956
+ flex-shrink: 0;
167957
+ }
167958
+ .logs .trace-link:hover { text-decoration: underline; }
167959
+ .overlay {
167960
+ position: fixed;
167961
+ inset: 0;
167962
+ background: rgb(0 0 0 / 60%);
167963
+ backdrop-filter: blur(6px);
167964
+ -webkit-backdrop-filter: blur(6px);
167965
+ display: flex;
167966
+ align-items: center;
167967
+ justify-content: center;
167968
+ z-index: 50;
167969
+ }
167970
+ .overlay .modal {
167800
167971
  background: var(--panel);
167801
- border: 1px solid var(--border);
167802
- border-radius: 6px;
167803
- padding: 8px;
167804
- margin-top: 8px;
167805
- max-height: 420px;
167972
+ border: 1px solid var(--border-strong);
167973
+ border-radius: 12px;
167974
+ box-shadow: 0 12px 48px rgb(0 0 0 / 60%);
167975
+ width: min(760px, 92vw);
167976
+ max-height: 82vh;
167806
167977
  overflow-y: auto;
167807
- font-size: 12px;
167978
+ padding: 18px 22px;
167979
+ }
167980
+ .overlay .modal-head { display: flex; align-items: baseline; gap: 10px; }
167981
+ .overlay .modal-head h3 { margin: 0; font-family: var(--font-mono); }
167982
+ .overlay .modal-head .detail { color: var(--muted); font-size: 12px; }
167983
+ .overlay .modal-head button {
167984
+ margin-left: auto;
167985
+ background: none;
167986
+ border: none;
167987
+ color: var(--muted);
167988
+ font-size: 16px;
167989
+ cursor: pointer;
167990
+ border-radius: 6px;
167991
+ padding: 2px 8px;
167808
167992
  }
167809
- .activity-card .rows { grid-template-columns: fit-content(110px) 1fr auto; }
167810
- .activity-card .row { padding: 3px 4px; gap: 8px; }
167811
- .activity-card .empty { padding: 4px; }
167993
+ .overlay .modal-head button:hover { color: var(--text); background: var(--hover); }
167994
+ /* The tree rows reuse the log entry format, the guide marks the
167995
+ parent-child steps of the chain. */
167996
+ .trace-tree { max-height: none; }
167997
+ .trace-tree .entry .guide { color: var(--muted); flex-shrink: 0; }
167812
167998
  .row.problem .id { color: var(--bad); }
167813
167999
  .empty.good { color: var(--good); }
167814
168000
  .row .stack {
@@ -167817,13 +168003,17 @@ var dashboardHtml = `<!doctype html>
167817
168003
  overflow: hidden;
167818
168004
  text-overflow: ellipsis;
167819
168005
  white-space: nowrap;
168006
+ font-family: var(--font-mono);
168007
+ font-size: 12.5px;
167820
168008
  }
167821
168009
  .row .id {
167822
- font-weight: bold;
168010
+ font-weight: 500;
167823
168011
  min-width: 0;
167824
168012
  overflow: hidden;
167825
168013
  text-overflow: ellipsis;
167826
168014
  white-space: nowrap;
168015
+ font-family: var(--font-mono);
168016
+ font-size: 12.5px;
167827
168017
  }
167828
168018
  .row .info {
167829
168019
  color: var(--muted);
@@ -167832,13 +168022,14 @@ var dashboardHtml = `<!doctype html>
167832
168022
  text-overflow: ellipsis;
167833
168023
  white-space: nowrap;
167834
168024
  max-width: 100%;
168025
+ font-size: 12.5px;
167835
168026
  }
167836
168027
  .email-body {
167837
168028
  width: 100%;
167838
168029
  min-height: 480px;
167839
168030
  background: #fff;
167840
168031
  border: 1px solid var(--border);
167841
- border-radius: 8px;
168032
+ border-radius: 10px;
167842
168033
  margin-top: 12px;
167843
168034
  }
167844
168035
  textarea {
@@ -167847,47 +168038,58 @@ var dashboardHtml = `<!doctype html>
167847
168038
  background: var(--panel);
167848
168039
  color: var(--text);
167849
168040
  border: 1px solid var(--border);
167850
- border-radius: 8px;
167851
- padding: 10px;
167852
- font: inherit;
168041
+ border-radius: 10px;
168042
+ padding: 12px;
168043
+ font-family: var(--font-mono);
168044
+ font-size: 12.5px;
167853
168045
  resize: vertical;
167854
168046
  }
168047
+ textarea:hover { border-color: var(--border-strong); }
168048
+ textarea:focus { border-color: #5b6272; box-shadow: 0 0 0 3px rgb(255 255 255 / 14%); outline: none; }
167855
168049
  .actions { margin: 12px 0; display: flex; gap: 8px; align-items: center; }
167856
- .actions .status { color: var(--muted); }
168050
+ .actions .status { color: var(--muted); font-size: 13px; }
168051
+ /* Action buttons in the x.ai style: white pill primary, outlined
168052
+ ghost secondary. */
167857
168053
  button.primary {
167858
- background: var(--accent);
167859
- color: #14100a;
168054
+ background: #fff;
168055
+ color: #0a0a0a;
167860
168056
  border: none;
167861
- border-radius: 6px;
167862
- padding: 7px 16px;
168057
+ border-radius: 999px;
168058
+ padding: 7px 18px;
167863
168059
  font: inherit;
167864
- font-weight: bold;
168060
+ font-weight: 500;
167865
168061
  cursor: pointer;
167866
168062
  }
168063
+ button.primary:hover { background: #d9d9de; }
167867
168064
  button.primary:disabled { opacity: 0.5; cursor: wait; }
167868
168065
  button.secondary {
167869
- background: var(--panel);
168066
+ background: transparent;
167870
168067
  color: var(--text);
167871
- border: 1px solid var(--border);
167872
- border-radius: 6px;
167873
- padding: 6px 16px;
168068
+ border: 1px solid var(--border-strong);
168069
+ border-radius: 999px;
168070
+ padding: 6px 18px;
167874
168071
  font: inherit;
167875
168072
  cursor: pointer;
167876
168073
  }
168074
+ button.secondary:hover { background: var(--hover); border-color: #3d3d44; }
167877
168075
  pre.result {
167878
168076
  background: var(--panel);
167879
168077
  border: 1px solid var(--border);
167880
- border-radius: 8px;
167881
- padding: 12px;
168078
+ border-radius: 10px;
168079
+ padding: 12px 14px;
167882
168080
  overflow-x: auto;
167883
168081
  white-space: pre-wrap;
167884
168082
  word-break: break-word;
168083
+ font-family: var(--font-mono);
168084
+ font-size: 12.5px;
167885
168085
  }
167886
- pre.result.error { border-color: var(--bad); color: var(--bad); }
167887
- table { border-collapse: collapse; width: 100%; }
168086
+ pre.result.error { border-color: rgb(255 97 102 / 45%); color: var(--bad); }
168087
+ /* Tables in the vercel style: horizontal hairlines only, quiet
168088
+ uppercase headers. */
168089
+ table { border-collapse: collapse; width: 100%; font-family: var(--font-mono); font-size: 12.5px; }
167888
168090
  th, td {
167889
- border: 1px solid var(--border);
167890
- padding: 6px 10px;
168091
+ border-bottom: 1px solid var(--border);
168092
+ padding: 8px 12px;
167891
168093
  text-align: left;
167892
168094
  vertical-align: top;
167893
168095
  max-width: 360px;
@@ -167895,7 +168097,16 @@ var dashboardHtml = `<!doctype html>
167895
168097
  text-overflow: ellipsis;
167896
168098
  white-space: nowrap;
167897
168099
  }
167898
- th { color: var(--muted); font-weight: normal; }
168100
+ th {
168101
+ color: var(--muted);
168102
+ font-weight: 500;
168103
+ font-family: var(--font-sans);
168104
+ font-size: 11px;
168105
+ text-transform: uppercase;
168106
+ letter-spacing: 0.08em;
168107
+ }
168108
+ tbody tr { transition: background 0.15s ease; }
168109
+ tbody tr:hover { background: var(--hover); }
167899
168110
  td:hover { white-space: normal; word-break: break-all; }
167900
168111
  .empty { color: var(--muted); }
167901
168112
  </style>
@@ -168320,6 +168531,50 @@ const rpcPanel = (main, r) => {
168320
168531
  // A terminal-style view streaming a resource's live event channel,
168321
168532
  // like the dev server output of a site. The bus replays the recent
168322
168533
  // lines, so the boot output shows even when the panel opens later.
168534
+ // Resolve a feed label back to its resource: route keys match
168535
+ // directly, while queue/stream/topic labels carry the physical name
168536
+ // their resource lists as its detail.
168537
+ const findRouteResource = route => {
168538
+ const direct = state.resources.find(r => r.routeKey === route)
168539
+
168540
+ if (direct) {
168541
+ return direct
168542
+ }
168543
+
168544
+ const [kind, name] = route.split(' ')
168545
+
168546
+ if (!name) {
168547
+ return undefined
168548
+ }
168549
+
168550
+ if (kind === 'queue') {
168551
+ return state.resources.find(r => r.kind === 'queue' && r.detail === name)
168552
+ }
168553
+
168554
+ if (kind === 'stream') {
168555
+ return state.resources.find(r => r.kind === 'table' && r.detail === name)
168556
+ }
168557
+
168558
+ if (kind === 'topic') {
168559
+ return state.resources.find(r => r.kind === 'topic' && r.detail === name)
168560
+ }
168561
+
168562
+ return undefined
168563
+ }
168564
+
168565
+ // A route tag that links through to its resource, shared by the log
168566
+ // feeds & the activity feed.
168567
+ const routeTag = route => {
168568
+ const resource = findRouteResource(route)
168569
+ const tag = $('span', { className: 'route' + (resource ? ' link' : ''), title: route }, route)
168570
+
168571
+ if (resource) {
168572
+ tag.onclick = () => selectResource(resource)
168573
+ }
168574
+
168575
+ return tag
168576
+ }
168577
+
168323
168578
  const attachLogFeed = (main, channel, route, title = 'Logs') => {
168324
168579
  if (title) {
168325
168580
  main.append($('h3', {}, title))
@@ -168351,7 +168606,7 @@ const attachLogFeed = (main, channel, route, title = 'Logs') => {
168351
168606
  feed.append($('div', { className: 'entry' + error }, [
168352
168607
  $('div', { className: 'meta' }, [
168353
168608
  $('span', { className: 'time' }, new Date(data.date).toLocaleTimeString()),
168354
- showRoute ? $('span', { className: 'route' }, data.route) : '',
168609
+ showRoute ? routeTag(data.route) : '',
168355
168610
  ]),
168356
168611
  $('div', { className: 'text' }, data.line),
168357
168612
  ]))
@@ -169202,15 +169457,21 @@ const render = () => {
169202
169457
  nav.append(reseed)
169203
169458
  }
169204
169459
 
169460
+ // Every view renders into its own container: navigating detaches
169461
+ // the old one, so a slow async panel (like a table scan) finishing
169462
+ // after the switch appends into a dead node instead of the screen.
169205
169463
  const main = document.getElementById('main')
169206
169464
  main.innerHTML = ''
169207
169465
 
169466
+ const page = $('div')
169467
+ main.append(page)
169468
+
169208
169469
  if (view.resource) {
169209
- renderResource(main)
169470
+ renderResource(page)
169210
169471
  } else if (view.kind) {
169211
- renderList(main)
169472
+ renderList(page)
169212
169473
  } else {
169213
- renderHome(main)
169474
+ renderHome(page)
169214
169475
  }
169215
169476
  }
169216
169477
 
@@ -169357,35 +169618,139 @@ const renderHome = main => {
169357
169618
 
169358
169619
  activityCol.append($('h3', {}, 'Activity'))
169359
169620
 
169360
- const card = $('div', { className: 'activity-card' })
169361
- const activity = $('div', { className: 'rows' })
169362
- const idle = $('p', { className: 'empty' }, 'Nothing ran yet.')
169621
+ const activityFeed = $('div', { className: 'logs' }, $('p', { className: 'empty' }, 'Nothing ran yet.'))
169622
+ activityCol.append(activityFeed)
169623
+
169624
+ // The recent dispatches kept as data, not just DOM - the trace tree
169625
+ // renders straight from this buffer. It outlives the visible feed,
169626
+ // so a chain's early spans stay renderable after the feed pruned them.
169627
+ const activityData = []
169628
+ const traceCounts = new Map()
169629
+
169630
+ const closeTrace = () => {
169631
+ document.querySelector('.overlay')?.remove()
169632
+ }
169633
+
169634
+ // The trace tree: the whole request chain of one trace as nested
169635
+ // spans - what ran, what caused it, how long each step took & where
169636
+ // it failed. Children hang under their caller in dispatch order.
169637
+ const openTrace = traceId => {
169638
+ closeTrace()
169639
+
169640
+ const entries = activityData.filter(entry => entry.trace === traceId)
169641
+
169642
+ if (entries.length === 0) {
169643
+ return
169644
+ }
169645
+
169646
+ const started = Math.min(...entries.map(entry => entry.date))
169647
+ const ended = Math.max(...entries.map(entry => entry.date + entry.ms))
169648
+ const failed = entries.some(entry => !entry.ok)
169649
+
169650
+ const tree = $('div', { className: 'logs trace-tree' })
169651
+ const spans = new Set(entries.map(entry => entry.span))
169652
+
169653
+ // A span whose parent already fell out of the buffer renders as
169654
+ // its own root instead of vanishing.
169655
+ const roots = entries.filter(entry => !entry.parent || !spans.has(entry.parent))
169656
+
169657
+ const renderSpan = (entry, depth) => {
169658
+ const guide = $('span', { className: 'guide' }, '\\u2514')
169659
+ guide.style.paddingLeft = ((depth - 1) * 18) + 'px'
169660
+
169661
+ tree.append($('div', { className: 'entry' + (entry.ok ? '' : ' error') }, [
169662
+ $('div', { className: 'meta' }, [
169663
+ depth > 0 ? guide : '',
169664
+ $('span', { className: 'time' }, new Date(entry.date).toLocaleTimeString()),
169665
+ routeTag(entry.route),
169666
+ $('span', { className: 'took' }, (entry.ok ? '' : '\\u2717 ') + entry.ms + 'ms'),
169667
+ ]),
169668
+ entry.ok ? '' : $('div', { className: 'text', title: entry.error ?? '' }, entry.error ?? 'failed'),
169669
+ entry.payload ? $('div', { className: 'payload' }, entry.payload) : '',
169670
+ ]))
169671
+
169672
+ for (const child of entries.filter(other => other.parent === entry.span)) {
169673
+ renderSpan(child, depth + 1)
169674
+ }
169675
+ }
169676
+
169677
+ for (const root of roots) {
169678
+ renderSpan(root, 0)
169679
+ }
169680
+
169681
+ const close = $('button', { title: 'Close' }, '\\u2715')
169682
+ const overlay = $('div', { className: 'overlay' }, $('div', { className: 'modal' }, [
169683
+ $('div', { className: 'modal-head' }, [
169684
+ $('h3', {}, 'Trace ' + traceId),
169685
+ $('span', { className: 'detail' },
169686
+ entries.length + ' spans \\u00b7 ' + (ended - started) + 'ms' + (failed ? ' \\u00b7 failed' : '')),
169687
+ close,
169688
+ ]),
169689
+ tree,
169690
+ ]))
169691
+
169692
+ close.onclick = closeTrace
169693
+ overlay.onclick = event => {
169694
+ if (event.target === overlay) closeTrace()
169695
+ }
169363
169696
 
169364
- card.append(idle, activity)
169365
- activityCol.append(card)
169697
+ document.body.append(overlay)
169698
+ }
169366
169699
 
169367
- const activityRows = []
169700
+ const traceChip = traceId => {
169701
+ const chip = $('span', { className: 'trace-link', title: 'View the whole request chain' }, 'trace')
169702
+ chip.onclick = () => openTrace(traceId)
169703
+ return chip
169704
+ }
169705
+
169706
+ // A lone dispatch shows no chip - once a second span of its trace
169707
+ // arrives, every entry of the chain gets one, retroactively.
169708
+ const markTraced = traceId => {
169709
+ for (const entry of activityFeed.querySelectorAll('[data-trace="' + traceId + '"]')) {
169710
+ if (!entry.querySelector('.trace-link')) {
169711
+ entry.querySelector('.meta')?.append(traceChip(traceId))
169712
+ }
169713
+ }
169714
+ }
169368
169715
 
169369
169716
  const activityRow = data => {
169370
- idle.hidden = true
169717
+ activityFeed.querySelector('.empty')?.remove()
169718
+
169719
+ activityData.push(data)
169720
+
169721
+ while (activityData.length > 200) {
169722
+ activityData.shift()
169723
+ }
169371
169724
 
169372
- const resource = state.resources.find(r => r.routeKey === data.route)
169373
- const row = $('button', { className: 'row' + (data.ok ? '' : ' problem') }, [
169374
- $('span', { className: 'stack' }, new Date(data.date).toLocaleTimeString()),
169375
- $('span', { className: 'id', title: data.route }, (data.ok ? '' : '\\u2717 ') + data.route),
169376
- $('span', { className: 'info', title: data.ok ? '' : (data.error ?? '') }, data.ok ? data.ms + 'ms' : (data.error ?? 'failed').slice(0, 80)),
169725
+ // The same entry format as the log feeds: meta header with the
169726
+ // linked route tag & the duration, the payload truncated on its
169727
+ // own line with the full value on hover.
169728
+ const row = $('div', { className: 'entry' + (data.ok ? '' : ' error') }, [
169729
+ $('div', { className: 'meta' }, [
169730
+ $('span', { className: 'time' }, new Date(data.date).toLocaleTimeString()),
169731
+ routeTag(data.route),
169732
+ $('span', { className: 'took' }, (data.ok ? '' : '\\u2717 ') + data.ms + 'ms'),
169733
+ ]),
169734
+ data.ok ? '' : $('div', { className: 'text', title: data.error ?? '' }, data.error ?? 'failed'),
169735
+ data.payload ? $('div', { className: 'payload' }, data.payload) : '',
169377
169736
  ])
169378
169737
 
169379
- if (resource) {
169380
- row.onclick = () => selectResource(resource)
169738
+ if (data.trace) {
169739
+ row.setAttribute('data-trace', data.trace)
169740
+ traceCounts.set(data.trace, (traceCounts.get(data.trace) ?? 0) + 1)
169381
169741
  }
169382
169742
 
169383
- activity.prepend(row)
169384
- activityRows.push(row)
169743
+ activityFeed.append(row)
169385
169744
 
169386
- while (activityRows.length > 50) {
169387
- activityRows.shift().remove()
169745
+ if (data.trace && traceCounts.get(data.trace) > 1) {
169746
+ markTraced(data.trace)
169388
169747
  }
169748
+
169749
+ while (activityFeed.children.length > 50) {
169750
+ activityFeed.firstChild.remove()
169751
+ }
169752
+
169753
+ activityFeed.scrollTop = activityFeed.scrollHeight
169389
169754
  }
169390
169755
 
169391
169756
  const activitySource = new EventSource('/api/events?channel=activity')
@@ -169403,6 +169768,7 @@ const renderHome = main => {
169403
169768
 
169404
169769
  cleanupPanel = () => {
169405
169770
  clearInterval(uptimeTimer)
169771
+ closeTrace()
169406
169772
  healthSource.close()
169407
169773
  problemSource.close()
169408
169774
  activitySource.close()
@@ -169435,6 +169801,7 @@ try {
169435
169801
  id: route.pattern,
169436
169802
  stack: route.routeKey ? route.routeKey.split(':')[0] : undefined,
169437
169803
  router: route.routerId,
169804
+ routeKey: route.routeKey,
169438
169805
  detail: route.routeKey ?? ('proxy \u2192 ' + route.proxy),
169439
169806
  url: 'http://localhost:' + state.routerPorts[route.routerId] + route.pattern.split('{')[0].replace(/\\*$/, ''),
169440
169807
  })),
@@ -169833,7 +170200,8 @@ var createFailureReporter = (props) => {
169833
170200
  return;
169834
170201
  }
169835
170202
  const event = JSON.parse(stringify5(format4(report)));
169836
- props.dispatch(formatRoutePayload2(CONSUMER_ROUTE, event)).catch((error3) => {
170203
+ const parent = report.error?.trace;
170204
+ props.dispatch(formatRoutePayload2(CONSUMER_ROUTE, event), parent).catch((error3) => {
169837
170205
  props.log(`The on-failure consumer itself failed: ${error3 instanceof Error ? error3.message : String(error3)}`);
169838
170206
  });
169839
170207
  };
@@ -169906,10 +170274,11 @@ var createLambdaServer = (props) => {
169906
170274
  }
169907
170275
  const type2 = String(req.headers["x-amz-invocation-type"] ?? "RequestResponse");
169908
170276
  const event = JSON.parse(body.toString() || "{}");
170277
+ const trace = parseTraceHeader(req.headers[TRACE_HEADER]);
169909
170278
  if (type2 === "Event") {
169910
170279
  res.writeHead(202, { "content-type": "application/json" });
169911
170280
  res.end();
169912
- dispatch?.(event).catch((error3) => {
170281
+ dispatch?.(event, trace).catch((error3) => {
169913
170282
  const routeKey = event?.["$awsless-route"];
169914
170283
  reportFailure?.({
169915
170284
  kind: "async",
@@ -169921,7 +170290,7 @@ var createLambdaServer = (props) => {
169921
170290
  return;
169922
170291
  }
169923
170292
  try {
169924
- const result = await dispatch?.(event);
170293
+ const result = await dispatch?.(event, trace);
169925
170294
  res.writeHead(200, { "content-type": "application/json" });
169926
170295
  res.end(typeof result === "undefined" || result === null ? "" : JSON.stringify(result));
169927
170296
  } catch (error3) {
@@ -170193,21 +170562,48 @@ var startDev = async (props) => {
170193
170562
  }
170194
170563
  return "invoke";
170195
170564
  };
170196
- const dispatch = async (event) => {
170565
+ const describePayload = (event) => {
170566
+ let payload = "";
170567
+ try {
170568
+ const envelope = event;
170569
+ const inner = typeof envelope?.["$awsless-route"] === "string" ? envelope.event : event;
170570
+ payload = JSON.stringify(inner) ?? "";
170571
+ } catch (_4) {}
170572
+ return payload.length > 1000 ? payload.slice(0, 1000) + "\u2026" : payload;
170573
+ };
170574
+ const dispatch = async (event, parent) => {
170197
170575
  await ensureFresh();
170198
170576
  const started = Date.now();
170199
170577
  const route = describeDispatch(event);
170578
+ const payload = describePayload(event);
170579
+ const trace = { traceId: parent?.traceId ?? traceId(), spanId: traceId() };
170200
170580
  try {
170201
- const result = await worker.dispatch(event);
170202
- dev.events.emit("activity", { date: started, route, ms: Date.now() - started, ok: true });
170581
+ const result = await worker.dispatch(event, formatTraceHeader(trace));
170582
+ dev.events.emit("activity", {
170583
+ date: started,
170584
+ route,
170585
+ payload,
170586
+ ms: Date.now() - started,
170587
+ ok: true,
170588
+ trace: trace.traceId,
170589
+ span: trace.spanId,
170590
+ parent: parent?.spanId
170591
+ });
170203
170592
  return result;
170204
170593
  } catch (error3) {
170594
+ if (error3 instanceof Error) {
170595
+ error3.trace = trace;
170596
+ }
170205
170597
  dev.events.emit("activity", {
170206
170598
  date: started,
170207
170599
  route,
170600
+ payload,
170208
170601
  ms: Date.now() - started,
170209
170602
  ok: false,
170210
- error: error3 instanceof Error ? error3.message : String(error3)
170603
+ error: error3 instanceof Error ? error3.message : String(error3),
170604
+ trace: trace.traceId,
170605
+ span: trace.spanId,
170606
+ parent: parent?.spanId
170211
170607
  });
170212
170608
  throw error3;
170213
170609
  }
@@ -177712,7 +178108,7 @@ ${job.error.stack.split(`
177712
178108
  stream2.shift();
177713
178109
  } else if (stream2.length > 0) {
177714
178110
  this._BOMseen = true;
177715
- }
178111
+ } else {}
177716
178112
  }
177717
178113
  return codePointsToString(stream2);
177718
178114
  }