@jterrazz/intelligence 3.0.1 → 3.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -56,10 +56,15 @@ Removes invisible characters, normalizes typography, and cleans common AI artifa
56
56
  ```typescript
57
57
  import { parseText } from '@jterrazz/intelligence';
58
58
 
59
- const clean = parseText(messyAiOutput, {
60
- normalizeTypography: true, // Smart quotes straight quotes
61
- removeInvisibleChars: true, // Zero-width chars, etc.
62
- trimWhitespace: true,
59
+ const clean = parseText(messyAiOutput);
60
+ // Removes: BOM, zero-width chars, AI citation markers
61
+ // Normalizes: smart quotes → straight, em dashes → ", ", ellipsis → ...
62
+ // Collapses multiple spaces and trims
63
+
64
+ // Options
65
+ parseText(text, {
66
+ normalizeEmDashesToCommas: true, // Convert em/en dashes to ", " (default: true)
67
+ collapseSpaces: true, // Collapse multiple spaces, trim (default: true)
63
68
  });
64
69
  ```
65
70
 
@@ -102,11 +107,13 @@ const model = wrapLanguageModel({
102
107
  model: provider.model('anthropic/claude-sonnet-4-20250514'),
103
108
  middleware: createLoggingMiddleware({
104
109
  logger, // Any logger with debug/error methods
105
- verbose: false, // Include full request/response in logs
110
+ include: {
111
+ params: false, // Include request params (default: false)
112
+ content: false, // Include response content (default: false)
113
+ usage: true, // Include token usage (default: true)
114
+ },
106
115
  }),
107
116
  });
108
117
  ```
109
118
 
110
- ## License
111
-
112
- MIT
119
+ Happy coding! 🚀
package/dist/index.cjs CHANGED
@@ -191,7 +191,8 @@ function _ts_generator(thisArg, body) {
191
191
  * });
192
192
  * ```
