@opensaas/stack-core 0.38.0 → 0.39.1
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/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +125 -0
- package/CLAUDE.md +21 -0
- package/dist/access/access-filter.d.ts +46 -1
- package/dist/access/access-filter.d.ts.map +1 -1
- package/dist/access/access-filter.js +113 -4
- package/dist/access/access-filter.js.map +1 -1
- package/dist/access/declared-dependencies.d.ts.map +1 -1
- package/dist/access/declared-dependencies.js +4 -9
- package/dist/access/declared-dependencies.js.map +1 -1
- package/dist/access/engine.d.ts +0 -20
- package/dist/access/engine.d.ts.map +1 -1
- package/dist/access/engine.js +0 -25
- package/dist/access/engine.js.map +1 -1
- package/dist/access/errors.d.ts +49 -0
- package/dist/access/errors.d.ts.map +1 -1
- package/dist/access/errors.js +75 -0
- package/dist/access/errors.js.map +1 -1
- package/dist/access/field-access.d.ts +39 -1
- package/dist/access/field-access.d.ts.map +1 -1
- package/dist/access/field-access.js +108 -42
- package/dist/access/field-access.js.map +1 -1
- package/dist/access/field-access.test.js +229 -2
- package/dist/access/field-access.test.js.map +1 -1
- package/dist/access/field-transforms.d.ts +0 -27
- package/dist/access/field-transforms.d.ts.map +1 -1
- package/dist/access/field-visibility.d.ts +0 -4
- package/dist/access/field-visibility.d.ts.map +1 -1
- package/dist/access/field-visibility.js +13 -39
- package/dist/access/field-visibility.js.map +1 -1
- package/dist/access/index.d.ts +6 -2
- package/dist/access/index.d.ts.map +1 -1
- package/dist/access/index.js +12 -2
- package/dist/access/index.js.map +1 -1
- package/dist/access/query-validation.d.ts +121 -0
- package/dist/access/query-validation.d.ts.map +1 -0
- package/dist/access/query-validation.js +292 -0
- package/dist/access/query-validation.js.map +1 -0
- package/dist/access/relationship-count.d.ts.map +1 -1
- package/dist/access/relationship-count.js +2 -10
- package/dist/access/relationship-count.js.map +1 -1
- package/dist/access/relationship-label-filter.d.ts +23 -23
- package/dist/access/relationship-label-filter.d.ts.map +1 -1
- package/dist/access/relationship-label-filter.js +5 -76
- package/dist/access/relationship-label-filter.js.map +1 -1
- package/dist/access/relationship-label-filter.test.js +19 -56
- package/dist/access/relationship-label-filter.test.js.map +1 -1
- package/dist/access/transaction-registry.d.ts +45 -0
- package/dist/access/transaction-registry.d.ts.map +1 -0
- package/dist/access/transaction-registry.js +37 -0
- package/dist/access/transaction-registry.js.map +1 -0
- package/dist/access/types.d.ts +55 -59
- package/dist/access/types.d.ts.map +1 -1
- package/dist/config/index.d.ts +9 -7
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +10 -18
- package/dist/config/index.js.map +1 -1
- package/dist/config/label.d.ts +6 -13
- package/dist/config/label.d.ts.map +1 -1
- package/dist/config/label.js +6 -13
- package/dist/config/label.js.map +1 -1
- package/dist/config/nav-count.d.ts +11 -19
- package/dist/config/nav-count.d.ts.map +1 -1
- package/dist/config/nav-count.js +11 -19
- package/dist/config/nav-count.js.map +1 -1
- package/dist/config/plugin-engine.d.ts +0 -10
- package/dist/config/plugin-engine.d.ts.map +1 -1
- package/dist/config/plugin-engine.js +1 -37
- package/dist/config/plugin-engine.js.map +1 -1
- package/dist/config/types.d.ts +94 -109
- package/dist/config/types.d.ts.map +1 -1
- package/dist/context/apply-defaults.d.ts +8 -31
- package/dist/context/apply-defaults.d.ts.map +1 -1
- package/dist/context/apply-defaults.js +12 -41
- package/dist/context/apply-defaults.js.map +1 -1
- package/dist/context/hook-pipeline.d.ts +4 -29
- package/dist/context/hook-pipeline.d.ts.map +1 -1
- package/dist/context/hook-pipeline.js +8 -41
- package/dist/context/hook-pipeline.js.map +1 -1
- package/dist/context/index.d.ts +4 -15
- package/dist/context/index.d.ts.map +1 -1
- package/dist/context/index.js +190 -193
- package/dist/context/index.js.map +1 -1
- package/dist/context/nested-operations.d.ts +7 -26
- package/dist/context/nested-operations.d.ts.map +1 -1
- package/dist/context/nested-operations.js +73 -171
- package/dist/context/nested-operations.js.map +1 -1
- package/dist/context/transaction-boundary.d.ts +36 -47
- package/dist/context/transaction-boundary.d.ts.map +1 -1
- package/dist/context/transaction-boundary.js +92 -79
- package/dist/context/transaction-boundary.js.map +1 -1
- package/dist/context/write-pipeline.d.ts +25 -64
- package/dist/context/write-pipeline.d.ts.map +1 -1
- package/dist/context/write-pipeline.js +81 -111
- package/dist/context/write-pipeline.js.map +1 -1
- package/dist/fields/format-prisma-default.d.ts.map +1 -1
- package/dist/fields/format-prisma-default.js +4 -7
- package/dist/fields/format-prisma-default.js.map +1 -1
- package/dist/fields/index.d.ts +17 -2
- package/dist/fields/index.d.ts.map +1 -1
- package/dist/fields/index.js +136 -147
- package/dist/fields/index.js.map +1 -1
- package/dist/filter/collect.d.ts +26 -3
- package/dist/filter/collect.d.ts.map +1 -1
- package/dist/filter/collect.js +30 -12
- package/dist/filter/collect.js.map +1 -1
- package/dist/filter/filter.test.js +98 -15
- package/dist/filter/filter.test.js.map +1 -1
- package/dist/filter/index.d.ts +1 -0
- package/dist/filter/index.d.ts.map +1 -1
- package/dist/filter/index.js.map +1 -1
- package/dist/filter/map.d.ts.map +1 -1
- package/dist/filter/map.js +0 -5
- package/dist/filter/map.js.map +1 -1
- package/dist/filter/parse.d.ts.map +1 -1
- package/dist/filter/parse.js +2 -9
- package/dist/filter/parse.js.map +1 -1
- package/dist/filter/serialize.d.ts.map +1 -1
- package/dist/filter/serialize.js +2 -4
- package/dist/filter/serialize.js.map +1 -1
- package/dist/hooks/index.d.ts +4 -42
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +5 -59
- package/dist/hooks/index.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +20 -4
- package/dist/index.js.map +1 -1
- package/dist/internal.d.ts +1 -0
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +4 -0
- package/dist/internal.js.map +1 -1
- package/dist/lib/case-utils.d.ts +0 -32
- package/dist/lib/case-utils.d.ts.map +1 -1
- package/dist/lib/case-utils.js +0 -32
- package/dist/lib/case-utils.js.map +1 -1
- package/dist/mcp/handler.d.ts +0 -4
- package/dist/mcp/handler.d.ts.map +1 -1
- package/dist/mcp/handler.js +12 -69
- package/dist/mcp/handler.js.map +1 -1
- package/dist/query/index.d.ts +26 -227
- package/dist/query/index.d.ts.map +1 -1
- package/dist/query/index.js +14 -117
- package/dist/query/index.js.map +1 -1
- package/dist/utils/password.d.ts +0 -68
- package/dist/utils/password.d.ts.map +1 -1
- package/dist/utils/password.js +7 -76
- package/dist/utils/password.js.map +1 -1
- package/dist/validation/field-config.d.ts.map +1 -1
- package/dist/validation/field-config.js +0 -6
- package/dist/validation/field-config.js.map +1 -1
- package/dist/validation/schema.d.ts +0 -7
- package/dist/validation/schema.d.ts.map +1 -1
- package/dist/validation/schema.js +0 -10
- package/dist/validation/schema.js.map +1 -1
- package/package.json +1 -1
- package/src/access/access-filter.ts +152 -5
- package/src/access/declared-dependencies.ts +4 -9
- package/src/access/engine.ts +0 -25
- package/src/access/errors.ts +81 -0
- package/src/access/field-access.test.ts +312 -2
- package/src/access/field-access.ts +118 -42
- package/src/access/field-transforms.ts +8 -39
- package/src/access/field-visibility.ts +16 -47
- package/src/access/index.ts +20 -2
- package/src/access/query-validation.ts +359 -0
- package/src/access/relationship-count.ts +2 -10
- package/src/access/relationship-label-filter.test.ts +19 -68
- package/src/access/relationship-label-filter.ts +27 -104
- package/src/access/transaction-registry.ts +58 -0
- package/src/access/types.ts +83 -86
- package/src/config/index.ts +10 -22
- package/src/config/label.ts +6 -13
- package/src/config/nav-count.ts +11 -19
- package/src/config/plugin-engine.ts +1 -37
- package/src/config/types.ts +95 -110
- package/src/context/apply-defaults.ts +12 -44
- package/src/context/hook-pipeline.ts +12 -67
- package/src/context/index.ts +263 -247
- package/src/context/nested-operations.ts +94 -226
- package/src/context/transaction-boundary.ts +113 -109
- package/src/context/write-pipeline.ts +99 -155
- package/src/fields/format-prisma-default.ts +4 -7
- package/src/fields/index.ts +155 -147
- package/src/filter/collect.ts +48 -12
- package/src/filter/filter.test.ts +153 -15
- package/src/filter/index.ts +1 -0
- package/src/filter/map.ts +0 -5
- package/src/filter/parse.ts +2 -9
- package/src/filter/serialize.ts +2 -4
- package/src/hooks/index.ts +5 -59
- package/src/index.ts +23 -4
- package/src/internal.ts +5 -0
- package/src/lib/case-utils.ts +0 -32
- package/src/mcp/handler.ts +13 -71
- package/src/query/index.ts +29 -235
- package/src/utils/password.ts +7 -76
- package/src/validation/field-config.ts +0 -6
- package/src/validation/schema.ts +0 -10
- package/tests/context.test.ts +700 -1
- package/tests/field-types.test.ts +222 -0
- package/tests/mcp-handler.test.ts +34 -0
- package/tests/transaction-boundary-outermost.test.ts +530 -0
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -2,6 +2,7 @@ import { describe, test, expect } from 'vitest'
|
|
|
2
2
|
import {
|
|
3
3
|
text,
|
|
4
4
|
integer,
|
|
5
|
+
bigInt,
|
|
5
6
|
checkbox,
|
|
6
7
|
timestamp,
|
|
7
8
|
password,
|
|
@@ -327,6 +328,227 @@ describe('Field Types', () => {
|
|
|
327
328
|
})
|
|
328
329
|
})
|
|
329
330
|
|
|
331
|
+
describe('bigInt field', () => {
|
|
332
|
+
describe('getZodSchema', () => {
|
|
333
|
+
test('returns optional bigint schema for non-required field', () => {
|
|
334
|
+
const field = bigInt()
|
|
335
|
+
const schema = field.getZodSchema('epoch', 'create')
|
|
336
|
+
|
|
337
|
+
expect(schema.safeParse(25n).success).toBe(true)
|
|
338
|
+
expect(schema.safeParse(undefined).success).toBe(true)
|
|
339
|
+
})
|
|
340
|
+
|
|
341
|
+
test('returns required schema for required field in create mode', () => {
|
|
342
|
+
const field = bigInt({ validation: { isRequired: true } })
|
|
343
|
+
const schema = field.getZodSchema('epoch', 'create')
|
|
344
|
+
|
|
345
|
+
expect(schema.safeParse(25n).success).toBe(true)
|
|
346
|
+
expect(schema.safeParse(undefined).success).toBe(false)
|
|
347
|
+
})
|
|
348
|
+
|
|
349
|
+
test('returns optional schema for required field in update mode', () => {
|
|
350
|
+
const field = bigInt({ validation: { isRequired: true } })
|
|
351
|
+
const schema = field.getZodSchema('epoch', 'update')
|
|
352
|
+
|
|
353
|
+
expect(schema.safeParse(25n).success).toBe(true)
|
|
354
|
+
expect(schema.safeParse(undefined).success).toBe(true)
|
|
355
|
+
})
|
|
356
|
+
|
|
357
|
+
test('coerces a bigint input to a bigint output unchanged', () => {
|
|
358
|
+
const field = bigInt()
|
|
359
|
+
const schema = field.getZodSchema('epoch', 'create')
|
|
360
|
+
|
|
361
|
+
const result = schema.safeParse(9007199254740993n)
|
|
362
|
+
expect(result.success).toBe(true)
|
|
363
|
+
if (result.success) {
|
|
364
|
+
expect(result.data).toBe(9007199254740993n)
|
|
365
|
+
expect(typeof result.data).toBe('bigint')
|
|
366
|
+
}
|
|
367
|
+
})
|
|
368
|
+
|
|
369
|
+
test('coerces a safe-integer number input to a bigint output', () => {
|
|
370
|
+
const field = bigInt()
|
|
371
|
+
const schema = field.getZodSchema('epoch', 'create')
|
|
372
|
+
|
|
373
|
+
const result = schema.safeParse(1700000000000)
|
|
374
|
+
expect(result.success).toBe(true)
|
|
375
|
+
if (result.success) {
|
|
376
|
+
expect(result.data).toBe(1700000000000n)
|
|
377
|
+
expect(typeof result.data).toBe('bigint')
|
|
378
|
+
}
|
|
379
|
+
})
|
|
380
|
+
|
|
381
|
+
test('coerces a numeric string input to a bigint output, round-tripping beyond Number.MAX_SAFE_INTEGER', () => {
|
|
382
|
+
const field = bigInt()
|
|
383
|
+
const schema = field.getZodSchema('epoch', 'create')
|
|
384
|
+
|
|
385
|
+
const result = schema.safeParse('9223372036854775807')
|
|
386
|
+
expect(result.success).toBe(true)
|
|
387
|
+
if (result.success) {
|
|
388
|
+
expect(result.data).toBe(9223372036854775807n)
|
|
389
|
+
}
|
|
390
|
+
})
|
|
391
|
+
|
|
392
|
+
test('accepts a negative numeric string', () => {
|
|
393
|
+
const field = bigInt()
|
|
394
|
+
const schema = field.getZodSchema('delta', 'create')
|
|
395
|
+
|
|
396
|
+
const result = schema.safeParse('-42')
|
|
397
|
+
expect(result.success).toBe(true)
|
|
398
|
+
if (result.success) {
|
|
399
|
+
expect(result.data).toBe(-42n)
|
|
400
|
+
}
|
|
401
|
+
})
|
|
402
|
+
|
|
403
|
+
test('rejects a non-integer number', () => {
|
|
404
|
+
const field = bigInt()
|
|
405
|
+
const schema = field.getZodSchema('epoch', 'create')
|
|
406
|
+
|
|
407
|
+
expect(schema.safeParse(1.5).success).toBe(false)
|
|
408
|
+
})
|
|
409
|
+
|
|
410
|
+
test('rejects a number above Number.MAX_SAFE_INTEGER instead of silently losing precision', () => {
|
|
411
|
+
const field = bigInt()
|
|
412
|
+
const schema = field.getZodSchema('epoch', 'create')
|
|
413
|
+
|
|
414
|
+
expect(schema.safeParse(Number.MAX_SAFE_INTEGER + 10).success).toBe(false)
|
|
415
|
+
})
|
|
416
|
+
|
|
417
|
+
test('rejects a non-numeric string', () => {
|
|
418
|
+
const field = bigInt()
|
|
419
|
+
const schema = field.getZodSchema('epoch', 'create')
|
|
420
|
+
|
|
421
|
+
expect(schema.safeParse('not-a-number').success).toBe(false)
|
|
422
|
+
})
|
|
423
|
+
|
|
424
|
+
test('rejects a decimal string', () => {
|
|
425
|
+
const field = bigInt()
|
|
426
|
+
const schema = field.getZodSchema('epoch', 'create')
|
|
427
|
+
|
|
428
|
+
expect(schema.safeParse('1.5').success).toBe(false)
|
|
429
|
+
})
|
|
430
|
+
|
|
431
|
+
test('validates min value', () => {
|
|
432
|
+
const field = bigInt({ validation: { min: 0n } })
|
|
433
|
+
const schema = field.getZodSchema('epoch', 'create')
|
|
434
|
+
|
|
435
|
+
expect(schema.safeParse(-1n).success).toBe(false)
|
|
436
|
+
expect(schema.safeParse(0n).success).toBe(true)
|
|
437
|
+
expect(schema.safeParse(1n).success).toBe(true)
|
|
438
|
+
})
|
|
439
|
+
|
|
440
|
+
test('validates max value', () => {
|
|
441
|
+
const field = bigInt({ validation: { max: 100n } })
|
|
442
|
+
const schema = field.getZodSchema('epoch', 'create')
|
|
443
|
+
|
|
444
|
+
expect(schema.safeParse(99n).success).toBe(true)
|
|
445
|
+
expect(schema.safeParse(100n).success).toBe(true)
|
|
446
|
+
expect(schema.safeParse(101n).success).toBe(false)
|
|
447
|
+
})
|
|
448
|
+
|
|
449
|
+
test('validates min and max together', () => {
|
|
450
|
+
const field = bigInt({ validation: { min: 18n, max: 65n } })
|
|
451
|
+
const schema = field.getZodSchema('age', 'create')
|
|
452
|
+
|
|
453
|
+
expect(schema.safeParse(17n).success).toBe(false)
|
|
454
|
+
expect(schema.safeParse(18n).success).toBe(true)
|
|
455
|
+
expect(schema.safeParse(65n).success).toBe(true)
|
|
456
|
+
expect(schema.safeParse(66n).success).toBe(false)
|
|
457
|
+
})
|
|
458
|
+
})
|
|
459
|
+
|
|
460
|
+
describe('getPrismaType', () => {
|
|
461
|
+
test('returns BigInt type for basic field', () => {
|
|
462
|
+
const field = bigInt()
|
|
463
|
+
const prismaType = field.getPrismaType('epoch')
|
|
464
|
+
|
|
465
|
+
expect(prismaType.type).toBe('BigInt')
|
|
466
|
+
expect(prismaType.modifiers).toBe('?')
|
|
467
|
+
})
|
|
468
|
+
|
|
469
|
+
test('returns required BigInt for required field', () => {
|
|
470
|
+
const field = bigInt({ validation: { isRequired: true } })
|
|
471
|
+
const prismaType = field.getPrismaType('epoch')
|
|
472
|
+
|
|
473
|
+
expect(prismaType.type).toBe('BigInt')
|
|
474
|
+
expect(prismaType.modifiers).toBeUndefined()
|
|
475
|
+
})
|
|
476
|
+
|
|
477
|
+
test('db.isNullable: false makes field non-nullable regardless of validation', () => {
|
|
478
|
+
const field = bigInt({ db: { isNullable: false } })
|
|
479
|
+
const prismaType = field.getPrismaType('epoch')
|
|
480
|
+
|
|
481
|
+
expect(prismaType.modifiers).toBeUndefined()
|
|
482
|
+
})
|
|
483
|
+
|
|
484
|
+
test('db.map generates @map attribute', () => {
|
|
485
|
+
const field = bigInt({ db: { map: 'occurred_at_ms' } })
|
|
486
|
+
const prismaType = field.getPrismaType('epoch')
|
|
487
|
+
|
|
488
|
+
expect(prismaType.modifiers).toContain('@map("occurred_at_ms")')
|
|
489
|
+
})
|
|
490
|
+
|
|
491
|
+
test('defaultValue generates a bare @default literal', () => {
|
|
492
|
+
const field = bigInt({ defaultValue: 0n })
|
|
493
|
+
const prismaType = field.getPrismaType('epoch')
|
|
494
|
+
|
|
495
|
+
expect(prismaType.modifiers).toContain('@default(0)')
|
|
496
|
+
})
|
|
497
|
+
|
|
498
|
+
test('isIndexed: true requests a block-level index', () => {
|
|
499
|
+
const field = bigInt({ isIndexed: true })
|
|
500
|
+
const prismaType = field.getPrismaType('epoch')
|
|
501
|
+
|
|
502
|
+
expect(prismaType.index).toBe(true)
|
|
503
|
+
})
|
|
504
|
+
|
|
505
|
+
test("isIndexed: 'unique' generates @unique modifier", () => {
|
|
506
|
+
const field = bigInt({ isIndexed: 'unique' })
|
|
507
|
+
const prismaType = field.getPrismaType('epoch')
|
|
508
|
+
|
|
509
|
+
expect(prismaType.modifiers).toContain('@unique')
|
|
510
|
+
})
|
|
511
|
+
})
|
|
512
|
+
|
|
513
|
+
describe('getTypeScriptType', () => {
|
|
514
|
+
test('returns optional bigint type for non-required field', () => {
|
|
515
|
+
const field = bigInt()
|
|
516
|
+
const tsType = field.getTypeScriptType()
|
|
517
|
+
|
|
518
|
+
expect(tsType.type).toBe('bigint')
|
|
519
|
+
expect(tsType.optional).toBe(true)
|
|
520
|
+
})
|
|
521
|
+
|
|
522
|
+
test('returns required bigint type for required field', () => {
|
|
523
|
+
const field = bigInt({ validation: { isRequired: true } })
|
|
524
|
+
const tsType = field.getTypeScriptType()
|
|
525
|
+
|
|
526
|
+
expect(tsType.type).toBe('bigint')
|
|
527
|
+
expect(tsType.optional).toBe(false)
|
|
528
|
+
})
|
|
529
|
+
})
|
|
530
|
+
|
|
531
|
+
describe('getFilterSpec', () => {
|
|
532
|
+
test('parses a valid integer token into a BigInt condition', () => {
|
|
533
|
+
const field = bigInt()
|
|
534
|
+
const spec = field.getFilterSpec?.('epoch', 'Event', {} as never)
|
|
535
|
+
|
|
536
|
+
expect(spec?.toCondition('eq', '9007199254740993')).toEqual({
|
|
537
|
+
epoch: { equals: 9007199254740993n },
|
|
538
|
+
})
|
|
539
|
+
expect(spec?.toCondition('gt', '5')).toEqual({ epoch: { gt: 5n } })
|
|
540
|
+
})
|
|
541
|
+
|
|
542
|
+
test('degrades to free text (null) for a non-integer token', () => {
|
|
543
|
+
const field = bigInt()
|
|
544
|
+
const spec = field.getFilterSpec?.('epoch', 'Event', {} as never)
|
|
545
|
+
|
|
546
|
+
expect(spec?.toCondition('eq', '1.5')).toBeNull()
|
|
547
|
+
expect(spec?.toCondition('eq', 'not-a-number')).toBeNull()
|
|
548
|
+
})
|
|
549
|
+
})
|
|
550
|
+
})
|
|
551
|
+
|
|
330
552
|
describe('checkbox field', () => {
|
|
331
553
|
describe('getZodSchema', () => {
|
|
332
554
|
test('returns optional boolean schema', () => {
|
|
@@ -326,6 +326,40 @@ describe('MCP Handler', () => {
|
|
|
326
326
|
})
|
|
327
327
|
})
|
|
328
328
|
|
|
329
|
+
// Regression test (issue #907 / ADR-0029): a bare `JSON.stringify` throws
|
|
330
|
+
// `TypeError: Do not know how to serialize a BigInt` on a bigInt() field's
|
|
331
|
+
// value. This must respond successfully, rendering the value as a decimal
|
|
332
|
+
// string — the field's MCP wire representation.
|
|
333
|
+
it('should serialize a bigint field value as a decimal string instead of throwing', async () => {
|
|
334
|
+
const mockResults = [{ id: '1', title: 'Post 1', occurredAtMs: 9007199254740993n }]
|
|
335
|
+
mockPrisma.post.findMany.mockResolvedValue(mockResults)
|
|
336
|
+
|
|
337
|
+
const handlers = createMcpHandlers({ config, getSession: mockGetSession, getContext })
|
|
338
|
+
|
|
339
|
+
const request = new Request('http://localhost/api/mcp', {
|
|
340
|
+
method: 'POST',
|
|
341
|
+
headers: { 'Content-Type': 'application/json' },
|
|
342
|
+
body: JSON.stringify({
|
|
343
|
+
jsonrpc: '2.0',
|
|
344
|
+
id: 1,
|
|
345
|
+
method: 'tools/call',
|
|
346
|
+
params: {
|
|
347
|
+
name: 'list_post_query',
|
|
348
|
+
arguments: { where: {}, take: 10 },
|
|
349
|
+
},
|
|
350
|
+
}),
|
|
351
|
+
})
|
|
352
|
+
|
|
353
|
+
const response = await handlers.POST(request)
|
|
354
|
+
expect(response.status).toBe(200)
|
|
355
|
+
|
|
356
|
+
const data = await response.json()
|
|
357
|
+
expect(data.result.content[0].text).toContain('"occurredAtMs": "9007199254740993"')
|
|
358
|
+
|
|
359
|
+
const result = JSON.parse(data.result.content[0].text)
|
|
360
|
+
expect(result.items[0].occurredAtMs).toBe('9007199254740993')
|
|
361
|
+
})
|
|
362
|
+
|
|
329
363
|
it('should execute create operation', async () => {
|
|
330
364
|
const mockResult = { id: '1', title: 'New Post', content: 'New Content' }
|
|
331
365
|
mockPrisma.post.create.mockResolvedValue(mockResult)
|