@bluelibs/runner 4.3.0 → 4.4.1

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/AI.md CHANGED
@@ -24,7 +24,8 @@ This is the foundation of trust for any DI framework.
24
24
  - **Resources**: Managed singletons (init/dispose).
25
25
  - **Events**: Decoupled communication. Flow: `emit → validation → find & order hooks → run hooks (stoppable)`
26
26
  - **Hooks**: Lightweight event listeners. Async and awaited by default.
27
- - **Middleware**: Cross-cutting concerns. Async and awaited by default.
27
+ - **Middleware**: Cross-cutting concerns. Async and awaited by default. Optionally contract-enforcing for input/output.
28
+ - **Tags**: Metadata for organizing, filtering, enforcing input/output contracts to tasks or resources.
28
29
 
29
30
  ## Quick Start
30
31
 
@@ -234,8 +235,8 @@ const auth = taskMiddleware<
234
235
  // of a resource and replaces it with a non-destructive update.
235
236
  const softDelete = resourceMiddleware({
236
237
  id: "app.middleware.softDelete",
237
- run: async ({ next }) => {
238
- const resourceInstance = await next(); // The original resource instance
238
+ run: async ({ resource, next }) => {
239
+ const resourceInstance = await next(resource.config); // The original resource instance
239
240
 
240
241
  // This example assumes the resource has `update` and `delete` methods.
241
242
  // A more robust implementation would check for their existence.
@@ -305,7 +306,12 @@ const globalTaskMiddleware = taskMiddleware({
305
306
  // if you have dependencies as task, exclude them via everywhere filter.
306
307
  });
307
308
 
308
- // Similar behavior for resourceMiddleware({ ... });
309
+ // Global resource middleware (same everywhere semantics)
310
+ const globalResourceMiddleware = resourceMiddleware({
311
+ id: "...",
312
+ everywhere: true, // or: (resource) => boolean
313
+ run: async ({ next }) => next(),
314
+ });
309
315
  ```
310
316
 
311
317
  ## Context (request-scoped values)
@@ -376,15 +382,20 @@ const app = resource({
376
382
 
377
383
  ## Namespacing
378
384
 
379
- As your app grows, use a consistent naming convention. This is the recommended format:
385
+ As your app grows, you'll want consistent naming. Here's the convention that won't drive you crazy:
386
+
387
+ | Type | Format |
388
+ | ------------------- | ------------------------------------------------ |
389
+ | Resources | `{domain}.resources.{resource-name}` |
390
+ | Tasks | `{domain}.tasks.{task-name}` |
391
+ | Events | `{domain}.events.{event-name}` |
392
+ | Hooks | `{domain}.hooks.on-{event-name}` |
393
+ | Task Middleware | `{domain}.middleware.task.{middleware-name}` |
394
+ | Resource Middleware | `{domain}.middleware.resource.{middleware-name}` |
395
+
396
+ We recommend kebab-case for file names and ids. Suffix files with their primitive type: `*.task.ts`, `*.task-middleware.ts`, `*.hook.ts`, etc.
380
397
 
381
- | Type | Format |
382
- | ---------- | -------------------------------------- |
383
- | Tasks | `{domain}.tasks.{taskName}` |
384
- | Hooks | `{domain}.hooks.on{EventName}` |
385
- | Resources | `{domain}.resources.{resourceName}` |
386
- | Events | `{domain}.events.{eventName}` |
387
- | Middleware | `{domain}.middleware.{middlewareName}` |
398
+ Folders can look something like this: `src/app/users/tasks/create-user.task.ts`. For domain: `app.users` and a task. Use `middleware/task|resource` for middleware files.
388
399
 
389
400
  ## Factory Pattern
390
401
 
package/LICENSE.md CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2024-present Theodor Diaconu <theodor.diaconu@cultofcoders.com>
1
+ Copyright (c) 2024-present Theodor Diaconu <theodor@bluelibs.com>
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
4
 
package/README.md CHANGED
@@ -9,11 +9,17 @@ _Or: How I Learned to Stop Worrying and Love Dependency Injection_
9
9
  <a href="https://github.com/bluelibs/runner" target="_blank"><img src="https://img.shields.io/badge/github-blue" alt="GitHub" /></a>
10
10
  </p>
11
11
 
12
- - [UX Friendly Docs](https://bluelibs.github.io/runner/)
13
- - [AI Friendly Docs (<4500 tokens)](https://github.com/bluelibs/runner/blob/main/AI.md)
14
- - [Migrate from 3.x.x to 4.x.x](https://github.com/bluelibs/runner/blob/main/readmes/MIGRATION.md)
15
- - [Runner Lore](https://github.com/bluelibs/runner/blob/main/readmes)
16
- - [Example: Express + OpenAPI + SQLite](https://github.com/bluelibs/runner/tree/main/examples/express-openapi-sqlite)
12
+ | Resource | Type | Notes |
13
+ | ------------------------------------------------------------------------------------------------------------------- | ------- | ------------------------------------------------------------- |
14
+ | [Presentation Website](https://runner.bluelibs.com/) | Website | Overview, features, and highlights |
15
+ | [BlueLibs Runner GitHub](https://github.com/bluelibs/runner) | GitHub | Source code, issues, and releases |
16
+ | [BlueLibs Runner Dev](https://github.com/bluelibs/runner-dev) | GitHub | Development tools and CLI for BlueLibs Runner |
17
+ | [UX Friendly Docs](https://bluelibs.github.io/runner/) | Docs | Clean, navigable documentation |
18
+ | [AI Friendly Docs (<5000 tokens)](https://github.com/bluelibs/runner/blob/main/AI.md) | Docs | Short, token-friendly summary (<5000 tokens) |
19
+ | [Migrate from 3.x.x to 4.x.x](https://github.com/bluelibs/runner/blob/main/readmes/MIGRATION.md) | Guide | Step-by-step upgrade from v3 to v4 |
20
+ | [Runner Lore](https://github.com/bluelibs/runner/blob/main/readmes) | Docs | Design notes, deep dives, and context |
21
+ | [Example: Express + OpenAPI + SQLite](https://github.com/bluelibs/runner/tree/main/examples/express-openapi-sqlite) | Example | Full Express + OpenAPI + SQLite demo |
22
+ | [OpenAI Runner Chatbot](https://chatgpt.com/g/g-68b756abec648191aa43eaa1ea7a7945-runner?model=gpt-5-thinking) | Chatbot | Ask questions interactively, or feed README.md to your own AI |
17
23
 
18
24
  Welcome to BlueLibs Runner, where we've taken the chaos of modern application architecture and turned it into something that won't make you question your life choices at 3am. This isn't just another framework – it's your new best friend who actually understands that code should be readable, testable, and not require a PhD in abstract nonsense to maintain.
19
25
 
@@ -90,9 +96,9 @@ const { dispose } = await run(app, { debug: "verbose" });
90
96
 
91
97
  > **runtime:** "'Less lines than Hello World.' Incredible. All you had to do was externalize 90% of the work into `express`, Node, and me. But please, bask in the brevity. I’ll be over here negotiating a peace treaty between your dependency tree and reality."
92
98
 
93
- ## The Big Four
99
+ ## The Big Five
94
100
 
95
- The framework is built around four core concepts: Tasks, Resources, Events, and Middleware. Understanding them is key to using the runner effectively.
101
+ The framework is built around five core concepts: Tasks, Resources, Events, Middleware, and Tags. Understanding them is key to using the runner effectively.
96
102
 
97
103
  ### Tasks
98
104
 
@@ -569,7 +575,149 @@ const loggedTask = task({
569
575
  });
570
576
  ```
571
577
 
572
- > **runtime:** "Ah, the onion pattern. A matryoshka doll made of promises. Every peel reveals… another logger. Another tracer. Another 'just a tiny wrapper'. Ill keep unwrapping until we hit the single lonely `return` you were hiding like state secrets."
578
+ > **runtime:** "Ah, the onion pattern. A matryoshka doll made of promises. Every peel reveals… another logger. Another tracer. Another 'just a tiny wrapper'. I'll keep unwrapping until we hit the single lonely `return` you were hiding like state secrets."
579
+
580
+ ### Tags
581
+
582
+ Tags are metadata that can influence system behavior. Unlike meta properties, tags can be queried at runtime to build dynamic functionality. They can be simple strings or structured configuration objects.
583
+
584
+ #### Basic Usage
585
+
586
+ ```typescript
587
+ import { tag, task, hook, globals } from "@bluelibs/runner";
588
+
589
+ // Simple string tags
590
+ const apiTask = task({
591
+ id: "app.tasks.getUserData",
592
+ tags: ["api", "public", "cacheable"],
593
+ run: async (userId) => getUserFromDatabase(userId),
594
+ });
595
+
596
+ // Structured tags with configuration
597
+ const httpTag = tag<{ method: string; path: string }>({
598
+ id: "http.route",
599
+ });
600
+
601
+ const getUserTask = task({
602
+ id: "app.tasks.getUser",
603
+ tags: ["api", httpTag.with({ method: "GET", path: "/users/:id" })],
604
+ run: async ({ id }) => getUserFromDatabase(id),
605
+ });
606
+ ```
607
+
608
+ #### Discovering Components by Tags
609
+
610
+ The core power of tags is runtime discovery. Use `store.getTasksWithTag()` to find components:
611
+
612
+ ```typescript
613
+ import { hook, globals } from "@bluelibs/runner";
614
+
615
+ // Auto-register HTTP routes based on tags
616
+ const routeRegistration = hook({
617
+ id: "app.hooks.registerRoutes",
618
+ on: globals.events.ready,
619
+ dependencies: {
620
+ store: globals.resources.store,
621
+ server: expressServer,
622
+ },
623
+ run: async (_, { store, server }) => {
624
+ // Find all tasks with HTTP tags
625
+ const apiTasks = store.getTasksWithTag(httpTag);
626
+
627
+ apiTasks.forEach((taskDef) => {
628
+ const config = httpTag.extract(taskDef);
629
+ if (!config) return;
630
+
631
+ const { method, path } = config;
632
+ server.app[method.toLowerCase()](path, async (req, res) => {
633
+ const result = await taskDef({ ...req.params, ...req.body });
634
+ res.json(result);
635
+ });
636
+ });
637
+
638
+ // Also find by string tags
639
+ const cacheableTasks = store.getTasksWithTag("cacheable");
640
+ console.log(`Found ${cacheableTasks.length} cacheable tasks`);
641
+ },
642
+ });
643
+ ```
644
+
645
+ #### Tag Extraction and Processing
646
+
647
+ ```typescript
648
+ // Check if a tag exists and extract its configuration
649
+ const performanceTag = tag<{ warnAboveMs: number }>({
650
+ id: "performance.monitor",
651
+ });
652
+
653
+ const performanceMiddleware = taskMiddleware({
654
+ id: "app.middleware.performance",
655
+ run: async ({ task, next }) => {
656
+ // Check if task has performance monitoring enabled
657
+ if (!performanceTag.exists(task.definition)) {
658
+ return next(task.input);
659
+ }
660
+
661
+ // Extract the configuration
662
+ const config = performanceTag.extract(task.definition);
663
+ const startTime = Date.now();
664
+
665
+ try {
666
+ const result = await next(task.input);
667
+ const duration = Date.now() - startTime;
668
+
669
+ if (duration > config.warnAboveMs) {
670
+ console.warn(`Task ${task.definition.id} took ${duration}ms`);
671
+ }
672
+
673
+ return result;
674
+ } catch (error) {
675
+ const duration = Date.now() - startTime;
676
+ console.error(`Task failed after ${duration}ms`, error);
677
+ throw error;
678
+ }
679
+ },
680
+ });
681
+ ```
682
+
683
+ #### System Tags
684
+
685
+ Built-in tags for framework behavior:
686
+
687
+ ```typescript
688
+ import { globals } from "@bluelibs/runner";
689
+
690
+ const internalTask = task({
691
+ id: "app.internal.cleanup",
692
+ tags: [
693
+ globals.tags.system, // Excludes from debug logs
694
+ globals.tags.debug.with({ logTaskInput: true }), // Per-component debug config
695
+ ],
696
+ run: async () => performCleanup(),
697
+ });
698
+
699
+ const internalEvent = event({
700
+ id: "app.events.internal",
701
+ tags: [globals.tags.excludeFromGlobalHooks], // Won't trigger wildcard listeners
702
+ });
703
+ ```
704
+
705
+ #### Contract Tags
706
+
707
+ Enforce return value shapes at compile time:
708
+
709
+ ```typescript
710
+ // Tags that enforce type contracts
711
+ const userContract = tag<void, void, { name: string }>({
712
+ id: "contract.user",
713
+ });
714
+
715
+ const profileTask = task({
716
+ id: "app.tasks.getProfile",
717
+ tags: [userContract], // Must return { name: string }
718
+ run: async () => ({ name: "Ada" }), // ✅ Satisfies contract
719
+ });
720
+ ```
573
721
 
574
722
  ## run() and RunOptions
575
723
 
@@ -887,7 +1035,7 @@ const databaseResource = resource({
887
1035
  },
888
1036
  dispose: async (connection) => {
889
1037
  await connection.close();
890
- console.log("Database connection closed");
1038
+ // console.log("Database connection closed");
891
1039
  },
892
1040
  });
893
1041
 
@@ -1310,6 +1458,7 @@ const app = resource({
1310
1458
  logger.trace("Very detailed trace"); // ❌ Hidden by default
1311
1459
 
1312
1460
  logger.onLog(async (log) => {
1461
+ // Sub-loggers instantiated .with() share the same log listeners.
1313
1462
  // Catch logs
1314
1463
  })
1315
1464
  },
@@ -1765,203 +1914,6 @@ const sendWelcomeEmail = task({
1765
1914
  });
1766
1915
  ```
1767
1916
 
1768
- ### Tags
1769
-
1770
- Tags are a way to describe your element, however, unlike meta, tags may influence behaviour in the system. They can be simple strings or sophisticated configuration objects that control component behavior. They have to be registered for it to work, to understand their ownership.
1771
-
1772
- #### Tags with Configuration
1773
-
1774
- For more sophisticated control, you can create structured tags that carry configuration:
1775
-
1776
- ```typescript
1777
- import { tag } from "@bluelibs/runner";
1778
-
1779
- // Define a reusable tag with configuration
1780
- const performanceTag = tag<{ alertAboveMs: number; criticalAboveMs: number }>({
1781
- id: "performance.monitoring",
1782
- });
1783
-
1784
- const rateLimitTag = tag<{ maxRequestsPerMinute: number; burstLimit?: number }>(
1785
- {
1786
- id: "rate.limit",
1787
- },
1788
- );
1789
-
1790
- const cacheTag = tag<{ ttl: number; keyPattern?: string }>({
1791
- id: "cache.strategy",
1792
- });
1793
-
1794
- // Use structured tags in your components
1795
- const expensiveTask = task({
1796
- id: "app.tasks.expensiveCalculation",
1797
- tags: [
1798
- "computation",
1799
- "background",
1800
- performanceTag.with({
1801
- alertAboveMs: 5000,
1802
- criticalAboveMs: 15000,
1803
- }),
1804
- cacheTag.with({
1805
- ttl: 300000, // 5 minutes
1806
- keyPattern: "calc-{userId}-{datasetId}",
1807
- }),
1808
- ],
1809
- run: async (input) => {
1810
- // Heavy computation here
1811
- },
1812
- });
1813
-
1814
- const apiEndpoint = task({
1815
- id: "app.tasks.api.getUserProfile",
1816
- tags: [
1817
- "api",
1818
- "public",
1819
- rateLimitTag.with({
1820
- maxRequestsPerMinute: 100,
1821
- burstLimit: 20,
1822
- }),
1823
- cacheTag.with({ ttl: 60000 }), // 1 minute cache
1824
- ],
1825
- run: async (userId) => {
1826
- // API logic
1827
- },
1828
- });
1829
- ```
1830
-
1831
- ### Global Tags System
1832
-
1833
- The framework now includes a sophisticated global tagging system for better component organization and control:
1834
-
1835
- ```typescript
1836
- import { globals } from "@bluelibs/runner";
1837
-
1838
- // System components (automatically excluded from debug logs)
1839
- const internalTask = task({
1840
- id: "app.tasks.internal",
1841
- tags: [globals.tags.system], // Marks as system component
1842
- run: async () => "internal work",
1843
- });
1844
-
1845
- // Debug-specific configuration
1846
- const debugTask = task({
1847
- id: "app.tasks.debug",
1848
- tags: [
1849
- globals.tags.debug.with({
1850
- logTaskInput: true,
1851
- logTaskResult: true,
1852
- }),
1853
- ],
1854
- run: async (input) => processInput(input),
1855
- });
1856
-
1857
- // Events that should not be sent to global listeners
1858
- const internalEvent = event({
1859
- id: "app.events.internal",
1860
- tags: [globals.tags.excludeFromGlobalHooks],
1861
- });
1862
- ```
1863
-
1864
- To process these tags you can hook into `globals.events.ready`, use the global store as dependency and use the `getTasksWithTag()` and `getResourcesWithTag()` functionality.
1865
-
1866
- #### Structured Tags
1867
-
1868
- ```typescript
1869
- const performanceMiddleware = taskMiddleware({
1870
- id: "app.middleware.performance",
1871
- run: async ({ task, next }) => {
1872
- const perfConfiguration = performanceTag.extract(task.definition); // you can just use .exists() if you want to check for presence
1873
-
1874
- if (perfConfiguration) {
1875
- const startTime = Date.now();
1876
-
1877
- try {
1878
- const result = await next(task?.input);
1879
- const duration = Date.now() - startTime;
1880
-
1881
- if (duration > perfConfiguration.criticalAboveMs) {
1882
- await alerting.critical(
1883
- `Task ${task.definition.id} took ${duration}ms`,
1884
- );
1885
- } else if (duration > perfConfiguration.alertAboveMs) {
1886
- await alerting.warn(`Task ${task.definition.id} took ${duration}ms`);
1887
- }
1888
-
1889
- return result;
1890
- } catch (error) {
1891
- const duration = Date.now() - startTime;
1892
- await alerting.error(
1893
- `Task ${task.definition.id} failed after ${duration}ms`,
1894
- error,
1895
- );
1896
- throw error;
1897
- }
1898
- }
1899
-
1900
- return next(task?.input);
1901
- },
1902
- });
1903
- ```
1904
-
1905
- #### Contract Tags
1906
-
1907
- You can attach contracts to tags to enforce the shape of a task's returned value and a resource's `init()` value at compile time. Contracts are specified via the third generic of `defineTag<TConfig, TUnused, TOutput>`.
1908
-
1909
- ```typescript
1910
- // A tag that enforces the returned value to include { name: string }
1911
- const userContract = tag<void, void, { name: string }>({ id: "contract.user" });
1912
-
1913
- // Another tag that enforces { age: number }
1914
- const ageContract = tag<void, void, { age: number }>({ id: "contract.age" });
1915
-
1916
- // Works with configured tags too
1917
- const preferenceContract = tag<
1918
- { locale: string },
1919
- void,
1920
- { preferredLocale: string }
1921
- >({
1922
- id: "contract.preferences",
1923
- });
1924
- ```
1925
-
1926
- The return value must return a union of all tags with return contracts.
1927
-
1928
- ```typescript
1929
- // Task: the awaited return value must satisfy { name: string } & { age: number }
1930
- const getProfile = task({
1931
- id: "app.tasks.getProfile",
1932
- tags: [userContract, ageContract, preferenceContract.with({ locale: "en" })],
1933
- run: async () => {
1934
- return { name: "Ada", age: 37, preferredLocale: "en" }; // OK
1935
- },
1936
- });
1937
-
1938
- // Resource: init() return must satisfy the same intersection
1939
- const profileService = resource({
1940
- id: "app.resources.profileService",
1941
- tags: [userContract, ageContract],
1942
- init: async () => {
1943
- return { name: "Ada", age: 37 }; // OK
1944
- },
1945
- });
1946
- ```
1947
-
1948
- If the returned value does not satisfy the intersection, TypeScript surfaces a readable, verbose type error that includes what was expected and what was received.
1949
-
1950
- ```typescript
1951
- const badTask = task({
1952
- id: "app.tasks.bad",
1953
- tags: [userContract, ageContract],
1954
- // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
1955
- run: async () => ({ name: "Ada" }), // Missing { age: number }
1956
- // Type error includes a helpful shape similar to:
1957
- // ContractViolationError<
1958
- // { message: "Value does not satisfy all tag contracts";
1959
- // expected: { name: string } & { age: number };
1960
- // received: { name: string } }
1961
- // >
1962
- });
1963
- ```
1964
-
1965
1917
  ### Extending Metadata: Custom Properties
1966
1918
 
1967
1919
  For advanced use cases, you can extend the metadata interfaces to add your own properties:
@@ -2102,14 +2054,18 @@ Overrides are applied after everything is registered. If multiple overrides targ
2102
2054
 
2103
2055
  As your app grows, you'll want consistent naming. Here's the convention that won't drive you crazy:
2104
2056
 
2105
- | Type | Format |
2106
- | ------------------- | ----------------------------------------------- |
2107
- | Resources | `{domain}.resources.{resourceName}` |
2108
- | Tasks | `{domain}.tasks.{taskName}` |
2109
- | Events | `{domain}.events.{eventName}` |
2110
- | Hooks | `{domain}.hooks.on{EventName}` |
2111
- | Task Middleware | `{domain}.middleware.task.{middlewareName}` |
2112
- | Resource Middleware | `{domain}.middleware.resource.{middlewareName}` |
2057
+ | Type | Format |
2058
+ | ------------------- | ------------------------------------------------ |
2059
+ | Resources | `{domain}.resources.{resource-name}` |
2060
+ | Tasks | `{domain}.tasks.{task-name}` |
2061
+ | Events | `{domain}.events.{event-name}` |
2062
+ | Hooks | `{domain}.hooks.on-{event-name}` |
2063
+ | Task Middleware | `{domain}.middleware.task.{middleware-name}` |
2064
+ | Resource Middleware | `{domain}.middleware.resource.{middleware-name}` |
2065
+
2066
+ We recommend kebab-case for file names and ids. Suffix files with their primitive type: `*.task.ts`, `*.task-middleware.ts`, `*.hook.ts`, etc.
2067
+
2068
+ Folders can look something like this: `src/app/users/tasks/create-user.task.ts`. For domain: `app.users` and a task. Use `middleware/task|resource` for middleware files.
2113
2069
 
2114
2070
  ```typescript
2115
2071
  // Helper function for consistency
@@ -2118,7 +2074,7 @@ function namespaced(id: string) {
2118
2074
  }
2119
2075
 
2120
2076
  const userTask = task({
2121
- id: namespaced("tasks.user.create"),
2077
+ id: namespaced("tasks.user.create-user"),
2122
2078
  // ...
2123
2079
  });
2124
2080
  ```
@@ -7,7 +7,7 @@ const globalResources_1 = require("../../globalResources");
7
7
  const globalTags_1 = require("../../globalTags");
8
8
  const types_1 = require("./types");
9
9
  exports.tasksTrackerMiddleware = (0, define_1.defineTaskMiddleware)({
10
- id: "debug.middleware.tracker.task",
10
+ id: "globals.debug.middleware.task.executionTracker",
11
11
  everywhere: (task) => !globalTags_1.globalTags.system.exists(task),
12
12
  dependencies: {
13
13
  logger: globalResources_1.globalResources.logger,
@@ -25,20 +25,14 @@ exports.tasksTrackerMiddleware = (0, define_1.defineTaskMiddleware)({
25
25
  await logger.info(taskStartMessage, {
26
26
  data: shouldShowData ? { input: task.input } : undefined,
27
27
  });
28
- try {
29
- const result = await next(task.input);
30
- const duration = Date.now() - start;
31
- const taskCompleteMessage = `Task ${task.definition.id} completed in ${duration}ms`;
32
- const shouldShowResult = debugConfig.logTaskOutput && result;
33
- await logger.info(taskCompleteMessage, {
34
- data: shouldShowResult ? { result } : undefined,
35
- });
36
- return result;
37
- }
38
- catch (error) {
39
- await logger.error(error);
40
- throw error;
41
- }
28
+ const result = await next(task.input);
29
+ const duration = Date.now() - start;
30
+ const taskCompleteMessage = `Task ${task.definition.id} completed in ${duration}ms`;
31
+ const shouldShowResult = debugConfig.logTaskOutput && result;
32
+ await logger.info(taskCompleteMessage, {
33
+ data: shouldShowResult ? { result } : undefined,
34
+ });
35
+ return result;
42
36
  },
43
37
  meta: {
44
38
  title: "Execution Tracker",
@@ -47,7 +41,7 @@ exports.tasksTrackerMiddleware = (0, define_1.defineTaskMiddleware)({
47
41
  tags: [globalTags_1.globalTags.system],
48
42
  });
49
43
  exports.resourcesTrackerMiddleware = (0, define_1.defineResourceMiddleware)({
50
- id: "debug.middleware.tracker.resource",
44
+ id: "globals.debug.middleware.resource.executionTracker",
51
45
  dependencies: {
52
46
  logger: globalResources_1.globalResources.logger,
53
47
  debugConfig: debugConfig_resource_1.debugConfig,
@@ -66,19 +60,14 @@ exports.resourcesTrackerMiddleware = (0, define_1.defineResourceMiddleware)({
66
60
  await logger.info(resourceStartMessage, {
67
61
  data: shouldShowConfig ? { config: resource.config } : undefined,
68
62
  });
69
- try {
70
- const result = await next(resource.config);
71
- const duration = Date.now() - start;
72
- const resourceCompleteMessage = `Resource ${String(resource.definition.id)} initialized in ${duration}ms`;
73
- const shouldShowResult = debugConfig.logResourceValue && result !== undefined;
74
- await logger.info(resourceCompleteMessage, {
75
- data: shouldShowResult ? { result } : undefined,
76
- });
77
- return result;
78
- }
79
- catch (error) {
80
- throw error;
81
- }
63
+ const result = await next(resource.config);
64
+ const duration = Date.now() - start;
65
+ const resourceCompleteMessage = `Resource ${String(resource.definition.id)} initialized in ${duration}ms`;
66
+ const shouldShowResult = debugConfig.logResourceValue && result !== undefined;
67
+ await logger.info(resourceCompleteMessage, {
68
+ data: shouldShowResult ? { result } : undefined,
69
+ });
70
+ return result;
82
71
  },
83
72
  meta: {
84
73
  title: "Execution Tracker",
@@ -1 +1 @@
1
- {"version":3,"file":"executionTracker.middleware.js","sourceRoot":"","sources":["../../../../src/globals/resources/debug/executionTracker.middleware.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"executionTracker.middleware.js","sourceRoot":"","sources":["../../../../src/globals/resources/debug/executionTracker.middleware.ts"],"names":[],"mappings":"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"}
@@ -8,7 +8,7 @@ const utils_1 = require("./utils");
8
8
  const debugConfig_resource_1 = require("./debugConfig.resource");
9
9
  const types_1 = require("./types");
10
10
  exports.globalEventListener = (0, define_1.defineHook)({
11
- id: "debug.catchAllHook",
11
+ id: "globals.debug.hooks.onAnyEvent",
12
12
  on: "*",
13
13
  dependencies: {
14
14
  logger: globalResources_1.globalResources.logger,
@@ -22,7 +22,7 @@ exports.globalEventListener = (0, define_1.defineHook)({
22
22
  if (debugConfig.logEventEmissionOnRun) {
23
23
  const message = `Event ${String(event.id)} emitted`;
24
24
  await logger.info(message, {
25
- source: "debug.catchAllHook",
25
+ source: "globals.debug.hooks.onAnyEvent",
26
26
  data: debugConfig.logEventEmissionInput
27
27
  ? { data: event.data }
28
28
  : undefined,
@@ -1 +1 @@
1
- {"version":3,"file":"globalEvent.hook.js","sourceRoot":"","sources":["../../../../src/globals/resources/debug/globalEvent.hook.ts"],"names":[],"mappings":";;;AAAA,4CAA6C;AAC7C,2DAAwD;AACxD,iDAA8C;AAC9C,mCAAuC;AACvC,iEAAqD;AACrD,mCAAoC;AAGvB,QAAA,mBAAmB,GAAG,IAAA,mBAAU,EAAC;IAC5C,EAAE,EAAE,oBAAoB;IACxB,EAAE,EAAE,GAAG;IACP,YAAY,EAAE;QACZ,MAAM,EAAE,iCAAe,CAAC,MAAM;QAC9B,WAAW,EAAX,kCAAW;KACZ;IACD,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,EAAE,EAAE;QAC5C,IAAI,IAAA,oBAAY,EAAC,KAAK,CAAC,EAAE,CAAC;YACxB,OAAO;QACT,CAAC;QAED,WAAW,GAAG,IAAA,iBAAS,EAAC,WAAW,EAAE,KAAM,CAAC,CAAC;QAC7C,IAAI,WAAW,CAAC,qBAAqB,EAAE,CAAC;YACtC,MAAM,OAAO,GAAG,SAAS,MAAM,CAAC,KAAM,CAAC,EAAE,CAAC,UAAU,CAAC;YACrD,MAAM,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE;gBACzB,MAAM,EAAE,oBAAoB;gBAC5B,IAAI,EAAE,WAAW,CAAC,qBAAqB;oBACrC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAM,CAAC,IAAI,EAAE;oBACvB,CAAC,CAAC,SAAS;aACd,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IACD,IAAI,EAAE;QACJ,KAAK,EAAE,yBAAyB;QAChC,WAAW,EAAE,6BAA6B;KAC3C;IACD,IAAI,EAAE,CAAC,uBAAU,CAAC,MAAM,CAAC;CAC1B,CAAC,CAAC"}
1
+ {"version":3,"file":"globalEvent.hook.js","sourceRoot":"","sources":["../../../../src/globals/resources/debug/globalEvent.hook.ts"],"names":[],"mappings":";;;AAAA,4CAA6C;AAC7C,2DAAwD;AACxD,iDAA8C;AAC9C,mCAAuC;AACvC,iEAAqD;AACrD,mCAAoC;AAGvB,QAAA,mBAAmB,GAAG,IAAA,mBAAU,EAAC;IAC5C,EAAE,EAAE,gCAAgC;IACpC,EAAE,EAAE,GAAG;IACP,YAAY,EAAE;QACZ,MAAM,EAAE,iCAAe,CAAC,MAAM;QAC9B,WAAW,EAAX,kCAAW;KACZ;IACD,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,EAAE,EAAE;QAC5C,IAAI,IAAA,oBAAY,EAAC,KAAK,CAAC,EAAE,CAAC;YACxB,OAAO;QACT,CAAC;QAED,WAAW,GAAG,IAAA,iBAAS,EAAC,WAAW,EAAE,KAAM,CAAC,CAAC;QAC7C,IAAI,WAAW,CAAC,qBAAqB,EAAE,CAAC;YACtC,MAAM,OAAO,GAAG,SAAS,MAAM,CAAC,KAAM,CAAC,EAAE,CAAC,UAAU,CAAC;YACrD,MAAM,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE;gBACzB,MAAM,EAAE,gCAAgC;gBACxC,IAAI,EAAE,WAAW,CAAC,qBAAqB;oBACrC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAM,CAAC,IAAI,EAAE;oBACvB,CAAC,CAAC,SAAS;aACd,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IACD,IAAI,EAAE;QACJ,KAAK,EAAE,yBAAyB;QAChC,WAAW,EAAE,6BAA6B;KAC3C;IACD,IAAI,EAAE,CAAC,uBAAU,CAAC,MAAM,CAAC;CAC1B,CAAC,CAAC"}
@@ -8,7 +8,7 @@ const utils_1 = require("./utils");
8
8
  const debugConfig_resource_1 = require("./debugConfig.resource");
9
9
  const types_1 = require("./types");
10
10
  exports.hookInterceptorResource = (0, define_1.defineResource)({
11
- id: "debug.hookInterceptorResource",
11
+ id: "globals.debug.resources.hookInterceptor",
12
12
  meta: {
13
13
  title: "Hook Interceptor",
14
14
  description: "Intercepts hooks for debug logging, skipping system-tagged hooks.",
@@ -31,7 +31,7 @@ exports.hookInterceptorResource = (0, define_1.defineResource)({
31
31
  const hookId = hook.id;
32
32
  let logString = `Hook triggered for ${String(hookId)}`;
33
33
  await logger.info(logString, {
34
- source: "debug.hookInterceptorResource",
34
+ source: "globals.debug.resources.hookInterceptor",
35
35
  });
36
36
  }
37
37
  await next(hook, event);
@@ -39,7 +39,7 @@ exports.hookInterceptorResource = (0, define_1.defineResource)({
39
39
  const hookId = hook.id;
40
40
  let logString = `Hook completed for ${String(hookId)}`;
41
41
  await logger.info(logString, {
42
- source: "debug.hookInterceptorResource",
42
+ source: "globals.debug.resources.hookInterceptor",
43
43
  });
44
44
  }
45
45
  });