@ciq-dev/neoiq-foundation-node 1.0.1-beta.1 → 1.0.1-beta.3

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 CHANGED
@@ -24,6 +24,7 @@ Node.js observability foundation for CommerceIQ services. Integrates with **Grou
24
24
  - **Type-Safe Configuration**: Zod validation with helpful error messages
25
25
  - **Fastify Plugin**: One-line integration for request lifecycle
26
26
  - **HTTP Client**: Axios wrapper with retry, circuit breaker, and trace propagation
27
+ - **Object Store Adapter**: Provider-agnostic wrapper for cloud object storage (e.g. S3) to avoid direct SDK coupling
27
28
 
28
29
  ---
29
30
 
@@ -39,6 +40,9 @@ npm install zod @opentelemetry/api @opentelemetry/sdk-node @opentelemetry/sdk-me
39
40
  @opentelemetry/exporter-trace-otlp-grpc @opentelemetry/exporter-metrics-otlp-grpc \
40
41
  @opentelemetry/auto-instrumentations-node @opentelemetry/resources @opentelemetry/semantic-conventions \
41
42
  pino pino-pretty axios axios-retry opossum fastify-plugin
43
+
44
+ # Optional (only if you want AWS S3 implementation of ObjectStore)
45
+ npm install @aws-sdk/client-s3 @aws-sdk/s3-request-presigner
42
46
  ```
43
47
 
44
48
  ### 2. Initialize (First Line of the App)
@@ -318,6 +322,40 @@ process.on('SIGTERM', async () => {
318
322
 
319
323
  ---
320
324
 
325
+ ## Object Store Adapter (S3 / Cloud Abstraction)
326
+
327
+ Use this when you want to **decouple application code** from `aws-sdk` / cloud vendor SDKs.
328
+
329
+ ### AWS S3 (optional peer deps)
330
+
331
+ ```typescript
332
+ import { AwsS3ObjectStore } from '@ciq-dev/neoiq-foundation-node';
333
+
334
+ const store = new AwsS3ObjectStore({
335
+ clientOptions: { region: process.env.AWS_REGION || 'us-east-1' },
336
+ });
337
+
338
+ const ref = { bucket: 'my-bucket', key: 'path/to/file.json' };
339
+
340
+ // Upload
341
+ await store.putObject(ref, JSON.stringify({ ok: true }), { contentType: 'application/json' });
342
+
343
+ // Presigned PUT URL (browser upload)
344
+ const uploadUrl = await store.presignPutObject(ref, { expiresInSeconds: 60, contentType: 'application/json' });
345
+ ```
346
+
347
+ ### In-memory (local/tests)
348
+
349
+ ```typescript
350
+ import { InMemoryObjectStore } from '@ciq-dev/neoiq-foundation-node';
351
+
352
+ const store = new InMemoryObjectStore();
353
+ await store.putObject({ bucket: 'b', key: 'k' }, 'hello');
354
+ const obj = await store.getObject({ bucket: 'b', key: 'k' });
355
+ ```
356
+
357
+ ---
358
+
321
359
  ## Complete Example
322
360
 
323
361
  ```typescript
@@ -422,7 +460,8 @@ src/
422
460
  │ └── metrics.ts # OTEL meter provider
423
461
  └── integrations/
424
462
  ├── fastify-plugin.ts # Fastify observability plugin
