@awsless/cli 0.0.46-local.47 → 0.0.46-local.48

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
@@ -153541,9 +153541,14 @@ for (const name in env) {
153541
153541
  process.env[name] ??= env[name]
153542
153542
  }
153543
153543
 
153544
- const { createBundle } = await import(${JSON.stringify(runtime)})
153544
+ const runtime = await import(${JSON.stringify(runtime)})
153545
153545
 
153546
- export default createBundle({
153546
+ // The local dev worker tags console output with the active route. A
153547
+ // lazy accessor instead of a re-export, since a static re-export would
153548
+ // hoist the runtime import above the env application.
153549
+ export const getCurrentRoute = () => runtime.getCurrentRoute?.()
153550
+
153551
+ export default runtime.createBundle({
153547
153552
  ${entries2.join(`
153548
153553
  `)}
153549
153554
  })
@@ -166621,11 +166626,37 @@ class WorkerError extends Error {
166621
166626
  }
166622
166627
  }
166623
166628
  var WORKER_ENTRY = `import { createServer } from 'node:http'
166629
+ import { format } from 'node:util'
166624
166630
 
166625
166631
  let handler
166632
+ let getCurrentRoute = () => undefined
166633
+
166634
+ // Console output is tagged with the active bundle route (invisible
166635
+ // \\x1f markers), so the dev cli can attribute every log line to the
166636
+ // function that wrote it - accurate even under concurrent requests,
166637
+ // since the route comes from the bundle's async context.
166638
+ const patchConsole = (method, stream) => {
166639
+ console[method] = (...args) => {
166640
+ const route = getCurrentRoute() ?? ''
166641
+ const text = format(...args)
166642
+
166643
+ for (const line of text.split('\\n')) {
166644
+ stream.write('\\x1f' + route + '\\x1f' + line + '\\n')
166645
+ }
166646
+ }
166647
+ }
166648
+
166649
+ patchConsole('log', process.stdout)
166650
+ patchConsole('info', process.stdout)
166651
+ patchConsole('debug', process.stdout)
166652
+ patchConsole('warn', process.stderr)
166653
+ patchConsole('error', process.stderr)
166626
166654
 
166627
166655
  try {
166628
- handler = (await import('./files/index.mjs')).default
166656
+ const bundle = await import('./files/index.mjs')
166657
+
166658
+ handler = bundle.default
166659
+ getCurrentRoute = bundle.getCurrentRoute ?? getCurrentRoute
166629
166660
  } catch (error) {
166630
166661
  // Keep module load failures readable, instead of node dumping the
166631
166662
  // whole minified line that threw.
@@ -166715,12 +166746,25 @@ var createBundleWorker = (props) => {
166715
166746
  }
166716
166747
  });
166717
166748
  const capture = (stream2) => (chunk3) => {
166718
- process[stream2].write(chunk3);
166719
166749
  for (const raw of chunk3.toString().split(`
166720
166750
  `)) {
166721
- const line = stripAnsi2(raw);
166722
- if (line.trim() !== "") {
166723
- props.onOutput?.(line, stream2);
166751
+ if (raw === "") {
166752
+ continue;
166753
+ }
166754
+ let line = raw;
166755
+ let route;
166756
+ if (raw.startsWith("\x1F")) {
166757
+ const end = raw.indexOf("\x1F", 1);
166758
+ if (end > 0) {
166759
+ route = raw.slice(1, end) || undefined;
166760
+ line = raw.slice(end + 1);
166761
+ }
166762
+ }
166763
+ process[stream2].write((route ? `[${route}] ` : "") + line + `
166764
+ `);
166765
+ const clean = stripAnsi2(line);
166766
+ if (clean.trim() !== "") {
166767
+ props.onOutput?.(clean, stream2, route);
166724
166768
  }
166725
166769
  }
166726
166770
  };
@@ -166831,6 +166875,7 @@ var dashboardHtml = `<!doctype html>
166831
166875
  }
166832
166876
  .logs .line { display: flex; gap: 8px; padding: 1px 0; }
166833
166877
  .logs .time { color: var(--muted); flex-shrink: 0; }
