@gobing-ai/ts-infra 0.4.8 → 0.4.9
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/README.md +47 -0
- package/dist/api-client.d.ts +8 -3
- package/dist/api-client.d.ts.map +1 -1
- package/dist/api-client.js +4 -3
- package/dist/application/index.d.ts +6 -0
- package/dist/application/index.d.ts.map +1 -1
- package/dist/application/index.js +29 -1
- package/dist/application/types.d.ts +26 -0
- package/dist/application/types.d.ts.map +1 -1
- package/dist/application-node.d.ts.map +1 -1
- package/dist/application-node.js +31 -3
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/package.json +6 -6
- package/src/api-client.ts +11 -4
- package/src/application/index.ts +31 -2
- package/src/application/types.ts +31 -1
- package/src/application-node.ts +32 -3
- package/src/index.ts +1 -0
package/README.md
CHANGED
|
@@ -704,6 +704,53 @@ const app = await runNodeApplication({
|
|
|
704
704
|
});
|
|
705
705
|
```
|
|
706
706
|
|
|
707
|
+
### System Events — lifecycle bus propagation contract
|
|
708
|
+
|
|
709
|
+
`runApplication` creates a single `lifecycleBus` (`EventBus<BusLifecycleEvents>`)
|
|
710
|
+
and parents the application event bus to it. Downstream consumers join the same
|
|
711
|
+
stream when callers pass `app.lifecycleBus` into their constructors. Domain emits
|
|
712
|
+
fan out as `bus.*` lifecycle events on the parent and — when a file observer is
|
|
713
|
+
attached — land in the JSONL System Events log alongside the domain event itself.
|
|
714
|
+
|
|
715
|
+
**Six System Events prefixes and where they originate:**
|
|
716
|
+
|
|
717
|
+
| Prefix | Source | Constructed when `events` is omitted |
|
|
718
|
+
|--------|--------|---------------------------------------|
|
|
719
|
+
| `bus.*` | `EventBus` lifecycle self-observability (the `lifecycleBus` itself) | always — `runApplication` creates it |
|
|
720
|
+
| `api.*` | `APIClient` (`api.request.error`) | `new EventBus<ApiClientEvents>({ lifecycleBus })` (R5) |
|
|
721
|
+
| `rule.*` | `RuleEngine` (rule-run structured observability) | `new EventBus<RuleEngineEvents>({ lifecycleBus })` (R2) |
|
|
722
|
+
| `workflow.*` | `WorkflowService` (workflow-run observability) | `new EventBus<WorkflowEngineEvents>({ lifecycleBus })` via `resolveEvents` (R3) |
|
|
723
|
+
| `agent.*` | `AiRunner` / `TeamOrchestrator` (agent invocation observability) | `new EventBus<AgentEvents>({ lifecycleBus })` (R4) |
|
|
724
|
+
| `process.*` | `AiRunner` default-executor process events | `new EventBus<AiRunnerProcessEvents>({ lifecycleBus })` (R4) |
|
|
725
|
+
|
|
726
|
+
**Caller-supplied `events` always wins.** Every consumer accepts an explicit
|
|
727
|
+
`events?: EventBus<TEvents>` (or equivalent) and an optional `lifecycleBus?`.
|
|
728
|
+
When `events` is provided the consumer uses it as-is; when `events` is omitted
|
|
729
|
+
and `lifecycleBus` is provided, the consumer constructs an internal bus
|
|
730
|
+
parented to the lifecycle bus. This keeps standalone use zero-config and lets
|
|
731
|
+
the bootstrap opt every consumer into the System Events stream by passing a
|
|
732
|
+
single `lifecycleBus`.
|
|
733
|
+
|
|
734
|
+
**Portable vs Node subpath split (ADR-011).** `runApplication` (portable)
|
|
735
|
+
never opens files: it calls `attachFileObserver(lifecycleBus, filePath, writer)`
|
|
736
|
+
only when `services.fileObserverWriter` is provided; its portable default path is
|
|
737
|
+
`logs/system-events.jsonl`. The Node subpath `runNodeApplication` constructs a
|
|
738
|
+
Node writer and uses `createNodeFileSystem()` to resolve the path to
|
|
739
|
+
`<projectRoot>/logs/system-events.jsonl`. Set `config.events.fileObserver: false`
|
|
740
|
+
to disable; supply a custom `filePath` (or a test-stub writer via
|
|
741
|
+
`services.fileObserverWriter`) to override.
|
|
742
|
+
|
|
743
|
+
**Wiring a consumer manually.** When you construct a consumer outside the
|
|
744
|
+
bootstrap (or want to share the bootstrap's bus), pass the exposed
|
|
745
|
+
`app.lifecycleBus`:
|
|
746
|
+
|
|
747
|
+
```ts
|
|
748
|
+
import { RuleEngine } from '@gobing-ai/ts-rule-engine';
|
|
749
|
+
|
|
750
|
+
const engine = new RuleEngine({ lifecycleBus: app.lifecycleBus });
|
|
751
|
+
// engine now emits `rule.*` events into the same JSONL log as the bootstrap.
|
|
752
|
+
```
|
|
753
|
+
|
|
707
754
|
If you prefer manual wiring (e.g. you already have an init sequence), the individual
|
|
708
755
|
subsystems still work standalone — `EventBus`, `APIClient`, `getLogger`, etc. are
|
|
709
756
|
all importable directly from the main barrel and do not require the bootstrap.
|
package/dist/api-client.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type BusLifecycleEvents, EventBus } from './event-bus/index';
|
|
2
2
|
import type { ApiClientEvents } from './events';
|
|
3
3
|
/** Configuration for {@link APIClient}: base URL, default headers, timeout, and optional custom fetch. */
|
|
4
4
|
export interface APIClientConfig {
|
|
@@ -12,6 +12,13 @@ export interface APIClientConfig {
|
|
|
12
12
|
* returns non-2xx statuses normally, so it emits only on network/timeout.
|
|
13
13
|
*/
|
|
14
14
|
events?: EventBus<ApiClientEvents>;
|
|
15
|
+
/**
|
|
16
|
+
* Optional lifecycle bus to bridge `api.*` events into the application
|
|
17
|
+
* System Events stream (R5). When `events` is omitted the client
|
|
18
|
+
* constructs an internal `EventBus<ApiClientEvents>` parented to this
|
|
19
|
+
* bus so `api.request.error` appears in the JSONL log.
|
|
20
|
+
*/
|
|
21
|
+
lifecycleBus?: EventBus<BusLifecycleEvents>;
|
|
15
22
|
}
|
|
16
23
|
/** Per-request overrides: headers, timeout, operation name, and abort signal. */
|
|
17
24
|
export interface RequestOptions {
|
|
@@ -46,9 +53,7 @@ export declare class APIError extends Error {
|
|
|
46
53
|
/**
|
|
47
54
|
* Typed HTTP client builder wrapping fetch with automatic JSON serialization,
|
|
48
55
|
* timeout support, and OpenTelemetry tracing on every request.
|
|
49
|
-
*
|
|
50
56
|
* @example
|
|
51
|
-
* ```ts
|
|
52
57
|
* const client = new APIClient({ baseUrl: 'https://api.example.com' });
|
|
53
58
|
* const data = await client.get<User>('/users/1');
|
|
54
59
|
* ```
|
package/dist/api-client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"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"}
|
package/dist/api-client.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { SpanKind } from '@opentelemetry/api';
|
|
5
5
|
import { ATTR_HTTP_REQUEST_METHOD, ATTR_HTTP_RESPONSE_STATUS_CODE, ATTR_URL_FULL, } from '@opentelemetry/semantic-conventions';
|
|
6
|
+
import { EventBus } from './event-bus/index.js';
|
|
6
7
|
import { getHttpClientRequestDuration, getHttpClientRequestErrors, getHttpClientRequestTotal, } from './telemetry/metrics.js';
|
|
7
8
|
import { traceAsync } from './telemetry/tracing.js';
|
|
8
9
|
/**
|
|
@@ -82,9 +83,7 @@ async function readBodyCapped(response, maxResponseBytes) {
|
|
|
82
83
|
/**
|
|
83
84
|
* Typed HTTP client builder wrapping fetch with automatic JSON serialization,
|
|
84
85
|
* timeout support, and OpenTelemetry tracing on every request.
|
|
85
|
-
*
|
|
86
86
|
* @example
|
|
87
|
-
* ```ts
|
|
88
87
|
* const client = new APIClient({ baseUrl: 'https://api.example.com' });
|
|
89
88
|
* const data = await client.get<User>('/users/1');
|
|
90
89
|
* ```
|
|
@@ -100,7 +99,9 @@ export class APIClient {
|
|
|
100
99
|
this.defaultHeaders = config.defaultHeaders ?? {};
|
|
101
100
|
this.timeout = config.timeout ?? 30_000;
|
|
102
101
|
this.fetchFn = config.fetch ?? globalThis.fetch;
|
|
103
|
-
this.events =
|
|
102
|
+
this.events =
|
|
103
|
+
config.events ??
|
|
104
|
+
(config.lifecycleBus ? new EventBus({ lifecycleBus: config.lifecycleBus }) : undefined);
|
|
104
105
|
}
|
|
105
106
|
buildUrl(path) {
|
|
106
107
|
return `${this.baseUrl}${path.startsWith('/') ? path : `/${path}`}`;
|
|
@@ -19,6 +19,12 @@ import type { ApplicationBootstrapOptions, ApplicationRuntime } from './types';
|
|
|
19
19
|
* Accepts injected dependencies; never opens files, reads config from disk,
|
|
20
20
|
* or wires runtime-specific exporters.
|
|
21
21
|
*
|
|
22
|
+
* The returned `lifecycleBus` is the parent of the application `events` bus and
|
|
23
|
+
* can be passed to RuleEngine, WorkflowService, AiRunner, TeamOrchestrator, and
|
|
24
|
+
* APIClient so their domain events share one System Events stream. A supplied
|
|
25
|
+
* file-observer writer records that stream as JSONL; the Node subpath supplies
|
|
26
|
+
* the writer and default `logs/system-events.jsonl` path.
|
|
27
|
+
*
|
|
22
28
|
* Startup is plugin-driven. Built-in service plugins are registered in dependency
|
|
23
29
|
* order, then `loadAll()` + `startAll()` run them forward:
|
|
24
30
|
* 1. Resolve bootstrap config; build EventBus + PluginHost
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/application/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/application/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,OAAO,KAAK,EAAsB,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACvE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAM7C,OAAO,KAAK,EAER,2BAA2B,EAC3B,kBAAkB,EAGrB,MAAM,SAAS,CAAC;AAiCjB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,wBAAsB,cAAc,CAAC,UAAU,GAAG,OAAO,EAAE,OAAO,SAAS,QAAQ,GAAG,WAAW,EAC7F,OAAO,EAAE,2BAA2B,CAAC,UAAU,EAAE,OAAO,CAAC,GAC1D,OAAO,CAAC,kBAAkB,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAyJlD;AAED,YAAY,EAAE,kBAAkB,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACvE,YAAY,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAC7C,YAAY,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjD,YAAY,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAE7D,YAAY,EACR,0BAA0B,EAC1B,2BAA2B,EAC3B,uBAAuB,EACvB,0BAA0B,EAC1B,kBAAkB,EAClB,mBAAmB,EACnB,qBAAqB,EACrB,sBAAsB,EACtB,aAAa,EACb,aAAa,EACb,cAAc,EACd,gBAAgB,EAChB,gBAAgB,GACnB,MAAM,SAAS,CAAC"}
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
*/
|
|
12
12
|
import { attachDefaultObservers, createLifecycleBus } from '../event-bus/default-observers.js';
|
|
13
13
|
import { EventBus } from '../event-bus/event-bus.js';
|
|
14
|
+
import { attachFileObserver } from '../event-bus/file-observer.js';
|
|
14
15
|
import { getLogger } from '../logger.js';
|
|
15
16
|
import { initScheduler } from '../scheduler/factory.js';
|
|
16
17
|
import { loggerPlugin, schedulerPlugin, telemetryPlugin, userCallbackPlugin } from './plugins/builtins.js';
|
|
@@ -39,6 +40,12 @@ async function performShutdown(state, reason) {
|
|
|
39
40
|
* Accepts injected dependencies; never opens files, reads config from disk,
|
|
40
41
|
* or wires runtime-specific exporters.
|
|
41
42
|
*
|
|
43
|
+
* The returned `lifecycleBus` is the parent of the application `events` bus and
|
|
44
|
+
* can be passed to RuleEngine, WorkflowService, AiRunner, TeamOrchestrator, and
|
|
45
|
+
* APIClient so their domain events share one System Events stream. A supplied
|
|
46
|
+
* file-observer writer records that stream as JSONL; the Node subpath supplies
|
|
47
|
+
* the writer and default `logs/system-events.jsonl` path.
|
|
48
|
+
*
|
|
42
49
|
* Startup is plugin-driven. Built-in service plugins are registered in dependency
|
|
43
50
|
* order, then `loadAll()` + `startAll()` run them forward:
|
|
44
51
|
* 1. Resolve bootstrap config; build EventBus + PluginHost
|
|
@@ -91,6 +98,9 @@ export async function runApplication(options) {
|
|
|
91
98
|
const eventsEnabled = options.config?.events?.enabled ?? true;
|
|
92
99
|
const eventsLifecycle = options.config?.events?.lifecycle ?? true;
|
|
93
100
|
const eventsDefaultObservers = options.config?.events?.defaultObservers ?? true;
|
|
101
|
+
const eventsFileObserver = options.config?.events?.fileObserver ?? true;
|
|
102
|
+
const fileObserverWriter = options.services?.fileObserverWriter;
|
|
103
|
+
const eventsFilePath = options.config?.events?.filePath ?? (fileObserverWriter !== undefined ? 'logs/system-events.jsonl' : undefined);
|
|
94
104
|
const state = {
|
|
95
105
|
app: undefined,
|
|
96
106
|
stopped: false,
|
|
@@ -105,6 +115,18 @@ export async function runApplication(options) {
|
|
|
105
115
|
if (lifecycleBus && eventsDefaultObservers) {
|
|
106
116
|
attachDefaultObservers(lifecycleBus);
|
|
107
117
|
}
|
|
118
|
+
// Attach the JSONL file observer when a writer is available. The
|
|
119
|
+
// portable subpath never opens files (ADR-011): the Node subpath
|
|
120
|
+
// injects `createNodeFileSystem()` (or a test stub) and resolves the
|
|
121
|
+
// default path against the project root. Without a writer or path
|
|
122
|
+
// the observer is a no-op even if `events.fileObserver` is `true`.
|
|
123
|
+
let fileObserverAttached = false;
|
|
124
|
+
let fileObserverPath;
|
|
125
|
+
if (lifecycleBus && eventsFileObserver && eventsFilePath !== undefined && fileObserverWriter !== undefined) {
|
|
126
|
+
attachFileObserver(lifecycleBus, eventsFilePath, fileObserverWriter);
|
|
127
|
+
fileObserverAttached = true;
|
|
128
|
+
fileObserverPath = eventsFilePath;
|
|
129
|
+
}
|
|
108
130
|
const events = options.services?.events ??
|
|
109
131
|
options.config?.events?.bus ??
|
|
110
132
|
new EventBus({ lifecycleBus: lifecycleBus });
|
|
@@ -128,7 +150,13 @@ export async function runApplication(options) {
|
|
|
128
150
|
// ── Build runtime handle (before startAll so plugins can capture it) ─
|
|
129
151
|
const resolvedConfig = {
|
|
130
152
|
logging: loggingConfig,
|
|
131
|
-
events: {
|
|
153
|
+
events: {
|
|
154
|
+
enabled: eventsEnabled,
|
|
155
|
+
lifecycle: eventsLifecycle,
|
|
156
|
+
defaultObservers: eventsDefaultObservers,
|
|
157
|
+
fileObserver: fileObserverAttached,
|
|
158
|
+
...(fileObserverPath !== undefined ? { filePath: fileObserverPath } : {}),
|
|
159
|
+
},
|
|
132
160
|
telemetry: telemetryConfig,
|
|
133
161
|
scheduler: schedulerConfig,
|
|
134
162
|
};
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
* @module application/types
|
|
9
9
|
*/
|
|
10
10
|
import type { EventBus } from '../event-bus/event-bus';
|
|
11
|
+
import type { FileObserverWriter } from '../event-bus/file-observer';
|
|
11
12
|
import type { BusLifecycleEvents, EventMap } from '../event-bus/types';
|
|
12
13
|
import type { InfraEvents } from '../events';
|
|
13
14
|
import type { Logger, LogLevel } from '../logger';
|
|
@@ -38,6 +39,20 @@ export interface EventsOptions<TEvents extends EventMap = InfraEvents> {
|
|
|
38
39
|
lifecycle?: boolean;
|
|
39
40
|
/** Attach default observers (log + telemetry). Default `true`. */
|
|
40
41
|
defaultObservers?: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Attach a file observer that appends JSONL rows for every lifecycle
|
|
44
|
+
* event to `filePath`. Default `true` when a writer is available
|
|
45
|
+
* (Node subpath injects `createNodeFileSystem()`; portable callers must
|
|
46
|
+
* supply one via `services.fileObserverWriter`). No-op when `lifecycle`
|
|
47
|
+
* is disabled or no writer is present.
|
|
48
|
+
*/
|
|
49
|
+
fileObserver?: boolean;
|
|
50
|
+
/**
|
|
51
|
+
* JSONL output path. Defaults to `logs/system-events.jsonl` when a writer
|
|
52
|
+
* is supplied; the Node subpath resolves this against the project root.
|
|
53
|
+
* Portable callers may override it with an absolute path.
|
|
54
|
+
*/
|
|
55
|
+
filePath?: string;
|
|
41
56
|
/** Pre-built event bus (skips creation when provided). */
|
|
42
57
|
bus?: EventBus<TEvents>;
|
|
43
58
|
}
|
|
@@ -75,6 +90,10 @@ export interface ApplicationBootstrapConfig {
|
|
|
75
90
|
enabled: boolean;
|
|
76
91
|
lifecycle: boolean;
|
|
77
92
|
defaultObservers: boolean;
|
|
93
|
+
/** Whether the JSONL file observer was attached (false when no writer is available). */
|
|
94
|
+
fileObserver: boolean;
|
|
95
|
+
/** Resolved JSONL absolute path, or undefined when fileObserver is false. */
|
|
96
|
+
filePath?: string;
|
|
78
97
|
};
|
|
79
98
|
readonly telemetry: {
|
|
80
99
|
enabled: boolean;
|
|
@@ -92,6 +111,13 @@ export interface ApplicationServices<TEvents extends EventMap = InfraEvents> {
|
|
|
92
111
|
logger?: Logger;
|
|
93
112
|
events?: EventBus<TEvents>;
|
|
94
113
|
lifecycleBus?: EventBus<BusLifecycleEvents>;
|
|
114
|
+
/**
|
|
115
|
+
* Writer for `attachFileObserver`. Portable subpath never opens files
|
|
116
|
+
* (ADR-011); the Node subpath injects `createNodeFileSystem()`. When
|
|
117
|
+
* absent, the file observer is skipped even if `events.fileObserver`
|
|
118
|
+
* is `true`.
|
|
119
|
+
*/
|
|
120
|
+
fileObserverWriter?: FileObserverWriter;
|
|
95
121
|
db?: DbAdapterLike;
|
|
96
122
|
scheduler?: SchedulerAdapter;
|
|
97
123
|
/** Pre-built plugin host (when injecting instead of constructing). */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/application/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,KAAK,EAAE,kBAAkB,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACvE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAClD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAI9C,6BAA6B;AAC7B,MAAM,WAAW,cAAc;IAC3B,sCAAsC;IACtC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,2CAA2C;IAC3C,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB,6CAA6C;IAC7C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;OAGG;IACH,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,yCAAyC;IACzC,IAAI,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,+BAA+B;AAC/B,MAAM,WAAW,aAAa,CAAC,OAAO,SAAS,QAAQ,GAAG,WAAW;IACjE,wCAAwC;IACxC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,yDAAyD;IACzD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,kEAAkE;IAClE,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,0DAA0D;IAC1D,GAAG,CAAC,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;CAC3B;AAED,+BAA+B;AAC/B,MAAM,WAAW,gBAAgB;IAC7B,wDAAwD;IACxD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,mDAAmD;IACnD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uDAAuD;IACvD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0DAA0D;IAC1D,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,+BAA+B;AAC/B,MAAM,WAAW,gBAAgB;IAC7B,yCAAyC;IACzC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,2DAA2D;IAC3D,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAC3B,oDAAoD;IACpD,OAAO,CAAC,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC/C,mFAAmF;IACnF,SAAS,CAAC,EAAE,OAAO,CAAC;CACvB;AAID;;;GAGG;AACH,MAAM,WAAW,0BAA0B;IACvC,QAAQ,CAAC,OAAO,EAAE,QAAQ,CACtB,QAAQ,CAAC,IAAI,CAAC,cAAc,EAAE,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC,CAAC,GAAG;QAAE,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;KAAE,CACnH,CAAC;IACF,QAAQ,CAAC,MAAM,EAAE;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/application/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"application-node.d.ts","sourceRoot":"","sources":["../src/application-node.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAWH,OAAO,KAAK,EACR,2BAA2B,EAC3B,uBAAuB,EAEvB,kBAAkB,EAClB,qBAAqB,EAGrB,QAAQ,EACR,aAAa,EACb,WAAW,EACX,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EACnB,MAAM,qBAAqB,CAAC;AAM7B,kGAAkG;AAClG,qBAAa,qBAAsB,SAAQ,KAAK;gBAChC,OAAO,EAAE,MAAM;CAI9B;AAgHD;;;;GAIG;AACH,MAAM,WAAW,6BAA8B,SAAQ,gBAAgB;IACnE,uEAAuE;IACvE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qEAAqE;IACrE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACpC;AAED,uEAAuE;AACvE,MAAM,WAAW,sBAAsB,CAAC,UAAU,GAAG,OAAO,EAAE,OAAO,SAAS,QAAQ,GAAG,WAAW;IAChG,gEAAgE;IAChE,QAAQ,CAAC,YAAY,CAAC,EAAE,uBAAuB,CAAC,UAAU,CAAC,CAAC;IAC5D,8DAA8D;IAC9D,QAAQ,CAAC,MAAM,CAAC,EAAE;QACd,OAAO,CAAC,EAAE,cAAc,CAAC;QACzB,MAAM,CAAC,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;QAChC,SAAS,CAAC,EAAE,6BAA6B,CAAC;QAC1C,SAAS,CAAC,EAAE,gBAAgB,CAAC;KAChC,CAAC;IACF,oCAAoC;IACpC,QAAQ,CAAC,QAAQ,CAAC,EAAE,2BAA2B,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,UAAU,CAAC,CAAC;IACjF,wCAAwC;IACxC,QAAQ,CAAC,KAAK,EAAE,CAAC,GAAG,EAAE,kBAAkB,CAAC,UAAU,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IACvF,wDAAwD;IACxD,QAAQ,CAAC,IAAI,CAAC,EAAE,CACZ,GAAG,EAAE,kBAAkB,CAAC,UAAU,EAAE,OAAO,CAAC,EAC5C,MAAM,EAAE,qBAAqB,KAC5B,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CAC7B;AAID;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAsB,kBAAkB,CAAC,UAAU,GAAG,OAAO,EAAE,OAAO,SAAS,QAAQ,GAAG,WAAW,EACjG,OAAO,EAAE,sBAAsB,CAAC,UAAU,EAAE,OAAO,CAAC,GACrD,OAAO,CAAC,kBAAkB,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"application-node.d.ts","sourceRoot":"","sources":["../src/application-node.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAWH,OAAO,KAAK,EACR,2BAA2B,EAC3B,uBAAuB,EAEvB,kBAAkB,EAClB,qBAAqB,EAGrB,QAAQ,EACR,aAAa,EACb,WAAW,EACX,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EACnB,MAAM,qBAAqB,CAAC;AAM7B,kGAAkG;AAClG,qBAAa,qBAAsB,SAAQ,KAAK;gBAChC,OAAO,EAAE,MAAM;CAI9B;AAgHD;;;;GAIG;AACH,MAAM,WAAW,6BAA8B,SAAQ,gBAAgB;IACnE,uEAAuE;IACvE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qEAAqE;IACrE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACpC;AAED,uEAAuE;AACvE,MAAM,WAAW,sBAAsB,CAAC,UAAU,GAAG,OAAO,EAAE,OAAO,SAAS,QAAQ,GAAG,WAAW;IAChG,gEAAgE;IAChE,QAAQ,CAAC,YAAY,CAAC,EAAE,uBAAuB,CAAC,UAAU,CAAC,CAAC;IAC5D,8DAA8D;IAC9D,QAAQ,CAAC,MAAM,CAAC,EAAE;QACd,OAAO,CAAC,EAAE,cAAc,CAAC;QACzB,MAAM,CAAC,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;QAChC,SAAS,CAAC,EAAE,6BAA6B,CAAC;QAC1C,SAAS,CAAC,EAAE,gBAAgB,CAAC;KAChC,CAAC;IACF,oCAAoC;IACpC,QAAQ,CAAC,QAAQ,CAAC,EAAE,2BAA2B,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,UAAU,CAAC,CAAC;IACjF,wCAAwC;IACxC,QAAQ,CAAC,KAAK,EAAE,CAAC,GAAG,EAAE,kBAAkB,CAAC,UAAU,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IACvF,wDAAwD;IACxD,QAAQ,CAAC,IAAI,CAAC,EAAE,CACZ,GAAG,EAAE,kBAAkB,CAAC,UAAU,EAAE,OAAO,CAAC,EAC5C,MAAM,EAAE,qBAAqB,KAC5B,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CAC7B;AAID;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAsB,kBAAkB,CAAC,UAAU,GAAG,OAAO,EAAE,OAAO,SAAS,QAAQ,GAAG,WAAW,EACjG,OAAO,EAAE,sBAAsB,CAAC,UAAU,EAAE,OAAO,CAAC,GACrD,OAAO,CAAC,kBAAkB,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAgIlD"}
|
package/dist/application-node.js
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
import { appendFileSync, mkdirSync, readFileSync } from 'node:fs';
|
|
18
18
|
import { dirname } from 'node:path';
|
|
19
19
|
import { createDbAdapter } from '@gobing-ai/ts-db';
|
|
20
|
-
import { interpolateTree, parseYamlObject } from '@gobing-ai/ts-runtime';
|
|
20
|
+
import { createNodeFileSystem, interpolateTree, parseYamlObject } from '@gobing-ai/ts-runtime';
|
|
21
21
|
import { runApplication } from './application/index.js';
|
|
22
22
|
import { dbPlugin } from './application/plugins/builtins.js';
|
|
23
23
|
import { NodeSchedulerAdapter } from './scheduler-node.js';
|
|
@@ -160,10 +160,12 @@ export async function runNodeApplication(options) {
|
|
|
160
160
|
const yamlLog = yamlBootstrap.logging;
|
|
161
161
|
const yamlTel = yamlBootstrap.telemetry;
|
|
162
162
|
const yamlSched = yamlBootstrap.scheduler;
|
|
163
|
+
const yamlEvents = yamlBootstrap.events;
|
|
163
164
|
const databaseOpts = (yamlBootstrap.database ?? {});
|
|
164
165
|
const loggingOpts = { ...yamlLog, ...options.config?.logging };
|
|
165
166
|
const telemetryOpts = { ...yamlTel, ...options.config?.telemetry };
|
|
166
167
|
const schedulerOpts = { ...yamlSched, ...options.config?.scheduler };
|
|
168
|
+
const eventsOpts = { ...yamlEvents, ...options.config?.events };
|
|
167
169
|
const logFilePath = yamlBootstrap.logging?.filePath;
|
|
168
170
|
const loggingConfig = typeof logFilePath === 'string' ? { ...loggingOpts, fileSink: createFileSink(logFilePath) } : loggingOpts;
|
|
169
171
|
// ── Scheduler adapter ───────────────────────────────────────────────
|
|
@@ -218,14 +220,40 @@ export async function runNodeApplication(options) {
|
|
|
218
220
|
`(expected "bun-sqlite"). Provide a supported driver or inject a DbAdapter via services.db.`);
|
|
219
221
|
}
|
|
220
222
|
}
|
|
223
|
+
// ── Inject Node file observer (ADR-011 writer for the JSONL bus log) ──
|
|
224
|
+
// The portable `runApplication` never opens files; the Node subpath
|
|
225
|
+
// supplies the writer and resolves the default path against the project
|
|
226
|
+
// root. Caller-provided `services.fileObserverWriter` and
|
|
227
|
+
// `config.events.filePath` overrides win; `fileObserver: false` disables.
|
|
228
|
+
const injectedFileSystem = createNodeFileSystem();
|
|
229
|
+
const fileObserverWriter = options.services?.fileObserverWriter ?? {
|
|
230
|
+
ensureDir: (dir) => {
|
|
231
|
+
mkdirSync(dir, { recursive: true });
|
|
232
|
+
},
|
|
233
|
+
appendFile: (path, content) => {
|
|
234
|
+
appendFileSync(path, content);
|
|
235
|
+
},
|
|
236
|
+
};
|
|
237
|
+
const eventsFilePath = eventsOpts.filePath ?? injectedFileSystem.resolve('logs', 'system-events.jsonl');
|
|
238
|
+
const eventsConfig = {
|
|
239
|
+
...eventsOpts,
|
|
240
|
+
filePath: eventsFilePath,
|
|
241
|
+
...(eventsOpts.fileObserver === false ? {} : { fileObserver: true }),
|
|
242
|
+
};
|
|
221
243
|
// ── Delegate to portable runApplication ─────────────────────────────
|
|
222
244
|
// Node-specific cleanup is handled by plugins in the service ring —
|
|
223
245
|
// node-telemetry onStop, owned-db onStop. No manual try/catch or stop
|
|
224
246
|
// override needed.
|
|
225
247
|
return await runApplication({
|
|
226
|
-
config: {
|
|
248
|
+
config: {
|
|
249
|
+
...options.config,
|
|
250
|
+
logging: loggingConfig,
|
|
251
|
+
telemetry: telemetryOpts,
|
|
252
|
+
scheduler: schedulerConfig,
|
|
253
|
+
events: eventsConfig,
|
|
254
|
+
},
|
|
227
255
|
appConfig: loadedAppConfig,
|
|
228
|
-
services: { ...options.services, ...(dbAdapter ? { db: dbAdapter } : {}) },
|
|
256
|
+
services: { ...options.services, fileObserverWriter, ...(dbAdapter ? { db: dbAdapter } : {}) },
|
|
229
257
|
start: options.start,
|
|
230
258
|
stop: options.stop,
|
|
231
259
|
plugins: plugins.length ? plugins : undefined,
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { APIClient, type APIClientConfig, APIError, type RawHttpResponse, type RawRequestOptions, type RequestOptions, } from './api-client';
|
|
2
|
-
export { type AsyncEventJobPayload, attachDefaultObservers, attachFileObserver, attachLogObserver, attachTelemetryObserver, createLifecycleBus, EventBus, type EventMap, type FileObserverWriter, type SubscribeOptions, } from './event-bus/index';
|
|
2
|
+
export { type AsyncEventJobPayload, attachDefaultObservers, attachFileObserver, attachLogObserver, attachTelemetryObserver, type BusLifecycleEvents, createLifecycleBus, EventBus, type EventMap, type FileObserverWriter, type SubscribeOptions, } from './event-bus/index';
|
|
3
3
|
export type { ApiClientEvents, ApiRequestErrorDetail, DbConnectionErrorDetail, DbEvents, InfraEvents, QueueEvents, QueueJobFailedDetail, QueueJobRetryingDetail, SchedulerEvents, SchedulerJobExecutedDetail, } from './events';
|
|
4
4
|
export type { EnqueueOptions, Job, JobHandler, JobQueue, QueueConsumer, QueueConsumerConfig, QueueStats, } from './job-queue/index';
|
|
5
5
|
export { getLogger, type InitLoggerOptions, initializeLogger, type Logger, type LogLevel, setLoggerMuted, } from './logger';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACH,SAAS,EACT,KAAK,eAAe,EACpB,QAAQ,EACR,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,KAAK,cAAc,GACtB,MAAM,cAAc,CAAC;AAGtB,OAAO,EACH,KAAK,oBAAoB,EACzB,sBAAsB,EACtB,kBAAkB,EAClB,iBAAiB,EACjB,uBAAuB,EACvB,kBAAkB,EAClB,QAAQ,EACR,KAAK,QAAQ,EACb,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,GACxB,MAAM,mBAAmB,CAAC;AAG3B,YAAY,EACR,eAAe,EACf,qBAAqB,EACrB,uBAAuB,EACvB,QAAQ,EACR,WAAW,EACX,WAAW,EACX,oBAAoB,EACpB,sBAAsB,EACtB,eAAe,EACf,0BAA0B,GAC7B,MAAM,UAAU,CAAC;AAElB,YAAY,EACR,cAAc,EACd,GAAG,EACH,UAAU,EACV,QAAQ,EACR,aAAa,EACb,mBAAmB,EACnB,UAAU,GACb,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACH,SAAS,EACT,KAAK,iBAAiB,EACtB,gBAAgB,EAChB,KAAK,MAAM,EACX,KAAK,QAAQ,EACb,cAAc,GACjB,MAAM,UAAU,CAAC;AAGlB,OAAO,EACH,cAAc,EACd,KAAK,4BAA4B,EACjC,qBAAqB,EACrB,gBAAgB,EAChB,KAAK,gBAAgB,EACrB,aAAa,EACb,SAAS,EACT,oBAAoB,EACpB,gBAAgB,EAChB,KAAK,qBAAqB,EAC1B,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,iBAAiB,EACjB,oBAAoB,GACvB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EACH,iBAAiB,EACjB,YAAY,EACZ,mBAAmB,EACnB,aAAa,EACb,qBAAqB,EACrB,sBAAsB,EACtB,4BAA4B,EAC5B,0BAA0B,EAC1B,yBAAyB,EACzB,yBAAyB,EACzB,wBAAwB,EACxB,sBAAsB,EACtB,6BAA6B,EAC7B,uBAAuB,EACvB,4BAA4B,EAC5B,0BAA0B,EAC1B,kBAAkB,EAClB,SAAS,EACT,WAAW,EACX,aAAa,EACb,kBAAkB,EAClB,WAAW,EACX,eAAe,EACf,iBAAiB,EACjB,KAAK,eAAe,EACpB,KAAK,sBAAsB,EAC3B,UAAU,EACV,SAAS,EACT,QAAQ,GACX,MAAM,mBAAmB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACH,SAAS,EACT,KAAK,eAAe,EACpB,QAAQ,EACR,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,KAAK,cAAc,GACtB,MAAM,cAAc,CAAC;AAGtB,OAAO,EACH,KAAK,oBAAoB,EACzB,sBAAsB,EACtB,kBAAkB,EAClB,iBAAiB,EACjB,uBAAuB,EACvB,KAAK,kBAAkB,EACvB,kBAAkB,EAClB,QAAQ,EACR,KAAK,QAAQ,EACb,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,GACxB,MAAM,mBAAmB,CAAC;AAG3B,YAAY,EACR,eAAe,EACf,qBAAqB,EACrB,uBAAuB,EACvB,QAAQ,EACR,WAAW,EACX,WAAW,EACX,oBAAoB,EACpB,sBAAsB,EACtB,eAAe,EACf,0BAA0B,GAC7B,MAAM,UAAU,CAAC;AAElB,YAAY,EACR,cAAc,EACd,GAAG,EACH,UAAU,EACV,QAAQ,EACR,aAAa,EACb,mBAAmB,EACnB,UAAU,GACb,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACH,SAAS,EACT,KAAK,iBAAiB,EACtB,gBAAgB,EAChB,KAAK,MAAM,EACX,KAAK,QAAQ,EACb,cAAc,GACjB,MAAM,UAAU,CAAC;AAGlB,OAAO,EACH,cAAc,EACd,KAAK,4BAA4B,EACjC,qBAAqB,EACrB,gBAAgB,EAChB,KAAK,gBAAgB,EACrB,aAAa,EACb,SAAS,EACT,oBAAoB,EACpB,gBAAgB,EAChB,KAAK,qBAAqB,EAC1B,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,iBAAiB,EACjB,oBAAoB,GACvB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EACH,iBAAiB,EACjB,YAAY,EACZ,mBAAmB,EACnB,aAAa,EACb,qBAAqB,EACrB,sBAAsB,EACtB,4BAA4B,EAC5B,0BAA0B,EAC1B,yBAAyB,EACzB,yBAAyB,EACzB,wBAAwB,EACxB,sBAAsB,EACtB,6BAA6B,EAC7B,uBAAuB,EACvB,4BAA4B,EAC5B,0BAA0B,EAC1B,kBAAkB,EAClB,SAAS,EACT,WAAW,EACX,aAAa,EACb,kBAAkB,EAClB,WAAW,EACX,eAAe,EACf,iBAAiB,EACjB,KAAK,eAAe,EACpB,KAAK,sBAAsB,EAC3B,UAAU,EACV,SAAS,EACT,QAAQ,GACX,MAAM,mBAAmB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gobing-ai/ts-infra",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.9",
|
|
4
4
|
"description": "@gobing-ai/ts-infra — Infrastructure backbone: event bus, job queue, scheduler, telemetry, API client, and logging.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"typescript",
|
|
@@ -78,12 +78,12 @@
|
|
|
78
78
|
"release": "echo 'Manual publish is disabled. Releases go through GitHub Actions via Trusted Publishing — push a tag: git tag @gobing-ai/ts-infra-v<version> && git push --tags' && exit 1"
|
|
79
79
|
},
|
|
80
80
|
"dependencies": {
|
|
81
|
-
"@gobing-ai/ts-utils": "^0.4.
|
|
81
|
+
"@gobing-ai/ts-utils": "^0.4.9",
|
|
82
82
|
"@logtape/logtape": "^2.0.0"
|
|
83
83
|
},
|
|
84
84
|
"peerDependencies": {
|
|
85
|
-
"@gobing-ai/ts-db": "^0.4.
|
|
86
|
-
"@gobing-ai/ts-runtime": "^0.4.
|
|
85
|
+
"@gobing-ai/ts-db": "^0.4.9",
|
|
86
|
+
"@gobing-ai/ts-runtime": "^0.4.9",
|
|
87
87
|
"@opentelemetry/api": "^1.9.0",
|
|
88
88
|
"@opentelemetry/sdk-trace-node": "^2.0.0",
|
|
89
89
|
"@opentelemetry/sdk-metrics": "^2.0.0",
|
|
@@ -116,8 +116,8 @@
|
|
|
116
116
|
}
|
|
117
117
|
},
|
|
118
118
|
"devDependencies": {
|
|
119
|
-
"@gobing-ai/ts-db": "^0.4.
|
|
120
|
-
"@gobing-ai/ts-runtime": "^0.4.
|
|
119
|
+
"@gobing-ai/ts-db": "^0.4.9",
|
|
120
|
+
"@gobing-ai/ts-runtime": "^0.4.9",
|
|
121
121
|
"@types/bun": "1.3.14",
|
|
122
122
|
"@opentelemetry/api": "^1.9.0",
|
|
123
123
|
"@opentelemetry/sdk-trace-node": "^2.0.0",
|
package/src/api-client.ts
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
ATTR_HTTP_RESPONSE_STATUS_CODE,
|
|
8
8
|
ATTR_URL_FULL,
|
|
9
9
|
} from '@opentelemetry/semantic-conventions';
|
|
10
|
-
import type
|
|
10
|
+
import { type BusLifecycleEvents, EventBus } from './event-bus/index';
|
|
11
11
|
import type { ApiClientEvents } from './events';
|
|
12
12
|
import {
|
|
13
13
|
getHttpClientRequestDuration,
|
|
@@ -30,6 +30,13 @@ export interface APIClientConfig {
|
|
|
30
30
|
* returns non-2xx statuses normally, so it emits only on network/timeout.
|
|
31
31
|
*/
|
|
32
32
|
events?: EventBus<ApiClientEvents>;
|
|
33
|
+
/**
|
|
34
|
+
* Optional lifecycle bus to bridge `api.*` events into the application
|
|
35
|
+
* System Events stream (R5). When `events` is omitted the client
|
|
36
|
+
* constructs an internal `EventBus<ApiClientEvents>` parented to this
|
|
37
|
+
* bus so `api.request.error` appears in the JSONL log.
|
|
38
|
+
*/
|
|
39
|
+
lifecycleBus?: EventBus<BusLifecycleEvents>;
|
|
33
40
|
}
|
|
34
41
|
/** Per-request overrides: headers, timeout, operation name, and abort signal. */
|
|
35
42
|
export interface RequestOptions {
|
|
@@ -137,9 +144,7 @@ async function readBodyCapped(
|
|
|
137
144
|
/**
|
|
138
145
|
* Typed HTTP client builder wrapping fetch with automatic JSON serialization,
|
|
139
146
|
* timeout support, and OpenTelemetry tracing on every request.
|
|
140
|
-
*
|
|
141
147
|
* @example
|
|
142
|
-
* ```ts
|
|
143
148
|
* const client = new APIClient({ baseUrl: 'https://api.example.com' });
|
|
144
149
|
* const data = await client.get<User>('/users/1');
|
|
145
150
|
* ```
|
|
@@ -156,7 +161,9 @@ export class APIClient {
|
|
|
156
161
|
this.defaultHeaders = config.defaultHeaders ?? {};
|
|
157
162
|
this.timeout = config.timeout ?? 30_000;
|
|
158
163
|
this.fetchFn = config.fetch ?? globalThis.fetch;
|
|
159
|
-
this.events =
|
|
164
|
+
this.events =
|
|
165
|
+
config.events ??
|
|
166
|
+
(config.lifecycleBus ? new EventBus<ApiClientEvents>({ lifecycleBus: config.lifecycleBus }) : undefined);
|
|
160
167
|
}
|
|
161
168
|
|
|
162
169
|
private buildUrl(path: string): string {
|
package/src/application/index.ts
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
import { attachDefaultObservers, createLifecycleBus } from '../event-bus/default-observers';
|
|
14
14
|
import { EventBus } from '../event-bus/event-bus';
|
|
15
|
+
import { attachFileObserver } from '../event-bus/file-observer';
|
|
15
16
|
import type { BusLifecycleEvents, EventMap } from '../event-bus/types';
|
|
16
17
|
import type { InfraEvents } from '../events';
|
|
17
18
|
import { getLogger, type Logger } from '../logger';
|
|
@@ -65,6 +66,12 @@ async function performShutdown<TAppConfig, TEvents extends EventMap>(
|
|
|
65
66
|
* Accepts injected dependencies; never opens files, reads config from disk,
|
|
66
67
|
* or wires runtime-specific exporters.
|
|
67
68
|
*
|
|
69
|
+
* The returned `lifecycleBus` is the parent of the application `events` bus and
|
|
70
|
+
* can be passed to RuleEngine, WorkflowService, AiRunner, TeamOrchestrator, and
|
|
71
|
+
* APIClient so their domain events share one System Events stream. A supplied
|
|
72
|
+
* file-observer writer records that stream as JSONL; the Node subpath supplies
|
|
73
|
+
* the writer and default `logs/system-events.jsonl` path.
|
|
74
|
+
*
|
|
68
75
|
* Startup is plugin-driven. Built-in service plugins are registered in dependency
|
|
69
76
|
* order, then `loadAll()` + `startAll()` run them forward:
|
|
70
77
|
* 1. Resolve bootstrap config; build EventBus + PluginHost
|
|
@@ -119,10 +126,13 @@ export async function runApplication<TAppConfig = unknown, TEvents extends Event
|
|
|
119
126
|
enabled: schedOpts?.enabled ?? false,
|
|
120
127
|
autoStart: schedOpts?.autoStart ?? true,
|
|
121
128
|
};
|
|
122
|
-
|
|
123
129
|
const eventsEnabled = options.config?.events?.enabled ?? true;
|
|
124
130
|
const eventsLifecycle = options.config?.events?.lifecycle ?? true;
|
|
125
131
|
const eventsDefaultObservers = options.config?.events?.defaultObservers ?? true;
|
|
132
|
+
const eventsFileObserver = options.config?.events?.fileObserver ?? true;
|
|
133
|
+
const fileObserverWriter = options.services?.fileObserverWriter;
|
|
134
|
+
const eventsFilePath =
|
|
135
|
+
options.config?.events?.filePath ?? (fileObserverWriter !== undefined ? 'logs/system-events.jsonl' : undefined);
|
|
126
136
|
|
|
127
137
|
const state: RuntimeState<TAppConfig, TEvents> = {
|
|
128
138
|
app: undefined,
|
|
@@ -143,6 +153,19 @@ export async function runApplication<TAppConfig = unknown, TEvents extends Event
|
|
|
143
153
|
attachDefaultObservers(lifecycleBus);
|
|
144
154
|
}
|
|
145
155
|
|
|
156
|
+
// Attach the JSONL file observer when a writer is available. The
|
|
157
|
+
// portable subpath never opens files (ADR-011): the Node subpath
|
|
158
|
+
// injects `createNodeFileSystem()` (or a test stub) and resolves the
|
|
159
|
+
// default path against the project root. Without a writer or path
|
|
160
|
+
// the observer is a no-op even if `events.fileObserver` is `true`.
|
|
161
|
+
let fileObserverAttached = false;
|
|
162
|
+
let fileObserverPath: string | undefined;
|
|
163
|
+
if (lifecycleBus && eventsFileObserver && eventsFilePath !== undefined && fileObserverWriter !== undefined) {
|
|
164
|
+
attachFileObserver(lifecycleBus, eventsFilePath, fileObserverWriter);
|
|
165
|
+
fileObserverAttached = true;
|
|
166
|
+
fileObserverPath = eventsFilePath;
|
|
167
|
+
}
|
|
168
|
+
|
|
146
169
|
const events =
|
|
147
170
|
options.services?.events ??
|
|
148
171
|
options.config?.events?.bus ??
|
|
@@ -173,7 +196,13 @@ export async function runApplication<TAppConfig = unknown, TEvents extends Event
|
|
|
173
196
|
// ── Build runtime handle (before startAll so plugins can capture it) ─
|
|
174
197
|
const resolvedConfig: ApplicationBootstrapConfig = {
|
|
175
198
|
logging: loggingConfig,
|
|
176
|
-
events: {
|
|
199
|
+
events: {
|
|
200
|
+
enabled: eventsEnabled,
|
|
201
|
+
lifecycle: eventsLifecycle,
|
|
202
|
+
defaultObservers: eventsDefaultObservers,
|
|
203
|
+
fileObserver: fileObserverAttached,
|
|
204
|
+
...(fileObserverPath !== undefined ? { filePath: fileObserverPath } : {}),
|
|
205
|
+
},
|
|
177
206
|
telemetry: telemetryConfig,
|
|
178
207
|
scheduler: schedulerConfig,
|
|
179
208
|
};
|
package/src/application/types.ts
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
import type { EventBus } from '../event-bus/event-bus';
|
|
12
|
+
import type { FileObserverWriter } from '../event-bus/file-observer';
|
|
12
13
|
import type { BusLifecycleEvents, EventMap } from '../event-bus/types';
|
|
13
14
|
import type { InfraEvents } from '../events';
|
|
14
15
|
import type { Logger, LogLevel } from '../logger';
|
|
@@ -43,6 +44,20 @@ export interface EventsOptions<TEvents extends EventMap = InfraEvents> {
|
|
|
43
44
|
lifecycle?: boolean;
|
|
44
45
|
/** Attach default observers (log + telemetry). Default `true`. */
|
|
45
46
|
defaultObservers?: boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Attach a file observer that appends JSONL rows for every lifecycle
|
|
49
|
+
* event to `filePath`. Default `true` when a writer is available
|
|
50
|
+
* (Node subpath injects `createNodeFileSystem()`; portable callers must
|
|
51
|
+
* supply one via `services.fileObserverWriter`). No-op when `lifecycle`
|
|
52
|
+
* is disabled or no writer is present.
|
|
53
|
+
*/
|
|
54
|
+
fileObserver?: boolean;
|
|
55
|
+
/**
|
|
56
|
+
* JSONL output path. Defaults to `logs/system-events.jsonl` when a writer
|
|
57
|
+
* is supplied; the Node subpath resolves this against the project root.
|
|
58
|
+
* Portable callers may override it with an absolute path.
|
|
59
|
+
*/
|
|
60
|
+
filePath?: string;
|
|
46
61
|
/** Pre-built event bus (skips creation when provided). */
|
|
47
62
|
bus?: EventBus<TEvents>;
|
|
48
63
|
}
|
|
@@ -81,7 +96,15 @@ export interface ApplicationBootstrapConfig {
|
|
|
81
96
|
readonly logging: Readonly<
|
|
82
97
|
Required<Pick<LoggingOptions, 'enabled' | 'level' | 'console' | 'json'>> & { fileSink?: (line: string) => void }
|
|
83
98
|
>;
|
|
84
|
-
readonly events: {
|
|
99
|
+
readonly events: {
|
|
100
|
+
enabled: boolean;
|
|
101
|
+
lifecycle: boolean;
|
|
102
|
+
defaultObservers: boolean;
|
|
103
|
+
/** Whether the JSONL file observer was attached (false when no writer is available). */
|
|
104
|
+
fileObserver: boolean;
|
|
105
|
+
/** Resolved JSONL absolute path, or undefined when fileObserver is false. */
|
|
106
|
+
filePath?: string;
|
|
107
|
+
};
|
|
85
108
|
readonly telemetry: { enabled: boolean; serviceName: string; environment: string; dbStatementDebug: boolean };
|
|
86
109
|
readonly scheduler: { enabled: boolean; autoStart: boolean };
|
|
87
110
|
}
|
|
@@ -93,6 +116,13 @@ export interface ApplicationServices<TEvents extends EventMap = InfraEvents> {
|
|
|
93
116
|
logger?: Logger;
|
|
94
117
|
events?: EventBus<TEvents>;
|
|
95
118
|
lifecycleBus?: EventBus<BusLifecycleEvents>;
|
|
119
|
+
/**
|
|
120
|
+
* Writer for `attachFileObserver`. Portable subpath never opens files
|
|
121
|
+
* (ADR-011); the Node subpath injects `createNodeFileSystem()`. When
|
|
122
|
+
* absent, the file observer is skipped even if `events.fileObserver`
|
|
123
|
+
* is `true`.
|
|
124
|
+
*/
|
|
125
|
+
fileObserverWriter?: FileObserverWriter;
|
|
96
126
|
db?: DbAdapterLike;
|
|
97
127
|
scheduler?: SchedulerAdapter;
|
|
98
128
|
/** Pre-built plugin host (when injecting instead of constructing). */
|
package/src/application-node.ts
CHANGED
|
@@ -19,7 +19,7 @@ import { appendFileSync, mkdirSync, readFileSync } from 'node:fs';
|
|
|
19
19
|
import { dirname } from 'node:path';
|
|
20
20
|
|
|
21
21
|
import { createDbAdapter, type DbAdapter } from '@gobing-ai/ts-db';
|
|
22
|
-
import { interpolateTree, parseYamlObject } from '@gobing-ai/ts-runtime';
|
|
22
|
+
import { createNodeFileSystem, interpolateTree, parseYamlObject } from '@gobing-ai/ts-runtime';
|
|
23
23
|
|
|
24
24
|
import { runApplication } from './application/index';
|
|
25
25
|
import { dbPlugin } from './application/plugins/builtins';
|
|
@@ -252,11 +252,13 @@ export async function runNodeApplication<TAppConfig = unknown, TEvents extends E
|
|
|
252
252
|
const yamlLog = yamlBootstrap.logging as Partial<LoggingOptions> | undefined;
|
|
253
253
|
const yamlTel = yamlBootstrap.telemetry as Partial<NodeTelemetryBootstrapOptions> | undefined;
|
|
254
254
|
const yamlSched = yamlBootstrap.scheduler as Partial<SchedulerOptions> | undefined;
|
|
255
|
+
const yamlEvents = yamlBootstrap.events as Partial<EventsOptions<TEvents>> | undefined;
|
|
255
256
|
const databaseOpts = (yamlBootstrap.database ?? {}) as Record<string, unknown>;
|
|
256
257
|
|
|
257
258
|
const loggingOpts: Partial<LoggingOptions> = { ...yamlLog, ...options.config?.logging };
|
|
258
259
|
const telemetryOpts: Partial<NodeTelemetryBootstrapOptions> = { ...yamlTel, ...options.config?.telemetry };
|
|
259
260
|
const schedulerOpts: Partial<SchedulerOptions> = { ...yamlSched, ...options.config?.scheduler };
|
|
261
|
+
const eventsOpts: EventsOptions<TEvents> = { ...yamlEvents, ...options.config?.events };
|
|
260
262
|
|
|
261
263
|
const logFilePath = (yamlBootstrap.logging as Record<string, unknown> | undefined)?.filePath as string | undefined;
|
|
262
264
|
const loggingConfig: Partial<LoggingOptions> =
|
|
@@ -319,14 +321,41 @@ export async function runNodeApplication<TAppConfig = unknown, TEvents extends E
|
|
|
319
321
|
}
|
|
320
322
|
}
|
|
321
323
|
|
|
324
|
+
// ── Inject Node file observer (ADR-011 writer for the JSONL bus log) ──
|
|
325
|
+
// The portable `runApplication` never opens files; the Node subpath
|
|
326
|
+
// supplies the writer and resolves the default path against the project
|
|
327
|
+
// root. Caller-provided `services.fileObserverWriter` and
|
|
328
|
+
// `config.events.filePath` overrides win; `fileObserver: false` disables.
|
|
329
|
+
const injectedFileSystem = createNodeFileSystem();
|
|
330
|
+
const fileObserverWriter = options.services?.fileObserverWriter ?? {
|
|
331
|
+
ensureDir: (dir: string) => {
|
|
332
|
+
mkdirSync(dir, { recursive: true });
|
|
333
|
+
},
|
|
334
|
+
appendFile: (path: string, content: string) => {
|
|
335
|
+
appendFileSync(path, content);
|
|
336
|
+
},
|
|
337
|
+
};
|
|
338
|
+
const eventsFilePath = eventsOpts.filePath ?? injectedFileSystem.resolve('logs', 'system-events.jsonl');
|
|
339
|
+
const eventsConfig: EventsOptions<TEvents> = {
|
|
340
|
+
...eventsOpts,
|
|
341
|
+
filePath: eventsFilePath,
|
|
342
|
+
...(eventsOpts.fileObserver === false ? {} : { fileObserver: true }),
|
|
343
|
+
};
|
|
344
|
+
|
|
322
345
|
// ── Delegate to portable runApplication ─────────────────────────────
|
|
323
346
|
// Node-specific cleanup is handled by plugins in the service ring —
|
|
324
347
|
// node-telemetry onStop, owned-db onStop. No manual try/catch or stop
|
|
325
348
|
// override needed.
|
|
326
349
|
return await runApplication<TAppConfig, TEvents>({
|
|
327
|
-
config: {
|
|
350
|
+
config: {
|
|
351
|
+
...options.config,
|
|
352
|
+
logging: loggingConfig,
|
|
353
|
+
telemetry: telemetryOpts,
|
|
354
|
+
scheduler: schedulerConfig,
|
|
355
|
+
events: eventsConfig,
|
|
356
|
+
},
|
|
328
357
|
appConfig: loadedAppConfig,
|
|
329
|
-
services: { ...options.services, ...(dbAdapter ? { db: dbAdapter } : {}) },
|
|
358
|
+
services: { ...options.services, fileObserverWriter, ...(dbAdapter ? { db: dbAdapter } : {}) },
|
|
330
359
|
start: options.start,
|
|
331
360
|
stop: options.stop,
|
|
332
361
|
plugins: plugins.length ? plugins : undefined,
|