autotel-adapters 0.3.11 → 0.3.13

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/src/nitro.ts DELETED
@@ -1,121 +0,0 @@
1
- import { AsyncLocalStorage } from 'node:async_hooks';
2
- import {
3
- getRequestLogger,
4
- trace,
5
- type RequestLogger,
6
- type RequestLoggerOptions,
7
- } from 'autotel';
8
- import { createAdapterToolkit, createUseLogger } from './core';
9
-
10
- export interface NitroEventLike {
11
- method?: string;
12
- path?: string;
13
- context?: Record<string, unknown>;
14
- }
15
-
16
- export interface NitroWithAutotelOptions {
17
- spanName?: string | ((event: NitroEventLike) => string);
18
- requestLoggerOptions?: RequestLoggerOptions;
19
- enrich?: (event: NitroEventLike) => Record<string, unknown> | undefined;
20
- /** Emit one wide event automatically when the handler settles. Default `true`. */
21
- autoEmit?: boolean;
22
- }
23
-
24
- function enrichFromEvent(
25
- event?: NitroEventLike,
26
- ): Record<string, unknown> | undefined {
27
- if (!event) return undefined;
28
-
29
- return {
30
- ...(event.method ? { 'http.request.method': event.method } : {}),
31
- ...(event.path ? { 'http.route': event.path } : {}),
32
- ...(typeof event.context?.requestId === 'string'
33
- ? { 'http.request.id': event.context.requestId }
34
- : {}),
35
- };
36
- }
37
-
38
- const baseUseLogger = createUseLogger<NitroEventLike>({
39
- adapterName: 'nitro',
40
- enrich: enrichFromEvent,
41
- });
42
- const nitroLoggerStorage = new AsyncLocalStorage<RequestLogger>();
43
-
44
- export function useLogger(
45
- event?: NitroEventLike,
46
- serviceOrOptions?: string | RequestLoggerOptions,
47
- ): RequestLogger {
48
- const stored = nitroLoggerStorage.getStore();
49
- const logger = stored ??
50
- (
51
- typeof serviceOrOptions === 'string'
52
- ? baseUseLogger(event)
53
- : baseUseLogger(event, serviceOrOptions)
54
- );
55
-
56
- if (typeof serviceOrOptions === 'string' && serviceOrOptions.length > 0) {
57
- logger.set({ service: serviceOrOptions });
58
- }
59
-
60
- return logger;
61
- }
62
-
63
- export function withAutotelEventHandler<TEvent extends NitroEventLike, TReturn>(
64
- handler: (event: TEvent) => TReturn | Promise<TReturn>,
65
- options?: NitroWithAutotelOptions,
66
- ): (event: TEvent) => Promise<TReturn> {
67
- return async (event: TEvent): Promise<TReturn> => {
68
- const spanName =
69
- typeof options?.spanName === 'function'
70
- ? options.spanName(event)
71
- : (options?.spanName ?? `nitro.${event.method ?? 'request'}`);
72
-
73
- const wrapped = trace({ name: spanName }, (ctx) => async (innerEvent: TEvent) => {
74
- const log = getRequestLogger(ctx, options?.requestLoggerOptions);
75
- const auto = enrichFromEvent(innerEvent);
76
- if (auto && Object.keys(auto).length > 0) {
77
- log.set(auto);
78
- }
79
- const custom = options?.enrich?.(innerEvent);
80
- if (custom && Object.keys(custom).length > 0) {
81
- log.set(custom);
82
- }
83
- try {
84
- return await nitroLoggerStorage.run(log, async () =>
85
- handler(innerEvent),
86
- );
87
- } finally {
88
- if (options?.autoEmit !== false) {
89
- log.emitNow();
90
- }
91
- }
92
- });
93
-
94
- return await wrapped(event);
95
- };
96
- }
97
-
98
- export function createNitroAdapter(options?: NitroWithAutotelOptions) {
99
- const toolkit = createAdapterToolkit<NitroEventLike>({
100
- adapterName: 'nitro',
101
- enrich: (event) => ({
102
- ...enrichFromEvent(event),
103
- ...(options?.enrich?.(event) ?? {}),
104
- }),
105
- });
106
-
107
- return {
108
- withAutotelEventHandler: <TEvent extends NitroEventLike, TReturn>(
109
- handler: (event: TEvent) => TReturn | Promise<TReturn>,
110
- ) => withAutotelEventHandler(handler, options),
111
- useLogger,
112
- parseError: toolkit.parseError,
113
- createStructuredError: toolkit.createStructuredError,
114
- createDrainPipeline: toolkit.createDrainPipeline,
115
- };
116
- }
117
-
118
- export const nitroToolkit = createAdapterToolkit<NitroEventLike>({
119
- adapterName: 'nitro',
120
- enrich: enrichFromEvent,
121
- });
@@ -1,110 +0,0 @@
1
- import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
2
- import {
3
- resolveAdapterConfig,
4
- shouldProbeRuntime,
5
- type ConfigField,
6
- } from './core';
7
-
8
- interface AdapterConfig {
9
- token?: string;
10
- endpoint?: string;
11
- timeout?: number;
12
- }
13
-
14
- const FIELDS: ConfigField<AdapterConfig>[] = [
15
- { key: 'token', env: ['MY_ADAPTER_TOKEN'] },
16
- { key: 'endpoint', env: ['MY_ADAPTER_ENDPOINT'] },
17
- { key: 'timeout' }, // optional tuning field, no env fallback
18
- ];
19
-
20
- describe('shouldProbeRuntime', () => {
21
- beforeEach(() => {
22
- delete process.env.MY_ADAPTER_TOKEN;
23
- delete process.env.MY_ADAPTER_ENDPOINT;
24
- });
25
-
26
- it('returns false when overrides cover every env-backed field', () => {
27
- expect(
28
- shouldProbeRuntime(FIELDS, { token: 't', endpoint: 'u' }),
29
- ).toBe(false);
30
- });
31
-
32
- it('returns false when env covers every env-backed field', () => {
33
- process.env.MY_ADAPTER_TOKEN = 't';
34
- process.env.MY_ADAPTER_ENDPOINT = 'u';
35
- expect(shouldProbeRuntime(FIELDS)).toBe(true);
36
- });
37
-
38
- it('returns true when an env-backed field is still missing', () => {
39
- process.env.MY_ADAPTER_TOKEN = 't';
40
- expect(shouldProbeRuntime(FIELDS)).toBe(true);
41
- });
42
-
43
- it('ignores fields with no env list (optional tuning fields)', () => {
44
- process.env.MY_ADAPTER_TOKEN = 't';
45
- process.env.MY_ADAPTER_ENDPOINT = 'u';
46
- // `timeout` is still a runtime-resolvable field, so probing may still apply.
47
- expect(shouldProbeRuntime(FIELDS)).toBe(true);
48
- });
49
- });
50
-
51
- describe('resolveAdapterConfig', () => {
52
- beforeEach(() => {
53
- delete process.env.MY_ADAPTER_TOKEN;
54
- delete process.env.MY_ADAPTER_ENDPOINT;
55
- });
56
- afterEach(() => vi.restoreAllMocks());
57
-
58
- it('calls the probe when overrides do not fully resolve config', async () => {
59
- process.env.MY_ADAPTER_TOKEN = 't';
60
- process.env.MY_ADAPTER_ENDPOINT = 'u';
61
-
62
- const probe = vi.fn().mockResolvedValue(undefined);
63
- const cfg = await resolveAdapterConfig('my-adapter', FIELDS, undefined, probe);
64
-
65
- expect(probe).toHaveBeenCalledOnce();
66
- expect(cfg.token).toBe('t');
67
- expect(cfg.endpoint).toBe('u');
68
- });
69
-
70
- it('calls the probe and merges runtimeConfig.autotel.<namespace>.<key>', async () => {
71
- const probe = vi.fn().mockResolvedValue({
72
- autotel: { 'my-adapter': { token: 'from-runtime', endpoint: 'rt-url' } },
73
- });
74
- const cfg = await resolveAdapterConfig('my-adapter', FIELDS, undefined, probe);
75
-
76
- expect(probe).toHaveBeenCalledOnce();
77
- expect(cfg.token).toBe('from-runtime');
78
- expect(cfg.endpoint).toBe('rt-url');
79
- });
80
-
81
- it('overrides win over runtime and env', async () => {
82
- process.env.MY_ADAPTER_TOKEN = 'env-token';
83
- const probe = vi.fn().mockResolvedValue({
84
- autotel: { 'my-adapter': { token: 'rt-token', endpoint: 'rt-url' } },
85
- });
86
-
87
- const cfg = await resolveAdapterConfig(
88
- 'my-adapter',
89
- FIELDS,
90
- { token: 'override' },
91
- probe,
92
- );
93
-
94
- expect(cfg.token).toBe('override');
95
- expect(cfg.endpoint).toBe('rt-url');
96
- });
97
-
98
- it('runtime config wins over env when both are present', async () => {
99
- process.env.MY_ADAPTER_TOKEN = 'env-token';
100
- process.env.MY_ADAPTER_ENDPOINT = 'env-url';
101
-
102
- const probe = vi.fn().mockResolvedValue({
103
- autotel: { 'my-adapter': { token: 'rt-token', endpoint: 'rt-url' } },
104
- });
105
- const cfg = await resolveAdapterConfig('my-adapter', FIELDS, undefined, probe);
106
-
107
- expect(cfg.token).toBe('rt-token');
108
- expect(cfg.endpoint).toBe('rt-url');
109
- });
110
- });
package/src/tanstack.ts DELETED
@@ -1,23 +0,0 @@
1
- import { createUseLogger, createAdapterToolkit } from './core';
2
-
3
- export const useLogger = createUseLogger<{
4
- pathname?: string;
5
- method?: string;
6
- }>({
7
- adapterName: 'tanstack',
8
- enrich: (ctx) => ({
9
- ...(ctx.method ? { 'http.request.method': ctx.method } : {}),
10
- ...(ctx.pathname ? { 'http.route': ctx.pathname } : {}),
11
- }),
12
- });
13
-
14
- export const tanstackToolkit = createAdapterToolkit<{
15
- pathname?: string;
16
- method?: string;
17
- }>({
18
- adapterName: 'tanstack',
19
- enrich: (ctx) => ({
20
- ...(ctx.method ? { 'http.request.method': ctx.method } : {}),
21
- ...(ctx.pathname ? { 'http.route': ctx.pathname } : {}),
22
- }),
23
- });