@loggerjs/browser 0.5.1 → 0.5.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.
@@ -27,6 +27,28 @@ export interface LogZipExportManifest {
27
27
  from: number;
28
28
  to: number;
29
29
  };
30
+ recentLogFileName?: string;
31
+ sessionCount?: number;
32
+ sessions?: LogZipExportSessionManifest[];
33
+ }
34
+ export interface LogZipExportSessionManifest {
35
+ sessionId: string;
36
+ logFileName: string;
37
+ logCount: number;
38
+ timeRange?: {
39
+ from: number;
40
+ to: number;
41
+ };
42
+ }
43
+ export interface LogZipExportSessionOptions {
44
+ contextKey?: string;
45
+ directory?: string;
46
+ fallbackSessionId?: string;
47
+ logFileName?: string;
48
+ }
49
+ export interface LogZipExportRecentOptions {
50
+ logFileName?: string;
51
+ maxEvents?: number;
30
52
  }
31
53
  export interface LogZipExportOptions {
32
54
  query?: IndexedDbTransportQueryOptions;
@@ -40,6 +62,8 @@ export interface LogZipExportOptions {
40
62
  stringify?: SafeStringifyOptions;
41
63
  serializeEvent?: (event: LogEvent) => string;
42
64
  mapEvent?: (event: LogEvent) => LogEvent | false | null | undefined;
65
+ groupBySession?: boolean | LogZipExportSessionOptions;
66
+ includeRecent?: boolean | LogZipExportRecentOptions;
43
67
  }
44
68
  export interface DownloadBlobOptions {
45
69
  filename?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"zip-export.d.ts","sourceRoot":"","sources":["../src/zip-export.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,QAAQ,EAAE,KAAK,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAC7F,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,uBAAuB,CAAC;AAE5E,MAAM,MAAM,kBAAkB,GAAG,QAAQ,GAAG,MAAM,CAAC;AAEnD,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,GAAG,UAAU,GAAG,WAAW,CAAC;IAC3C,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,iBAAiB;IAChC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,uBAAuB;IACtC,KAAK,EAAE,CAAC,OAAO,CAAC,EAAE,8BAA8B,KAAK,aAAa,CAAC,QAAQ,CAAC,CAAC;CAC9E;AAED,MAAM,MAAM,kBAAkB,GAAG,aAAa,CAAC,QAAQ,CAAC,GAAG,uBAAuB,CAAC;AAEnF,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,wBAAwB,CAAC;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,kBAAkB,CAAC;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,8BAA8B,CAAC;IACvC,SAAS,CAAC,EAAE;QACV,IAAI,EAAE,MAAM,CAAC;QACb,EAAE,EAAE,MAAM,CAAC;KACZ,CAAC;CACH;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,CAAC,EAAE,8BAA8B,CAAC;IACvC,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,oBAAoB,CAAC;IACjC,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,MAAM,CAAC;IAC7C,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,QAAQ,GAAG,KAAK,GAAG,IAAI,GAAG,SAAS,CAAC;CACrE;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,GAAG,CAAC,EAAE,IAAI,CAAC,OAAO,GAAG,EAAE,iBAAiB,GAAG,iBAAiB,CAAC,CAAC;IAC9D,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAyMD,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,SAAS,aAAa,EAAE,EAC/B,OAAO,GAAE,iBAAsB,GAC9B,IAAI,CAwBN;AAED,wBAAsB,eAAe,CACnC,MAAM,EAAE,kBAAkB,EAC1B,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,IAAI,CAAC,CAwDf;AAED,wBAAgB,YAAY,CAC1B,IAAI,EAAE,IAAI,EACV,iBAAiB,GAAE,MAAM,GAAG,mBAAwB,GACnD,MAAM,CA2BR"}
1
+ {"version":3,"file":"zip-export.d.ts","sourceRoot":"","sources":["../src/zip-export.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,QAAQ,EAAE,KAAK,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAC7F,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,uBAAuB,CAAC;AAE5E,MAAM,MAAM,kBAAkB,GAAG,QAAQ,GAAG,MAAM,CAAC;AAEnD,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,GAAG,UAAU,GAAG,WAAW,CAAC;IAC3C,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,iBAAiB;IAChC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,uBAAuB;IACtC,KAAK,EAAE,CAAC,OAAO,CAAC,EAAE,8BAA8B,KAAK,aAAa,CAAC,QAAQ,CAAC,CAAC;CAC9E;AAED,MAAM,MAAM,kBAAkB,GAAG,aAAa,CAAC,QAAQ,CAAC,GAAG,uBAAuB,CAAC;AAEnF,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,wBAAwB,CAAC;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,kBAAkB,CAAC;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,8BAA8B,CAAC;IACvC,SAAS,CAAC,EAAE;QACV,IAAI,EAAE,MAAM,CAAC;QACb,EAAE,EAAE,MAAM,CAAC;KACZ,CAAC;IACF,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,2BAA2B,EAAE,CAAC;CAC1C;AAED,MAAM,WAAW,2BAA2B;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE;QACV,IAAI,EAAE,MAAM,CAAC;QACb,EAAE,EAAE,MAAM,CAAC;KACZ,CAAC;CACH;AAED,MAAM,WAAW,0BAA0B;IACzC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,yBAAyB;IACxC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,CAAC,EAAE,8BAA8B,CAAC;IACvC,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,oBAAoB,CAAC;IACjC,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,MAAM,CAAC;IAC7C,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,QAAQ,GAAG,KAAK,GAAG,IAAI,GAAG,SAAS,CAAC;IACpE,cAAc,CAAC,EAAE,OAAO,GAAG,0BAA0B,CAAC;IACtD,aAAa,CAAC,EAAE,OAAO,GAAG,yBAAyB,CAAC;CACrD;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,GAAG,CAAC,EAAE,IAAI,CAAC,OAAO,GAAG,EAAE,iBAAiB,GAAG,iBAAiB,CAAC,CAAC;IAC9D,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AA6RD,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,SAAS,aAAa,EAAE,EAC/B,OAAO,GAAE,iBAAsB,GAC9B,IAAI,CAwBN;AAED,wBAAsB,eAAe,CACnC,MAAM,EAAE,kBAAkB,EAC1B,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,IAAI,CAAC,CAuHf;AAED,wBAAgB,YAAY,CAC1B,IAAI,EAAE,IAAI,EACV,iBAAiB,GAAE,MAAM,GAAG,mBAAwB,GACnD,MAAM,CA2BR"}
@@ -8,6 +8,7 @@ const ZIP_MAX_UINT32 = 4294967295;
8
8
  const LOCAL_FILE_HEADER_SIGNATURE = 67324752;
9
9
  const CENTRAL_DIRECTORY_SIGNATURE = 33639248;
10
10
  const END_OF_CENTRAL_DIRECTORY_SIGNATURE = 101010256;
11
+ const DEFAULT_SESSION_CONTEXT_KEY = "sessionId";
11
12
  let crc32Table;
12
13
  function getCrc32Table() {
13
14
  if (crc32Table) return crc32Table;
@@ -147,6 +148,56 @@ function normalizeMaxEvents(value) {
147
148
  if (!Number.isFinite(value)) return void 0;
148
149
  return Math.max(0, Math.floor(value));
149
150
  }
151
+ function normalizeSessionExportOptions(value, logFileName) {
152
+ if (!value) return void 0;
153
+ const options = value === true ? {} : value;
154
+ return {
155
+ contextKey: options.contextKey ?? DEFAULT_SESSION_CONTEXT_KEY,
156
+ directory: options.directory ?? "sessions",
157
+ fallbackSessionId: options.fallbackSessionId ?? "unknown",
158
+ logFileName: options.logFileName ?? logFileName
159
+ };
160
+ }
161
+ function normalizeRecentExportOptions(value, format) {
162
+ if (!value) return void 0;
163
+ const options = value === true ? {} : value;
164
+ return {
165
+ logFileName: options.logFileName ?? (format === "json" ? "recent.json" : "recent.ndjson"),
166
+ maxEvents: normalizeMaxEvents(options.maxEvents) ?? 100
167
+ };
168
+ }
169
+ function logContentForLines(lines, format) {
170
+ if (format === "json") return `[${lines.join(",")}]`;
171
+ return lines.length > 0 ? `${lines.join("\n")}\n` : "";
172
+ }
173
+ function eventTimeRange(items) {
174
+ let from;
175
+ let to;
176
+ for (const item of items) {
177
+ from = from === void 0 ? item.event.time : Math.min(from, item.event.time);
178
+ to = to === void 0 ? item.event.time : Math.max(to, item.event.time);
179
+ }
180
+ return from === void 0 || to === void 0 ? void 0 : {
181
+ from,
182
+ to
183
+ };
184
+ }
185
+ function sessionIdForEvent(event, options) {
186
+ const value = event.context?.[options.contextKey];
187
+ return typeof value === "string" && value.length > 0 ? value : options.fallbackSessionId;
188
+ }
189
+ function safeZipPathSegment(value) {
190
+ const encoded = encodeURIComponent(value).replace(/%/g, "_");
191
+ if (!encoded || encoded === "." || encoded === "..") return "_";
192
+ return encoded;
193
+ }
194
+ function sortByEventTime(items) {
195
+ return [...items].sort((left, right) => {
196
+ if (left.event.time !== right.event.time) return left.event.time - right.event.time;
197
+ if (left.event.seq !== right.event.seq) return left.event.seq - right.event.seq;
198
+ return left.event.id < right.event.id ? -1 : left.event.id > right.event.id ? 1 : 0;
199
+ });
200
+ }
150
201
  function createLogZipBlob(files, options = {}) {
151
202
  const normalizedFiles = createNormalizedZipFiles(files, options);
152
203
  const parts = [];
@@ -169,27 +220,72 @@ async function exportLogsToZip(source, options = {}) {
169
220
  const createdAt = options.createdAt ?? Date.now();
170
221
  const logFileName = options.logFileName ?? (format === "json" ? "logs.json" : "logs.ndjson");
171
222
  const maxEvents = normalizeMaxEvents(options.maxEvents);
223
+ const sessionExportOptions = normalizeSessionExportOptions(options.groupBySession, logFileName);
224
+ const recentExportOptions = normalizeRecentExportOptions(options.includeRecent, format);
172
225
  const serialize = options.serializeEvent ?? ((event) => safeJsonStringify(event, options.stringify ?? {}));
173
- const lines = [];
226
+ const exported = [];
174
227
  let skippedCount = 0;
175
- let from;
176
- let to;
177
228
  for await (const event of resolveSource(source, options.query)) {
178
- if (maxEvents !== void 0 && lines.length >= maxEvents) break;
229
+ if (maxEvents !== void 0 && exported.length >= maxEvents) break;
179
230
  const mapped = options.mapEvent ? options.mapEvent(event) : event;
180
231
  if (!mapped) {
181
232
  skippedCount += 1;
182
233
  continue;
183
234
  }
184
- lines.push(serialize(mapped));
185
- from = from === void 0 ? mapped.time : Math.min(from, mapped.time);
186
- to = to === void 0 ? mapped.time : Math.max(to, mapped.time);
235
+ exported.push({
236
+ event: mapped,
237
+ line: serialize(mapped)
238
+ });
187
239
  }
188
240
  const files = [{
189
241
  name: logFileName,
190
- content: format === "json" ? `[${lines.join(",")}]` : lines.length > 0 ? `${lines.join("\n")}\n` : "",
242
+ content: logContentForLines(exported.map((item) => item.line), format),
191
243
  lastModified: createdAt
192
244
  }];
245
+ const sessionManifests = [];
246
+ if (sessionExportOptions) {
247
+ const groups = /* @__PURE__ */ new Map();
248
+ for (const item of exported) {
249
+ const sessionId = sessionIdForEvent(item.event, sessionExportOptions);
250
+ const group = groups.get(sessionId) ?? [];
251
+ group.push(item);
252
+ groups.set(sessionId, group);
253
+ }
254
+ const usedFileNames = new Set(files.map((file) => normalizeZipFileName(file.name)));
255
+ const sortedGroups = [...groups.entries()];
256
+ sortedGroups.sort(([left], [right]) => left < right ? -1 : left > right ? 1 : 0);
257
+ for (const [sessionId, group] of sortedGroups) {
258
+ let fileName = normalizeZipFileName(`${sessionExportOptions.directory}/${safeZipPathSegment(sessionId)}/${sessionExportOptions.logFileName}`);
259
+ let suffix = 1;
260
+ while (usedFileNames.has(fileName)) {
261
+ fileName = normalizeZipFileName(`${sessionExportOptions.directory}/${safeZipPathSegment(sessionId)}-${suffix}/${sessionExportOptions.logFileName}`);
262
+ suffix += 1;
263
+ }
264
+ usedFileNames.add(fileName);
265
+ const orderedGroup = sortByEventTime(group);
266
+ files.push({
267
+ name: fileName,
268
+ content: logContentForLines(orderedGroup.map((item) => item.line), format),
269
+ lastModified: createdAt
270
+ });
271
+ sessionManifests.push({
272
+ logCount: orderedGroup.length,
273
+ logFileName: fileName,
274
+ sessionId,
275
+ timeRange: eventTimeRange(orderedGroup)
276
+ });
277
+ }
278
+ }
279
+ let recentLogFileName;
280
+ if (recentExportOptions) {
281
+ const recentItems = recentExportOptions.maxEvents <= 0 ? [] : sortByEventTime(exported).slice(-recentExportOptions.maxEvents);
282
+ recentLogFileName = normalizeZipFileName(recentExportOptions.logFileName);
283
+ files.push({
284
+ name: recentLogFileName,
285
+ content: logContentForLines(recentItems.map((item) => item.line), format),
286
+ lastModified: createdAt
287
+ });
288
+ }
193
289
  if (options.includeManifest ?? true) {
194
290
  const manifest = {
195
291
  schema: "loggerjs.log-export.v1",
@@ -197,13 +293,13 @@ async function exportLogsToZip(source, options = {}) {
197
293
  source: options.source,
198
294
  format,
199
295
  logFileName: normalizeZipFileName(logFileName),
200
- logCount: lines.length,
296
+ logCount: exported.length,
201
297
  skippedCount,
202
298
  query: options.query,
203
- timeRange: from === void 0 || to === void 0 ? void 0 : {
204
- from,
205
- to
206
- }
299
+ recentLogFileName,
300
+ sessionCount: sessionExportOptions ? sessionManifests.length : void 0,
301
+ sessions: sessionExportOptions ? sessionManifests : void 0,
302
+ timeRange: eventTimeRange(exported)
207
303
  };
208
304
  files.push({
209
305
  name: options.manifestFileName ?? "manifest.json",
@@ -1 +1 @@
1
- {"version":3,"file":"zip-export.js","names":[],"sources":["../src/zip-export.ts"],"sourcesContent":["import { safeJsonStringify, type LogEvent, type SafeStringifyOptions } from \"@loggerjs/core\";\nimport type { IndexedDbTransportQueryOptions } from \"./indexeddb-transport\";\n\nexport type LogZipExportFormat = \"ndjson\" | \"json\";\n\nexport interface ZipExportFile {\n name: string;\n content: string | Uint8Array | ArrayBuffer;\n lastModified?: number;\n}\n\nexport interface LogZipBlobOptions {\n lastModified?: number;\n type?: string;\n}\n\nexport interface LogZipExportQuerySource {\n query: (options?: IndexedDbTransportQueryOptions) => AsyncIterable<LogEvent>;\n}\n\nexport type LogZipExportSource = AsyncIterable<LogEvent> | LogZipExportQuerySource;\n\nexport interface LogZipExportManifest {\n schema: \"loggerjs.log-export.v1\";\n createdAt: string;\n source?: string;\n format: LogZipExportFormat;\n logFileName: string;\n logCount: number;\n skippedCount: number;\n query?: IndexedDbTransportQueryOptions;\n timeRange?: {\n from: number;\n to: number;\n };\n}\n\nexport interface LogZipExportOptions {\n query?: IndexedDbTransportQueryOptions;\n format?: LogZipExportFormat;\n logFileName?: string;\n includeManifest?: boolean;\n manifestFileName?: string;\n source?: string;\n createdAt?: number;\n maxEvents?: number;\n stringify?: SafeStringifyOptions;\n serializeEvent?: (event: LogEvent) => string;\n mapEvent?: (event: LogEvent) => LogEvent | false | null | undefined;\n}\n\nexport interface DownloadBlobOptions {\n filename?: string;\n document?: Document;\n url?: Pick<typeof URL, \"createObjectURL\" | \"revokeObjectURL\">;\n revokeDelayMs?: number;\n}\n\ninterface NormalizedZipFile {\n name: string;\n nameBytes: Uint8Array;\n contentBytes: Uint8Array;\n crc32: number;\n modifiedTime: number;\n modifiedDate: number;\n localHeaderOffset: number;\n}\n\nconst ZIP_UTF8_FLAG = 0x0800;\nconst ZIP_STORE_METHOD = 0;\nconst ZIP_VERSION = 20;\nconst ZIP_MAX_UINT16 = 0xffff;\nconst ZIP_MAX_UINT32 = 0xffffffff;\nconst LOCAL_FILE_HEADER_SIGNATURE = 0x04034b50;\nconst CENTRAL_DIRECTORY_SIGNATURE = 0x02014b50;\nconst END_OF_CENTRAL_DIRECTORY_SIGNATURE = 0x06054b50;\n\nlet crc32Table: Uint32Array | undefined;\n\nfunction getCrc32Table(): Uint32Array {\n if (crc32Table) return crc32Table;\n const table = new Uint32Array(256);\n for (let index = 0; index < table.length; index += 1) {\n let crc = index;\n for (let bit = 0; bit < 8; bit += 1) {\n crc = crc & 1 ? 0xedb88320 ^ (crc >>> 1) : crc >>> 1;\n }\n table[index] = crc >>> 0;\n }\n crc32Table = table;\n return table;\n}\n\nfunction crc32(bytes: Uint8Array): number {\n const table = getCrc32Table();\n let crc = 0xffffffff;\n for (const byte of bytes) {\n crc = (crc >>> 8) ^ (table[(crc ^ byte) & 0xff] ?? 0);\n }\n return (crc ^ 0xffffffff) >>> 0;\n}\n\nfunction encodeText(value: string): Uint8Array {\n return new TextEncoder().encode(value);\n}\n\nfunction normalizeFileContent(content: ZipExportFile[\"content\"]): Uint8Array {\n if (typeof content === \"string\") return encodeText(content);\n if (content instanceof Uint8Array) return content;\n return new Uint8Array(content);\n}\n\nfunction normalizeZipFileName(name: string): string {\n const normalized = name\n .replace(/\\\\/g, \"/\")\n .split(\"/\")\n .filter((part) => part.length > 0 && part !== \".\" && part !== \"..\")\n .join(\"/\");\n if (!normalized) throw new Error(\"ZIP file name cannot be empty\");\n return normalized;\n}\n\nfunction toDosDateTime(timestamp: number): { time: number; date: number } {\n const date = new Date(Number.isFinite(timestamp) ? timestamp : Date.now());\n const year = Math.min(2107, Math.max(1980, date.getFullYear()));\n return {\n time: (date.getHours() << 11) | (date.getMinutes() << 5) | Math.floor(date.getSeconds() / 2),\n date: ((year - 1980) << 9) | ((date.getMonth() + 1) << 5) | date.getDate(),\n };\n}\n\nfunction assertZipUint16(value: number, label: string) {\n if (!Number.isSafeInteger(value) || value < 0 || value > ZIP_MAX_UINT16) {\n throw new Error(`${label} exceeds ZIP32 limit`);\n }\n}\n\nfunction assertZipUint32(value: number, label: string) {\n if (!Number.isSafeInteger(value) || value < 0 || value > ZIP_MAX_UINT32) {\n throw new Error(`${label} exceeds ZIP32 limit`);\n }\n}\n\nfunction createLocalFileHeader(file: NormalizedZipFile): Uint8Array {\n const header = new Uint8Array(30);\n const view = new DataView(header.buffer);\n view.setUint32(0, LOCAL_FILE_HEADER_SIGNATURE, true);\n view.setUint16(4, ZIP_VERSION, true);\n view.setUint16(6, ZIP_UTF8_FLAG, true);\n view.setUint16(8, ZIP_STORE_METHOD, true);\n view.setUint16(10, file.modifiedTime, true);\n view.setUint16(12, file.modifiedDate, true);\n view.setUint32(14, file.crc32, true);\n view.setUint32(18, file.contentBytes.byteLength, true);\n view.setUint32(22, file.contentBytes.byteLength, true);\n view.setUint16(26, file.nameBytes.byteLength, true);\n view.setUint16(28, 0, true);\n return header;\n}\n\nfunction createCentralDirectoryHeader(file: NormalizedZipFile): Uint8Array {\n const header = new Uint8Array(46);\n const view = new DataView(header.buffer);\n view.setUint32(0, CENTRAL_DIRECTORY_SIGNATURE, true);\n view.setUint16(4, ZIP_VERSION, true);\n view.setUint16(6, ZIP_VERSION, true);\n view.setUint16(8, ZIP_UTF8_FLAG, true);\n view.setUint16(10, ZIP_STORE_METHOD, true);\n view.setUint16(12, file.modifiedTime, true);\n view.setUint16(14, file.modifiedDate, true);\n view.setUint32(16, file.crc32, true);\n view.setUint32(20, file.contentBytes.byteLength, true);\n view.setUint32(24, file.contentBytes.byteLength, true);\n view.setUint16(28, file.nameBytes.byteLength, true);\n view.setUint16(30, 0, true);\n view.setUint16(32, 0, true);\n view.setUint16(34, 0, true);\n view.setUint16(36, 0, true);\n view.setUint32(38, 0, true);\n view.setUint32(42, file.localHeaderOffset, true);\n return header;\n}\n\nfunction createEndOfCentralDirectory(\n fileCount: number,\n centralDirectorySize: number,\n centralDirectoryOffset: number,\n): Uint8Array {\n assertZipUint16(fileCount, \"ZIP file count\");\n assertZipUint32(centralDirectorySize, \"ZIP central directory size\");\n assertZipUint32(centralDirectoryOffset, \"ZIP central directory offset\");\n\n const footer = new Uint8Array(22);\n const view = new DataView(footer.buffer);\n view.setUint32(0, END_OF_CENTRAL_DIRECTORY_SIGNATURE, true);\n view.setUint16(4, 0, true);\n view.setUint16(6, 0, true);\n view.setUint16(8, fileCount, true);\n view.setUint16(10, fileCount, true);\n view.setUint32(12, centralDirectorySize, true);\n view.setUint32(16, centralDirectoryOffset, true);\n view.setUint16(20, 0, true);\n return footer;\n}\n\nfunction createNormalizedZipFiles(\n files: readonly ZipExportFile[],\n options: LogZipBlobOptions,\n): NormalizedZipFile[] {\n const names = new Set<string>();\n let offset = 0;\n return files.map((file) => {\n const name = normalizeZipFileName(file.name);\n if (names.has(name)) throw new Error(`Duplicate ZIP file name: ${name}`);\n names.add(name);\n\n const nameBytes = encodeText(name);\n const contentBytes = normalizeFileContent(file.content);\n assertZipUint16(nameBytes.byteLength, `ZIP file name ${name}`);\n assertZipUint32(contentBytes.byteLength, `ZIP file ${name}`);\n assertZipUint32(offset, \"ZIP local header offset\");\n\n const modified = toDosDateTime(file.lastModified ?? options.lastModified ?? Date.now());\n const normalized: NormalizedZipFile = {\n name,\n nameBytes,\n contentBytes,\n crc32: crc32(contentBytes),\n modifiedTime: modified.time,\n modifiedDate: modified.date,\n localHeaderOffset: offset,\n };\n offset += 30 + nameBytes.byteLength + contentBytes.byteLength;\n assertZipUint32(offset, \"ZIP local data size\");\n return normalized;\n });\n}\n\nfunction isQuerySource(source: LogZipExportSource): source is LogZipExportQuerySource {\n return \"query\" in source && typeof source.query === \"function\";\n}\n\nfunction resolveSource(\n source: LogZipExportSource,\n query: IndexedDbTransportQueryOptions | undefined,\n): AsyncIterable<LogEvent> {\n if (isQuerySource(source)) return source.query(query);\n if (query) throw new Error(\"Log ZIP export query options require a source with query()\");\n return source;\n}\n\nfunction normalizeMaxEvents(value: number | undefined): number | undefined {\n if (value === undefined) return undefined;\n if (!Number.isFinite(value)) return undefined;\n return Math.max(0, Math.floor(value));\n}\n\nexport function createLogZipBlob(\n files: readonly ZipExportFile[],\n options: LogZipBlobOptions = {},\n): Blob {\n const normalizedFiles = createNormalizedZipFiles(files, options);\n const parts: Uint8Array[] = [];\n let centralDirectoryOffset = 0;\n for (const file of normalizedFiles) {\n parts.push(createLocalFileHeader(file), file.nameBytes, file.contentBytes);\n centralDirectoryOffset += 30 + file.nameBytes.byteLength + file.contentBytes.byteLength;\n }\n\n let centralDirectorySize = 0;\n for (const file of normalizedFiles) {\n const header = createCentralDirectoryHeader(file);\n parts.push(header, file.nameBytes);\n centralDirectorySize += header.byteLength + file.nameBytes.byteLength;\n }\n parts.push(\n createEndOfCentralDirectory(\n normalizedFiles.length,\n centralDirectorySize,\n centralDirectoryOffset,\n ),\n );\n\n return new Blob(parts as unknown as BlobPart[], { type: options.type ?? \"application/zip\" });\n}\n\nexport async function exportLogsToZip(\n source: LogZipExportSource,\n options: LogZipExportOptions = {},\n): Promise<Blob> {\n const format = options.format ?? \"ndjson\";\n const createdAt = options.createdAt ?? Date.now();\n const logFileName = options.logFileName ?? (format === \"json\" ? \"logs.json\" : \"logs.ndjson\");\n const maxEvents = normalizeMaxEvents(options.maxEvents);\n const serialize =\n options.serializeEvent ??\n ((event: LogEvent) => safeJsonStringify(event, options.stringify ?? {}));\n const lines: string[] = [];\n let skippedCount = 0;\n let from: number | undefined;\n let to: number | undefined;\n\n for await (const event of resolveSource(source, options.query)) {\n if (maxEvents !== undefined && lines.length >= maxEvents) break;\n const mapped = options.mapEvent ? options.mapEvent(event) : event;\n if (!mapped) {\n skippedCount += 1;\n continue;\n }\n lines.push(serialize(mapped));\n from = from === undefined ? mapped.time : Math.min(from, mapped.time);\n to = to === undefined ? mapped.time : Math.max(to, mapped.time);\n }\n\n const logContent =\n format === \"json\" ? `[${lines.join(\",\")}]` : lines.length > 0 ? `${lines.join(\"\\n\")}\\n` : \"\";\n\n const files: ZipExportFile[] = [\n {\n name: logFileName,\n content: logContent,\n lastModified: createdAt,\n },\n ];\n\n if (options.includeManifest ?? true) {\n const manifest: LogZipExportManifest = {\n schema: \"loggerjs.log-export.v1\",\n createdAt: new Date(createdAt).toISOString(),\n source: options.source,\n format,\n logFileName: normalizeZipFileName(logFileName),\n logCount: lines.length,\n skippedCount,\n query: options.query,\n timeRange: from === undefined || to === undefined ? undefined : { from, to },\n };\n files.push({\n name: options.manifestFileName ?? \"manifest.json\",\n content: `${safeJsonStringify(manifest, { space: 2 })}\\n`,\n lastModified: createdAt,\n });\n }\n\n return createLogZipBlob(files, { lastModified: createdAt });\n}\n\nexport function downloadBlob(\n blob: Blob,\n filenameOrOptions: string | DownloadBlobOptions = {},\n): string {\n const options =\n typeof filenameOrOptions === \"string\" ? { filename: filenameOrOptions } : filenameOrOptions;\n const documentRef = options.document ?? globalThis.document;\n const urlRef = options.url ?? globalThis.URL;\n if (!documentRef?.body || !urlRef?.createObjectURL || !urlRef.revokeObjectURL) {\n throw new Error(\"downloadBlob requires document and URL.createObjectURL\");\n }\n\n const href = urlRef.createObjectURL(blob);\n const anchor = documentRef.createElement(\"a\");\n anchor.href = href;\n anchor.download = options.filename ?? \"loggerjs-logs.zip\";\n anchor.style.display = \"none\";\n documentRef.body.appendChild(anchor);\n anchor.click();\n anchor.remove();\n\n const revoke = () => urlRef.revokeObjectURL(href);\n const revokeDelayMs = options.revokeDelayMs ?? 1000;\n if (revokeDelayMs <= 0) {\n revoke();\n } else {\n setTimeout(revoke, revokeDelayMs);\n }\n\n return href;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"zip-export.js","names":[],"sources":["../src/zip-export.ts"],"sourcesContent":["import { safeJsonStringify, type LogEvent, type SafeStringifyOptions } from \"@loggerjs/core\";\nimport type { IndexedDbTransportQueryOptions } from \"./indexeddb-transport\";\n\nexport type LogZipExportFormat = \"ndjson\" | \"json\";\n\nexport interface ZipExportFile {\n name: string;\n content: string | Uint8Array | ArrayBuffer;\n lastModified?: number;\n}\n\nexport interface LogZipBlobOptions {\n lastModified?: number;\n type?: string;\n}\n\nexport interface LogZipExportQuerySource {\n query: (options?: IndexedDbTransportQueryOptions) => AsyncIterable<LogEvent>;\n}\n\nexport type LogZipExportSource = AsyncIterable<LogEvent> | LogZipExportQuerySource;\n\nexport interface LogZipExportManifest {\n schema: \"loggerjs.log-export.v1\";\n createdAt: string;\n source?: string;\n format: LogZipExportFormat;\n logFileName: string;\n logCount: number;\n skippedCount: number;\n query?: IndexedDbTransportQueryOptions;\n timeRange?: {\n from: number;\n to: number;\n };\n recentLogFileName?: string;\n sessionCount?: number;\n sessions?: LogZipExportSessionManifest[];\n}\n\nexport interface LogZipExportSessionManifest {\n sessionId: string;\n logFileName: string;\n logCount: number;\n timeRange?: {\n from: number;\n to: number;\n };\n}\n\nexport interface LogZipExportSessionOptions {\n contextKey?: string;\n directory?: string;\n fallbackSessionId?: string;\n logFileName?: string;\n}\n\nexport interface LogZipExportRecentOptions {\n logFileName?: string;\n maxEvents?: number;\n}\n\nexport interface LogZipExportOptions {\n query?: IndexedDbTransportQueryOptions;\n format?: LogZipExportFormat;\n logFileName?: string;\n includeManifest?: boolean;\n manifestFileName?: string;\n source?: string;\n createdAt?: number;\n maxEvents?: number;\n stringify?: SafeStringifyOptions;\n serializeEvent?: (event: LogEvent) => string;\n mapEvent?: (event: LogEvent) => LogEvent | false | null | undefined;\n groupBySession?: boolean | LogZipExportSessionOptions;\n includeRecent?: boolean | LogZipExportRecentOptions;\n}\n\nexport interface DownloadBlobOptions {\n filename?: string;\n document?: Document;\n url?: Pick<typeof URL, \"createObjectURL\" | \"revokeObjectURL\">;\n revokeDelayMs?: number;\n}\n\ninterface NormalizedZipFile {\n name: string;\n nameBytes: Uint8Array;\n contentBytes: Uint8Array;\n crc32: number;\n modifiedTime: number;\n modifiedDate: number;\n localHeaderOffset: number;\n}\n\ninterface ExportedLogLine {\n event: LogEvent;\n line: string;\n}\n\ninterface NormalizedSessionExportOptions {\n contextKey: string;\n directory: string;\n fallbackSessionId: string;\n logFileName: string;\n}\n\ninterface NormalizedRecentExportOptions {\n logFileName: string;\n maxEvents: number;\n}\n\nconst ZIP_UTF8_FLAG = 0x0800;\nconst ZIP_STORE_METHOD = 0;\nconst ZIP_VERSION = 20;\nconst ZIP_MAX_UINT16 = 0xffff;\nconst ZIP_MAX_UINT32 = 0xffffffff;\nconst LOCAL_FILE_HEADER_SIGNATURE = 0x04034b50;\nconst CENTRAL_DIRECTORY_SIGNATURE = 0x02014b50;\nconst END_OF_CENTRAL_DIRECTORY_SIGNATURE = 0x06054b50;\nconst DEFAULT_SESSION_CONTEXT_KEY = \"sessionId\";\n\nlet crc32Table: Uint32Array | undefined;\n\nfunction getCrc32Table(): Uint32Array {\n if (crc32Table) return crc32Table;\n const table = new Uint32Array(256);\n for (let index = 0; index < table.length; index += 1) {\n let crc = index;\n for (let bit = 0; bit < 8; bit += 1) {\n crc = crc & 1 ? 0xedb88320 ^ (crc >>> 1) : crc >>> 1;\n }\n table[index] = crc >>> 0;\n }\n crc32Table = table;\n return table;\n}\n\nfunction crc32(bytes: Uint8Array): number {\n const table = getCrc32Table();\n let crc = 0xffffffff;\n for (const byte of bytes) {\n crc = (crc >>> 8) ^ (table[(crc ^ byte) & 0xff] ?? 0);\n }\n return (crc ^ 0xffffffff) >>> 0;\n}\n\nfunction encodeText(value: string): Uint8Array {\n return new TextEncoder().encode(value);\n}\n\nfunction normalizeFileContent(content: ZipExportFile[\"content\"]): Uint8Array {\n if (typeof content === \"string\") return encodeText(content);\n if (content instanceof Uint8Array) return content;\n return new Uint8Array(content);\n}\n\nfunction normalizeZipFileName(name: string): string {\n const normalized = name\n .replace(/\\\\/g, \"/\")\n .split(\"/\")\n .filter((part) => part.length > 0 && part !== \".\" && part !== \"..\")\n .join(\"/\");\n if (!normalized) throw new Error(\"ZIP file name cannot be empty\");\n return normalized;\n}\n\nfunction toDosDateTime(timestamp: number): { time: number; date: number } {\n const date = new Date(Number.isFinite(timestamp) ? timestamp : Date.now());\n const year = Math.min(2107, Math.max(1980, date.getFullYear()));\n return {\n time: (date.getHours() << 11) | (date.getMinutes() << 5) | Math.floor(date.getSeconds() / 2),\n date: ((year - 1980) << 9) | ((date.getMonth() + 1) << 5) | date.getDate(),\n };\n}\n\nfunction assertZipUint16(value: number, label: string) {\n if (!Number.isSafeInteger(value) || value < 0 || value > ZIP_MAX_UINT16) {\n throw new Error(`${label} exceeds ZIP32 limit`);\n }\n}\n\nfunction assertZipUint32(value: number, label: string) {\n if (!Number.isSafeInteger(value) || value < 0 || value > ZIP_MAX_UINT32) {\n throw new Error(`${label} exceeds ZIP32 limit`);\n }\n}\n\nfunction createLocalFileHeader(file: NormalizedZipFile): Uint8Array {\n const header = new Uint8Array(30);\n const view = new DataView(header.buffer);\n view.setUint32(0, LOCAL_FILE_HEADER_SIGNATURE, true);\n view.setUint16(4, ZIP_VERSION, true);\n view.setUint16(6, ZIP_UTF8_FLAG, true);\n view.setUint16(8, ZIP_STORE_METHOD, true);\n view.setUint16(10, file.modifiedTime, true);\n view.setUint16(12, file.modifiedDate, true);\n view.setUint32(14, file.crc32, true);\n view.setUint32(18, file.contentBytes.byteLength, true);\n view.setUint32(22, file.contentBytes.byteLength, true);\n view.setUint16(26, file.nameBytes.byteLength, true);\n view.setUint16(28, 0, true);\n return header;\n}\n\nfunction createCentralDirectoryHeader(file: NormalizedZipFile): Uint8Array {\n const header = new Uint8Array(46);\n const view = new DataView(header.buffer);\n view.setUint32(0, CENTRAL_DIRECTORY_SIGNATURE, true);\n view.setUint16(4, ZIP_VERSION, true);\n view.setUint16(6, ZIP_VERSION, true);\n view.setUint16(8, ZIP_UTF8_FLAG, true);\n view.setUint16(10, ZIP_STORE_METHOD, true);\n view.setUint16(12, file.modifiedTime, true);\n view.setUint16(14, file.modifiedDate, true);\n view.setUint32(16, file.crc32, true);\n view.setUint32(20, file.contentBytes.byteLength, true);\n view.setUint32(24, file.contentBytes.byteLength, true);\n view.setUint16(28, file.nameBytes.byteLength, true);\n view.setUint16(30, 0, true);\n view.setUint16(32, 0, true);\n view.setUint16(34, 0, true);\n view.setUint16(36, 0, true);\n view.setUint32(38, 0, true);\n view.setUint32(42, file.localHeaderOffset, true);\n return header;\n}\n\nfunction createEndOfCentralDirectory(\n fileCount: number,\n centralDirectorySize: number,\n centralDirectoryOffset: number,\n): Uint8Array {\n assertZipUint16(fileCount, \"ZIP file count\");\n assertZipUint32(centralDirectorySize, \"ZIP central directory size\");\n assertZipUint32(centralDirectoryOffset, \"ZIP central directory offset\");\n\n const footer = new Uint8Array(22);\n const view = new DataView(footer.buffer);\n view.setUint32(0, END_OF_CENTRAL_DIRECTORY_SIGNATURE, true);\n view.setUint16(4, 0, true);\n view.setUint16(6, 0, true);\n view.setUint16(8, fileCount, true);\n view.setUint16(10, fileCount, true);\n view.setUint32(12, centralDirectorySize, true);\n view.setUint32(16, centralDirectoryOffset, true);\n view.setUint16(20, 0, true);\n return footer;\n}\n\nfunction createNormalizedZipFiles(\n files: readonly ZipExportFile[],\n options: LogZipBlobOptions,\n): NormalizedZipFile[] {\n const names = new Set<string>();\n let offset = 0;\n return files.map((file) => {\n const name = normalizeZipFileName(file.name);\n if (names.has(name)) throw new Error(`Duplicate ZIP file name: ${name}`);\n names.add(name);\n\n const nameBytes = encodeText(name);\n const contentBytes = normalizeFileContent(file.content);\n assertZipUint16(nameBytes.byteLength, `ZIP file name ${name}`);\n assertZipUint32(contentBytes.byteLength, `ZIP file ${name}`);\n assertZipUint32(offset, \"ZIP local header offset\");\n\n const modified = toDosDateTime(file.lastModified ?? options.lastModified ?? Date.now());\n const normalized: NormalizedZipFile = {\n name,\n nameBytes,\n contentBytes,\n crc32: crc32(contentBytes),\n modifiedTime: modified.time,\n modifiedDate: modified.date,\n localHeaderOffset: offset,\n };\n offset += 30 + nameBytes.byteLength + contentBytes.byteLength;\n assertZipUint32(offset, \"ZIP local data size\");\n return normalized;\n });\n}\n\nfunction isQuerySource(source: LogZipExportSource): source is LogZipExportQuerySource {\n return \"query\" in source && typeof source.query === \"function\";\n}\n\nfunction resolveSource(\n source: LogZipExportSource,\n query: IndexedDbTransportQueryOptions | undefined,\n): AsyncIterable<LogEvent> {\n if (isQuerySource(source)) return source.query(query);\n if (query) throw new Error(\"Log ZIP export query options require a source with query()\");\n return source;\n}\n\nfunction normalizeMaxEvents(value: number | undefined): number | undefined {\n if (value === undefined) return undefined;\n if (!Number.isFinite(value)) return undefined;\n return Math.max(0, Math.floor(value));\n}\n\nfunction normalizeSessionExportOptions(\n value: boolean | LogZipExportSessionOptions | undefined,\n logFileName: string,\n): NormalizedSessionExportOptions | undefined {\n if (!value) return undefined;\n const options = value === true ? {} : value;\n return {\n contextKey: options.contextKey ?? DEFAULT_SESSION_CONTEXT_KEY,\n directory: options.directory ?? \"sessions\",\n fallbackSessionId: options.fallbackSessionId ?? \"unknown\",\n logFileName: options.logFileName ?? logFileName,\n };\n}\n\nfunction normalizeRecentExportOptions(\n value: boolean | LogZipExportRecentOptions | undefined,\n format: LogZipExportFormat,\n): NormalizedRecentExportOptions | undefined {\n if (!value) return undefined;\n const options = value === true ? {} : value;\n return {\n logFileName: options.logFileName ?? (format === \"json\" ? \"recent.json\" : \"recent.ndjson\"),\n maxEvents: normalizeMaxEvents(options.maxEvents) ?? 100,\n };\n}\n\nfunction logContentForLines(lines: readonly string[], format: LogZipExportFormat): string {\n if (format === \"json\") return `[${lines.join(\",\")}]`;\n return lines.length > 0 ? `${lines.join(\"\\n\")}\\n` : \"\";\n}\n\nfunction eventTimeRange(items: readonly ExportedLogLine[]):\n | {\n from: number;\n to: number;\n }\n | undefined {\n let from: number | undefined;\n let to: number | undefined;\n for (const item of items) {\n from = from === undefined ? item.event.time : Math.min(from, item.event.time);\n to = to === undefined ? item.event.time : Math.max(to, item.event.time);\n }\n return from === undefined || to === undefined ? undefined : { from, to };\n}\n\nfunction sessionIdForEvent(event: LogEvent, options: NormalizedSessionExportOptions): string {\n const value = event.context?.[options.contextKey];\n return typeof value === \"string\" && value.length > 0 ? value : options.fallbackSessionId;\n}\n\nfunction safeZipPathSegment(value: string): string {\n const encoded = encodeURIComponent(value).replace(/%/g, \"_\");\n if (!encoded || encoded === \".\" || encoded === \"..\") return \"_\";\n return encoded;\n}\n\nfunction sortByEventTime(items: readonly ExportedLogLine[]): ExportedLogLine[] {\n // oxlint-disable-next-line no-array-sort -- Sort a copy for stable export ordering.\n return [...items].sort((left, right) => {\n if (left.event.time !== right.event.time) return left.event.time - right.event.time;\n if (left.event.seq !== right.event.seq) return left.event.seq - right.event.seq;\n return left.event.id < right.event.id ? -1 : left.event.id > right.event.id ? 1 : 0;\n });\n}\n\nexport function createLogZipBlob(\n files: readonly ZipExportFile[],\n options: LogZipBlobOptions = {},\n): Blob {\n const normalizedFiles = createNormalizedZipFiles(files, options);\n const parts: Uint8Array[] = [];\n let centralDirectoryOffset = 0;\n for (const file of normalizedFiles) {\n parts.push(createLocalFileHeader(file), file.nameBytes, file.contentBytes);\n centralDirectoryOffset += 30 + file.nameBytes.byteLength + file.contentBytes.byteLength;\n }\n\n let centralDirectorySize = 0;\n for (const file of normalizedFiles) {\n const header = createCentralDirectoryHeader(file);\n parts.push(header, file.nameBytes);\n centralDirectorySize += header.byteLength + file.nameBytes.byteLength;\n }\n parts.push(\n createEndOfCentralDirectory(\n normalizedFiles.length,\n centralDirectorySize,\n centralDirectoryOffset,\n ),\n );\n\n return new Blob(parts as unknown as BlobPart[], { type: options.type ?? \"application/zip\" });\n}\n\nexport async function exportLogsToZip(\n source: LogZipExportSource,\n options: LogZipExportOptions = {},\n): Promise<Blob> {\n const format = options.format ?? \"ndjson\";\n const createdAt = options.createdAt ?? Date.now();\n const logFileName = options.logFileName ?? (format === \"json\" ? \"logs.json\" : \"logs.ndjson\");\n const maxEvents = normalizeMaxEvents(options.maxEvents);\n const sessionExportOptions = normalizeSessionExportOptions(options.groupBySession, logFileName);\n const recentExportOptions = normalizeRecentExportOptions(options.includeRecent, format);\n const serialize =\n options.serializeEvent ??\n ((event: LogEvent) => safeJsonStringify(event, options.stringify ?? {}));\n const exported: ExportedLogLine[] = [];\n let skippedCount = 0;\n\n for await (const event of resolveSource(source, options.query)) {\n if (maxEvents !== undefined && exported.length >= maxEvents) break;\n const mapped = options.mapEvent ? options.mapEvent(event) : event;\n if (!mapped) {\n skippedCount += 1;\n continue;\n }\n exported.push({ event: mapped, line: serialize(mapped) });\n }\n\n const files: ZipExportFile[] = [\n {\n name: logFileName,\n content: logContentForLines(\n exported.map((item) => item.line),\n format,\n ),\n lastModified: createdAt,\n },\n ];\n const sessionManifests: LogZipExportSessionManifest[] = [];\n\n if (sessionExportOptions) {\n const groups = new Map<string, ExportedLogLine[]>();\n for (const item of exported) {\n const sessionId = sessionIdForEvent(item.event, sessionExportOptions);\n const group = groups.get(sessionId) ?? [];\n group.push(item);\n groups.set(sessionId, group);\n }\n const usedFileNames = new Set(files.map((file) => normalizeZipFileName(file.name)));\n const sortedGroups = [...groups.entries()];\n sortedGroups.sort(([left], [right]) => (left < right ? -1 : left > right ? 1 : 0));\n for (const [sessionId, group] of sortedGroups) {\n const sessionPath = `${sessionExportOptions.directory}/${safeZipPathSegment(sessionId)}/${\n sessionExportOptions.logFileName\n }`;\n let fileName = normalizeZipFileName(sessionPath);\n let suffix = 1;\n while (usedFileNames.has(fileName)) {\n fileName = normalizeZipFileName(\n `${sessionExportOptions.directory}/${safeZipPathSegment(sessionId)}-${suffix}/${\n sessionExportOptions.logFileName\n }`,\n );\n suffix += 1;\n }\n usedFileNames.add(fileName);\n const orderedGroup = sortByEventTime(group);\n files.push({\n name: fileName,\n content: logContentForLines(\n orderedGroup.map((item) => item.line),\n format,\n ),\n lastModified: createdAt,\n });\n sessionManifests.push({\n logCount: orderedGroup.length,\n logFileName: fileName,\n sessionId,\n timeRange: eventTimeRange(orderedGroup),\n });\n }\n }\n\n let recentLogFileName: string | undefined;\n if (recentExportOptions) {\n const recentItems =\n recentExportOptions.maxEvents <= 0\n ? []\n : sortByEventTime(exported).slice(-recentExportOptions.maxEvents);\n recentLogFileName = normalizeZipFileName(recentExportOptions.logFileName);\n files.push({\n name: recentLogFileName,\n content: logContentForLines(\n recentItems.map((item) => item.line),\n format,\n ),\n lastModified: createdAt,\n });\n }\n\n if (options.includeManifest ?? true) {\n const manifest: LogZipExportManifest = {\n schema: \"loggerjs.log-export.v1\",\n createdAt: new Date(createdAt).toISOString(),\n source: options.source,\n format,\n logFileName: normalizeZipFileName(logFileName),\n logCount: exported.length,\n skippedCount,\n query: options.query,\n recentLogFileName,\n sessionCount: sessionExportOptions ? sessionManifests.length : undefined,\n sessions: sessionExportOptions ? sessionManifests : undefined,\n timeRange: eventTimeRange(exported),\n };\n files.push({\n name: options.manifestFileName ?? \"manifest.json\",\n content: `${safeJsonStringify(manifest, { space: 2 })}\\n`,\n lastModified: createdAt,\n });\n }\n\n return createLogZipBlob(files, { lastModified: createdAt });\n}\n\nexport function downloadBlob(\n blob: Blob,\n filenameOrOptions: string | DownloadBlobOptions = {},\n): string {\n const options =\n typeof filenameOrOptions === \"string\" ? { filename: filenameOrOptions } : filenameOrOptions;\n const documentRef = options.document ?? globalThis.document;\n const urlRef = options.url ?? globalThis.URL;\n if (!documentRef?.body || !urlRef?.createObjectURL || !urlRef.revokeObjectURL) {\n throw new Error(\"downloadBlob requires document and URL.createObjectURL\");\n }\n\n const href = urlRef.createObjectURL(blob);\n const anchor = documentRef.createElement(\"a\");\n anchor.href = href;\n anchor.download = options.filename ?? \"loggerjs-logs.zip\";\n anchor.style.display = \"none\";\n documentRef.body.appendChild(anchor);\n anchor.click();\n anchor.remove();\n\n const revoke = () => urlRef.revokeObjectURL(href);\n const revokeDelayMs = options.revokeDelayMs ?? 1000;\n if (revokeDelayMs <= 0) {\n revoke();\n } else {\n setTimeout(revoke, revokeDelayMs);\n }\n\n return href;\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@loggerjs/browser",
3
- "version": "0.5.1",
3
+ "version": "0.5.3",
4
4
  "description": "Browser transports and integrations for loggerjs.",
5
5
  "homepage": "https://github.com/jskits/loggerjs/tree/main/packages/browser#readme",
6
6
  "bugs": {
@@ -159,7 +159,7 @@
159
159
  "provenance": true
160
160
  },
161
161
  "dependencies": {
162
- "@loggerjs/core": "0.5.1"
162
+ "@loggerjs/core": "0.5.3"
163
163
  },
164
164
  "loggerjsSubpathEntries": {
165
165
  "http-transport": "src/http-transport.ts",