@vielzeug/vault 2.2.0 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/README.md +0 -19
  2. package/dist/_dev.cjs +1 -1
  3. package/dist/_dev.cjs.map +1 -1
  4. package/dist/_dev.js +2 -3
  5. package/dist/_dev.js.map +1 -1
  6. package/dist/adapter-core.cjs +1 -1
  7. package/dist/adapter-core.cjs.map +1 -1
  8. package/dist/adapter-core.d.ts.map +1 -1
  9. package/dist/adapter-core.js +2 -2
  10. package/dist/adapter-core.js.map +1 -1
  11. package/dist/adapters/indexeddb.cjs +1 -1
  12. package/dist/adapters/indexeddb.cjs.map +1 -1
  13. package/dist/adapters/indexeddb.d.ts +46 -2
  14. package/dist/adapters/indexeddb.d.ts.map +1 -1
  15. package/dist/adapters/indexeddb.js +76 -56
  16. package/dist/adapters/indexeddb.js.map +1 -1
  17. package/dist/adapters/sqlite.cjs.map +1 -1
  18. package/dist/adapters/sqlite.d.ts +2 -2
  19. package/dist/adapters/sqlite.d.ts.map +1 -1
  20. package/dist/adapters/sqlite.js.map +1 -1
  21. package/dist/adapters/webstorage.cjs.map +1 -1
  22. package/dist/adapters/webstorage.d.ts.map +1 -1
  23. package/dist/adapters/webstorage.js.map +1 -1
  24. package/dist/index.cjs +1 -1
  25. package/dist/index.d.ts +1 -1
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +3 -3
  28. package/dist/indexeddb.cjs +1 -1
  29. package/dist/indexeddb.d.ts +3 -4
  30. package/dist/indexeddb.d.ts.map +1 -1
  31. package/dist/indexeddb.js +1 -2
  32. package/dist/prune.cjs +1 -1
  33. package/dist/prune.cjs.map +1 -1
  34. package/dist/prune.d.ts +8 -19
  35. package/dist/prune.d.ts.map +1 -1
  36. package/dist/prune.js +9 -13
  37. package/dist/prune.js.map +1 -1
  38. package/dist/query.cjs +1 -1
  39. package/dist/query.cjs.map +1 -1
  40. package/dist/query.d.ts +5 -11
  41. package/dist/query.d.ts.map +1 -1
  42. package/dist/query.js +1 -4
  43. package/dist/query.js.map +1 -1
  44. package/dist/sqlite.d.ts +1 -2
  45. package/dist/sqlite.d.ts.map +1 -1
  46. package/dist/ttl.cjs +1 -1
  47. package/dist/ttl.cjs.map +1 -1
  48. package/dist/ttl.d.ts +8 -12
  49. package/dist/ttl.d.ts.map +1 -1
  50. package/dist/ttl.js +5 -5
  51. package/dist/ttl.js.map +1 -1
  52. package/dist/types.cjs +1 -1
  53. package/dist/types.cjs.map +1 -1
  54. package/dist/types.d.ts +22 -34
  55. package/dist/types.d.ts.map +1 -1
  56. package/dist/types.js +14 -19
  57. package/dist/types.js.map +1 -1
  58. package/dist/vault.cjs +1 -1
  59. package/dist/vault.cjs.map +1 -1
  60. package/dist/vault.iife.js +1 -1
  61. package/dist/vault.iife.js.map +1 -1
  62. package/dist/vault.js +1 -1
  63. package/dist/vault.js.map +1 -1
  64. package/package.json +1 -1
  65. package/dist/migration.cjs +0 -2
  66. package/dist/migration.cjs.map +0 -1
  67. package/dist/migration.d.ts +0 -37
  68. package/dist/migration.d.ts.map +0 -1
  69. package/dist/migration.js +0 -25
  70. package/dist/migration.js.map +0 -1
