gravity-run 0.0.6 → 0.0.7

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/cli/index.js CHANGED
@@ -3,9 +3,80 @@ import {
3
3
  BadRequestError,
4
4
  ForbiddenError,
5
5
  UnauthorizedError,
6
- globalLogger,
6
+ __commonJS,
7
+ __toESM,
7
8
  loadConfig
8
- } from "../shared/chunk-b636e30q.js";
9
+ } from "../shared/chunk-s3hrp89d.js";
10
+
11
+ // node_modules/picocolors/picocolors.js
12
+ var require_picocolors = __commonJS((exports, module) => {
13
+ var p = process || {};
14
+ var argv = p.argv || [];
15
+ var env = p.env || {};
16
+ var isColorSupported = !(!!env.NO_COLOR || argv.includes("--no-color")) && (!!env.FORCE_COLOR || argv.includes("--color") || p.platform === "win32" || (p.stdout || {}).isTTY && env.TERM !== "dumb" || !!env.CI);
17
+ var formatter = (open, close, replace = open) => (input) => {
18
+ let string = "" + input, index = string.indexOf(close, open.length);
19
+ return ~index ? open + replaceClose(string, close, replace, index) + close : open + string + close;
20
+ };
21
+ var replaceClose = (string, close, replace, index) => {
22
+ let result = "", cursor = 0;
23
+ do {
24
+ result += string.substring(cursor, index) + replace;
25
+ cursor = index + close.length;
26
+ index = string.indexOf(close, cursor);
27
+ } while (~index);
28
+ return result + string.substring(cursor);
29
+ };
30
+ var createColors = (enabled = isColorSupported) => {
31
+ let f = enabled ? formatter : () => String;
32
+ return {
33
+ isColorSupported: enabled,
34
+ reset: f("\x1B[0m", "\x1B[0m"),
35
+ bold: f("\x1B[1m", "\x1B[22m", "\x1B[22m\x1B[1m"),
36
+ dim: f("\x1B[2m", "\x1B[22m", "\x1B[22m\x1B[2m"),
37
+ italic: f("\x1B[3m", "\x1B[23m"),
38
+ underline: f("\x1B[4m", "\x1B[24m"),
39
+ inverse: f("\x1B[7m", "\x1B[27m"),
40
+ hidden: f("\x1B[8m", "\x1B[28m"),
41
+ strikethrough: f("\x1B[9m", "\x1B[29m"),
42
+ black: f("\x1B[30m", "\x1B[39m"),
43
+ red: f("\x1B[31m", "\x1B[39m"),
44
+ green: f("\x1B[32m", "\x1B[39m"),
45
+ yellow: f("\x1B[33m", "\x1B[39m"),
46
+ blue: f("\x1B[34m", "\x1B[39m"),
47
+ magenta: f("\x1B[35m", "\x1B[39m"),
48
+ cyan: f("\x1B[36m", "\x1B[39m"),
49
+ white: f("\x1B[37m", "\x1B[39m"),
50
+ gray: f("\x1B[90m", "\x1B[39m"),
51
+ bgBlack: f("\x1B[40m", "\x1B[49m"),
52
+ bgRed: f("\x1B[41m", "\x1B[49m"),
53
+ bgGreen: f("\x1B[42m", "\x1B[49m"),
54
+ bgYellow: f("\x1B[43m", "\x1B[49m"),
55
+ bgBlue: f("\x1B[44m", "\x1B[49m"),
56
+ bgMagenta: f("\x1B[45m", "\x1B[49m"),
57
+ bgCyan: f("\x1B[46m", "\x1B[49m"),
58
+ bgWhite: f("\x1B[47m", "\x1B[49m"),
59
+ blackBright: f("\x1B[90m", "\x1B[39m"),
60
+ redBright: f("\x1B[91m", "\x1B[39m"),
61
+ greenBright: f("\x1B[92m", "\x1B[39m"),
62
+ yellowBright: f("\x1B[93m", "\x1B[39m"),
63
+ blueBright: f("\x1B[94m", "\x1B[39m"),
64
+ magentaBright: f("\x1B[95m", "\x1B[39m"),
65
+ cyanBright: f("\x1B[96m", "\x1B[39m"),
66
+ whiteBright: f("\x1B[97m", "\x1B[39m"),
67
+ bgBlackBright: f("\x1B[100m", "\x1B[49m"),
68
+ bgRedBright: f("\x1B[101m", "\x1B[49m"),
69
+ bgGreenBright: f("\x1B[102m", "\x1B[49m"),
70
+ bgYellowBright: f("\x1B[103m", "\x1B[49m"),
71
+ bgBlueBright: f("\x1B[104m", "\x1B[49m"),
72
+ bgMagentaBright: f("\x1B[105m", "\x1B[49m"),
73
+ bgCyanBright: f("\x1B[106m", "\x1B[49m"),
74
+ bgWhiteBright: f("\x1B[107m", "\x1B[49m")
75
+ };
76
+ };
77
+ module.exports = createColors();
78
+ module.exports.createColors = createColors;
79
+ });
9
80
 
10
81
  // src/cli/index.ts
11
82
  import { Command as Command5 } from "commander";
@@ -152,15 +223,219 @@ function schemaToTypeString(schema) {
152
223
  return "any";
153
224
  }
154
225
 
