|
| 1 | +import { describe, expect, it } from 'vitest' |
| 2 | +import { |
| 3 | + EXPOSED_DOMAIN_ENTRIES, |
| 4 | + envelopeTypeNameForCastAs, |
| 5 | + isOrdOreDomain, |
| 6 | + toV3CodecId, |
| 7 | + V3_CODEC_IDS, |
| 8 | + V3_DOMAIN_META_BY_CODEC_ID, |
| 9 | + V3_FACTORY_BY_NATIVE_TYPE, |
| 10 | +} from '../../src/v3/catalog' |
| 11 | + |
| 12 | +describe('v3 catalog derivation', () => { |
| 13 | + it('derives a concrete codec id per domain from the registry key verbatim', () => { |
| 14 | + expect(toV3CodecId('eql_v3_text_search')).toBe('cipherstash/eql-v3/eql_v3_text_search@1') |
| 15 | + expect(toV3CodecId('eql_v3_boolean')).toBe('cipherstash/eql-v3/eql_v3_boolean@1') |
| 16 | + }) |
| 17 | + |
| 18 | + it('records the public.* native type (never eql_v3.*) for text_search with full caps', () => { |
| 19 | + const meta = V3_DOMAIN_META_BY_CODEC_ID.get('cipherstash/eql-v3/eql_v3_text_search@1') |
| 20 | + expect(meta?.nativeType).toBe('public.eql_v3_text_search') |
| 21 | + expect(meta?.nativeType.startsWith('public.')).toBe(true) |
| 22 | + expect(meta?.castAs).toBe('string') |
| 23 | + expect(meta?.capabilities).toEqual({ equality: true, orderAndRange: true, freeTextSearch: true }) |
| 24 | + expect(Object.keys(meta?.indexes ?? {}).sort()).toEqual(['match', 'ope', 'unique']) |
| 25 | + }) |
| 26 | + |
| 27 | + it('marks public.eql_v3_boolean as storage-only (no indexes, all capabilities false)', () => { |
| 28 | + const meta = V3_DOMAIN_META_BY_CODEC_ID.get('cipherstash/eql-v3/eql_v3_boolean@1') |
| 29 | + expect(meta?.nativeType).toBe('public.eql_v3_boolean') |
| 30 | + expect(meta?.castAs).toBe('boolean') |
| 31 | + expect(meta?.capabilities).toEqual({ equality: false, orderAndRange: false, freeTextSearch: false }) |
| 32 | + expect(Object.keys(meta?.indexes ?? {})).toEqual([]) |
| 33 | + }) |
| 34 | + |
| 35 | + it('exposes bigint as a first-class family with bigint castAs', () => { |
| 36 | + expect(V3_DOMAIN_META_BY_CODEC_ID.get('cipherstash/eql-v3/eql_v3_bigint@1')?.castAs).toBe('bigint') |
| 37 | + expect(V3_DOMAIN_META_BY_CODEC_ID.get('cipherstash/eql-v3/eql_v3_bigint_ord@1')?.nativeType).toBe( |
| 38 | + 'public.eql_v3_bigint_ord', |
| 39 | + ) |
| 40 | + }) |
| 41 | + |
| 42 | + it('derives timestamp castAs distinctly from date', () => { |
| 43 | + expect(V3_DOMAIN_META_BY_CODEC_ID.get('cipherstash/eql-v3/eql_v3_timestamp@1')?.castAs).toBe('timestamp') |
| 44 | + expect(V3_DOMAIN_META_BY_CODEC_ID.get('cipherstash/eql-v3/eql_v3_date@1')?.castAs).toBe('date') |
| 45 | + }) |
| 46 | + |
| 47 | + it('exposes json as a first-class searchable-JSON domain (ste_vec index)', () => { |
| 48 | + const meta = V3_DOMAIN_META_BY_CODEC_ID.get('cipherstash/eql-v3/eql_v3_json@1') |
| 49 | + expect(meta?.nativeType).toBe('public.eql_v3_json') |
| 50 | + expect(meta?.castAs).toBe('json') |
| 51 | + expect(meta?.capabilities).toEqual({ |
| 52 | + equality: false, |
| 53 | + orderAndRange: false, |
| 54 | + freeTextSearch: false, |
| 55 | + searchableJson: true, |
| 56 | + }) |
| 57 | + expect(Object.keys(meta?.indexes ?? {})).toEqual(['ste_vec']) |
| 58 | + expect(EXPOSED_DOMAIN_ENTRIES.some(([, m]) => m.bareDomain === 'eql_v3_json')).toBe(true) |
| 59 | + }) |
| 60 | + |
| 61 | + it('maps native type back to its concrete factory', () => { |
| 62 | + const factory = V3_FACTORY_BY_NATIVE_TYPE.get('public.eql_v3_integer_ord') |
| 63 | + expect(factory).toBeDefined() |
| 64 | + expect(factory?.('score').getEqlType()).toBe('public.eql_v3_integer_ord') |
| 65 | + }) |
| 66 | + |
| 67 | + it('maps castAs to the envelope type name (bigint distinct from number, json distinct)', () => { |
| 68 | + expect(envelopeTypeNameForCastAs('string')).toBe('EncryptedString') |
| 69 | + expect(envelopeTypeNameForCastAs('number')).toBe('EncryptedNumber') |
| 70 | + expect(envelopeTypeNameForCastAs('bigint')).toBe('EncryptedBigInt') |
| 71 | + expect(envelopeTypeNameForCastAs('date')).toBe('EncryptedDate') |
| 72 | + expect(envelopeTypeNameForCastAs('timestamp')).toBe('EncryptedDate') |
| 73 | + expect(envelopeTypeNameForCastAs('boolean')).toBe('EncryptedBoolean') |
| 74 | + expect(envelopeTypeNameForCastAs('json')).toBe('EncryptedJson') |
| 75 | + }) |
| 76 | + |
| 77 | + it('includes *_ord_ore in the full meta but excludes it from the exposed entries', () => { |
| 78 | + expect(V3_DOMAIN_META_BY_CODEC_ID.has('cipherstash/eql-v3/eql_v3_integer_ord_ore@1')).toBe(true) |
| 79 | + expect(isOrdOreDomain('eql_v3_integer_ord_ore')).toBe(true) |
| 80 | + const exposedBare = new Set(EXPOSED_DOMAIN_ENTRIES.map(([, m]) => m.bareDomain)) |
| 81 | + expect([...exposedBare].some((b) => b.endsWith('_ord_ore'))).toBe(false) |
| 82 | + expect(exposedBare.has('eql_v3_integer_ord')).toBe(true) |
| 83 | + expect(exposedBare.has('eql_v3_bigint')).toBe(true) |
| 84 | + }) |
| 85 | + |
| 86 | + it('every codec id is v3-namespaced and unique', () => { |
| 87 | + expect(new Set(V3_CODEC_IDS).size).toBe(V3_CODEC_IDS.length) |
| 88 | + for (const id of V3_CODEC_IDS) expect(id.startsWith('cipherstash/eql-v3/')).toBe(true) |
| 89 | + }) |
| 90 | +}) |
0 commit comments