package/dist/query.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"query.js","names":[],"sources":["../src/query.ts"],"sourcesContent":["import { VaultError } from './errors';\n\ntype Predicate<T> = (value: T, index: number, array: T[]) => boolean;\n/**\n * `isNonFilter`: when true this op is excluded from `totalCount()` — it does not restrict\n * *which* records match (limit, offset, orderBy), only how results are presented.\n */\ntype QueryOp<T> = { apply: (data: T[]) => T[]; isNonFilter?: boolean };\ntype ComparableFieldKeys<T extends object> = {\n [K in keyof T]-?: Extract<NonNullable<T[K]>, number | string> extends never ? never : K;\n}[keyof T];\n\n/**\n * A primary-key range hint that can be pushed down to native storage backends (e.g. IndexedDB).\n * When `QueryContext.getRange` and `keyField` are present, a matching first filter op replaces\n * the full-table `source()` scan with a targeted range fetch.\n */\nexport type NativeRange =\n | { type: 'eq'; value: unknown }\n | { lower: unknown; type: 'between'; upper: unknown }\n | { prefix: string; type: 'starts' };\n\nexport type QueryContext<T extends object> = {\n deleteMany?: (records: T[]) => Promise<number>;\n /**\n * When present alongside `indexedFields`, replaces `source()` for secondary-index filter ops.\n * Only activated when the first op is `equals`, `between`, or `startsWith` on a field that\n * has an index registered in the schema. IndexedDB uses `IDBIndex.getAll(range)` under the hood.\n */\n getIndexRange?: (field: string, range: NativeRange) => Promise<T[]>;\n /**\n * When present alongside `keyField`, replaces `source()` for primary-key filter ops.\n * Only activated when the first op is an `equals`, `between`, or case-sensitive `startsWith`\n * on `keyField`. All remaining ops still run in-memory against the range result.\n */\n getRange?: (range: NativeRange) => Promise<T[]>;\n /** Fields that have secondary indexes — used to detect when a filter op can use `getIndexRange`. */\n indexedFields?: ReadonlySet<string>;\n /** Primary key field name — used to detect when a filter op can be pushed to `getRange`. */\n keyField?: string;\n source: () => Promise<T[]>;\n};\n\n/* -------------------- Public interfaces -------------------- */\n\n/**\n * Shared query methods. `T` is the base record type; `N` is the progressively-narrowed type\n * accumulated by `equals()` calls.\n */\ntype ChainedQuery<T extends object, N extends T, Self extends ChainedQuery<T, N, Self>> = {\n /**\n * Filter records where `field` is between `lower` and `upper` (inclusive).\n * Preserves any type narrowing already accumulated by prior `equals()` calls.\n */\n between<K extends ComparableFieldKeys<T>>(\n field: K,\n lower: Extract<NonNullable<T[K]>, number | string>,\n upper: Extract<NonNullable<T[K]>, number | string>,\n ): QueryBuilder<T, N>;\n /**\n * Returns the number of records matching all applied operations, including `limit` and `offset`.\n * To get the full filtered set size regardless of pagination (e.g. for \"page X of N\" UIs),\n * use `totalCount()` instead.\n */\n count(): Promise<number>;\n /**\n * Filter records where `field` exactly equals `value`.\n * The return type is narrowed to `QueryBuilder<T & Record<K, V>>` so that subsequent\n * `.toArray()`, `.first()`, etc. reflect the equality constraint in their result type.\n *\n * ```ts\n * // result: (User & { role: 'admin' })[]\n * const admins = await db.query('users').equals('role', 'admin').toArray();\n * ```\n */\n equals<K extends keyof T & string, V extends T[K]>(field: K, value: V): QueryBuilder<T & Record<K, V>>;\n /**\n * Returns `true` if at least one record matches all applied filter operations.\n * Equivalent to `(await query.first()) !== undefined` but makes the intent explicit.\n * Presentation-only ops (`limit`, `offset`, `orderBy`) are respected before checking.\n */\n exists(): Promise<boolean>;\n filter(fn: Predicate<N>): Self;\n first(): Promise<N | undefined>;\n limit(n: number): Self;\n offset(n: number): Self;\n orderBy<K extends keyof T>(field: K, direction?: 'asc' | 'desc'): Self;\n /**\n * Filter records where `field` starts with `prefix`.\n * Preserves any type narrowing already accumulated by prior `equals()` calls.\n *\n * **Index push-down** is only active when `ignoreCase` is `false` (default) and this\n * is the first operation in the chain. With `ignoreCase: true`, a full-table scan is\n * always performed regardless of whether the field has an index.\n */\n startsWith<K extends keyof T>(field: K, prefix: string, options?: { ignoreCase?: boolean }): QueryBuilder<T, N>;\n toArray(): Promise<N[]>;\n /**\n * Returns the number of records matching the applied filter predicates.\n * Presentation-only ops (`limit`, `offset`, `orderBy`) are intentionally ignored — this\n * always counts the full filtered set, making paginated total-count queries possible\n * without a second query.\n */\n totalCount(): Promise<number>;\n};\n\n/** Extends the shared query API with `delete()`. Available on stores and IndexedDB transaction callbacks. */\nexport interface QueryBuilder<T extends object, N extends T = T> extends ChainedQuery<T, N, QueryBuilder<T, N>> {\n delete(): Promise<number>;\n}\n\n/* -------------------- Helpers -------------------- */\n\nasync function applyOps<T extends object>(ctx: QueryContext<T>, ops: readonly QueryOp<T>[]): Promise<T[]> {\n let data = await ctx.source();\n\n for (const op of ops) {\n data = op.apply(data);\n }\n\n return data;\n}\n\nfunction assertNonNegativeInteger(value: number, name: string): number {\n if (!Number.isInteger(value) || value < 0) {\n throw new VaultError(`${name} must be a non-negative integer`);\n }\n\n return value;\n}\n\n/* -------------------- Push-down helpers -------------------- */\n\n/** Build a new QueryContext with source replaced by a range/index fetch. Drops range hints since push-down is done. */\nfunction pushDownContext<T extends object>(ctx: QueryContext<T>, newSource: () => Promise<T[]>): QueryContext<T> {\n return { deleteMany: ctx.deleteMany, source: newSource };\n}\n\n/* -------------------- Factory -------------------- */\n\nexport function createQueryBuilder<T extends object, N extends T = T>(\n ctx: QueryContext<T>,\n ops: readonly QueryOp<T>[] = [],\n): QueryBuilder<T, N> {\n const append = (op: QueryOp<T>): QueryBuilder<T, N> => createQueryBuilder<T, N>(ctx, [...ops, op]);\n\n return {\n between(field, lower, upper) {\n const fieldStr = String(field);\n\n if (ops.length === 0) {\n if (ctx.getRange && ctx.keyField === fieldStr) {\n return createQueryBuilder(\n pushDownContext(ctx, () => ctx.getRange!({ lower, type: 'between', upper })),\n ops,\n );\n }\n\n if (ctx.getIndexRange && ctx.indexedFields?.has(fieldStr)) {\n return createQueryBuilder(\n pushDownContext(ctx, () => ctx.getIndexRange!(fieldStr, { lower, type: 'between', upper })),\n ops,\n );\n }\n }\n\n return append({\n apply: (data) =>\n data.filter((r) => {\n const v = r[field] as number | string;\n\n return v >= lower && v <= upper;\n }),\n }) as unknown as QueryBuilder<T, N>;\n },\n count(): Promise<number> {\n return applyOps(ctx, ops).then((r) => r.length);\n },\n async delete(): Promise<number> {\n if (!ctx.deleteMany) {\n throw new VaultError('query.delete is not available for this adapter context');\n }\n\n const records = await applyOps(ctx, ops);\n\n return ctx.deleteMany(records);\n },\n equals<K extends keyof T & string, V extends T[K]>(field: K, value: V): QueryBuilder<T & Record<K, V>> {\n const fieldStr = String(field);\n\n if (ops.length === 0) {\n if (ctx.getRange && ctx.keyField === fieldStr) {\n return createQueryBuilder<T & Record<K, V>>(\n pushDownContext(\n ctx as unknown as QueryContext<T & Record<K, V>>,\n () => ctx.getRange!({ type: 'eq', value }) as Promise<(T & Record<K, V>)[]>,\n ),\n ) as QueryBuilder<T & Record<K, V>>;\n }\n\n if (ctx.getIndexRange && ctx.indexedFields?.has(fieldStr)) {\n return createQueryBuilder<T & Record<K, V>>(\n pushDownContext(\n ctx as unknown as QueryContext<T & Record<K, V>>,\n () => ctx.getIndexRange!(fieldStr, { type: 'eq', value }) as Promise<(T & Record<K, V>)[]>,\n ),\n ) as QueryBuilder<T & Record<K, V>>;\n }\n }\n\n return createQueryBuilder<T & Record<K, V>>(ctx as unknown as QueryContext<T & Record<K, V>>, [\n ...(ops as unknown as QueryOp<T & Record<K, V>>[]),\n { apply: (data) => data.filter((r) => r[field] === value) as (T & Record<K, V>)[] },\n ]);\n },\n async exists(): Promise<boolean> {\n if (ops.length === 0) return ctx.source().then((r) => r.length > 0);\n\n return applyOps(ctx, ops).then((r) => r.length > 0);\n },\n filter(fn) {\n return append({ apply: (data) => data.filter(fn as Predicate<T>) });\n },\n first(): Promise<N | undefined> {\n if (ops.length === 0) return ctx.source().then((r) => r[0] as N | undefined);\n\n return applyOps(ctx, ops).then((r) => r[0] as N | undefined);\n },\n limit(n) {\n const safeN = assertNonNegativeInteger(n, 'query.limit');\n\n return append({ apply: (data) => data.slice(0, safeN), isNonFilter: true });\n },\n offset(n) {\n const safeN = assertNonNegativeInteger(n, 'query.offset');\n\n return append({ apply: (data) => data.slice(safeN), isNonFilter: true });\n },\n orderBy(field, direction = 'asc') {\n return append({\n apply: (data) => {\n const sign = direction === 'asc' ? 1 : -1;\n\n return [...data].sort((a, b) => {\n const av = a[field] as number | string;\n const bv = b[field] as number | string;\n\n if (av === bv) return 0;\n\n return av > bv ? sign : -sign;\n });\n },\n isNonFilter: true,\n });\n },\n startsWith(field, prefix, { ignoreCase = false } = {}) {\n const fieldStr = String(field);\n\n if (!ignoreCase && prefix.length > 0 && ops.length === 0) {\n if (ctx.getRange && ctx.keyField === fieldStr) {\n return createQueryBuilder(\n pushDownContext(ctx, () => ctx.getRange!({ prefix, type: 'starts' })),\n ops,\n );\n }\n\n if (ctx.getIndexRange && ctx.indexedFields?.has(fieldStr)) {\n return createQueryBuilder(\n pushDownContext(ctx, () => ctx.getIndexRange!(fieldStr, { prefix, type: 'starts' })),\n ops,\n );\n }\n }\n\n const needle = ignoreCase ? prefix.toLowerCase() : prefix;\n\n return append({\n apply: (data) =>\n data.filter((r) => {\n const v = r[field];\n\n if (typeof v !== 'string') return false;\n\n const haystack = ignoreCase ? v.toLowerCase() : v;\n\n return haystack.startsWith(needle);\n }),\n }) as unknown as QueryBuilder<T, N>;\n },\n toArray(): Promise<N[]> {\n return applyOps(ctx, ops) as Promise<N[]>;\n },\n totalCount(): Promise<number> {\n const filterOps = ops.filter((op) => !op.isNonFilter);\n\n return applyOps(ctx, filterOps).then((r) => r.length);\n },\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"query.js","names":[],"sources":["../src/query.ts"],"sourcesContent":["import { VaultError } from './errors';\n\ntype Predicate<T> = (value: T, index: number, array: T[]) => boolean;\n/**\n * `isNonFilter`: when true this op is excluded from `count()` — it does not restrict\n * *which* records match (limit, offset, orderBy), only how results are presented.\n */\ntype QueryOp<T> = { apply: (data: T[]) => T[]; isNonFilter?: boolean };\ntype ComparableFieldKeys<T extends object> = {\n [K in keyof T]-?: Extract<NonNullable<T[K]>, number | string> extends never ? never : K;\n}[keyof T];\n\n/**\n * A primary-key range hint that can be pushed down to native storage backends (e.g. IndexedDB).\n * When `QueryContext.getRange` and `keyField` are present, a matching first filter op replaces\n * the full-table `source()` scan with a targeted range fetch.\n */\nexport type NativeRange =\n | { type: 'eq'; value: unknown }\n | { lower: unknown; type: 'between'; upper: unknown }\n | { prefix: string; type: 'starts' };\n\nexport type QueryContext<T extends object> = {\n deleteMany?: (records: T[]) => Promise<number>;\n /**\n * When present alongside `indexedFields`, replaces `source()` for secondary-index filter ops.\n * Only activated when the first op is `equals`, `between`, or `startsWith` on a field that\n * has an index registered in the schema. IndexedDB uses `IDBIndex.getAll(range)` under the hood.\n */\n getIndexRange?: (field: string, range: NativeRange) => Promise<T[]>;\n /**\n * When present alongside `keyField`, replaces `source()` for primary-key filter ops.\n * Only activated when the first op is an `equals`, `between`, or case-sensitive `startsWith`\n * on `keyField`. All remaining ops still run in-memory against the range result.\n */\n getRange?: (range: NativeRange) => Promise<T[]>;\n /** Fields that have secondary indexes — used to detect when a filter op can use `getIndexRange`. */\n indexedFields?: ReadonlySet<string>;\n /** Primary key field name — used to detect when a filter op can be pushed to `getRange`. */\n keyField?: string;\n source: () => Promise<T[]>;\n};\n\n/* -------------------- Public interfaces -------------------- */\n\n/**\n * Shared query methods. `T` is the base record type; `N` is the progressively-narrowed type\n * accumulated by `equals()` calls.\n */\ntype ChainedQuery<T extends object, N extends T, Self extends ChainedQuery<T, N, Self>> = {\n /**\n * Filter records where `field` is between `lower` and `upper` (inclusive).\n * Preserves any type narrowing already accumulated by prior `equals()` calls.\n */\n between<K extends ComparableFieldKeys<T>>(\n field: K,\n lower: Extract<NonNullable<T[K]>, number | string>,\n upper: Extract<NonNullable<T[K]>, number | string>,\n ): QueryBuilder<T, N>;\n /**\n * Returns the number of records matching the applied filter predicates.\n * Presentation-only ops (`limit`, `offset`, `orderBy`) are intentionally ignored — this\n * always counts the full filtered set, making paginated total-count queries possible\n * without a second query.\n */\n count(): Promise<number>;\n /**\n * Filter records where `field` exactly equals `value`.\n * The return type is narrowed to `QueryBuilder<T & Record<K, V>>` so that subsequent\n * `.toArray()`, `.first()`, etc. reflect the equality constraint in their result type.\n *\n * ```ts\n * // result: (User & { role: 'admin' })[]\n * const admins = await db.query('users').equals('role', 'admin').toArray();\n * ```\n */\n equals<K extends keyof T & string, V extends T[K]>(field: K, value: V): QueryBuilder<T & Record<K, V>>;\n /**\n * Returns `true` if at least one record matches all applied filter operations.\n * Equivalent to `(await query.first()) !== undefined` but makes the intent explicit.\n * Presentation-only ops (`limit`, `offset`, `orderBy`) are respected before checking.\n */\n exists(): Promise<boolean>;\n filter(fn: Predicate<N>): Self;\n first(): Promise<N | undefined>;\n limit(n: number): Self;\n offset(n: number): Self;\n orderBy<K extends keyof T>(field: K, direction?: 'asc' | 'desc'): Self;\n /**\n * Filter records where `field` starts with `prefix`.\n * Preserves any type narrowing already accumulated by prior `equals()` calls.\n *\n * **Index push-down** is only active when `ignoreCase` is `false` (default) and this\n * is the first operation in the chain. With `ignoreCase: true`, a full-table scan is\n * always performed regardless of whether the field has an index.\n */\n startsWith<K extends keyof T>(field: K, prefix: string, options?: { ignoreCase?: boolean }): QueryBuilder<T, N>;\n toArray(): Promise<N[]>;\n};\n\n/** Extends the shared query API with `delete()`. Available on stores and IndexedDB transaction callbacks. */\nexport interface QueryBuilder<T extends object, N extends T = T> extends ChainedQuery<T, N, QueryBuilder<T, N>> {\n delete(): Promise<number>;\n}\n\n/* -------------------- Helpers -------------------- */\n\nasync function applyOps<T extends object>(ctx: QueryContext<T>, ops: readonly QueryOp<T>[]): Promise<T[]> {\n let data = await ctx.source();\n\n for (const op of ops) {\n data = op.apply(data);\n }\n\n return data;\n}\n\nfunction assertNonNegativeInteger(value: number, name: string): number {\n if (!Number.isInteger(value) || value < 0) {\n throw new VaultError(`${name} must be a non-negative integer`);\n }\n\n return value;\n}\n\n/* -------------------- Push-down helpers -------------------- */\n\n/** Build a new QueryContext with source replaced by a range/index fetch. Drops range hints since push-down is done. */\nfunction pushDownContext<T extends object>(ctx: QueryContext<T>, newSource: () => Promise<T[]>): QueryContext<T> {\n return { deleteMany: ctx.deleteMany, source: newSource };\n}\n\n/* -------------------- Factory -------------------- */\n\nexport function createQueryBuilder<T extends object, N extends T = T>(\n ctx: QueryContext<T>,\n ops: readonly QueryOp<T>[] = [],\n): QueryBuilder<T, N> {\n const append = (op: QueryOp<T>): QueryBuilder<T, N> => createQueryBuilder<T, N>(ctx, [...ops, op]);\n\n return {\n between(field, lower, upper) {\n const fieldStr = String(field);\n\n if (ops.length === 0) {\n if (ctx.getRange && ctx.keyField === fieldStr) {\n return createQueryBuilder(\n pushDownContext(ctx, () => ctx.getRange!({ lower, type: 'between', upper })),\n ops,\n );\n }\n\n if (ctx.getIndexRange && ctx.indexedFields?.has(fieldStr)) {\n return createQueryBuilder(\n pushDownContext(ctx, () => ctx.getIndexRange!(fieldStr, { lower, type: 'between', upper })),\n ops,\n );\n }\n }\n\n return append({\n apply: (data) =>\n data.filter((r) => {\n const v = r[field] as number | string;\n\n return v >= lower && v <= upper;\n }),\n }) as unknown as QueryBuilder<T, N>;\n },\n count(): Promise<number> {\n const filterOps = ops.filter((op) => !op.isNonFilter);\n\n return applyOps(ctx, filterOps).then((r) => r.length);\n },\n async delete(): Promise<number> {\n if (!ctx.deleteMany) {\n throw new VaultError('query.delete is not available for this adapter context');\n }\n\n const records = await applyOps(ctx, ops);\n\n return ctx.deleteMany(records);\n },\n equals<K extends keyof T & string, V extends T[K]>(field: K, value: V): QueryBuilder<T & Record<K, V>> {\n const fieldStr = String(field);\n\n if (ops.length === 0) {\n if (ctx.getRange && ctx.keyField === fieldStr) {\n return createQueryBuilder<T & Record<K, V>>(\n pushDownContext(\n ctx as unknown as QueryContext<T & Record<K, V>>,\n () => ctx.getRange!({ type: 'eq', value }) as Promise<(T & Record<K, V>)[]>,\n ),\n ) as QueryBuilder<T & Record<K, V>>;\n }\n\n if (ctx.getIndexRange && ctx.indexedFields?.has(fieldStr)) {\n return createQueryBuilder<T & Record<K, V>>(\n pushDownContext(\n ctx as unknown as QueryContext<T & Record<K, V>>,\n () => ctx.getIndexRange!(fieldStr, { type: 'eq', value }) as Promise<(T & Record<K, V>)[]>,\n ),\n ) as QueryBuilder<T & Record<K, V>>;\n }\n }\n\n return createQueryBuilder<T & Record<K, V>>(ctx as unknown as QueryContext<T & Record<K, V>>, [\n ...(ops as unknown as QueryOp<T & Record<K, V>>[]),\n { apply: (data) => data.filter((r) => r[field] === value) as (T & Record<K, V>)[] },\n ]);\n },\n async exists(): Promise<boolean> {\n if (ops.length === 0) return ctx.source().then((r) => r.length > 0);\n\n return applyOps(ctx, ops).then((r) => r.length > 0);\n },\n filter(fn) {\n return append({ apply: (data) => data.filter(fn as Predicate<T>) });\n },\n first(): Promise<N | undefined> {\n if (ops.length === 0) return ctx.source().then((r) => r[0] as N | undefined);\n\n return applyOps(ctx, ops).then((r) => r[0] as N | undefined);\n },\n limit(n) {\n const safeN = assertNonNegativeInteger(n, 'query.limit');\n\n return append({ apply: (data) => data.slice(0, safeN), isNonFilter: true });\n },\n offset(n) {\n const safeN = assertNonNegativeInteger(n, 'query.offset');\n\n return append({ apply: (data) => data.slice(safeN), isNonFilter: true });\n },\n orderBy(field, direction = 'asc') {\n return append({\n apply: (data) => {\n const sign = direction === 'asc' ? 1 : -1;\n\n return [...data].sort((a, b) => {\n const av = a[field] as number | string;\n const bv = b[field] as number | string;\n\n if (av === bv) return 0;\n\n return av > bv ? sign : -sign;\n });\n },\n isNonFilter: true,\n });\n },\n startsWith(field, prefix, { ignoreCase = false } = {}) {\n const fieldStr = String(field);\n\n if (!ignoreCase && prefix.length > 0 && ops.length === 0) {\n if (ctx.getRange && ctx.keyField === fieldStr) {\n return createQueryBuilder(\n pushDownContext(ctx, () => ctx.getRange!({ prefix, type: 'starts' })),\n ops,\n );\n }\n\n if (ctx.getIndexRange && ctx.indexedFields?.has(fieldStr)) {\n return createQueryBuilder(\n pushDownContext(ctx, () => ctx.getIndexRange!(fieldStr, { prefix, type: 'starts' })),\n ops,\n );\n }\n }\n\n const needle = ignoreCase ? prefix.toLowerCase() : prefix;\n\n return append({\n apply: (data) =>\n data.filter((r) => {\n const v = r[field];\n\n if (typeof v !== 'string') return false;\n\n const haystack = ignoreCase ? v.toLowerCase() : v;\n\n return haystack.startsWith(needle);\n }),\n }) as unknown as QueryBuilder<T, N>;\n },\n toArray(): Promise<N[]> {\n return applyOps(ctx, ops) as Promise<N[]>;\n },\n };\n}\n"],"mappings":";;AA2GA,eAAe,EAA2B,GAAsB,GAA0C;CACxG,IAAI,IAAO,MAAM,EAAI,OAAO;CAE5B,KAAK,IAAM,KAAM,GACf,IAAO,EAAG,MAAM,CAAI;CAGtB,OAAO;AACT;AAEA,SAAS,EAAyB,GAAe,GAAsB;CACrE,IAAI,CAAC,OAAO,UAAU,CAAK,KAAK,IAAQ,GACtC,MAAM,IAAI,EAAW,GAAG,EAAK,gCAAgC;CAG/D,OAAO;AACT;AAKA,SAAS,EAAkC,GAAsB,GAAgD;CAC/G,OAAO;EAAE,YAAY,EAAI;EAAY,QAAQ;CAAU;AACzD;AAIA,SAAgB,EACd,GACA,IAA6B,CAAC,GACV;CACpB,IAAM,KAAU,MAAuC,EAAyB,GAAK,CAAC,GAAG,GAAK,CAAE,CAAC;CAEjG,OAAO;EACL,QAAQ,GAAO,GAAO,GAAO;GAC3B,IAAM,IAAW,OAAO,CAAK;GAE7B,IAAI,EAAI,WAAW,GAAG;IACpB,IAAI,EAAI,YAAY,EAAI,aAAa,GACnC,OAAO,EACL,EAAgB,SAAW,EAAI,SAAU;KAAE;KAAO,MAAM;KAAW;IAAM,CAAC,CAAC,GAC3E,CACF;IAGF,IAAI,EAAI,iBAAiB,EAAI,eAAe,IAAI,CAAQ,GACtD,OAAO,EACL,EAAgB,SAAW,EAAI,cAAe,GAAU;KAAE;KAAO,MAAM;KAAW;IAAM,CAAC,CAAC,GAC1F,CACF;GAEJ;GAEA,OAAO,EAAO,EACZ,QAAQ,MACN,EAAK,QAAQ,MAAM;IACjB,IAAM,IAAI,EAAE;IAEZ,OAAO,KAAK,KAAS,KAAK;GAC5B,CAAC,EACL,CAAC;EACH;EACA,QAAyB;GAGvB,OAAO,EAAS,GAFE,EAAI,QAAQ,MAAO,CAAC,EAAG,WAEpB,CAAS,CAAC,CAAC,MAAM,MAAM,EAAE,MAAM;EACtD;EACA,MAAM,SAA0B;GAC9B,IAAI,CAAC,EAAI,YACP,MAAM,IAAI,EAAW,wDAAwD;GAG/E,IAAM,IAAU,MAAM,EAAS,GAAK,CAAG;GAEvC,OAAO,EAAI,WAAW,CAAO;EAC/B;EACA,OAAmD,GAAU,GAA0C;GACrG,IAAM,IAAW,OAAO,CAAK;GAE7B,IAAI,EAAI,WAAW,GAAG;IACpB,IAAI,EAAI,YAAY,EAAI,aAAa,GACnC,OAAO,EACL,EACE,SACM,EAAI,SAAU;KAAE,MAAM;KAAM;IAAM,CAAC,CAC3C,CACF;IAGF,IAAI,EAAI,iBAAiB,EAAI,eAAe,IAAI,CAAQ,GACtD,OAAO,EACL,EACE,SACM,EAAI,cAAe,GAAU;KAAE,MAAM;KAAM;IAAM,CAAC,CAC1D,CACF;GAEJ;GAEA,OAAO,EAAqC,GAAkD,CAC5F,GAAI,GACJ,EAAE,QAAQ,MAAS,EAAK,QAAQ,MAAM,EAAE,OAAW,CAAK,EAA0B,CACpF,CAAC;EACH;EACA,MAAM,SAA2B;GAG/B,OAFI,EAAI,WAAW,IAAU,EAAI,OAAO,CAAC,CAAC,MAAM,MAAM,EAAE,SAAS,CAAC,IAE3D,EAAS,GAAK,CAAG,CAAC,CAAC,MAAM,MAAM,EAAE,SAAS,CAAC;EACpD;EACA,OAAO,GAAI;GACT,OAAO,EAAO,EAAE,QAAQ,MAAS,EAAK,OAAO,CAAkB,EAAE,CAAC;EACpE;EACA,QAAgC;GAG9B,OAFI,EAAI,WAAW,IAAU,EAAI,OAAO,CAAC,CAAC,MAAM,MAAM,EAAE,EAAmB,IAEpE,EAAS,GAAK,CAAG,CAAC,CAAC,MAAM,MAAM,EAAE,EAAmB;EAC7D;EACA,MAAM,GAAG;GACP,IAAM,IAAQ,EAAyB,GAAG,aAAa;GAEvD,OAAO,EAAO;IAAE,QAAQ,MAAS,EAAK,MAAM,GAAG,CAAK;IAAG,aAAa;GAAK,CAAC;EAC5E;EACA,OAAO,GAAG;GACR,IAAM,IAAQ,EAAyB,GAAG,cAAc;GAExD,OAAO,EAAO;IAAE,QAAQ,MAAS,EAAK,MAAM,CAAK;IAAG,aAAa;GAAK,CAAC;EACzE;EACA,QAAQ,GAAO,IAAY,OAAO;GAChC,OAAO,EAAO;IACZ,QAAQ,MAAS;KACf,IAAM,IAAO,MAAc,QAAQ,IAAI;KAEvC,OAAO,CAAC,GAAG,CAAI,CAAC,CAAC,MAAM,GAAG,MAAM;MAC9B,IAAM,IAAK,EAAE,IACP,IAAK,EAAE;MAIb,OAFI,MAAO,IAAW,IAEf,IAAK,IAAK,IAAO,CAAC;KAC3B,CAAC;IACH;IACA,aAAa;GACf,CAAC;EACH;EACA,WAAW,GAAO,GAAQ,EAAE,gBAAa,OAAU,CAAC,GAAG;GACrD,IAAM,IAAW,OAAO,CAAK;GAE7B,IAAI,CAAC,KAAc,EAAO,SAAS,KAAK,EAAI,WAAW,GAAG;IACxD,IAAI,EAAI,YAAY,EAAI,aAAa,GACnC,OAAO,EACL,EAAgB,SAAW,EAAI,SAAU;KAAE;KAAQ,MAAM;IAAS,CAAC,CAAC,GACpE,CACF;IAGF,IAAI,EAAI,iBAAiB,EAAI,eAAe,IAAI,CAAQ,GACtD,OAAO,EACL,EAAgB,SAAW,EAAI,cAAe,GAAU;KAAE;KAAQ,MAAM;IAAS,CAAC,CAAC,GACnF,CACF;GAEJ;GAEA,IAAM,IAAS,IAAa,EAAO,YAAY,IAAI;GAEnD,OAAO,EAAO,EACZ,QAAQ,MACN,EAAK,QAAQ,MAAM;IACjB,IAAM,IAAI,EAAE;IAMZ,OAJI,OAAO,KAAM,aAEA,IAAa,EAAE,YAAY,IAAI,EAAA,CAEhC,WAAW,CAAM;GACnC,CAAC,EACL,CAAC;EACH;EACA,UAAwB;GACtB,OAAO,EAAS,GAAK,CAAG;EAC1B;CACF;AACF"}
package/dist/sqlite.d.ts CHANGED
@@ -1,4 +1,3 @@
1
- export type { SQLiteDatabase, SQLiteParameter, SQLiteStatement, SQLiteVaultOptions, SQLiteVaultStore, } from './adapters/sqlite';
1
+ export type { SQLiteDatabase, SQLiteParameter, SQLiteStatement, SQLiteVaultOptions, SQLiteVaultStore, TransactionContext, } from './adapters/sqlite';
2
2
  export { createSQLite } from './adapters/sqlite';
3
- export type { TransactionContext } from './types';
4
3
  //# sourceMappingURL=sqlite.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sqlite.d.ts","sourceRoot":"","sources":["../src/sqlite.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,cAAc,EACd,eAAe,EACf,eAAe,EACf,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,YAAY,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC"}
1
+ {"version":3,"file":"sqlite.d.ts","sourceRoot":"","sources":["../src/sqlite.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,cAAc,EACd,eAAe,EACf,eAAe,EACf,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC"}
package/dist/ttl.cjs CHANGED
@@ -1,2 +1,2 @@
1
- const e=require("./errors.cjs");var t={days:e=>r(r(e,`ttl.days`)*864e5,`ttl.days (result)`),hours:e=>r(r(e,`ttl.hours`)*36e5,`ttl.hours (result)`),minutes:e=>r(r(e,`ttl.minutes`)*6e4,`ttl.minutes (result)`),ms:e=>r(e,`ttl.ms`),seconds:e=>r(r(e,`ttl.seconds`)*1e3,`ttl.seconds (result)`)};function n(e){return e!==void 0&&Date.now()>=e}function r(t,n){if(!Number.isFinite(t)||t<=0)throw new e.VaultError(`${n} expected a finite positive number, received ${String(t)}`);return t}function i(e){if(typeof e!=`object`||!e||!(`value`in e))return;let t=e;if(!(t.expiresAt!==void 0&&(typeof t.expiresAt!=`number`||!Number.isFinite(t.expiresAt))))return t}exports.assertTtlMs=r,exports.isExpired=n,exports.parseStored=i,exports.ttl=t;
1
+ const e=require("./errors.cjs");var t={days:e=>r(e*864e5,`ttl.days`),hours:e=>r(e*36e5,`ttl.hours`),minutes:e=>r(e*6e4,`ttl.minutes`),ms:e=>r(e,`ttl.ms`),seconds:e=>r(e*1e3,`ttl.seconds`)};function n(e){return e!==void 0&&Date.now()>=e}function r(t,n){if(!Number.isFinite(t)||t<=0)throw new e.VaultError(`${n} expected a finite positive number, received ${String(t)}`);return t}function i(e){if(typeof e!=`object`||!e||!(`value`in e))return;let t=e;if(!(t.expiresAt!==void 0&&(typeof t.expiresAt!=`number`||!Number.isFinite(t.expiresAt))))return t}exports.assertPositiveFinite=r,exports.isExpired=n,exports.parseStored=i,exports.ttl=t;
2
2
  //# sourceMappingURL=ttl.cjs.map
package/dist/ttl.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"ttl.cjs","names":[],"sources":["../src/ttl.ts"],"sourcesContent":["import { VaultError } from './errors';\n\ndeclare const ttlMsBrand: unique symbol;\n/** A duration in milliseconds, produced by the `ttl.*` helpers. */\nexport type TtlMs = number & { readonly [ttlMsBrand]: never };\n\nexport const ttl = {\n days: (n: number) => assertTtlMs(assertTtlMs(n, 'ttl.days') * 86_400_000, 'ttl.days (result)'),\n hours: (n: number) => assertTtlMs(assertTtlMs(n, 'ttl.hours') * 3_600_000, 'ttl.hours (result)'),\n minutes: (n: number) => assertTtlMs(assertTtlMs(n, 'ttl.minutes') * 60_000, 'ttl.minutes (result)'),\n ms: (n: number) => assertTtlMs(n, 'ttl.ms'),\n seconds: (n: number) => assertTtlMs(assertTtlMs(n, 'ttl.seconds') * 1000, 'ttl.seconds (result)'),\n} as const;\n\n/** Fixed storage envelope shared by every adapter, so data and indexes stay portable. */\nexport type StoredRecord<T> = { expiresAt?: number; value: T };\n\nexport function isExpired(expiresAt: number | undefined): boolean {\n return expiresAt !== undefined && Date.now() >= expiresAt;\n}\n\nexport function assertTtlMs(ttlMs: number, source: string): TtlMs {\n if (!Number.isFinite(ttlMs) || ttlMs <= 0) {\n throw new VaultError(`${source} expected a finite positive number, received ${String(ttlMs)}`);\n }\n\n return ttlMs as TtlMs;\n}\n\nexport function parseStored<T>(raw: unknown): StoredRecord<T> | undefined {\n if (typeof raw !== 'object' || raw === null || !('value' in raw)) return undefined;\n\n const record = raw as { expiresAt?: unknown; value: unknown };\n\n if (record.expiresAt !== undefined && (typeof record.expiresAt !== 'number' || !Number.isFinite(record.expiresAt))) {\n return undefined;\n }\n\n return record as StoredRecord<T>;\n}\n"],"mappings":"gCAMA,IAAa,EAAM,CACjB,KAAO,GAAc,EAAY,EAAY,EAAG,UAAU,EAAI,MAAY,mBAAmB,EAC7F,MAAQ,GAAc,EAAY,EAAY,EAAG,WAAW,EAAI,KAAW,oBAAoB,EAC/F,QAAU,GAAc,EAAY,EAAY,EAAG,aAAa,EAAI,IAAQ,sBAAsB,EAClG,GAAK,GAAc,EAAY,EAAG,QAAQ,EAC1C,QAAU,GAAc,EAAY,EAAY,EAAG,aAAa,EAAI,IAAM,sBAAsB,CAClG,EAKA,SAAgB,EAAU,EAAwC,CAChE,OAAO,IAAc,IAAA,IAAa,KAAK,IAAI,GAAK,CAClD,CAEA,SAAgB,EAAY,EAAe,EAAuB,CAChE,GAAI,CAAC,OAAO,SAAS,CAAK,GAAK,GAAS,EACtC,MAAM,IAAI,EAAA,WAAW,GAAG,EAAO,+CAA+C,OAAO,CAAK,GAAG,EAG/F,OAAO,CACT,CAEA,SAAgB,EAAe,EAA2C,CACxE,GAAI,OAAO,GAAQ,WAAY,GAAgB,EAAE,UAAW,GAAM,OAElE,IAAM,EAAS,EAEX,OAAO,YAAc,IAAA,KAAc,OAAO,EAAO,WAAc,UAAY,CAAC,OAAO,SAAS,EAAO,SAAS,IAIhH,OAAO,CACT"}
1
+ {"version":3,"file":"ttl.cjs","names":[],"sources":["../src/ttl.ts"],"sourcesContent":["import { VaultError } from './errors';\n\n/** Duration helpers that produce finite, positive millisecond values. */\nexport const ttl = {\n days: (n: number) => assertPositiveFinite(n * 86_400_000, 'ttl.days'),\n hours: (n: number) => assertPositiveFinite(n * 3_600_000, 'ttl.hours'),\n minutes: (n: number) => assertPositiveFinite(n * 60_000, 'ttl.minutes'),\n ms: (n: number) => assertPositiveFinite(n, 'ttl.ms'),\n seconds: (n: number) => assertPositiveFinite(n * 1000, 'ttl.seconds'),\n} as const;\n\n/** Fixed storage envelope shared by every adapter, so data and indexes stay portable. */\nexport type StoredRecord<T> = { expiresAt?: number; value: T };\n\nexport function isExpired(expiresAt: number | undefined): boolean {\n return expiresAt !== undefined && Date.now() >= expiresAt;\n}\n\n/** Throws when `ttlMs` is not a finite, positive number. Returns it unchanged otherwise. */\nexport function assertPositiveFinite(ttlMs: number, source: string): number {\n if (!Number.isFinite(ttlMs) || ttlMs <= 0) {\n throw new VaultError(`${source} expected a finite positive number, received ${String(ttlMs)}`);\n }\n\n return ttlMs;\n}\n\nexport function parseStored<T>(raw: unknown): StoredRecord<T> | undefined {\n if (typeof raw !== 'object' || raw === null || !('value' in raw)) return undefined;\n\n const record = raw as { expiresAt?: unknown; value: unknown };\n\n if (record.expiresAt !== undefined && (typeof record.expiresAt !== 'number' || !Number.isFinite(record.expiresAt))) {\n return undefined;\n }\n\n return record as StoredRecord<T>;\n}\n"],"mappings":"gCAGA,IAAa,EAAM,CACjB,KAAO,GAAc,EAAqB,EAAI,MAAY,UAAU,EACpE,MAAQ,GAAc,EAAqB,EAAI,KAAW,WAAW,EACrE,QAAU,GAAc,EAAqB,EAAI,IAAQ,aAAa,EACtE,GAAK,GAAc,EAAqB,EAAG,QAAQ,EACnD,QAAU,GAAc,EAAqB,EAAI,IAAM,aAAa,CACtE,EAKA,SAAgB,EAAU,EAAwC,CAChE,OAAO,IAAc,IAAA,IAAa,KAAK,IAAI,GAAK,CAClD,CAGA,SAAgB,EAAqB,EAAe,EAAwB,CAC1E,GAAI,CAAC,OAAO,SAAS,CAAK,GAAK,GAAS,EACtC,MAAM,IAAI,EAAA,WAAW,GAAG,EAAO,+CAA+C,OAAO,CAAK,GAAG,EAG/F,OAAO,CACT,CAEA,SAAgB,EAAe,EAA2C,CACxE,GAAI,OAAO,GAAQ,WAAY,GAAgB,EAAE,UAAW,GAAM,OAElE,IAAM,EAAS,EAEX,OAAO,YAAc,IAAA,KAAc,OAAO,EAAO,WAAc,UAAY,CAAC,OAAO,SAAS,EAAO,SAAS,IAIhH,OAAO,CACT"}
package/dist/ttl.d.ts CHANGED
@@ -1,14 +1,10 @@
1
- declare const ttlMsBrand: unique symbol;
2
- /** A duration in milliseconds, produced by the `ttl.*` helpers. */
3
- export type TtlMs = number & {
4
- readonly [ttlMsBrand]: never;
5
- };
1
+ /** Duration helpers that produce finite, positive millisecond values. */
6
2
  export declare const ttl: {
7
- readonly days: (n: number) => TtlMs;
8
- readonly hours: (n: number) => TtlMs;
9
- readonly minutes: (n: number) => TtlMs;
10
- readonly ms: (n: number) => TtlMs;
11
- readonly seconds: (n: number) => TtlMs;
3
+ readonly days: (n: number) => number;
4
+ readonly hours: (n: number) => number;
5
+ readonly minutes: (n: number) => number;
6
+ readonly ms: (n: number) => number;
7
+ readonly seconds: (n: number) => number;
12
8
  };
13
9
  /** Fixed storage envelope shared by every adapter, so data and indexes stay portable. */
14
10
  export type StoredRecord<T> = {
@@ -16,7 +12,7 @@ export type StoredRecord<T> = {
16
12
  value: T;
17
13
  };
18
14
  export declare function isExpired(expiresAt: number | undefined): boolean;
19
- export declare function assertTtlMs(ttlMs: number, source: string): TtlMs;
15
+ /** Throws when `ttlMs` is not a finite, positive number. Returns it unchanged otherwise. */
16
+ export declare function assertPositiveFinite(ttlMs: number, source: string): number;
20
17
  export declare function parseStored<T>(raw: unknown): StoredRecord<T> | undefined;
21
- export {};
22
18
  //# sourceMappingURL=ttl.d.ts.map
package/dist/ttl.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"ttl.d.ts","sourceRoot":"","sources":["../src/ttl.ts"],"names":[],"mappings":"AAEA,OAAO,CAAC,MAAM,UAAU,EAAE,OAAO,MAAM,CAAC;AACxC,mEAAmE;AACnE,MAAM,MAAM,KAAK,GAAG,MAAM,GAAG;IAAE,QAAQ,CAAC,CAAC,UAAU,CAAC,EAAE,KAAK,CAAA;CAAE,CAAC;AAE9D,eAAO,MAAM,GAAG;uBACJ,MAAM;wBACL,MAAM;0BACJ,MAAM;qBACX,MAAM;0BACD,MAAM;CACX,CAAC;AAEX,yFAAyF;AACzF,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAE,CAAC;AAE/D,wBAAgB,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAEhE;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,KAAK,CAMhE;AAED,wBAAgB,WAAW,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,GAAG,YAAY,CAAC,CAAC,CAAC,GAAG,SAAS,CAUxE"}
1
+ {"version":3,"file":"ttl.d.ts","sourceRoot":"","sources":["../src/ttl.ts"],"names":[],"mappings":"AAEA,yEAAyE;AACzE,eAAO,MAAM,GAAG;uBACJ,MAAM;wBACL,MAAM;0BACJ,MAAM;qBACX,MAAM;0BACD,MAAM;CACX,CAAC;AAEX,yFAAyF;AACzF,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAE,CAAC;AAE/D,wBAAgB,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAEhE;AAED,4FAA4F;AAC5F,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAM1E;AAED,wBAAgB,WAAW,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,GAAG,YAAY,CAAC,CAAC,CAAC,GAAG,SAAS,CAUxE"}
package/dist/ttl.js CHANGED
@@ -1,11 +1,11 @@
1
1
  import { VaultError as e } from "./errors.js";
2
2
  //#region src/ttl.ts
3
3
  var t = {
4
- days: (e) => r(r(e, "ttl.days") * 864e5, "ttl.days (result)"),
5
- hours: (e) => r(r(e, "ttl.hours") * 36e5, "ttl.hours (result)"),
6
- minutes: (e) => r(r(e, "ttl.minutes") * 6e4, "ttl.minutes (result)"),
4
+ days: (e) => r(e * 864e5, "ttl.days"),
5
+ hours: (e) => r(e * 36e5, "ttl.hours"),
6
+ minutes: (e) => r(e * 6e4, "ttl.minutes"),
7
7
  ms: (e) => r(e, "ttl.ms"),
8
- seconds: (e) => r(r(e, "ttl.seconds") * 1e3, "ttl.seconds (result)")
8
+ seconds: (e) => r(e * 1e3, "ttl.seconds")
9
9
  };
10
10
  function n(e) {
11
11
  return e !== void 0 && Date.now() >= e;
@@ -20,6 +20,6 @@ function i(e) {
20
20
  if (!(t.expiresAt !== void 0 && (typeof t.expiresAt != "number" || !Number.isFinite(t.expiresAt)))) return t;
21
21
  }
22
22
  //#endregion
23
- export { r as assertTtlMs, n as isExpired, i as parseStored, t as ttl };
23
+ export { r as assertPositiveFinite, n as isExpired, i as parseStored, t as ttl };
24
24
 
25
25
  //# sourceMappingURL=ttl.js.map
package/dist/ttl.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"ttl.js","names":[],"sources":["../src/ttl.ts"],"sourcesContent":["import { VaultError } from './errors';\n\ndeclare const ttlMsBrand: unique symbol;\n/** A duration in milliseconds, produced by the `ttl.*` helpers. */\nexport type TtlMs = number & { readonly [ttlMsBrand]: never };\n\nexport const ttl = {\n days: (n: number) => assertTtlMs(assertTtlMs(n, 'ttl.days') * 86_400_000, 'ttl.days (result)'),\n hours: (n: number) => assertTtlMs(assertTtlMs(n, 'ttl.hours') * 3_600_000, 'ttl.hours (result)'),\n minutes: (n: number) => assertTtlMs(assertTtlMs(n, 'ttl.minutes') * 60_000, 'ttl.minutes (result)'),\n ms: (n: number) => assertTtlMs(n, 'ttl.ms'),\n seconds: (n: number) => assertTtlMs(assertTtlMs(n, 'ttl.seconds') * 1000, 'ttl.seconds (result)'),\n} as const;\n\n/** Fixed storage envelope shared by every adapter, so data and indexes stay portable. */\nexport type StoredRecord<T> = { expiresAt?: number; value: T };\n\nexport function isExpired(expiresAt: number | undefined): boolean {\n return expiresAt !== undefined && Date.now() >= expiresAt;\n}\n\nexport function assertTtlMs(ttlMs: number, source: string): TtlMs {\n if (!Number.isFinite(ttlMs) || ttlMs <= 0) {\n throw new VaultError(`${source} expected a finite positive number, received ${String(ttlMs)}`);\n }\n\n return ttlMs as TtlMs;\n}\n\nexport function parseStored<T>(raw: unknown): StoredRecord<T> | undefined {\n if (typeof raw !== 'object' || raw === null || !('value' in raw)) return undefined;\n\n const record = raw as { expiresAt?: unknown; value: unknown };\n\n if (record.expiresAt !== undefined && (typeof record.expiresAt !== 'number' || !Number.isFinite(record.expiresAt))) {\n return undefined;\n }\n\n return record as StoredRecord<T>;\n}\n"],"mappings":";;AAMA,IAAa,IAAM;CACjB,OAAO,MAAc,EAAY,EAAY,GAAG,UAAU,IAAI,OAAY,mBAAmB;CAC7F,QAAQ,MAAc,EAAY,EAAY,GAAG,WAAW,IAAI,MAAW,oBAAoB;CAC/F,UAAU,MAAc,EAAY,EAAY,GAAG,aAAa,IAAI,KAAQ,sBAAsB;CAClG,KAAK,MAAc,EAAY,GAAG,QAAQ;CAC1C,UAAU,MAAc,EAAY,EAAY,GAAG,aAAa,IAAI,KAAM,sBAAsB;AAClG;AAKA,SAAgB,EAAU,GAAwC;CAChE,OAAO,MAAc,KAAA,KAAa,KAAK,IAAI,KAAK;AAClD;AAEA,SAAgB,EAAY,GAAe,GAAuB;CAChE,IAAI,CAAC,OAAO,SAAS,CAAK,KAAK,KAAS,GACtC,MAAM,IAAI,EAAW,GAAG,EAAO,+CAA+C,OAAO,CAAK,GAAG;CAG/F,OAAO;AACT;AAEA,SAAgB,EAAe,GAA2C;CACxE,IAAI,OAAO,KAAQ,aAAY,KAAgB,EAAE,WAAW,IAAM;CAElE,IAAM,IAAS;CAEX,QAAO,cAAc,KAAA,MAAc,OAAO,EAAO,aAAc,YAAY,CAAC,OAAO,SAAS,EAAO,SAAS,KAIhH,OAAO;AACT"}
1
+ {"version":3,"file":"ttl.js","names":[],"sources":["../src/ttl.ts"],"sourcesContent":["import { VaultError } from './errors';\n\n/** Duration helpers that produce finite, positive millisecond values. */\nexport const ttl = {\n days: (n: number) => assertPositiveFinite(n * 86_400_000, 'ttl.days'),\n hours: (n: number) => assertPositiveFinite(n * 3_600_000, 'ttl.hours'),\n minutes: (n: number) => assertPositiveFinite(n * 60_000, 'ttl.minutes'),\n ms: (n: number) => assertPositiveFinite(n, 'ttl.ms'),\n seconds: (n: number) => assertPositiveFinite(n * 1000, 'ttl.seconds'),\n} as const;\n\n/** Fixed storage envelope shared by every adapter, so data and indexes stay portable. */\nexport type StoredRecord<T> = { expiresAt?: number; value: T };\n\nexport function isExpired(expiresAt: number | undefined): boolean {\n return expiresAt !== undefined && Date.now() >= expiresAt;\n}\n\n/** Throws when `ttlMs` is not a finite, positive number. Returns it unchanged otherwise. */\nexport function assertPositiveFinite(ttlMs: number, source: string): number {\n if (!Number.isFinite(ttlMs) || ttlMs <= 0) {\n throw new VaultError(`${source} expected a finite positive number, received ${String(ttlMs)}`);\n }\n\n return ttlMs;\n}\n\nexport function parseStored<T>(raw: unknown): StoredRecord<T> | undefined {\n if (typeof raw !== 'object' || raw === null || !('value' in raw)) return undefined;\n\n const record = raw as { expiresAt?: unknown; value: unknown };\n\n if (record.expiresAt !== undefined && (typeof record.expiresAt !== 'number' || !Number.isFinite(record.expiresAt))) {\n return undefined;\n }\n\n return record as StoredRecord<T>;\n}\n"],"mappings":";;AAGA,IAAa,IAAM;CACjB,OAAO,MAAc,EAAqB,IAAI,OAAY,UAAU;CACpE,QAAQ,MAAc,EAAqB,IAAI,MAAW,WAAW;CACrE,UAAU,MAAc,EAAqB,IAAI,KAAQ,aAAa;CACtE,KAAK,MAAc,EAAqB,GAAG,QAAQ;CACnD,UAAU,MAAc,EAAqB,IAAI,KAAM,aAAa;AACtE;AAKA,SAAgB,EAAU,GAAwC;CAChE,OAAO,MAAc,KAAA,KAAa,KAAK,IAAI,KAAK;AAClD;AAGA,SAAgB,EAAqB,GAAe,GAAwB;CAC1E,IAAI,CAAC,OAAO,SAAS,CAAK,KAAK,KAAS,GACtC,MAAM,IAAI,EAAW,GAAG,EAAO,+CAA+C,OAAO,CAAK,GAAG;CAG/F,OAAO;AACT;AAEA,SAAgB,EAAe,GAA2C;CACxE,IAAI,OAAO,KAAQ,aAAY,KAAgB,EAAE,WAAW,IAAM;CAElE,IAAM,IAAS;CAEX,QAAO,cAAc,KAAA,MAAc,OAAO,EAAO,aAAc,YAAY,CAAC,OAAO,SAAS,EAAO,SAAS,KAIhH,OAAO;AACT"}
package/dist/types.cjs CHANGED
@@ -1,2 +1,2 @@
1
- const e=require("./errors.cjs"),t=require("./ttl.cjs");function n(n){function r(n){return{...n,index:t=>{let i=n.indexes??[];if(i.includes(t))throw new e.VaultError(`table index "${t}" is already registered`);return r({...n,indexes:[...i,t]})},ttl:e=>(t.assertTtlMs(e,`table.ttl`),r({...n,defaultTtl:e}))}}return r({key:n})}exports.table=n;
1
+ const e=require("./errors.cjs"),t=require("./ttl.cjs");function n(n,r={}){let{defaultTtl:i,indexes:a}=r;if(i!==void 0&&t.assertPositiveFinite(i,`table: defaultTtl`),a){let t=new Set;for(let n of a){if(t.has(n))throw new e.VaultError(`table: index "${n}" is already registered`);t.add(n)}}return{defaultTtl:i,indexes:a,key:n}}exports.table=n;
2
2
  //# sourceMappingURL=types.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.cjs","names":[],"sources":["../src/types.ts"],"sourcesContent":["/// <reference lib=\"dom\" />\n\nimport { VaultError } from './errors';\nimport type { QueryBuilder } from './query';\nimport { assertTtlMs, type TtlMs } from './ttl';\n\nexport type { TtlMs };\n\n/** Portable primary-key values. Vault preserves their type and encodes them distinctly at rest. */\nexport type VaultKey = number | string;\n\ndeclare const schemaEntryBrand: unique symbol;\n\n/** A typed table definition whose primary-key field must hold a portable Vault key. */\nexport type SchemaEntry<T extends object, Key extends keyof T & string = keyof T & string> = T[Key] extends VaultKey\n ? {\n defaultTtl?: TtlMs;\n /** IndexedDB creates these as `value.<field>` indexes; other stores filter in memory. */\n indexes?: readonly (keyof T & string)[];\n key: Key;\n readonly [schemaEntryBrand]?: T;\n }\n : never;\n\nexport type AnySchema = Record<string, { defaultTtl?: TtlMs; indexes?: readonly string[]; key: string }>;\n\nexport type TableBuilder<T extends object, Key extends keyof T & string = keyof T & string> = SchemaEntry<T, Key> & {\n index: <F extends keyof T & string>(field: F) => TableBuilder<T, Key>;\n ttl: (ms: TtlMs) => TableBuilder<T, Key>;\n};\n\n/** Define a table once so all stores share the same record and portable-key contract. */\nexport function table<T extends object, Key extends keyof T & string = keyof T & string>(\n key: Key & (T[Key] extends VaultKey ? unknown : never),\n): TableBuilder<T, Key> {\n function makeBuilder(entry: SchemaEntry<T, Key>): TableBuilder<T, Key> {\n return {\n ...entry,\n index: <F extends keyof T & string>(field: F): TableBuilder<T, Key> => {\n const current = (entry.indexes ?? []) as readonly (keyof T & string)[];\n\n if (current.includes(field)) {\n throw new VaultError(`table index \"${field}\" is already registered`);\n }\n\n return makeBuilder({ ...entry, indexes: [...current, field] });\n },\n ttl: (ms: TtlMs): TableBuilder<T, Key> => {\n assertTtlMs(ms, 'table.ttl');\n\n return makeBuilder({ ...entry, defaultTtl: ms });\n },\n };\n }\n\n return makeBuilder({ key } as unknown as SchemaEntry<T, Key>);\n}\n\nexport type RecordOf<S extends AnySchema, K extends keyof S> =\n S[K] extends SchemaEntry<infer R, infer _Key> ? R : never;\nexport type KeyOf<S extends AnySchema, K extends keyof S> = Extract<\n S[K] extends SchemaEntry<infer R, infer Key> ? R[Key] : never,\n VaultKey\n>;\n\nexport type MigrationContext = {\n db: IDBDatabase;\n newVersion: number | null;\n oldVersion: number;\n tx: IDBTransaction;\n};\n\nexport type MigrationFn = (ctx: MigrationContext) => void;\n\nexport interface VaultLogger {\n error(messageOrContext?: Record<string, unknown> | Error | string, message?: string): void;\n}\n\nexport interface RecordValidator<T> {\n parse(value: unknown): T;\n}\n\nexport type TableValidators<S extends AnySchema> = {\n [K in keyof S]?: RecordValidator<RecordOf<S, K>>;\n};\n\nexport type Observer<T> = (records: T[]) => void;\nexport type Unsubscribe = () => void;\n\n/** Shared factory options. Values always use Vault's fixed `{ value, expiresAt? }` envelope. */\nexport type BaseAdapterOptions<S extends AnySchema> = {\n logger?: VaultLogger;\n onMetrics?: (event: MetricsEvent) => void;\n schema: S;\n validators?: TableValidators<S>;\n};\n\nexport type MetricsEvent = {\n duration: number;\n operation:\n | 'batch'\n | 'clear'\n | 'count'\n | 'delete'\n | 'deleteMany'\n | 'entries'\n | 'get'\n | 'getAll'\n | 'getMany'\n | 'getOrDefault'\n | 'has'\n | 'isEmpty'\n | 'keys'\n | 'put'\n | 'putAll'\n | 'query'\n | 'queryDelete'\n | 'update'\n | 'upsert';\n table: string;\n};\n\nexport type DebugStats = { expiredCount: number; recordCount: number };\nexport type DebugInfo<S extends AnySchema> = { tables: Array<{ name: keyof S & string } & DebugStats> };\n\n/** Methods available within an IndexedDB transaction. */\nexport type TransactionContext<S extends AnySchema, K extends keyof S & string = keyof S & string> = {\n clear<T extends K>(table: T): Promise<void>;\n count<T extends K>(table: T): Promise<number>;\n delete<T extends K>(table: T, key: KeyOf<S, T>): Promise<boolean>;\n deleteMany<T extends K>(table: T, keys: KeyOf<S, T>[]): Promise<number>;\n entries<T extends K>(table: T): Promise<Array<[KeyOf<S, T>, RecordOf<S, T>]>>;\n get<T extends K>(table: T, key: KeyOf<S, T>): Promise<RecordOf<S, T> | undefined>;\n getAll<T extends K>(table: T): Promise<RecordOf<S, T>[]>;\n getMany<T extends K>(table: T, keys: KeyOf<S, T>[]): Promise<Array<RecordOf<S, T> | undefined>>;\n getOrDefault<T extends K>(\n table: T,\n key: KeyOf<S, T>,\n defaultFn: () => RecordOf<S, T>,\n ttl?: TtlMs,\n ): Promise<RecordOf<S, T>>;\n has<T extends K>(table: T, key: KeyOf<S, T>): Promise<boolean>;\n isEmpty<T extends K>(table: T): Promise<boolean>;\n keys<T extends K>(table: T, filter?: (record: RecordOf<S, T>) => boolean): Promise<KeyOf<S, T>[]>;\n put<T extends K>(table: T, value: RecordOf<S, T>, ttl?: TtlMs): Promise<void>;\n putAll<T extends K>(table: T, values: RecordOf<S, T>[], ttl?: TtlMs): Promise<void>;\n query<T extends K>(table: T): QueryBuilder<RecordOf<S, T>>;\n update<T extends K>(\n table: T,\n key: KeyOf<S, T>,\n changes: Partial<RecordOf<S, T>>,\n ttl?: TtlMs,\n ): Promise<RecordOf<S, T> | undefined>;\n upsert<T extends K>(\n table: T,\n key: KeyOf<S, T>,\n fn: (existing: RecordOf<S, T> | undefined) => RecordOf<S, T>,\n ttl?: TtlMs,\n ): Promise<RecordOf<S, T>>;\n};\n\n/** Portable API returned by memory and Web Storage factories. */\nexport interface VaultStore<S extends AnySchema> {\n clear<K extends keyof S & string>(table: K): Promise<void>;\n count<K extends keyof S & string>(table: K): Promise<number>;\n debug(): Promise<DebugInfo<S>>;\n delete<K extends keyof S & string>(table: K, key: KeyOf<S, K>): Promise<boolean>;\n deleteMany<K extends keyof S & string>(table: K, keys: KeyOf<S, K>[]): Promise<number>;\n readonly disposalSignal: AbortSignal;\n dispose(): Promise<void>;\n readonly disposed: boolean;\n entries<K extends keyof S & string>(table: K): Promise<Array<[KeyOf<S, K>, RecordOf<S, K>]>>;\n get<K extends keyof S & string>(table: K, key: KeyOf<S, K>): Promise<RecordOf<S, K> | undefined>;\n getAll<K extends keyof S & string>(table: K): Promise<RecordOf<S, K>[]>;\n getMany<K extends keyof S & string>(table: K, keys: KeyOf<S, K>[]): Promise<Array<RecordOf<S, K> | undefined>>;\n getOrDefault<K extends keyof S & string>(\n table: K,\n key: KeyOf<S, K>,\n defaultFn: () => RecordOf<S, K>,\n ttl?: TtlMs,\n ): Promise<RecordOf<S, K>>;\n has<K extends keyof S & string>(table: K, key: KeyOf<S, K>): Promise<boolean>;\n isEmpty<K extends keyof S & string>(table: K): Promise<boolean>;\n keys<K extends keyof S & string>(table: K, filter?: (record: RecordOf<S, K>) => boolean): Promise<KeyOf<S, K>[]>;\n observe<K extends keyof S & string>(\n table: K,\n listener: Observer<RecordOf<S, K>>,\n options?: { immediate?: boolean; signal?: AbortSignal },\n ): Unsubscribe;\n pruneExpired(): Promise<Record<keyof S & string, number>>;\n put<K extends keyof S & string>(table: K, value: RecordOf<S, K>, ttl?: TtlMs): Promise<void>;\n putAll<K extends keyof S & string>(table: K, values: RecordOf<S, K>[], ttl?: TtlMs): Promise<void>;\n query<K extends keyof S & string>(table: K): QueryBuilder<RecordOf<S, K>>;\n update<K extends keyof S & string>(\n table: K,\n key: KeyOf<S, K>,\n changes: Partial<RecordOf<S, K>>,\n ttl?: TtlMs,\n ): Promise<RecordOf<S, K> | undefined>;\n upsert<K extends keyof S & string>(\n table: K,\n key: KeyOf<S, K>,\n fn: (existing: RecordOf<S, K> | undefined) => RecordOf<S, K>,\n ttl?: TtlMs,\n ): Promise<RecordOf<S, K>>;\n [Symbol.asyncDispose](): Promise<void>;\n}\n\n/** Atomic, scoped transactions supplied by storage engines that support them. */\nexport interface TransactionalVaultStore<S extends AnySchema> extends VaultStore<S> {\n batch<K extends keyof S & string, R>(\n tables: readonly K[],\n fn: (tx: TransactionContext<S, K>) => Promise<R>,\n ): Promise<R>;\n}\n\n/** Lazy record iteration supplied by storage engines that support it. */\nexport interface IterableVaultStore<S extends AnySchema> extends VaultStore<S> {\n iterate<K extends keyof S & string>(table: K): AsyncIterable<RecordOf<S, K>>;\n}\n\n/** IndexedDB-only guarantees: cursor iteration and atomic, scoped transactions. */\nexport interface IndexedDbVaultStore<S extends AnySchema> extends TransactionalVaultStore<S>, IterableVaultStore<S> {}\n"],"mappings":"uDAgCA,SAAgB,EACd,EACsB,CACtB,SAAS,EAAY,EAAkD,CACrE,MAAO,CACL,GAAG,EACH,MAAoC,GAAmC,CACrE,IAAM,EAAW,EAAM,SAAW,CAAC,EAEnC,GAAI,EAAQ,SAAS,CAAK,EACxB,MAAM,IAAI,EAAA,WAAW,gBAAgB,EAAM,wBAAwB,EAGrE,OAAO,EAAY,CAAE,GAAG,EAAO,QAAS,CAAC,GAAG,EAAS,CAAK,CAAE,CAAC,CAC/D,EACA,IAAM,IACJ,EAAA,YAAY,EAAI,WAAW,EAEpB,EAAY,CAAE,GAAG,EAAO,WAAY,CAAG,CAAC,EAEnD,CACF,CAEA,OAAO,EAAY,CAAE,KAAI,CAAmC,CAC9D"}
1
+ {"version":3,"file":"types.cjs","names":[],"sources":["../src/types.ts"],"sourcesContent":["/// <reference lib=\"dom\" />\n\nimport { VaultError } from './errors';\nimport type { QueryBuilder } from './query';\nimport { assertPositiveFinite } from './ttl';\n\n/** Portable primary-key values. Vault preserves their type and encodes them distinctly at rest. */\nexport type VaultKey = number | string;\n\n/** A typed table definition whose primary-key field must hold a portable Vault key. */\nexport type SchemaEntry<T extends object, Key extends keyof T & string = keyof T & string> = T[Key] extends VaultKey\n ? {\n defaultTtl?: number;\n /** IndexedDB creates these as `value.<field>` indexes; other stores filter in memory. */\n indexes?: readonly (keyof T & string)[];\n key: Key;\n }\n : never;\n\nexport type AnySchema = Record<string, { defaultTtl?: number; indexes?: readonly string[]; key: string }>;\n\nexport type RecordOf<S extends AnySchema, K extends keyof S> =\n S[K] extends SchemaEntry<infer R, infer _Key> ? R : never;\nexport type KeyOf<S extends AnySchema, K extends keyof S> = Extract<\n S[K] extends SchemaEntry<infer R, infer Key> ? R[Key] : never,\n VaultKey\n>;\n\nexport type VaultLogger = {\n error(message: string, context?: Error | Record<string, unknown>): void;\n};\n\nexport type RecordValidator<T> = {\n parse(value: unknown): T;\n};\n\nexport type TableValidators<S extends AnySchema> = {\n [K in keyof S]?: RecordValidator<RecordOf<S, K>>;\n};\n\nexport type Observer<T> = (records: T[]) => void;\nexport type Unsubscribe = () => void;\n\n/** Shared factory options. Values always use Vault's fixed `{ value, expiresAt? }` envelope. */\nexport type BaseAdapterOptions<S extends AnySchema> = {\n logger?: VaultLogger;\n onMetrics?: (event: MetricsEvent) => void;\n schema: S;\n validators?: TableValidators<S>;\n};\n\nexport type MetricsEvent = {\n duration: number;\n operation:\n | 'batch'\n | 'clear'\n | 'count'\n | 'delete'\n | 'deleteMany'\n | 'entries'\n | 'get'\n | 'getAll'\n | 'getMany'\n | 'getOrDefault'\n | 'has'\n | 'isEmpty'\n | 'keys'\n | 'put'\n | 'putAll'\n | 'query'\n | 'queryDelete'\n | 'update'\n | 'upsert';\n table: string;\n};\n\nexport type DebugStats = { expiredCount: number; recordCount: number };\nexport type DebugInfo<S extends AnySchema> = { tables: Array<{ name: keyof S & string } & DebugStats> };\n\n/** Methods available within an IndexedDB or SQLite transaction. */\nexport type TransactionContext<S extends AnySchema, K extends keyof S & string = keyof S & string> = {\n clear<T extends K>(table: T): Promise<void>;\n count<T extends K>(table: T): Promise<number>;\n delete<T extends K>(table: T, key: KeyOf<S, T>): Promise<boolean>;\n deleteMany<T extends K>(table: T, keys: KeyOf<S, T>[]): Promise<number>;\n entries<T extends K>(table: T): Promise<Array<[KeyOf<S, T>, RecordOf<S, T>]>>;\n get<T extends K>(table: T, key: KeyOf<S, T>): Promise<RecordOf<S, T> | undefined>;\n getAll<T extends K>(table: T): Promise<RecordOf<S, T>[]>;\n getMany<T extends K>(table: T, keys: KeyOf<S, T>[]): Promise<Array<RecordOf<S, T> | undefined>>;\n getOrDefault<T extends K>(\n table: T,\n key: KeyOf<S, T>,\n defaultFn: () => RecordOf<S, T>,\n ttl?: number,\n ): Promise<RecordOf<S, T>>;\n has<T extends K>(table: T, key: KeyOf<S, T>): Promise<boolean>;\n isEmpty<T extends K>(table: T): Promise<boolean>;\n keys<T extends K>(table: T, filter?: (record: RecordOf<S, T>) => boolean): Promise<KeyOf<S, T>[]>;\n put<T extends K>(table: T, value: RecordOf<S, T>, ttl?: number): Promise<void>;\n putAll<T extends K>(table: T, values: RecordOf<S, T>[], ttl?: number): Promise<void>;\n query<T extends K>(table: T): QueryBuilder<RecordOf<S, T>>;\n update<T extends K>(\n table: T,\n key: KeyOf<S, T>,\n changes: Partial<RecordOf<S, T>>,\n ttl?: number,\n ): Promise<RecordOf<S, T> | undefined>;\n upsert<T extends K>(\n table: T,\n key: KeyOf<S, T>,\n fn: (existing: RecordOf<S, T> | undefined) => RecordOf<S, T>,\n ttl?: number,\n ): Promise<RecordOf<S, T>>;\n};\n\n/** Portable API returned by memory and Web Storage factories. */\nexport interface VaultStore<S extends AnySchema> {\n clear<K extends keyof S & string>(table: K): Promise<void>;\n count<K extends keyof S & string>(table: K): Promise<number>;\n debug(): Promise<DebugInfo<S>>;\n delete<K extends keyof S & string>(table: K, key: KeyOf<S, K>): Promise<boolean>;\n deleteMany<K extends keyof S & string>(table: K, keys: KeyOf<S, K>[]): Promise<number>;\n readonly disposalSignal: AbortSignal;\n dispose(): Promise<void>;\n readonly disposed: boolean;\n entries<K extends keyof S & string>(table: K): Promise<Array<[KeyOf<S, K>, RecordOf<S, K>]>>;\n get<K extends keyof S & string>(table: K, key: KeyOf<S, K>): Promise<RecordOf<S, K> | undefined>;\n getAll<K extends keyof S & string>(table: K): Promise<RecordOf<S, K>[]>;\n getMany<K extends keyof S & string>(table: K, keys: KeyOf<S, K>[]): Promise<Array<RecordOf<S, K> | undefined>>;\n getOrDefault<K extends keyof S & string>(\n table: K,\n key: KeyOf<S, K>,\n defaultFn: () => RecordOf<S, K>,\n ttl?: number,\n ): Promise<RecordOf<S, K>>;\n has<K extends keyof S & string>(table: K, key: KeyOf<S, K>): Promise<boolean>;\n isEmpty<K extends keyof S & string>(table: K): Promise<boolean>;\n keys<K extends keyof S & string>(table: K, filter?: (record: RecordOf<S, K>) => boolean): Promise<KeyOf<S, K>[]>;\n observe<K extends keyof S & string>(\n table: K,\n listener: Observer<RecordOf<S, K>>,\n options?: { immediate?: boolean; signal?: AbortSignal },\n ): Unsubscribe;\n pruneExpired(): Promise<Record<keyof S & string, number>>;\n put<K extends keyof S & string>(table: K, value: RecordOf<S, K>, ttl?: number): Promise<void>;\n putAll<K extends keyof S & string>(table: K, values: RecordOf<S, K>[], ttl?: number): Promise<void>;\n query<K extends keyof S & string>(table: K): QueryBuilder<RecordOf<S, K>>;\n update<K extends keyof S & string>(\n table: K,\n key: KeyOf<S, K>,\n changes: Partial<RecordOf<S, K>>,\n ttl?: number,\n ): Promise<RecordOf<S, K> | undefined>;\n upsert<K extends keyof S & string>(\n table: K,\n key: KeyOf<S, K>,\n fn: (existing: RecordOf<S, K> | undefined) => RecordOf<S, K>,\n ttl?: number,\n ): Promise<RecordOf<S, K>>;\n [Symbol.asyncDispose](): Promise<void>;\n}\n\n/** Atomic, scoped transactions supplied by storage engines that support them. */\nexport interface TransactionalVaultStore<S extends AnySchema> extends VaultStore<S> {\n batch<K extends keyof S & string, R>(\n tables: readonly K[],\n fn: (tx: TransactionContext<S, K>) => Promise<R>,\n ): Promise<R>;\n}\n\n/** Lazy record iteration supplied by storage engines that support it. */\nexport interface IterableVaultStore<S extends AnySchema> extends VaultStore<S> {\n iterate<K extends keyof S & string>(table: K): AsyncIterable<RecordOf<S, K>>;\n}\n\n/** IndexedDB-only guarantees: cursor iteration and atomic, scoped transactions. */\nexport interface IndexedDbVaultStore<S extends AnySchema> extends TransactionalVaultStore<S>, IterableVaultStore<S> {}\n\n/** Define a typed table whose primary-key field holds a portable Vault key. */\nexport function table<T extends object, Key extends keyof T & string = keyof T & string>(\n key: Key & (T[Key] extends VaultKey ? unknown : never),\n options: { defaultTtl?: number; indexes?: readonly (keyof T & string)[] } = {},\n): SchemaEntry<T, Key> {\n const { defaultTtl, indexes } = options;\n\n if (defaultTtl !== undefined) assertPositiveFinite(defaultTtl, 'table: defaultTtl');\n\n if (indexes) {\n const seen = new Set<string>();\n\n for (const field of indexes) {\n if (seen.has(field)) {\n throw new VaultError(`table: index \"${field}\" is already registered`);\n }\n\n seen.add(field);\n }\n }\n\n return { defaultTtl, indexes, key } as unknown as SchemaEntry<T, Key>;\n}\n"],"mappings":"uDAmLA,SAAgB,EACd,EACA,EAA4E,CAAC,EACxD,CACrB,GAAM,CAAE,aAAY,WAAY,EAIhC,GAFI,IAAe,IAAA,IAAW,EAAA,qBAAqB,EAAY,mBAAmB,EAE9E,EAAS,CACX,IAAM,EAAO,IAAI,IAEjB,IAAK,IAAM,KAAS,EAAS,CAC3B,GAAI,EAAK,IAAI,CAAK,EAChB,MAAM,IAAI,EAAA,WAAW,iBAAiB,EAAM,wBAAwB,EAGtE,EAAK,IAAI,CAAK,CAChB,CACF,CAEA,MAAO,CAAE,aAAY,UAAS,KAAI,CACpC"}
package/dist/types.d.ts CHANGED
@@ -1,43 +1,26 @@
1
1
  import type { QueryBuilder } from './query';
2
- import { type TtlMs } from './ttl';
3
- export type { TtlMs };
4
2
  /** Portable primary-key values. Vault preserves their type and encodes them distinctly at rest. */
5
3
  export type VaultKey = number | string;
6
- declare const schemaEntryBrand: unique symbol;
7
4
  /** A typed table definition whose primary-key field must hold a portable Vault key. */
8
5
  export type SchemaEntry<T extends object, Key extends keyof T & string = keyof T & string> = T[Key] extends VaultKey ? {
9
- defaultTtl?: TtlMs;
6
+ defaultTtl?: number;
10
7
  /** IndexedDB creates these as `value.<field>` indexes; other stores filter in memory. */
11
8
  indexes?: readonly (keyof T & string)[];
12
9
  key: Key;
13
- readonly [schemaEntryBrand]?: T;
14
10
  } : never;
15
11
  export type AnySchema = Record<string, {
16
- defaultTtl?: TtlMs;
12
+ defaultTtl?: number;
17
13
  indexes?: readonly string[];
18
14
  key: string;
19
15
  }>;
20
- export type TableBuilder<T extends object, Key extends keyof T & string = keyof T & string> = SchemaEntry<T, Key> & {
21
- index: <F extends keyof T & string>(field: F) => TableBuilder<T, Key>;
22
- ttl: (ms: TtlMs) => TableBuilder<T, Key>;
23
- };
24
- /** Define a table once so all stores share the same record and portable-key contract. */
25
- export declare function table<T extends object, Key extends keyof T & string = keyof T & string>(key: Key & (T[Key] extends VaultKey ? unknown : never)): TableBuilder<T, Key>;
26
16
  export type RecordOf<S extends AnySchema, K extends keyof S> = S[K] extends SchemaEntry<infer R, infer _Key> ? R : never;
27
17
  export type KeyOf<S extends AnySchema, K extends keyof S> = Extract<S[K] extends SchemaEntry<infer R, infer Key> ? R[Key] : never, VaultKey>;
28
- export type MigrationContext = {
29
- db: IDBDatabase;
30
- newVersion: number | null;
31
- oldVersion: number;
32
- tx: IDBTransaction;
18
+ export type VaultLogger = {
19
+ error(message: string, context?: Error | Record<string, unknown>): void;
33
20
  };
34
- export type MigrationFn = (ctx: MigrationContext) => void;
35
- export interface VaultLogger {
36
- error(messageOrContext?: Record<string, unknown> | Error | string, message?: string): void;
37
- }
38
- export interface RecordValidator<T> {
21
+ export type RecordValidator<T> = {
39
22
  parse(value: unknown): T;
40
- }
23
+ };
41
24
  export type TableValidators<S extends AnySchema> = {
42
25
  [K in keyof S]?: RecordValidator<RecordOf<S, K>>;
43
26
  };
@@ -64,7 +47,7 @@ export type DebugInfo<S extends AnySchema> = {
64
47
  name: keyof S & string;
65
48
  } & DebugStats>;
66
49
  };
67
- /** Methods available within an IndexedDB transaction. */
50
+ /** Methods available within an IndexedDB or SQLite transaction. */
68
51
  export type TransactionContext<S extends AnySchema, K extends keyof S & string = keyof S & string> = {
69
52
  clear<T extends K>(table: T): Promise<void>;
70
53
  count<T extends K>(table: T): Promise<number>;
@@ -74,15 +57,15 @@ export type TransactionContext<S extends AnySchema, K extends keyof S & string =
74
57
  get<T extends K>(table: T, key: KeyOf<S, T>): Promise<RecordOf<S, T> | undefined>;
75
58
  getAll<T extends K>(table: T): Promise<RecordOf<S, T>[]>;
76
59
  getMany<T extends K>(table: T, keys: KeyOf<S, T>[]): Promise<Array<RecordOf<S, T> | undefined>>;
77
- getOrDefault<T extends K>(table: T, key: KeyOf<S, T>, defaultFn: () => RecordOf<S, T>, ttl?: TtlMs): Promise<RecordOf<S, T>>;
60
+ getOrDefault<T extends K>(table: T, key: KeyOf<S, T>, defaultFn: () => RecordOf<S, T>, ttl?: number): Promise<RecordOf<S, T>>;
78
61
  has<T extends K>(table: T, key: KeyOf<S, T>): Promise<boolean>;
79
62
  isEmpty<T extends K>(table: T): Promise<boolean>;
80
63
  keys<T extends K>(table: T, filter?: (record: RecordOf<S, T>) => boolean): Promise<KeyOf<S, T>[]>;
81
- put<T extends K>(table: T, value: RecordOf<S, T>, ttl?: TtlMs): Promise<void>;
82
- putAll<T extends K>(table: T, values: RecordOf<S, T>[], ttl?: TtlMs): Promise<void>;
64
+ put<T extends K>(table: T, value: RecordOf<S, T>, ttl?: number): Promise<void>;
65
+ putAll<T extends K>(table: T, values: RecordOf<S, T>[], ttl?: number): Promise<void>;
83
66
  query<T extends K>(table: T): QueryBuilder<RecordOf<S, T>>;
84
- update<T extends K>(table: T, key: KeyOf<S, T>, changes: Partial<RecordOf<S, T>>, ttl?: TtlMs): Promise<RecordOf<S, T> | undefined>;
85
- upsert<T extends K>(table: T, key: KeyOf<S, T>, fn: (existing: RecordOf<S, T> | undefined) => RecordOf<S, T>, ttl?: TtlMs): Promise<RecordOf<S, T>>;
67
+ update<T extends K>(table: T, key: KeyOf<S, T>, changes: Partial<RecordOf<S, T>>, ttl?: number): Promise<RecordOf<S, T> | undefined>;
68
+ upsert<T extends K>(table: T, key: KeyOf<S, T>, fn: (existing: RecordOf<S, T> | undefined) => RecordOf<S, T>, ttl?: number): Promise<RecordOf<S, T>>;
86
69
  };
87
70
  /** Portable API returned by memory and Web Storage factories. */
88
71
  export interface VaultStore<S extends AnySchema> {
@@ -98,7 +81,7 @@ export interface VaultStore<S extends AnySchema> {
98
81
  get<K extends keyof S & string>(table: K, key: KeyOf<S, K>): Promise<RecordOf<S, K> | undefined>;
99
82
  getAll<K extends keyof S & string>(table: K): Promise<RecordOf<S, K>[]>;
100
83
  getMany<K extends keyof S & string>(table: K, keys: KeyOf<S, K>[]): Promise<Array<RecordOf<S, K> | undefined>>;
101
- getOrDefault<K extends keyof S & string>(table: K, key: KeyOf<S, K>, defaultFn: () => RecordOf<S, K>, ttl?: TtlMs): Promise<RecordOf<S, K>>;
84
+ getOrDefault<K extends keyof S & string>(table: K, key: KeyOf<S, K>, defaultFn: () => RecordOf<S, K>, ttl?: number): Promise<RecordOf<S, K>>;
102
85
  has<K extends keyof S & string>(table: K, key: KeyOf<S, K>): Promise<boolean>;
103
86
  isEmpty<K extends keyof S & string>(table: K): Promise<boolean>;
104
87
  keys<K extends keyof S & string>(table: K, filter?: (record: RecordOf<S, K>) => boolean): Promise<KeyOf<S, K>[]>;
@@ -107,11 +90,11 @@ export interface VaultStore<S extends AnySchema> {
107
90
  signal?: AbortSignal;
108
91
  }): Unsubscribe;
109
92
  pruneExpired(): Promise<Record<keyof S & string, number>>;
110
- put<K extends keyof S & string>(table: K, value: RecordOf<S, K>, ttl?: TtlMs): Promise<void>;
111
- putAll<K extends keyof S & string>(table: K, values: RecordOf<S, K>[], ttl?: TtlMs): Promise<void>;
93
+ put<K extends keyof S & string>(table: K, value: RecordOf<S, K>, ttl?: number): Promise<void>;
94
+ putAll<K extends keyof S & string>(table: K, values: RecordOf<S, K>[], ttl?: number): Promise<void>;
112
95
  query<K extends keyof S & string>(table: K): QueryBuilder<RecordOf<S, K>>;
113
- update<K extends keyof S & string>(table: K, key: KeyOf<S, K>, changes: Partial<RecordOf<S, K>>, ttl?: TtlMs): Promise<RecordOf<S, K> | undefined>;
114
- upsert<K extends keyof S & string>(table: K, key: KeyOf<S, K>, fn: (existing: RecordOf<S, K> | undefined) => RecordOf<S, K>, ttl?: TtlMs): Promise<RecordOf<S, K>>;
96
+ update<K extends keyof S & string>(table: K, key: KeyOf<S, K>, changes: Partial<RecordOf<S, K>>, ttl?: number): Promise<RecordOf<S, K> | undefined>;
97
+ upsert<K extends keyof S & string>(table: K, key: KeyOf<S, K>, fn: (existing: RecordOf<S, K> | undefined) => RecordOf<S, K>, ttl?: number): Promise<RecordOf<S, K>>;
115
98
  [Symbol.asyncDispose](): Promise<void>;
116
99
  }
117
100
  /** Atomic, scoped transactions supplied by storage engines that support them. */
@@ -125,4 +108,9 @@ export interface IterableVaultStore<S extends AnySchema> extends VaultStore<S> {
125
108
  /** IndexedDB-only guarantees: cursor iteration and atomic, scoped transactions. */
126
109
  export interface IndexedDbVaultStore<S extends AnySchema> extends TransactionalVaultStore<S>, IterableVaultStore<S> {
127
110
  }
111
+ /** Define a typed table whose primary-key field holds a portable Vault key. */
112
+ export declare function table<T extends object, Key extends keyof T & string = keyof T & string>(key: Key & (T[Key] extends VaultKey ? unknown : never), options?: {
113
+ defaultTtl?: number;
114
+ indexes?: readonly (keyof T & string)[];
115
+ }): SchemaEntry<T, Key>;
128
116
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js CHANGED
@@ -1,25 +1,20 @@
1
1
  import { VaultError as e } from "./errors.js";
2
- import { assertTtlMs as t } from "./ttl.js";
2
+ import { assertPositiveFinite as t } from "./ttl.js";
3
3
  //#region src/types.ts
4
- function n(n) {
5
- function r(n) {
6
- return {
7
- ...n,
8
- index: (t) => {
9
- let i = n.indexes ?? [];
10
- if (i.includes(t)) throw new e(`table index "${t}" is already registered`);
11
- return r({
12
- ...n,
13
- indexes: [...i, t]
14
- });
15
- },
16
- ttl: (e) => (t(e, "table.ttl"), r({
17
- ...n,
18
- defaultTtl: e
19
- }))
20
- };
4
+ function n(n, r = {}) {
5
+ let { defaultTtl: i, indexes: a } = r;
6
+ if (i !== void 0 && t(i, "table: defaultTtl"), a) {
7
+ let t = /* @__PURE__ */ new Set();
8
+ for (let n of a) {
9
+ if (t.has(n)) throw new e(`table: index "${n}" is already registered`);
10
+ t.add(n);
11
+ }
21
12
  }
22
- return r({ key: n });
13
+ return {
14
+ defaultTtl: i,
15
+ indexes: a,
16
+ key: n
17
+ };
23
18
  }
24
19
  //#endregion
25
20
  export { n as table };
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","names":[],"sources":["../src/types.ts"],"sourcesContent":["/// <reference lib=\"dom\" />\n\nimport { VaultError } from './errors';\nimport type { QueryBuilder } from './query';\nimport { assertTtlMs, type TtlMs } from './ttl';\n\nexport type { TtlMs };\n\n/** Portable primary-key values. Vault preserves their type and encodes them distinctly at rest. */\nexport type VaultKey = number | string;\n\ndeclare const schemaEntryBrand: unique symbol;\n\n/** A typed table definition whose primary-key field must hold a portable Vault key. */\nexport type SchemaEntry<T extends object, Key extends keyof T & string = keyof T & string> = T[Key] extends VaultKey\n ? {\n defaultTtl?: TtlMs;\n /** IndexedDB creates these as `value.<field>` indexes; other stores filter in memory. */\n indexes?: readonly (keyof T & string)[];\n key: Key;\n readonly [schemaEntryBrand]?: T;\n }\n : never;\n\nexport type AnySchema = Record<string, { defaultTtl?: TtlMs; indexes?: readonly string[]; key: string }>;\n\nexport type TableBuilder<T extends object, Key extends keyof T & string = keyof T & string> = SchemaEntry<T, Key> & {\n index: <F extends keyof T & string>(field: F) => TableBuilder<T, Key>;\n ttl: (ms: TtlMs) => TableBuilder<T, Key>;\n};\n\n/** Define a table once so all stores share the same record and portable-key contract. */\nexport function table<T extends object, Key extends keyof T & string = keyof T & string>(\n key: Key & (T[Key] extends VaultKey ? unknown : never),\n): TableBuilder<T, Key> {\n function makeBuilder(entry: SchemaEntry<T, Key>): TableBuilder<T, Key> {\n return {\n ...entry,\n index: <F extends keyof T & string>(field: F): TableBuilder<T, Key> => {\n const current = (entry.indexes ?? []) as readonly (keyof T & string)[];\n\n if (current.includes(field)) {\n throw new VaultError(`table index \"${field}\" is already registered`);\n }\n\n return makeBuilder({ ...entry, indexes: [...current, field] });\n },\n ttl: (ms: TtlMs): TableBuilder<T, Key> => {\n assertTtlMs(ms, 'table.ttl');\n\n return makeBuilder({ ...entry, defaultTtl: ms });\n },\n };\n }\n\n return makeBuilder({ key } as unknown as SchemaEntry<T, Key>);\n}\n\nexport type RecordOf<S extends AnySchema, K extends keyof S> =\n S[K] extends SchemaEntry<infer R, infer _Key> ? R : never;\nexport type KeyOf<S extends AnySchema, K extends keyof S> = Extract<\n S[K] extends SchemaEntry<infer R, infer Key> ? R[Key] : never,\n VaultKey\n>;\n\nexport type MigrationContext = {\n db: IDBDatabase;\n newVersion: number | null;\n oldVersion: number;\n tx: IDBTransaction;\n};\n\nexport type MigrationFn = (ctx: MigrationContext) => void;\n\nexport interface VaultLogger {\n error(messageOrContext?: Record<string, unknown> | Error | string, message?: string): void;\n}\n\nexport interface RecordValidator<T> {\n parse(value: unknown): T;\n}\n\nexport type TableValidators<S extends AnySchema> = {\n [K in keyof S]?: RecordValidator<RecordOf<S, K>>;\n};\n\nexport type Observer<T> = (records: T[]) => void;\nexport type Unsubscribe = () => void;\n\n/** Shared factory options. Values always use Vault's fixed `{ value, expiresAt? }` envelope. */\nexport type BaseAdapterOptions<S extends AnySchema> = {\n logger?: VaultLogger;\n onMetrics?: (event: MetricsEvent) => void;\n schema: S;\n validators?: TableValidators<S>;\n};\n\nexport type MetricsEvent = {\n duration: number;\n operation:\n | 'batch'\n | 'clear'\n | 'count'\n | 'delete'\n | 'deleteMany'\n | 'entries'\n | 'get'\n | 'getAll'\n | 'getMany'\n | 'getOrDefault'\n | 'has'\n | 'isEmpty'\n | 'keys'\n | 'put'\n | 'putAll'\n | 'query'\n | 'queryDelete'\n | 'update'\n | 'upsert';\n table: string;\n};\n\nexport type DebugStats = { expiredCount: number; recordCount: number };\nexport type DebugInfo<S extends AnySchema> = { tables: Array<{ name: keyof S & string } & DebugStats> };\n\n/** Methods available within an IndexedDB transaction. */\nexport type TransactionContext<S extends AnySchema, K extends keyof S & string = keyof S & string> = {\n clear<T extends K>(table: T): Promise<void>;\n count<T extends K>(table: T): Promise<number>;\n delete<T extends K>(table: T, key: KeyOf<S, T>): Promise<boolean>;\n deleteMany<T extends K>(table: T, keys: KeyOf<S, T>[]): Promise<number>;\n entries<T extends K>(table: T): Promise<Array<[KeyOf<S, T>, RecordOf<S, T>]>>;\n get<T extends K>(table: T, key: KeyOf<S, T>): Promise<RecordOf<S, T> | undefined>;\n getAll<T extends K>(table: T): Promise<RecordOf<S, T>[]>;\n getMany<T extends K>(table: T, keys: KeyOf<S, T>[]): Promise<Array<RecordOf<S, T> | undefined>>;\n getOrDefault<T extends K>(\n table: T,\n key: KeyOf<S, T>,\n defaultFn: () => RecordOf<S, T>,\n ttl?: TtlMs,\n ): Promise<RecordOf<S, T>>;\n has<T extends K>(table: T, key: KeyOf<S, T>): Promise<boolean>;\n isEmpty<T extends K>(table: T): Promise<boolean>;\n keys<T extends K>(table: T, filter?: (record: RecordOf<S, T>) => boolean): Promise<KeyOf<S, T>[]>;\n put<T extends K>(table: T, value: RecordOf<S, T>, ttl?: TtlMs): Promise<void>;\n putAll<T extends K>(table: T, values: RecordOf<S, T>[], ttl?: TtlMs): Promise<void>;\n query<T extends K>(table: T): QueryBuilder<RecordOf<S, T>>;\n update<T extends K>(\n table: T,\n key: KeyOf<S, T>,\n changes: Partial<RecordOf<S, T>>,\n ttl?: TtlMs,\n ): Promise<RecordOf<S, T> | undefined>;\n upsert<T extends K>(\n table: T,\n key: KeyOf<S, T>,\n fn: (existing: RecordOf<S, T> | undefined) => RecordOf<S, T>,\n ttl?: TtlMs,\n ): Promise<RecordOf<S, T>>;\n};\n\n/** Portable API returned by memory and Web Storage factories. */\nexport interface VaultStore<S extends AnySchema> {\n clear<K extends keyof S & string>(table: K): Promise<void>;\n count<K extends keyof S & string>(table: K): Promise<number>;\n debug(): Promise<DebugInfo<S>>;\n delete<K extends keyof S & string>(table: K, key: KeyOf<S, K>): Promise<boolean>;\n deleteMany<K extends keyof S & string>(table: K, keys: KeyOf<S, K>[]): Promise<number>;\n readonly disposalSignal: AbortSignal;\n dispose(): Promise<void>;\n readonly disposed: boolean;\n entries<K extends keyof S & string>(table: K): Promise<Array<[KeyOf<S, K>, RecordOf<S, K>]>>;\n get<K extends keyof S & string>(table: K, key: KeyOf<S, K>): Promise<RecordOf<S, K> | undefined>;\n getAll<K extends keyof S & string>(table: K): Promise<RecordOf<S, K>[]>;\n getMany<K extends keyof S & string>(table: K, keys: KeyOf<S, K>[]): Promise<Array<RecordOf<S, K> | undefined>>;\n getOrDefault<K extends keyof S & string>(\n table: K,\n key: KeyOf<S, K>,\n defaultFn: () => RecordOf<S, K>,\n ttl?: TtlMs,\n ): Promise<RecordOf<S, K>>;\n has<K extends keyof S & string>(table: K, key: KeyOf<S, K>): Promise<boolean>;\n isEmpty<K extends keyof S & string>(table: K): Promise<boolean>;\n keys<K extends keyof S & string>(table: K, filter?: (record: RecordOf<S, K>) => boolean): Promise<KeyOf<S, K>[]>;\n observe<K extends keyof S & string>(\n table: K,\n listener: Observer<RecordOf<S, K>>,\n options?: { immediate?: boolean; signal?: AbortSignal },\n ): Unsubscribe;\n pruneExpired(): Promise<Record<keyof S & string, number>>;\n put<K extends keyof S & string>(table: K, value: RecordOf<S, K>, ttl?: TtlMs): Promise<void>;\n putAll<K extends keyof S & string>(table: K, values: RecordOf<S, K>[], ttl?: TtlMs): Promise<void>;\n query<K extends keyof S & string>(table: K): QueryBuilder<RecordOf<S, K>>;\n update<K extends keyof S & string>(\n table: K,\n key: KeyOf<S, K>,\n changes: Partial<RecordOf<S, K>>,\n ttl?: TtlMs,\n ): Promise<RecordOf<S, K> | undefined>;\n upsert<K extends keyof S & string>(\n table: K,\n key: KeyOf<S, K>,\n fn: (existing: RecordOf<S, K> | undefined) => RecordOf<S, K>,\n ttl?: TtlMs,\n ): Promise<RecordOf<S, K>>;\n [Symbol.asyncDispose](): Promise<void>;\n}\n\n/** Atomic, scoped transactions supplied by storage engines that support them. */\nexport interface TransactionalVaultStore<S extends AnySchema> extends VaultStore<S> {\n batch<K extends keyof S & string, R>(\n tables: readonly K[],\n fn: (tx: TransactionContext<S, K>) => Promise<R>,\n ): Promise<R>;\n}\n\n/** Lazy record iteration supplied by storage engines that support it. */\nexport interface IterableVaultStore<S extends AnySchema> extends VaultStore<S> {\n iterate<K extends keyof S & string>(table: K): AsyncIterable<RecordOf<S, K>>;\n}\n\n/** IndexedDB-only guarantees: cursor iteration and atomic, scoped transactions. */\nexport interface IndexedDbVaultStore<S extends AnySchema> extends TransactionalVaultStore<S>, IterableVaultStore<S> {}\n"],"mappings":";;;AAgCA,SAAgB,EACd,GACsB;CACtB,SAAS,EAAY,GAAkD;EACrE,OAAO;GACL,GAAG;GACH,QAAoC,MAAmC;IACrE,IAAM,IAAW,EAAM,WAAW,CAAC;IAEnC,IAAI,EAAQ,SAAS,CAAK,GACxB,MAAM,IAAI,EAAW,gBAAgB,EAAM,wBAAwB;IAGrE,OAAO,EAAY;KAAE,GAAG;KAAO,SAAS,CAAC,GAAG,GAAS,CAAK;IAAE,CAAC;GAC/D;GACA,MAAM,OACJ,EAAY,GAAI,WAAW,GAEpB,EAAY;IAAE,GAAG;IAAO,YAAY;GAAG,CAAC;EAEnD;CACF;CAEA,OAAO,EAAY,EAAE,OAAI,CAAmC;AAC9D"}
1
+ {"version":3,"file":"types.js","names":[],"sources":["../src/types.ts"],"sourcesContent":["/// <reference lib=\"dom\" />\n\nimport { VaultError } from './errors';\nimport type { QueryBuilder } from './query';\nimport { assertPositiveFinite } from './ttl';\n\n/** Portable primary-key values. Vault preserves their type and encodes them distinctly at rest. */\nexport type VaultKey = number | string;\n\n/** A typed table definition whose primary-key field must hold a portable Vault key. */\nexport type SchemaEntry<T extends object, Key extends keyof T & string = keyof T & string> = T[Key] extends VaultKey\n ? {\n defaultTtl?: number;\n /** IndexedDB creates these as `value.<field>` indexes; other stores filter in memory. */\n indexes?: readonly (keyof T & string)[];\n key: Key;\n }\n : never;\n\nexport type AnySchema = Record<string, { defaultTtl?: number; indexes?: readonly string[]; key: string }>;\n\nexport type RecordOf<S extends AnySchema, K extends keyof S> =\n S[K] extends SchemaEntry<infer R, infer _Key> ? R : never;\nexport type KeyOf<S extends AnySchema, K extends keyof S> = Extract<\n S[K] extends SchemaEntry<infer R, infer Key> ? R[Key] : never,\n VaultKey\n>;\n\nexport type VaultLogger = {\n error(message: string, context?: Error | Record<string, unknown>): void;\n};\n\nexport type RecordValidator<T> = {\n parse(value: unknown): T;\n};\n\nexport type TableValidators<S extends AnySchema> = {\n [K in keyof S]?: RecordValidator<RecordOf<S, K>>;\n};\n\nexport type Observer<T> = (records: T[]) => void;\nexport type Unsubscribe = () => void;\n\n/** Shared factory options. Values always use Vault's fixed `{ value, expiresAt? }` envelope. */\nexport type BaseAdapterOptions<S extends AnySchema> = {\n logger?: VaultLogger;\n onMetrics?: (event: MetricsEvent) => void;\n schema: S;\n validators?: TableValidators<S>;\n};\n\nexport type MetricsEvent = {\n duration: number;\n operation:\n | 'batch'\n | 'clear'\n | 'count'\n | 'delete'\n | 'deleteMany'\n | 'entries'\n | 'get'\n | 'getAll'\n | 'getMany'\n | 'getOrDefault'\n | 'has'\n | 'isEmpty'\n | 'keys'\n | 'put'\n | 'putAll'\n | 'query'\n | 'queryDelete'\n | 'update'\n | 'upsert';\n table: string;\n};\n\nexport type DebugStats = { expiredCount: number; recordCount: number };\nexport type DebugInfo<S extends AnySchema> = { tables: Array<{ name: keyof S & string } & DebugStats> };\n\n/** Methods available within an IndexedDB or SQLite transaction. */\nexport type TransactionContext<S extends AnySchema, K extends keyof S & string = keyof S & string> = {\n clear<T extends K>(table: T): Promise<void>;\n count<T extends K>(table: T): Promise<number>;\n delete<T extends K>(table: T, key: KeyOf<S, T>): Promise<boolean>;\n deleteMany<T extends K>(table: T, keys: KeyOf<S, T>[]): Promise<number>;\n entries<T extends K>(table: T): Promise<Array<[KeyOf<S, T>, RecordOf<S, T>]>>;\n get<T extends K>(table: T, key: KeyOf<S, T>): Promise<RecordOf<S, T> | undefined>;\n getAll<T extends K>(table: T): Promise<RecordOf<S, T>[]>;\n getMany<T extends K>(table: T, keys: KeyOf<S, T>[]): Promise<Array<RecordOf<S, T> | undefined>>;\n getOrDefault<T extends K>(\n table: T,\n key: KeyOf<S, T>,\n defaultFn: () => RecordOf<S, T>,\n ttl?: number,\n ): Promise<RecordOf<S, T>>;\n has<T extends K>(table: T, key: KeyOf<S, T>): Promise<boolean>;\n isEmpty<T extends K>(table: T): Promise<boolean>;\n keys<T extends K>(table: T, filter?: (record: RecordOf<S, T>) => boolean): Promise<KeyOf<S, T>[]>;\n put<T extends K>(table: T, value: RecordOf<S, T>, ttl?: number): Promise<void>;\n putAll<T extends K>(table: T, values: RecordOf<S, T>[], ttl?: number): Promise<void>;\n query<T extends K>(table: T): QueryBuilder<RecordOf<S, T>>;\n update<T extends K>(\n table: T,\n key: KeyOf<S, T>,\n changes: Partial<RecordOf<S, T>>,\n ttl?: number,\n ): Promise<RecordOf<S, T> | undefined>;\n upsert<T extends K>(\n table: T,\n key: KeyOf<S, T>,\n fn: (existing: RecordOf<S, T> | undefined) => RecordOf<S, T>,\n ttl?: number,\n ): Promise<RecordOf<S, T>>;\n};\n\n/** Portable API returned by memory and Web Storage factories. */\nexport interface VaultStore<S extends AnySchema> {\n clear<K extends keyof S & string>(table: K): Promise<void>;\n count<K extends keyof S & string>(table: K): Promise<number>;\n debug(): Promise<DebugInfo<S>>;\n delete<K extends keyof S & string>(table: K, key: KeyOf<S, K>): Promise<boolean>;\n deleteMany<K extends keyof S & string>(table: K, keys: KeyOf<S, K>[]): Promise<number>;\n readonly disposalSignal: AbortSignal;\n dispose(): Promise<void>;\n readonly disposed: boolean;\n entries<K extends keyof S & string>(table: K): Promise<Array<[KeyOf<S, K>, RecordOf<S, K>]>>;\n get<K extends keyof S & string>(table: K, key: KeyOf<S, K>): Promise<RecordOf<S, K> | undefined>;\n getAll<K extends keyof S & string>(table: K): Promise<RecordOf<S, K>[]>;\n getMany<K extends keyof S & string>(table: K, keys: KeyOf<S, K>[]): Promise<Array<RecordOf<S, K> | undefined>>;\n getOrDefault<K extends keyof S & string>(\n table: K,\n key: KeyOf<S, K>,\n defaultFn: () => RecordOf<S, K>,\n ttl?: number,\n ): Promise<RecordOf<S, K>>;\n has<K extends keyof S & string>(table: K, key: KeyOf<S, K>): Promise<boolean>;\n isEmpty<K extends keyof S & string>(table: K): Promise<boolean>;\n keys<K extends keyof S & string>(table: K, filter?: (record: RecordOf<S, K>) => boolean): Promise<KeyOf<S, K>[]>;\n observe<K extends keyof S & string>(\n table: K,\n listener: Observer<RecordOf<S, K>>,\n options?: { immediate?: boolean; signal?: AbortSignal },\n ): Unsubscribe;\n pruneExpired(): Promise<Record<keyof S & string, number>>;\n put<K extends keyof S & string>(table: K, value: RecordOf<S, K>, ttl?: number): Promise<void>;\n putAll<K extends keyof S & string>(table: K, values: RecordOf<S, K>[], ttl?: number): Promise<void>;\n query<K extends keyof S & string>(table: K): QueryBuilder<RecordOf<S, K>>;\n update<K extends keyof S & string>(\n table: K,\n key: KeyOf<S, K>,\n changes: Partial<RecordOf<S, K>>,\n ttl?: number,\n ): Promise<RecordOf<S, K> | undefined>;\n upsert<K extends keyof S & string>(\n table: K,\n key: KeyOf<S, K>,\n fn: (existing: RecordOf<S, K> | undefined) => RecordOf<S, K>,\n ttl?: number,\n ): Promise<RecordOf<S, K>>;\n [Symbol.asyncDispose](): Promise<void>;\n}\n\n/** Atomic, scoped transactions supplied by storage engines that support them. */\nexport interface TransactionalVaultStore<S extends AnySchema> extends VaultStore<S> {\n batch<K extends keyof S & string, R>(\n tables: readonly K[],\n fn: (tx: TransactionContext<S, K>) => Promise<R>,\n ): Promise<R>;\n}\n\n/** Lazy record iteration supplied by storage engines that support it. */\nexport interface IterableVaultStore<S extends AnySchema> extends VaultStore<S> {\n iterate<K extends keyof S & string>(table: K): AsyncIterable<RecordOf<S, K>>;\n}\n\n/** IndexedDB-only guarantees: cursor iteration and atomic, scoped transactions. */\nexport interface IndexedDbVaultStore<S extends AnySchema> extends TransactionalVaultStore<S>, IterableVaultStore<S> {}\n\n/** Define a typed table whose primary-key field holds a portable Vault key. */\nexport function table<T extends object, Key extends keyof T & string = keyof T & string>(\n key: Key & (T[Key] extends VaultKey ? unknown : never),\n options: { defaultTtl?: number; indexes?: readonly (keyof T & string)[] } = {},\n): SchemaEntry<T, Key> {\n const { defaultTtl, indexes } = options;\n\n if (defaultTtl !== undefined) assertPositiveFinite(defaultTtl, 'table: defaultTtl');\n\n if (indexes) {\n const seen = new Set<string>();\n\n for (const field of indexes) {\n if (seen.has(field)) {\n throw new VaultError(`table: index \"${field}\" is already registered`);\n }\n\n seen.add(field);\n }\n }\n\n return { defaultTtl, indexes, key } as unknown as SchemaEntry<T, Key>;\n}\n"],"mappings":";;;AAmLA,SAAgB,EACd,GACA,IAA4E,CAAC,GACxD;CACrB,IAAM,EAAE,eAAY,eAAY;CAIhC,IAFI,MAAe,KAAA,KAAW,EAAqB,GAAY,mBAAmB,GAE9E,GAAS;EACX,IAAM,oBAAO,IAAI,IAAY;EAE7B,KAAK,IAAM,KAAS,GAAS;GAC3B,IAAI,EAAK,IAAI,CAAK,GAChB,MAAM,IAAI,EAAW,iBAAiB,EAAM,wBAAwB;GAGtE,EAAK,IAAI,CAAK;EAChB;CACF;CAEA,OAAO;EAAE;EAAY;EAAS;CAAI;AACpC"}
package/dist/vault.cjs CHANGED
@@ -1,2 +1,2 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=class extends Error{constructor(e,t){super(e,t),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}},t=class extends e{constructor(e=`adapter is disposed`,t){super(e,t)}},n=class extends e{},r=class extends e{},i=class extends e{};function a(n,r){if(!Number.isFinite(r.interval)||r.interval<=0)throw new e(`scheduleExpiredPrune: interval must be a finite positive number`);let i=!0,a=()=>{i=!1,clearInterval(o)};r.signal?.addEventListener(`abort`,a,{once:!0});let o=setInterval(()=>{i&&n.pruneExpired().catch(e=>{e instanceof t?(i=!1,clearInterval(o)):r.onError?r.onError(e):`${String(e)}`})},r.interval);return a}var o={days:e=>c(c(e,`ttl.days`)*864e5,`ttl.days (result)`),hours:e=>c(c(e,`ttl.hours`)*36e5,`ttl.hours (result)`),minutes:e=>c(c(e,`ttl.minutes`)*6e4,`ttl.minutes (result)`),ms:e=>c(e,`ttl.ms`),seconds:e=>c(c(e,`ttl.seconds`)*1e3,`ttl.seconds (result)`)};function s(e){return e!==void 0&&Date.now()>=e}function c(t,n){if(!Number.isFinite(t)||t<=0)throw new e(`${n} expected a finite positive number, received ${String(t)}`);return t}function l(t){function n(t){return{...t,index:r=>{let i=t.indexes??[];if(i.includes(r))throw new e(`table index "${r}" is already registered`);return n({...t,indexes:[...i,r]})},ttl:e=>(c(e,`table.ttl`),n({...t,defaultTtl:e}))}}return n({key:t})}exports.VaultDisposedError=t,exports.VaultError=e,exports.VaultMigrationError=i,exports.VaultQuotaError=r,exports.VaultScopeError=n,exports.isExpired=s,exports.scheduleExpiredPrune=a,exports.table=l,exports.ttl=o;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=class extends Error{constructor(e,t){super(e,t),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}},t=class extends e{constructor(e=`adapter is disposed`,t){super(e,t)}},n=class extends e{},r=class extends e{},i=class extends e{},a={days:e=>s(e*864e5,`ttl.days`),hours:e=>s(e*36e5,`ttl.hours`),minutes:e=>s(e*6e4,`ttl.minutes`),ms:e=>s(e,`ttl.ms`),seconds:e=>s(e*1e3,`ttl.seconds`)};function o(e){return e!==void 0&&Date.now()>=e}function s(t,n){if(!Number.isFinite(t)||t<=0)throw new e(`${n} expected a finite positive number, received ${String(t)}`);return t}function c(e,t){s(t.interval,`scheduleExpiredPrune: interval`);let n=setInterval(()=>{e.pruneExpired().catch(e=>{t.onError&&t.onError(e)})},t.interval),r=()=>clearInterval(n);return t.signal?.addEventListener(`abort`,r,{once:!0}),r}function l(t,n={}){let{defaultTtl:r,indexes:i}=n;if(r!==void 0&&s(r,`table: defaultTtl`),i){let t=new Set;for(let n of i){if(t.has(n))throw new e(`table: index "${n}" is already registered`);t.add(n)}}return{defaultTtl:r,indexes:i,key:t}}exports.VaultDisposedError=t,exports.VaultError=e,exports.VaultMigrationError=i,exports.VaultQuotaError=r,exports.VaultScopeError=n,exports.isExpired=o,exports.scheduleExpiredPrune=c,exports.table=l,exports.ttl=a;
2
2
  //# sourceMappingURL=vault.cjs.map