425
- └── http-client.ts # Axios wrapper with observability
463
+ ├── http-client.ts # Axios wrapper with observability
464
+ └── object-store/ # Cloud object store abstraction (S3, etc.)
426
465
  ```
427
466
 
428
467
  ---
@@ -0,0 +1 @@
1
+ export { };
@@ -0,0 +1 @@
1
+ export { };
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ const require_tracing = require('./tracing-DM5OFo7l.js');
3
+
4
+ //#region src/bootstrap.ts
5
+ const VALID_ENVIRONMENTS = [
6
+ "development",
7
+ "staging",
8
+ "qa",
9
+ "production"
10
+ ];
11
+ function resolveEnvironment() {
12
+ const env = process.env.NODE_ENV;
13
+ if (env && VALID_ENVIRONMENTS.includes(env)) return env;
14
+ return "development";
15
+ }
16
+ const serviceName = process.env.FOUNDATION_SERVICE_NAME || process.env.SERVICE_NAME;
17
+ if (!serviceName) console.warn("[neoiq-foundation/bootstrap] FOUNDATION_SERVICE_NAME or SERVICE_NAME env var not set. Skipping tracing bootstrap. Set the env var or use createFoundation() directly.");
18
+ else try {
19
+ require_tracing.setupTracing({
20
+ serviceName,
21
+ serviceVersion: process.env.SERVICE_VERSION || "1.0.0",
22
+ environment: resolveEnvironment(),
23
+ endpoint: require_tracing.getDefaultOtelEndpoint()
24
+ });
25
+ console.log(`[neoiq-foundation/bootstrap] Tracing initialized for "${serviceName}"`);
26
+ } catch (err) {
27
+ console.error("[neoiq-foundation/bootstrap] Failed to initialize tracing:", err);
28
+ }
29
+
30
+ //#endregion
31
+ //# sourceMappingURL=bootstrap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bootstrap.js","names":[],"sources":["../src/bootstrap.ts"],"sourcesContent":["/**\n * Bootstrap entry point for OTEL auto-instrumentation.\n *\n * Usage: node -r @ciq-dev/neoiq-foundation-node/bootstrap app.js\n *\n * Ensures tracing is initialized BEFORE any target libraries (pg, http,\n * ioredis, etc.) are imported, which is required for monkey-patching\n * to work. Reads config from environment variables.\n */\n\nimport { setupTracing } from './features/tracing';\nimport { getDefaultOtelEndpoint } from './config';\n\nconst VALID_ENVIRONMENTS = ['development', 'staging', 'qa', 'production'] as const;\n\nfunction resolveEnvironment(): string {\n const env = process.env.NODE_ENV;\n if (env && (VALID_ENVIRONMENTS as readonly string[]).includes(env)) return env;\n return 'development';\n}\n\nconst serviceName = process.env.FOUNDATION_SERVICE_NAME || process.env.SERVICE_NAME;\n\nif (!serviceName) {\n console.warn(\n '[neoiq-foundation/bootstrap] FOUNDATION_SERVICE_NAME or SERVICE_NAME env var not set. ' +\n 'Skipping tracing bootstrap. Set the env var or use createFoundation() directly.',\n );\n} else {\n try {\n setupTracing({\n serviceName,\n serviceVersion: process.env.SERVICE_VERSION || '1.0.0',\n environment: resolveEnvironment(),\n endpoint: getDefaultOtelEndpoint(),\n });\n console.log(`[neoiq-foundation/bootstrap] Tracing initialized for \"${serviceName}\"`);\n } catch (err) {\n console.error('[neoiq-foundation/bootstrap] Failed to initialize tracing:', err);\n }\n}\n"],"mappings":";;;;AAaA,MAAM,qBAAqB;CAAC;CAAe;CAAW;CAAM;AAAa;AAEzE,SAAS,qBAA6B;CACpC,MAAM,MAAM,QAAQ,IAAI;AACxB,KAAI,OAAO,mBAA0C,SAAS,IAAI,CAAE,QAAO;AAC3E,QAAO;AACR;AAED,MAAM,cAAc,QAAQ,IAAI,2BAA2B,QAAQ,IAAI;AAEvE,KAAK,YACH,SAAQ,KACN,wKAED;IAED,KAAI;AACF,8BAAa;EACX;EACA,gBAAgB,QAAQ,IAAI,mBAAmB;EAC/C,aAAa,oBAAoB;EACjC,UAAU,wCAAwB;CACnC,EAAC;AACF,SAAQ,KAAK,wDAAwD,YAAY,GAAG;AACrF,SAAQ,KAAK;AACZ,SAAQ,MAAM,8DAA8D,IAAI;AACjF"}
@@ -0,0 +1,30 @@
1
+ import { getDefaultOtelEndpoint, setupTracing } from "./tracing-Cv-Y3fZx.mjs";
2
+
3
+ //#region src/bootstrap.ts
4
+ const VALID_ENVIRONMENTS = [
5
+ "development",
6
+ "staging",
7
+ "qa",
8
+ "production"
9
+ ];
10
+ function resolveEnvironment() {
11
+ const env = process.env.NODE_ENV;
12
+ if (env && VALID_ENVIRONMENTS.includes(env)) return env;
13
+ return "development";
14
+ }
15
+ const serviceName = process.env.FOUNDATION_SERVICE_NAME || process.env.SERVICE_NAME;
16
+ if (!serviceName) console.warn("[neoiq-foundation/bootstrap] FOUNDATION_SERVICE_NAME or SERVICE_NAME env var not set. Skipping tracing bootstrap. Set the env var or use createFoundation() directly.");
17
+ else try {
18
+ setupTracing({
19
+ serviceName,
20
+ serviceVersion: process.env.SERVICE_VERSION || "1.0.0",
21
+ environment: resolveEnvironment(),
22
+ endpoint: getDefaultOtelEndpoint()
23
+ });
24
+ console.log(`[neoiq-foundation/bootstrap] Tracing initialized for "${serviceName}"`);
25
+ } catch (err) {
26
+ console.error("[neoiq-foundation/bootstrap] Failed to initialize tracing:", err);
27
+ }
28
+
29
+ //#endregion
30
+ //# sourceMappingURL=bootstrap.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bootstrap.mjs","names":[],"sources":["../src/bootstrap.ts"],"sourcesContent":["/**\n * Bootstrap entry point for OTEL auto-instrumentation.\n *\n * Usage: node -r @ciq-dev/neoiq-foundation-node/bootstrap app.js\n *\n * Ensures tracing is initialized BEFORE any target libraries (pg, http,\n * ioredis, etc.) are imported, which is required for monkey-patching\n * to work. Reads config from environment variables.\n */\n\nimport { setupTracing } from './features/tracing';\nimport { getDefaultOtelEndpoint } from './config';\n\nconst VALID_ENVIRONMENTS = ['development', 'staging', 'qa', 'production'] as const;\n\nfunction resolveEnvironment(): string {\n const env = process.env.NODE_ENV;\n if (env && (VALID_ENVIRONMENTS as readonly string[]).includes(env)) return env;\n return 'development';\n}\n\nconst serviceName = process.env.FOUNDATION_SERVICE_NAME || process.env.SERVICE_NAME;\n\nif (!serviceName) {\n console.warn(\n '[neoiq-foundation/bootstrap] FOUNDATION_SERVICE_NAME or SERVICE_NAME env var not set. ' +\n 'Skipping tracing bootstrap. Set the env var or use createFoundation() directly.',\n );\n} else {\n try {\n setupTracing({\n serviceName,\n serviceVersion: process.env.SERVICE_VERSION || '1.0.0',\n environment: resolveEnvironment(),\n endpoint: getDefaultOtelEndpoint(),\n });\n console.log(`[neoiq-foundation/bootstrap] Tracing initialized for \"${serviceName}\"`);\n } catch (err) {\n console.error('[neoiq-foundation/bootstrap] Failed to initialize tracing:', err);\n }\n}\n"],"mappings":";;;AAaA,MAAM,qBAAqB;CAAC;CAAe;CAAW;CAAM;AAAa;AAEzE,SAAS,qBAA6B;CACpC,MAAM,MAAM,QAAQ,IAAI;AACxB,KAAI,OAAO,mBAA0C,SAAS,IAAI,CAAE,QAAO;AAC3E,QAAO;AACR;AAED,MAAM,cAAc,QAAQ,IAAI,2BAA2B,QAAQ,IAAI;AAEvE,KAAK,YACH,SAAQ,KACN,wKAED;IAED,KAAI;AACF,cAAa;EACX;EACA,gBAAgB,QAAQ,IAAI,mBAAmB;EAC/C,aAAa,oBAAoB;EACjC,UAAU,wBAAwB;CACnC,EAAC;AACF,SAAQ,KAAK,wDAAwD,YAAY,GAAG;AACrF,SAAQ,KAAK;AACZ,SAAQ,MAAM,8DAA8D,IAAI;AACjF"}
package/dist/index.d.mts CHANGED
@@ -1,8 +1,8 @@
1
+ import { Meter, Meter as Meter$1, Span, SpanStatusCode, Tracer, Tracer as Tracer$1, context, metrics, propagation, trace } from "@opentelemetry/api";
1
2
  import { z } from "zod";