193
193
  */ function createLoggingMiddleware(options) {
194
- var logger = options.logger, _options_verbose = options.verbose, verbose = _options_verbose === void 0 ? false : _options_verbose;
194
+ var logger = options.logger, _options_include = options.include, include = _options_include === void 0 ? {} : _options_include;
195
+ var includeParams = include.params, includeContent = include.content, tmp = include.usage, includeUsage = tmp === void 0 ? true : tmp;
195
196
  return {
196
197
  middlewareVersion: 'v2',
197
198
  wrapGenerate: function(param) {
@@ -202,7 +203,7 @@ function _ts_generator(thisArg, body) {
202
203
  switch(_state.label){
203
204
  case 0:
204
205
  startTime = Date.now();
205
- logger.debug('Model request started', _object_spread$1({}, verbose && {
206
+ logger.debug('Model request started', _object_spread$1({}, includeParams && {
206
207
  params: params
207
208
  }));
208
209
  _state.label = 1;
@@ -221,9 +222,10 @@ function _ts_generator(thisArg, body) {
221
222
  result = _state.sent();
222
223
  logger.debug('Model request completed', _object_spread$1({
223
224
  durationMs: Date.now() - startTime,
224
- finishReason: result.finishReason,
225
+ finishReason: result.finishReason
226
+ }, includeUsage && {
225
227
  usage: result.usage
226
- }, verbose && {
228
+ }, includeContent && {
227
229
  content: result.content
228
230
  }));
229
231
  return [
@@ -253,7 +255,7 @@ function _ts_generator(thisArg, body) {
253
255
  switch(_state.label){
254
256
  case 0:
255
257
  startTime = Date.now();
256
- logger.debug('Model stream started', _object_spread$1({}, verbose && {
258
+ logger.debug('Model stream started', _object_spread$1({}, includeParams && {
257
259
  params: params
258
260
  }));
259
261
  _state.label = 1;
@@ -587,6 +589,29 @@ function extractBySchemaType(text, schema, originalText) {
587
589
  if (_instanceof(schema, v4.z.ZodBoolean) || _instanceof(schema, v4.z.ZodNull) || _instanceof(schema, v4.z.ZodNumber) || _instanceof(schema, v4.z.ZodString)) {
588
590
  return extractPrimitive(text, schema);
589
591
  }
592
+ // Handle union types - extract as object/array and let Zod validate which variant matches
593
+ if (_instanceof(schema, v4.z.ZodUnion) || _instanceof(schema, v4.z.ZodDiscriminatedUnion)) {
594
+ var objectStart = text.indexOf('{');
595
+ if (objectStart !== -1) {
596
+ return extractObject(text, originalText);
597
+ }
598
+ var arrayStart = text.indexOf('[');
599
+ if (arrayStart !== -1) {
600
+ return extractArray(text, originalText);
601
+ }
602
+ throw new ParseObjectError('No object or array found for union type', undefined, originalText);
603
+ }
604
+ // Handle wrapper types - unwrap and delegate to inner type
605
+ if (_instanceof(schema, v4.z.ZodOptional) || _instanceof(schema, v4.z.ZodNullable)) {
606
+ return extractBySchemaType(text, schema.unwrap(), originalText);
607
+ }
608
+ if (_instanceof(schema, v4.z.ZodDefault)) {
609
+ return extractBySchemaType(text, schema.def.innerType, originalText);
610
+ }
611
+ // Handle .transform() which creates a ZodPipe in Zod v4
612
+ if (_instanceof(schema, v4.z.ZodPipe)) {
613
+ return extractBySchemaType(text, schema.def["in"], originalText);
614
+ }
590
615
  throw new ParseObjectError('Unsupported schema type', undefined, originalText);
591
616
  }
592
617
  function extractJsonFromCodeBlock(block) {
@@ -230,7 +230,7 @@ describe('createLoggingMiddleware', function() {
230
230
  });
231
231
  })();
232
232
  });
233
- it('includes params and content when verbose is true', function() {
233
+ it('includes params when include.params is true', function() {
234
234
  return _async_to_generator(function() {
235
235
  var _middleware_wrapGenerate, logger, middleware, mockResult, mockParams, doGenerate;
236
236
  return _ts_generator(this, function(_state) {
@@ -239,7 +239,9 @@ describe('createLoggingMiddleware', function() {
239
239
  logger = createMockLogger();
240
240
  middleware = createLoggingMiddleware({
241
241
  logger: logger,
242
- verbose: true
242
+ include: {
243
+ params: true
244
+ }
243
245
  });
244
246
  mockResult = createMockGenerateResult();
245
247
  mockParams = {
@@ -260,6 +262,39 @@ describe('createLoggingMiddleware', function() {
260
262
  expect(logger.debug).toHaveBeenNthCalledWith(1, 'Model request started', expect.objectContaining({
261
263
  params: mockParams
262
264
  }));
265
+ return [
266
+ 2
267
+ ];
268
+ }
269
+ });
270
+ })();
271
+ });
272
+ it('includes content when include.content is true', function() {
273
+ return _async_to_generator(function() {
274
+ var _middleware_wrapGenerate, logger, middleware, mockResult, doGenerate;
275
+ return _ts_generator(this, function(_state) {
276
+ switch(_state.label){
277
+ case 0:
278
+ logger = createMockLogger();
279
+ middleware = createLoggingMiddleware({
280
+ logger: logger,
281
+ include: {
282
+ content: true
283
+ }
284
+ });
285
+ mockResult = createMockGenerateResult();
286
+ doGenerate = vi.fn().mockResolvedValue(mockResult);
287
+ return [
288
+ 4,
289
+ (_middleware_wrapGenerate = middleware.wrapGenerate) === null || _middleware_wrapGenerate === void 0 ? void 0 : _middleware_wrapGenerate.call(middleware, {
290
+ doGenerate: doGenerate,
291
+ doStream: vi.fn(),
292
+ params: {},
293
+ model: {}
294
+ })
295
+ ];
296
+ case 1:
297
+ _state.sent();
263
298
  expect(logger.debug).toHaveBeenNthCalledWith(2, 'Model request completed', expect.objectContaining({
264
299
  content: mockResult.content
265
300
  }));
@@ -270,6 +305,42 @@ describe('createLoggingMiddleware', function() {
270
305
  });
271
306
  })();
272
307
  });
308
+ it('excludes usage when include.usage is false', function() {
309
+ return _async_to_generator(function() {
310
+ var _middleware_wrapGenerate, logger, middleware, mockResult, doGenerate;
311
+ return _ts_generator(this, function(_state) {
312
+ switch(_state.label){
313
+ case 0:
314
+ logger = createMockLogger();
315
+ middleware = createLoggingMiddleware({
316
+ logger: logger,
317
+ include: {
318
+ usage: false
319
+ }
320
+ });
321
+ mockResult = createMockGenerateResult();
322
+ doGenerate = vi.fn().mockResolvedValue(mockResult);
323
+ return [
324
+ 4,
325
+ (_middleware_wrapGenerate = middleware.wrapGenerate) === null || _middleware_wrapGenerate === void 0 ? void 0 : _middleware_wrapGenerate.call(middleware, {
326
+ doGenerate: doGenerate,
327
+ doStream: vi.fn(),
328
+ params: {},
329
+ model: {}
330
+ })
331
+ ];
332
+ case 1:
333
+ _state.sent();
334
+ expect(logger.debug).toHaveBeenNthCalledWith(2, 'Model request completed', expect.not.objectContaining({
335
+ usage: expect.anything()
336
+ }));
337
+ return [
338
+ 2
339
+ ];
340
+ }
341
+ });
342
+ })();
343
+ });
273
344
  });
274
345
  describe('wrapStream', function() {
275
346
  it('logs stream start on success', function() {
@@ -338,7 +409,7 @@ describe('createLoggingMiddleware', function() {
338
409
  });
339
410
  })();
340
411
  });
341
- it('includes params when verbose is true', function() {
412
+ it('includes params when include.params is true', function() {
342
413
  return _async_to_generator(function() {
343
414
  var _middleware_wrapStream, logger, middleware, mockResult, mockParams, doStream;
344
415
  return _ts_generator(this, function(_state) {
@@ -347,7 +418,9 @@ describe('createLoggingMiddleware', function() {
347
418
  logger = createMockLogger();
348
419
  middleware = createLoggingMiddleware({
349
420
  logger: logger,
350
- verbose: true
421
+ include: {
422
+ params: true
423
+ }
351
424
  });
352
425
  mockResult = createMockStreamResult();
353
426
  mockParams = {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/middleware/__tests__/logging.middleware.test.ts"],"sourcesContent":["import { describe, expect, it, vi } from 'vitest';\n\nimport { createLoggingMiddleware } from '../logging.middleware.js';\n\nfunction createMockLogger() {\n const logger = {\n child: vi.fn(() => logger),\n debug: vi.fn(),\n error: vi.fn(),\n info: vi.fn(),\n warn: vi.fn(),\n };\n return logger;\n}\n\nfunction createMockGenerateResult() {\n return {\n content: [{ type: 'text' as const, text: 'Hello world' }],\n finishReason: 'stop' as const,\n usage: { inputTokens: 10, outputTokens: 20, totalTokens: 30 },\n warnings: [],\n };\n}\n\nfunction createMockStreamResult() {\n return {\n stream: new ReadableStream(),\n warnings: [],\n };\n}\n\ndescribe('createLoggingMiddleware', () => {\n describe('wrapGenerate', () => {\n it('logs request start and completion on success', async () => {\n const logger = createMockLogger();\n const middleware = createLoggingMiddleware({ logger });\n const mockResult = createMockGenerateResult();\n const doGenerate = vi.fn().mockResolvedValue(mockResult);\n\n const result = await middleware.wrapGenerate?.({\n doGenerate,\n doStream: vi.fn(),\n params: {} as never,\n model: {} as never,\n });\n\n expect(logger.debug).toHaveBeenCalledTimes(2);\n expect(logger.debug).toHaveBeenNthCalledWith(1, 'Model request started', {});\n expect(logger.debug).toHaveBeenNthCalledWith(\n 2,\n 'Model request completed',\n expect.objectContaining({\n durationMs: expect.any(Number),\n finishReason: 'stop',\n usage: mockResult.usage,\n }),\n );\n expect(result).toBe(mockResult);\n });\n\n it('logs error on failure', async () => {\n const logger = createMockLogger();\n const middleware = createLoggingMiddleware({ logger });\n const error = new Error('API error');\n const doGenerate = vi.fn().mockRejectedValue(error);\n\n await expect(\n middleware.wrapGenerate?.({\n doGenerate,\n doStream: vi.fn(),\n params: {} as never,\n model: {} as never,\n }),\n ).rejects.toThrow('API error');\n\n expect(logger.debug).toHaveBeenCalledWith('Model request started', {});\n expect(logger.error).toHaveBeenCalledWith(\n 'Model request failed',\n expect.objectContaining({\n durationMs: expect.any(Number),\n error: 'API error',\n }),\n );\n });\n\n it('includes params and content when verbose is true', async () => {\n const logger = createMockLogger();\n const middleware = createLoggingMiddleware({ logger, verbose: true });\n const mockResult = createMockGenerateResult();\n const mockParams = { prompt: 'Hello' };\n const doGenerate = vi.fn().mockResolvedValue(mockResult);\n\n await middleware.wrapGenerate?.({\n doGenerate,\n doStream: vi.fn(),\n params: mockParams as never,\n model: {} as never,\n });\n\n expect(logger.debug).toHaveBeenNthCalledWith(\n 1,\n 'Model request started',\n expect.objectContaining({ params: mockParams }),\n );\n expect(logger.debug).toHaveBeenNthCalledWith(\n 2,\n 'Model request completed',\n expect.objectContaining({ content: mockResult.content }),\n );\n });\n });\n\n describe('wrapStream', () => {\n it('logs stream start on success', async () => {\n const logger = createMockLogger();\n const middleware = createLoggingMiddleware({ logger });\n const mockResult = createMockStreamResult();\n const doStream = vi.fn().mockResolvedValue(mockResult);\n\n const result = await middleware.wrapStream?.({\n doGenerate: vi.fn(),\n doStream,\n params: {} as never,\n model: {} as never,\n });\n\n expect(logger.debug).toHaveBeenCalledWith('Model stream started', {});\n expect(result?.stream).toBe(mockResult.stream);\n });\n\n it('logs error on stream failure', async () => {\n const logger = createMockLogger();\n const middleware = createLoggingMiddleware({ logger });\n const error = new Error('Stream error');\n const doStream = vi.fn().mockRejectedValue(error);\n\n await expect(\n middleware.wrapStream?.({\n doGenerate: vi.fn(),\n doStream,\n params: {} as never,\n model: {} as never,\n }),\n ).rejects.toThrow('Stream error');\n\n expect(logger.error).toHaveBeenCalledWith(\n 'Model stream failed',\n expect.objectContaining({\n durationMs: expect.any(Number),\n error: 'Stream error',\n }),\n );\n });\n\n it('includes params when verbose is true', async () => {\n const logger = createMockLogger();\n const middleware = createLoggingMiddleware({ logger, verbose: true });\n const mockResult = createMockStreamResult();\n const mockParams = { prompt: 'Hello' };\n const doStream = vi.fn().mockResolvedValue(mockResult);\n\n await middleware.wrapStream?.({\n doGenerate: vi.fn(),\n doStream,\n params: mockParams as never,\n model: {} as never,\n });\n\n expect(logger.debug).toHaveBeenCalledWith(\n 'Model stream started',\n expect.objectContaining({ params: mockParams }),\n );\n });\n });\n\n describe('middleware structure', () => {\n it('returns middleware with v2 version', () => {\n const logger = createMockLogger();\n const middleware = createLoggingMiddleware({ logger });\n\n expect(middleware.middlewareVersion).toBe('v2');\n });\n });\n});\n"],"names":["describe","expect","it","vi","createLoggingMiddleware","createMockLogger","logger","child","fn","debug","error","info","warn","createMockGenerateResult","content","type","text","finishReason","usage","inputTokens","outputTokens","totalTokens","warnings","createMockStreamResult","stream","ReadableStream","middleware","mockResult","doGenerate","result","mockResolvedValue","wrapGenerate","doStream","params","model","toHaveBeenCalledTimes","toHaveBeenNthCalledWith","objectContaining","durationMs","any","Number","toBe","Error","mockRejectedValue","rejects","toThrow","toHaveBeenCalledWith","mockParams","verbose","prompt","wrapStream","middlewareVersion"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/middleware/__tests__/logging.middleware.test.ts"],"sourcesContent":["import { describe, expect, it, vi } from 'vitest';\n\nimport { createLoggingMiddleware } from '../logging.middleware.js';\n\nfunction createMockLogger() {\n const logger = {\n child: vi.fn(() => logger),\n debug: vi.fn(),\n error: vi.fn(),\n info: vi.fn(),\n warn: vi.fn(),\n };\n return logger;\n}\n\nfunction createMockGenerateResult() {\n return {\n content: [{ type: 'text' as const, text: 'Hello world' }],\n finishReason: 'stop' as const,\n usage: { inputTokens: 10, outputTokens: 20, totalTokens: 30 },\n warnings: [],\n };\n}\n\nfunction createMockStreamResult() {\n return {\n stream: new ReadableStream(),\n warnings: [],\n };\n}\n\ndescribe('createLoggingMiddleware', () => {\n describe('wrapGenerate', () => {\n it('logs request start and completion on success', async () => {\n const logger = createMockLogger();\n const middleware = createLoggingMiddleware({ logger });\n const mockResult = createMockGenerateResult();\n const doGenerate = vi.fn().mockResolvedValue(mockResult);\n\n const result = await middleware.wrapGenerate?.({\n doGenerate,\n doStream: vi.fn(),\n params: {} as never,\n model: {} as never,\n });\n\n expect(logger.debug).toHaveBeenCalledTimes(2);\n expect(logger.debug).toHaveBeenNthCalledWith(1, 'Model request started', {});\n expect(logger.debug).toHaveBeenNthCalledWith(\n 2,\n 'Model request completed',\n expect.objectContaining({\n durationMs: expect.any(Number),\n finishReason: 'stop',\n usage: mockResult.usage,\n }),\n );\n expect(result).toBe(mockResult);\n });\n\n it('logs error on failure', async () => {\n const logger = createMockLogger();\n const middleware = createLoggingMiddleware({ logger });\n const error = new Error('API error');\n const doGenerate = vi.fn().mockRejectedValue(error);\n\n await expect(\n middleware.wrapGenerate?.({\n doGenerate,\n doStream: vi.fn(),\n params: {} as never,\n model: {} as never,\n }),\n ).rejects.toThrow('API error');\n\n expect(logger.debug).toHaveBeenCalledWith('Model request started', {});\n expect(logger.error).toHaveBeenCalledWith(\n 'Model request failed',\n expect.objectContaining({\n durationMs: expect.any(Number),\n error: 'API error',\n }),\n );\n });\n\n it('includes params when include.params is true', async () => {\n const logger = createMockLogger();\n const middleware = createLoggingMiddleware({ logger, include: { params: true } });\n const mockResult = createMockGenerateResult();\n const mockParams = { prompt: 'Hello' };\n const doGenerate = vi.fn().mockResolvedValue(mockResult);\n\n await middleware.wrapGenerate?.({\n doGenerate,\n doStream: vi.fn(),\n params: mockParams as never,\n model: {} as never,\n });\n\n expect(logger.debug).toHaveBeenNthCalledWith(\n 1,\n 'Model request started',\n expect.objectContaining({ params: mockParams }),\n );\n });\n\n it('includes content when include.content is true', async () => {\n const logger = createMockLogger();\n const middleware = createLoggingMiddleware({ logger, include: { content: true } });\n const mockResult = createMockGenerateResult();\n const doGenerate = vi.fn().mockResolvedValue(mockResult);\n\n await middleware.wrapGenerate?.({\n doGenerate,\n doStream: vi.fn(),\n params: {} as never,\n model: {} as never,\n });\n\n expect(logger.debug).toHaveBeenNthCalledWith(\n 2,\n 'Model request completed',\n expect.objectContaining({ content: mockResult.content }),\n );\n });\n\n it('excludes usage when include.usage is false', async () => {\n const logger = createMockLogger();\n const middleware = createLoggingMiddleware({ logger, include: { usage: false } });\n const mockResult = createMockGenerateResult();\n const doGenerate = vi.fn().mockResolvedValue(mockResult);\n\n await middleware.wrapGenerate?.({\n doGenerate,\n doStream: vi.fn(),\n params: {} as never,\n model: {} as never,\n });\n\n expect(logger.debug).toHaveBeenNthCalledWith(\n 2,\n 'Model request completed',\n expect.not.objectContaining({ usage: expect.anything() }),\n );\n });\n });\n\n describe('wrapStream', () => {\n it('logs stream start on success', async () => {\n const logger = createMockLogger();\n const middleware = createLoggingMiddleware({ logger });\n const mockResult = createMockStreamResult();\n const doStream = vi.fn().mockResolvedValue(mockResult);\n\n const result = await middleware.wrapStream?.({\n doGenerate: vi.fn(),\n doStream,\n params: {} as never,\n model: {} as never,\n });\n\n expect(logger.debug).toHaveBeenCalledWith('Model stream started', {});\n expect(result?.stream).toBe(mockResult.stream);\n });\n\n it('logs error on stream failure', async () => {\n const logger = createMockLogger();\n const middleware = createLoggingMiddleware({ logger });\n const error = new Error('Stream error');\n const doStream = vi.fn().mockRejectedValue(error);\n\n await expect(\n middleware.wrapStream?.({\n doGenerate: vi.fn(),\n doStream,\n params: {} as never,\n model: {} as never,\n }),\n ).rejects.toThrow('Stream error');\n\n expect(logger.error).toHaveBeenCalledWith(\n 'Model stream failed',\n expect.objectContaining({\n durationMs: expect.any(Number),\n error: 'Stream error',\n }),\n );\n });\n\n it('includes params when include.params is true', async () => {\n const logger = createMockLogger();\n const middleware = createLoggingMiddleware({ logger, include: { params: true } });\n const mockResult = createMockStreamResult();\n const mockParams = { prompt: 'Hello' };\n const doStream = vi.fn().mockResolvedValue(mockResult);\n\n await middleware.wrapStream?.({\n doGenerate: vi.fn(),\n doStream,\n params: mockParams as never,\n model: {} as never,\n });\n\n expect(logger.debug).toHaveBeenCalledWith(\n 'Model stream started',\n expect.objectContaining({ params: mockParams }),\n );\n });\n });\n\n describe('middleware structure', () => {\n it('returns middleware with v2 version', () => {\n const logger = createMockLogger();\n const middleware = createLoggingMiddleware({ logger });\n\n expect(middleware.middlewareVersion).toBe('v2');\n });\n });\n});\n"],"names":["describe","expect","it","vi","createLoggingMiddleware","createMockLogger","logger","child","fn","debug","error","info","warn","createMockGenerateResult","content","type","text","finishReason","usage","inputTokens","outputTokens","totalTokens","warnings","createMockStreamResult","stream","ReadableStream","middleware","mockResult","doGenerate","result","mockResolvedValue","wrapGenerate","doStream","params","model","toHaveBeenCalledTimes","toHaveBeenNthCalledWith","objectContaining","durationMs","any","Number","toBe","Error","mockRejectedValue","rejects","toThrow","toHaveBeenCalledWith","mockParams","include","prompt","not","anything","wrapStream","middlewareVersion"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAASA,QAAQ,EAAEC,MAAM,EAAEC,EAAE,EAAEC,EAAE,QAAQ,SAAS;AAElD,SAASC,uBAAuB,QAAQ,2BAA2B;AAEnE,SAASC;IACL,IAAMC,SAAS;QACXC,OAAOJ,GAAGK,EAAE,CAAC;mBAAMF;;QACnBG,OAAON,GAAGK,EAAE;QACZE,OAAOP,GAAGK,EAAE;QACZG,MAAMR,GAAGK,EAAE;QACXI,MAAMT,GAAGK,EAAE;IACf;IACA,OAAOF;AACX;AAEA,SAASO;IACL,OAAO;QACHC,SAAS;YAAC;gBAAEC,MAAM;gBAAiBC,MAAM;YAAc;SAAE;QACzDC,cAAc;QACdC,OAAO;YAAEC,aAAa;YAAIC,cAAc;YAAIC,aAAa;QAAG;QAC5DC,UAAU,EAAE;IAChB;AACJ;AAEA,SAASC;IACL,OAAO;QACHC,QAAQ,IAAIC;QACZH,UAAU,EAAE;IAChB;AACJ;AAEAtB,SAAS,2BAA2B;IAChCA,SAAS,gBAAgB;QACrBE,GAAG,gDAAgD;;oBAM1BwB,0BALfpB,QACAoB,YACAC,YACAC,YAEAC;;;;4BALAvB,SAASD;4BACTqB,aAAatB,wBAAwB;gCAAEE,QAAAA;4BAAO;4BAC9CqB,aAAad;4BACbe,aAAazB,GAAGK,EAAE,GAAGsB,iBAAiB,CAACH;4BAE9B;;iCAAMD,2BAAAA,WAAWK,YAAY,cAAvBL,+CAAAA,8BAAAA,YAA0B;oCAC3CE,YAAAA;oCACAI,UAAU7B,GAAGK,EAAE;oCACfyB,QAAQ,CAAC;oCACTC,OAAO,CAAC;gCACZ;;;4BALML,SAAS;4BAOf5B,OAAOK,OAAOG,KAAK,EAAE0B,qBAAqB,CAAC;4BAC3ClC,OAAOK,OAAOG,KAAK,EAAE2B,uBAAuB,CAAC,GAAG,yBAAyB,CAAC;4BAC1EnC,OAAOK,OAAOG,KAAK,EAAE2B,uBAAuB,CACxC,GACA,2BACAnC,OAAOoC,gBAAgB,CAAC;gCACpBC,YAAYrC,OAAOsC,GAAG,CAACC;gCACvBvB,cAAc;gCACdC,OAAOS,WAAWT,KAAK;4BAC3B;4BAEJjB,OAAO4B,QAAQY,IAAI,CAACd;;;;;;YACxB;;QAEAzB,GAAG,yBAAyB;;oBAOpBwB,0BANEpB,QACAoB,YACAhB,OACAkB;;;;4BAHAtB,SAASD;4BACTqB,aAAatB,wBAAwB;gCAAEE,QAAAA;4BAAO;4BAC9CI,QAAQ,IAAIgC,MAAM;4BAClBd,aAAazB,GAAGK,EAAE,GAAGmC,iBAAiB,CAACjC;4BAE7C;;gCAAMT,QACFyB,2BAAAA,WAAWK,YAAY,cAAvBL,+CAAAA,8BAAAA,YAA0B;oCACtBE,YAAAA;oCACAI,UAAU7B,GAAGK,EAAE;oCACfyB,QAAQ,CAAC;oCACTC,OAAO,CAAC;gCACZ,IACFU,OAAO,CAACC,OAAO,CAAC;;;4BAPlB;4BASA5C,OAAOK,OAAOG,KAAK,EAAEqC,oBAAoB,CAAC,yBAAyB,CAAC;4BACpE7C,OAAOK,OAAOI,KAAK,EAAEoC,oBAAoB,CACrC,wBACA7C,OAAOoC,gBAAgB,CAAC;gCACpBC,YAAYrC,OAAOsC,GAAG,CAACC;gCACvB9B,OAAO;4BACX;;;;;;YAER;;QAEAR,GAAG,+CAA+C;;oBAOxCwB,0BANApB,QACAoB,YACAC,YACAoB,YACAnB;;;;4BAJAtB,SAASD;4BACTqB,aAAatB,wBAAwB;gCAAEE,QAAAA;gCAAQ0C,SAAS;oCAAEf,QAAQ;gCAAK;4BAAE;4BACzEN,aAAad;4BACbkC,aAAa;gCAAEE,QAAQ;4BAAQ;4BAC/BrB,aAAazB,GAAGK,EAAE,GAAGsB,iBAAiB,CAACH;4BAE7C;;iCAAMD,2BAAAA,WAAWK,YAAY,cAAvBL,+CAAAA,8BAAAA,YAA0B;oCAC5BE,YAAAA;oCACAI,UAAU7B,GAAGK,EAAE;oCACfyB,QAAQc;oCACRb,OAAO,CAAC;gCACZ;;;4BALA;4BAOAjC,OAAOK,OAAOG,KAAK,EAAE2B,uBAAuB,CACxC,GACA,yBACAnC,OAAOoC,gBAAgB,CAAC;gCAAEJ,QAAQc;4BAAW;;;;;;YAErD;;QAEA7C,GAAG,iDAAiD;;oBAM1CwB,0BALApB,QACAoB,YACAC,YACAC;;;;4BAHAtB,SAASD;4BACTqB,aAAatB,wBAAwB;gCAAEE,QAAAA;gCAAQ0C,SAAS;oCAAElC,SAAS;gCAAK;4BAAE;4BAC1Ea,aAAad;4BACbe,aAAazB,GAAGK,EAAE,GAAGsB,iBAAiB,CAACH;4BAE7C;;iCAAMD,2BAAAA,WAAWK,YAAY,cAAvBL,+CAAAA,8BAAAA,YAA0B;oCAC5BE,YAAAA;oCACAI,UAAU7B,GAAGK,EAAE;oCACfyB,QAAQ,CAAC;oCACTC,OAAO,CAAC;gCACZ;;;4BALA;4BAOAjC,OAAOK,OAAOG,KAAK,EAAE2B,uBAAuB,CACxC,GACA,2BACAnC,OAAOoC,gBAAgB,CAAC;gCAAEvB,SAASa,WAAWb,OAAO;4BAAC;;;;;;YAE9D;;QAEAZ,GAAG,8CAA8C;;oBAMvCwB,0BALApB,QACAoB,YACAC,YACAC;;;;4BAHAtB,SAASD;4BACTqB,aAAatB,wBAAwB;gCAAEE,QAAAA;gCAAQ0C,SAAS;oCAAE9B,OAAO;gCAAM;4BAAE;4BACzES,aAAad;4BACbe,aAAazB,GAAGK,EAAE,GAAGsB,iBAAiB,CAACH;4BAE7C;;iCAAMD,2BAAAA,WAAWK,YAAY,cAAvBL,+CAAAA,8BAAAA,YAA0B;oCAC5BE,YAAAA;oCACAI,UAAU7B,GAAGK,EAAE;oCACfyB,QAAQ,CAAC;oCACTC,OAAO,CAAC;gCACZ;;;4BALA;4BAOAjC,OAAOK,OAAOG,KAAK,EAAE2B,uBAAuB,CACxC,GACA,2BACAnC,OAAOiD,GAAG,CAACb,gBAAgB,CAAC;gCAAEnB,OAAOjB,OAAOkD,QAAQ;4BAAG;;;;;;YAE/D;;IACJ;IAEAnD,SAAS,cAAc;QACnBE,GAAG,gCAAgC;;oBAMVwB,wBALfpB,QACAoB,YACAC,YACAK,UAEAH;;;;4BALAvB,SAASD;4BACTqB,aAAatB,wBAAwB;gCAAEE,QAAAA;4BAAO;4BAC9CqB,aAAaJ;4BACbS,WAAW7B,GAAGK,EAAE,GAAGsB,iBAAiB,CAACH;4BAE5B;;iCAAMD,yBAAAA,WAAW0B,UAAU,cAArB1B,6CAAAA,4BAAAA,YAAwB;oCACzCE,YAAYzB,GAAGK,EAAE;oCACjBwB,UAAAA;oCACAC,QAAQ,CAAC;oCACTC,OAAO,CAAC;gCACZ;;;4BALML,SAAS;4BAOf5B,OAAOK,OAAOG,KAAK,EAAEqC,oBAAoB,CAAC,wBAAwB,CAAC;4BACnE7C,OAAO4B,mBAAAA,6BAAAA,OAAQL,MAAM,EAAEiB,IAAI,CAACd,WAAWH,MAAM;;;;;;YACjD;;QAEAtB,GAAG,gCAAgC;;oBAO3BwB,wBANEpB,QACAoB,YACAhB,OACAsB;;;;4BAHA1B,SAASD;4BACTqB,aAAatB,wBAAwB;gCAAEE,QAAAA;4BAAO;4BAC9CI,QAAQ,IAAIgC,MAAM;4BAClBV,WAAW7B,GAAGK,EAAE,GAAGmC,iBAAiB,CAACjC;4BAE3C;;gCAAMT,QACFyB,yBAAAA,WAAW0B,UAAU,cAArB1B,6CAAAA,4BAAAA,YAAwB;oCACpBE,YAAYzB,GAAGK,EAAE;oCACjBwB,UAAAA;oCACAC,QAAQ,CAAC;oCACTC,OAAO,CAAC;gCACZ,IACFU,OAAO,CAACC,OAAO,CAAC;;;4BAPlB;4BASA5C,OAAOK,OAAOI,KAAK,EAAEoC,oBAAoB,CACrC,uBACA7C,OAAOoC,gBAAgB,CAAC;gCACpBC,YAAYrC,OAAOsC,GAAG,CAACC;gCACvB9B,OAAO;4BACX;;;;;;YAER;;QAEAR,GAAG,+CAA+C;;oBAOxCwB,wBANApB,QACAoB,YACAC,YACAoB,YACAf;;;;4BAJA1B,SAASD;4BACTqB,aAAatB,wBAAwB;gCAAEE,QAAAA;gCAAQ0C,SAAS;oCAAEf,QAAQ;gCAAK;4BAAE;4BACzEN,aAAaJ;4BACbwB,aAAa;gCAAEE,QAAQ;4BAAQ;4BAC/BjB,WAAW7B,GAAGK,EAAE,GAAGsB,iBAAiB,CAACH;4BAE3C;;iCAAMD,yBAAAA,WAAW0B,UAAU,cAArB1B,6CAAAA,4BAAAA,YAAwB;oCAC1BE,YAAYzB,GAAGK,EAAE;oCACjBwB,UAAAA;oCACAC,QAAQc;oCACRb,OAAO,CAAC;gCACZ;;;4BALA;4BAOAjC,OAAOK,OAAOG,KAAK,EAAEqC,oBAAoB,CACrC,wBACA7C,OAAOoC,gBAAgB,CAAC;gCAAEJ,QAAQc;4BAAW;;;;;;YAErD;;IACJ;IAEA/C,SAAS,wBAAwB;QAC7BE,GAAG,sCAAsC;YACrC,IAAMI,SAASD;YACf,IAAMqB,aAAatB,wBAAwB;gBAAEE,QAAAA;YAAO;YAEpDL,OAAOyB,WAAW2B,iBAAiB,EAAEZ,IAAI,CAAC;QAC9C;IACJ;AACJ"}
@@ -1,9 +1,17 @@
1
1
  import type { LoggerPort } from '@jterrazz/logger';
2
2
  import type { LanguageModelMiddleware } from 'ai';
3
+ export interface LoggingMiddlewareInclude {
4
+ /** Include request params in logs */
5
+ params?: boolean;
6
+ /** Include response content in logs */
7
+ content?: boolean;
8
+ /** Include token usage in logs */
9
+ usage?: boolean;
10
+ }
3
11
  export interface LoggingMiddlewareOptions {
4
12
  logger: LoggerPort;
5
- /** Include request/response details in logs (default: false) */
6
- verbose?: boolean;
13
+ /** Select which fields to include in logs (default: { usage: true }) */
14
+ include?: LoggingMiddlewareInclude;
7
15
  }
8
16
  /**
9
17
  * Creates AI SDK middleware that logs model requests and responses.
@@ -190,7 +190,8 @@ function _ts_generator(thisArg, body) {
190
190
  * });
191
191
  * ```
192
192
  */ export function createLoggingMiddleware(options) {
193
- var logger = options.logger, _options_verbose = options.verbose, verbose = _options_verbose === void 0 ? false : _options_verbose;
193
+ var logger = options.logger, _options_include = options.include, include = _options_include === void 0 ? {} : _options_include;
194
+ var includeParams = include.params, includeContent = include.content, tmp = include.usage, includeUsage = tmp === void 0 ? true : tmp;
194
195
  return {
195
196
  middlewareVersion: 'v2',
196
197
  wrapGenerate: function(param) {
@@ -201,7 +202,7 @@ function _ts_generator(thisArg, body) {
201
202
  switch(_state.label){
202
203
  case 0:
203
204
  startTime = Date.now();
204
- logger.debug('Model request started', _object_spread({}, verbose && {
205
+ logger.debug('Model request started', _object_spread({}, includeParams && {
205
206
  params: params
206
207
  }));
207
208
  _state.label = 1;
@@ -220,9 +221,10 @@ function _ts_generator(thisArg, body) {
220
221
  result = _state.sent();
221
222
  logger.debug('Model request completed', _object_spread({
222
223
  durationMs: Date.now() - startTime,
223
- finishReason: result.finishReason,
224
+ finishReason: result.finishReason
225
+ }, includeUsage && {
224
226
  usage: result.usage
225
- }, verbose && {
227
+ }, includeContent && {
226
228
  content: result.content
227
229
  }));
228
230
  return [
@@ -252,7 +254,7 @@ function _ts_generator(thisArg, body) {
252
254
  switch(_state.label){
253
255
  case 0:
254
256
  startTime = Date.now();
255
- logger.debug('Model stream started', _object_spread({}, verbose && {
257
+ logger.debug('Model stream started', _object_spread({}, includeParams && {
256
258
  params: params
257
259
  }));
258
260
  _state.label = 1;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/middleware/logging.middleware.ts"],"sourcesContent":["import type { LoggerPort } from '@jterrazz/logger';\nimport type { LanguageModelMiddleware } from 'ai';\n\nexport interface LoggingMiddlewareOptions {\n logger: LoggerPort;\n /** Include request/response details in logs (default: false) */\n verbose?: boolean;\n}\n\n/**\n * Creates AI SDK middleware that logs model requests and responses.\n *\n * @example\n * ```ts\n * import { wrapLanguageModel } from 'ai';\n *\n * const model = wrapLanguageModel({\n * model: openrouter('anthropic/claude-sonnet-4-20250514'),\n * middleware: createLoggingMiddleware({ logger }),\n * });\n * ```\n */\nexport function createLoggingMiddleware(\n options: LoggingMiddlewareOptions,\n): LanguageModelMiddleware {\n const { logger, verbose = false } = options;\n\n return {\n middlewareVersion: 'v2',\n\n wrapGenerate: async ({ doGenerate, params }) => {\n const startTime = Date.now();\n\n logger.debug('Model request started', {\n ...(verbose && { params }),\n });\n\n try {\n const result = await doGenerate();\n\n logger.debug('Model request completed', {\n durationMs: Date.now() - startTime,\n finishReason: result.finishReason,\n usage: result.usage,\n ...(verbose && { content: result.content }),\n });\n\n return result;\n } catch (error) {\n logger.error('Model request failed', {\n durationMs: Date.now() - startTime,\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n throw error;\n }\n },\n\n wrapStream: async ({ doStream, params }) => {\n const startTime = Date.now();\n\n logger.debug('Model stream started', {\n ...(verbose && { params }),\n });\n\n try {\n const result = await doStream();\n\n return {\n ...result,\n stream: result.stream,\n };\n } catch (error) {\n logger.error('Model stream failed', {\n durationMs: Date.now() - startTime,\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n throw error;\n }\n },\n };\n}\n"],"names":["createLoggingMiddleware","options","logger","verbose","middlewareVersion","wrapGenerate","doGenerate","params","startTime","result","error","Date","now","debug","durationMs","finishReason","usage","content","Error","message","wrapStream","doStream","stream"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AASA;;;;;;;;;;;;CAYC,GACD,OAAO,SAASA,wBACZC,OAAiC;IAEjC,IAAQC,SAA4BD,QAA5BC,2BAA4BD,QAApBE,SAAAA,wCAAU;IAE1B,OAAO;QACHC,mBAAmB;QAEnBC,cAAc;gBAASC,mBAAAA,YAAYC,eAAAA;;oBACzBC,WAOIC,QAUDC;;;;4BAjBHF,YAAYG,KAAKC,GAAG;4BAE1BV,OAAOW,KAAK,CAAC,yBAAyB,mBAC9BV,WAAW;gCAAEI,QAAAA;4BAAO;;;;;;;;;4BAIT;;gCAAMD;;;4BAAfG,SAAS;4BAEfP,OAAOW,KAAK,CAAC,2BAA2B;gCACpCC,YAAYH,KAAKC,GAAG,KAAKJ;gCACzBO,cAAcN,OAAOM,YAAY;gCACjCC,OAAOP,OAAOO,KAAK;+BACfb,WAAW;gCAAEc,SAASR,OAAOQ,OAAO;4BAAC;4BAG7C;;gCAAOR;;;4BACFC;4BACLR,OAAOQ,KAAK,CAAC,wBAAwB;gCACjCI,YAAYH,KAAKC,GAAG,KAAKJ;gCACzBE,OAAOA,AAAK,YAALA,OAAiBQ,SAAQR,MAAMS,OAAO,GAAG;4BACpD;4BACA,MAAMT;;;;;;;YAEd;;QAEAU,YAAY;gBAASC,iBAAAA,UAAUd,eAAAA;;oBACrBC,WAOIC,QAMDC;;;;4BAbHF,YAAYG,KAAKC,GAAG;4BAE1BV,OAAOW,KAAK,CAAC,wBAAwB,mBAC7BV,WAAW;gCAAEI,QAAAA;4BAAO;;;;;;;;;4BAIT;;gCAAMc;;;4BAAfZ,SAAS;4BAEf;;gCAAO,wCACAA;oCACHa,QAAQb,OAAOa,MAAM;;;;4BAEpBZ;4BACLR,OAAOQ,KAAK,CAAC,uBAAuB;gCAChCI,YAAYH,KAAKC,GAAG,KAAKJ;gCACzBE,OAAOA,AAAK,YAALA,OAAiBQ,SAAQR,MAAMS,OAAO,GAAG;4BACpD;4BACA,MAAMT;;;;;;;YAEd;;IACJ;AACJ"}
1
+ {"version":3,"sources":["../../src/middleware/logging.middleware.ts"],"sourcesContent":["import type { LoggerPort } from '@jterrazz/logger';\nimport type { LanguageModelMiddleware } from 'ai';\n\nexport interface LoggingMiddlewareInclude {\n /** Include request params in logs */\n params?: boolean;\n /** Include response content in logs */\n content?: boolean;\n /** Include token usage in logs */\n usage?: boolean;\n}\n\nexport interface LoggingMiddlewareOptions {\n logger: LoggerPort;\n /** Select which fields to include in logs (default: { usage: true }) */\n include?: LoggingMiddlewareInclude;\n}\n\n/**\n * Creates AI SDK middleware that logs model requests and responses.\n *\n * @example\n * ```ts\n * import { wrapLanguageModel } from 'ai';\n *\n * const model = wrapLanguageModel({\n * model: openrouter('anthropic/claude-sonnet-4-20250514'),\n * middleware: createLoggingMiddleware({ logger }),\n * });\n * ```\n */\nexport function createLoggingMiddleware(\n options: LoggingMiddlewareOptions,\n): LanguageModelMiddleware {\n const { logger, include = {} } = options;\n const { params: includeParams, content: includeContent, usage: includeUsage = true } = include;\n\n return {\n middlewareVersion: 'v2',\n\n wrapGenerate: async ({ doGenerate, params }) => {\n const startTime = Date.now();\n\n logger.debug('Model request started', {\n ...(includeParams && { params }),\n });\n\n try {\n const result = await doGenerate();\n\n logger.debug('Model request completed', {\n durationMs: Date.now() - startTime,\n finishReason: result.finishReason,\n ...(includeUsage && { usage: result.usage }),\n ...(includeContent && { content: result.content }),\n });\n\n return result;\n } catch (error) {\n logger.error('Model request failed', {\n durationMs: Date.now() - startTime,\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n throw error;\n }\n },\n\n wrapStream: async ({ doStream, params }) => {\n const startTime = Date.now();\n\n logger.debug('Model stream started', {\n ...(includeParams && { params }),\n });\n\n try {\n const result = await doStream();\n\n return {\n ...result,\n stream: result.stream,\n };\n } catch (error) {\n logger.error('Model stream failed', {\n durationMs: Date.now() - startTime,\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n throw error;\n }\n },\n };\n}\n"],"names":["createLoggingMiddleware","options","logger","include","params","includeParams","content","includeContent","includeUsage","usage","middlewareVersion","wrapGenerate","doGenerate","startTime","result","error","Date","now","debug","durationMs","finishReason","Error","message","wrapStream","doStream","stream"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkBA;;;;;;;;;;;;CAYC,GACD,OAAO,SAASA,wBACZC,OAAiC;IAEjC,IAAQC,SAAyBD,QAAzBC,2BAAyBD,QAAjBE,SAAAA,wCAAU,CAAC;IAC3B,IAAQC,AAAQC,gBAAuEF,QAA/EC,QAAuBE,AAASC,iBAA+CJ,QAAxDG,SAAgCE,MAAwBL,QAA/BM,OAAOD,eAAAA,iBAAe,OAAfA;IAE/D,OAAO;QACHE,mBAAmB;QAEnBC,cAAc;gBAASC,mBAAAA,YAAYR,eAAAA;;oBACzBS,WAOIC,QAUDC;;;;4BAjBHF,YAAYG,KAAKC,GAAG;4BAE1Bf,OAAOgB,KAAK,CAAC,yBAAyB,mBAC9Bb,iBAAiB;gCAAED,QAAAA;4BAAO;;;;;;;;;4BAIf;;gCAAMQ;;;4BAAfE,SAAS;4BAEfZ,OAAOgB,KAAK,CAAC,2BAA2B;gCACpCC,YAAYH,KAAKC,GAAG,KAAKJ;gCACzBO,cAAcN,OAAOM,YAAY;+BAC7BZ,gBAAgB;gCAAEC,OAAOK,OAAOL,KAAK;4BAAC,GACtCF,kBAAkB;gCAAED,SAASQ,OAAOR,OAAO;4BAAC;4BAGpD;;gCAAOQ;;;4BACFC;4BACLb,OAAOa,KAAK,CAAC,wBAAwB;gCACjCI,YAAYH,KAAKC,GAAG,KAAKJ;gCACzBE,OAAOA,AAAK,YAALA,OAAiBM,SAAQN,MAAMO,OAAO,GAAG;4BACpD;4BACA,MAAMP;;;;;;;YAEd;;QAEAQ,YAAY;gBAASC,iBAAAA,UAAUpB,eAAAA;;oBACrBS,WAOIC,QAMDC;;;;4BAbHF,YAAYG,KAAKC,GAAG;4BAE1Bf,OAAOgB,KAAK,CAAC,wBAAwB,mBAC7Bb,iBAAiB;gCAAED,QAAAA;4BAAO;;;;;;;;;4BAIf;;gCAAMoB;;;4BAAfV,SAAS;4BAEf;;gCAAO,wCACAA;oCACHW,QAAQX,OAAOW,MAAM;;;;4BAEpBV;4BACLb,OAAOa,KAAK,CAAC,uBAAuB;gCAChCI,YAAYH,KAAKC,GAAG,KAAKJ;gCACzBE,OAAOA,AAAK,YAALA,OAAiBM,SAAQN,MAAMO,OAAO,GAAG;4BACpD;4BACA,MAAMP;;;;;;;YAEd;;IACJ;AACJ"}
@@ -1,3 +1,55 @@
1
+ function _define_property(obj, key, value) {
2
+ if (key in obj) {
3
+ Object.defineProperty(obj, key, {
4
+ value: value,
5
+ enumerable: true,
6
+ configurable: true,
7
+ writable: true
8
+ });
9
+ } else {
10
+ obj[key] = value;
11
+ }
12
+ return obj;
13
+ }
14
+ function _object_spread(target) {
15
+ for(var i = 1; i < arguments.length; i++){
16
+ var source = arguments[i] != null ? arguments[i] : {};
17
+ var ownKeys = Object.keys(source);
18
+ if (typeof Object.getOwnPropertySymbols === "function") {
19
+ ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
20
+ return Object.getOwnPropertyDescriptor(source, sym).enumerable;
21
+ }));
22
+ }
23
+ ownKeys.forEach(function(key) {
24
+ _define_property(target, key, source[key]);
25
+ });
26
+ }
27
+ return target;
28
+ }
29
+ function ownKeys(object, enumerableOnly) {
30
+ var keys = Object.keys(object);
31
+ if (Object.getOwnPropertySymbols) {
32
+ var symbols = Object.getOwnPropertySymbols(object);
33
+ if (enumerableOnly) {
34
+ symbols = symbols.filter(function(sym) {
35
+ return Object.getOwnPropertyDescriptor(object, sym).enumerable;
36
+ });
37
+ }
38
+ keys.push.apply(keys, symbols);
39
+ }
40
+ return keys;
41
+ }
42
+ function _object_spread_props(target, source) {
43
+ source = source != null ? source : {};
44
+ if (Object.getOwnPropertyDescriptors) {
45
+ Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
46
+ } else {
47
+ ownKeys(Object(source)).forEach(function(key) {
48
+ Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
49
+ });
50
+ }
51
+ return target;
52
+ }
1
53
  import { describe, expect, it } from 'vitest';
2
54
  import { z } from 'zod/v4';
3
55
  import { parseObject, ParseObjectError } from '../parse-object.js';
@@ -133,9 +185,20 @@ describe('parseObject', function() {
133
185
  });
134
186
  it('throws ParseObjectError for unsupported schema type', function() {
135
187
  var text = 'test';
188
+ var schema = z.date();
189
+ expect(function() {
190
+ return parseObject(text, schema);
191
+ }).toThrow(ParseObjectError);
192
+ });
193
+ it('throws ParseObjectError for union when no object or array found', function() {
194
+ var text = 'just plain text';
136
195
  var schema = z.union([
137
- z.string(),
138
- z.number()
196
+ z.object({
197
+ type: z.literal('a')
198
+ }),
199
+ z.object({
200
+ type: z.literal('b')
201
+ })
139
202
  ]);
140
203
  expect(function() {
141
204
  return parseObject(text, schema);
@@ -188,6 +251,183 @@ describe('parseObject', function() {
188
251
  expect(result).toEqual(validArticle);
189
252
  });
190
253
  });
254
+ describe('union types', function() {
255
+ it('parses z.union - variant A', function() {
256
+ var schema = z.union([
257
+ z.object({
258
+ type: z.literal('a'),
259
+ value: z.string()
260
+ }),
261
+ z.object({
262
+ type: z.literal('b'),
263
+ count: z.number()
264
+ })
265
+ ]);
266
+ var text = '{"type": "a", "value": "hello"}';
267
+ expect(parseObject(text, schema)).toEqual({
268
+ type: 'a',
269
+ value: 'hello'
270
+ });
271
+ });
272
+ it('parses z.union - variant B', function() {
273
+ var schema = z.union([
274
+ z.object({
275
+ type: z.literal('a'),
276
+ value: z.string()
277
+ }),
278
+ z.object({
279
+ type: z.literal('b'),
280
+ count: z.number()
281
+ })
282
+ ]);
283
+ var text = '{"type": "b", "count": 42}';
284
+ expect(parseObject(text, schema)).toEqual({
285
+ type: 'b',
286
+ count: 42
287
+ });
288
+ });
289
+ it('parses z.discriminatedUnion', function() {
290
+ var schema = z.discriminatedUnion('action', [
291
+ z.object({
292
+ action: z.literal('join'),
293
+ eventId: z.string()
294
+ }),
295
+ z.object({
296
+ action: z.literal('create'),
297
+ name: z.string()
298
+ })
299
+ ]);
300
+ var text = '```json\n{"action": "create", "name": "Test"}\n```';
301
+ expect(parseObject(text, schema)).toEqual({
302
+ action: 'create',
303
+ name: 'Test'
304
+ });
305
+ });
306
+ it('parses discriminated union from surrounding prose', function() {
307
+ var schema = z.discriminatedUnion('action', [
308
+ z.object({
309
+ action: z.literal('join'),
310
+ eventId: z.string()
311
+ }),
312
+ z.object({
313
+ action: z.literal('create'),
314
+ name: z.string()
315
+ })
316
+ ]);
317
+ var text = 'Here is the result: {"action": "join", "eventId": "evt-123"} - done';
318
+ expect(parseObject(text, schema)).toEqual({
319
+ action: 'join',
320
+ eventId: 'evt-123'
321
+ });
322
+ });
323
+ it('parses union of arrays', function() {
324
+ var schema = z.union([
325
+ z.array(z.string()),
326
+ z.array(z.number())
327
+ ]);
328
+ var text = '["a", "b", "c"]';
329
+ expect(parseObject(text, schema)).toEqual([
330
+ 'a',
331
+ 'b',
332
+ 'c'
333
+ ]);
334
+ });
335
+ it('throws when union variant does not match', function() {
336
+ var schema = z.discriminatedUnion('action', [
337
+ z.object({
338
+ action: z.literal('join'),
339
+ eventId: z.string()
340
+ }),
341
+ z.object({
342
+ action: z.literal('create'),
343
+ name: z.string()
344
+ })
345
+ ]);
346
+ var text = '{"action": "delete", "id": "123"}';
347
+ expect(function() {
348
+ return parseObject(text, schema);
349
+ }).toThrow(ParseObjectError);
350
+ });
351
+ });
352
+ describe('wrapper types', function() {
353
+ it('parses z.optional wrapping an object', function() {
354
+ var schema = z.object({
355
+ name: z.string()
356
+ }).optional();
357
+ var text = '{"name": "test"}';
358
+ expect(parseObject(text, schema)).toEqual({
359
+ name: 'test'
360
+ });
361
+ });
362
+ it('parses z.nullable wrapping an object', function() {
363
+ var schema = z.object({
364
+ name: z.string()
365
+ }).nullable();
366
+ var text = '{"name": "test"}';
367
+ expect(parseObject(text, schema)).toEqual({
368
+ name: 'test'
369
+ });
370
+ });
371
+ it('parses z.default wrapping an object', function() {
372
+ var schema = z.object({
373
+ name: z.string()
374
+ })["default"]({
375
+ name: 'default'
376
+ });
377
+ var text = '{"name": "custom"}';
378
+ expect(parseObject(text, schema)).toEqual({
379
+ name: 'custom'
380
+ });
381
+ });
382
+ it('parses schema with .transform()', function() {
383
+ var schema = z.object({
384
+ value: z.string()
385
+ }).transform(function(obj) {
386
+ return _object_spread_props(_object_spread({}, obj), {
387
+ transformed: true
388
+ });
389
+ });
390
+ var text = '{"value": "test"}';
391
+ var result = parseObject(text, schema);
392
+ expect(result).toEqual({
393
+ value: 'test',
394
+ transformed: true
395
+ });
396
+ });
397
+ it('parses schema with .refine()', function() {
398
+ var schema = z.object({
399
+ value: z.number()
400
+ }).refine(function(obj) {
401
+ return obj.value > 0;
402
+ }, {
403
+ message: 'Value must be positive'
404
+ });
405
+ var text = '{"value": 42}';
406
+ expect(parseObject(text, schema)).toEqual({
407
+ value: 42
408
+ });
409
+ });
410
+ it('parses deeply nested wrapper types', function() {
411
+ var schema = z.object({
412
+ name: z.string()
413
+ }).optional().nullable()["default"]({
414
+ name: 'default'
415
+ });
416
+ var text = '{"name": "nested"}';
417
+ expect(parseObject(text, schema)).toEqual({
418
+ name: 'nested'
419
+ });
420
+ });
421
+ it('parses optional array', function() {
422
+ var schema = z.array(z.string()).optional();
423
+ var text = '["a", "b", "c"]';
424
+ expect(parseObject(text, schema)).toEqual([
425
+ 'a',
426
+ 'b',
427
+ 'c'
428
+ ]);
429
+ });
430
+ });
191
431
  });
192
432
 
193
433
  //# sourceMappingURL=parse-object.test.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/parsing/__tests__/parse-object.test.ts"],"sourcesContent":["import { describe, expect, it } from 'vitest';\nimport { z } from 'zod/v4';\n\nimport { parseObject, ParseObjectError } from '../parse-object.js';\n\nconst articleSchema = z.object({\n content: z.string(),\n tags: z.array(z.string()),\n title: z.string(),\n});\n\nconst validArticle = {\n content: 'Test content',\n tags: ['test', 'ai'],\n title: 'Test Article',\n};\n\nconst validArticleJson = JSON.stringify(validArticle);\n\ndescribe('parseObject', () => {\n describe('object parsing', () => {\n it('parses valid JSON object', () => {\n const text = validArticleJson;\n const result = parseObject(text, articleSchema);\n expect(result).toEqual(validArticle);\n });\n\n it('extracts JSON object from surrounding prose', () => {\n const text = `Here's the article: ${validArticleJson} - end of article`;\n const result = parseObject(text, articleSchema);\n expect(result).toEqual(validArticle);\n });\n\n it('parses JSON from markdown code block', () => {\n const text = `\\`\\`\\`json\\n${validArticleJson}\\n\\`\\`\\``;\n const result = parseObject(text, articleSchema);\n expect(result).toEqual(validArticle);\n });\n\n it('handles newlines in JSON values', () => {\n const text = `{\n \"content\": \"Test\\\\ncontent\\\\nwith\\\\nnewlines\",\n \"tags\": [\"test\", \"ai\"],\n \"title\": \"Test\\\\nArticle\"\n }`;\n const result = parseObject(text, articleSchema);\n expect(result).toEqual({\n content: 'Test\\ncontent\\nwith\\nnewlines',\n tags: ['test', 'ai'],\n title: 'Test\\nArticle',\n });\n });\n\n it('handles escaped characters in JSON', () => {\n const text =\n '{\"content\": \"Test\\\\ncontent\\\\twith\\\\r\\\\nescapes\", \"tags\": [\"test\\\\u0020ai\", \"escaped\\\\\"quotes\\\\\"\"], \"title\": \"Test\\\\\\\\Article\"}';\n const result = parseObject(text, articleSchema);\n expect(result).toEqual({\n content: 'Test\\ncontent\\twith\\r\\nescapes',\n tags: ['test ai', 'escaped\"quotes\"'],\n title: 'Test\\\\Article',\n });\n });\n });\n\n describe('array parsing', () => {\n it('parses JSON array', () => {\n const text = '[\"test\", \"ai\", \"content\"]';\n const schema = z.array(z.string());\n const result = parseObject(text, schema);\n expect(result).toEqual(['test', 'ai', 'content']);\n });\n\n it('parses array of objects from markdown code block', () => {\n const text = `\\`\\`\\`json\\n[${validArticleJson}]\\n\\`\\`\\``;\n const schema = z.array(articleSchema);\n const result = parseObject(text, schema);\n expect(result).toEqual([validArticle]);\n });\n });\n\n describe('primitive parsing', () => {\n it('parses string value', () => {\n const text = '\"test string\"';\n const result = parseObject(text, z.string());\n expect(result).toBe('test string');\n });\n\n it('parses number value', () => {\n const text = '42';\n const result = parseObject(text, z.number());\n expect(result).toBe(42);\n });\n\n it('parses boolean value', () => {\n const text = 'true';\n const result = parseObject(text, z.boolean());\n expect(result).toBe(true);\n });\n\n it('parses null value', () => {\n const text = 'null';\n const result = parseObject(text, z.null());\n expect(result).toBeNull();\n });\n });\n\n describe('error handling', () => {\n it('throws ParseObjectError for invalid JSON', () => {\n const text = '{invalid json}';\n expect(() => parseObject(text, articleSchema)).toThrow(ParseObjectError);\n });\n\n it('throws ParseObjectError when schema validation fails', () => {\n const text = JSON.stringify({\n content: 'Test',\n tags: ['test'],\n title: 123,\n });\n expect(() => parseObject(text, articleSchema)).toThrow(ParseObjectError);\n });\n\n it('throws ParseObjectError when no object found', () => {\n const text = 'No JSON object here';\n expect(() => parseObject(text, articleSchema)).toThrow(ParseObjectError);\n });\n\n it('throws ParseObjectError when no array found', () => {\n const text = 'No array here';\n const schema = z.array(z.string());\n expect(() => parseObject(text, schema)).toThrow(ParseObjectError);\n });\n\n it('throws ParseObjectError for unsupported schema type', () => {\n const text = 'test';\n const schema = z.union([z.string(), z.number()]);\n expect(() => parseObject(text, schema)).toThrow(ParseObjectError);\n });\n\n it('includes original text in error', () => {\n const text = '{invalid json}';\n try {\n parseObject(text, articleSchema);\n throw new Error('Should have thrown');\n } catch (error) {\n expect(error).toBeInstanceOf(ParseObjectError);\n expect((error as ParseObjectError).text).toBe(text);\n }\n });\n });\n\n describe('complex scenarios', () => {\n it('parses complex nested JSON with escaped quotes', () => {\n const schema = z.object({\n category: z.string(),\n countries: z.array(z.string()),\n perspectives: z.array(\n z.object({\n digest: z.string(),\n tags: z.object({\n type: z.string(),\n stance: z.string(),\n }),\n }),\n ),\n synopsis: z.string(),\n });\n\n const text = `\\`\\`\\`json\n{\n \"category\": \"sports\",\n \"countries\": [\"us\"],\n \"perspectives\": [{\n \"digest\": \"The team's \\\\\"Big 3\\\\\" experiment failed.\",\n \"tags\": { \"type\": \"analysis\", \"stance\": \"neutral\" }\n }],\n \"synopsis\": \"A major trade occurred.\"\n}\n\\`\\`\\``;\n\n const result = parseObject(text, schema);\n expect(result.category).toBe('sports');\n expect(result.countries).toEqual(['us']);\n expect(result.perspectives[0]?.digest).toContain('\"Big 3\" experiment');\n expect(result.synopsis).toBe('A major trade occurred.');\n });\n\n it('handles text with multiple whitespace variations', () => {\n const text = `Here's the\\n\\n article: \\n\\n${validArticleJson}\\n\\n`;\n const result = parseObject(text, articleSchema);\n expect(result).toEqual(validArticle);\n });\n\n it('selects largest valid JSON when multiple structures present', () => {\n const smallJson = '{\"title\": \"Small\"}';\n const text = `First: ${smallJson}, Second: ${validArticleJson}`;\n const result = parseObject(text, articleSchema);\n expect(result).toEqual(validArticle);\n });\n });\n});\n"],"names":["describe","expect","it","z","parseObject","ParseObjectError","articleSchema","object","content","string","tags","array","title","validArticle","validArticleJson","JSON","stringify","text","result","toEqual","schema","toBe","number","boolean","null","toBeNull","toThrow","union","Error","error","toBeInstanceOf","category","countries","perspectives","digest","type","stance","synopsis","toContain","smallJson"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/parsing/__tests__/parse-object.test.ts"],"sourcesContent":["import { describe, expect, it } from 'vitest';\nimport { z } from 'zod/v4';\n\nimport { parseObject, ParseObjectError } from '../parse-object.js';\n\nconst articleSchema = z.object({\n content: z.string(),\n tags: z.array(z.string()),\n title: z.string(),\n});\n\nconst validArticle = {\n content: 'Test content',\n tags: ['test', 'ai'],\n title: 'Test Article',\n};\n\nconst validArticleJson = JSON.stringify(validArticle);\n\ndescribe('parseObject', () => {\n describe('object parsing', () => {\n it('parses valid JSON object', () => {\n const text = validArticleJson;\n const result = parseObject(text, articleSchema);\n expect(result).toEqual(validArticle);\n });\n\n it('extracts JSON object from surrounding prose', () => {\n const text = `Here's the article: ${validArticleJson} - end of article`;\n const result = parseObject(text, articleSchema);\n expect(result).toEqual(validArticle);\n });\n\n it('parses JSON from markdown code block', () => {\n const text = `\\`\\`\\`json\\n${validArticleJson}\\n\\`\\`\\``;\n const result = parseObject(text, articleSchema);\n expect(result).toEqual(validArticle);\n });\n\n it('handles newlines in JSON values', () => {\n const text = `{\n \"content\": \"Test\\\\ncontent\\\\nwith\\\\nnewlines\",\n \"tags\": [\"test\", \"ai\"],\n \"title\": \"Test\\\\nArticle\"\n }`;\n const result = parseObject(text, articleSchema);\n expect(result).toEqual({\n content: 'Test\\ncontent\\nwith\\nnewlines',\n tags: ['test', 'ai'],\n title: 'Test\\nArticle',\n });\n });\n\n it('handles escaped characters in JSON', () => {\n const text =\n '{\"content\": \"Test\\\\ncontent\\\\twith\\\\r\\\\nescapes\", \"tags\": [\"test\\\\u0020ai\", \"escaped\\\\\"quotes\\\\\"\"], \"title\": \"Test\\\\\\\\Article\"}';\n const result = parseObject(text, articleSchema);\n expect(result).toEqual({\n content: 'Test\\ncontent\\twith\\r\\nescapes',\n tags: ['test ai', 'escaped\"quotes\"'],\n title: 'Test\\\\Article',\n });\n });\n });\n\n describe('array parsing', () => {\n it('parses JSON array', () => {\n const text = '[\"test\", \"ai\", \"content\"]';\n const schema = z.array(z.string());\n const result = parseObject(text, schema);\n expect(result).toEqual(['test', 'ai', 'content']);\n });\n\n it('parses array of objects from markdown code block', () => {\n const text = `\\`\\`\\`json\\n[${validArticleJson}]\\n\\`\\`\\``;\n const schema = z.array(articleSchema);\n const result = parseObject(text, schema);\n expect(result).toEqual([validArticle]);\n });\n });\n\n describe('primitive parsing', () => {\n it('parses string value', () => {\n const text = '\"test string\"';\n const result = parseObject(text, z.string());\n expect(result).toBe('test string');\n });\n\n it('parses number value', () => {\n const text = '42';\n const result = parseObject(text, z.number());\n expect(result).toBe(42);\n });\n\n it('parses boolean value', () => {\n const text = 'true';\n const result = parseObject(text, z.boolean());\n expect(result).toBe(true);\n });\n\n it('parses null value', () => {\n const text = 'null';\n const result = parseObject(text, z.null());\n expect(result).toBeNull();\n });\n });\n\n describe('error handling', () => {\n it('throws ParseObjectError for invalid JSON', () => {\n const text = '{invalid json}';\n expect(() => parseObject(text, articleSchema)).toThrow(ParseObjectError);\n });\n\n it('throws ParseObjectError when schema validation fails', () => {\n const text = JSON.stringify({\n content: 'Test',\n tags: ['test'],\n title: 123,\n });\n expect(() => parseObject(text, articleSchema)).toThrow(ParseObjectError);\n });\n\n it('throws ParseObjectError when no object found', () => {\n const text = 'No JSON object here';\n expect(() => parseObject(text, articleSchema)).toThrow(ParseObjectError);\n });\n\n it('throws ParseObjectError when no array found', () => {\n const text = 'No array here';\n const schema = z.array(z.string());\n expect(() => parseObject(text, schema)).toThrow(ParseObjectError);\n });\n\n it('throws ParseObjectError for unsupported schema type', () => {\n const text = 'test';\n const schema = z.date();\n expect(() => parseObject(text, schema)).toThrow(ParseObjectError);\n });\n\n it('throws ParseObjectError for union when no object or array found', () => {\n const text = 'just plain text';\n const schema = z.union([\n z.object({ type: z.literal('a') }),\n z.object({ type: z.literal('b') }),\n ]);\n expect(() => parseObject(text, schema)).toThrow(ParseObjectError);\n });\n\n it('includes original text in error', () => {\n const text = '{invalid json}';\n try {\n parseObject(text, articleSchema);\n throw new Error('Should have thrown');\n } catch (error) {\n expect(error).toBeInstanceOf(ParseObjectError);\n expect((error as ParseObjectError).text).toBe(text);\n }\n });\n });\n\n describe('complex scenarios', () => {\n it('parses complex nested JSON with escaped quotes', () => {\n const schema = z.object({\n category: z.string(),\n countries: z.array(z.string()),\n perspectives: z.array(\n z.object({\n digest: z.string(),\n tags: z.object({\n type: z.string(),\n stance: z.string(),\n }),\n }),\n ),\n synopsis: z.string(),\n });\n\n const text = `\\`\\`\\`json\n{\n \"category\": \"sports\",\n \"countries\": [\"us\"],\n \"perspectives\": [{\n \"digest\": \"The team's \\\\\"Big 3\\\\\" experiment failed.\",\n \"tags\": { \"type\": \"analysis\", \"stance\": \"neutral\" }\n }],\n \"synopsis\": \"A major trade occurred.\"\n}\n\\`\\`\\``;\n\n const result = parseObject(text, schema);\n expect(result.category).toBe('sports');\n expect(result.countries).toEqual(['us']);\n expect(result.perspectives[0]?.digest).toContain('\"Big 3\" experiment');\n expect(result.synopsis).toBe('A major trade occurred.');\n });\n\n it('handles text with multiple whitespace variations', () => {\n const text = `Here's the\\n\\n article: \\n\\n${validArticleJson}\\n\\n`;\n const result = parseObject(text, articleSchema);\n expect(result).toEqual(validArticle);\n });\n\n it('selects largest valid JSON when multiple structures present', () => {\n const smallJson = '{\"title\": \"Small\"}';\n const text = `First: ${smallJson}, Second: ${validArticleJson}`;\n const result = parseObject(text, articleSchema);\n expect(result).toEqual(validArticle);\n });\n });\n\n describe('union types', () => {\n it('parses z.union - variant A', () => {\n const schema = z.union([\n z.object({ type: z.literal('a'), value: z.string() }),\n z.object({ type: z.literal('b'), count: z.number() }),\n ]);\n const text = '{\"type\": \"a\", \"value\": \"hello\"}';\n expect(parseObject(text, schema)).toEqual({ type: 'a', value: 'hello' });\n });\n\n it('parses z.union - variant B', () => {\n const schema = z.union([\n z.object({ type: z.literal('a'), value: z.string() }),\n z.object({ type: z.literal('b'), count: z.number() }),\n ]);\n const text = '{\"type\": \"b\", \"count\": 42}';\n expect(parseObject(text, schema)).toEqual({ type: 'b', count: 42 });\n });\n\n it('parses z.discriminatedUnion', () => {\n const schema = z.discriminatedUnion('action', [\n z.object({ action: z.literal('join'), eventId: z.string() }),\n z.object({ action: z.literal('create'), name: z.string() }),\n ]);\n const text = '```json\\n{\"action\": \"create\", \"name\": \"Test\"}\\n```';\n expect(parseObject(text, schema)).toEqual({ action: 'create', name: 'Test' });\n });\n\n it('parses discriminated union from surrounding prose', () => {\n const schema = z.discriminatedUnion('action', [\n z.object({ action: z.literal('join'), eventId: z.string() }),\n z.object({ action: z.literal('create'), name: z.string() }),\n ]);\n const text = 'Here is the result: {\"action\": \"join\", \"eventId\": \"evt-123\"} - done';\n expect(parseObject(text, schema)).toEqual({ action: 'join', eventId: 'evt-123' });\n });\n\n it('parses union of arrays', () => {\n const schema = z.union([z.array(z.string()), z.array(z.number())]);\n const text = '[\"a\", \"b\", \"c\"]';\n expect(parseObject(text, schema)).toEqual(['a', 'b', 'c']);\n });\n\n it('throws when union variant does not match', () => {\n const schema = z.discriminatedUnion('action', [\n z.object({ action: z.literal('join'), eventId: z.string() }),\n z.object({ action: z.literal('create'), name: z.string() }),\n ]);\n const text = '{\"action\": \"delete\", \"id\": \"123\"}';\n expect(() => parseObject(text, schema)).toThrow(ParseObjectError);\n });\n });\n\n describe('wrapper types', () => {\n it('parses z.optional wrapping an object', () => {\n const schema = z.object({ name: z.string() }).optional();\n const text = '{\"name\": \"test\"}';\n expect(parseObject(text, schema)).toEqual({ name: 'test' });\n });\n\n it('parses z.nullable wrapping an object', () => {\n const schema = z.object({ name: z.string() }).nullable();\n const text = '{\"name\": \"test\"}';\n expect(parseObject(text, schema)).toEqual({ name: 'test' });\n });\n\n it('parses z.default wrapping an object', () => {\n const schema = z.object({ name: z.string() }).default({ name: 'default' });\n const text = '{\"name\": \"custom\"}';\n expect(parseObject(text, schema)).toEqual({ name: 'custom' });\n });\n\n it('parses schema with .transform()', () => {\n const schema = z.object({ value: z.string() }).transform((obj) => ({\n ...obj,\n transformed: true,\n }));\n const text = '{\"value\": \"test\"}';\n const result = parseObject(text, schema);\n expect(result).toEqual({ value: 'test', transformed: true });\n });\n\n it('parses schema with .refine()', () => {\n const schema = z.object({ value: z.number() }).refine((obj) => obj.value > 0, {\n message: 'Value must be positive',\n });\n const text = '{\"value\": 42}';\n expect(parseObject(text, schema)).toEqual({ value: 42 });\n });\n\n it('parses deeply nested wrapper types', () => {\n const schema = z\n .object({ name: z.string() })\n .optional()\n .nullable()\n .default({ name: 'default' });\n const text = '{\"name\": \"nested\"}';\n expect(parseObject(text, schema)).toEqual({ name: 'nested' });\n });\n\n it('parses optional array', () => {\n const schema = z.array(z.string()).optional();\n const text = '[\"a\", \"b\", \"c\"]';\n expect(parseObject(text, schema)).toEqual(['a', 'b', 'c']);\n });\n });\n});\n"],"names":["describe","expect","it","z","parseObject","ParseObjectError","articleSchema","object","content","string","tags","array","title","validArticle","validArticleJson","JSON","stringify","text","result","toEqual","schema","toBe","number","boolean","null","toBeNull","toThrow","date","union","type","literal","Error","error","toBeInstanceOf","category","countries","perspectives","digest","stance","synopsis","toContain","smallJson","value","count","discriminatedUnion","action","eventId","name","optional","nullable","default","transform","obj","transformed","refine","message"],"mappings":"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"}
@@ -254,6 +254,29 @@ function extractBySchemaType(text, schema, originalText) {
254
254
  if (_instanceof(schema, z.ZodBoolean) || _instanceof(schema, z.ZodNull) || _instanceof(schema, z.ZodNumber) || _instanceof(schema, z.ZodString)) {
255
255
  return extractPrimitive(text, schema);
256
256
  }
257
+ // Handle union types - extract as object/array and let Zod validate which variant matches
258
+ if (_instanceof(schema, z.ZodUnion) || _instanceof(schema, z.ZodDiscriminatedUnion)) {
259
+ var objectStart = text.indexOf('{');
260
+ if (objectStart !== -1) {
261
+ return extractObject(text, originalText);
262
+ }
263
+ var arrayStart = text.indexOf('[');
264
+ if (arrayStart !== -1) {
265
+ return extractArray(text, originalText);
266
+ }
267
+ throw new ParseObjectError('No object or array found for union type', undefined, originalText);
268
+ }
269
+ // Handle wrapper types - unwrap and delegate to inner type
270
+ if (_instanceof(schema, z.ZodOptional) || _instanceof(schema, z.ZodNullable)) {
271
+ return extractBySchemaType(text, schema.unwrap(), originalText);
272
+ }
273
+ if (_instanceof(schema, z.ZodDefault)) {
274
+ return extractBySchemaType(text, schema.def.innerType, originalText);
275
+ }
276
+ // Handle .transform() which creates a ZodPipe in Zod v4
277
+ if (_instanceof(schema, z.ZodPipe)) {
278
+ return extractBySchemaType(text, schema.def["in"], originalText);
279
+ }
257
280
  throw new ParseObjectError('Unsupported schema type', undefined, originalText);
258
281
  }
259
282
  function extractJsonFromCodeBlock(block) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/parsing/parse-object.ts"],"sourcesContent":["import { jsonrepair } from 'jsonrepair';\nimport { z } from 'zod/v4';\n\n/**\n * Error thrown when object parsing fails.\n * Contains the original text for debugging purposes.\n */\nexport class ParseObjectError extends Error {\n public readonly name = 'ParseObjectError';\n\n constructor(\n message: string,\n public readonly cause?: unknown,\n public readonly text?: string,\n ) {\n super(message);\n }\n}\n\n/**\n * Parses AI-generated text into structured data validated against a Zod schema.\n *\n * Handles common AI response formats:\n * - JSON wrapped in markdown code blocks\n * - JSON embedded in prose text\n * - Malformed JSON (auto-repaired)\n * - Escaped unicode and special characters\n *\n * @param text - The raw AI response text\n * @param schema - A Zod schema to validate and type the result\n * @returns The parsed and validated data\n * @throws {ParseObjectError} When parsing or validation fails\n *\n * @example\n * ```ts\n * const schema = z.object({ title: z.string(), tags: z.array(z.string()) });\n * const result = parseObject(aiResponse, schema);\n * // result is typed as { title: string; tags: string[] }\n * ```\n */\nexport function parseObject<T>(text: string, schema: z.ZodSchema<T>): T {\n try {\n const jsonString = extractJsonString(text);\n const extracted = extractBySchemaType(jsonString, schema, text);\n const unescaped = unescapeJsonValues(extracted);\n return schema.parse(unescaped);\n } catch (error) {\n if (error instanceof ParseObjectError) {\n throw error;\n }\n if (error instanceof z.ZodError) {\n throw new ParseObjectError('Failed to validate response against schema', error, text);\n }\n throw error;\n }\n}\n\nconst MARKDOWN_CODE_BLOCK_RE = /```(?:json)?\\r?\\n([^`]*?)\\r?\\n```/g;\n\nfunction convertToPrimitive(value: unknown, schema: z.ZodType): unknown {\n if (schema instanceof z.ZodBoolean) return Boolean(value);\n if (schema instanceof z.ZodNull) return null;\n if (schema instanceof z.ZodNumber) return Number(value);\n if (schema instanceof z.ZodString) return String(value);\n return value;\n}\n\nfunction extractArray(text: string, originalText: string): unknown {\n const start = text.indexOf('[');\n const end = text.lastIndexOf(']');\n\n if (start === -1 || end === -1) {\n throw new ParseObjectError('No array found in response', undefined, originalText);\n }\n\n try {\n const raw = text.slice(start, end + 1);\n return JSON.parse(jsonrepair(raw));\n } catch (error) {\n throw new ParseObjectError('Failed to parse array JSON', error, originalText);\n }\n}\n\nfunction extractBySchemaType(text: string, schema: z.ZodType, originalText: string): unknown {\n if (schema instanceof z.ZodArray) {\n return extractArray(text, originalText);\n }\n\n if (schema instanceof z.ZodObject) {\n return extractObject(text, originalText);\n }\n\n if (\n schema instanceof z.ZodBoolean ||\n schema instanceof z.ZodNull ||\n schema instanceof z.ZodNumber ||\n schema instanceof z.ZodString\n ) {\n return extractPrimitive(text, schema);\n }\n\n throw new ParseObjectError('Unsupported schema type', undefined, originalText);\n}\n\nfunction extractJsonFromCodeBlock(block: string): null | string {\n const content = block.replace(/```(?:json)?\\r?\\n([^`]*?)\\r?\\n```/, '$1').trim();\n try {\n JSON.parse(content);\n return content;\n } catch {\n return null;\n }\n}\n\nfunction extractJsonString(text: string): string {\n const codeBlocks = text.match(MARKDOWN_CODE_BLOCK_RE);\n if (codeBlocks && codeBlocks.length > 0) {\n const validBlocks = codeBlocks\n .map((block) => extractJsonFromCodeBlock(block))\n .filter((block): block is string => block !== null);\n\n if (validBlocks.length > 0) {\n return findLongestString(validBlocks);\n }\n }\n\n const structures = findJsonStructures(text);\n if (structures.length > 0) {\n return findLongestString(structures);\n }\n\n return text.replace(/\\s+/g, ' ').trim();\n}\n\nfunction extractObject(text: string, originalText: string): unknown {\n const start = text.indexOf('{');\n const end = text.lastIndexOf('}');\n\n if (start === -1 || end === -1) {\n throw new ParseObjectError('No object found in response', undefined, originalText);\n }\n\n try {\n const raw = text.slice(start, end + 1);\n return JSON.parse(jsonrepair(raw));\n } catch (error) {\n throw new ParseObjectError('Failed to parse object JSON', error, originalText);\n }\n}\n\nfunction extractPrimitive(text: string, schema: z.ZodType): unknown {\n const trimmed = text.trim();\n try {\n return convertToPrimitive(JSON.parse(trimmed), schema);\n } catch {\n return convertToPrimitive(trimmed, schema);\n }\n}\n\nfunction findJsonStructures(text: string): string[] {\n const matches: string[] = [];\n let depth = 0;\n let start = -1;\n\n for (let i = 0; i < text.length; i++) {\n const char = text[i];\n if (char === '{' || char === '[') {\n if (depth === 0) start = i;\n depth++;\n } else if (char === '}' || char === ']') {\n depth--;\n if (depth === 0 && start !== -1) {\n const candidate = text.slice(start, i + 1);\n try {\n JSON.parse(candidate);\n matches.push(candidate);\n } catch {\n // Invalid JSON, skip\n }\n }\n }\n }\n\n return matches;\n}\n\nfunction findLongestString(strings: string[]): string {\n return strings.reduce((longest, current) =>\n current.length > longest.length ? current : longest,\n );\n}\n\nfunction unescapeJsonValues(json: unknown): unknown {\n if (typeof json === 'string') {\n return unescapeString(json);\n }\n if (Array.isArray(json)) {\n return json.map(unescapeJsonValues);\n }\n if (typeof json === 'object' && json !== null) {\n return Object.fromEntries(\n Object.entries(json).map(([key, value]) => [key, unescapeJsonValues(value)]),\n );\n }\n return json;\n}\n\nfunction unescapeString(text: string): string {\n return text\n .replace(/\\\\\"/g, '\"')\n .replace(/\\\\n/g, '\\n')\n .replace(/\\\\r/g, '\\r')\n .replace(/\\\\t/g, '\\t')\n .replace(/\\\\\\\\/g, '\\\\')\n .replace(/\\\\u([0-9a-fA-F]{4})/g, (_, code) =>\n String.fromCharCode(Number.parseInt(code, 16)),\n );\n}\n"],"names":["jsonrepair","z","ParseObjectError","message","cause","text","name","Error","parseObject","schema","jsonString","extractJsonString","extracted","extractBySchemaType","unescaped","unescapeJsonValues","parse","error","ZodError","MARKDOWN_CODE_BLOCK_RE","convertToPrimitive","value","ZodBoolean","Boolean","ZodNull","ZodNumber","Number","ZodString","String","extractArray","originalText","start","indexOf","end","lastIndexOf","undefined","raw","slice","JSON","ZodArray","ZodObject","extractObject","extractPrimitive","extractJsonFromCodeBlock","block","content","replace","trim","codeBlocks","match","length","validBlocks","map","filter","findLongestString","structures","findJsonStructures","trimmed","matches","depth","i","char","candidate","push","strings","reduce","longest","current","json","unescapeString","Array","isArray","Object","fromEntries","entries","key","_","code","fromCharCode","parseInt"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/parsing/parse-object.ts"],"sourcesContent":["import { jsonrepair } from 'jsonrepair';\nimport { z } from 'zod/v4';\n\n/**\n * Error thrown when object parsing fails.\n * Contains the original text for debugging purposes.\n */\nexport class ParseObjectError extends Error {\n public readonly name = 'ParseObjectError';\n\n constructor(\n message: string,\n public readonly cause?: unknown,\n public readonly text?: string,\n ) {\n super(message);\n }\n}\n\n/**\n * Parses AI-generated text into structured data validated against a Zod schema.\n *\n * Handles common AI response formats:\n * - JSON wrapped in markdown code blocks\n * - JSON embedded in prose text\n * - Malformed JSON (auto-repaired)\n * - Escaped unicode and special characters\n *\n * @param text - The raw AI response text\n * @param schema - A Zod schema to validate and type the result\n * @returns The parsed and validated data\n * @throws {ParseObjectError} When parsing or validation fails\n *\n * @example\n * ```ts\n * const schema = z.object({ title: z.string(), tags: z.array(z.string()) });\n * const result = parseObject(aiResponse, schema);\n * // result is typed as { title: string; tags: string[] }\n * ```\n */\nexport function parseObject<T>(text: string, schema: z.ZodSchema<T>): T {\n try {\n const jsonString = extractJsonString(text);\n const extracted = extractBySchemaType(jsonString, schema, text);\n const unescaped = unescapeJsonValues(extracted);\n return schema.parse(unescaped);\n } catch (error) {\n if (error instanceof ParseObjectError) {\n throw error;\n }\n if (error instanceof z.ZodError) {\n throw new ParseObjectError('Failed to validate response against schema', error, text);\n }\n throw error;\n }\n}\n\nconst MARKDOWN_CODE_BLOCK_RE = /```(?:json)?\\r?\\n([^`]*?)\\r?\\n```/g;\n\nfunction convertToPrimitive(value: unknown, schema: z.ZodType): unknown {\n if (schema instanceof z.ZodBoolean) return Boolean(value);\n if (schema instanceof z.ZodNull) return null;\n if (schema instanceof z.ZodNumber) return Number(value);\n if (schema instanceof z.ZodString) return String(value);\n return value;\n}\n\nfunction extractArray(text: string, originalText: string): unknown {\n const start = text.indexOf('[');\n const end = text.lastIndexOf(']');\n\n if (start === -1 || end === -1) {\n throw new ParseObjectError('No array found in response', undefined, originalText);\n }\n\n try {\n const raw = text.slice(start, end + 1);\n return JSON.parse(jsonrepair(raw));\n } catch (error) {\n throw new ParseObjectError('Failed to parse array JSON', error, originalText);\n }\n}\n\nfunction extractBySchemaType(text: string, schema: z.ZodType, originalText: string): unknown {\n if (schema instanceof z.ZodArray) {\n return extractArray(text, originalText);\n }\n\n if (schema instanceof z.ZodObject) {\n return extractObject(text, originalText);\n }\n\n if (\n schema instanceof z.ZodBoolean ||\n schema instanceof z.ZodNull ||\n schema instanceof z.ZodNumber ||\n schema instanceof z.ZodString\n ) {\n return extractPrimitive(text, schema);\n }\n\n // Handle union types - extract as object/array and let Zod validate which variant matches\n if (schema instanceof z.ZodUnion || schema instanceof z.ZodDiscriminatedUnion) {\n const objectStart = text.indexOf('{');\n if (objectStart !== -1) {\n return extractObject(text, originalText);\n }\n const arrayStart = text.indexOf('[');\n if (arrayStart !== -1) {\n return extractArray(text, originalText);\n }\n throw new ParseObjectError(\n 'No object or array found for union type',\n undefined,\n originalText,\n );\n }\n\n // Handle wrapper types - unwrap and delegate to inner type\n if (schema instanceof z.ZodOptional || schema instanceof z.ZodNullable) {\n return extractBySchemaType(text, schema.unwrap() as z.ZodType, originalText);\n }\n\n if (schema instanceof z.ZodDefault) {\n return extractBySchemaType(text, schema.def.innerType as z.ZodType, originalText);\n }\n\n // Handle .transform() which creates a ZodPipe in Zod v4\n if (schema instanceof z.ZodPipe) {\n return extractBySchemaType(text, schema.def.in as z.ZodType, originalText);\n }\n\n throw new ParseObjectError('Unsupported schema type', undefined, originalText);\n}\n\nfunction extractJsonFromCodeBlock(block: string): null | string {\n const content = block.replace(/```(?:json)?\\r?\\n([^`]*?)\\r?\\n```/, '$1').trim();\n try {\n JSON.parse(content);\n return content;\n } catch {\n return null;\n }\n}\n\nfunction extractJsonString(text: string): string {\n const codeBlocks = text.match(MARKDOWN_CODE_BLOCK_RE);\n if (codeBlocks && codeBlocks.length > 0) {\n const validBlocks = codeBlocks\n .map((block) => extractJsonFromCodeBlock(block))\n .filter((block): block is string => block !== null);\n\n if (validBlocks.length > 0) {\n return findLongestString(validBlocks);\n }\n }\n\n const structures = findJsonStructures(text);\n if (structures.length > 0) {\n return findLongestString(structures);\n }\n\n return text.replace(/\\s+/g, ' ').trim();\n}\n\nfunction extractObject(text: string, originalText: string): unknown {\n const start = text.indexOf('{');\n const end = text.lastIndexOf('}');\n\n if (start === -1 || end === -1) {\n throw new ParseObjectError('No object found in response', undefined, originalText);\n }\n\n try {\n const raw = text.slice(start, end + 1);\n return JSON.parse(jsonrepair(raw));\n } catch (error) {\n throw new ParseObjectError('Failed to parse object JSON', error, originalText);\n }\n}\n\nfunction extractPrimitive(text: string, schema: z.ZodType): unknown {\n const trimmed = text.trim();\n try {\n return convertToPrimitive(JSON.parse(trimmed), schema);\n } catch {\n return convertToPrimitive(trimmed, schema);\n }\n}\n\nfunction findJsonStructures(text: string): string[] {\n const matches: string[] = [];\n let depth = 0;\n let start = -1;\n\n for (let i = 0; i < text.length; i++) {\n const char = text[i];\n if (char === '{' || char === '[') {\n if (depth === 0) start = i;\n depth++;\n } else if (char === '}' || char === ']') {\n depth--;\n if (depth === 0 && start !== -1) {\n const candidate = text.slice(start, i + 1);\n try {\n JSON.parse(candidate);\n matches.push(candidate);\n } catch {\n // Invalid JSON, skip\n }\n }\n }\n }\n\n return matches;\n}\n\nfunction findLongestString(strings: string[]): string {\n return strings.reduce((longest, current) =>\n current.length > longest.length ? current : longest,\n );\n}\n\nfunction unescapeJsonValues(json: unknown): unknown {\n if (typeof json === 'string') {\n return unescapeString(json);\n }\n if (Array.isArray(json)) {\n return json.map(unescapeJsonValues);\n }\n if (typeof json === 'object' && json !== null) {\n return Object.fromEntries(\n Object.entries(json).map(([key, value]) => [key, unescapeJsonValues(value)]),\n );\n }\n return json;\n}\n\nfunction unescapeString(text: string): string {\n return text\n .replace(/\\\\\"/g, '\"')\n .replace(/\\\\n/g, '\\n')\n .replace(/\\\\r/g, '\\r')\n .replace(/\\\\t/g, '\\t')\n .replace(/\\\\\\\\/g, '\\\\')\n .replace(/\\\\u([0-9a-fA-F]{4})/g, (_, code) =>\n String.fromCharCode(Number.parseInt(code, 16)),\n );\n}\n"],"names":["jsonrepair","z","ParseObjectError","message","cause","text","name","Error","parseObject","schema","jsonString","extractJsonString","extracted","extractBySchemaType","unescaped","unescapeJsonValues","parse","error","ZodError","MARKDOWN_CODE_BLOCK_RE","convertToPrimitive","value","ZodBoolean","Boolean","ZodNull","ZodNumber","Number","ZodString","String","extractArray","originalText","start","indexOf","end","lastIndexOf","undefined","raw","slice","JSON","ZodArray","ZodObject","extractObject","extractPrimitive","ZodUnion","ZodDiscriminatedUnion","objectStart","arrayStart","ZodOptional","ZodNullable","unwrap","ZodDefault","def","innerType","ZodPipe","in","extractJsonFromCodeBlock","block","content","replace","trim","codeBlocks","match","length","validBlocks","map","filter","findLongestString","structures","findJsonStructures","trimmed","matches","depth","i","char","candidate","push","strings","reduce","longest","current","json","unescapeString","Array","isArray","Object","fromEntries","entries","key","_","code","fromCharCode","parseInt"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAASA,UAAU,QAAQ,aAAa;AACxC,SAASC,CAAC,QAAQ,SAAS;AAE3B;;;CAGC,GACD,OAAO,IAAA,AAAMC,iCAAN;;cAAMA;aAAAA,iBAILC,OAAe,EACf,AAAgBC,KAAe,EAC/B,AAAgBC,IAAa;gCANxBH;;gBAQL,kBARKA;YAQCC;+FAPV,wBAAgBG,QAAhB,KAAA,UAIoBF,QAAAA,aACAC,OAAAA,YALJC,OAAO;;;WADdJ;qBAAyBK,QAUrC;AAED;;;;;;;;;;;;;;;;;;;;CAoBC,GACD,OAAO,SAASC,YAAeH,IAAY,EAAEI,MAAsB;IAC/D,IAAI;QACA,IAAMC,aAAaC,kBAAkBN;QACrC,IAAMO,YAAYC,oBAAoBH,YAAYD,QAAQJ;QAC1D,IAAMS,YAAYC,mBAAmBH;QACrC,OAAOH,OAAOO,KAAK,CAACF;IACxB,EAAE,OAAOG,OAAO;QACZ,IAAIA,AAAK,YAALA,OAAiBf,mBAAkB;YACnC,MAAMe;QACV;QACA,IAAIA,AAAK,YAALA,OAAiBhB,EAAEiB,QAAQ,GAAE;YAC7B,MAAM,IAAIhB,iBAAiB,8CAA8Ce,OAAOZ;QACpF;QACA,MAAMY;IACV;AACJ;AAEA,IAAME,yBAAyB;AAE/B,SAASC,mBAAmBC,KAAc,EAAEZ,MAAiB;IACzD,IAAIA,AAAM,YAANA,QAAkBR,EAAEqB,UAAU,GAAE,OAAOC,QAAQF;IACnD,IAAIZ,AAAM,YAANA,QAAkBR,EAAEuB,OAAO,GAAE,OAAO;IACxC,IAAIf,AAAM,YAANA,QAAkBR,EAAEwB,SAAS,GAAE,OAAOC,OAAOL;IACjD,IAAIZ,AAAM,YAANA,QAAkBR,EAAE0B,SAAS,GAAE,OAAOC,OAAOP;IACjD,OAAOA;AACX;AAEA,SAASQ,aAAaxB,IAAY,EAAEyB,YAAoB;IACpD,IAAMC,QAAQ1B,KAAK2B,OAAO,CAAC;IAC3B,IAAMC,MAAM5B,KAAK6B,WAAW,CAAC;IAE7B,IAAIH,UAAU,CAAC,KAAKE,QAAQ,CAAC,GAAG;QAC5B,MAAM,IAAI/B,iBAAiB,8BAA8BiC,WAAWL;IACxE;IAEA,IAAI;QACA,IAAMM,MAAM/B,KAAKgC,KAAK,CAACN,OAAOE,MAAM;QACpC,OAAOK,KAAKtB,KAAK,CAAChB,WAAWoC;IACjC,EAAE,OAAOnB,OAAO;QACZ,MAAM,IAAIf,iBAAiB,8BAA8Be,OAAOa;IACpE;AACJ;AAEA,SAASjB,oBAAoBR,IAAY,EAAEI,MAAiB,EAAEqB,YAAoB;IAC9E,IAAIrB,AAAM,YAANA,QAAkBR,EAAEsC,QAAQ,GAAE;QAC9B,OAAOV,aAAaxB,MAAMyB;IAC9B;IAEA,IAAIrB,AAAM,YAANA,QAAkBR,EAAEuC,SAAS,GAAE;QAC/B,OAAOC,cAAcpC,MAAMyB;IAC/B;IAEA,IACIrB,AAAM,YAANA,QAAkBR,EAAEqB,UAAU,KAC9Bb,AAAM,YAANA,QAAkBR,EAAEuB,OAAO,KAC3Bf,AAAM,YAANA,QAAkBR,EAAEwB,SAAS,KAC7BhB,AAAM,YAANA,QAAkBR,EAAE0B,SAAS,GAC/B;QACE,OAAOe,iBAAiBrC,MAAMI;IAClC;IAEA,0FAA0F;IAC1F,IAAIA,AAAM,YAANA,QAAkBR,EAAE0C,QAAQ,KAAIlC,AAAM,YAANA,QAAkBR,EAAE2C,qBAAqB,GAAE;QAC3E,IAAMC,cAAcxC,KAAK2B,OAAO,CAAC;QACjC,IAAIa,gBAAgB,CAAC,GAAG;YACpB,OAAOJ,cAAcpC,MAAMyB;QAC/B;QACA,IAAMgB,aAAazC,KAAK2B,OAAO,CAAC;QAChC,IAAIc,eAAe,CAAC,GAAG;YACnB,OAAOjB,aAAaxB,MAAMyB;QAC9B;QACA,MAAM,IAAI5B,iBACN,2CACAiC,WACAL;IAER;IAEA,2DAA2D;IAC3D,IAAIrB,AAAM,YAANA,QAAkBR,EAAE8C,WAAW,KAAItC,AAAM,YAANA,QAAkBR,EAAE+C,WAAW,GAAE;QACpE,OAAOnC,oBAAoBR,MAAMI,OAAOwC,MAAM,IAAiBnB;IACnE;IAEA,IAAIrB,AAAM,YAANA,QAAkBR,EAAEiD,UAAU,GAAE;QAChC,OAAOrC,oBAAoBR,MAAMI,OAAO0C,GAAG,CAACC,SAAS,EAAetB;IACxE;IAEA,wDAAwD;IACxD,IAAIrB,AAAM,YAANA,QAAkBR,EAAEoD,OAAO,GAAE;QAC7B,OAAOxC,oBAAoBR,MAAMI,OAAO0C,GAAG,AAACG,CAAAA,KAAE,EAAexB;IACjE;IAEA,MAAM,IAAI5B,iBAAiB,2BAA2BiC,WAAWL;AACrE;AAEA,SAASyB,yBAAyBC,KAAa;IAC3C,IAAMC,UAAUD,MAAME,OAAO,CAAC,qCAAqC,MAAMC,IAAI;IAC7E,IAAI;QACArB,KAAKtB,KAAK,CAACyC;QACX,OAAOA;IACX,EAAE,UAAM;QACJ,OAAO;IACX;AACJ;AAEA,SAAS9C,kBAAkBN,IAAY;IACnC,IAAMuD,aAAavD,KAAKwD,KAAK,CAAC1C;IAC9B,IAAIyC,cAAcA,WAAWE,MAAM,GAAG,GAAG;QACrC,IAAMC,cAAcH,WACfI,GAAG,CAAC,SAACR;mBAAUD,yBAAyBC;WACxCS,MAAM,CAAC,SAACT;mBAA2BA,UAAU;;QAElD,IAAIO,YAAYD,MAAM,GAAG,GAAG;YACxB,OAAOI,kBAAkBH;QAC7B;IACJ;IAEA,IAAMI,aAAaC,mBAAmB/D;IACtC,IAAI8D,WAAWL,MAAM,GAAG,GAAG;QACvB,OAAOI,kBAAkBC;IAC7B;IAEA,OAAO9D,KAAKqD,OAAO,CAAC,QAAQ,KAAKC,IAAI;AACzC;AAEA,SAASlB,cAAcpC,IAAY,EAAEyB,YAAoB;IACrD,IAAMC,QAAQ1B,KAAK2B,OAAO,CAAC;IAC3B,IAAMC,MAAM5B,KAAK6B,WAAW,CAAC;IAE7B,IAAIH,UAAU,CAAC,KAAKE,QAAQ,CAAC,GAAG;QAC5B,MAAM,IAAI/B,iBAAiB,+BAA+BiC,WAAWL;IACzE;IAEA,IAAI;QACA,IAAMM,MAAM/B,KAAKgC,KAAK,CAACN,OAAOE,MAAM;QACpC,OAAOK,KAAKtB,KAAK,CAAChB,WAAWoC;IACjC,EAAE,OAAOnB,OAAO;QACZ,MAAM,IAAIf,iBAAiB,+BAA+Be,OAAOa;IACrE;AACJ;AAEA,SAASY,iBAAiBrC,IAAY,EAAEI,MAAiB;IACrD,IAAM4D,UAAUhE,KAAKsD,IAAI;IACzB,IAAI;QACA,OAAOvC,mBAAmBkB,KAAKtB,KAAK,CAACqD,UAAU5D;IACnD,EAAE,UAAM;QACJ,OAAOW,mBAAmBiD,SAAS5D;IACvC;AACJ;AAEA,SAAS2D,mBAAmB/D,IAAY;IACpC,IAAMiE,UAAoB,EAAE;IAC5B,IAAIC,QAAQ;IACZ,IAAIxC,QAAQ,CAAC;IAEb,IAAK,IAAIyC,IAAI,GAAGA,IAAInE,KAAKyD,MAAM,EAAEU,IAAK;QAClC,IAAMC,QAAOpE,IAAI,CAACmE,EAAE;QACpB,IAAIC,UAAS,OAAOA,UAAS,KAAK;YAC9B,IAAIF,UAAU,GAAGxC,QAAQyC;YACzBD;QACJ,OAAO,IAAIE,UAAS,OAAOA,UAAS,KAAK;YACrCF;YACA,IAAIA,UAAU,KAAKxC,UAAU,CAAC,GAAG;gBAC7B,IAAM2C,YAAYrE,KAAKgC,KAAK,CAACN,OAAOyC,IAAI;gBACxC,IAAI;oBACAlC,KAAKtB,KAAK,CAAC0D;oBACXJ,QAAQK,IAAI,CAACD;gBACjB,EAAE,UAAM;gBACJ,qBAAqB;gBACzB;YACJ;QACJ;IACJ;IAEA,OAAOJ;AACX;AAEA,SAASJ,kBAAkBU,OAAiB;IACxC,OAAOA,QAAQC,MAAM,CAAC,SAACC,SAASC;eAC5BA,QAAQjB,MAAM,GAAGgB,QAAQhB,MAAM,GAAGiB,UAAUD;;AAEpD;AAEA,SAAS/D,mBAAmBiE,IAAa;IACrC,IAAI,OAAOA,SAAS,UAAU;QAC1B,OAAOC,eAAeD;IAC1B;IACA,IAAIE,MAAMC,OAAO,CAACH,OAAO;QACrB,OAAOA,KAAKhB,GAAG,CAACjD;IACpB;IACA,IAAI,CAAA,OAAOiE,qCAAP,SAAOA,KAAG,MAAM,YAAYA,SAAS,MAAM;QAC3C,OAAOI,OAAOC,WAAW,CACrBD,OAAOE,OAAO,CAACN,MAAMhB,GAAG,CAAC;qDAAEuB,iBAAKlE;mBAAW;gBAACkE;gBAAKxE,mBAAmBM;aAAO;;IAEnF;IACA,OAAO2D;AACX;AAEA,SAASC,eAAe5E,IAAY;IAChC,OAAOA,KACFqD,OAAO,CAAC,QAAQ,KAChBA,OAAO,CAAC,QAAQ,MAChBA,OAAO,CAAC,QAAQ,MAChBA,OAAO,CAAC,QAAQ,MAChBA,OAAO,CAAC,SAAS,MACjBA,OAAO,CAAC,wBAAwB,SAAC8B,GAAGC;eACjC7D,OAAO8D,YAAY,CAAChE,OAAOiE,QAAQ,CAACF,MAAM;;AAEtD"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@jterrazz/intelligence",
3
3
  "author": "Jean-Baptiste Terrazzoni <contact@jterrazz.com>",
4
- "version": "3.0.1",
4
+ "version": "3.0.2",
5
5
  "exports": {
6
6
  ".": {
7
7
  "require": "./dist/index.cjs",