166878
+ .logs .route { color: var(--accent); max-width: 220px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
166834
166879
  .logs .text { white-space: pre-wrap; word-break: break-word; }
166835
166880
  .logs .line.error .text { color: var(--bad); }
166836
166881
  .config-form { display: flex; flex-direction: column; gap: 8px; max-width: 520px; }
@@ -166998,6 +167043,15 @@ var dashboardHtml = `<!doctype html>
166998
167043
  cursor: pointer;
166999
167044
  }
167000
167045
  button.primary:disabled { opacity: 0.5; cursor: wait; }
167046
+ button.secondary {
167047
+ background: var(--panel);
167048
+ color: var(--text);
167049
+ border: 1px solid var(--border);
167050
+ border-radius: 6px;
167051
+ padding: 6px 16px;
167052
+ font: inherit;
167053
+ cursor: pointer;
167054
+ }
167001
167055
  pre.result {
167002
167056
  background: var(--panel);
167003
167057
  border: 1px solid var(--border);
@@ -167066,7 +167120,7 @@ const GROUPS = [
167066
167120
  ['config', 'Config'],
167067
167121
  ['auth', 'Auth'],
167068
167122
  ['email', 'Emails'],
167069
- ['worker', 'Worker'],
167123
+ ['worker', 'Logs'],
167070
167124
  ['route', 'Routes'],
167071
167125
  ]
167072
167126
 
@@ -167184,11 +167238,23 @@ window.addEventListener('popstate', applyLocation)
167184
167238
  // Detail panels
167185
167239
 
167186
167240
  const invokePanel = (main, r) => {
167241
+ // The last payload survives reloads & panel switches, so a hand
167242
+ // crafted event never gets lost. The envelope only prefills the
167243
+ // first visit.
167244
+ const storageKey = 'invoke-payload:' + r.kind + ':' + (r.stack ?? '-') + ':' + r.id
167187
167245
  const placeholder = JSON.stringify(r.envelope ?? {}, null, 2)
167188
- const input = $('textarea', { value: placeholder, spellcheck: false })
167246
+ const input = $('textarea', { value: localStorage.getItem(storageKey) ?? placeholder, spellcheck: false })
167189
167247
  const status = $('span', { className: 'status' })
167190
167248
  const result = $('pre', { className: 'result', hidden: true })
167191
167249
  const run = $('button', { className: 'primary', textContent: r.kind === 'topic' ? 'Publish' : 'Invoke' })
167250
+ const reset = $('button', { className: 'secondary', textContent: 'Reset' })
167251
+
167252
+ input.oninput = () => localStorage.setItem(storageKey, input.value)
167253
+
167254
+ reset.onclick = () => {
167255
+ localStorage.removeItem(storageKey)
167256
+ input.value = placeholder
167257
+ }
167192
167258
 
167193
167259
  run.onclick = async () => {
167194
167260
  run.disabled = true
@@ -167214,9 +167280,14 @@ const invokePanel = (main, r) => {
167214
167280
 
167215
167281
  main.append(
167216
167282
  input,
167217
- $('div', { className: 'actions' }, [run, status]),
167283
+ $('div', { className: 'actions' }, [run, reset, status]),
167218
167284
  result,
167219
167285
  )
167286
+
167287
+ // The resource's own console output, filtered from the worker feed.
167288
+ if (r.routeKey) {
167289
+ cleanupPanel = attachLogFeed(main, 'worker', r.routeKey)
167290
+ }
167220
167291
  }
167221
167292
 
167222
167293
  const pubsubPanel = (main, r) => {
@@ -167340,8 +167411,10 @@ const rpcPanel = (main, r) => {
167340
167411
  // A terminal-style view streaming a resource's live event channel,
167341
167412
  // like the dev server output of a site. The bus replays the recent
167342
167413
  // lines, so the boot output shows even when the panel opens later.
167343
- const attachLogFeed = (main, channel) => {
167344
- main.append($('h3', {}, 'Logs'))
167414
+ const attachLogFeed = (main, channel, route, title = 'Logs') => {
167415
+ if (title) {
167416
+ main.append($('h3', {}, title))
167417
+ }
167345
167418
 
167346
167419
  const feed = $('div', { className: 'logs' }, $('p', { className: 'empty' }, 'Waiting for output...'))
167347
167420
  main.append(feed)
@@ -167351,9 +167424,16 @@ const attachLogFeed = (main, channel) => {
167351
167424
  source.onmessage = message => {
167352
167425
  const data = JSON.parse(message.data)
167353
167426
 
167427
+ // A route filter shows only the lines of one resource, like the
167428
+ // function panel showing its own console output.
167429
+ if (route && data.route !== route) {
167430
+ return
167431
+ }
167432
+
167354
167433
  feed.querySelector('.empty')?.remove()
167355
167434
  feed.append($('div', { className: 'line' + (data.error ? ' error' : '') }, [
167356
167435
  $('span', { className: 'time' }, new Date(data.date).toLocaleTimeString()),
167436
+ !route && data.route ? $('span', { className: 'route' }, data.route) : '',
167357
167437
  $('span', { className: 'text' }, data.line),
167358
167438
  ]))
167359
167439
 
@@ -167878,7 +167958,7 @@ const renderList = main => {
167878
167958
  // The worker page streams the bundle worker output directly,
167879
167959
  // instead of listing its single resource.
167880
167960
  if (view.kind === 'worker') {
167881
- cleanupPanel = attachLogFeed(main, 'worker')
167961
+ cleanupPanel = attachLogFeed(main, 'worker', undefined, null)
167882
167962
  return
167883
167963
  }
167884
167964
 
@@ -168644,14 +168724,14 @@ var startDev = async (props) => {
168644
168724
  workspace = await loadWorkspace3(directories.root);
168645
168725
  await buildAll();
168646
168726
  });
168647
- const emitWorkerLine = (line, error3 = false) => {
168648
- dev.events.emit("worker", { date: Date.now(), line, error: error3 });
168727
+ const emitWorkerLine = (line, error3 = false, route) => {
168728
+ dev.events.emit("worker", { date: Date.now(), line, error: error3, route });
168649
168729
  };
168650
168730
  const worker = createBundleWorker({
168651
168731
  buildDir,
168652
168732
  env: env4,
168653
168733
  functionName: bundleName,
168654
- onOutput: (line, stream2) => emitWorkerLine(line, stream2 === "stderr")
168734
+ onOutput: (line, stream2, route) => emitWorkerLine(line, stream2 === "stderr", route)
168655
168735
  });
168656
168736
  dev.resources.push({
168657
168737
  kind: "worker",
@@ -168739,7 +168819,7 @@ var startDev = async (props) => {
168739
168819
  const detail = error3 instanceof Error ? error3.stack ?? error3.message : String(error3);
168740
168820
  process.stderr.write(`Route ${routeKey} failed: ${detail}
168741
168821
  `);
168742
- emitWorkerLine(`Route ${routeKey} failed: ${detail}`, true);
168822
+ emitWorkerLine(`Route ${routeKey} failed: ${detail}`, true, routeKey);
168743
168823
  }
168744
168824
  }));
168745
168825
  }
@@ -406,6 +406,7 @@ var topicHandler = (event, routes) => {
406
406
  };
407
407
 
408
408
  // src/feature/bundle/server/handle.ts
409
+ import { getCurrentRoute as getCurrentRoute2 } from "awsless";
409
410
  var createBundle = (handlers) => {
410
411
  const routes = Object.keys(handlers);
411
412
  setBundleRoutes(routes);
@@ -504,5 +505,6 @@ var createBundle = (handlers) => {
504
505
  };
505
506
  };
506
507
  export {
508
+ getCurrentRoute2 as getCurrentRoute,
507
509
  createBundle
508
510
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@awsless/cli",
3
- "version": "0.0.46-local.47",
3
+ "version": "0.0.46-local.48",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -38,19 +38,19 @@
38
38
  "@opensearch-project/opensearch": "^2.13.0",
39
39
  "rolldown": "1.2.1",
40
40
  "vitest": "4.1.10",
41
- "@awsless/ts-file-cache": "^0.0.16",
42
- "@awsless/dynamodb-server": "^0.1.8"
41
+ "@awsless/dynamodb-server": "^0.1.8",
42
+ "@awsless/ts-file-cache": "^0.0.16"
43
43
  },
44
44
  "peerDependencies": {
45
- "@awsless/dynamodb": "^0.3.22",
46
45
  "@awsless/big-float": "^0.1.7",
47
- "@awsless/lambda": "^0.0.47",
48
- "@awsless/validate": "^0.1.7",
49
- "@awsless/s3": "^0.0.22",
50
46
  "@awsless/duration": "^0.0.4",
51
47
  "@awsless/json": "^0.0.11",
48
+ "@awsless/dynamodb": "^0.3.22",
49
+ "@awsless/s3": "^0.0.22",
52
50
  "@awsless/weak-cache": "^0.0.1",
53
- "awsless": "^0.0.15-local.11"
51
+ "@awsless/lambda": "^0.0.47",
52
+ "awsless": "^0.0.15-local.12",
53
+ "@awsless/validate": "^0.1.8"
54
54
  },
55
55
  "devDependencies": {
56
56
  "@aws-sdk/client-cloudformation": "^3.369.0",
@@ -122,23 +122,23 @@
122
122
  "zod-to-json-schema": "^3.24.3",
123
123
  "@awsless/big-float": "^0.1.7",
124
124
  "@awsless/clui": "^0.0.9",
125
- "@awsless/duration": "^0.0.4",
126
125
  "@awsless/cloudwatch": "^0.0.1",
126
+ "@awsless/duration": "^0.0.4",
127
+ "@awsless/dynamodb": "^0.3.22",
127
128
  "@awsless/iot": "^0.0.5",
128
129
  "@awsless/json": "^0.0.11",
129
- "@awsless/dynamodb": "^0.3.22",
130
- "@awsless/open-search": "^0.0.26",
131
- "@awsless/lambda": "^0.0.47",
132
- "@awsless/s3": "^0.0.22",
133
130
  "@awsless/redis": "^0.1.13",
131
+ "@awsless/lambda": "^0.0.47",
134
132
  "@awsless/size": "^0.0.2",
135
- "@awsless/sns": "^0.0.11",
133
+ "@awsless/s3": "^0.0.22",
134
+ "@awsless/open-search": "^0.0.26",
136
135
  "@awsless/scheduler": "^0.0.5",
137
136
  "@awsless/sqs": "^0.0.24",
138
- "@awsless/validate": "^0.1.7",
137
+ "@awsless/sns": "^0.0.11",
138
+ "awsless": "^0.0.15-local.12",
139
139
  "@awsless/ssm": "^0.0.8",
140
140
  "@awsless/weak-cache": "^0.0.1",
141
- "awsless": "^0.0.15-local.11"
141
+ "@awsless/validate": "^0.1.8"
142
142
  },
143
143
  "scripts": {
144
144
  "test": "bun cli/build-handlers.ts && pnpm vitest",