2
3
  import { Logger as Logger$1 } from "pino";
3
- import * as _opentelemetry_api0 from "@opentelemetry/api";
4
- import { Meter, Span, SpanStatusCode, Tracer, context, metrics, propagation, trace } from "@opentelemetry/api";
5
- import { AxiosInstance, AxiosRequestConfig, AxiosResponse } from "axios";
4
+ import { AxiosInstance, AxiosInstance as AxiosInstance$1, AxiosRequestConfig, AxiosResponse } from "axios";
5
+ import { Readable } from "node:stream";
6
6
  import { FastifyPluginAsync } from "fastify";
7
7
 
8
8
  //#region src/config.d.ts
@@ -122,13 +122,13 @@ declare const FeaturesConfigSchema: z.ZodObject<{
122
122
  }>;
123
123
  type FeaturesConfig = z.infer<typeof FeaturesConfigSchema>;
124
124
  declare const OtelConfigSchema: z.ZodObject<{
125
- endpoint: z.ZodOptional<z.ZodDefault<z.ZodString>>;
126
- metricsIntervalMs: z.ZodOptional<z.ZodDefault<z.ZodNumber>>;
127
- traceSampleRate: z.ZodOptional<z.ZodDefault<z.ZodNumber>>;
125
+ endpoint: z.ZodDefault<z.ZodString>;
126
+ metricsIntervalMs: z.ZodDefault<z.ZodNumber>;
127
+ traceSampleRate: z.ZodDefault<z.ZodNumber>;
128
128
  }, "strip", z.ZodTypeAny, {
129
- endpoint?: string | undefined;
130
- metricsIntervalMs?: number | undefined;
131
- traceSampleRate?: number | undefined;
129
+ endpoint: string;
130
+ metricsIntervalMs: number;
131
+ traceSampleRate: number;
132
132
  }, {
133
133
  endpoint?: string | undefined;
134
134
  metricsIntervalMs?: number | undefined;
@@ -166,6 +166,25 @@ declare const RequestLoggingConfigSchema: z.ZodObject<{
166
166
  redactHeaders?: string[] | undefined;
167
167
  }>;
168
168
  type RequestLoggingConfig = z.infer<typeof RequestLoggingConfigSchema>;
169
+ declare const RedactionConfigSchema: z.ZodObject<{
170
+ additionalPaths: z.ZodOptional<z.ZodDefault<z.ZodArray<z.ZodString, "many">>>;
171
+ }, "strip", z.ZodTypeAny, {
172
+ additionalPaths?: string[] | undefined;
173
+ }, {
174
+ additionalPaths?: string[] | undefined;
175
+ }>;
176
+ type RedactionConfig = z.infer<typeof RedactionConfigSchema>;
177
+ declare const ShutdownConfigSchema: z.ZodObject<{
178
+ flushOnCrash: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
179
+ flushTimeoutMs: z.ZodOptional<z.ZodDefault<z.ZodNumber>>;
180
+ }, "strip", z.ZodTypeAny, {
181
+ flushOnCrash?: boolean | undefined;
182
+ flushTimeoutMs?: number | undefined;
183
+ }, {
184
+ flushOnCrash?: boolean | undefined;
185
+ flushTimeoutMs?: number | undefined;
186
+ }>;
187
+ type ShutdownConfig = z.infer<typeof ShutdownConfigSchema>;
169
188
  declare const FoundationConfigSchema: z.ZodObject<{
170
189
  serviceName: z.ZodString;
171
190
  serviceVersion: z.ZodDefault<z.ZodString>;
@@ -247,13 +266,13 @@ declare const FoundationConfigSchema: z.ZodObject<{
247
266
  } | undefined;
248
267
  }>>;
249
268
  otel: z.ZodDefault<z.ZodObject<{
250
- endpoint: z.ZodOptional<z.ZodDefault<z.ZodString>>;
251
- metricsIntervalMs: z.ZodOptional<z.ZodDefault<z.ZodNumber>>;
252
- traceSampleRate: z.ZodOptional<z.ZodDefault<z.ZodNumber>>;
269
+ endpoint: z.ZodDefault<z.ZodString>;
270
+ metricsIntervalMs: z.ZodDefault<z.ZodNumber>;
271
+ traceSampleRate: z.ZodDefault<z.ZodNumber>;
253
272
  }, "strip", z.ZodTypeAny, {
254
- endpoint?: string | undefined;
255
- metricsIntervalMs?: number | undefined;
256
- traceSampleRate?: number | undefined;
273
+ endpoint: string;
274
+ metricsIntervalMs: number;
275
+ traceSampleRate: number;
257
276
  }, {
258
277
  endpoint?: string | undefined;
259
278
  metricsIntervalMs?: number | undefined;
@@ -288,6 +307,23 @@ declare const FoundationConfigSchema: z.ZodObject<{
288
307
  maxBodySize?: number | undefined;
289
308
  redactHeaders?: string[] | undefined;
290
309
  }>>;
310
+ redaction: z.ZodDefault<z.ZodObject<{
311
+ additionalPaths: z.ZodOptional<z.ZodDefault<z.ZodArray<z.ZodString, "many">>>;
312
+ }, "strip", z.ZodTypeAny, {
313
+ additionalPaths?: string[] | undefined;
314
+ }, {
315
+ additionalPaths?: string[] | undefined;
316
+ }>>;
317
+ shutdown: z.ZodDefault<z.ZodObject<{
318
+ flushOnCrash: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
319
+ flushTimeoutMs: z.ZodOptional<z.ZodDefault<z.ZodNumber>>;
320
+ }, "strip", z.ZodTypeAny, {
321
+ flushOnCrash?: boolean | undefined;
322
+ flushTimeoutMs?: number | undefined;
323
+ }, {
324
+ flushOnCrash?: boolean | undefined;
325
+ flushTimeoutMs?: number | undefined;
326
+ }>>;
291
327
  }, "strip", z.ZodTypeAny, {
292
328
  logging: {
293
329
  level?: "debug" | "info" | "warn" | "error" | undefined;
@@ -315,9 +351,9 @@ declare const FoundationConfigSchema: z.ZodObject<{
315
351
  } | undefined;
316
352
  };
317
353
  otel: {
318
- endpoint?: string | undefined;
319
- metricsIntervalMs?: number | undefined;
320
- traceSampleRate?: number | undefined;
354
+ endpoint: string;
355
+ metricsIntervalMs: number;
356
+ traceSampleRate: number;
321
357
  };
322
358
  requestLogging: {
323
359
  logHeaders?: boolean | undefined;
@@ -326,6 +362,13 @@ declare const FoundationConfigSchema: z.ZodObject<{
326
362
  maxBodySize?: number | undefined;
327
363
  redactHeaders?: string[] | undefined;
328
364
  };
365
+ redaction: {
366
+ additionalPaths?: string[] | undefined;
367
+ };
368
+ shutdown: {
369
+ flushOnCrash?: boolean | undefined;
370
+ flushTimeoutMs?: number | undefined;
371
+ };
329
372
  }, {
330
373
  serviceName: string;
331
374
  logging?: {
@@ -364,9 +407,16 @@ declare const FoundationConfigSchema: z.ZodObject<{
364
407
  maxBodySize?: number | undefined;
365
408
  redactHeaders?: string[] | undefined;
366
409
  } | undefined;
410
+ redaction?: {
411
+ additionalPaths?: string[] | undefined;
412
+ } | undefined;
413
+ shutdown?: {
414
+ flushOnCrash?: boolean | undefined;
415
+ flushTimeoutMs?: number | undefined;
416
+ } | undefined;
367
417
  }>;
368
418
  type FoundationConfig = z.infer<typeof FoundationConfigSchema>;
369
- type FoundationConfigInput = Partial<FoundationConfig> & {
419
+ type FoundationConfigInput = z.input<typeof FoundationConfigSchema> & {
370
420
  serviceName: string;
371
421
  };
372
422
  /** Parse and validate configuration */
@@ -377,13 +427,18 @@ declare function getDefaultOtelEndpoint(): string; //#endregion
377
427
 
378
428
  //# sourceMappingURL=config.d.ts.map
379
429
  /**
380
- * Context Manager - AsyncLocalStorage for request context propagation
430
+ * Context Manager
431
+ *
432
+ * Uses OTEL Baggage as the primary store for correlationId when tracing
433
+ * is active. Falls back to AsyncLocalStorage when tracing is disabled,
434
+ * ensuring correlation IDs work regardless of OTEL state.
381
435
  */
382
436
  interface RequestContext {
383
437
  correlationId?: string;
384
438
  traceId?: string;
385
439
  spanId?: string;
386
440
  startTime?: number;
441
+ contextData?: Record<string, unknown>;
387
442
  [key: string]: unknown;
388
443
  }
389
444
  interface ContextManager {
@@ -391,6 +446,16 @@ interface ContextManager {
391
446
  run<T>(context: RequestContext, fn: () => T): T;
392
447
  get<K extends keyof RequestContext>(key: K): RequestContext[K] | undefined;
393
448
  update(updates: Partial<RequestContext>): RequestContext | undefined;
449
+ /** Set an arbitrary context value (e.g. tenant_id, user_id) — auto-injected into every log line */
450
+ setContextValue(key: string, value: unknown): void;
451
+ /** Get a single context value by key */
452
+ getContextValue(key: string): unknown;
453
+ /** Get all arbitrary context data */
454
+ getContextData(): Record<string, unknown>;
455
+ /** Bulk-set multiple context values */
456
+ setContextData(data: Record<string, unknown>): void;
457
+ /** Clear all arbitrary context data */
458
+ clearContextData(): void;
394
459
  }
395
460
  /** Create a new context manager instance */
396
461
  declare function createContextManager(): ContextManager;
@@ -405,6 +470,7 @@ interface LoggerOptions {
405
470
  level: 'debug' | 'info' | 'warn' | 'error';
406
471
  prettyPrint: boolean;
407
472
  contextManager?: ContextManager;
473
+ additionalRedactPaths?: string[];
408
474
  }
409
475
  interface Logger {
410
476
  debug: (obj: object, msg?: string) => void;
@@ -417,7 +483,7 @@ interface Logger {
417
483
  /** Create a structured logger with automatic trace context injection */
418
484
  declare function createLogger(options: LoggerOptions): Logger;
419
485
  /** Fallback logger when Pino is not available */
420
- declare function createFallbackLogger(serviceName?: string): Logger;
486
+ declare function createFallbackLogger(serviceName?: string, baseBindings?: object): Logger;
421
487
  declare function setGlobalLogger(logger: Logger): void;
422
488
  declare function getGlobalLogger(): Logger;
423
489
 
@@ -437,7 +503,7 @@ declare function setupTracing(options: TracingOptions): void;
437
503
  /** Shutdown tracing gracefully */
438
504
  declare function shutdownTracing(): Promise<void>;
439
505
  declare function getTracer(name: string): Tracer;
440
- declare function getActiveSpan(): _opentelemetry_api0.Span | undefined;
506
+ declare function getActiveSpan(): ReturnType<typeof trace.getActiveSpan>;
441
507
  declare function getTraceContext(): {
442
508
  traceId?: string;
443
509
  spanId?: string;
@@ -488,7 +554,6 @@ interface FastifyPluginOptions {
488
554
  }
489
555
  declare module 'fastify' {
490
556
  interface FastifyRequest {
491
- __span?: Span;
492
557
  __requestContext?: PluginRequestContext;
493
558
  }
494
559
  }
@@ -496,12 +561,44 @@ declare module 'fastify' {
496
561
  declare function createObservabilityPlugin(options: FastifyPluginOptions): FastifyPluginAsync<Partial<FastifyPluginOptions>>;
497
562
 
498
563
  //#endregion
499
- //#region src/integrations/http-client.d.ts
564
+ //#region src/types.d.ts
565
+ interface HealthStatus {
566
+ status: 'healthy' | 'degraded' | 'unhealthy';
567
+ timestamp: string;
568
+ service: string;
569
+ version: string;
570
+ uptime: number;
571
+ components: {
572
+ tracing: ComponentHealth;
573
+ metrics: ComponentHealth;
574
+ logging: ComponentHealth;
575
+ };
576
+ }
577
+ interface ComponentHealth {
578
+ enabled: boolean;
579
+ status: 'up' | 'down' | 'disabled';
580
+ message?: string;
581
+ }
582
+ interface ObservabilityModule {
583
+ readonly logger: Logger;
584
+ readonly tracer: Tracer$1 | null;
585
+ readonly meter: Meter$1 | null;
586
+ getTracer(name?: string): Tracer$1;
587
+ getMeter(name: string, version?: string): Meter$1;
588
+ getTraceContext(): {
589
+ traceId?: string;
590
+ spanId?: string;
591
+ };
592
+ getActiveSpan(): Span | undefined;
593
+ trace<T>(name: string, fn: () => T | Promise<T>): Promise<T>;
594
+ }
595
+ type HttpClient = AxiosInstance$1;
500
596
  interface HttpClientOptions {
501
597
  baseURL: string;
502
598
  serviceName: string;
503
599
  timeout?: number;
504
600
  retry?: {
601
+ enabled?: boolean;
505
602
  retries?: number;
506
603
  retryDelay?: number;
507
604
  retryStatusCodes?: number[];
@@ -514,60 +611,241 @@ interface HttpClientOptions {
514
611
  headers?: Record<string, string>;
515
612
  foundation?: FoundationInstance;
516
613
  }
517
- type HttpClient = AxiosInstance;
518
- /** Create a configured HTTP client with full observability */
519
- declare function createHttpClient(options: HttpClientOptions): HttpClient;
520
-
521
- //#endregion
522
- //#region src/foundation.d.ts
523
- interface HealthStatus {
524
- status: 'healthy' | 'degraded' | 'unhealthy';
525
- timestamp: string;
526
- service: string;
527
- version: string;
528
- uptime: number;
529
- components: {
530
- tracing: ComponentHealth;
531
- metrics: ComponentHealth;
532
- logging: ComponentHealth;
533
- };
614
+ interface HttpModule {
615
+ createClient(options: Omit<HttpClientOptions, 'foundation'>): HttpClient;
534
616
  }
535
- interface ComponentHealth {
536
- enabled: boolean;
537
- status: 'up' | 'down' | 'disabled';
538
- message?: string;
617
+ interface LifecycleModule {
618
+ health(): HealthStatus;
619
+ isReady(): boolean;
620
+ shutdown(): Promise<void>;
621
+ safeRun<T>(fn: () => T | Promise<T>, fallback?: T): Promise<T | undefined>;
539
622
  }
540
623
  interface FoundationInstance {
541
624
  readonly config: FoundationConfig;
542
- readonly logger: Logger;
543
- readonly context: ContextManager;
544
- readonly tracer: Tracer | null;
545
- readonly meter: Meter | null;
546
- readonly fastifyPlugin: ReturnType<typeof createObservabilityPlugin>;
547
625
  readonly features: {
548
626
  tracing: boolean;
549
627
  metrics: boolean;
550
628
  logging: boolean;
551
629
  };
552
- getTracer: (name?: string) => Tracer;
553
- getMeter: (name: string, version?: string) => Meter;
630
+ readonly observability: ObservabilityModule;
631
+ readonly http: HttpModule;
632
+ readonly lifecycle: LifecycleModule;
633
+ readonly logger: Logger;
634
+ readonly context: ContextManager;
635
+ readonly fastifyPlugin: FastifyPluginAsync;
636
+ /** @deprecated Use `foundation.observability.tracer` */
637
+ readonly tracer: Tracer$1 | null;
638
+ /** @deprecated Use `foundation.observability.meter` */
639
+ readonly meter: Meter$1 | null;
640
+ /** @deprecated Use `foundation.observability.getTracer()` */
641
+ getTracer: (name?: string) => Tracer$1;
642
+ /** @deprecated Use `foundation.observability.getMeter()` */
643
+ getMeter: (name: string, version?: string) => Meter$1;
644
+ /** @deprecated Use `foundation.observability.getTraceContext()` */
554
645
  getTraceContext: () => {
555
646
  traceId?: string;
556
647
  spanId?: string;
557
648
  };
558
- getActiveSpan: () => ReturnType<typeof getActiveSpan>;
649
+ /** @deprecated Use `foundation.observability.getActiveSpan()` */
650
+ getActiveSpan: () => Span | undefined;
651
+ /** @deprecated Use `foundation.http.createClient()` */
559
652
  createHttpClient: (options: Omit<HttpClientOptions, 'foundation'>) => HttpClient;
653
+ /** @deprecated Use `foundation.lifecycle.shutdown()` */
560
654
  shutdown: () => Promise<void>;
655
+ /** @deprecated Use `foundation.lifecycle.isReady()` */
561
656
  isReady: () => boolean;
657
+ /** @deprecated Use `foundation.lifecycle.health()` */
562
658
  health: () => HealthStatus;
659
+ /** @deprecated Use `foundation.observability.trace()` */
563
660
  trace: <T>(name: string, fn: () => T | Promise<T>) => Promise<T>;
661
+ /** @deprecated Use `foundation.lifecycle.safeRun()` */
564
662
  safeRun: <T>(fn: () => T | Promise<T>, fallback?: T) => Promise<T | undefined>;
565
663
  }
664
+
665
+ //#endregion
666
+ //#region src/foundation.d.ts
667
+ //# sourceMappingURL=types.d.ts.map
566
668
  /** Create a fully configured observability foundation */
567
669
  declare function createFoundation(input: FoundationConfigInput): FoundationInstance;
568
670
  /** Alias for createFoundation */
569
671
  declare const setupObservability: typeof createFoundation;
570
672
 
571
673
  //#endregion
572
- export { AutoInstrumentationConfig, AutoInstrumentationConfigSchema, AxiosInstance, AxiosRequestConfig, AxiosResponse, ComponentHealth, ContextManager, FastifyPluginOptions, FeaturesConfig, FeaturesConfigSchema, FoundationConfig, FoundationConfigInput, FoundationConfigSchema, FoundationInstance, HealthStatus, HttpClient, HttpClientOptions, Logger, LoggerOptions, LoggingConfig, LoggingConfigSchema, Meter, MetricsOptions, OtelConfig, OtelConfigSchema, RequestContext, RequestLoggingConfig, RequestLoggingConfigSchema, SpanStatusCode, Tracer, TracingOptions, context, createContextManager, createFallbackLogger, createFoundation, createHttpClient, createLogger, createObservabilityPlugin, getActiveSpan, getDefaultOtelEndpoint, getGlobalLogger, getMeter, getTraceContext, getTracer, isMetricsEnabled, isTracingEnabled, metrics, parseConfig, propagation, setGlobalLogger, setupMetrics, setupObservability, setupTracing, shutdownMetrics, shutdownTracing, trace };
674
+ //#region src/features/redaction.d.ts
675
+ /**
676
+ * Log Redaction & PII Sanitization
677
+ *
678
+ * Two-layer approach:
679
+ * - Layer A: Pino native `redact` (fast-redact) for key-based redaction on every log call.
680
+ * Compiled at init, near-zero runtime cost.
681
+ * - Layer B: Deep-traverse sanitizer for value-pattern detection (JWTs, AWS keys, etc.).
682
+ * Only used for request/response body logging — NOT on every log call.
683
+ */
684
+ /**
685
+ * Key names that Pino's fast-redact will censor automatically.
686
+ * Supports wildcards: '*.password' matches nested keys one level deep.
687
+ */
688
+ declare const REDACT_PATHS: ReadonlyArray<string>;
689
+ /**
690
+ * Deep-traverse sanitizer for request/response bodies.
691
+ * Checks both key names (deny-list) and value patterns (JWT, AWS keys, etc.).
692
+ * NOT intended for every log call — use Pino native `redact` for that.
693
+ */
694
+ declare function sanitizeBody<T>(body: T): T;
695
+ /** Build the Pino `redact` config object for fast-redact integration */
696
+ declare function buildPinoRedactConfig(additionalPaths?: string[]): {
697
+ paths: string[];
698
+ censor: string;
699
+ };
700
+
701
+ //#endregion
702
+ //#region src/integrations/http-client.d.ts
703
+ //# sourceMappingURL=redaction.d.ts.map
704
+ /** Create a configured HTTP client with full observability */
705
+ declare function createHttpClient(options: HttpClientOptions): HttpClient;
706
+
707
+ //#endregion
708
+ //#region src/integrations/object-store/types.d.ts
709
+ type ObjectStoreProvider = 'aws-s3' | 'gcp-gcs' | 'azure-blob' | 'in-memory';
710
+ interface ObjectRef {
711
+ bucket: string;
712
+ key: string;
713
+ }
714
+ type ObjectBody = string | Uint8Array | Buffer | Readable;
715
+ interface PutObjectOptions {
716
+ contentType?: string;
717
+ cacheControl?: string;
718
+ metadata?: Record<string, string>;
719
+ }
720
+ interface PutObjectResult {
721
+ etag?: string;
722
+ versionId?: string;
723
+ }
724
+ interface HeadObjectResult {
725
+ exists: boolean;
726
+ contentType?: string;
727
+ contentLength?: number;
728
+ etag?: string;
729
+ versionId?: string;
730
+ metadata?: Record<string, string>;
731
+ lastModified?: Date;
732
+ }
733
+ interface GetObjectResult {
734
+ body: Readable;
735
+ contentType?: string;
736
+ contentLength?: number;
737
+ etag?: string;
738
+ versionId?: string;
739
+ metadata?: Record<string, string>;
740
+ lastModified?: Date;
741
+ }
742
+ interface ListObjectsOptions {
743
+ bucket: string;
744
+ prefix?: string;
745
+ continuationToken?: string;
746
+ maxKeys?: number;
747
+ }
748
+ interface ListObjectsResult {
749
+ objects: Array<{
750
+ key: string;
751
+ size?: number;
752
+ etag?: string;
753
+ lastModified?: Date;
754
+ }>;
755
+ nextContinuationToken?: string;
756
+ }
757
+ interface PresignGetObjectOptions {
758
+ expiresInSeconds: number;
759
+ responseContentType?: string;
760
+ }
761
+ interface PresignPutObjectOptions {
762
+ expiresInSeconds: number;
763
+ contentType?: string;
764
+ }
765
+
766
+ //#endregion
767
+ //#region src/integrations/object-store/object-store.d.ts
768
+ //# sourceMappingURL=types.d.ts.map
769
+ /**
770
+ * ObjectStore - provider-agnostic interface to wrap AWS S3 / GCS / etc.
771
+ *
772
+ * Downstream services should depend on this interface, not on cloud SDKs directly.
773
+ */
774
+ interface ObjectStore {
775
+ readonly provider: string;
776
+ putObject(ref: ObjectRef, body: ObjectBody, options?: PutObjectOptions): Promise<PutObjectResult>;
777
+ getObject(ref: ObjectRef): Promise<GetObjectResult>;
778
+ headObject(ref: ObjectRef): Promise<HeadObjectResult>;
779
+ deleteObject(ref: ObjectRef): Promise<void>;
780
+ listObjects(options: ListObjectsOptions): Promise<ListObjectsResult>;
781
+ presignGetObject(ref: ObjectRef, options: PresignGetObjectOptions): Promise<string>;
782
+ presignPutObject(ref: ObjectRef, options: PresignPutObjectOptions): Promise<string>;
783
+ }
784
+
785
+ //#endregion
786
+ //#region src/integrations/object-store/aws-s3.d.ts
787
+ //# sourceMappingURL=object-store.d.ts.map
788
+ /**
789
+ * Minimal interface for the subset of AWS S3Client we use.
790
+ * Keeps the module free of `any` while the SDK is dynamically imported.
791
+ */
792
+ interface S3ClientLike {
793
+ send(command: unknown): Promise<Record<string, unknown>>;
794
+ }
795
+ interface AwsS3ObjectStoreOptions {
796
+ /** Provide an existing S3 client instance (advanced use). */
797
+ client?: S3ClientLike;
798
+ /** Options forwarded to `new S3Client(...)` when `client` isn't provided. */
799
+ clientOptions?: Record<string, unknown>;
800
+ }
801
+ /**
802
+ * AwsS3ObjectStore - wraps AWS S3 behind the provider-agnostic `ObjectStore` interface.
803
+ *
804
+ * This implementation uses dynamic imports so `neoiq-foundation-node` can be used without AWS SDK.
805
+ */
806
+ declare class AwsS3ObjectStore implements ObjectStore {
807
+ readonly provider = "aws-s3";
808
+ private readonly clientPromise;
809
+ private readonly awsPromise;
810
+ constructor(options?: AwsS3ObjectStoreOptions);
811
+ private client;
812
+ putObject(ref: ObjectRef, body: ObjectBody, options?: PutObjectOptions): Promise<PutObjectResult>;
813
+ getObject(ref: ObjectRef): Promise<GetObjectResult>;
814
+ headObject(ref: ObjectRef): Promise<HeadObjectResult>;
815
+ deleteObject(ref: ObjectRef): Promise<void>;
816
+ listObjects(options: ListObjectsOptions): Promise<ListObjectsResult>;
817
+ presignGetObject(ref: ObjectRef, options: PresignGetObjectOptions): Promise<string>;
818
+ presignPutObject(ref: ObjectRef, options: PresignPutObjectOptions): Promise<string>;
819
+ }
820
+
821
+ //#endregion
822
+ //#region src/integrations/object-store/in-memory.d.ts
823
+ interface InMemoryObjectStoreOptions {
824
+ /** Maximum number of objects across all buckets. Throws when exceeded. */
825
+ maxObjects?: number;
826
+ }
827
+ /**
828
+ * InMemoryObjectStore - useful for local dev, unit tests, and as a safe default.
829
+ * NOTE: presign* methods are not meaningful here and will throw.
830
+ */
831
+ declare class InMemoryObjectStore implements ObjectStore {
832
+ readonly provider = "in-memory";
833
+ private readonly buckets;
834
+ private readonly maxObjects;
835
+ private objectCount;
836
+ constructor(options?: InMemoryObjectStoreOptions);
837
+ private bucketMap;
838
+ putObject(ref: ObjectRef, body: ObjectBody, options?: PutObjectOptions): Promise<PutObjectResult>;
839
+ getObject(ref: ObjectRef): Promise<GetObjectResult>;
840
+ headObject(ref: ObjectRef): Promise<HeadObjectResult>;
841
+ deleteObject(ref: ObjectRef): Promise<void>;
842
+ listObjects(options: ListObjectsOptions): Promise<ListObjectsResult>;
843
+ presignGetObject(_ref: ObjectRef, _options: PresignGetObjectOptions): Promise<string>;
844
+ presignPutObject(_ref: ObjectRef, _options: PresignPutObjectOptions): Promise<string>;
845
+ }
846
+
847
+ //#endregion
848
+ //# sourceMappingURL=in-memory.d.ts.map
849
+
850
+ export { AutoInstrumentationConfig, AutoInstrumentationConfigSchema, AwsS3ObjectStore, AwsS3ObjectStoreOptions, AxiosInstance, AxiosRequestConfig, AxiosResponse, ComponentHealth, ContextManager, FastifyPluginOptions, FeaturesConfig, FeaturesConfigSchema, FoundationConfig, FoundationConfigInput, FoundationConfigSchema, FoundationInstance, GetObjectResult, HeadObjectResult, HealthStatus, HttpClient, HttpClientOptions, HttpModule, InMemoryObjectStore, LifecycleModule, ListObjectsOptions, ListObjectsResult, Logger, LoggerOptions, LoggingConfig, LoggingConfigSchema, Meter, MetricsOptions, ObjectBody, ObjectRef, ObjectStore, ObjectStoreProvider, ObservabilityModule, OtelConfig, OtelConfigSchema, PresignGetObjectOptions, PresignPutObjectOptions, PutObjectOptions, PutObjectResult, REDACT_PATHS, RedactionConfig, RedactionConfigSchema, RequestContext, RequestLoggingConfig, RequestLoggingConfigSchema, RequestLoggingOptions, ShutdownConfig, ShutdownConfigSchema, SpanStatusCode, Tracer, TracingOptions, buildPinoRedactConfig, context, createContextManager, createFallbackLogger, createFoundation, createHttpClient, createLogger, createObservabilityPlugin, getActiveSpan, getDefaultOtelEndpoint, getGlobalLogger, getMeter, getTraceContext, getTracer, isMetricsEnabled, isTracingEnabled, metrics, parseConfig, propagation, sanitizeBody, setGlobalLogger, setupMetrics, setupObservability, setupTracing, shutdownMetrics, shutdownTracing, trace };
573
851
  //# sourceMappingURL=index.d.mts.map