226
+ // src/logger/action-logger.ts
227
+ var import_picocolors2 = __toESM(require_picocolors(), 1);
228
+
229
+ // src/logger/symbols.ts
230
+ var import_picocolors = __toESM(require_picocolors(), 1);
231
+ import isUnicodeSupported from "is-unicode-supported";
232
+ var unicode = isUnicodeSupported();
233
+ var u = (c, fallback) => unicode ? c : fallback;
234
+ var S_BAR_START = u("┌", "T");
235
+ var S_BAR = u("│", "|");
236
+ var S_BAR_END = u("└", "-");
237
+ var S_STEP_SUBMIT = u("◇", "o");
238
+ var S_RADIO_ACTIVE = u("●", ">");
239
+ var S_SUCCESS = u("✔", "√");
240
+ var S_ERROR = u("✖", "x");
241
+ var S_WARN = u("▲", "!");
242
+ var S_INFO = u("●", "•");
243
+ var bar = () => import_picocolors.default.gray(S_BAR);
244
+ var barStart = (text) => `${import_picocolors.default.gray(S_BAR_START)} ${text}`;
245
+ var barEnd = (text) => `${import_picocolors.default.gray(S_BAR_END)} ${text}`;
246
+ var stepInfo = (label, detail) => `${import_picocolors.default.green(S_STEP_SUBMIT)} ${label}${detail ? `: ${detail}` : ""}`;
247
+ var stepActive = (label, detail) => `${import_picocolors.default.cyan(S_RADIO_ACTIVE)} ${label}${detail ? `: ${detail}` : ""}`;
248
+ var stepSuccess = (label, detail) => `${import_picocolors.default.green(S_SUCCESS)} ${label}${detail ? `: ${detail}` : ""}`;
249
+ var stepError = (label, detail) => `${import_picocolors.default.red(S_ERROR)} ${label}${detail ? `: ${detail}` : ""}`;
250
+ var stepWarn = (label, detail) => `${import_picocolors.default.yellow(S_WARN)} ${label}${detail ? `: ${detail}` : ""}`;
251
+
252
+ // src/logger/action-logger.ts
253
+ class LoggerSession {
254
+ output;
255
+ startTime;
256
+ constructor(title, output = process.stdout) {
257
+ this.output = output;
258
+ this.startTime = Date.now();
259
+ this.write(barStart(title));
260
+ }
261
+ write(line) {
262
+ this.output.write(`${line}
263
+ `);
264
+ }
265
+ info(label, detail) {
266
+ this.write(stepInfo(label, detail));
267
+ return this;
268
+ }
269
+ step(label, detail) {
270
+ this.write(stepActive(label, detail));
271
+ return this;
272
+ }
273
+ success(label, detail) {
274
+ this.write(stepSuccess(label, detail));
275
+ return this;
276
+ }
277
+ warn(label, detail) {
278
+ this.write(stepWarn(label, detail));
279
+ return this;
280
+ }
281
+ error(label, detail) {
282
+ this.write(stepError(label, detail));
283
+ return this;
284
+ }
285
+ bar() {
286
+ this.write(bar());
287
+ return this;
288
+ }
289
+ end(message) {
290
+ const elapsed = Date.now() - this.startTime;
291
+ const msg = message ?? "Done";
292
+ this.write(bar());
293
+ this.write(barEnd(import_picocolors2.default.green(`${msg}`) + import_picocolors2.default.gray(` (${elapsed}ms)`)));
294
+ this.write("");
295
+ }
296
+ fail(message) {
297
+ const elapsed = Date.now() - this.startTime;
298
+ const msg = message ?? "Failed";
299
+ this.write(bar());
300
+ this.write(barEnd(import_picocolors2.default.red(`${msg}`) + import_picocolors2.default.gray(` (${elapsed}ms)`)));
301
+ this.write("");
302
+ }
303
+ }
304
+ // src/logger/pretty-print.ts
305
+ var import_picocolors3 = __toESM(require_picocolors(), 1);
306
+ var stepTag = (step) => step ? import_picocolors3.default.bold(import_picocolors3.default.cyan(step)) : "";
307
+ var timestampTag = (timestamp) => import_picocolors3.default.gray(timestamp);
308
+ var traceIdTag = (traceId) => traceId ? import_picocolors3.default.gray(traceId) : "";
309
+ var levelTags = {
310
+ error: import_picocolors3.default.red("[ERROR]"),
311
+ info: import_picocolors3.default.blue("[INFO]"),
312
+ warn: import_picocolors3.default.yellow("[WARN]"),
313
+ debug: import_picocolors3.default.gray("[DEBUG]")
314
+ };
315
+ var numericTag = (value) => import_picocolors3.default.green(value);
316
+ var stringTag = (value) => import_picocolors3.default.cyan(value);
317
+ var booleanTag = (value) => import_picocolors3.default.blue(value);
318
+ var arrayBrackets = ["[", "]"].map((s) => import_picocolors3.default.gray(s));
319
+ var objectBrackets = ["{", "}"].map((s) => import_picocolors3.default.gray(s));
320
+ var prettyPrintObject = (obj, depth = 0, parentIsLast = false, prefix = "") => {
321
+ const tab = prefix + (depth === 0 ? "" : parentIsLast ? "│ " : "│ ");
322
+ if (depth > 2)
323
+ return `${tab} └ ${import_picocolors3.default.gray("[...]")}`;
324
+ const entries = Object.entries(obj);
325
+ return entries.map(([key, value], index) => {
326
+ const isLast = index === entries.length - 1;
327
+ const isObject = typeof value === "object" && value !== null;
328
+ const branch = isLast ? "└" : "├";
329
+ if (isObject) {
330
+ const subObject = prettyPrintObject(value, depth + 1, isLast, tab);
331
+ const [start, end] = Array.isArray(value) ? arrayBrackets : objectBrackets;
332
+ return `${tab}${branch} ${key}: ${start}
333
+ ${subObject}
334
+ ${tab}${isLast ? " " : "│"} ${end}`;
335
+ }
336
+ let printedValue = value;
337
+ if (typeof value === "number")
338
+ printedValue = numericTag(String(value));
339
+ else if (typeof value === "boolean")
340
+ printedValue = booleanTag(String(value));
341
+ else if (typeof value === "string")
342
+ printedValue = stringTag(value);
343
+ return `${tab}${branch} ${key}: ${printedValue}`;
344
+ }).join(`
345
+ `);
346
+ };
347
+ var prettyPrint = (json, excludeDetails = false) => {
348
+ const { time, traceId, msg, flows, level, step, ...details } = json;
349
+ const levelTag = levelTags[level?.toLowerCase?.()] ?? levelTags.info;
350
+ const timestamp = timestampTag(`[${new Date(time).toLocaleTimeString()}]`);
351
+ const objectHasKeys = Object.keys(details).length > 0;
352
+ process.stdout.write(`${timestamp} ${traceIdTag(traceId)} ${levelTag} ${stepTag(step)} ${msg}
353
+ `);
354
+ if (objectHasKeys && !excludeDetails) {
355
+ process.stdout.write(`${prettyPrintObject(details)}
356
+ `);
357
+ }
358
+ };
359
+
360
+ // src/logger/logger.ts
361
+ var LEVELS = {
362
+ DEBUG: 10,
363
+ INFO: 20,
364
+ WARNING: 30,
365
+ ERROR: 40,
366
+ CRITICAL: 50
367
+ };
368
+ var levelMap = {
369
+ debug: LEVELS.DEBUG,
370
+ info: LEVELS.INFO,
371
+ warn: LEVELS.WARNING,
372
+ warning: LEVELS.WARNING,
373
+ error: LEVELS.ERROR,
374
+ critical: LEVELS.CRITICAL
375
+ };
376
+
377
+ class Logger {
378
+ options;
379
+ meta;
380
+ coreListeners;
381
+ listeners = [];
382
+ minLevel;
383
+ constructor(options = {}, meta = {}, coreListeners = []) {
384
+ this.options = options;
385
+ this.meta = meta;
386
+ this.coreListeners = coreListeners;
387
+ this.minLevel = options.level ? levelMap[options.level] ?? LEVELS.INFO : LEVELS.INFO;
388
+ }
389
+ child(meta) {
390
+ return new Logger(this.options, { ...this.meta, ...meta }, this.coreListeners);
391
+ }
392
+ session(title) {
393
+ return new LoggerSession(title);
394
+ }
395
+ shouldLog(messageLevel) {
396
+ return messageLevel >= this.minLevel;
397
+ }
398
+ _log(level, msg, args) {
399
+ const time = Date.now();
400
+ const meta = { ...this.meta, ...args ?? {} };
401
+ const isVerbose = this.options.verbose ?? false;
402
+ prettyPrint({ level, time, msg, ...meta }, !isVerbose);
403
+ this.coreListeners.forEach((listener) => {
404
+ listener(level, msg, meta);
405
+ });
406
+ this.listeners.forEach((listener) => {
407
+ listener(level, msg, meta);
408
+ });
409
+ }
410
+ info(message, args) {
411
+ if (this.shouldLog(LEVELS.INFO))
412
+ this._log("INFO", message, args);
413
+ }
414
+ error(message, args) {
415
+ if (this.shouldLog(LEVELS.ERROR))
416
+ this._log("ERROR", message, args);
417
+ }
418
+ debug(message, args) {
419
+ if (this.shouldLog(LEVELS.DEBUG))
420
+ this._log("DEBUG", message, args);
421
+ }
422
+ warn(message, args) {
423
+ if (this.shouldLog(LEVELS.WARNING))
424
+ this._log("WARNING", message, args);
425
+ }
426
+ addListener(listener) {
427
+ this.listeners.push(listener);
428
+ }
429
+ }
155
430
  // src/runtime/loader.ts
