@kb-labs/adapters-log-document 2.112.0 → 2.114.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +5 -2
- package/dist/index.js +85 -41
- package/dist/index.js.map +1 -1
- package/dist/manifest.js +10 -2
- package/dist/manifest.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -42,11 +42,12 @@ declare class DocumentLogPersistence implements ILogPersistence {
|
|
|
42
42
|
write(record: LogRecord): Promise<void>;
|
|
43
43
|
writeBatch(records: LogRecord[]): Promise<void>;
|
|
44
44
|
private flush;
|
|
45
|
+
private scheduleFlush;
|
|
45
46
|
query(query: LogQuery, options?: {
|
|
46
47
|
limit?: number;
|
|
47
48
|
offset?: number;
|
|
48
|
-
sortBy?:
|
|
49
|
-
sortOrder?:
|
|
49
|
+
sortBy?: "timestamp" | "level";
|
|
50
|
+
sortOrder?: "asc" | "desc";
|
|
50
51
|
}): Promise<{
|
|
51
52
|
logs: LogRecord[];
|
|
52
53
|
total: number;
|
|
@@ -56,6 +57,7 @@ declare class DocumentLogPersistence implements ILogPersistence {
|
|
|
56
57
|
search(searchText: string, options?: {
|
|
57
58
|
limit?: number;
|
|
58
59
|
offset?: number;
|
|
60
|
+
filters?: LogQuery;
|
|
59
61
|
}): Promise<{
|
|
60
62
|
logs: LogRecord[];
|
|
61
63
|
total: number;
|
|
@@ -71,6 +73,7 @@ declare class DocumentLogPersistence implements ILogPersistence {
|
|
|
71
73
|
}>;
|
|
72
74
|
close(): Promise<void>;
|
|
73
75
|
private runRetention;
|
|
76
|
+
private expire;
|
|
74
77
|
}
|
|
75
78
|
declare function createAdapter(config: LogPersistenceConfig, deps?: Record<string, unknown>): DocumentLogPersistence;
|
|
76
79
|
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import { LOG_CONTEXT_FIELDS } from '@kb-labs/sdk/adapters';
|
|
2
|
+
|
|
3
|
+
// src/index.ts
|
|
4
|
+
|
|
1
5
|
// src/manifest.ts
|
|
2
6
|
var manifest = {
|
|
3
7
|
manifestVersion: "1.0.0",
|
|
@@ -7,10 +11,18 @@ var manifest = {
|
|
|
7
11
|
description: "ILogPersistence implementation storing log entries in any IDocumentDatabase. Driver-agnostic.",
|
|
8
12
|
author: "KB Labs Team",
|
|
9
13
|
license: "KBPL-1.1",
|
|
10
|
-
type: "
|
|
14
|
+
type: "extension",
|
|
11
15
|
implements: "ILogPersistence",
|
|
16
|
+
extends: {
|
|
17
|
+
adapter: "logger",
|
|
18
|
+
hook: "onLog",
|
|
19
|
+
method: "write",
|
|
20
|
+
priority: 0
|
|
21
|
+
},
|
|
12
22
|
contexts: ["workspace", "process"],
|
|
13
|
-
requires: {
|
|
23
|
+
requires: {
|
|
24
|
+
adapters: [{ id: "documentDatabase", alias: "documentDatabase" }]
|
|
25
|
+
},
|
|
14
26
|
capabilities: {
|
|
15
27
|
batch: true,
|
|
16
28
|
search: true,
|
|
@@ -48,17 +60,16 @@ var LEVEL_ORDER = {
|
|
|
48
60
|
};
|
|
49
61
|
var LEVELS_AT_OR_ABOVE = (min) => {
|
|
50
62
|
const threshold = LEVEL_ORDER[min];
|
|
51
|
-
return Object.keys(LEVEL_ORDER).filter(
|
|
63
|
+
return Object.keys(LEVEL_ORDER).filter(
|
|
64
|
+
(l) => LEVEL_ORDER[l] >= threshold
|
|
65
|
+
);
|
|
52
66
|
};
|
|
53
67
|
var DEFAULT_RETENTION = {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
maxAgeInfo:
|
|
59
|
-
// 24 hours for info
|
|
60
|
-
maxSizeBytes: 500 * 1024 * 1024,
|
|
61
|
-
// 500 MB
|
|
68
|
+
maxAgeFatal: 30 * 24 * 60 * 60 * 1e3,
|
|
69
|
+
maxAgeError: 14 * 24 * 60 * 60 * 1e3,
|
|
70
|
+
maxAgeWarn: 7 * 24 * 60 * 60 * 1e3,
|
|
71
|
+
maxAgeDebug: 30 * 60 * 1e3,
|
|
72
|
+
maxAgeInfo: 30 * 60 * 1e3,
|
|
62
73
|
cleanupIntervalMs: 5 * 60 * 1e3
|
|
63
74
|
// 5 minutes
|
|
64
75
|
};
|
|
@@ -85,11 +96,12 @@ var DocumentLogPersistence = class {
|
|
|
85
96
|
{ path: "logId", unique: true },
|
|
86
97
|
{ path: "timestamp" },
|
|
87
98
|
{ path: "level" },
|
|
88
|
-
{ path: "source" }
|
|
99
|
+
{ path: "source" },
|
|
100
|
+
...LOG_CONTEXT_FIELDS.map((field) => ({ path: `fields.${field}` }))
|
|
89
101
|
]
|
|
90
102
|
});
|
|
91
103
|
this.flushTimer = setInterval(() => {
|
|
92
|
-
|
|
104
|
+
this.scheduleFlush();
|
|
93
105
|
}, this.flushIntervalMs).unref();
|
|
94
106
|
this.retentionTimer = setInterval(() => {
|
|
95
107
|
void this.runRetention();
|
|
@@ -100,23 +112,23 @@ var DocumentLogPersistence = class {
|
|
|
100
112
|
// ──────────────────────────────────────────────────────────────────────────
|
|
101
113
|
async write(record) {
|
|
102
114
|
if (this.closed) {
|
|
103
|
-
|
|
115
|
+
return;
|
|
104
116
|
}
|
|
105
117
|
this.buffer.push(record);
|
|
106
118
|
if (this.buffer.length >= this.batchSize) {
|
|
107
|
-
|
|
119
|
+
this.scheduleFlush();
|
|
108
120
|
}
|
|
109
121
|
}
|
|
110
122
|
async writeBatch(records) {
|
|
111
123
|
if (this.closed) {
|
|
112
|
-
|
|
124
|
+
return;
|
|
113
125
|
}
|
|
114
126
|
if (records.length === 0) {
|
|
115
127
|
return;
|
|
116
128
|
}
|
|
117
129
|
this.buffer.push(...records);
|
|
118
130
|
if (this.buffer.length >= this.batchSize) {
|
|
119
|
-
|
|
131
|
+
this.scheduleFlush();
|
|
120
132
|
}
|
|
121
133
|
}
|
|
122
134
|
async flush() {
|
|
@@ -131,14 +143,17 @@ var DocumentLogPersistence = class {
|
|
|
131
143
|
this.flushing = (async () => {
|
|
132
144
|
try {
|
|
133
145
|
await this.initialised;
|
|
134
|
-
await this.docs.insertMany(
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
146
|
+
await this.docs.insertMany(
|
|
147
|
+
this.collection,
|
|
148
|
+
batch.map((r) => ({
|
|
149
|
+
logId: r.id,
|
|
150
|
+
timestamp: r.timestamp,
|
|
151
|
+
level: r.level,
|
|
152
|
+
message: r.message,
|
|
153
|
+
fields: r.fields,
|
|
154
|
+
source: r.source
|
|
155
|
+
}))
|
|
156
|
+
);
|
|
142
157
|
} catch (err) {
|
|
143
158
|
this.buffer.unshift(...batch);
|
|
144
159
|
throw err;
|
|
@@ -148,6 +163,10 @@ var DocumentLogPersistence = class {
|
|
|
148
163
|
})();
|
|
149
164
|
await this.flushing;
|
|
150
165
|
}
|
|
166
|
+
scheduleFlush() {
|
|
167
|
+
void this.flush().catch(() => {
|
|
168
|
+
});
|
|
169
|
+
}
|
|
151
170
|
// ──────────────────────────────────────────────────────────────────────────
|
|
152
171
|
// Read path
|
|
153
172
|
// ──────────────────────────────────────────────────────────────────────────
|
|
@@ -174,13 +193,21 @@ var DocumentLogPersistence = class {
|
|
|
174
193
|
}
|
|
175
194
|
async getById(id) {
|
|
176
195
|
await this.initialised;
|
|
177
|
-
const docs = await this.docs.find(
|
|
196
|
+
const docs = await this.docs.find(
|
|
197
|
+
this.collection,
|
|
198
|
+
{ logId: { $eq: id } },
|
|
199
|
+
{ limit: 1 }
|
|
200
|
+
);
|
|
178
201
|
const first = docs[0];
|
|
179
202
|
return first ? toLogRecord(first) : null;
|
|
180
203
|
}
|
|
181
204
|
async search(searchText, options) {
|
|
182
205
|
await this.initialised;
|
|
183
|
-
const
|
|
206
|
+
const textFilter = {
|
|
207
|
+
message: { $contains: searchText }
|
|
208
|
+
};
|
|
209
|
+
const structuredFilter = buildFilter(options?.filters ?? {});
|
|
210
|
+
const filter = Object.keys(structuredFilter).length === 0 ? textFilter : { $and: [structuredFilter, textFilter] };
|
|
184
211
|
const limit = options?.limit ?? 100;
|
|
185
212
|
const offset = options?.offset ?? 0;
|
|
186
213
|
const [total, docs] = await Promise.all([
|
|
@@ -216,8 +243,16 @@ var DocumentLogPersistence = class {
|
|
|
216
243
|
await this.initialised;
|
|
217
244
|
const [totalLogs, oldest, newest] = await Promise.all([
|
|
218
245
|
this.docs.count(this.collection, {}),
|
|
219
|
-
this.docs.find(
|
|
220
|
-
|
|
246
|
+
this.docs.find(
|
|
247
|
+
this.collection,
|
|
248
|
+
{},
|
|
249
|
+
{ sort: { timestamp: 1 }, limit: 1 }
|
|
250
|
+
),
|
|
251
|
+
this.docs.find(
|
|
252
|
+
this.collection,
|
|
253
|
+
{},
|
|
254
|
+
{ sort: { timestamp: -1 }, limit: 1 }
|
|
255
|
+
)
|
|
221
256
|
]);
|
|
222
257
|
return {
|
|
223
258
|
totalLogs,
|
|
@@ -253,20 +288,20 @@ var DocumentLogPersistence = class {
|
|
|
253
288
|
}
|
|
254
289
|
const now = Date.now();
|
|
255
290
|
try {
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
if (this.retention.maxAgeInfo > 0) {
|
|
262
|
-
await this.deleteByLevelOlderThan(["info"], now - this.retention.maxAgeInfo);
|
|
263
|
-
}
|
|
264
|
-
if (this.retention.maxAge > 0) {
|
|
265
|
-
await this.deleteByLevelOlderThan(["warn", "error", "fatal"], now - this.retention.maxAge);
|
|
266
|
-
}
|
|
291
|
+
await this.expire(["trace", "debug"], this.retention.maxAgeDebug, now);
|
|
292
|
+
await this.expire(["info"], this.retention.maxAgeInfo, now);
|
|
293
|
+
await this.expire(["warn"], this.retention.maxAgeWarn, now);
|
|
294
|
+
await this.expire(["error"], this.retention.maxAgeError, now);
|
|
295
|
+
await this.expire(["fatal"], this.retention.maxAgeFatal, now);
|
|
267
296
|
} catch {
|
|
268
297
|
}
|
|
269
298
|
}
|
|
299
|
+
async expire(levels, maxAge, now) {
|
|
300
|
+
await this.deleteByLevelOlderThan(
|
|
301
|
+
levels,
|
|
302
|
+
maxAge > 0 ? now - maxAge : now + 1
|
|
303
|
+
);
|
|
304
|
+
}
|
|
270
305
|
};
|
|
271
306
|
var buildFilter = (query) => {
|
|
272
307
|
const clauses = [];
|
|
@@ -282,6 +317,12 @@ var buildFilter = (query) => {
|
|
|
282
317
|
if (query.to !== void 0) {
|
|
283
318
|
clauses.push({ timestamp: { $lte: query.to } });
|
|
284
319
|
}
|
|
320
|
+
for (const field of LOG_CONTEXT_FIELDS) {
|
|
321
|
+
const value = query[field];
|
|
322
|
+
if (value !== void 0) {
|
|
323
|
+
clauses.push({ [`fields.${field}`]: { $eq: value } });
|
|
324
|
+
}
|
|
325
|
+
}
|
|
285
326
|
if (clauses.length === 0) {
|
|
286
327
|
return {};
|
|
287
328
|
}
|
|
@@ -299,7 +340,10 @@ var toLogRecord = (doc) => ({
|
|
|
299
340
|
source: doc.source
|
|
300
341
|
});
|
|
301
342
|
function createAdapter(config, deps) {
|
|
302
|
-
const resolved = deps?.["documentDatabase"] ? {
|
|
343
|
+
const resolved = deps?.["documentDatabase"] ? {
|
|
344
|
+
...config,
|
|
345
|
+
documentDatabase: deps["documentDatabase"]
|
|
346
|
+
} : config;
|
|
303
347
|
return new DocumentLogPersistence(resolved);
|
|
304
348
|
}
|
|
305
349
|
var index_default = createAdapter;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/manifest.ts","../src/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * @module @kb-labs/adapters-log-document/manifest\n *\n * Manifest for the Document-backed log persistence adapter. It depends on\n * the platform's `documentDatabase` service — register a concrete document\n * driver (sqlite, postgres, mongo) first and this adapter rides on top.\n */\n\nimport type { AdapterManifest } from '@kb-labs/sdk/adapters';\n\nexport const manifest: AdapterManifest = {\n manifestVersion: '1.0.0',\n id: 'log-document',\n name: 'Document-backed Log Persistence',\n version: '1.0.0',\n description:\n 'ILogPersistence implementation storing log entries in any IDocumentDatabase. Driver-agnostic.',\n author: 'KB Labs Team',\n license: 'KBPL-1.1',\n type: 'core',\n implements: 'ILogPersistence',\n contexts: ['workspace', 'process'],\n requires: { adapters: [{ id: 'documentDatabase', alias: 'documentDatabase' }] },\n capabilities: {\n batch: true,\n search: true,\n custom: {\n retentionPolicy: true,\n },\n },\n configSchema: {\n collection: {\n type: 'string',\n default: 'logs',\n description: 'Name of the document collection that stores log entries.',\n },\n batchSize: {\n type: 'number',\n default: 100,\n description: 'Batch size for buffered writes.',\n },\n flushInterval: {\n type: 'number',\n default: 5000,\n description: 'Maximum delay before a partial batch is flushed (ms).',\n },\n },\n};\n","/**\n * @module @kb-labs/adapters-log-document\n *\n * `ILogPersistence` implementation backed by any `IDocumentDatabase`.\n *\n * This is the dogfooded replacement for the old sqlite-only log persistence\n * adapter: log entries are now stored as documents in a `logs` collection\n * using the same abstraction every other plugin uses. The platform stays\n * driver-agnostic — switch from sqlite to postgres-JSONB and logs follow.\n *\n * Buffering: writes are queued in memory and flushed in batches to amortise\n * per-call overhead. `close()` (and the next flush after batchSize entries)\n * drains the queue.\n *\n * Retention: a periodic timer deletes documents older than the configured\n * thresholds per log level. Without retention the collection grows\n * unbounded — defaults are applied if `retention` is absent.\n *\n * Search: implemented via `$contains` on the message field. Full-text\n * indexing (FTS5, MongoDB text) is intentionally OUT of scope here — that's\n * a backend-specific capability and would leak through the contract. If\n * advanced search is needed, route it via an external index (Meilisearch\n * etc.) and keep this layer simple.\n */\n\nimport type {\n ILogPersistence,\n LogPersistenceConfig,\n LogRetentionPolicy,\n LogRecord,\n LogQuery,\n LogLevel,\n IDocumentDatabase,\n DocumentFilter,\n BaseDocument,\n} from '@kb-labs/sdk/adapters';\n\nexport { manifest } from './manifest.js';\n\ninterface LogDoc extends BaseDocument {\n logId: string;\n timestamp: number;\n level: LogLevel;\n message: string;\n fields: Record<string, unknown>;\n source: string;\n}\n\nconst LEVEL_ORDER: Record<LogLevel, number> = {\n trace: 0,\n debug: 1,\n info: 2,\n warn: 3,\n error: 4,\n fatal: 5,\n};\n\nconst LEVELS_AT_OR_ABOVE = (min: LogLevel): LogLevel[] => {\n const threshold = LEVEL_ORDER[min];\n return (Object.keys(LEVEL_ORDER) as LogLevel[]).filter((l) => LEVEL_ORDER[l] >= threshold);\n};\n\nconst DEFAULT_RETENTION: Required<Pick<LogRetentionPolicy,\n 'maxAge' | 'maxAgeDebug' | 'maxAgeInfo' | 'maxSizeBytes' | 'cleanupIntervalMs'>> = {\n maxAge: 7 * 24 * 60 * 60 * 1000, // 7 days for warn/error/fatal\n maxAgeDebug: 60 * 60 * 1000, // 1 hour for debug/trace\n maxAgeInfo: 24 * 60 * 60 * 1000, // 24 hours for info\n maxSizeBytes: 500 * 1024 * 1024, // 500 MB\n cleanupIntervalMs: 5 * 60 * 1000, // 5 minutes\n};\n\nexport class DocumentLogPersistence implements ILogPersistence {\n private readonly docs: IDocumentDatabase;\n private readonly collection: string;\n private readonly batchSize: number;\n private readonly flushIntervalMs: number;\n private readonly retention: Required<Pick<LogRetentionPolicy,\n 'maxAge' | 'maxAgeDebug' | 'maxAgeInfo' | 'maxSizeBytes' | 'cleanupIntervalMs'>>;\n\n private buffer: LogRecord[] = [];\n private flushTimer: NodeJS.Timeout | null = null;\n private retentionTimer: NodeJS.Timeout | null = null;\n private closed = false;\n private flushing: Promise<void> | null = null;\n private initialised: Promise<void>;\n\n constructor(config: LogPersistenceConfig) {\n this.docs = config.documentDatabase;\n this.collection = config.collection ?? 'logs';\n this.batchSize = config.batchSize ?? 100;\n this.flushIntervalMs = config.flushInterval ?? 5_000;\n this.retention = { ...DEFAULT_RETENTION, ...(config.retention ?? {}) };\n\n this.initialised = this.docs.ensureCollection(this.collection, {\n indexes: [\n { path: 'logId', unique: true },\n { path: 'timestamp' },\n { path: 'level' },\n { path: 'source' },\n ],\n });\n\n this.flushTimer = setInterval(() => { void this.flush(); }, this.flushIntervalMs).unref();\n this.retentionTimer = setInterval(() => { void this.runRetention(); }, this.retention.cleanupIntervalMs).unref();\n }\n\n // ──────────────────────────────────────────────────────────────────────────\n // Write path (buffered)\n // ──────────────────────────────────────────────────────────────────────────\n\n async write(record: LogRecord): Promise<void> {\n if (this.closed) {throw new Error('DocumentLogPersistence is closed');}\n this.buffer.push(record);\n if (this.buffer.length >= this.batchSize) {\n void this.flush();\n }\n }\n\n async writeBatch(records: LogRecord[]): Promise<void> {\n if (this.closed) {throw new Error('DocumentLogPersistence is closed');}\n if (records.length === 0) {return;}\n this.buffer.push(...records);\n if (this.buffer.length >= this.batchSize) {\n void this.flush();\n }\n }\n\n private async flush(): Promise<void> {\n if (this.flushing) {\n await this.flushing;\n return;\n }\n if (this.buffer.length === 0) {return;}\n const batch = this.buffer.splice(0, this.buffer.length);\n\n this.flushing = (async () => {\n try {\n await this.initialised;\n await this.docs.insertMany<LogDoc>(this.collection, batch.map((r) => ({\n logId: r.id,\n timestamp: r.timestamp,\n level: r.level,\n message: r.message,\n fields: r.fields,\n source: r.source,\n })));\n } catch (err) {\n // Re-queue on failure so the next attempt picks up the lost batch.\n this.buffer.unshift(...batch);\n throw err;\n } finally {\n this.flushing = null;\n }\n })();\n\n await this.flushing;\n }\n\n // ──────────────────────────────────────────────────────────────────────────\n // Read path\n // ──────────────────────────────────────────────────────────────────────────\n\n async query(\n query: LogQuery,\n options?: {\n limit?: number;\n offset?: number;\n sortBy?: 'timestamp' | 'level';\n sortOrder?: 'asc' | 'desc';\n },\n ): Promise<{ logs: LogRecord[]; total: number; hasMore: boolean }> {\n await this.initialised;\n const filter = buildFilter(query);\n const limit = options?.limit ?? 100;\n const offset = options?.offset ?? 0;\n const sortField = options?.sortBy ?? 'timestamp';\n const sortDir = options?.sortOrder === 'asc' ? 1 : -1;\n\n const [total, docs] = await Promise.all([\n this.docs.count<LogDoc>(this.collection, filter),\n this.docs.find<LogDoc>(this.collection, filter, {\n sort: { [sortField]: sortDir },\n limit,\n skip: offset,\n }),\n ]);\n\n return {\n logs: docs.map(toLogRecord),\n total,\n hasMore: offset + docs.length < total,\n };\n }\n\n async getById(id: string): Promise<LogRecord | null> {\n await this.initialised;\n const docs = await this.docs.find<LogDoc>(this.collection, { logId: { $eq: id } }, { limit: 1 });\n const first = docs[0];\n return first ? toLogRecord(first) : null;\n }\n\n async search(\n searchText: string,\n options?: { limit?: number; offset?: number },\n ): Promise<{ logs: LogRecord[]; total: number; hasMore: boolean }> {\n await this.initialised;\n const filter: DocumentFilter<LogDoc> = { message: { $contains: searchText } };\n const limit = options?.limit ?? 100;\n const offset = options?.offset ?? 0;\n\n const [total, docs] = await Promise.all([\n this.docs.count<LogDoc>(this.collection, filter),\n this.docs.find<LogDoc>(this.collection, filter, {\n sort: { timestamp: -1 },\n limit,\n skip: offset,\n }),\n ]);\n\n return {\n logs: docs.map(toLogRecord),\n total,\n hasMore: offset + docs.length < total,\n };\n }\n\n async deleteOlderThan(beforeTimestamp: number): Promise<number> {\n await this.initialised;\n return this.docs.deleteMany<LogDoc>(this.collection, {\n timestamp: { $lt: beforeTimestamp },\n });\n }\n\n async deleteByLevelOlderThan(levels: string[], beforeTimestamp: number): Promise<number> {\n await this.initialised;\n return this.docs.deleteMany<LogDoc>(this.collection, {\n $and: [\n { level: { $in: levels as LogLevel[] } },\n { timestamp: { $lt: beforeTimestamp } },\n ],\n });\n }\n\n async getStats(): Promise<{\n totalLogs: number;\n oldestTimestamp: number;\n newestTimestamp: number;\n sizeBytes: number;\n }> {\n await this.initialised;\n const [totalLogs, oldest, newest] = await Promise.all([\n this.docs.count<LogDoc>(this.collection, {}),\n this.docs.find<LogDoc>(this.collection, {}, { sort: { timestamp: 1 }, limit: 1 }),\n this.docs.find<LogDoc>(this.collection, {}, { sort: { timestamp: -1 }, limit: 1 }),\n ]);\n // Size is not exposed by IDocumentDatabase by design (it varies wildly\n // by backend). Returning 0 here is honest — callers driving retention\n // by size should configure maxAge instead and stop pretending bytes are\n // a universal currency across drivers.\n return {\n totalLogs,\n oldestTimestamp: oldest[0]?.timestamp ?? 0,\n newestTimestamp: newest[0]?.timestamp ?? 0,\n sizeBytes: 0,\n };\n }\n\n async close(): Promise<void> {\n if (this.closed) {return;}\n this.closed = true;\n if (this.flushTimer) { clearInterval(this.flushTimer); this.flushTimer = null; }\n if (this.retentionTimer) { clearInterval(this.retentionTimer); this.retentionTimer = null; }\n try {\n await this.flush();\n } catch {\n /* swallow — we tried */\n }\n }\n\n // ──────────────────────────────────────────────────────────────────────────\n // Retention\n // ──────────────────────────────────────────────────────────────────────────\n\n private async runRetention(): Promise<void> {\n if (this.closed) {return;}\n const now = Date.now();\n try {\n if (this.retention.maxAgeDebug > 0) {\n await this.deleteByLevelOlderThan(['trace', 'debug'], now - this.retention.maxAgeDebug);\n } else {\n // maxAgeDebug = 0 means do not persist debug/trace at all → wipe immediately.\n await this.deleteByLevelOlderThan(['trace', 'debug'], now + 1);\n }\n if (this.retention.maxAgeInfo > 0) {\n await this.deleteByLevelOlderThan(['info'], now - this.retention.maxAgeInfo);\n }\n if (this.retention.maxAge > 0) {\n await this.deleteByLevelOlderThan(['warn', 'error', 'fatal'], now - this.retention.maxAge);\n }\n } catch {\n /* retention failures should not propagate — they're best-effort cleanup */\n }\n }\n}\n\nconst buildFilter = (query: LogQuery): DocumentFilter<LogDoc> => {\n const clauses: Array<DocumentFilter<LogDoc>> = [];\n if (query.level !== undefined) {\n clauses.push({ level: { $in: LEVELS_AT_OR_ABOVE(query.level) } });\n }\n if (query.source !== undefined) {\n clauses.push({ source: { $eq: query.source } });\n }\n if (query.from !== undefined) {\n clauses.push({ timestamp: { $gte: query.from } });\n }\n if (query.to !== undefined) {\n clauses.push({ timestamp: { $lte: query.to } });\n }\n if (clauses.length === 0) {return {};}\n if (clauses.length === 1) {return clauses[0]!;}\n return { $and: clauses };\n};\n\nconst toLogRecord = (doc: LogDoc): LogRecord => ({\n id: doc.logId,\n timestamp: doc.timestamp,\n level: doc.level,\n message: doc.message,\n fields: doc.fields,\n source: doc.source,\n});\n\nexport function createAdapter(\n config: LogPersistenceConfig,\n deps?: Record<string, unknown>,\n): DocumentLogPersistence {\n // deps.documentDatabase is injected by the adapter-loader when the manifest\n // declares requires.adapters = [{ id: \"documentDatabase\" }]. Merge it in so\n // callers don't need to duplicate the reference in adapterOptions config.\n const resolved: LogPersistenceConfig = deps?.['documentDatabase']\n ? { ...config, documentDatabase: deps['documentDatabase'] as IDocumentDatabase }\n : config;\n return new DocumentLogPersistence(resolved);\n}\n\nexport default createAdapter;\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/manifest.ts","../src/index.ts"],"names":[],"mappings":";;;;;AAUO,IAAM,QAAA,GAA4B;AAAA,EACvC,eAAA,EAAiB,OAAA;AAAA,EACjB,EAAA,EAAI,cAAA;AAAA,EACJ,IAAA,EAAM,iCAAA;AAAA,EACN,OAAA,EAAS,OAAA;AAAA,EACT,WAAA,EACE,+FAAA;AAAA,EACF,MAAA,EAAQ,cAAA;AAAA,EACR,OAAA,EAAS,UAAA;AAAA,EACT,IAAA,EAAM,WAAA;AAAA,EACN,UAAA,EAAY,iBAAA;AAAA,EACZ,OAAA,EAAS;AAAA,IACP,OAAA,EAAS,QAAA;AAAA,IACT,IAAA,EAAM,OAAA;AAAA,IACN,MAAA,EAAQ,OAAA;AAAA,IACR,QAAA,EAAU;AAAA,GACZ;AAAA,EACA,QAAA,EAAU,CAAC,WAAA,EAAa,SAAS,CAAA;AAAA,EACjC,QAAA,EAAU;AAAA,IACR,UAAU,CAAC,EAAE,IAAI,kBAAA,EAAoB,KAAA,EAAO,oBAAoB;AAAA,GAClE;AAAA,EACA,YAAA,EAAc;AAAA,IACZ,KAAA,EAAO,IAAA;AAAA,IACP,MAAA,EAAQ,IAAA;AAAA,IACR,MAAA,EAAQ;AAAA,MACN,eAAA,EAAiB;AAAA;AACnB,GACF;AAAA,EACA,YAAA,EAAc;AAAA,IACZ,UAAA,EAAY;AAAA,MACV,IAAA,EAAM,QAAA;AAAA,MACN,OAAA,EAAS,MAAA;AAAA,MACT,WAAA,EAAa;AAAA,KACf;AAAA,IACA,SAAA,EAAW;AAAA,MACT,IAAA,EAAM,QAAA;AAAA,MACN,OAAA,EAAS,GAAA;AAAA,MACT,WAAA,EAAa;AAAA,KACf;AAAA,IACA,aAAA,EAAe;AAAA,MACb,IAAA,EAAM,QAAA;AAAA,MACN,OAAA,EAAS,GAAA;AAAA,MACT,WAAA,EAAa;AAAA;AACf;AAEJ;;;ACNA,IAAM,WAAA,GAAwC;AAAA,EAC5C,KAAA,EAAO,CAAA;AAAA,EACP,KAAA,EAAO,CAAA;AAAA,EACP,IAAA,EAAM,CAAA;AAAA,EACN,IAAA,EAAM,CAAA;AAAA,EACN,KAAA,EAAO,CAAA;AAAA,EACP,KAAA,EAAO;AACT,CAAA;AAEA,IAAM,kBAAA,GAAqB,CAAC,GAAA,KAA8B;AACxD,EAAA,MAAM,SAAA,GAAY,YAAY,GAAG,CAAA;AACjC,EAAA,OAAQ,MAAA,CAAO,IAAA,CAAK,WAAW,CAAA,CAAiB,MAAA;AAAA,IAC9C,CAAC,CAAA,KAAM,WAAA,CAAY,CAAC,CAAA,IAAK;AAAA,GAC3B;AACF,CAAA;AAEA,IAAM,iBAAA,GAUF;AAAA,EACF,WAAA,EAAa,EAAA,GAAK,EAAA,GAAK,EAAA,GAAK,EAAA,GAAK,GAAA;AAAA,EACjC,WAAA,EAAa,EAAA,GAAK,EAAA,GAAK,EAAA,GAAK,EAAA,GAAK,GAAA;AAAA,EACjC,UAAA,EAAY,CAAA,GAAI,EAAA,GAAK,EAAA,GAAK,EAAA,GAAK,GAAA;AAAA,EAC/B,WAAA,EAAa,KAAK,EAAA,GAAK,GAAA;AAAA,EACvB,UAAA,EAAY,KAAK,EAAA,GAAK,GAAA;AAAA,EACtB,iBAAA,EAAmB,IAAI,EAAA,GAAK;AAAA;AAC9B,CAAA;AAEO,IAAM,yBAAN,MAAwD;AAAA,EAC5C,IAAA;AAAA,EACA,UAAA;AAAA,EACA,SAAA;AAAA,EACA,eAAA;AAAA,EACA,SAAA;AAAA,EAYT,SAAsB,EAAC;AAAA,EACvB,UAAA,GAAoC,IAAA;AAAA,EACpC,cAAA,GAAwC,IAAA;AAAA,EACxC,MAAA,GAAS,KAAA;AAAA,EACT,QAAA,GAAiC,IAAA;AAAA,EACjC,WAAA;AAAA,EAER,YAAY,MAAA,EAA8B;AACxC,IAAA,IAAA,CAAK,OAAO,MAAA,CAAO,gBAAA;AACnB,IAAA,IAAA,CAAK,UAAA,GAAa,OAAO,UAAA,IAAc,MAAA;AACvC,IAAA,IAAA,CAAK,SAAA,GAAY,OAAO,SAAA,IAAa,GAAA;AACrC,IAAA,IAAA,CAAK,eAAA,GAAkB,OAAO,aAAA,IAAiB,GAAA;AAC/C,IAAA,IAAA,CAAK,SAAA,GAAY,EAAE,GAAG,iBAAA,EAAmB,GAAI,MAAA,CAAO,SAAA,IAAa,EAAC,EAAG;AAErE,IAAA,IAAA,CAAK,WAAA,GAAc,IAAA,CAAK,IAAA,CAAK,gBAAA,CAAiB,KAAK,UAAA,EAAY;AAAA,MAC7D,OAAA,EAAS;AAAA,QACP,EAAE,IAAA,EAAM,OAAA,EAAS,MAAA,EAAQ,IAAA,EAAK;AAAA,QAC9B,EAAE,MAAM,WAAA,EAAY;AAAA,QACpB,EAAE,MAAM,OAAA,EAAQ;AAAA,QAChB,EAAE,MAAM,QAAA,EAAS;AAAA,QACjB,GAAG,kBAAA,CAAmB,GAAA,CAAI,CAAC,KAAA,MAAW,EAAE,IAAA,EAAM,CAAA,OAAA,EAAU,KAAK,CAAA,CAAA,EAAG,CAAE;AAAA;AACpE,KACD,CAAA;AAED,IAAA,IAAA,CAAK,UAAA,GAAa,YAAY,MAAM;AAClC,MAAA,IAAA,CAAK,aAAA,EAAc;AAAA,IACrB,CAAA,EAAG,IAAA,CAAK,eAAe,CAAA,CAAE,KAAA,EAAM;AAC/B,IAAA,IAAA,CAAK,cAAA,GAAiB,YAAY,MAAM;AACtC,MAAA,KAAK,KAAK,YAAA,EAAa;AAAA,IACzB,CAAA,EAAG,IAAA,CAAK,SAAA,CAAU,iBAAiB,EAAE,KAAA,EAAM;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,MAAM,MAAA,EAAkC;AAC5C,IAAA,IAAI,KAAK,MAAA,EAAQ;AACf,MAAA;AAAA,IACF;AACA,IAAA,IAAA,CAAK,MAAA,CAAO,KAAK,MAAM,CAAA;AACvB,IAAA,IAAI,IAAA,CAAK,MAAA,CAAO,MAAA,IAAU,IAAA,CAAK,SAAA,EAAW;AACxC,MAAA,IAAA,CAAK,aAAA,EAAc;AAAA,IACrB;AAAA,EACF;AAAA,EAEA,MAAM,WAAW,OAAA,EAAqC;AACpD,IAAA,IAAI,KAAK,MAAA,EAAQ;AACf,MAAA;AAAA,IACF;AACA,IAAA,IAAI,OAAA,CAAQ,WAAW,CAAA,EAAG;AACxB,MAAA;AAAA,IACF;AACA,IAAA,IAAA,CAAK,MAAA,CAAO,IAAA,CAAK,GAAG,OAAO,CAAA;AAC3B,IAAA,IAAI,IAAA,CAAK,MAAA,CAAO,MAAA,IAAU,IAAA,CAAK,SAAA,EAAW;AACxC,MAAA,IAAA,CAAK,aAAA,EAAc;AAAA,IACrB;AAAA,EACF;AAAA,EAEA,MAAc,KAAA,GAAuB;AACnC,IAAA,IAAI,KAAK,QAAA,EAAU;AACjB,MAAA,MAAM,IAAA,CAAK,QAAA;AACX,MAAA;AAAA,IACF;AACA,IAAA,IAAI,IAAA,CAAK,MAAA,CAAO,MAAA,KAAW,CAAA,EAAG;AAC5B,MAAA;AAAA,IACF;AACA,IAAA,MAAM,QAAQ,IAAA,CAAK,MAAA,CAAO,OAAO,CAAA,EAAG,IAAA,CAAK,OAAO,MAAM,CAAA;AAEtD,IAAA,IAAA,CAAK,YAAY,YAAY;AAC3B,MAAA,IAAI;AACF,QAAA,MAAM,IAAA,CAAK,WAAA;AACX,QAAA,MAAM,KAAK,IAAA,CAAK,UAAA;AAAA,UACd,IAAA,CAAK,UAAA;AAAA,UACL,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,YAChB,OAAO,CAAA,CAAE,EAAA;AAAA,YACT,WAAW,CAAA,CAAE,SAAA;AAAA,YACb,OAAO,CAAA,CAAE,KAAA;AAAA,YACT,SAAS,CAAA,CAAE,OAAA;AAAA,YACX,QAAQ,CAAA,CAAE,MAAA;AAAA,YACV,QAAQ,CAAA,CAAE;AAAA,WACZ,CAAE;AAAA,SACJ;AAAA,MACF,SAAS,GAAA,EAAK;AAEZ,QAAA,IAAA,CAAK,MAAA,CAAO,OAAA,CAAQ,GAAG,KAAK,CAAA;AAC5B,QAAA,MAAM,GAAA;AAAA,MACR,CAAA,SAAE;AACA,QAAA,IAAA,CAAK,QAAA,GAAW,IAAA;AAAA,MAClB;AAAA,IACF,CAAA,GAAG;AAEH,IAAA,MAAM,IAAA,CAAK,QAAA;AAAA,EACb;AAAA,EAEQ,aAAA,GAAsB;AAC5B,IAAA,KAAK,IAAA,CAAK,KAAA,EAAM,CAAE,KAAA,CAAM,MAAM;AAAA,IAG9B,CAAC,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,KAAA,CACJ,KAAA,EACA,OAAA,EAMiE;AACjE,IAAA,MAAM,IAAA,CAAK,WAAA;AACX,IAAA,MAAM,MAAA,GAAS,YAAY,KAAK,CAAA;AAChC,IAAA,MAAM,KAAA,GAAQ,SAAS,KAAA,IAAS,GAAA;AAChC,IAAA,MAAM,MAAA,GAAS,SAAS,MAAA,IAAU,CAAA;AAClC,IAAA,MAAM,SAAA,GAAY,SAAS,MAAA,IAAU,WAAA;AACrC,IAAA,MAAM,OAAA,GAAU,OAAA,EAAS,SAAA,KAAc,KAAA,GAAQ,CAAA,GAAI,EAAA;AAEnD,IAAA,MAAM,CAAC,KAAA,EAAO,IAAI,CAAA,GAAI,MAAM,QAAQ,GAAA,CAAI;AAAA,MACtC,IAAA,CAAK,IAAA,CAAK,KAAA,CAAc,IAAA,CAAK,YAAY,MAAM,CAAA;AAAA,MAC/C,IAAA,CAAK,IAAA,CAAK,IAAA,CAAa,IAAA,CAAK,YAAY,MAAA,EAAQ;AAAA,QAC9C,IAAA,EAAM,EAAE,CAAC,SAAS,GAAG,OAAA,EAAQ;AAAA,QAC7B,KAAA;AAAA,QACA,IAAA,EAAM;AAAA,OACP;AAAA,KACF,CAAA;AAED,IAAA,OAAO;AAAA,MACL,IAAA,EAAM,IAAA,CAAK,GAAA,CAAI,WAAW,CAAA;AAAA,MAC1B,KAAA;AAAA,MACA,OAAA,EAAS,MAAA,GAAS,IAAA,CAAK,MAAA,GAAS;AAAA,KAClC;AAAA,EACF;AAAA,EAEA,MAAM,QAAQ,EAAA,EAAuC;AACnD,IAAA,MAAM,IAAA,CAAK,WAAA;AACX,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,IAAA,CAAK,IAAA;AAAA,MAC3B,IAAA,CAAK,UAAA;AAAA,MACL,EAAE,KAAA,EAAO,EAAE,GAAA,EAAK,IAAG,EAAE;AAAA,MACrB,EAAE,OAAO,CAAA;AAAE,KACb;AACA,IAAA,MAAM,KAAA,GAAQ,KAAK,CAAC,CAAA;AACpB,IAAA,OAAO,KAAA,GAAQ,WAAA,CAAY,KAAK,CAAA,GAAI,IAAA;AAAA,EACtC;AAAA,EAEA,MAAM,MAAA,CACJ,UAAA,EACA,OAAA,EACiE;AACjE,IAAA,MAAM,IAAA,CAAK,WAAA;AACX,IAAA,MAAM,UAAA,GAAqC;AAAA,MACzC,OAAA,EAAS,EAAE,SAAA,EAAW,UAAA;AAAW,KACnC;AACA,IAAA,MAAM,gBAAA,GAAmB,WAAA,CAAY,OAAA,EAAS,OAAA,IAAW,EAAE,CAAA;AAC3D,IAAA,MAAM,MAAA,GACJ,MAAA,CAAO,IAAA,CAAK,gBAAgB,CAAA,CAAE,MAAA,KAAW,CAAA,GACrC,UAAA,GACA,EAAE,IAAA,EAAM,CAAC,gBAAA,EAAkB,UAAU,CAAA,EAAE;AAC7C,IAAA,MAAM,KAAA,GAAQ,SAAS,KAAA,IAAS,GAAA;AAChC,IAAA,MAAM,MAAA,GAAS,SAAS,MAAA,IAAU,CAAA;AAElC,IAAA,MAAM,CAAC,KAAA,EAAO,IAAI,CAAA,GAAI,MAAM,QAAQ,GAAA,CAAI;AAAA,MACtC,IAAA,CAAK,IAAA,CAAK,KAAA,CAAc,IAAA,CAAK,YAAY,MAAM,CAAA;AAAA,MAC/C,IAAA,CAAK,IAAA,CAAK,IAAA,CAAa,IAAA,CAAK,YAAY,MAAA,EAAQ;AAAA,QAC9C,IAAA,EAAM,EAAE,SAAA,EAAW,EAAA,EAAG;AAAA,QACtB,KAAA;AAAA,QACA,IAAA,EAAM;AAAA,OACP;AAAA,KACF,CAAA;AAED,IAAA,OAAO;AAAA,MACL,IAAA,EAAM,IAAA,CAAK,GAAA,CAAI,WAAW,CAAA;AAAA,MAC1B,KAAA;AAAA,MACA,OAAA,EAAS,MAAA,GAAS,IAAA,CAAK,MAAA,GAAS;AAAA,KAClC;AAAA,EACF;AAAA,EAEA,MAAM,gBAAgB,eAAA,EAA0C;AAC9D,IAAA,MAAM,IAAA,CAAK,WAAA;AACX,IAAA,OAAO,IAAA,CAAK,IAAA,CAAK,UAAA,CAAmB,IAAA,CAAK,UAAA,EAAY;AAAA,MACnD,SAAA,EAAW,EAAE,GAAA,EAAK,eAAA;AAAgB,KACnC,CAAA;AAAA,EACH;AAAA,EAEA,MAAM,sBAAA,CACJ,MAAA,EACA,eAAA,EACiB;AACjB,IAAA,MAAM,IAAA,CAAK,WAAA;AACX,IAAA,OAAO,IAAA,CAAK,IAAA,CAAK,UAAA,CAAmB,IAAA,CAAK,UAAA,EAAY;AAAA,MACnD,IAAA,EAAM;AAAA,QACJ,EAAE,KAAA,EAAO,EAAE,GAAA,EAAK,QAAqB,EAAE;AAAA,QACvC,EAAE,SAAA,EAAW,EAAE,GAAA,EAAK,iBAAgB;AAAE;AACxC,KACD,CAAA;AAAA,EACH;AAAA,EAEA,MAAM,QAAA,GAKH;AACD,IAAA,MAAM,IAAA,CAAK,WAAA;AACX,IAAA,MAAM,CAAC,SAAA,EAAW,MAAA,EAAQ,MAAM,CAAA,GAAI,MAAM,QAAQ,GAAA,CAAI;AAAA,MACpD,KAAK,IAAA,CAAK,KAAA,CAAc,IAAA,CAAK,UAAA,EAAY,EAAE,CAAA;AAAA,MAC3C,KAAK,IAAA,CAAK,IAAA;AAAA,QACR,IAAA,CAAK,UAAA;AAAA,QACL,EAAC;AAAA,QACD,EAAE,IAAA,EAAM,EAAE,WAAW,CAAA,EAAE,EAAG,OAAO,CAAA;AAAE,OACrC;AAAA,MACA,KAAK,IAAA,CAAK,IAAA;AAAA,QACR,IAAA,CAAK,UAAA;AAAA,QACL,EAAC;AAAA,QACD,EAAE,IAAA,EAAM,EAAE,WAAW,EAAA,EAAG,EAAG,OAAO,CAAA;AAAE;AACtC,KACD,CAAA;AAKD,IAAA,OAAO;AAAA,MACL,SAAA;AAAA,MACA,eAAA,EAAiB,MAAA,CAAO,CAAC,CAAA,EAAG,SAAA,IAAa,CAAA;AAAA,MACzC,eAAA,EAAiB,MAAA,CAAO,CAAC,CAAA,EAAG,SAAA,IAAa,CAAA;AAAA,MACzC,SAAA,EAAW;AAAA,KACb;AAAA,EACF;AAAA,EAEA,MAAM,KAAA,GAAuB;AAC3B,IAAA,IAAI,KAAK,MAAA,EAAQ;AACf,MAAA;AAAA,IACF;AACA,IAAA,IAAA,CAAK,MAAA,GAAS,IAAA;AACd,IAAA,IAAI,KAAK,UAAA,EAAY;AACnB,MAAA,aAAA,CAAc,KAAK,UAAU,CAAA;AAC7B,MAAA,IAAA,CAAK,UAAA,GAAa,IAAA;AAAA,IACpB;AACA,IAAA,IAAI,KAAK,cAAA,EAAgB;AACvB,MAAA,aAAA,CAAc,KAAK,cAAc,CAAA;AACjC,MAAA,IAAA,CAAK,cAAA,GAAiB,IAAA;AAAA,IACxB;AACA,IAAA,IAAI;AACF,MAAA,MAAM,KAAK,KAAA,EAAM;AAAA,IACnB,CAAA,CAAA,MAAQ;AAAA,IAER;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,YAAA,GAA8B;AAC1C,IAAA,IAAI,KAAK,MAAA,EAAQ;AACf,MAAA;AAAA,IACF;AACA,IAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,CAAK,OAAO,CAAC,OAAA,EAAS,OAAO,CAAA,EAAG,IAAA,CAAK,SAAA,CAAU,WAAA,EAAa,GAAG,CAAA;AACrE,MAAA,MAAM,IAAA,CAAK,OAAO,CAAC,MAAM,GAAG,IAAA,CAAK,SAAA,CAAU,YAAY,GAAG,CAAA;AAC1D,MAAA,MAAM,IAAA,CAAK,OAAO,CAAC,MAAM,GAAG,IAAA,CAAK,SAAA,CAAU,YAAY,GAAG,CAAA;AAC1D,MAAA,MAAM,IAAA,CAAK,OAAO,CAAC,OAAO,GAAG,IAAA,CAAK,SAAA,CAAU,aAAa,GAAG,CAAA;AAC5D,MAAA,MAAM,IAAA,CAAK,OAAO,CAAC,OAAO,GAAG,IAAA,CAAK,SAAA,CAAU,aAAa,GAAG,CAAA;AAAA,IAC9D,CAAA,CAAA,MAAQ;AAAA,IAER;AAAA,EACF;AAAA,EAEA,MAAc,MAAA,CACZ,MAAA,EACA,MAAA,EACA,GAAA,EACe;AACf,IAAA,MAAM,IAAA,CAAK,sBAAA;AAAA,MACT,MAAA;AAAA,MACA,MAAA,GAAS,CAAA,GAAI,GAAA,GAAM,MAAA,GAAS,GAAA,GAAM;AAAA,KACpC;AAAA,EACF;AACF;AAEA,IAAM,WAAA,GAAc,CAAC,KAAA,KAA4C;AAC/D,EAAA,MAAM,UAAyC,EAAC;AAChD,EAAA,IAAI,KAAA,CAAM,UAAU,MAAA,EAAW;AAC7B,IAAA,OAAA,CAAQ,IAAA,CAAK,EAAE,KAAA,EAAO,EAAE,GAAA,EAAK,mBAAmB,KAAA,CAAM,KAAK,CAAA,EAAE,EAAG,CAAA;AAAA,EAClE;AACA,EAAA,IAAI,KAAA,CAAM,WAAW,MAAA,EAAW;AAC9B,IAAA,OAAA,CAAQ,IAAA,CAAK,EAAE,MAAA,EAAQ,EAAE,KAAK,KAAA,CAAM,MAAA,IAAU,CAAA;AAAA,EAChD;AACA,EAAA,IAAI,KAAA,CAAM,SAAS,MAAA,EAAW;AAC5B,IAAA,OAAA,CAAQ,IAAA,CAAK,EAAE,SAAA,EAAW,EAAE,MAAM,KAAA,CAAM,IAAA,IAAQ,CAAA;AAAA,EAClD;AACA,EAAA,IAAI,KAAA,CAAM,OAAO,MAAA,EAAW;AAC1B,IAAA,OAAA,CAAQ,IAAA,CAAK,EAAE,SAAA,EAAW,EAAE,MAAM,KAAA,CAAM,EAAA,IAAM,CAAA;AAAA,EAChD;AACA,EAAA,KAAA,MAAW,SAAS,kBAAA,EAAoB;AACtC,IAAA,MAAM,KAAA,GAAQ,MAAM,KAAK,CAAA;AACzB,IAAA,IAAI,UAAU,MAAA,EAAW;AACvB,MAAA,OAAA,CAAQ,IAAA,CAAK,EAAE,CAAC,CAAA,OAAA,EAAU,KAAK,CAAA,CAAE,GAAG,EAAE,GAAA,EAAK,KAAA,EAAM,EAAG,CAAA;AAAA,IACtD;AAAA,EACF;AACA,EAAA,IAAI,OAAA,CAAQ,WAAW,CAAA,EAAG;AACxB,IAAA,OAAO,EAAC;AAAA,EACV;AACA,EAAA,IAAI,OAAA,CAAQ,WAAW,CAAA,EAAG;AACxB,IAAA,OAAO,QAAQ,CAAC,CAAA;AAAA,EAClB;AACA,EAAA,OAAO,EAAE,MAAM,OAAA,EAAQ;AACzB,CAAA;AAEA,IAAM,WAAA,GAAc,CAAC,GAAA,MAA4B;AAAA,EAC/C,IAAI,GAAA,CAAI,KAAA;AAAA,EACR,WAAW,GAAA,CAAI,SAAA;AAAA,EACf,OAAO,GAAA,CAAI,KAAA;AAAA,EACX,SAAS,GAAA,CAAI,OAAA;AAAA,EACb,QAAQ,GAAA,CAAI,MAAA;AAAA,EACZ,QAAQ,GAAA,CAAI;AACd,CAAA,CAAA;AAEO,SAAS,aAAA,CACd,QACA,IAAA,EACwB;AAIxB,EAAA,MAAM,QAAA,GAAiC,IAAA,GAAO,kBAAkB,CAAA,GAC5D;AAAA,IACE,GAAG,MAAA;AAAA,IACH,gBAAA,EAAkB,KAAK,kBAAkB;AAAA,GAC3C,GACA,MAAA;AACJ,EAAA,OAAO,IAAI,uBAAuB,QAAQ,CAAA;AAC5C;AAEA,IAAO,aAAA,GAAQ","file":"index.js","sourcesContent":["/**\n * @module @kb-labs/adapters-log-document/manifest\n *\n * Manifest for the Document-backed log persistence adapter. It depends on\n * the platform's `documentDatabase` service — register a concrete document\n * driver (sqlite, postgres, mongo) first and this adapter rides on top.\n */\n\nimport type { AdapterManifest } from \"@kb-labs/sdk/adapters\";\n\nexport const manifest: AdapterManifest = {\n manifestVersion: \"1.0.0\",\n id: \"log-document\",\n name: \"Document-backed Log Persistence\",\n version: \"1.0.0\",\n description:\n \"ILogPersistence implementation storing log entries in any IDocumentDatabase. Driver-agnostic.\",\n author: \"KB Labs Team\",\n license: \"KBPL-1.1\",\n type: \"extension\",\n implements: \"ILogPersistence\",\n extends: {\n adapter: \"logger\",\n hook: \"onLog\",\n method: \"write\",\n priority: 0,\n },\n contexts: [\"workspace\", \"process\"],\n requires: {\n adapters: [{ id: \"documentDatabase\", alias: \"documentDatabase\" }],\n },\n capabilities: {\n batch: true,\n search: true,\n custom: {\n retentionPolicy: true,\n },\n },\n configSchema: {\n collection: {\n type: \"string\",\n default: \"logs\",\n description: \"Name of the document collection that stores log entries.\",\n },\n batchSize: {\n type: \"number\",\n default: 100,\n description: \"Batch size for buffered writes.\",\n },\n flushInterval: {\n type: \"number\",\n default: 5000,\n description: \"Maximum delay before a partial batch is flushed (ms).\",\n },\n },\n};\n","/**\n * @module @kb-labs/adapters-log-document\n *\n * `ILogPersistence` implementation backed by any `IDocumentDatabase`.\n *\n * This is the dogfooded replacement for the old sqlite-only log persistence\n * adapter: log entries are now stored as documents in a `logs` collection\n * using the same abstraction every other plugin uses. The platform stays\n * driver-agnostic — switch from sqlite to postgres-JSONB and logs follow.\n *\n * Buffering: writes are queued in memory and flushed in batches to amortise\n * per-call overhead. `close()` (and the next flush after batchSize entries)\n * drains the queue.\n *\n * Retention: a periodic timer deletes documents older than the configured\n * thresholds per log level. Without retention the collection grows\n * unbounded — defaults are applied if `retention` is absent.\n *\n * Search: implemented via `$contains` on the message field. Full-text\n * indexing (FTS5, MongoDB text) is intentionally OUT of scope here — that's\n * a backend-specific capability and would leak through the contract. If\n * advanced search is needed, route it via an external index (Meilisearch\n * etc.) and keep this layer simple.\n */\n\nimport { LOG_CONTEXT_FIELDS } from \"@kb-labs/sdk/adapters\";\nimport type {\n ILogPersistence,\n LogPersistenceConfig,\n LogRetentionPolicy,\n LogRecord,\n LogQuery,\n LogLevel,\n IDocumentDatabase,\n DocumentFilter,\n BaseDocument,\n} from \"@kb-labs/sdk/adapters\";\n\nexport { manifest } from \"./manifest.js\";\n\ninterface LogDoc extends BaseDocument {\n logId: string;\n timestamp: number;\n level: LogLevel;\n message: string;\n fields: Record<string, unknown>;\n source: string;\n}\n\nconst LEVEL_ORDER: Record<LogLevel, number> = {\n trace: 0,\n debug: 1,\n info: 2,\n warn: 3,\n error: 4,\n fatal: 5,\n};\n\nconst LEVELS_AT_OR_ABOVE = (min: LogLevel): LogLevel[] => {\n const threshold = LEVEL_ORDER[min];\n return (Object.keys(LEVEL_ORDER) as LogLevel[]).filter(\n (l) => LEVEL_ORDER[l] >= threshold,\n );\n};\n\nconst DEFAULT_RETENTION: Required<\n Pick<\n LogRetentionPolicy,\n | \"maxAgeFatal\"\n | \"maxAgeError\"\n | \"maxAgeWarn\"\n | \"maxAgeDebug\"\n | \"maxAgeInfo\"\n | \"cleanupIntervalMs\"\n >\n> = {\n maxAgeFatal: 30 * 24 * 60 * 60 * 1000,\n maxAgeError: 14 * 24 * 60 * 60 * 1000,\n maxAgeWarn: 7 * 24 * 60 * 60 * 1000,\n maxAgeDebug: 30 * 60 * 1000,\n maxAgeInfo: 30 * 60 * 1000,\n cleanupIntervalMs: 5 * 60 * 1000, // 5 minutes\n};\n\nexport class DocumentLogPersistence implements ILogPersistence {\n private readonly docs: IDocumentDatabase;\n private readonly collection: string;\n private readonly batchSize: number;\n private readonly flushIntervalMs: number;\n private readonly retention: Required<\n Pick<\n LogRetentionPolicy,\n | \"maxAgeFatal\"\n | \"maxAgeError\"\n | \"maxAgeWarn\"\n | \"maxAgeDebug\"\n | \"maxAgeInfo\"\n | \"cleanupIntervalMs\"\n >\n >;\n\n private buffer: LogRecord[] = [];\n private flushTimer: NodeJS.Timeout | null = null;\n private retentionTimer: NodeJS.Timeout | null = null;\n private closed = false;\n private flushing: Promise<void> | null = null;\n private initialised: Promise<void>;\n\n constructor(config: LogPersistenceConfig) {\n this.docs = config.documentDatabase;\n this.collection = config.collection ?? \"logs\";\n this.batchSize = config.batchSize ?? 100;\n this.flushIntervalMs = config.flushInterval ?? 5_000;\n this.retention = { ...DEFAULT_RETENTION, ...(config.retention ?? {}) };\n\n this.initialised = this.docs.ensureCollection(this.collection, {\n indexes: [\n { path: \"logId\", unique: true },\n { path: \"timestamp\" },\n { path: \"level\" },\n { path: \"source\" },\n ...LOG_CONTEXT_FIELDS.map((field) => ({ path: `fields.${field}` })),\n ],\n });\n\n this.flushTimer = setInterval(() => {\n this.scheduleFlush();\n }, this.flushIntervalMs).unref();\n this.retentionTimer = setInterval(() => {\n void this.runRetention();\n }, this.retention.cleanupIntervalMs).unref();\n }\n\n // ──────────────────────────────────────────────────────────────────────────\n // Write path (buffered)\n // ──────────────────────────────────────────────────────────────────────────\n\n async write(record: LogRecord): Promise<void> {\n if (this.closed) {\n return;\n }\n this.buffer.push(record);\n if (this.buffer.length >= this.batchSize) {\n this.scheduleFlush();\n }\n }\n\n async writeBatch(records: LogRecord[]): Promise<void> {\n if (this.closed) {\n return;\n }\n if (records.length === 0) {\n return;\n }\n this.buffer.push(...records);\n if (this.buffer.length >= this.batchSize) {\n this.scheduleFlush();\n }\n }\n\n private async flush(): Promise<void> {\n if (this.flushing) {\n await this.flushing;\n return;\n }\n if (this.buffer.length === 0) {\n return;\n }\n const batch = this.buffer.splice(0, this.buffer.length);\n\n this.flushing = (async () => {\n try {\n await this.initialised;\n await this.docs.insertMany<LogDoc>(\n this.collection,\n batch.map((r) => ({\n logId: r.id,\n timestamp: r.timestamp,\n level: r.level,\n message: r.message,\n fields: r.fields,\n source: r.source,\n })),\n );\n } catch (err) {\n // Re-queue on failure so the next attempt picks up the lost batch.\n this.buffer.unshift(...batch);\n throw err;\n } finally {\n this.flushing = null;\n }\n })();\n\n await this.flushing;\n }\n\n private scheduleFlush(): void {\n void this.flush().catch(() => {\n // The batch was re-queued by flush(). A subsequent interval or write\n // retries it; logging itself must not create an unhandled rejection.\n });\n }\n\n // ──────────────────────────────────────────────────────────────────────────\n // Read path\n // ──────────────────────────────────────────────────────────────────────────\n\n async query(\n query: LogQuery,\n options?: {\n limit?: number;\n offset?: number;\n sortBy?: \"timestamp\" | \"level\";\n sortOrder?: \"asc\" | \"desc\";\n },\n ): Promise<{ logs: LogRecord[]; total: number; hasMore: boolean }> {\n await this.initialised;\n const filter = buildFilter(query);\n const limit = options?.limit ?? 100;\n const offset = options?.offset ?? 0;\n const sortField = options?.sortBy ?? \"timestamp\";\n const sortDir = options?.sortOrder === \"asc\" ? 1 : -1;\n\n const [total, docs] = await Promise.all([\n this.docs.count<LogDoc>(this.collection, filter),\n this.docs.find<LogDoc>(this.collection, filter, {\n sort: { [sortField]: sortDir },\n limit,\n skip: offset,\n }),\n ]);\n\n return {\n logs: docs.map(toLogRecord),\n total,\n hasMore: offset + docs.length < total,\n };\n }\n\n async getById(id: string): Promise<LogRecord | null> {\n await this.initialised;\n const docs = await this.docs.find<LogDoc>(\n this.collection,\n { logId: { $eq: id } },\n { limit: 1 },\n );\n const first = docs[0];\n return first ? toLogRecord(first) : null;\n }\n\n async search(\n searchText: string,\n options?: { limit?: number; offset?: number; filters?: LogQuery },\n ): Promise<{ logs: LogRecord[]; total: number; hasMore: boolean }> {\n await this.initialised;\n const textFilter: DocumentFilter<LogDoc> = {\n message: { $contains: searchText },\n };\n const structuredFilter = buildFilter(options?.filters ?? {});\n const filter: DocumentFilter<LogDoc> =\n Object.keys(structuredFilter).length === 0\n ? textFilter\n : { $and: [structuredFilter, textFilter] };\n const limit = options?.limit ?? 100;\n const offset = options?.offset ?? 0;\n\n const [total, docs] = await Promise.all([\n this.docs.count<LogDoc>(this.collection, filter),\n this.docs.find<LogDoc>(this.collection, filter, {\n sort: { timestamp: -1 },\n limit,\n skip: offset,\n }),\n ]);\n\n return {\n logs: docs.map(toLogRecord),\n total,\n hasMore: offset + docs.length < total,\n };\n }\n\n async deleteOlderThan(beforeTimestamp: number): Promise<number> {\n await this.initialised;\n return this.docs.deleteMany<LogDoc>(this.collection, {\n timestamp: { $lt: beforeTimestamp },\n });\n }\n\n async deleteByLevelOlderThan(\n levels: string[],\n beforeTimestamp: number,\n ): Promise<number> {\n await this.initialised;\n return this.docs.deleteMany<LogDoc>(this.collection, {\n $and: [\n { level: { $in: levels as LogLevel[] } },\n { timestamp: { $lt: beforeTimestamp } },\n ],\n });\n }\n\n async getStats(): Promise<{\n totalLogs: number;\n oldestTimestamp: number;\n newestTimestamp: number;\n sizeBytes: number;\n }> {\n await this.initialised;\n const [totalLogs, oldest, newest] = await Promise.all([\n this.docs.count<LogDoc>(this.collection, {}),\n this.docs.find<LogDoc>(\n this.collection,\n {},\n { sort: { timestamp: 1 }, limit: 1 },\n ),\n this.docs.find<LogDoc>(\n this.collection,\n {},\n { sort: { timestamp: -1 }, limit: 1 },\n ),\n ]);\n // Size is not exposed by IDocumentDatabase by design (it varies wildly\n // by backend). Returning 0 here is honest — callers driving retention\n // by size should configure maxAge instead and stop pretending bytes are\n // a universal currency across drivers.\n return {\n totalLogs,\n oldestTimestamp: oldest[0]?.timestamp ?? 0,\n newestTimestamp: newest[0]?.timestamp ?? 0,\n sizeBytes: 0,\n };\n }\n\n async close(): Promise<void> {\n if (this.closed) {\n return;\n }\n this.closed = true;\n if (this.flushTimer) {\n clearInterval(this.flushTimer);\n this.flushTimer = null;\n }\n if (this.retentionTimer) {\n clearInterval(this.retentionTimer);\n this.retentionTimer = null;\n }\n try {\n await this.flush();\n } catch {\n /* swallow — we tried */\n }\n }\n\n // ──────────────────────────────────────────────────────────────────────────\n // Retention\n // ──────────────────────────────────────────────────────────────────────────\n\n private async runRetention(): Promise<void> {\n if (this.closed) {\n return;\n }\n const now = Date.now();\n try {\n await this.expire([\"trace\", \"debug\"], this.retention.maxAgeDebug, now);\n await this.expire([\"info\"], this.retention.maxAgeInfo, now);\n await this.expire([\"warn\"], this.retention.maxAgeWarn, now);\n await this.expire([\"error\"], this.retention.maxAgeError, now);\n await this.expire([\"fatal\"], this.retention.maxAgeFatal, now);\n } catch {\n /* retention failures should not propagate — they're best-effort cleanup */\n }\n }\n\n private async expire(\n levels: LogLevel[],\n maxAge: number,\n now: number,\n ): Promise<void> {\n await this.deleteByLevelOlderThan(\n levels,\n maxAge > 0 ? now - maxAge : now + 1,\n );\n }\n}\n\nconst buildFilter = (query: LogQuery): DocumentFilter<LogDoc> => {\n const clauses: Array<DocumentFilter<LogDoc>> = [];\n if (query.level !== undefined) {\n clauses.push({ level: { $in: LEVELS_AT_OR_ABOVE(query.level) } });\n }\n if (query.source !== undefined) {\n clauses.push({ source: { $eq: query.source } });\n }\n if (query.from !== undefined) {\n clauses.push({ timestamp: { $gte: query.from } });\n }\n if (query.to !== undefined) {\n clauses.push({ timestamp: { $lte: query.to } });\n }\n for (const field of LOG_CONTEXT_FIELDS) {\n const value = query[field];\n if (value !== undefined) {\n clauses.push({ [`fields.${field}`]: { $eq: value } });\n }\n }\n if (clauses.length === 0) {\n return {};\n }\n if (clauses.length === 1) {\n return clauses[0]!;\n }\n return { $and: clauses };\n};\n\nconst toLogRecord = (doc: LogDoc): LogRecord => ({\n id: doc.logId,\n timestamp: doc.timestamp,\n level: doc.level,\n message: doc.message,\n fields: doc.fields,\n source: doc.source,\n});\n\nexport function createAdapter(\n config: LogPersistenceConfig,\n deps?: Record<string, unknown>,\n): DocumentLogPersistence {\n // deps.documentDatabase is injected by the adapter-loader when the manifest\n // declares requires.adapters = [{ id: \"documentDatabase\" }]. Merge it in so\n // callers don't need to duplicate the reference in adapterOptions config.\n const resolved: LogPersistenceConfig = deps?.[\"documentDatabase\"]\n ? {\n ...config,\n documentDatabase: deps[\"documentDatabase\"] as IDocumentDatabase,\n }\n : config;\n return new DocumentLogPersistence(resolved);\n}\n\nexport default createAdapter;\n"]}
|
package/dist/manifest.js
CHANGED
|
@@ -7,10 +7,18 @@ var manifest = {
|
|
|
7
7
|
description: "ILogPersistence implementation storing log entries in any IDocumentDatabase. Driver-agnostic.",
|
|
8
8
|
author: "KB Labs Team",
|
|
9
9
|
license: "KBPL-1.1",
|
|
10
|
-
type: "
|
|
10
|
+
type: "extension",
|
|
11
11
|
implements: "ILogPersistence",
|
|
12
|
+
extends: {
|
|
13
|
+
adapter: "logger",
|
|
14
|
+
hook: "onLog",
|
|
15
|
+
method: "write",
|
|
16
|
+
priority: 0
|
|
17
|
+
},
|
|
12
18
|
contexts: ["workspace", "process"],
|
|
13
|
-
requires: {
|
|
19
|
+
requires: {
|
|
20
|
+
adapters: [{ id: "documentDatabase", alias: "documentDatabase" }]
|
|
21
|
+
},
|
|
14
22
|
capabilities: {
|
|
15
23
|
batch: true,
|
|
16
24
|
search: true,
|
package/dist/manifest.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/manifest.ts"],"names":[],"mappings":";AAUO,IAAM,QAAA,GAA4B;AAAA,EACvC,eAAA,EAAiB,OAAA;AAAA,EACjB,EAAA,EAAI,cAAA;AAAA,EACJ,IAAA,EAAM,iCAAA;AAAA,EACN,OAAA,EAAS,OAAA;AAAA,EACT,WAAA,EACE,+FAAA;AAAA,EACF,MAAA,EAAQ,cAAA;AAAA,EACR,OAAA,EAAS,UAAA;AAAA,EACT,IAAA,EAAM,
|
|
1
|
+
{"version":3,"sources":["../src/manifest.ts"],"names":[],"mappings":";AAUO,IAAM,QAAA,GAA4B;AAAA,EACvC,eAAA,EAAiB,OAAA;AAAA,EACjB,EAAA,EAAI,cAAA;AAAA,EACJ,IAAA,EAAM,iCAAA;AAAA,EACN,OAAA,EAAS,OAAA;AAAA,EACT,WAAA,EACE,+FAAA;AAAA,EACF,MAAA,EAAQ,cAAA;AAAA,EACR,OAAA,EAAS,UAAA;AAAA,EACT,IAAA,EAAM,WAAA;AAAA,EACN,UAAA,EAAY,iBAAA;AAAA,EACZ,OAAA,EAAS;AAAA,IACP,OAAA,EAAS,QAAA;AAAA,IACT,IAAA,EAAM,OAAA;AAAA,IACN,MAAA,EAAQ,OAAA;AAAA,IACR,QAAA,EAAU;AAAA,GACZ;AAAA,EACA,QAAA,EAAU,CAAC,WAAA,EAAa,SAAS,CAAA;AAAA,EACjC,QAAA,EAAU;AAAA,IACR,UAAU,CAAC,EAAE,IAAI,kBAAA,EAAoB,KAAA,EAAO,oBAAoB;AAAA,GAClE;AAAA,EACA,YAAA,EAAc;AAAA,IACZ,KAAA,EAAO,IAAA;AAAA,IACP,MAAA,EAAQ,IAAA;AAAA,IACR,MAAA,EAAQ;AAAA,MACN,eAAA,EAAiB;AAAA;AACnB,GACF;AAAA,EACA,YAAA,EAAc;AAAA,IACZ,UAAA,EAAY;AAAA,MACV,IAAA,EAAM,QAAA;AAAA,MACN,OAAA,EAAS,MAAA;AAAA,MACT,WAAA,EAAa;AAAA,KACf;AAAA,IACA,SAAA,EAAW;AAAA,MACT,IAAA,EAAM,QAAA;AAAA,MACN,OAAA,EAAS,GAAA;AAAA,MACT,WAAA,EAAa;AAAA,KACf;AAAA,IACA,aAAA,EAAe;AAAA,MACb,IAAA,EAAM,QAAA;AAAA,MACN,OAAA,EAAS,GAAA;AAAA,MACT,WAAA,EAAa;AAAA;AACf;AAEJ","file":"manifest.js","sourcesContent":["/**\n * @module @kb-labs/adapters-log-document/manifest\n *\n * Manifest for the Document-backed log persistence adapter. It depends on\n * the platform's `documentDatabase` service — register a concrete document\n * driver (sqlite, postgres, mongo) first and this adapter rides on top.\n */\n\nimport type { AdapterManifest } from \"@kb-labs/sdk/adapters\";\n\nexport const manifest: AdapterManifest = {\n manifestVersion: \"1.0.0\",\n id: \"log-document\",\n name: \"Document-backed Log Persistence\",\n version: \"1.0.0\",\n description:\n \"ILogPersistence implementation storing log entries in any IDocumentDatabase. Driver-agnostic.\",\n author: \"KB Labs Team\",\n license: \"KBPL-1.1\",\n type: \"extension\",\n implements: \"ILogPersistence\",\n extends: {\n adapter: \"logger\",\n hook: \"onLog\",\n method: \"write\",\n priority: 0,\n },\n contexts: [\"workspace\", \"process\"],\n requires: {\n adapters: [{ id: \"documentDatabase\", alias: \"documentDatabase\" }],\n },\n capabilities: {\n batch: true,\n search: true,\n custom: {\n retentionPolicy: true,\n },\n },\n configSchema: {\n collection: {\n type: \"string\",\n default: \"logs\",\n description: \"Name of the document collection that stores log entries.\",\n },\n batchSize: {\n type: \"number\",\n default: 100,\n description: \"Batch size for buffered writes.\",\n },\n flushInterval: {\n type: \"number\",\n default: 5000,\n description: \"Maximum delay before a partial batch is flushed (ms).\",\n },\n },\n};\n"]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kb-labs/adapters-log-document",
|
|
3
3
|
"description": "ILogPersistence implementation backed by IDocumentDatabase (dogfooded — same abstraction the rest of the platform uses).",
|
|
4
|
-
"version": "2.
|
|
4
|
+
"version": "2.114.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"types": "./dist/index.d.ts",
|