156
- async function loadActions(dir) {
431
+ async function loadActions(dir, logger = new Logger) {
157
432
  const glob = new Bun.Glob(`${dir}/**/*.ts`);
158
433
  const files = glob.scanSync();
159
- globalLogger.info("Loading actions from", { files });
434
+ logger.debug("Loading actions from", { files });
160
435
  const actions = [];
161
436
  for (const file of files) {
162
437
  const module = await import(Bun.pathToFileURL(file).href);
163
- globalLogger.info("Loading action", { file });
438
+ logger.debug("Loading action", { file });
164
439
  for (const exported of Object.values(module)) {
165
440
  if (isAction(exported)) {
166
441
  actions.push(exported);
@@ -181,34 +456,34 @@ class ActionExecutor {
181
456
  this.baseContext = baseContext;
182
457
  }
183
458
  async execute(action, triggerName, sourceData) {
459
+ const traceId = Bun.randomUUIDv7();
184
460
  const config = action.config;
461
+ const baseLogger = this.baseContext.logger ?? new Logger;
462
+ const logger = baseLogger.child({
463
+ action: config.name,
464
+ traceId,
465
+ trigger: triggerName
466
+ });
185
467
  const trigger = config.triggers?.find((t) => t.name === triggerName);
186
468
  if (!trigger) {
187
469
  throw new BadRequestError(`Trigger '${triggerName}' not found for action '${config.name}'`);
188
470
  }
189
471
  const actor = await this.resolveActor(trigger, sourceData);
472
+ const session = logger.session(`Basalt Action: ${config.name}`);
473
+ session.bar().info("Trigger", `${trigger.kind} (${triggerName})`).info("Identity", `${actor.id ?? "anonymous"} (${actor.type})`).bar();
190
474
  const ctx = {
191
- requestId: this.baseContext.requestId || `req-${Date.now()}-${Math.random().toString(36).slice(2)}`,
475
+ traceId,
192
476
  triggerName,
193
477
  triggerType: trigger.kind,
194
478
  actor,
195
- logger: this.baseContext.logger || globalLogger,
479
+ logger,
196
480
  db: this.baseContext.db,
197
481
  storage: this.baseContext.storage,
198
- enqueue: this.baseContext.enqueue || this.createEnqueueFn(),
199
- schedule: this.baseContext.schedule || this.createScheduleFn(),
482
+ enqueue: this.baseContext.enqueue || this.createEnqueueFn(logger),
483
+ schedule: this.baseContext.schedule || this.createScheduleFn(logger),
200
484
  org: this.baseContext.org,
201
485
  ...this.baseContext
202
486
  };
203
- const logger = ctx.logger.child({
204
- action: config.name,
205
- requestId: ctx.requestId,
206
- trigger: triggerName
207
- });
208
- logger.info("Action execution started", {
209
- actor: actor.type,
210
- triggerType: trigger.kind
211
- });
212
487
  try {
213
488
  let input = sourceData;
214
489
  if (trigger.map) {
@@ -220,17 +495,21 @@ class ActionExecutor {
220
495
  }
221
496
  await this.checkRateLimit(ctx, config);
222
497
  if (config.access) {
498
+ session.step("Access", "checking...");
223
499
  await this.checkAccess(ctx, config.access);
500
+ session.success("Access", "passed");
501
+ }
502
+ if (config.guard) {
503
+ session.step("Guard", "checking...");
504
+ await this.checkGuard(ctx, input, config);
505
+ session.success("Guard", "passed");
224
506
  }
225
- await this.checkGuard(ctx, input, config);
226
507
  const result = await action(input, ctx);
227
- logger.info("Action execution completed");
508
+ session.end("Success");
228
509
  return result;
229
510
  } catch (error) {
230
- logger.error("Action execution failed", {
231
- error: error.message,
232
- stack: error.stack
233
- });
511
+ session.error("Error", error.message);
512
+ session.fail("Failed");
234
513
  throw error;
235
514
  }
236
515
  }
@@ -314,17 +593,17 @@ class ActionExecutor {
314
593
  }
315
594
  }
316
595
  }
317
- createEnqueueFn() {
596
+ createEnqueueFn(logger) {
318
597
  return async (eventType, data) => {
319
- globalLogger.warn("enqueue called but no event bus configured", {
598
+ logger.warn("enqueue called but no event bus configured", {
320
599
  eventType,
321
600
  data
322
601
  });
323
602
  };
324
603
  }
325
- createScheduleFn() {
604
+ createScheduleFn(logger) {
326
605
  return async (actionName, input, runAt) => {
327
- globalLogger.warn("schedule called but no scheduler configured", {
606
+ logger.warn("schedule called but no scheduler configured", {
328
607
  actionName,
329
608
  runAt,
330
609
  input
@@ -337,8 +616,10 @@ class ActionExecutor {
337
616
  class EventBus {
338
617
  subscriptions = [];
339
618
  executor;
619
+ logger;
340
620
  constructor(baseContext) {
341
621
  this.executor = new ActionExecutor(baseContext);
622
+ this.logger = baseContext.logger;
342
623
  }
343
624
  subscribe(pattern, action, triggerName) {
344
625
  this.subscriptions.push({ pattern, action, triggerName });
@@ -346,14 +627,14 @@ class EventBus {
346
627
  async publish(event) {
347
628
  const matching = this.subscriptions.filter((sub) => this.matchPattern(sub.pattern, event.type));
348
629
  if (matching.length === 0) {
349
- globalLogger.debug("No subscribers for event", { eventType: event.type });
630
+ this.logger.debug("No subscribers for event", { eventType: event.type });
350
631
  return;
351
632
  }
352
633
  const results = await Promise.allSettled(matching.map(async (sub) => {
353
634
  try {
354
635
  return await this.executor.execute(sub.action, sub.triggerName, event);
355
636
  } catch (error) {
356
- globalLogger.error("Event handler failed", {
637
+ this.logger.error("Event handler failed", {
357
638
  event: event.type,
358
639
  action: sub.action.config.name,
359
640
  error: error.message
@@ -363,7 +644,7 @@ class EventBus {
363
644
  }));
364
645
  const failed = results.filter((r) => r.status === "rejected").length;
365
646
  const succeeded = results.filter((r) => r.status === "fulfilled").length;
366
- globalLogger.info("Event published", {
647
+ this.logger.info("Event published", {
367
648
  event: event.type,
368
649
  handlers: matching.length,
369
650
  succeeded,
@@ -379,10 +660,12 @@ class EventBus {
379
660
  // src/runtime/http.ts
380
661
  class HttpServer {
381
662
  config;
663
+ logger;
382
664
  server;
383
665
  router;
384
- constructor(config, router) {
666
+ constructor(config, router, logger = new Logger) {
385
667
  this.config = config;
668
+ this.logger = logger;
386
669
  this.router = router;
387
670
  }
388
671
  async start() {
@@ -410,10 +693,10 @@ class HttpServer {
410
693
  body = await req.json();
411
694
  } else if (contentType.includes("application/x-www-form-urlencoded")) {
412
695
  const formData = await req.formData();
413
- body = Object.fromEntries(formData);
696
+ body = Object.fromEntries(formData.entries());
414
697
  } else if (contentType.includes("multipart/form-data")) {
415
698
  const formData = await req.formData();
416
- body = Object.fromEntries(formData);
699
+ body = Object.fromEntries(formData.entries());
417
700
  } else {
418
701
  body = await req.text();
419
702
  }
@@ -444,7 +727,7 @@ class HttpServer {
444
727
  }
445
728
  });
446
729
  } catch (error) {
447
- globalLogger.error("HTTP request failed", {
730
+ this.logger.error("HTTP request failed", {
448
731
  error: error.message,
449
732
  stack: error.stack
450
733
  });
@@ -472,8 +755,8 @@ class HttpServer {
472
755
  });
473
756
  }
474
757
  },
475
- error(error) {
476
- globalLogger.error("HTTP server error", {
758
+ error: (error) => {
759
+ this.logger.error("HTTP server error", {
477
760
  error: error.message,
478
761
  stack: error.stack
479
762
  });
@@ -485,14 +768,14 @@ class HttpServer {
485
768
  });
486
769
  }
487
770
  });
488
- globalLogger.info("HTTP server started", {
771
+ this.logger.info("HTTP server started", {
489
772
  url: `http://${host}:${port}`
490
773
  });
491
774
  }
492
775
  async stop() {
493
776
  if (this.server) {
494
777
  this.server.stop();
495
- globalLogger.info("HTTP server stopped");
778
+ this.logger.info("HTTP server stopped");
496
779
  }
497
780
  }
498
781
  getUrl() {
@@ -520,21 +803,23 @@ function getCorsHeaders(corsConfig) {
520
803
  // src/runtime/mcp-server.ts
521
804
  class McpServer {
522
805
  context;
523
- constructor(context) {
806
+ logger;
807
+ constructor(context, logger = new Logger) {
524
808
  this.context = context;
809
+ this.logger = logger;
525
810
  }
526
811
  register(action, trigger) {
527
- globalLogger.info("Registering MCP tool", {
812
+ this.logger.info("Registering MCP tool", {
528
813
  tool: trigger.tool,
529
814
  action: action.config.name,
530
815
  context: this.context
531
816
  });
532
817
  }
533
818
  async start() {
534
- globalLogger.info("MCP Server started");
819
+ this.logger.info("MCP Server started");
535
820
  }
536
821
  async stop() {
537
- globalLogger.info("MCP Server stopped");
822
+ this.logger.info("MCP Server stopped");
538
823
  }
539
824
  }
540
825
 
@@ -588,11 +873,7 @@ class Router {
588
873
  };
589
874
  }
590
875
  getRoutes() {
591
- return this.routes.map((r) => ({
592
- method: r.method,
593
- path: r.trigger.path,
594
- action: r.action.config.name
595
- }));
876
+ return this.routes;
596
877
  }
597
878
  }
598
879
 
@@ -601,8 +882,10 @@ import Baker from "cronbake";
601
882
  class Scheduler {
602
883
  baker = Baker.create();
603
884
  executor;
885
+ logger;
604
886
  constructor(baseContext) {
605
887
  this.executor = new ActionExecutor(baseContext);
888
+ this.logger = baseContext.logger;
606
889
  }
607
890
  schedule(action, trigger) {
608
891
  this.baker.add({
@@ -610,13 +893,13 @@ class Scheduler {
610
893
  cron: trigger.schedule,
611
894
  callback: async () => {
612
895
  try {
613
- globalLogger.info("Running scheduled action", {
896
+ this.logger.info("Running scheduled action", {
614
897
  action: action.config.name,
615
898
  schedule: trigger.schedule
616
899
  });
617
900
  await this.executor.execute(action, trigger.name, {});
618
901
  } catch (error) {
619
- globalLogger.error("Scheduled action failed", {
902
+ this.logger.error("Scheduled action failed", {
620
903
  action: action.config.name,
621
904
  error: error.message,
622
905
  stack: error.stack
@@ -627,11 +910,11 @@ class Scheduler {
627
910
  }
628
911
  start() {
629
912
  this.baker.bakeAll();
630
- globalLogger.info("Scheduler started");
913
+ this.logger.info("Scheduler started");
631
914
  }
632
915
  stop() {
633
916
  this.baker.stopAll();
634
- globalLogger.info("Stopped all cron jobs");
917
+ this.logger.info("Stopped all cron jobs");
635
918
  }
636
919
  }
637
920
 
@@ -643,21 +926,23 @@ class BasaltServer {
643
926
  scheduler;
644
927
  mcpServer;
645
928
  httpServer;
929
+ logger;
646
930
  actions = [];
647
931
  constructor(config) {
648
932
  this.config = config;
933
+ this.logger = new Logger(config.logger ?? {});
649
934
  const baseContext = this.buildBaseContext();
650
935
  this.router = new Router(baseContext);
651
936
  this.eventBus = new EventBus(baseContext);
652
937
  this.scheduler = new Scheduler(baseContext);
653
- this.httpServer = new HttpServer(this.config, this.router);
938
+ this.httpServer = new HttpServer(this.config, this.router, this.logger);
654
939
  if (this.config.mcp?.enabled) {
655
- this.mcpServer = new McpServer(baseContext);
940
+ this.mcpServer = new McpServer(baseContext, this.logger);
656
941
  }
657
942
  }
658
943
  buildBaseContext() {
659
944
  return {
660
- logger: globalLogger,
945
+ logger: this.logger,
661
946
  db: undefined,
662
947
  storage: undefined,
663
948
  enqueue: async (eventType, data) => {
@@ -678,11 +963,11 @@ class BasaltServer {
678
963
  const actionName = action.config.name;
679
964
  if (typeof when === "number") {
680
965
  const runAt = new Date(Date.now() + when * 1000);
681
- globalLogger.info("Scheduling action", { actionName, runAt, input });
966
+ this.logger.info("Scheduling action", { actionName, runAt, input });
682
967
  } else if (when instanceof Date) {
683
- globalLogger.info("Scheduling action", { actionName, runAt: when, input });
968
+ this.logger.info("Scheduling action", { actionName, runAt: when, input });
684
969
  } else if (typeof when === "string") {
685
- globalLogger.info("Scheduling recurring action", {
970
+ this.logger.info("Scheduling recurring action", {
686
971
  actionName,
687
972
  cron: when,
688
973
  input
@@ -690,7 +975,7 @@ class BasaltServer {
690
975
  }
691
976
  }
692
977
  async initialize() {
693
- this.actions = await loadActions(this.config.actionsDir || "./src/actions");
978
+ this.actions = await loadActions(this.config.actionsDir || "./src/actions", this.logger);
694
979
  for (const action of this.actions) {
695
980
  if (!action.config.triggers)
696
981
  continue;
@@ -699,7 +984,7 @@ class BasaltServer {
699
984
  case "api": {
700
985
  const apiTrigger = trigger;
701
986
  this.router.register(action, apiTrigger);
702
- globalLogger.info("Registered API route", {
987
+ this.logger.info("Registered API route", {
703
988
  method: apiTrigger.method,
704
989
  path: apiTrigger.path,
705
990
  action: action.config.name
@@ -709,7 +994,7 @@ class BasaltServer {
709
994
  case "cron": {
710
995
  const cronTrigger = trigger;
711
996
  this.scheduler.schedule(action, cronTrigger);
712
- globalLogger.info("Registered cron job", {
997
+ this.logger.info("Registered cron job", {
713
998
  schedule: cronTrigger.schedule,
714
999
  action: action.config.name
715
1000
  });
@@ -718,7 +1003,7 @@ class BasaltServer {
718
1003
  case "event": {
719
1004
  const eventTrigger = trigger;
720
1005
  this.eventBus.subscribe(eventTrigger.event, action, eventTrigger.name);
721
- globalLogger.info("Registered event handler", {
1006
+ this.logger.info("Registered event handler", {
722
1007
  event: eventTrigger.event,
723
1008
  action: action.config.name
724
1009
  });
@@ -727,7 +1012,7 @@ class BasaltServer {
727
1012
  case "agent": {
728
1013
  const agentTrigger = trigger;
729
1014
  this.mcpServer?.register(action, agentTrigger);
730
- globalLogger.info("Registered MCP tool", {
1015
+ this.logger.info("Registered MCP tool", {
731
1016
  tool: agentTrigger.tool,
732
1017
  action: action.config.name
733
1018
  });
@@ -736,7 +1021,7 @@ class BasaltServer {
736
1021
  }
737
1022
  }
738
1023
  }
739
- globalLogger.info("Basalt initialized", {
1024
+ this.logger.info("Basalt initialized", {
740
1025
  actions: this.actions.length,
741
1026
  routes: this.router.getRoutes().length
742
1027
  });
@@ -769,6 +1054,7 @@ class BasaltServer {
769
1054
 
770
1055
  // src/runtime/dev.ts
771
1056
  async function createDevServer(config) {
1057
+ const logger = new Logger(config.logger ?? {});
772
1058
  const server = new BasaltServer(config);
773
1059
  await server.initialize();
774
1060
  if (config.dev?.watch !== false) {
@@ -778,16 +1064,16 @@ async function createDevServer(config) {
778
1064
  return;
779
1065
  if (!/\.(ts|js)$/.test(filename))
780
1066
  return;
781
- globalLogger.info("Action file changed, regenerating...", {
1067
+ logger.info("Action file changed, regenerating...", {
782
1068
  filename,
783
1069
  eventType
784
1070
  });
785
1071
  try {
786
- const actions = await loadActions(actionsDir);
1072
+ const actions = await loadActions(actionsDir, logger);
787
1073
  await generateActionTypes(actions);
788
- globalLogger.info("Types regenerated");
1074
+ logger.info("Types regenerated");
789
1075
  } catch (error) {
790
- globalLogger.error("Failed to regenerate types", {
1076
+ logger.error("Failed to regenerate types", {
791
1077
  error: error.message
792
1078
  });
793
1079
  }
package/dist/index.d.ts CHANGED
@@ -1,5 +1,11 @@
1
1
  type DatabaseConfig = {};
2
- type LoggerOptions = {};
2
+ type LogLevel = "debug" | "info" | "warn" | "error" | "critical";
3
+ type LoggerOptions = {
4
+ /** Minimum log level (default: 'info') */
5
+ level?: LogLevel;
6
+ /** Show verbose output with metadata details (default: false) */
7
+ verbose?: boolean;
8
+ };
3
9
  type StorageConfig = {};
4
10
  interface BasaltConfig {
5
11
  /**
@@ -76,6 +82,32 @@ declare function loadConfig(): Promise<BasaltConfig>;
76
82
  declare function defineConfig(config: BasaltConfig): BasaltConfig;
77
83
  import { TSchema as TSchema2 } from "typebox";
78
84
  import { Static, TSchema } from "typebox";
85
+ /**
86
+ * A structured logging session with clack-style box-drawing output.
87
+ * Created via `logger.session("title")`.
88
+ */
89
+ declare class LoggerSession {
90
+ private output;
91
+ private startTime;
92
+ constructor(title: string, output?: NodeJS.WritableStream);
93
+ private write;
94
+ /** Static info line: ◇ label: detail */
95
+ info(label: string, detail?: string): this;
96
+ /** In-progress step: ● label: detail */
97
+ step(label: string, detail?: string): this;
98
+ /** Completed step: ✔ label: detail */
99
+ success(label: string, detail?: string): this;
100
+ /** Warning step: ▲ label: detail */
101
+ warn(label: string, detail?: string): this;
102
+ /** Error step: ✖ label: detail */
103
+ error(label: string, detail?: string): this;
104
+ /** Empty separator bar: │ */
105
+ bar(): this;
106
+ /** Close the session with success: └ message (Xms) */
107
+ end(message?: string): void;
108
+ /** Close the session as error: └ message (Xms) */
109
+ fail(message?: string): void;
110
+ }
79
111
  declare const LEVELS: {
80
112
  readonly DEBUG: 10;
81
113
  readonly INFO: 20;
@@ -83,15 +115,20 @@ declare const LEVELS: {
83
115
  readonly ERROR: 40;
84
116
  readonly CRITICAL: 50;
85
117
  };
86
- type LogLevel = keyof typeof LEVELS;
87
- type LogListener = (level: LogLevel, msg: string, args?: unknown) => void;
118
+ type LogLevel2 = keyof typeof LEVELS;
119
+ type LogListener = (level: LogLevel2, msg: string, args?: unknown) => void;
88
120
  declare class Logger {
89
- readonly isVerbose: boolean;
121
+ private readonly options;
90
122
  private readonly meta;
91
123
  private readonly coreListeners;
92
124
  private readonly listeners;
93
- constructor(isVerbose?: boolean, meta?: Record<string, unknown>, coreListeners?: LogListener[]);
125
+ private readonly minLevel;
126
+ constructor(options?: LoggerOptions, meta?: Record<string, unknown>, coreListeners?: LogListener[]);
127
+ /** Create a child logger with additional metadata */
94
128
  child(meta: Record<string, unknown>): Logger;
129
+ /** Start a structured logging session with clack-style output */
130
+ session(title: string): LoggerSession;
131
+ private shouldLog;
95
132
  private _log;
96
133
  info(message: string, args?: unknown): void;
97
134
  error(message: string, args?: unknown): void;
@@ -128,7 +165,7 @@ interface ApiTrigger extends BaseTrigger<"api"> {
128
165
  interface ApiRequest {
129
166
  method: string;
130
167
  path: string;
131
- params: Record<string, string>;
168
+ params: Record<string, string | undefined>;
132
169
  query: Record<string, string>;
133
170
  body: unknown;
134
171
  headers: Record<string, string>;
@@ -256,7 +293,7 @@ type BaseActionContext = {
256
293
  logger: Logger;
257
294
  triggerName: string;
258
295
  triggerType: TriggerKind;
259
- requestId: string;
296
+ traceId: string;
260
297
  };
261
298
  type ExtendActionContext = {};
262
299
  type ActionContext = BaseActionContext & ExtendActionContext;
package/dist/index.js CHANGED
@@ -7,9 +7,8 @@ import {
7
7
  NotFoundError,
8
8
  UnauthorizedError,
9
9
  defineConfig,
10
- globalLogger,
11
10
  loadConfig
12
- } from "./shared/chunk-b636e30q.js";
11
+ } from "./shared/chunk-s3hrp89d.js";
13
12
  // src/core/action.ts
14
13
  import { Value } from "typebox/value";
15
14
  function resolveRateLimitRules(config, triggerType) {
@@ -85,8 +84,6 @@ async function checkGuard(ctx, input, config) {
85
84
  }
86
85
  function action(config, handler) {
87
86
  const wrapped = async (input, ctx) => {
88
- const logger = ctx.log ? ctx.log.child({ action: config.name, requestId: ctx.requestId }) : globalLogger.child({ action: config.name, requestId: ctx.requestId });
89
- logger.info("Action started", { input, trigger: ctx.triggerName });
90
87
  try {
91
88
  if (config.input && !Value.Check(config.input, input)) {
92
89
  const errors = [...Value.Errors(config.input, input)];
@@ -97,14 +94,8 @@ function action(config, handler) {
97
94
  await checkAccess(ctx, config.access);
98
95
  }
99
96
  await checkGuard(ctx, input, config);
100
- const result = await handler(input, ctx);
101
- logger.info("Action completed successfully");
102
- return result;
97
+ return await handler(input, ctx);
103
98
  } catch (error) {
104
- logger.error("Action failed", {
105
- error: error.message,
106
- stack: error.stack
107
- });
108
99
  throw error;
109
100
  }
110
101
  };
@@ -0,0 +1,79 @@
1
+ import { createRequire } from "node:module";
2
+ var __create = Object.create;
3
+ var __getProtoOf = Object.getPrototypeOf;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __toESM = (mod, isNodeMode, target) => {
8
+ target = mod != null ? __create(__getProtoOf(mod)) : {};
9
+ const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
10
+ for (let key of __getOwnPropNames(mod))
11
+ if (!__hasOwnProp.call(to, key))
12
+ __defProp(to, key, {
13
+ get: () => mod[key],
14
+ enumerable: true
15
+ });
16
+ return to;
17
+ };
18
+ var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
19
+
20
+ // src/config/loader.ts
21
+ function loadConfig() {
22
+ return Promise.resolve({});
23
+ }
24
+
25
+ // src/config/index.ts
26
+ function defineConfig(config) {
27
+ return config;
28
+ }
29
+
30
+ // src/utils/errors.ts
31
+ class BasaltError extends Error {
32
+ code;
33
+ status;
34
+ constructor(message, code, status) {
35
+ super(message);
36
+ this.code = code;
37
+ this.status = status;
38
+ this.name = this.constructor.name;
39
+ Object.setPrototypeOf(this, new.target.prototype);
40
+ }
41
+ }
42
+
43
+ class NotFoundError extends BasaltError {
44
+ constructor(message = "Resource not found") {
45
+ super(message, "NOT_FOUND", 404);
46
+ }
47
+ }
48
+
49
+ class UnauthorizedError extends BasaltError {
50
+ constructor(message = "Unauthorized") {
51
+ super(message, "UNAUTHORIZED", 401);
52
+ }
53
+ }
54
+
55
+ class ForbiddenError extends BasaltError {
56
+ constructor(message = "Forbidden") {
57
+ super(message, "FORBIDDEN", 403);
58
+ }
59
+ }
60
+
61
+ class BadRequestError extends BasaltError {
62
+ constructor(message = "Bad Request") {
63
+ super(message, "BAD_REQUEST", 400);
64
+ }
65
+ }
66
+
67
+ class InternalServerError extends BasaltError {
68
+ constructor(message = "Internal Server Error") {
69
+ super(message, "INTERNAL_SERVER_ERROR", 500);
70
+ }
71
+ }
72
+
73
+ class NonRetriableError extends BasaltError {
74
+ constructor(message) {
75
+ super(message, "NON_RETRIABLE_ERROR", 500);
76
+ }
77
+ }
78
+
79
+ export { __toESM, __commonJS, loadConfig, defineConfig, BasaltError, NotFoundError, UnauthorizedError, ForbiddenError, BadRequestError, InternalServerError, NonRetriableError };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gravity-run",
3
- "version": "0.0.6",
3
+ "version": "0.0.7",
4
4
  "description": "A framework for building scalable applications",
5
5
  "homepage": "https://github.com/alihussnainrb/gravity#readme",
6
6
  "bugs": {
@@ -80,6 +80,7 @@
80
80
  "cronbake": "^0.4.0",
81
81
  "glob": "^13.0.1",
82
82
  "inquirer": "^13.2.2",
83
+ "is-unicode-supported": "^2.1.0",
83
84
  "typebox": "^1.0.81"
84
85
  }
85
86
  }
@@ -1,274 +0,0 @@
1
- import { createRequire } from "node:module";
2
- var __create = Object.create;
3
- var __getProtoOf = Object.getPrototypeOf;
4
- var __defProp = Object.defineProperty;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __hasOwnProp = Object.prototype.hasOwnProperty;
7
- var __toESM = (mod, isNodeMode, target) => {
8
- target = mod != null ? __create(__getProtoOf(mod)) : {};
9
- const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
10
- for (let key of __getOwnPropNames(mod))
11
- if (!__hasOwnProp.call(to, key))
12
- __defProp(to, key, {
13
- get: () => mod[key],
14
- enumerable: true
15
- });
16
- return to;
17
- };
18
- var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
19
-
20
- // node_modules/picocolors/picocolors.js
21
- var require_picocolors = __commonJS((exports, module) => {
22
- var p = process || {};
23
- var argv = p.argv || [];
24
- var env = p.env || {};
25
- var isColorSupported = !(!!env.NO_COLOR || argv.includes("--no-color")) && (!!env.FORCE_COLOR || argv.includes("--color") || p.platform === "win32" || (p.stdout || {}).isTTY && env.TERM !== "dumb" || !!env.CI);
26
- var formatter = (open, close, replace = open) => (input) => {
27
- let string = "" + input, index = string.indexOf(close, open.length);
28
- return ~index ? open + replaceClose(string, close, replace, index) + close : open + string + close;
29
- };
30
- var replaceClose = (string, close, replace, index) => {
31
- let result = "", cursor = 0;
32
- do {
33
- result += string.substring(cursor, index) + replace;
34
- cursor = index + close.length;
35
- index = string.indexOf(close, cursor);
36
- } while (~index);
37
- return result + string.substring(cursor);
38
- };
39
- var createColors = (enabled = isColorSupported) => {
40
- let f = enabled ? formatter : () => String;
41
- return {
42
- isColorSupported: enabled,
43
- reset: f("\x1B[0m", "\x1B[0m"),
44
- bold: f("\x1B[1m", "\x1B[22m", "\x1B[22m\x1B[1m"),
45
- dim: f("\x1B[2m", "\x1B[22m", "\x1B[22m\x1B[2m"),
46
- italic: f("\x1B[3m", "\x1B[23m"),
47
- underline: f("\x1B[4m", "\x1B[24m"),
48
- inverse: f("\x1B[7m", "\x1B[27m"),
49
- hidden: f("\x1B[8m", "\x1B[28m"),
50
- strikethrough: f("\x1B[9m", "\x1B[29m"),
51
- black: f("\x1B[30m", "\x1B[39m"),
52
- red: f("\x1B[31m", "\x1B[39m"),
53
- green: f("\x1B[32m", "\x1B[39m"),
54
- yellow: f("\x1B[33m", "\x1B[39m"),
55
- blue: f("\x1B[34m", "\x1B[39m"),
56
- magenta: f("\x1B[35m", "\x1B[39m"),
57
- cyan: f("\x1B[36m", "\x1B[39m"),
58
- white: f("\x1B[37m", "\x1B[39m"),
59
- gray: f("\x1B[90m", "\x1B[39m"),
60
- bgBlack: f("\x1B[40m", "\x1B[49m"),
61
- bgRed: f("\x1B[41m", "\x1B[49m"),
62
- bgGreen: f("\x1B[42m", "\x1B[49m"),
63
- bgYellow: f("\x1B[43m", "\x1B[49m"),
64
- bgBlue: f("\x1B[44m", "\x1B[49m"),
65
- bgMagenta: f("\x1B[45m", "\x1B[49m"),
66
- bgCyan: f("\x1B[46m", "\x1B[49m"),
67
- bgWhite: f("\x1B[47m", "\x1B[49m"),
68
- blackBright: f("\x1B[90m", "\x1B[39m"),
69
- redBright: f("\x1B[91m", "\x1B[39m"),
70
- greenBright: f("\x1B[92m", "\x1B[39m"),
71
- yellowBright: f("\x1B[93m", "\x1B[39m"),
72
- blueBright: f("\x1B[94m", "\x1B[39m"),
73
- magentaBright: f("\x1B[95m", "\x1B[39m"),
74
- cyanBright: f("\x1B[96m", "\x1B[39m"),
75
- whiteBright: f("\x1B[97m", "\x1B[39m"),
76
- bgBlackBright: f("\x1B[100m", "\x1B[49m"),
77
- bgRedBright: f("\x1B[101m", "\x1B[49m"),
78
- bgGreenBright: f("\x1B[102m", "\x1B[49m"),
79
- bgYellowBright: f("\x1B[103m", "\x1B[49m"),
80
- bgBlueBright: f("\x1B[104m", "\x1B[49m"),
81
- bgMagentaBright: f("\x1B[105m", "\x1B[49m"),
82
- bgCyanBright: f("\x1B[106m", "\x1B[49m"),
83
- bgWhiteBright: f("\x1B[107m", "\x1B[49m")
84
- };
85
- };
86
- module.exports = createColors();
87
- module.exports.createColors = createColors;
88
- });
89
-
90
- // src/config/loader.ts
91
- function loadConfig() {
92
- return Promise.resolve({});
93
- }
94
-
95
- // src/config/index.ts
96
- function defineConfig(config) {
97
- return config;
98
- }
99
-
100
- // src/utils/errors.ts
101
- class BasaltError extends Error {
102
- code;
103
- status;
104
- constructor(message, code, status) {
105
- super(message);
106
- this.code = code;
107
- this.status = status;
108
- this.name = this.constructor.name;
109
- Object.setPrototypeOf(this, new.target.prototype);
110
- }
111
- }
112
-
113
- class NotFoundError extends BasaltError {
114
- constructor(message = "Resource not found") {
115
- super(message, "NOT_FOUND", 404);
116
- }
117
- }
118
-
119
- class UnauthorizedError extends BasaltError {
120
- constructor(message = "Unauthorized") {
121
- super(message, "UNAUTHORIZED", 401);
122
- }
123
- }
124
-
125
- class ForbiddenError extends BasaltError {
126
- constructor(message = "Forbidden") {
127
- super(message, "FORBIDDEN", 403);
128
- }
129
- }
130
-
131
- class BadRequestError extends BasaltError {
132
- constructor(message = "Bad Request") {
133
- super(message, "BAD_REQUEST", 400);
134
- }
135
- }
136
-
137
- class InternalServerError extends BasaltError {
138
- constructor(message = "Internal Server Error") {
139
- super(message, "INTERNAL_SERVER_ERROR", 500);
140
- }
141
- }
142
-
143
- class NonRetriableError extends BasaltError {
144
- constructor(message) {
145
- super(message, "NON_RETRIABLE_ERROR", 500);
146
- }
147
- }
148
-
149
- // src/logger/pretty-print.ts
150
- var import_picocolors = __toESM(require_picocolors(), 1);
151
- var stepTag = (step) => step ? import_picocolors.default.bold(import_picocolors.default.cyan(step)) : "";
152
- var timestampTag = (timestamp) => import_picocolors.default.gray(timestamp);
153
- var traceIdTag = (traceId) => traceId ? import_picocolors.default.gray(traceId) : "";
154
- var levelTags = {
155
- error: import_picocolors.default.red("[ERROR]"),
156
- info: import_picocolors.default.blue("[INFO]"),
157
- warn: import_picocolors.default.yellow("[WARN]"),
158
- debug: import_picocolors.default.gray("[DEBUG]")
159
- };
160
- var numericTag = (value) => import_picocolors.default.green(value);
161
- var stringTag = (value) => import_picocolors.default.cyan(value);
162
- var booleanTag = (value) => import_picocolors.default.blue(value);
163
- var arrayBrackets = ["[", "]"].map((s) => import_picocolors.default.gray(s));
164
- var objectBrackets = ["{", "}"].map((s) => import_picocolors.default.gray(s));
165
- var prettyPrintObject = (obj, depth = 0, parentIsLast = false, prefix = "") => {
166
- const tab = prefix + (depth === 0 ? "" : parentIsLast ? "│ " : "│ ");
167
- if (depth > 2)
168
- return `${tab} └ ${import_picocolors.default.gray("[...]")}`;
169
- const entries = Object.entries(obj);
170
- return entries.map(([key, value], index) => {
171
- const isLast = index === entries.length - 1;
172
- const isObject = typeof value === "object" && value !== null;
173
- const branch = isLast ? "└" : "├";
174
- if (isObject) {
175
- const subObject = prettyPrintObject(value, depth + 1, isLast, tab);
176
- const [start, end] = Array.isArray(value) ? arrayBrackets : objectBrackets;
177
- return `${tab}${branch} ${key}: ${start}
178
- ${subObject}
179
- ${tab}${isLast ? " " : "│"} ${end}`;
180
- }
181
- let printedValue = value;
182
- if (typeof value === "number")
183
- printedValue = numericTag(String(value));
184
- else if (typeof value === "boolean")
185
- printedValue = booleanTag(String(value));
186
- else if (typeof value === "string")
187
- printedValue = stringTag(value);
188
- return `${tab}${branch} ${key}: ${printedValue}`;
189
- }).join(`
190
- `);
191
- };
192
- var prettyPrint = (json, excludeDetails = false) => {
193
- const { time, traceId, msg, flows, level, step, ...details } = json;
194
- const levelTag = levelTags[level] ?? levelTags.info;
195
- const timestamp = timestampTag(`[${new Date(time).toLocaleTimeString()}]`);
196
- const objectHasKeys = Object.keys(details).length > 0;
197
- process.stdout.write(`${timestamp} ${traceIdTag(traceId)} ${levelTag} ${stepTag(step)} ${msg}
198
- `);
199
- if (objectHasKeys && !excludeDetails) {
200
- process.stdout.write(`${prettyPrintObject(details)}
201
- `);
202
- }
203
- };
204
-
205
- // src/logger/logger.ts
206
- var LEVELS = {
207
- DEBUG: 10,
208
- INFO: 20,
209
- WARNING: 30,
210
- ERROR: 40,
211
- CRITICAL: 50
212
- };
213
- var levelMap = {
214
- debug: LEVELS.DEBUG,
215
- info: LEVELS.INFO,
216
- warn: LEVELS.WARNING,
217
- warning: LEVELS.WARNING,
218
- error: LEVELS.ERROR,
219
- critical: LEVELS.CRITICAL
220
- };
221
- var getLogLevel = () => {
222
- const level = process.env.LOG_LEVEL ?? "info";
223
- return levelMap[level] ?? LEVELS.INFO;
224
- };
225
- var shouldLog = (messageLevel) => {
226
- return messageLevel >= getLogLevel();
227
- };
228
-
229
- class Logger {
230
- isVerbose;
231
- meta;
232
- coreListeners;
233
- listeners = [];
234
- constructor(isVerbose = false, meta = {}, coreListeners = []) {
235
- this.isVerbose = isVerbose;
236
- this.meta = meta;
237
- this.coreListeners = coreListeners;
238
- }
239
- child(meta) {
240
- return new Logger(this.isVerbose, { ...this.meta, ...meta }, this.coreListeners);
241
- }
242
- _log(level, msg, args) {
243
- const time = Date.now();
244
- const meta = { ...this.meta, ...args ?? {} };
245
- prettyPrint({ level, time, msg, ...meta }, !this.isVerbose);
246
- this.coreListeners.forEach((listener) => {
247
- listener(level, msg, meta);
248
- });
249
- this.listeners.forEach((listener) => {
250
- listener(level, msg, meta);
251
- });
252
- }
253
- info(message, args) {
254
- if (shouldLog(LEVELS.INFO))
255
- this._log("INFO", message, args);
256
- }
257
- error(message, args) {
258
- if (shouldLog(LEVELS.ERROR))
259
- this._log("ERROR", message, args);
260
- }
261
- debug(message, args) {
262
- if (shouldLog(LEVELS.DEBUG))
263
- this._log("DEBUG", message, args);
264
- }
265
- warn(message, args) {
266
- if (shouldLog(LEVELS.WARNING))
267
- this._log("WARNING", message, args);
268
- }
269
- addListener(listener) {
270
- this.listeners.push(listener);
271
- }
272
- }
273
- var globalLogger = new Logger;
274
- export { loadConfig, defineConfig, globalLogger, BasaltError, NotFoundError, UnauthorizedError, ForbiddenError, BadRequestError, InternalServerError, NonRetriableError };