@datakable/core 2.0.1 → 2.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -2
- package/dist/{codes-B9bCK73-.d.cts → codes-4sYQv_7J.d.cts} +42 -12
- package/dist/{codes-B9bCK73-.d.ts → codes-4sYQv_7J.d.ts} +42 -12
- package/dist/column-filters.d.cts +2 -2
- package/dist/column-filters.d.ts +2 -2
- package/dist/diagnostics/build.cjs +1 -1
- package/dist/diagnostics/build.cjs.map +1 -1
- package/dist/diagnostics/build.js +2 -2
- package/dist/diagnostics/build.js.map +1 -1
- package/dist/diagnostics/console.cjs +15 -4
- package/dist/diagnostics/console.cjs.map +1 -1
- package/dist/diagnostics/console.js +15 -4
- package/dist/diagnostics/console.js.map +1 -1
- package/dist/diagnostics/explain.cjs.map +1 -1
- package/dist/diagnostics/explain.js.map +1 -1
- package/dist/diagnostics/hub.cjs +7 -1
- package/dist/diagnostics/hub.cjs.map +1 -1
- package/dist/diagnostics/hub.js +7 -1
- package/dist/diagnostics/hub.js.map +1 -1
- package/dist/diagnostics/prose.cjs +10 -1
- package/dist/diagnostics/prose.cjs.map +1 -1
- package/dist/diagnostics/prose.js +9 -1
- package/dist/diagnostics/prose.js.map +1 -1
- package/dist/diagnostics/redact.cjs +1 -1
- package/dist/diagnostics/redact.cjs.map +1 -1
- package/dist/diagnostics/redact.js +1 -1
- package/dist/diagnostics/redact.js.map +1 -1
- package/dist/diagnostics/types.cjs.map +1 -1
- package/dist/{explain-i0OATi_W.d.ts → explain-DmwN_RG9.d.cts} +13 -6
- package/dist/{explain-Q8Cg0cZy.d.cts → explain-Dr3SmMNY.d.ts} +13 -6
- package/dist/feature/install.cjs +2 -1
- package/dist/feature/install.cjs.map +1 -1
- package/dist/feature/install.js +2 -1
- package/dist/feature/install.js.map +1 -1
- package/dist/feature/slice-guard.cjs +76 -0
- package/dist/feature/slice-guard.cjs.map +1 -0
- package/dist/feature/slice-guard.js +50 -0
- package/dist/feature/slice-guard.js.map +1 -0
- package/dist/features/column-filters/codes.cjs +2 -19
- package/dist/features/column-filters/codes.cjs.map +1 -1
- package/dist/features/column-filters/codes.js +2 -19
- package/dist/features/column-filters/codes.js.map +1 -1
- package/dist/features/column-filters/column-filters.cjs +37 -22
- package/dist/features/column-filters/column-filters.cjs.map +1 -1
- package/dist/features/column-filters/column-filters.js +37 -22
- package/dist/features/column-filters/column-filters.js.map +1 -1
- package/dist/features/column-filters/match.cjs +6 -2
- package/dist/features/column-filters/match.cjs.map +1 -1
- package/dist/features/column-filters/match.js +6 -2
- package/dist/features/column-filters/match.js.map +1 -1
- package/dist/features/pagination/pagination.cjs +2 -2
- package/dist/features/pagination/pagination.cjs.map +1 -1
- package/dist/features/pagination/pagination.js +2 -2
- package/dist/features/pagination/pagination.js.map +1 -1
- package/dist/features/search/codes.cjs +18 -2
- package/dist/features/search/codes.cjs.map +1 -1
- package/dist/features/search/codes.js +16 -1
- package/dist/features/search/codes.js.map +1 -1
- package/dist/features/search/search-engine.cjs +24 -5
- package/dist/features/search/search-engine.cjs.map +1 -1
- package/dist/features/search/search-engine.js +25 -6
- package/dist/features/search/search-engine.js.map +1 -1
- package/dist/features/sorting/sorting.cjs +55 -24
- package/dist/features/sorting/sorting.cjs.map +1 -1
- package/dist/features/sorting/sorting.js +55 -24
- package/dist/features/sorting/sorting.js.map +1 -1
- package/dist/index.d.cts +26 -17
- package/dist/index.d.ts +26 -17
- package/dist/intercept/runtime.cjs +3 -2
- package/dist/intercept/runtime.cjs.map +1 -1
- package/dist/intercept/runtime.js +3 -2
- package/dist/intercept/runtime.js.map +1 -1
- package/dist/messages/index.cjs +2 -0
- package/dist/messages/index.cjs.map +1 -1
- package/dist/messages/index.js +2 -0
- package/dist/messages/index.js.map +1 -1
- package/dist/pagination.d.cts +2 -2
- package/dist/pagination.d.ts +2 -2
- package/dist/schema.d.cts +2 -2
- package/dist/schema.d.ts +2 -2
- package/dist/{search-async-entry-CuLYPfY_.d.cts → search-async-entry-BiemO3JT.d.cts} +2 -2
- package/dist/{search-async-entry-Cx7xpuVZ.d.ts → search-async-entry-GRj0E06n.d.ts} +2 -2
- package/dist/search-async.d.cts +3 -3
- package/dist/search-async.d.ts +3 -3
- package/dist/search.d.cts +4 -4
- package/dist/search.d.ts +4 -4
- package/dist/server.d.cts +3 -3
- package/dist/server.d.ts +3 -3
- package/dist/sorting.d.cts +2 -2
- package/dist/sorting.d.ts +2 -2
- package/dist/source/async-control.cjs +2 -1
- package/dist/source/async-control.cjs.map +1 -1
- package/dist/source/async-control.js +2 -1
- package/dist/source/async-control.js.map +1 -1
- package/dist/source/fetcher.cjs.map +1 -1
- package/dist/source/fetcher.js.map +1 -1
- package/dist/source/server.cjs +58 -5
- package/dist/source/server.cjs.map +1 -1
- package/dist/source/server.js +58 -5
- package/dist/source/server.js.map +1 -1
- package/dist/table/create-table.cjs +30 -20
- package/dist/table/create-table.cjs.map +1 -1
- package/dist/table/create-table.js +30 -20
- package/dist/table/create-table.js.map +1 -1
- package/dist/table/index.cjs +3 -0
- package/dist/table/index.cjs.map +1 -1
- package/dist/table/index.js +5 -1
- package/dist/table/index.js.map +1 -1
- package/dist/table/state-codes.cjs +72 -0
- package/dist/table/state-codes.cjs.map +1 -0
- package/dist/table/state-codes.js +45 -0
- package/dist/table/state-codes.js.map +1 -0
- package/dist/table/types.cjs.map +1 -1
- package/dist/table/types.js.map +1 -1
- package/dist/validity.d.cts +2 -2
- package/dist/validity.d.ts +2 -2
- package/dist/version.cjs +1 -1
- package/dist/version.cjs.map +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/package.json +1 -1
- package/dist/ingest/test-schemas.cjs +0 -73
- package/dist/ingest/test-schemas.cjs.map +0 -1
- package/dist/ingest/test-schemas.js +0 -46
- package/dist/ingest/test-schemas.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/features/sorting/sorting.ts"],"sourcesContent":["import { optionDiagnostics } from '../../catalog/codes'\nimport { defineOptions } from '../../catalog/options'\nimport { describeReturn } from '../../catalog/slots'\nimport type { SortAlgorithm } from '../../column/column-def'\nimport { compilePath, getValue } from '../../column/get-value'\nimport type { Path } from '../../column/path'\nimport { keepDiagnostics } from '../../diagnostics/catalog'\nimport '../../diagnostics/process-guard'\nimport type { Emit } from '../../diagnostics/types'\nimport { defineFeature } from '../../feature/define'\nimport type { FeatureTypes, RowModelContext } from '../../feature/types'\nimport { CellFailures } from '../../intercept/cell-batch'\nimport { errorName } from '../../intercept/classify'\nimport { boundaryDiagnostics } from '../../intercept/codes'\nimport { type ResolvedColumn, resolveColumns } from '../../pipeline/columns'\nimport { envDiagnostics } from '../../pipeline/env-codes'\nimport { allRows } from '../../pipeline/indices'\nimport { sliced } from '../../pipeline/slice'\nimport type { ColumnValues } from '../../pipeline/types'\nimport { type DataMode, modeOption } from '../../source/mode'\nimport { detectCapability, hasCapability } from '../../versioning/capability'\nimport { comparatorDiagnostics, sortingDiagnostics } from './codes'\nimport {\n defaultIndexComparator,\n type IndexComparator,\n RANK,\n sortFnIndexComparator,\n typeRank,\n} from './compare'\nimport { collationRanks } from './ranks'\nimport {\n chooseAuto,\n hasExsorted,\n intKeys,\n needsIntKeys,\n sortIntKeys,\n sortWithComparator,\n} from './strategy'\n\nkeepDiagnostics(\n sortingDiagnostics,\n comparatorDiagnostics,\n boundaryDiagnostics,\n optionDiagnostics,\n envDiagnostics,\n)\n\n/** One sort key: a column id (a path of the row type) and its direction. */\nexport type SortEntry<T> = { id: Path<T>; desc: boolean }\n\n/** The `sorting` slice (§6.4): multi-column, earlier entries first. Empty = unsorted. */\nexport type SortingState<T> = { by: readonly SortEntry<T>[] }\n\nexport type SortDirection = 'asc' | 'desc'\n\n/** Replaces the sort; an equal one keeps the slice (same reference, no notification, #21). */\nconst setSort = (\n ctx: { setState(u: (s: SortingState<unknown>) => SortingState<unknown>): void },\n by: readonly SortEntry<unknown>[],\n) => ctx.setState((s) => (JSON.stringify(s.by) === JSON.stringify(by) ? s : { by: by.slice() }))\n\nexport type SortingApi<T> = {\n /**\n * Cycles `id` asc → desc → none. Without `multi` the result is a single-column sort; with `multi`\n * (Shift+click) `id` is appended, cycled in place or removed and the other entries are kept.\n */\n toggleSort(id: Path<T>, options?: { multi?: boolean }): void\n /** Replaces the whole sort. */\n setSorting(by: readonly SortEntry<T>[]): void\n /** Removes every sort entry (input order). */\n clearSorting(): void\n /** `id`'s direction in the current sort, or `false` (for `aria-sort`). */\n getSortDirection(id: Path<T>): SortDirection | false\n}\n\nexport interface SortingTypes extends FeatureTypes {\n state: SortingState<this['T']>\n api: SortingApi<this['T']>\n}\n\n/**\n * How rows are sorted (§6.4): `'auto'` (default) picks per sort from one O(n) scan — exsorted\n * tim / counting / radix for a single column of safe-integer keys (numbers, `Date`s), native\n * `Array.prototype.sort` otherwise. A built-in name forces that algorithm (radix / counting only\n * apply to safe-integer keys); a function sorts the row indices itself.\n */\nexport type SortAlgorithmOption = SortAlgorithm\n\nexport interface SortingOptions {\n /**\n * Locale(s) of the string collator (`Intl.Collator(locale, { numeric: true })`). Default `'en'`,\n * not the runtime's: the server and the browser must sort alike (SSR hydration, #12).\n */\n locale?: string | readonly string[]\n /** The sort algorithm (default `'auto'`); a column's `sortAlgorithm` takes precedence. */\n algorithm?: SortAlgorithmOption\n /** Reports the algorithm chosen for each sort, why, n and the time taken (`DK_SORT_STRATEGY`). */\n debug?: boolean\n /**\n * `'server'`: the server sorts (its state goes to `options.fetcher`, or the app fetches); core\n * skips this step (§7.1). Default `'client'`.\n */\n mode?: DataMode\n}\n\nconst validLocale = (v: unknown) => {\n try {\n Intl.getCanonicalLocales(v as string | string[])\n return true\n } catch {\n return false\n }\n}\n\nconst ALGORITHMS = ['auto', 'tim', 'radix', 'counting', 'native'] as const\n\nconst sortingOptions = {\n locale: {\n type: ['string', 'array'],\n check: validLocale,\n expected: 'a BCP 47 locale tag or a list of them, e.g. \"th\" or [\"th\", \"en\"]',\n },\n algorithm: {\n type: ['string', 'function'],\n oneOf: ALGORITHMS,\n // A literal (not built from ALGORITHMS): a module-level call would keep the schema in production.\n expected:\n \"one of 'auto', 'tim', 'radix', 'counting', 'native', or (indices, compare) => indices\",\n },\n debug: { type: 'boolean' },\n mode: modeOption,\n} as const\n\ntype CustomAlgorithm = Extract<SortAlgorithm, (...args: never[]) => unknown>\n\nconst now = () => (typeof performance === 'undefined' ? Date.now() : performance.now())\n\n/**\n * From this many rows, `auto` sorts a string column by precomputed collation ranks (§9.1): one\n * time-sliced job per column values, then integer-key sorts (a few ms at 100k rows) instead of a\n * collator call per comparison (~100–200 ms at 100k, one long task).\n */\nconst RANKS_MIN = 10_000\n\nconst missing = (v: unknown) => typeRank(v) === RANK.missing\n\n/**\n * Dev check of a column's `sortFn` (§8.3 `DK_SORT_COMPARATOR_INVALID`), sampled: up to 8 present\n * values spread over the input, every pair both ways. A throw gives no verdict (the sort reports\n * it as `DK_CALLBACK_FAILED`).\n */\nfunction checkSortFn(\n fn: SortFn,\n values: ColumnValues,\n indices: Uint32Array,\n): { reason: 'nan' | 'not-number' | 'inconsistent'; received?: string } | undefined {\n const sample: unknown[] = []\n const step = Math.max(1, Math.floor(indices.length / 8))\n for (let i = 0; i < indices.length && sample.length < 8; i += step) {\n const v = values[indices[i] as number]\n if (!missing(v)) sample.push(v)\n }\n try {\n for (let i = 0; i < sample.length; i++) {\n for (let j = i; j < sample.length; j++) {\n const x = fn(sample[i], sample[j])\n const y = fn(sample[j], sample[i])\n for (const r of [x, y]) {\n if (typeof r !== 'number') return { reason: 'not-number', received: describeReturn(r) }\n if (Number.isNaN(r)) return { reason: 'nan' }\n }\n if (Math.sign(x) !== -Math.sign(y)) return { reason: 'inconsistent' }\n }\n }\n } catch {\n return undefined\n }\n return undefined\n}\n\ntype SortFn = (a: unknown, b: unknown) => number\ntype SortBy = (row: unknown) => unknown\n\nconst fnField = (def: object, field: 'sortFn' | 'sortBy') => {\n const f = (def as Record<string, unknown>)[field]\n return typeof f === 'function' ? f : undefined\n}\n\n/** Aborts a native sort when a column's `sortFn` throws (the entry then falls back). */\nclass SortFnFailed {\n constructor(\n readonly entry: number,\n readonly error: unknown,\n ) {}\n}\n\n/**\n * Sorting (§6.4): `toggleSort` (asc → desc → none, `multi`), stable sort of the row indices with\n * the default comparator — missing values (`null`, `undefined`, `NaN`, invalid `Date`) last in both\n * directions, mixed types by type rank, strings with one `Intl.Collator(locale, { numeric: true })`\n * — or a column's `sortFn` / `sortBy`. Never touches the data: a copy of the index array is sorted.\n *\n * `algorithm: 'auto'` (default) picks per sort from one O(n) scan (§6.4): exsorted tim / counting /\n * radix for a single column of safe-integer keys (numbers, `Date`s), native `Array.prototype.sort`\n * (stable) for strings, floats, multi-column and `sortFn`. Every choice gives the same stable order.\n * `sorting({ algorithm })` or a column's `sortAlgorithm` overrides it; `debug: true` reports each\n * choice (`DK_SORT_STRATEGY`).\n */\nexport const sorting = (opts: SortingOptions = {}) => {\n let collator: Intl.Collator | undefined\n /** The collator; `DK_ENV_FALLBACK` when the runtime supports none of the requested locales. */\n const getCollator = (emit: Emit) => {\n if (collator) return collator\n const locale = (opts.locale ?? 'en') as string | string[]\n let supported = true\n try {\n collator = new Intl.Collator(locale, { numeric: true })\n supported = Intl.Collator.supportedLocalesOf(locale).length > 0\n } catch {\n collator = new Intl.Collator(undefined, { numeric: true })\n supported = false\n }\n if (!supported) {\n emit('DK_ENV_FALLBACK', {\n api: 'Intl.Collator',\n feature: 'sorting',\n requested: ([] as string[]).concat(locale).join(', '),\n fallback: `collation|${collator.resolvedOptions().locale}`,\n })\n }\n return collator\n }\n\n /** Values array → the key of its collation-ranks job (`ctx.slice`); released with the values. */\n const rankKeys = new WeakMap<object, object>()\n function ranksFor(ctx: RowModelContext, values: readonly unknown[]) {\n let key = rankKeys.get(values)\n if (!key) {\n key = {}\n rankKeys.set(values, key)\n }\n const c = getCollator(ctx.emit)\n return sliced(ctx, key, () => collationRanks(values, c))\n }\n /** The last sorted output and its input: the stand-in while ranks are computed (§9.1). */\n let shown: { input: Uint32Array; output: Uint32Array } | undefined\n\n // Values that the column cache does not hold, per data reference (released with it).\n const sortByCache = new WeakMap<readonly unknown[], WeakMap<object, unknown[]>>()\n const pathCache = new WeakMap<readonly unknown[], Map<string, unknown[]>>()\n /** exsorted feature detection (§8.5), once per feature instance, on the first sort needing it. */\n let exsorted: boolean | undefined\n\n /** `sortBy` failures (§3.4): numbers only; text is built only when a cell failed. */\n const sortByFailures = new CellFailures()\n\n /**\n * `sortBy` is a cell slot: one `column:batch` per column per data reference, an inline\n * `try/catch` per row. A failed row (or a batch an interceptor skipped) keys as `undefined`,\n * which sorts last.\n */\n function sortByValues(ctx: RowModelContext, col: ResolvedColumn, sortBy: SortBy): unknown[] {\n const data = ctx.data\n let byDef = sortByCache.get(data)\n if (!byDef) {\n byDef = new WeakMap()\n sortByCache.set(data, byDef)\n }\n let out = byDef.get(col.def)\n if (out) return out\n const values: unknown[] = new Array(data.length).fill(undefined)\n const rows = allRows(data)\n sortByFailures.reset()\n ctx.batch(col.id, 'sortBy', rows, () => {\n for (let i = 0; i < rows.length; i++) {\n const r = rows[i] as number\n try {\n values[r] = sortBy(data[r])\n } catch (e) {\n sortByFailures.add(r, e)\n }\n }\n sortByFailures.report(ctx.emit, col.index, col.id, 'sortBy')\n })\n sortByFailures.reset()\n out = values\n byDef.set(col.def, out)\n return out\n }\n\n function pathValues(ctx: RowModelContext, id: string): unknown[] {\n const data = ctx.data\n let byId = pathCache.get(data)\n if (!byId) {\n byId = new Map()\n pathCache.set(data, byId)\n }\n let out = byId.get(id)\n if (out) return out\n const path = compilePath(id)\n out = new Array(data.length)\n for (let r = 0; r < data.length; r++) out[r] = getValue(data[r], path)\n byId.set(id, out)\n return out\n }\n\n return defineFeature<'sorting', SortingTypes>({\n name: 'sorting',\n stage: 'sort',\n mode: opts.mode ?? 'client',\n options: defineOptions(\n // The option validator runs in development only (§9.3): production drops the schema.\n (process.env.NODE_ENV !== \"production\") ? sortingOptions : ({} as typeof sortingOptions),\n opts,\n ),\n initialState: () => ({ by: [] }),\n // After destroy(): still a declared value (`aria-sort` reads it during teardown renders).\n destroyedResult: { getSortDirection: () => false },\n createApi: (ctx) => ({\n toggleSort: (id, options) =>\n ctx.setState((s) => {\n const by = s.by\n const i = by.findIndex((e) => e.id === id)\n const cur = by[i]\n const next = !cur ? { id, desc: false } : cur.desc ? undefined : { id, desc: true }\n if (!options?.multi) return { by: next ? [next] : [] }\n if (!cur) return { by: [...by, next as SortEntry<unknown>] }\n const out = by.slice()\n if (next) out[i] = next\n else out.splice(i, 1)\n return { by: out }\n }),\n setSorting: (by) => setSort(ctx, by),\n clearSorting: () => setSort(ctx, []),\n getSortDirection: (id) => {\n const e = ctx.getState().by.find((x) => x.id === id)\n return e ? (e.desc ? 'desc' : 'asc') : false\n },\n }),\n rowModel: (indices, state, ctx) => {\n const by = state?.by\n if (!by || by.length === 0 || indices.length < 2) {\n shown = undefined\n return indices\n }\n const t0 = opts.debug ? now() : 0\n const cols = resolveColumns(ctx.columns)\n const entries = by.map((e) => {\n const id = String(e.id)\n const col = cols.byId.get(id)\n const sortBy = col && (fnField(col.def, 'sortBy') as SortBy | undefined)\n const values: ColumnValues = sortBy\n ? sortByValues(ctx, col, sortBy)\n : (ctx.getColumnValues(id) ?? pathValues(ctx, id))\n const sortFn =\n col && !sortBy ? (fnField(col.def, 'sortFn') as SortFn | undefined) : undefined\n return { col, desc: e.desc === true, values, sortFn, ranked: false }\n })\n\n // Dev (§8.3): a sampled sortFn check; an invalid one falls back to the default comparator.\n if ((process.env.NODE_ENV !== \"production\")) {\n for (const e of entries) {\n if (!e.sortFn) continue\n const bad = checkSortFn(e.sortFn, e.values, indices)\n if (!bad) continue\n e.sortFn = undefined\n const col = e.col as ResolvedColumn\n ctx.emit('DK_SORT_COMPARATOR_INVALID', { column: col.id, index: col.index, ...bad })\n }\n }\n\n // The requested algorithm: the primary column's `sortAlgorithm`, else the table's.\n const primary = entries[0] as (typeof entries)[number]\n const colAlgorithm =\n primary.col && (primary.col.def as { sortAlgorithm?: unknown }).sortAlgorithm\n const fromColumn = colAlgorithm !== undefined\n let requested = (fromColumn ? colAlgorithm : (opts.algorithm ?? 'auto')) as SortAlgorithm\n const noEffect = (reason: string) =>\n ctx.emit(\n 'DK_OPTION_NO_EFFECT',\n fromColumn\n ? { path: `columns[${primary.col?.index}].sortAlgorithm`, reason, once: false }\n : { path: 'algorithm', feature: 'sorting', reason, once: false },\n )\n if (\n typeof requested !== 'function' &&\n !(ALGORITHMS as readonly unknown[]).includes(requested)\n ) {\n noEffect(`not-algorithm|${JSON.stringify(requested)}`)\n requested = 'auto'\n }\n if (requested !== 'native' && exsorted === undefined) {\n // DK_DEP_INCOMPATIBLE is a development check (§8.5); the fallback is not.\n exsorted = (process.env.NODE_ENV !== \"production\")\n ? detectCapability(\n hasExsorted,\n {\n feature: 'sorting',\n dependency: 'exsorted',\n capability: 'timSort / radixSort / countingSort',\n supported: '^1.2.3',\n fallback: 'Array.prototype.sort (native, stable)',\n },\n ctx.emit,\n )\n : hasCapability(hasExsorted)\n }\n\n // auto at large n (§9.1): string columns sort by collation ranks, computed by a sliced job.\n if (requested === 'auto' && indices.length >= RANKS_MIN) {\n let computing = false\n for (const e of entries) {\n if (e.sortFn || e.values instanceof Float64Array) continue\n const ranks = ranksFor(ctx, e.values)\n if (ranks === undefined) computing = true\n else if (ranks) {\n e.values = ranks\n e.ranked = true\n }\n }\n // Meanwhile: the previous order of these rows (or the input order); 'pending'.\n if (computing) return shown && shown.input === indices ? shown.output : indices\n }\n const ranked = entries.some((e) => e.ranked)\n\n const build = (): IndexComparator => {\n const cmps = entries.map((e, k) => {\n const fn = e.sortFn\n if (!fn) return defaultIndexComparator(e.values, e.desc, getCollator(ctx.emit))\n const guarded: SortFn = (a, b) => {\n try {\n return fn(a, b)\n } catch (error) {\n throw new SortFnFailed(k, error)\n }\n }\n return sortFnIndexComparator(e.values, e.desc, guarded)\n })\n if (cmps.length === 1) return cmps[0] as IndexComparator\n return (a, b) => {\n for (let k = 0; k < cmps.length; k++) {\n const c = (cmps[k] as IndexComparator)(a, b)\n if (c !== 0) return c\n }\n return 0\n }\n }\n\n let algorithm: string = 'native'\n let reason = ''\n /** One attempt; a throwing sortFn propagates as SortFnFailed (the loop below retries). */\n const sortOnce = (): Uint32Array => {\n const want = requested\n if (typeof want === 'function') {\n const custom = want as CustomAlgorithm\n let res: unknown\n try {\n res = custom(indices.slice(), build())\n } catch (error) {\n if (error instanceof SortFnFailed) throw error\n reportCustom(true, error)\n return native('custom-threw')\n }\n if (res instanceof Uint32Array && res.length === indices.length) {\n algorithm = 'custom'\n reason = fromColumn ? 'column sortAlgorithm' : 'sorting({ algorithm })'\n return res\n }\n reportCustom(false, res)\n return native('custom-bad')\n }\n if (exsorted === false) return native('exsorted unavailable')\n const by = fromColumn ? 'column sortAlgorithm' : 'sorting({ algorithm })'\n // Integer keys: a single column with the default comparator (§6.4).\n const single = entries.length === 1 && !primary.sortFn\n const keys =\n single && want !== 'native' ? intKeys(primary.values, indices, primary.desc) : undefined\n if (want !== 'auto' && want !== 'native') {\n if (keys) {\n try {\n const out = sortIntKeys(keys, want)\n algorithm = want\n reason = `int-keys|${by}`\n return out\n } catch {\n noEffect(`exsorted-${want === 'counting' ? 'range' : 'failed'}|${want}`)\n }\n } else if (needsIntKeys(want)) {\n noEffect(`needs-int-keys|${want}`)\n } else {\n algorithm = want\n reason = by\n return sortWithComparator(indices, build(), want as 'tim')\n }\n } else if (want === 'native') return native(by)\n if (!keys) {\n return native(\n single ? 'not-safe-int' : entries.length > 1 ? 'multi-column' : 'custom sortFn',\n )\n }\n const choice = chooseAuto(keys)\n algorithm = choice.algorithm\n reason = `auto-${ranked ? 'ranked-' : ''}${choice.reason}`\n return sortIntKeys(keys, choice.algorithm)\n }\n const native = (why: string) => {\n algorithm = 'native'\n reason = ranked ? `ranks|${why}` : why\n return sortWithComparator(indices, build(), 'native')\n }\n /** A custom algorithm threw (`threw`, `value` = the error) or returned a bad `value`. */\n const reportCustom = (threw: boolean, value: unknown) => {\n const slot = fromColumn\n ? `columns[${primary.col?.index}].sortAlgorithm`\n : 'sorting.algorithm'\n const fallback = 'sorted-native'\n if (!threw) {\n // The slot contract check is dev only (§3.4 slotContract); the fallback applies always.\n if ((process.env.NODE_ENV !== \"production\")) {\n ctx.emit('DK_CALLBACK_BAD_RETURN', {\n slot,\n expected: `a Uint32Array of ${indices.length} row indices`,\n received: describeReturn(value),\n count: 1,\n fallback,\n })\n }\n return\n }\n const name = errorName(value)\n ctx.emit(\n 'DK_CALLBACK_FAILED',\n {\n slot,\n count: 1,\n fallback,\n ...(name === undefined ? {} : { errorName: name }),\n },\n { cause: value },\n )\n }\n\n // At most one retry per entry: each failing sortFn falls back to the default comparator.\n for (;;) {\n try {\n const out = sortOnce()\n if (opts.debug) {\n ctx.emit('DK_SORT_STRATEGY', {\n algorithm,\n reason,\n n: indices.length,\n ms: now() - t0,\n by: by.map((e) => `${String(e.id)}:${e.desc ? 'desc' : 'asc'}`),\n ...(primary.col ? { column: { index: primary.col.index, id: primary.col.id } } : {}),\n })\n }\n shown = { input: indices, output: out }\n return out\n } catch (e) {\n if (!(e instanceof SortFnFailed)) throw e\n const entry = entries[e.entry] as (typeof entries)[number]\n entry.sortFn = undefined\n const col = entry.col as ResolvedColumn\n const name = errorName(e.error)\n ctx.emit(\n 'DK_CALLBACK_FAILED',\n {\n slot: `columns[${col.index}].sortFn`,\n column: col.id,\n count: 1,\n fallback: 'sorted-default',\n ...(name === undefined ? {} : { errorName: name }),\n },\n { cause: e.error },\n )\n }\n }\n },\n })\n}\n"],"mappings":"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","names":["reason","by"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/features/sorting/sorting.ts"],"sourcesContent":["import { optionDiagnostics } from '../../catalog/codes'\nimport { defineOptions } from '../../catalog/options'\nimport { describeReturn } from '../../catalog/slots'\nimport type { SortAlgorithm } from '../../column/column-def'\nimport { compilePath, getValue } from '../../column/get-value'\nimport type { Path } from '../../column/path'\nimport { keepDiagnostics } from '../../diagnostics/catalog'\nimport '../../diagnostics/process-guard'\nimport { proseArg } from '../../diagnostics/prose'\nimport { describeValue } from '../../diagnostics/redact'\nimport type { Emit } from '../../diagnostics/types'\nimport { defineFeature } from '../../feature/define'\nimport { type SliceFix, sliceGuard } from '../../feature/slice-guard'\nimport type { FeatureTypes, RowModelContext } from '../../feature/types'\nimport { CellFailures } from '../../intercept/cell-batch'\nimport { errorName } from '../../intercept/classify'\nimport { boundaryDiagnostics } from '../../intercept/codes'\nimport { type ResolvedColumn, resolveColumns } from '../../pipeline/columns'\nimport { envDiagnostics } from '../../pipeline/env-codes'\nimport { allRows } from '../../pipeline/indices'\nimport { sliced } from '../../pipeline/slice'\nimport type { ColumnValues } from '../../pipeline/types'\nimport { type DataMode, modeOption } from '../../source/mode'\nimport { detectCapability, hasCapability } from '../../versioning/capability'\nimport { comparatorDiagnostics, sortingDiagnostics } from './codes'\nimport {\n defaultIndexComparator,\n type IndexComparator,\n RANK,\n sortFnIndexComparator,\n typeRank,\n} from './compare'\nimport { collationRanks } from './ranks'\nimport {\n chooseAuto,\n hasExsorted,\n intKeys,\n needsIntKeys,\n sortIntKeys,\n sortWithComparator,\n} from './strategy'\n\nkeepDiagnostics(\n sortingDiagnostics,\n comparatorDiagnostics,\n boundaryDiagnostics,\n optionDiagnostics,\n envDiagnostics,\n)\n\n/** One sort key: a column id (a path of the row type) and its direction. */\nexport type SortEntry<T> = { id: Path<T>; desc: boolean }\n\n/** The `sorting` slice (§6.4): multi-column, earlier entries first. Empty = unsorted. */\nexport type SortingState<T> = { by: readonly SortEntry<T>[] }\n\nexport type SortDirection = 'asc' | 'desc'\n\n/** An entry with an `id` (a `null` entry or one without an id is malformed, #89). */\nconst isEntry = (e: unknown): e is SortEntry<unknown> => (e as { id?: unknown } | null)?.id != null\n\nconst byOf = (s: unknown): unknown => (s as { by?: unknown } | null | undefined)?.by\n\n/**\n * The entries of a slice; `[]` for a malformed one (a controlled slice not fed back yet, #89).\n * The slice itself is replaced by the guard (`DK_INVALID_STATE`).\n */\nconst entriesOf = (s: unknown): readonly SortEntry<unknown>[] => {\n const by = byOf(s)\n return Array.isArray(by) ? by.filter(isEntry) : []\n}\n\n/** A malformed restored slice: the valid entries are kept (#89). */\nfunction fixSlice(s: unknown): SliceFix<SortingState<unknown>> | undefined {\n const raw = byOf(s)\n const by = entriesOf(s)\n if (Array.isArray(raw) && raw.length === by.length) return undefined\n const bad = Array.isArray(raw) ? raw.findIndex((e) => !isEntry(e)) : -1\n return [\n { by },\n bad < 0 ? describeValue(raw ?? s) : `by[${bad}]: ${describeValue((raw as unknown[])[bad])}`,\n `{ by: [${by.length} valid] }`,\n ]\n}\n\n/** Replaces the sort; an equal one keeps the slice (same reference, no notification, #21). */\nconst setSort = (\n ctx: { getState(): unknown; setState(s: SortingState<unknown>): void },\n by: readonly SortEntry<unknown>[],\n) => {\n // JSON equality (key order included, #21); a restored entry nested deep enough to overflow\n // JSON.stringify counts as a change instead of throwing (#103).\n try {\n if (JSON.stringify(byOf(ctx.getState())) === JSON.stringify(by)) return\n } catch {}\n // A value that is not an array reaches the guard (dev: replaced, DK_INVALID_STATE).\n ctx.setState({ by: Array.isArray(by) ? by.slice() : by })\n}\n\nexport type SortingApi<T> = {\n /**\n * Cycles `id` asc → desc → none. Without `multi` the result is a single-column sort; with `multi`\n * (Shift+click) `id` is appended, cycled in place or removed and the other entries are kept.\n */\n toggleSort(id: Path<T>, options?: { multi?: boolean }): void\n /** Replaces the whole sort. */\n setSorting(by: readonly SortEntry<T>[]): void\n /** Removes every sort entry (input order). */\n clearSorting(): void\n /** `id`'s direction in the current sort, or `false` (for `aria-sort`). */\n getSortDirection(id: Path<T>): SortDirection | false\n}\n\nexport interface SortingTypes extends FeatureTypes {\n state: SortingState<this['T']>\n api: SortingApi<this['T']>\n}\n\n/**\n * How rows are sorted (§6.4): `'auto'` (default) picks per sort from one O(n) scan — exsorted\n * tim / counting / radix for a single column of safe-integer keys (numbers, `Date`s), native\n * `Array.prototype.sort` otherwise. A built-in name forces that algorithm (radix / counting only\n * apply to safe-integer keys); a function sorts the row indices itself.\n */\nexport type SortAlgorithmOption = SortAlgorithm\n\nexport interface SortingOptions {\n /**\n * Locale(s) of the string collator (`Intl.Collator(locale, { numeric: true })`). Default `'en'`,\n * not the runtime's: the server and the browser must sort alike (SSR hydration, #12).\n */\n locale?: string | readonly string[]\n /** The sort algorithm (default `'auto'`); a column's `sortAlgorithm` takes precedence. */\n algorithm?: SortAlgorithmOption\n /** Reports the algorithm chosen for each sort, why, n and the time taken (`DK_SORT_STRATEGY`). */\n debug?: boolean\n /**\n * `'server'`: the server sorts (its state goes to `options.fetcher`, or the app fetches); core\n * skips this step (§7.1). Default `'client'`.\n */\n mode?: DataMode\n}\n\nconst validLocale = (v: unknown) => {\n try {\n Intl.getCanonicalLocales(v as string | string[])\n return true\n } catch {\n return false\n }\n}\n\nconst ALGORITHMS = ['auto', 'tim', 'radix', 'counting', 'native'] as const\n\nconst sortingOptions = {\n locale: {\n type: ['string', 'array'],\n check: validLocale,\n expected: 'a BCP 47 locale tag or a list of them, e.g. \"th\" or [\"th\", \"en\"]',\n },\n algorithm: {\n type: ['string', 'function'],\n oneOf: ALGORITHMS,\n // A literal (not built from ALGORITHMS): a module-level call would keep the schema in production.\n expected:\n \"one of 'auto', 'tim', 'radix', 'counting', 'native', or (indices, compare) => indices\",\n },\n debug: { type: 'boolean' },\n mode: modeOption,\n} as const\n\ntype CustomAlgorithm = Extract<SortAlgorithm, (...args: never[]) => unknown>\n\nconst now = () => (typeof performance === 'undefined' ? Date.now() : performance.now())\n\n/**\n * From this many rows, `auto` sorts a string column by precomputed collation ranks (§9.1): one\n * time-sliced job per column values, then integer-key sorts (a few ms at 100k rows) instead of a\n * collator call per comparison (~100–200 ms at 100k, one long task).\n */\nconst RANKS_MIN = 10_000\n\nconst missing = (v: unknown) => typeRank(v) === RANK.missing\n\n/**\n * Dev check of a column's `sortFn` (§8.3 `DK_SORT_COMPARATOR_INVALID`), sampled: up to 8 present\n * values spread over the input, every pair both ways. A throw gives no verdict (the sort reports\n * it as `DK_CALLBACK_FAILED`).\n */\nfunction checkSortFn(\n fn: SortFn,\n values: ColumnValues,\n indices: Uint32Array,\n): { reason: 'nan' | 'not-number' | 'inconsistent'; received?: string } | undefined {\n const sample: unknown[] = []\n const step = Math.max(1, Math.floor(indices.length / 8))\n for (let i = 0; i < indices.length && sample.length < 8; i += step) {\n const v = values[indices[i] as number]\n if (!missing(v)) sample.push(v)\n }\n try {\n for (let i = 0; i < sample.length; i++) {\n for (let j = i; j < sample.length; j++) {\n const x = fn(sample[i], sample[j])\n const y = fn(sample[j], sample[i])\n for (const r of [x, y]) {\n if (typeof r !== 'number') return { reason: 'not-number', received: describeReturn(r) }\n if (Number.isNaN(r)) return { reason: 'nan' }\n }\n if (Math.sign(x) !== -Math.sign(y)) return { reason: 'inconsistent' }\n }\n }\n } catch {\n return undefined\n }\n return undefined\n}\n\ntype SortFn = (a: unknown, b: unknown) => number\ntype SortBy = (row: unknown) => unknown\n\nconst fnField = (def: object, field: 'sortFn' | 'sortBy') => {\n const f = (def as Record<string, unknown>)[field]\n return typeof f === 'function' ? f : undefined\n}\n\n/** Aborts a native sort when a column's `sortFn` throws (the entry then falls back). */\nclass SortFnFailed {\n constructor(\n readonly entry: number,\n readonly error: unknown,\n ) {}\n}\n\n/**\n * Sorting (§6.4): `toggleSort` (asc → desc → none, `multi`), stable sort of the row indices with\n * the default comparator — missing values (`null`, `undefined`, `NaN`, invalid `Date`) last in both\n * directions, mixed types by type rank, strings with one `Intl.Collator(locale, { numeric: true })`\n * — or a column's `sortFn` / `sortBy`. Never touches the data: a copy of the index array is sorted.\n *\n * `algorithm: 'auto'` (default) picks per sort from one O(n) scan (§6.4): exsorted tim / counting /\n * radix for a single column of safe-integer keys (numbers, `Date`s), native `Array.prototype.sort`\n * (stable) for strings, floats, multi-column and `sortFn`. Every choice gives the same stable order.\n * `sorting({ algorithm })` or a column's `sortAlgorithm` overrides it; `debug: true` reports each\n * choice (`DK_SORT_STRATEGY`).\n */\nexport const sorting = (opts: SortingOptions = {}) => {\n // Dev only (§9.3): production reads a malformed slice as no sort and stays cheap.\n const guard = (process.env.NODE_ENV !== \"production\") ? sliceGuard('sorting', fixSlice) : undefined\n let collator: Intl.Collator | undefined\n /** The collator; `DK_ENV_FALLBACK` when the runtime supports none of the requested locales. */\n const getCollator = (emit: Emit) => {\n if (collator) return collator\n const locale = (opts.locale ?? 'en') as string | string[]\n let supported = true\n try {\n collator = new Intl.Collator(locale, { numeric: true })\n supported = Intl.Collator.supportedLocalesOf(locale).length > 0\n } catch {\n collator = new Intl.Collator(undefined, { numeric: true })\n supported = false\n }\n if (!supported) {\n emit('DK_ENV_FALLBACK', {\n api: 'Intl.Collator',\n feature: 'sorting',\n requested: ([] as string[]).concat(locale).join(', '),\n fallback: `collation|${collator.resolvedOptions().locale}`,\n })\n }\n return collator\n }\n\n /** Values array → the key of its collation-ranks job (`ctx.slice`); released with the values. */\n const rankKeys = new WeakMap<object, object>()\n function ranksFor(ctx: RowModelContext, values: readonly unknown[]) {\n let key = rankKeys.get(values)\n if (!key) {\n key = {}\n rankKeys.set(values, key)\n }\n const c = getCollator(ctx.emit)\n return sliced(ctx, key, () => collationRanks(values, c))\n }\n /** The last sorted output and its input: the stand-in while ranks are computed (§9.1). */\n let shown: { input: Uint32Array; output: Uint32Array } | undefined\n\n // Values that the column cache does not hold, per data reference (released with it).\n const sortByCache = new WeakMap<readonly unknown[], WeakMap<object, unknown[]>>()\n const pathCache = new WeakMap<readonly unknown[], Map<string, unknown[]>>()\n /** exsorted feature detection (§8.5), once per feature instance, on the first sort needing it. */\n let exsorted: boolean | undefined\n\n /** `sortBy` failures (§3.4): numbers only; text is built only when a cell failed. */\n const sortByFailures = new CellFailures()\n\n /**\n * `sortBy` is a cell slot: one `column:batch` per column per data reference, an inline\n * `try/catch` per row. A failed row (or a batch an interceptor skipped) keys as `undefined`,\n * which sorts last.\n */\n function sortByValues(ctx: RowModelContext, col: ResolvedColumn, sortBy: SortBy): unknown[] {\n const data = ctx.data\n let byDef = sortByCache.get(data)\n if (!byDef) {\n byDef = new WeakMap()\n sortByCache.set(data, byDef)\n }\n let out = byDef.get(col.def)\n if (out) return out\n const values: unknown[] = new Array(data.length).fill(undefined)\n const rows = allRows(data)\n sortByFailures.reset()\n ctx.batch(col.id, 'sortBy', rows, () => {\n for (let i = 0; i < rows.length; i++) {\n const r = rows[i] as number\n try {\n values[r] = sortBy(data[r])\n } catch (e) {\n sortByFailures.add(r, e)\n }\n }\n sortByFailures.report(ctx.emit, col.index, col.id, 'sortBy')\n })\n sortByFailures.reset()\n out = values\n byDef.set(col.def, out)\n return out\n }\n\n function pathValues(ctx: RowModelContext, id: string): unknown[] {\n const data = ctx.data\n let byId = pathCache.get(data)\n if (!byId) {\n byId = new Map()\n pathCache.set(data, byId)\n }\n let out = byId.get(id)\n if (out) return out\n const path = compilePath(id)\n out = new Array(data.length)\n for (let r = 0; r < data.length; r++) out[r] = getValue(data[r], path)\n byId.set(id, out)\n return out\n }\n\n return defineFeature<'sorting', SortingTypes>({\n name: 'sorting',\n stage: 'sort',\n mode: opts.mode ?? 'client',\n options: defineOptions(\n // The option validator runs in development only (§9.3): production drops the schema.\n (process.env.NODE_ENV !== \"production\") ? sortingOptions : ({} as typeof sortingOptions),\n opts,\n ),\n ...(guard ? { interceptors: [guard.interceptor] } : undefined),\n initialState: () => ({ by: [] }),\n // After destroy(): still a declared value (`aria-sort` reads it during teardown renders).\n destroyedResult: { getSortDirection: () => false },\n createApi: (ctx) => {\n guard?.install(ctx)\n // Values, not updaters: a library step is never reported as a failing user `updater` (#89).\n return {\n toggleSort: (id, options) => {\n const by = entriesOf(ctx.getState())\n const i = by.findIndex((e) => e.id === id)\n const cur = by[i]\n const next = !cur ? { id, desc: false } : cur.desc ? undefined : { id, desc: true }\n if (!options?.multi) return ctx.setState({ by: next ? [next] : [] })\n if (!cur) return ctx.setState({ by: [...by, next as SortEntry<unknown>] })\n const out = by.slice()\n if (next) out[i] = next as SortEntry<unknown>\n else out.splice(i, 1)\n ctx.setState({ by: out })\n },\n setSorting: (by) => setSort(ctx, by),\n clearSorting: () => setSort(ctx, []),\n getSortDirection: (id) => {\n const e = entriesOf(ctx.getState()).find((x) => x.id === id)\n return e ? (e.desc ? 'desc' : 'asc') : false\n },\n }\n },\n rowModel: (indices, state, ctx) => {\n const by = entriesOf(state)\n if (by.length === 0 || indices.length < 2) {\n shown = undefined\n return indices\n }\n const t0 = opts.debug ? now() : 0\n const cols = resolveColumns(ctx.columns)\n const entries = by.map((e) => {\n const id = String(e.id)\n const col = cols.byId.get(id)\n const sortBy = col && (fnField(col.def, 'sortBy') as SortBy | undefined)\n const values: ColumnValues = sortBy\n ? sortByValues(ctx, col, sortBy)\n : (ctx.getColumnValues(id) ?? pathValues(ctx, id))\n const sortFn =\n col && !sortBy ? (fnField(col.def, 'sortFn') as SortFn | undefined) : undefined\n return { col, desc: e.desc === true, values, sortFn, ranked: false }\n })\n\n // Dev (§8.3): a sampled sortFn check; an invalid one falls back to the default comparator.\n if ((process.env.NODE_ENV !== \"production\")) {\n for (const e of entries) {\n if (!e.sortFn) continue\n const bad = checkSortFn(e.sortFn, e.values, indices)\n if (!bad) continue\n e.sortFn = undefined\n const col = e.col as ResolvedColumn\n ctx.emit('DK_SORT_COMPARATOR_INVALID', { column: col.id, index: col.index, ...bad })\n }\n }\n\n // The requested algorithm: the primary column's `sortAlgorithm`, else the table's.\n const primary = entries[0] as (typeof entries)[number]\n const colAlgorithm =\n primary.col && (primary.col.def as { sortAlgorithm?: unknown }).sortAlgorithm\n const fromColumn = colAlgorithm !== undefined\n let requested = (fromColumn ? colAlgorithm : (opts.algorithm ?? 'auto')) as SortAlgorithm\n const noEffect = (reason: string) =>\n ctx.emit(\n 'DK_OPTION_NO_EFFECT',\n fromColumn\n ? { path: `columns[${primary.col?.index}].sortAlgorithm`, reason, once: false }\n : { path: 'algorithm', feature: 'sorting', reason, once: false },\n )\n if (\n typeof requested !== 'function' &&\n !(ALGORITHMS as readonly unknown[]).includes(requested)\n ) {\n noEffect(`not-algorithm|${proseArg(JSON.stringify(requested))}`)\n requested = 'auto'\n }\n if (requested !== 'native' && exsorted === undefined) {\n // DK_DEP_INCOMPATIBLE is a development check (§8.5); the fallback is not.\n exsorted = (process.env.NODE_ENV !== \"production\")\n ? detectCapability(\n hasExsorted,\n {\n feature: 'sorting',\n dependency: 'exsorted',\n capability: 'timSort / radixSort / countingSort',\n supported: '^1.2.3',\n fallback: 'Array.prototype.sort (native, stable)',\n },\n ctx.emit,\n )\n : hasCapability(hasExsorted)\n }\n\n // auto at large n (§9.1): string columns sort by collation ranks, computed by a sliced job.\n if (requested === 'auto' && indices.length >= RANKS_MIN) {\n let computing = false\n for (const e of entries) {\n if (e.sortFn || e.values instanceof Float64Array) continue\n const ranks = ranksFor(ctx, e.values)\n if (ranks === undefined) computing = true\n else if (ranks) {\n e.values = ranks\n e.ranked = true\n }\n }\n // Meanwhile: the previous order of these rows (or the input order); 'pending'.\n if (computing) return shown && shown.input === indices ? shown.output : indices\n }\n const ranked = entries.some((e) => e.ranked)\n\n const build = (): IndexComparator => {\n const cmps = entries.map((e, k) => {\n const fn = e.sortFn\n if (!fn) return defaultIndexComparator(e.values, e.desc, getCollator(ctx.emit))\n const guarded: SortFn = (a, b) => {\n try {\n return fn(a, b)\n } catch (error) {\n throw new SortFnFailed(k, error)\n }\n }\n return sortFnIndexComparator(e.values, e.desc, guarded)\n })\n if (cmps.length === 1) return cmps[0] as IndexComparator\n return (a, b) => {\n for (let k = 0; k < cmps.length; k++) {\n const c = (cmps[k] as IndexComparator)(a, b)\n if (c !== 0) return c\n }\n return 0\n }\n }\n\n let algorithm: string = 'native'\n let reason = ''\n /** One attempt; a throwing sortFn propagates as SortFnFailed (the loop below retries). */\n const sortOnce = (): Uint32Array => {\n const want = requested\n if (typeof want === 'function') {\n const custom = want as CustomAlgorithm\n let res: unknown\n try {\n res = custom(indices.slice(), build())\n } catch (error) {\n if (error instanceof SortFnFailed) throw error\n reportCustom(true, error)\n return native('custom-threw')\n }\n if (res instanceof Uint32Array && res.length === indices.length) {\n algorithm = 'custom'\n reason = fromColumn ? 'column sortAlgorithm' : 'sorting({ algorithm })'\n return res\n }\n reportCustom(false, res)\n return native('custom-bad')\n }\n if (exsorted === false) return native('exsorted unavailable')\n const by = fromColumn ? 'column sortAlgorithm' : 'sorting({ algorithm })'\n // Integer keys: a single column with the default comparator (§6.4).\n const single = entries.length === 1 && !primary.sortFn\n const keys =\n single && want !== 'native' ? intKeys(primary.values, indices, primary.desc) : undefined\n if (want !== 'auto' && want !== 'native') {\n if (keys) {\n try {\n const out = sortIntKeys(keys, want)\n algorithm = want\n reason = `int-keys|${by}`\n return out\n } catch {\n noEffect(`exsorted-${want === 'counting' ? 'range' : 'failed'}|${want}`)\n }\n } else if (needsIntKeys(want)) {\n noEffect(`needs-int-keys|${want}`)\n } else {\n algorithm = want\n reason = by\n return sortWithComparator(indices, build(), want as 'tim')\n }\n } else if (want === 'native') return native(by)\n if (!keys) {\n return native(\n single ? 'not-safe-int' : entries.length > 1 ? 'multi-column' : 'custom sortFn',\n )\n }\n const choice = chooseAuto(keys)\n algorithm = choice.algorithm\n reason = `auto-${ranked ? 'ranked-' : ''}${choice.reason}`\n return sortIntKeys(keys, choice.algorithm)\n }\n const native = (why: string) => {\n algorithm = 'native'\n reason = ranked ? `ranks|${why}` : why\n return sortWithComparator(indices, build(), 'native')\n }\n /** A custom algorithm threw (`threw`, `value` = the error) or returned a bad `value`. */\n const reportCustom = (threw: boolean, value: unknown) => {\n const slot = fromColumn\n ? `columns[${primary.col?.index}].sortAlgorithm`\n : 'sorting.algorithm'\n const fallback = 'sorted-native'\n if (!threw) {\n // The slot contract check is dev only (§3.4 slotContract); the fallback applies always.\n if ((process.env.NODE_ENV !== \"production\")) {\n ctx.emit('DK_CALLBACK_BAD_RETURN', {\n slot,\n expected: `a Uint32Array of ${indices.length} row indices`,\n received: describeReturn(value),\n count: 1,\n fallback,\n })\n }\n return\n }\n const name = errorName(value)\n ctx.emit(\n 'DK_CALLBACK_FAILED',\n {\n slot,\n count: 1,\n fallback,\n ...(name === undefined ? {} : { errorName: name }),\n },\n { cause: value },\n )\n }\n\n // At most one retry per entry: each failing sortFn falls back to the default comparator.\n for (;;) {\n try {\n const out = sortOnce()\n if (opts.debug) {\n ctx.emit('DK_SORT_STRATEGY', {\n algorithm,\n reason,\n n: indices.length,\n ms: now() - t0,\n by: by.map((e) => `${String(e.id)}:${e.desc ? 'desc' : 'asc'}`),\n ...(primary.col ? { column: { index: primary.col.index, id: primary.col.id } } : {}),\n })\n }\n shown = { input: indices, output: out }\n return out\n } catch (e) {\n if (!(e instanceof SortFnFailed)) throw e\n const entry = entries[e.entry] as (typeof entries)[number]\n entry.sortFn = undefined\n const col = entry.col as ResolvedColumn\n const name = errorName(e.error)\n ctx.emit(\n 'DK_CALLBACK_FAILED',\n {\n slot: `columns[${col.index}].sortFn`,\n column: col.id,\n count: 1,\n fallback: 'sorted-default',\n ...(name === undefined ? {} : { errorName: name }),\n },\n { cause: e.error },\n )\n }\n }\n },\n })\n}\n"],"mappings":"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","names":["reason","by"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import { D as Diagnostic, c as DiagnosticCode, d as DiagnosticDetails, a as EmitOptions, T as Trigger, P as Phase, j as DiagnosticStateSummary, f as RedactLevel, k as RedactionOptions, l as DiagnosticDefinition, I as InvalidRowsMode, e as TableSchema, S as StandardSchemaV1, E as Emit } from './codes-
|
|
2
|
-
export { B as BadResponse, m as BuildInput, n as DK_UNSAFE_REDACTION, o as DatakableConfigError, p as DatakableError, q as DatakableSchemaError, r as DiagnosticCatalog, s as DiagnosticContext, t as DiagnosticLevel, u as DiagnosticMessages, v as DiagnosticMeta, w as DiagnosticText, x as FlaggedInvalidRow, F as FlaggedRow, h as InvalidRow, L as Location, y as REDACTED, z as RedactField, g as RedactFn, A as Redactor, b as Row, R as RowIssue, i as RowKey, C as SCHEMA_INGEST, G as SENSITIVE, H as SchemaIssueColumn, J as SchemaOutcome, K as SlotDefinition, M as SlotReturns, V as ValidRow, N as asyncDiagnostics, O as boundaryDiagnostics, Q as buildDiagnostic, U as columnFiltersDiagnostics, W as comparatorDiagnostics, X as coreDiagnostics, Y as dataCheckDiagnostics, Z as dataMutationDiagnostics, _ as defineDiagnostic, $ as defineSlot, a0 as describeReturn, a1 as describeValue, a2 as envDiagnostics, a3 as featureDiagnostics, a4 as fetchDiagnostics, a5 as formatSlot, a6 as formatWhere, a7 as getDiagnosticDefinition, a8 as getDiagnosticText, a9 as getSlot, aa as hasMessages, ab as hashRowKey, ac as installMessages, ad as isStandardSchema, ae as keepDiagnostics, af as listDiagnosticCodes, ag as matchesSlot, ah as optionDiagnostics, ai as paginationDiagnostics, aj as pipelineDiagnostics, ak as resolveRedaction, al as rowKeyDiagnostics, am as schemaDiagnostics, an as scrubError, ao as scrubSchemaIssue, ap as searchDiagnostics, aq as slotDiagnostics, ar as sortingDiagnostics, as as ssrDiagnostics, at as
|
|
3
|
-
import { S as Stage, A as AnyFeature, I as InterceptorRuntime, a as Interceptor, F as Feature, b as FixedTypes, c as FeatureContext, R as RowModelContext, d as AnyRow, e as FeatureTypes, O as OpName, f as InterceptorContext, g as OpResult, T as TableState, h as TableOptions, i as ServerFetcher, j as TableStateFor, k as Table, l as ApiOf } from './explain-
|
|
4
|
-
export { m as AccessorColumn, n as Apply, B as BuiltinOperations, C as CELL_FALLBACK, o as CellContext, p as CellFailures, q as CellSlot, r as ColumnDef, s as ColumnValues, t as ContextBase, u as ContextPool, v as ControlledState, w as Core, E as ExplainStep, x as FetchOutcome, y as FetchParams, z as FetchResult, D as Fetcher, G as FilterFor, H as HotOpWarning, J as InterceptorRuntimeOptions, K as InvalidCellContext, L as IsAny, M as KeyColumn, N as Listener, P as LooseRow, Q as OpInput, U as OpKind, V as OpOutput, W as OpSpec, X as OperationInfo, Y as Operations, Z as OptionRule, _ as OptionType, $ as OptionsDefinition, a0 as OptionsSchema, a1 as Path, a2 as PathValue, a3 as Primitive, a4 as RenderReq, a5 as RowExplanation, a6 as RowModel, a7 as RowModelStatus, a8 as RowOf, a9 as RowStep, aa as RowStepOutcome, ab as SERVER_SOURCE, ac as SliceUpdater, ad as SortAlgorithm, ae as StateOf, af as TableDiagnosticsOptions, ag as TableExplanation, ah as UPDATE_DEPTH_LIMIT, ai as Updater, aj as createContext, ak as createContextPool, al as createInterceptorRuntime, am as defineInterceptor, an as defineOptions, ao as emitTableDiagnostic, ap as getOperation, aq as isOptionsDefinition, ar as listOperations, as as registerOperation, at as runCells } from './explain-
|
|
1
|
+
import { D as Diagnostic, c as DiagnosticCode, d as DiagnosticDetails, a as EmitOptions, T as Trigger, P as Phase, j as DiagnosticStateSummary, f as RedactLevel, k as RedactionOptions, l as DiagnosticDefinition, I as InvalidRowsMode, e as TableSchema, S as StandardSchemaV1, E as Emit } from './codes-4sYQv_7J.cjs';
|
|
2
|
+
export { B as BadResponse, m as BuildInput, n as DK_UNSAFE_REDACTION, o as DatakableConfigError, p as DatakableError, q as DatakableSchemaError, r as DiagnosticCatalog, s as DiagnosticContext, t as DiagnosticLevel, u as DiagnosticMessages, v as DiagnosticMeta, w as DiagnosticText, x as FlaggedInvalidRow, F as FlaggedRow, h as InvalidRow, L as Location, y as REDACTED, z as RedactField, g as RedactFn, A as Redactor, b as Row, R as RowIssue, i as RowKey, C as SCHEMA_INGEST, G as SENSITIVE, H as SchemaIssueColumn, J as SchemaOutcome, K as SlotDefinition, M as SlotReturns, V as ValidRow, N as asyncDiagnostics, O as boundaryDiagnostics, Q as buildDiagnostic, U as columnFiltersDiagnostics, W as comparatorDiagnostics, X as coreDiagnostics, Y as dataCheckDiagnostics, Z as dataMutationDiagnostics, _ as defineDiagnostic, $ as defineSlot, a0 as describeReturn, a1 as describeValue, a2 as envDiagnostics, a3 as featureDiagnostics, a4 as fetchDiagnostics, a5 as formatSlot, a6 as formatWhere, a7 as getDiagnosticDefinition, a8 as getDiagnosticText, a9 as getSlot, aa as hasMessages, ab as hashRowKey, ac as installMessages, ad as isStandardSchema, ae as keepDiagnostics, af as listDiagnosticCodes, ag as matchesSlot, ah as optionDiagnostics, ai as paginationDiagnostics, aj as pipelineDiagnostics, ak as resolveRedaction, al as rowKeyDiagnostics, am as schemaDiagnostics, an as scrubError, ao as scrubSchemaIssue, ap as searchDiagnostics, aq as slotDiagnostics, ar as sortingDiagnostics, as as ssrDiagnostics, at as stateDiagnostics, au as stepDiagnostics, av as tableDiagnostics, aw as throwConfigError, ax as validityDiagnostics, ay as versioningDiagnostics } from './codes-4sYQv_7J.cjs';
|
|
3
|
+
import { S as Stage, A as AnyFeature, I as InterceptorRuntime, a as Interceptor, F as Feature, b as FixedTypes, c as FeatureContext, R as RowModelContext, d as AnyRow, e as FeatureTypes, O as OpName, f as InterceptorContext, g as OpResult, T as TableState, h as TableOptions, i as ServerFetcher, j as TableStateFor, k as Table, l as ApiOf } from './explain-DmwN_RG9.cjs';
|
|
4
|
+
export { m as AccessorColumn, n as Apply, B as BuiltinOperations, C as CELL_FALLBACK, o as CellContext, p as CellFailures, q as CellSlot, r as ColumnDef, s as ColumnValues, t as ContextBase, u as ContextPool, v as ControlledState, w as Core, E as ExplainStep, x as FetchOutcome, y as FetchParams, z as FetchResult, D as Fetcher, G as FilterFor, H as HotOpWarning, J as InterceptorRuntimeOptions, K as InvalidCellContext, L as IsAny, M as KeyColumn, N as Listener, P as LooseRow, Q as OpInput, U as OpKind, V as OpOutput, W as OpSpec, X as OperationInfo, Y as Operations, Z as OptionRule, _ as OptionType, $ as OptionsDefinition, a0 as OptionsSchema, a1 as Path, a2 as PathValue, a3 as Primitive, a4 as RenderReq, a5 as RowExplanation, a6 as RowModel, a7 as RowModelStatus, a8 as RowOf, a9 as RowStep, aa as RowStepOutcome, ab as SERVER_SOURCE, ac as SliceUpdater, ad as SortAlgorithm, ae as StateOf, af as TableDiagnosticsOptions, ag as TableExplanation, ah as UPDATE_DEPTH_LIMIT, ai as Updater, aj as createContext, ak as createContextPool, al as createInterceptorRuntime, am as defineInterceptor, an as defineOptions, ao as emitTableDiagnostic, ap as getOperation, aq as isOptionsDefinition, ar as listOperations, as as registerOperation, at as runCells } from './explain-DmwN_RG9.cjs';
|
|
5
5
|
import { ColumnFiltersTypes } from './column-filters.cjs';
|
|
6
6
|
export { ColumnFilter, ColumnFiltersApi, ColumnFiltersOptions, ColumnFiltersState, ContainsFilter, CustomFilter, EqualsFilter, InFilter, RangeFilter, RangeValue, columnFilters } from './column-filters.cjs';
|
|
7
7
|
import { PaginationState, PaginationApi } from './pagination.cjs';
|
|
8
8
|
export { PaginationOptions, pagination } from './pagination.cjs';
|
|
9
9
|
import { SearchApi } from './search.cjs';
|
|
10
10
|
export { SearchOptions, SearchTyping, SearchWait, search } from './search.cjs';
|
|
11
|
-
import { S as SearchState } from './search-async-entry-
|
|
12
|
-
export { A as AsyncSearchFn, a as SEARCH_ENGINE, b as SearchFn, c as SearchFnContext, d as SearchOutcome, e as SearchResult, f as SearchStatus, w as withSearchFn } from './search-async-entry-
|
|
11
|
+
import { S as SearchState } from './search-async-entry-BiemO3JT.cjs';
|
|
12
|
+
export { A as AsyncSearchFn, a as SEARCH_ENGINE, b as SearchFn, c as SearchFnContext, d as SearchOutcome, e as SearchResult, f as SearchStatus, w as withSearchFn } from './search-async-entry-BiemO3JT.cjs';
|
|
13
13
|
import { SortingTypes } from './sorting.cjs';
|
|
14
14
|
export { SortAlgorithmOption, SortDirection, SortEntry, SortingApi, SortingOptions, SortingState, compareValues, sorting, typeRank } from './sorting.cjs';
|
|
15
15
|
import { ValidityState, ValidityApi } from './validity.cjs';
|
|
@@ -45,7 +45,10 @@ declare function compilePath(path: string): CompiledPath;
|
|
|
45
45
|
*/
|
|
46
46
|
declare function getValue(row: unknown, path: string | CompiledPath, onError?: (error: unknown) => void): unknown;
|
|
47
47
|
|
|
48
|
-
/**
|
|
48
|
+
/**
|
|
49
|
+
* The §8.1 console text: header + aligned body, each line {@link printable}. Also usable by
|
|
50
|
+
* explain() and tests.
|
|
51
|
+
*/
|
|
49
52
|
declare function formatDiagnostic(d: Diagnostic): {
|
|
50
53
|
header: string;
|
|
51
54
|
body: string;
|
|
@@ -279,20 +282,28 @@ type DefaultFeatures = ReturnType<typeof createDefaultFeatures>;
|
|
|
279
282
|
*/
|
|
280
283
|
declare const defaultFeatures: DefaultFeatures;
|
|
281
284
|
|
|
285
|
+
/** `undefined` exactly (not `any`, `never` or a union with it). */
|
|
286
|
+
type IsUndefined<X> = (<G>() => G extends X ? 1 : 2) extends <G>() => G extends undefined ? 1 : 2 ? true : false;
|
|
287
|
+
/**
|
|
288
|
+
* `true` when `Sch` (the inferred `schema` option) is a schema. Its default, `undefined` (no
|
|
289
|
+
* schema), is excluded explicitly: without `strictNullChecks` `undefined` is assignable to every
|
|
290
|
+
* type, `TableSchema` included, which typed `data` as `unknown[]` and `T` as `unknown` (#93).
|
|
291
|
+
*/
|
|
292
|
+
type HasSchema<Sch> = [Sch] extends [TableSchema] ? IsUndefined<Sch> extends true ? false : true : false;
|
|
282
293
|
/** The row type: the schema output with a `schema` (§5.1), else `T`. */
|
|
283
|
-
type SchemaRow<T, Sch> = [Sch] extends [TableSchema] ? StandardSchemaV1.InferOutput<Sch> : T;
|
|
294
|
+
type SchemaRow<T, Sch> = [Sch] extends [TableSchema] ? IsUndefined<Sch> extends true ? T : StandardSchemaV1.InferOutput<Sch> : T;
|
|
284
295
|
/**
|
|
285
296
|
* `createTable` options: with a `schema`, the row type is its output and `data` is the raw input
|
|
286
297
|
* (`unknown[]`, e.g. parsed JSON), validated per row.
|
|
287
298
|
*/
|
|
288
299
|
type CreateTableOptions<T, S extends TableState, Sch, M extends InvalidRowsMode> = Omit<TableOptions<SchemaRow<T, Sch>, S>, 'data' | 'schema' | 'invalidRows' | 'fetcher' | 'initialData'> & {
|
|
289
|
-
data?: readonly (
|
|
300
|
+
data?: readonly (HasSchema<Sch> extends true ? unknown : T)[];
|
|
290
301
|
/** With a schema, the raw rows (validated like `data`). */
|
|
291
|
-
initialData?: readonly (
|
|
302
|
+
initialData?: readonly (HasSchema<Sch> extends true ? unknown : T)[];
|
|
292
303
|
/** With a schema, the fetcher returns raw rows (validated like `data`). */
|
|
293
|
-
fetcher?: ServerFetcher<
|
|
294
|
-
schema?:
|
|
295
|
-
invalidRows?:
|
|
304
|
+
fetcher?: ServerFetcher<HasSchema<Sch> extends true ? unknown : T>;
|
|
305
|
+
schema?: HasSchema<Sch> extends true ? Sch : TableSchema<unknown, T>;
|
|
306
|
+
invalidRows?: HasSchema<Sch> extends true ? M : InvalidRowsMode;
|
|
296
307
|
};
|
|
297
308
|
/**
|
|
298
309
|
* Creates the table store (§3.2): immutable state snapshots, controlled slices, isolated listeners,
|
|
@@ -305,9 +316,7 @@ type CreateTableOptions<T, S extends TableState, Sch, M extends InvalidRowsMode>
|
|
|
305
316
|
*/
|
|
306
317
|
declare function createTable<T, S extends TableState = never, const Fs extends readonly AnyFeature[] = [], const Sch extends TableSchema | undefined = undefined, const M extends InvalidRowsMode = 'drop'>(options: CreateTableOptions<T, TableStateFor<S, Fs, SchemaRow<T, Sch>>, Sch, M> & {
|
|
307
318
|
features?: Fs;
|
|
308
|
-
}): Table<SchemaRow<T, Sch>, TableStateFor<S, Fs, SchemaRow<T, Sch>>, M,
|
|
309
|
-
Sch
|
|
310
|
-
] extends [TableSchema] ? unknown : T> & ApiOf<Fs, SchemaRow<T, Sch>>;
|
|
319
|
+
}): Table<SchemaRow<T, Sch>, TableStateFor<S, Fs, SchemaRow<T, Sch>>, M, HasSchema<Sch> extends true ? unknown : T> & ApiOf<Fs, SchemaRow<T, Sch>>;
|
|
311
320
|
|
|
312
321
|
/**
|
|
313
322
|
* SSR seam for bindings (§7.2): runs `create` (a `createTable` call) so that the table it creates
|
|
@@ -398,4 +407,4 @@ interface VersionRegistry {
|
|
|
398
407
|
*/
|
|
399
408
|
declare function registerPackage(name: string, version: string): void;
|
|
400
409
|
|
|
401
|
-
export { AnyFeature, ApiOf, CallbackError, ColumnFiltersTypes, type ColumnKey, type CompiledPath, type CreateTableOptions, type DefaultFeatures, type DependencyCapability, type Deprecation, type DerivedColumn, Diagnostic, DiagnosticCode, DiagnosticDefinition, DiagnosticDetails, DiagnosticStateSummary, type Diagnostics, type DiagnosticsOptions, Emit, EmitOptions, type ErrorClass, FALLBACK, type Fallback, Feature, FeatureContext, FeatureTypes, type FixedFeatureDefinition, FixedTypes, INGEST_SAMPLE, Interceptor, InterceptorContext, InterceptorRuntime, InvalidRowsMode, type LiveDiagnosticContext, OpName, OpResult, PaginationApi, PaginationState, Phase, REGISTRY_KEY, RedactLevel, RedactionOptions, type RowData, RowModelContext, STAGES, type SchemaRow, SearchApi, SearchState, ServerFetcher, SortingTypes, Stage, StandardSchemaV1, Table, TableOptions, TableSchema, TableState, TableStateFor, Trigger, VERSION, ValidityApi, ValidityState, type VersionRegistry, callUser, classifyError, compilePath, createDefaultFeatures, createDeferred, createDiagnostics, createTable, defaultFeatures, defaultFormat, defineDeprecation, defineFeature, deriveColumns, detectCapability, errorBoundary, formatDiagnostic, getFallback, getValue, orderFeatures, perfDiagnostics, registerFallback, registerPackage, startTable, toSafeJson, tracer, warnDeprecated };
|
|
410
|
+
export { AnyFeature, ApiOf, CallbackError, ColumnFiltersTypes, type ColumnKey, type CompiledPath, type CreateTableOptions, type DefaultFeatures, type DependencyCapability, type Deprecation, type DerivedColumn, Diagnostic, DiagnosticCode, DiagnosticDefinition, DiagnosticDetails, DiagnosticStateSummary, type Diagnostics, type DiagnosticsOptions, Emit, EmitOptions, type ErrorClass, FALLBACK, type Fallback, Feature, FeatureContext, FeatureTypes, type FixedFeatureDefinition, FixedTypes, type HasSchema, INGEST_SAMPLE, Interceptor, InterceptorContext, InterceptorRuntime, InvalidRowsMode, type LiveDiagnosticContext, OpName, OpResult, PaginationApi, PaginationState, Phase, REGISTRY_KEY, RedactLevel, RedactionOptions, type RowData, RowModelContext, STAGES, type SchemaRow, SearchApi, SearchState, ServerFetcher, SortingTypes, Stage, StandardSchemaV1, Table, TableOptions, TableSchema, TableState, TableStateFor, Trigger, VERSION, ValidityApi, ValidityState, type VersionRegistry, callUser, classifyError, compilePath, createDefaultFeatures, createDeferred, createDiagnostics, createTable, defaultFeatures, defaultFormat, defineDeprecation, defineFeature, deriveColumns, detectCapability, errorBoundary, formatDiagnostic, getFallback, getValue, orderFeatures, perfDiagnostics, registerFallback, registerPackage, startTable, toSafeJson, tracer, warnDeprecated };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import { D as Diagnostic, c as DiagnosticCode, d as DiagnosticDetails, a as EmitOptions, T as Trigger, P as Phase, j as DiagnosticStateSummary, f as RedactLevel, k as RedactionOptions, l as DiagnosticDefinition, I as InvalidRowsMode, e as TableSchema, S as StandardSchemaV1, E as Emit } from './codes-
|
|
2
|
-
export { B as BadResponse, m as BuildInput, n as DK_UNSAFE_REDACTION, o as DatakableConfigError, p as DatakableError, q as DatakableSchemaError, r as DiagnosticCatalog, s as DiagnosticContext, t as DiagnosticLevel, u as DiagnosticMessages, v as DiagnosticMeta, w as DiagnosticText, x as FlaggedInvalidRow, F as FlaggedRow, h as InvalidRow, L as Location, y as REDACTED, z as RedactField, g as RedactFn, A as Redactor, b as Row, R as RowIssue, i as RowKey, C as SCHEMA_INGEST, G as SENSITIVE, H as SchemaIssueColumn, J as SchemaOutcome, K as SlotDefinition, M as SlotReturns, V as ValidRow, N as asyncDiagnostics, O as boundaryDiagnostics, Q as buildDiagnostic, U as columnFiltersDiagnostics, W as comparatorDiagnostics, X as coreDiagnostics, Y as dataCheckDiagnostics, Z as dataMutationDiagnostics, _ as defineDiagnostic, $ as defineSlot, a0 as describeReturn, a1 as describeValue, a2 as envDiagnostics, a3 as featureDiagnostics, a4 as fetchDiagnostics, a5 as formatSlot, a6 as formatWhere, a7 as getDiagnosticDefinition, a8 as getDiagnosticText, a9 as getSlot, aa as hasMessages, ab as hashRowKey, ac as installMessages, ad as isStandardSchema, ae as keepDiagnostics, af as listDiagnosticCodes, ag as matchesSlot, ah as optionDiagnostics, ai as paginationDiagnostics, aj as pipelineDiagnostics, ak as resolveRedaction, al as rowKeyDiagnostics, am as schemaDiagnostics, an as scrubError, ao as scrubSchemaIssue, ap as searchDiagnostics, aq as slotDiagnostics, ar as sortingDiagnostics, as as ssrDiagnostics, at as
|
|
3
|
-
import { S as Stage, A as AnyFeature, I as InterceptorRuntime, a as Interceptor, F as Feature, b as FixedTypes, c as FeatureContext, R as RowModelContext, d as AnyRow, e as FeatureTypes, O as OpName, f as InterceptorContext, g as OpResult, T as TableState, h as TableOptions, i as ServerFetcher, j as TableStateFor, k as Table, l as ApiOf } from './explain-
|
|
4
|
-
export { m as AccessorColumn, n as Apply, B as BuiltinOperations, C as CELL_FALLBACK, o as CellContext, p as CellFailures, q as CellSlot, r as ColumnDef, s as ColumnValues, t as ContextBase, u as ContextPool, v as ControlledState, w as Core, E as ExplainStep, x as FetchOutcome, y as FetchParams, z as FetchResult, D as Fetcher, G as FilterFor, H as HotOpWarning, J as InterceptorRuntimeOptions, K as InvalidCellContext, L as IsAny, M as KeyColumn, N as Listener, P as LooseRow, Q as OpInput, U as OpKind, V as OpOutput, W as OpSpec, X as OperationInfo, Y as Operations, Z as OptionRule, _ as OptionType, $ as OptionsDefinition, a0 as OptionsSchema, a1 as Path, a2 as PathValue, a3 as Primitive, a4 as RenderReq, a5 as RowExplanation, a6 as RowModel, a7 as RowModelStatus, a8 as RowOf, a9 as RowStep, aa as RowStepOutcome, ab as SERVER_SOURCE, ac as SliceUpdater, ad as SortAlgorithm, ae as StateOf, af as TableDiagnosticsOptions, ag as TableExplanation, ah as UPDATE_DEPTH_LIMIT, ai as Updater, aj as createContext, ak as createContextPool, al as createInterceptorRuntime, am as defineInterceptor, an as defineOptions, ao as emitTableDiagnostic, ap as getOperation, aq as isOptionsDefinition, ar as listOperations, as as registerOperation, at as runCells } from './explain-
|
|
1
|
+
import { D as Diagnostic, c as DiagnosticCode, d as DiagnosticDetails, a as EmitOptions, T as Trigger, P as Phase, j as DiagnosticStateSummary, f as RedactLevel, k as RedactionOptions, l as DiagnosticDefinition, I as InvalidRowsMode, e as TableSchema, S as StandardSchemaV1, E as Emit } from './codes-4sYQv_7J.js';
|
|
2
|
+
export { B as BadResponse, m as BuildInput, n as DK_UNSAFE_REDACTION, o as DatakableConfigError, p as DatakableError, q as DatakableSchemaError, r as DiagnosticCatalog, s as DiagnosticContext, t as DiagnosticLevel, u as DiagnosticMessages, v as DiagnosticMeta, w as DiagnosticText, x as FlaggedInvalidRow, F as FlaggedRow, h as InvalidRow, L as Location, y as REDACTED, z as RedactField, g as RedactFn, A as Redactor, b as Row, R as RowIssue, i as RowKey, C as SCHEMA_INGEST, G as SENSITIVE, H as SchemaIssueColumn, J as SchemaOutcome, K as SlotDefinition, M as SlotReturns, V as ValidRow, N as asyncDiagnostics, O as boundaryDiagnostics, Q as buildDiagnostic, U as columnFiltersDiagnostics, W as comparatorDiagnostics, X as coreDiagnostics, Y as dataCheckDiagnostics, Z as dataMutationDiagnostics, _ as defineDiagnostic, $ as defineSlot, a0 as describeReturn, a1 as describeValue, a2 as envDiagnostics, a3 as featureDiagnostics, a4 as fetchDiagnostics, a5 as formatSlot, a6 as formatWhere, a7 as getDiagnosticDefinition, a8 as getDiagnosticText, a9 as getSlot, aa as hasMessages, ab as hashRowKey, ac as installMessages, ad as isStandardSchema, ae as keepDiagnostics, af as listDiagnosticCodes, ag as matchesSlot, ah as optionDiagnostics, ai as paginationDiagnostics, aj as pipelineDiagnostics, ak as resolveRedaction, al as rowKeyDiagnostics, am as schemaDiagnostics, an as scrubError, ao as scrubSchemaIssue, ap as searchDiagnostics, aq as slotDiagnostics, ar as sortingDiagnostics, as as ssrDiagnostics, at as stateDiagnostics, au as stepDiagnostics, av as tableDiagnostics, aw as throwConfigError, ax as validityDiagnostics, ay as versioningDiagnostics } from './codes-4sYQv_7J.js';
|
|
3
|
+
import { S as Stage, A as AnyFeature, I as InterceptorRuntime, a as Interceptor, F as Feature, b as FixedTypes, c as FeatureContext, R as RowModelContext, d as AnyRow, e as FeatureTypes, O as OpName, f as InterceptorContext, g as OpResult, T as TableState, h as TableOptions, i as ServerFetcher, j as TableStateFor, k as Table, l as ApiOf } from './explain-Dr3SmMNY.js';
|
|
4
|
+
export { m as AccessorColumn, n as Apply, B as BuiltinOperations, C as CELL_FALLBACK, o as CellContext, p as CellFailures, q as CellSlot, r as ColumnDef, s as ColumnValues, t as ContextBase, u as ContextPool, v as ControlledState, w as Core, E as ExplainStep, x as FetchOutcome, y as FetchParams, z as FetchResult, D as Fetcher, G as FilterFor, H as HotOpWarning, J as InterceptorRuntimeOptions, K as InvalidCellContext, L as IsAny, M as KeyColumn, N as Listener, P as LooseRow, Q as OpInput, U as OpKind, V as OpOutput, W as OpSpec, X as OperationInfo, Y as Operations, Z as OptionRule, _ as OptionType, $ as OptionsDefinition, a0 as OptionsSchema, a1 as Path, a2 as PathValue, a3 as Primitive, a4 as RenderReq, a5 as RowExplanation, a6 as RowModel, a7 as RowModelStatus, a8 as RowOf, a9 as RowStep, aa as RowStepOutcome, ab as SERVER_SOURCE, ac as SliceUpdater, ad as SortAlgorithm, ae as StateOf, af as TableDiagnosticsOptions, ag as TableExplanation, ah as UPDATE_DEPTH_LIMIT, ai as Updater, aj as createContext, ak as createContextPool, al as createInterceptorRuntime, am as defineInterceptor, an as defineOptions, ao as emitTableDiagnostic, ap as getOperation, aq as isOptionsDefinition, ar as listOperations, as as registerOperation, at as runCells } from './explain-Dr3SmMNY.js';
|
|
5
5
|
import { ColumnFiltersTypes } from './column-filters.js';
|
|
6
6
|
export { ColumnFilter, ColumnFiltersApi, ColumnFiltersOptions, ColumnFiltersState, ContainsFilter, CustomFilter, EqualsFilter, InFilter, RangeFilter, RangeValue, columnFilters } from './column-filters.js';
|
|
7
7
|
import { PaginationState, PaginationApi } from './pagination.js';
|
|
8
8
|
export { PaginationOptions, pagination } from './pagination.js';
|
|
9
9
|
import { SearchApi } from './search.js';
|
|
10
10
|
export { SearchOptions, SearchTyping, SearchWait, search } from './search.js';
|
|
11
|
-
import { S as SearchState } from './search-async-entry-
|
|
12
|
-
export { A as AsyncSearchFn, a as SEARCH_ENGINE, b as SearchFn, c as SearchFnContext, d as SearchOutcome, e as SearchResult, f as SearchStatus, w as withSearchFn } from './search-async-entry-
|
|
11
|
+
import { S as SearchState } from './search-async-entry-GRj0E06n.js';
|
|
12
|
+
export { A as AsyncSearchFn, a as SEARCH_ENGINE, b as SearchFn, c as SearchFnContext, d as SearchOutcome, e as SearchResult, f as SearchStatus, w as withSearchFn } from './search-async-entry-GRj0E06n.js';
|
|
13
13
|
import { SortingTypes } from './sorting.js';
|
|
14
14
|
export { SortAlgorithmOption, SortDirection, SortEntry, SortingApi, SortingOptions, SortingState, compareValues, sorting, typeRank } from './sorting.js';
|
|
15
15
|
import { ValidityState, ValidityApi } from './validity.js';
|
|
@@ -45,7 +45,10 @@ declare function compilePath(path: string): CompiledPath;
|
|
|
45
45
|
*/
|
|
46
46
|
declare function getValue(row: unknown, path: string | CompiledPath, onError?: (error: unknown) => void): unknown;
|
|
47
47
|
|
|
48
|
-
/**
|
|
48
|
+
/**
|
|
49
|
+
* The §8.1 console text: header + aligned body, each line {@link printable}. Also usable by
|
|
50
|
+
* explain() and tests.
|
|
51
|
+
*/
|
|
49
52
|
declare function formatDiagnostic(d: Diagnostic): {
|
|
50
53
|
header: string;
|
|
51
54
|
body: string;
|
|
@@ -279,20 +282,28 @@ type DefaultFeatures = ReturnType<typeof createDefaultFeatures>;
|
|
|
279
282
|
*/
|
|
280
283
|
declare const defaultFeatures: DefaultFeatures;
|
|
281
284
|
|
|
285
|
+
/** `undefined` exactly (not `any`, `never` or a union with it). */
|
|
286
|
+
type IsUndefined<X> = (<G>() => G extends X ? 1 : 2) extends <G>() => G extends undefined ? 1 : 2 ? true : false;
|
|
287
|
+
/**
|
|
288
|
+
* `true` when `Sch` (the inferred `schema` option) is a schema. Its default, `undefined` (no
|
|
289
|
+
* schema), is excluded explicitly: without `strictNullChecks` `undefined` is assignable to every
|
|
290
|
+
* type, `TableSchema` included, which typed `data` as `unknown[]` and `T` as `unknown` (#93).
|
|
291
|
+
*/
|
|
292
|
+
type HasSchema<Sch> = [Sch] extends [TableSchema] ? IsUndefined<Sch> extends true ? false : true : false;
|
|
282
293
|
/** The row type: the schema output with a `schema` (§5.1), else `T`. */
|
|
283
|
-
type SchemaRow<T, Sch> = [Sch] extends [TableSchema] ? StandardSchemaV1.InferOutput<Sch> : T;
|
|
294
|
+
type SchemaRow<T, Sch> = [Sch] extends [TableSchema] ? IsUndefined<Sch> extends true ? T : StandardSchemaV1.InferOutput<Sch> : T;
|
|
284
295
|
/**
|
|
285
296
|
* `createTable` options: with a `schema`, the row type is its output and `data` is the raw input
|
|
286
297
|
* (`unknown[]`, e.g. parsed JSON), validated per row.
|
|
287
298
|
*/
|
|
288
299
|
type CreateTableOptions<T, S extends TableState, Sch, M extends InvalidRowsMode> = Omit<TableOptions<SchemaRow<T, Sch>, S>, 'data' | 'schema' | 'invalidRows' | 'fetcher' | 'initialData'> & {
|
|
289
|
-
data?: readonly (
|
|
300
|
+
data?: readonly (HasSchema<Sch> extends true ? unknown : T)[];
|
|
290
301
|
/** With a schema, the raw rows (validated like `data`). */
|
|
291
|
-
initialData?: readonly (
|
|
302
|
+
initialData?: readonly (HasSchema<Sch> extends true ? unknown : T)[];
|
|
292
303
|
/** With a schema, the fetcher returns raw rows (validated like `data`). */
|
|
293
|
-
fetcher?: ServerFetcher<
|
|
294
|
-
schema?:
|
|
295
|
-
invalidRows?:
|
|
304
|
+
fetcher?: ServerFetcher<HasSchema<Sch> extends true ? unknown : T>;
|
|
305
|
+
schema?: HasSchema<Sch> extends true ? Sch : TableSchema<unknown, T>;
|
|
306
|
+
invalidRows?: HasSchema<Sch> extends true ? M : InvalidRowsMode;
|
|
296
307
|
};
|
|
297
308
|
/**
|
|
298
309
|
* Creates the table store (§3.2): immutable state snapshots, controlled slices, isolated listeners,
|
|
@@ -305,9 +316,7 @@ type CreateTableOptions<T, S extends TableState, Sch, M extends InvalidRowsMode>
|
|
|
305
316
|
*/
|
|
306
317
|
declare function createTable<T, S extends TableState = never, const Fs extends readonly AnyFeature[] = [], const Sch extends TableSchema | undefined = undefined, const M extends InvalidRowsMode = 'drop'>(options: CreateTableOptions<T, TableStateFor<S, Fs, SchemaRow<T, Sch>>, Sch, M> & {
|
|
307
318
|
features?: Fs;
|
|
308
|
-
}): Table<SchemaRow<T, Sch>, TableStateFor<S, Fs, SchemaRow<T, Sch>>, M,
|
|
309
|
-
Sch
|
|
310
|
-
] extends [TableSchema] ? unknown : T> & ApiOf<Fs, SchemaRow<T, Sch>>;
|
|
319
|
+
}): Table<SchemaRow<T, Sch>, TableStateFor<S, Fs, SchemaRow<T, Sch>>, M, HasSchema<Sch> extends true ? unknown : T> & ApiOf<Fs, SchemaRow<T, Sch>>;
|
|
311
320
|
|
|
312
321
|
/**
|
|
313
322
|
* SSR seam for bindings (§7.2): runs `create` (a `createTable` call) so that the table it creates
|
|
@@ -398,4 +407,4 @@ interface VersionRegistry {
|
|
|
398
407
|
*/
|
|
399
408
|
declare function registerPackage(name: string, version: string): void;
|
|
400
409
|
|
|
401
|
-
export { AnyFeature, ApiOf, CallbackError, ColumnFiltersTypes, type ColumnKey, type CompiledPath, type CreateTableOptions, type DefaultFeatures, type DependencyCapability, type Deprecation, type DerivedColumn, Diagnostic, DiagnosticCode, DiagnosticDefinition, DiagnosticDetails, DiagnosticStateSummary, type Diagnostics, type DiagnosticsOptions, Emit, EmitOptions, type ErrorClass, FALLBACK, type Fallback, Feature, FeatureContext, FeatureTypes, type FixedFeatureDefinition, FixedTypes, INGEST_SAMPLE, Interceptor, InterceptorContext, InterceptorRuntime, InvalidRowsMode, type LiveDiagnosticContext, OpName, OpResult, PaginationApi, PaginationState, Phase, REGISTRY_KEY, RedactLevel, RedactionOptions, type RowData, RowModelContext, STAGES, type SchemaRow, SearchApi, SearchState, ServerFetcher, SortingTypes, Stage, StandardSchemaV1, Table, TableOptions, TableSchema, TableState, TableStateFor, Trigger, VERSION, ValidityApi, ValidityState, type VersionRegistry, callUser, classifyError, compilePath, createDefaultFeatures, createDeferred, createDiagnostics, createTable, defaultFeatures, defaultFormat, defineDeprecation, defineFeature, deriveColumns, detectCapability, errorBoundary, formatDiagnostic, getFallback, getValue, orderFeatures, perfDiagnostics, registerFallback, registerPackage, startTable, toSafeJson, tracer, warnDeprecated };
|
|
410
|
+
export { AnyFeature, ApiOf, CallbackError, ColumnFiltersTypes, type ColumnKey, type CompiledPath, type CreateTableOptions, type DefaultFeatures, type DependencyCapability, type Deprecation, type DerivedColumn, Diagnostic, DiagnosticCode, DiagnosticDefinition, DiagnosticDetails, DiagnosticStateSummary, type Diagnostics, type DiagnosticsOptions, Emit, EmitOptions, type ErrorClass, FALLBACK, type Fallback, Feature, FeatureContext, FeatureTypes, type FixedFeatureDefinition, FixedTypes, type HasSchema, INGEST_SAMPLE, Interceptor, InterceptorContext, InterceptorRuntime, InvalidRowsMode, type LiveDiagnosticContext, OpName, OpResult, PaginationApi, PaginationState, Phase, REGISTRY_KEY, RedactLevel, RedactionOptions, type RowData, RowModelContext, STAGES, type SchemaRow, SearchApi, SearchState, ServerFetcher, SortingTypes, Stage, StandardSchemaV1, Table, TableOptions, TableSchema, TableState, TableStateFor, Trigger, VERSION, ValidityApi, ValidityState, type VersionRegistry, callUser, classifyError, compilePath, createDefaultFeatures, createDeferred, createDiagnostics, createTable, defaultFeatures, defaultFormat, defineDeprecation, defineFeature, deriveColumns, detectCapability, errorBoundary, formatDiagnostic, getFallback, getValue, orderFeatures, perfDiagnostics, registerFallback, registerPackage, startTable, toSafeJson, tracer, warnDeprecated };
|
|
@@ -25,6 +25,7 @@ __export(runtime_exports, {
|
|
|
25
25
|
module.exports = __toCommonJS(runtime_exports);
|
|
26
26
|
var import_build = require("../diagnostics/build.cjs");
|
|
27
27
|
var import_process_guard = require("../diagnostics/process-guard.cjs");
|
|
28
|
+
var import_prose = require("../diagnostics/prose.cjs");
|
|
28
29
|
var import_operations = require("./operations.cjs");
|
|
29
30
|
var NOT_CALLED = 0;
|
|
30
31
|
var CALLED = 1;
|
|
@@ -122,7 +123,7 @@ function createInterceptorRuntime(options = {}) {
|
|
|
122
123
|
function compile(op) {
|
|
123
124
|
const info = (0, import_operations.getOperation)(op);
|
|
124
125
|
if (!info) {
|
|
125
|
-
throw (0, import_build.internalError)(op, `unknown-op|${op}`);
|
|
126
|
+
throw (0, import_build.internalError)(op, `unknown-op|${(0, import_prose.proseArg)(op)}`);
|
|
126
127
|
}
|
|
127
128
|
const mine = list.filter((i) => attaches(i, op));
|
|
128
129
|
if (boundary && attaches(boundary, op)) mine.unshift(boundary);
|
|
@@ -152,7 +153,7 @@ function createInterceptorRuntime(options = {}) {
|
|
|
152
153
|
setInterceptors,
|
|
153
154
|
installBoundary(b) {
|
|
154
155
|
if (boundary) {
|
|
155
|
-
throw (0, import_build.internalError)("*", `boundary-twice|${boundary.name}|${b.name}`);
|
|
156
|
+
throw (0, import_build.internalError)("*", `boundary-twice|${(0, import_prose.proseArg)(boundary.name)}|${(0, import_prose.proseArg)(b.name)}`);
|
|
156
157
|
}
|
|
157
158
|
boundary = b;
|
|
158
159
|
compileAll();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/intercept/runtime.ts"],"sourcesContent":["import { DatakableError, internalError } from '../diagnostics/build'\nimport '../diagnostics/process-guard'\nimport type { Emit } from '../diagnostics/types'\nimport type { InterceptorContext } from './context'\nimport type { Interceptor } from './define'\nimport { getOperation, listOperations, type OpName, type OpResult } from './operations'\n\nexport type Core<O extends OpName> = (ctx: InterceptorContext<O>) => OpResult<O>\n\nexport interface HotOpWarning {\n interceptor: Interceptor<OpName>\n op: string\n message: string\n}\n\nexport interface InterceptorRuntimeOptions {\n interceptors?: readonly Interceptor<OpName>[]\n /**\n * The table's diagnostic emitter. When given, the default hooks below report through it:\n * `DK_INTERCEPTOR_FAILED` and (dev only) `DK_HOT_INTERCEPTOR`. Without it they use the console.\n */\n emit?: Emit\n /**\n * An interceptor threw (or its promise rejected); it was skipped. Overrides the default report\n * (`DK_INTERCEPTOR_FAILED` via `emit`, else console.error).\n */\n onInterceptorError?: (\n error: unknown,\n interceptor: Interceptor<OpName>,\n ctx: InterceptorContext,\n ) => void\n /**\n * An interceptor is attached to a hot op without `hot: true` (checked when the op's chain is\n * compiled, once per interceptor + op). Overrides the default (`DK_HOT_INTERCEPTOR` via `emit`).\n */\n onHotWarning?: (warning: HotOpWarning) => void\n /** Called each time a chain is compiled (tracing / tests). `length` counts the boundary too. */\n onCompile?: (op: string, length: number) => void\n}\n\nexport interface InterceptorRuntime {\n /** Runs `core` for `op` through the compiled chain. */\n run<O extends OpName>(op: O, ctx: InterceptorContext<O>, core: NoInfer<Core<O>>): OpResult<O>\n /** Replaces the user / feature interceptors and recompiles. The boundary slot is kept. */\n setInterceptors(interceptors: readonly Interceptor<OpName>[]): void\n /** Installs the outermost, non-removable interceptor (errorBoundary, T06). Once only. */\n installBoundary(boundary: Interceptor<OpName>): void\n}\n\ntype AnyCtx = InterceptorContext\ntype AnyCore = (ctx: AnyCtx) => unknown\ntype Chain = (ctx: AnyCtx, core: AnyCore) => unknown\n\nconst NOT_CALLED = 0\nconst CALLED = 1\nconst FAILED_INSIDE = 2\n\nconst direct: Chain = (ctx, core) => core(ctx)\n\nconst isThenable = (v: unknown): v is PromiseLike<unknown> =>\n v != null && typeof (v as { then?: unknown }).then === 'function'\n\nconst attaches = (i: Interceptor<OpName>, op: string) =>\n i.on === '*' || (i.on as readonly string[]).includes(op)\n\n/**\n * Wraps one interceptor around `inner`. Skip semantics (§3.4): if the interceptor throws before\n * calling `next`, `next` runs directly; if it throws after, the result `next` produced is kept so\n * the core never runs twice. An error that came out of `next` belongs to an inner layer and is\n * rethrown untouched. Async results get the same rules on rejection.\n */\nfunction wrap(\n i: Interceptor<OpName>,\n inner: Chain,\n mayBeAsync: boolean,\n report: (error: unknown, i: Interceptor<OpName>, ctx: AnyCtx) => void,\n): Chain {\n const intercept = i.intercept as (ctx: AnyCtx, next: () => unknown) => unknown\n return (ctx, core) => {\n let state = NOT_CALLED\n let out: unknown\n const next = () => {\n state = CALLED\n try {\n out = inner(ctx, core)\n } catch (e) {\n state = FAILED_INSIDE\n throw e\n }\n if (mayBeAsync && isThenable(out)) {\n const p = Promise.resolve(out).then(undefined, (e: unknown) => {\n state = FAILED_INSIDE\n throw e\n })\n // Handled here so an interceptor that drops `next()` never causes an unhandled rejection;\n // whoever awaits `p` still sees the rejection.\n p.catch(() => {})\n out = p\n }\n return out\n }\n const recover = (e: unknown) => {\n if (state === FAILED_INSIDE) throw e\n report(e, i, ctx)\n return state === CALLED ? out : inner(ctx, core)\n }\n let r: unknown\n try {\n r = intercept(ctx, next)\n } catch (e) {\n return recover(e)\n }\n return mayBeAsync && isThenable(r) ? Promise.resolve(r).then(undefined, recover) : r\n }\n}\n\nexport function createInterceptorRuntime(\n options: InterceptorRuntimeOptions = {},\n): InterceptorRuntime {\n const { emit, onCompile } = options\n const onError =\n options.onInterceptorError ??\n ((error: unknown, i: Interceptor<OpName>, ctx: AnyCtx) => {\n if (emit) {\n emit(\n 'DK_INTERCEPTOR_FAILED',\n { interceptor: i.name, op: ctx.op, slot: ctx.where },\n { cause: error, run: ctx.run, trigger: ctx.trigger, phase: ctx.phase },\n )\n } else {\n console.error(\n `[DataKable] interceptor \"${i.name}\" failed on ${ctx.op} and was skipped`,\n error,\n )\n }\n })\n // Dev-only (DK_HOT_INTERCEPTOR): `undefined` in production, with the code and its text.\n const onHotWarning = (process.env.NODE_ENV !== \"production\")\n ? (options.onHotWarning ??\n ((w: HotOpWarning) => {\n if (emit) emit('DK_HOT_INTERCEPTOR', { interceptor: w.interceptor.name, op: w.op })\n else console.warn(`[DataKable] ${w.message}`)\n }))\n : undefined\n const report = (error: unknown, i: Interceptor<OpName>, ctx: AnyCtx) => {\n try {\n onError(error, i, ctx)\n } catch (e) {\n // The reporter must never break the operation it reports on — except `strict: true`, whose\n // DatakableError is the requested behaviour.\n if (e instanceof DatakableError) throw e\n }\n }\n\n let list: readonly Interceptor<OpName>[] = []\n let boundary: Interceptor<OpName> | undefined\n const chains = new Map<string, Chain>()\n /** (interceptor, op) pairs already warned about, so recompiles do not repeat the warning. */\n const warned = (process.env.NODE_ENV !== \"production\") ? new WeakMap<Interceptor<OpName>, Set<string>>() : undefined\n\n function warnHot(i: Interceptor<OpName>, op: string) {\n if (!(process.env.NODE_ENV !== \"production\") || !warned || !onHotWarning) return // dev-only: production bundles drop the text below\n let ops = warned.get(i)\n if (ops?.has(op)) return\n if (!ops) {\n ops = new Set()\n warned.set(i, ops)\n }\n ops.add(op)\n try {\n onHotWarning({\n interceptor: i,\n op,\n message:\n `Interceptor \"${i.name}\" is attached to hot op \"${op}\" without hot: true. ` +\n // Measured by intercept/chain.bench.ts (Apple M4 Pro, Node 25.2.1). Inline here, inside\n // the (process.env.NODE_ENV !== \"production\")-only function, so production bundles carry none of it.\n 'It runs once per column per pipeline run; measured cost: ~10 ns per call per ' +\n 'interceptor (+15% on a per-cell format call, spec §9.2) on top of the interceptor ' +\n 'body, which runs columns × pipeline runs times. ' +\n 'Never loop per cell inside it. Set hot: true to accept the cost, ' +\n 'or attach it to a cold op.',\n })\n } catch {\n // A warning must never break compilation.\n }\n }\n\n function compile(op: string): Chain {\n const info = getOperation(op)\n if (!info) {\n throw internalError(op, `unknown-op|${op}`)\n }\n const mine = list.filter((i) => attaches(i, op))\n if (boundary && attaches(boundary, op)) mine.unshift(boundary)\n // Checked here, not when the list is set, so ops registered after creation are covered too.\n if ((process.env.NODE_ENV !== \"production\") && info.hot) for (const i of mine) if (!i.hot) warnHot(i, op)\n const mayBeAsync = info.kind !== 'sync'\n const chain = mine.reduceRight<Chain>((inner, i) => wrap(i, inner, mayBeAsync, report), direct)\n chains.set(op, chain)\n onCompile?.(op, mine.length)\n return chain\n }\n\n function compileAll() {\n chains.clear()\n for (const op of listOperations()) compile(op)\n }\n\n function setInterceptors(next: readonly Interceptor<OpName>[]) {\n list = [...next]\n compileAll()\n }\n\n setInterceptors(options.interceptors ?? [])\n\n return {\n run(op, ctx, core) {\n const chain = chains.get(op) ?? compile(op)\n return chain(ctx, core as AnyCore) as OpResult<typeof op>\n },\n setInterceptors,\n installBoundary(b) {\n if (boundary) {\n throw internalError('*', `boundary-twice|${boundary.name}|${b.name}`)\n }\n boundary = b\n compileAll()\n },\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAA8C;AAC9C,2BAAO;AAIP,wBAAyE;AAgDzE,IAAM,aAAa;AACnB,IAAM,SAAS;AACf,IAAM,gBAAgB;AAEtB,IAAM,SAAgB,CAAC,KAAK,SAAS,KAAK,GAAG;AAE7C,IAAM,aAAa,CAAC,MAClB,KAAK,QAAQ,OAAQ,EAAyB,SAAS;AAEzD,IAAM,WAAW,CAAC,GAAwB,OACxC,EAAE,OAAO,OAAQ,EAAE,GAAyB,SAAS,EAAE;AAQzD,SAAS,KACP,GACA,OACA,YACA,QACO;AACP,QAAM,YAAY,EAAE;AACpB,SAAO,CAAC,KAAK,SAAS;AACpB,QAAI,QAAQ;AACZ,QAAI;AACJ,UAAM,OAAO,MAAM;AACjB,cAAQ;AACR,UAAI;AACF,cAAM,MAAM,KAAK,IAAI;AAAA,MACvB,SAAS,GAAG;AACV,gBAAQ;AACR,cAAM;AAAA,MACR;AACA,UAAI,cAAc,WAAW,GAAG,GAAG;AACjC,cAAM,IAAI,QAAQ,QAAQ,GAAG,EAAE,KAAK,QAAW,CAAC,MAAe;AAC7D,kBAAQ;AACR,gBAAM;AAAA,QACR,CAAC;AAGD,UAAE,MAAM,MAAM;AAAA,QAAC,CAAC;AAChB,cAAM;AAAA,MACR;AACA,aAAO;AAAA,IACT;AACA,UAAM,UAAU,CAAC,MAAe;AAC9B,UAAI,UAAU,cAAe,OAAM;AACnC,aAAO,GAAG,GAAG,GAAG;AAChB,aAAO,UAAU,SAAS,MAAM,MAAM,KAAK,IAAI;AAAA,IACjD;AACA,QAAI;AACJ,QAAI;AACF,UAAI,UAAU,KAAK,IAAI;AAAA,IACzB,SAAS,GAAG;AACV,aAAO,QAAQ,CAAC;AAAA,IAClB;AACA,WAAO,cAAc,WAAW,CAAC,IAAI,QAAQ,QAAQ,CAAC,EAAE,KAAK,QAAW,OAAO,IAAI;AAAA,EACrF;AACF;AAEO,SAAS,yBACd,UAAqC,CAAC,GAClB;AACpB,QAAM,EAAE,MAAM,UAAU,IAAI;AAC5B,QAAM,UACJ,QAAQ,uBACP,CAAC,OAAgB,GAAwB,QAAgB;AACxD,QAAI,MAAM;AACR;AAAA,QACE;AAAA,QACA,EAAE,aAAa,EAAE,MAAM,IAAI,IAAI,IAAI,MAAM,IAAI,MAAM;AAAA,QACnD,EAAE,OAAO,OAAO,KAAK,IAAI,KAAK,SAAS,IAAI,SAAS,OAAO,IAAI,MAAM;AAAA,MACvE;AAAA,IACF,OAAO;AACL,cAAQ;AAAA,QACN,4BAA4B,EAAE,IAAI,eAAe,IAAI,EAAE;AAAA,QACvD;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEF,QAAM,eAAgB,QAAQ,IAAI,aAAa,eAC1C,QAAQ,iBACR,CAAC,MAAoB;AACpB,QAAI,KAAM,MAAK,sBAAsB,EAAE,aAAa,EAAE,YAAY,MAAM,IAAI,EAAE,GAAG,CAAC;AAAA,QAC7E,SAAQ,KAAK,eAAe,EAAE,OAAO,EAAE;AAAA,EAC9C,KACA;AACJ,QAAM,SAAS,CAAC,OAAgB,GAAwB,QAAgB;AACtE,QAAI;AACF,cAAQ,OAAO,GAAG,GAAG;AAAA,IACvB,SAAS,GAAG;AAGV,UAAI,aAAa,4BAAgB,OAAM;AAAA,IACzC;AAAA,EACF;AAEA,MAAI,OAAuC,CAAC;AAC5C,MAAI;AACJ,QAAM,SAAS,oBAAI,IAAmB;AAEtC,QAAM,SAAU,QAAQ,IAAI,aAAa,eAAgB,oBAAI,QAA0C,IAAI;AAE3G,WAAS,QAAQ,GAAwB,IAAY;AACnD,QAAI,EAAE,QAAQ,IAAI,aAAa,iBAAiB,CAAC,UAAU,CAAC,aAAc;AAC1E,QAAI,MAAM,OAAO,IAAI,CAAC;AACtB,QAAI,KAAK,IAAI,EAAE,EAAG;AAClB,QAAI,CAAC,KAAK;AACR,YAAM,oBAAI,IAAI;AACd,aAAO,IAAI,GAAG,GAAG;AAAA,IACnB;AACA,QAAI,IAAI,EAAE;AACV,QAAI;AACF,mBAAa;AAAA,QACX,aAAa;AAAA,QACb;AAAA,QACA,SACE,gBAAgB,EAAE,IAAI,4BAA4B,EAAE;AAAA,MAQxD,CAAC;AAAA,IACH,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,WAAS,QAAQ,IAAmB;AAClC,UAAM,WAAO,gCAAa,EAAE;AAC5B,QAAI,CAAC,MAAM;AACT,gBAAM,4BAAc,IAAI,cAAc,EAAE,EAAE;AAAA,IAC5C;AACA,UAAM,OAAO,KAAK,OAAO,CAAC,MAAM,SAAS,GAAG,EAAE,CAAC;AAC/C,QAAI,YAAY,SAAS,UAAU,EAAE,EAAG,MAAK,QAAQ,QAAQ;AAE7D,QAAK,QAAQ,IAAI,aAAa,gBAAiB,KAAK;AAAK,iBAAW,KAAK,KAAM,KAAI,CAAC,EAAE,IAAK,SAAQ,GAAG,EAAE;AAAA;AACxG,UAAM,aAAa,KAAK,SAAS;AACjC,UAAM,QAAQ,KAAK,YAAmB,CAAC,OAAO,MAAM,KAAK,GAAG,OAAO,YAAY,MAAM,GAAG,MAAM;AAC9F,WAAO,IAAI,IAAI,KAAK;AACpB,gBAAY,IAAI,KAAK,MAAM;AAC3B,WAAO;AAAA,EACT;AAEA,WAAS,aAAa;AACpB,WAAO,MAAM;AACb,eAAW,UAAM,kCAAe,EAAG,SAAQ,EAAE;AAAA,EAC/C;AAEA,WAAS,gBAAgB,MAAsC;AAC7D,WAAO,CAAC,GAAG,IAAI;AACf,eAAW;AAAA,EACb;AAEA,kBAAgB,QAAQ,gBAAgB,CAAC,CAAC;AAE1C,SAAO;AAAA,IACL,IAAI,IAAI,KAAK,MAAM;AACjB,YAAM,QAAQ,OAAO,IAAI,EAAE,KAAK,QAAQ,EAAE;AAC1C,aAAO,MAAM,KAAK,IAAe;AAAA,IACnC;AAAA,IACA;AAAA,IACA,gBAAgB,GAAG;AACjB,UAAI,UAAU;AACZ,kBAAM,4BAAc,KAAK,kBAAkB,SAAS,IAAI,IAAI,EAAE,IAAI,EAAE;AAAA,MACtE;AACA,iBAAW;AACX,iBAAW;AAAA,IACb;AAAA,EACF;AACF;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/intercept/runtime.ts"],"sourcesContent":["import { DatakableError, internalError } from '../diagnostics/build'\nimport '../diagnostics/process-guard'\nimport { proseArg } from '../diagnostics/prose'\nimport type { Emit } from '../diagnostics/types'\nimport type { InterceptorContext } from './context'\nimport type { Interceptor } from './define'\nimport { getOperation, listOperations, type OpName, type OpResult } from './operations'\n\nexport type Core<O extends OpName> = (ctx: InterceptorContext<O>) => OpResult<O>\n\nexport interface HotOpWarning {\n interceptor: Interceptor<OpName>\n op: string\n message: string\n}\n\nexport interface InterceptorRuntimeOptions {\n interceptors?: readonly Interceptor<OpName>[]\n /**\n * The table's diagnostic emitter. When given, the default hooks below report through it:\n * `DK_INTERCEPTOR_FAILED` and (dev only) `DK_HOT_INTERCEPTOR`. Without it they use the console.\n */\n emit?: Emit\n /**\n * An interceptor threw (or its promise rejected); it was skipped. Overrides the default report\n * (`DK_INTERCEPTOR_FAILED` via `emit`, else console.error).\n */\n onInterceptorError?: (\n error: unknown,\n interceptor: Interceptor<OpName>,\n ctx: InterceptorContext,\n ) => void\n /**\n * An interceptor is attached to a hot op without `hot: true` (checked when the op's chain is\n * compiled, once per interceptor + op). Overrides the default (`DK_HOT_INTERCEPTOR` via `emit`).\n */\n onHotWarning?: (warning: HotOpWarning) => void\n /** Called each time a chain is compiled (tracing / tests). `length` counts the boundary too. */\n onCompile?: (op: string, length: number) => void\n}\n\nexport interface InterceptorRuntime {\n /** Runs `core` for `op` through the compiled chain. */\n run<O extends OpName>(op: O, ctx: InterceptorContext<O>, core: NoInfer<Core<O>>): OpResult<O>\n /** Replaces the user / feature interceptors and recompiles. The boundary slot is kept. */\n setInterceptors(interceptors: readonly Interceptor<OpName>[]): void\n /** Installs the outermost, non-removable interceptor (errorBoundary, T06). Once only. */\n installBoundary(boundary: Interceptor<OpName>): void\n}\n\ntype AnyCtx = InterceptorContext\ntype AnyCore = (ctx: AnyCtx) => unknown\ntype Chain = (ctx: AnyCtx, core: AnyCore) => unknown\n\nconst NOT_CALLED = 0\nconst CALLED = 1\nconst FAILED_INSIDE = 2\n\nconst direct: Chain = (ctx, core) => core(ctx)\n\nconst isThenable = (v: unknown): v is PromiseLike<unknown> =>\n v != null && typeof (v as { then?: unknown }).then === 'function'\n\nconst attaches = (i: Interceptor<OpName>, op: string) =>\n i.on === '*' || (i.on as readonly string[]).includes(op)\n\n/**\n * Wraps one interceptor around `inner`. Skip semantics (§3.4): if the interceptor throws before\n * calling `next`, `next` runs directly; if it throws after, the result `next` produced is kept so\n * the core never runs twice. An error that came out of `next` belongs to an inner layer and is\n * rethrown untouched. Async results get the same rules on rejection.\n */\nfunction wrap(\n i: Interceptor<OpName>,\n inner: Chain,\n mayBeAsync: boolean,\n report: (error: unknown, i: Interceptor<OpName>, ctx: AnyCtx) => void,\n): Chain {\n const intercept = i.intercept as (ctx: AnyCtx, next: () => unknown) => unknown\n return (ctx, core) => {\n let state = NOT_CALLED\n let out: unknown\n const next = () => {\n state = CALLED\n try {\n out = inner(ctx, core)\n } catch (e) {\n state = FAILED_INSIDE\n throw e\n }\n if (mayBeAsync && isThenable(out)) {\n const p = Promise.resolve(out).then(undefined, (e: unknown) => {\n state = FAILED_INSIDE\n throw e\n })\n // Handled here so an interceptor that drops `next()` never causes an unhandled rejection;\n // whoever awaits `p` still sees the rejection.\n p.catch(() => {})\n out = p\n }\n return out\n }\n const recover = (e: unknown) => {\n if (state === FAILED_INSIDE) throw e\n report(e, i, ctx)\n return state === CALLED ? out : inner(ctx, core)\n }\n let r: unknown\n try {\n r = intercept(ctx, next)\n } catch (e) {\n return recover(e)\n }\n return mayBeAsync && isThenable(r) ? Promise.resolve(r).then(undefined, recover) : r\n }\n}\n\nexport function createInterceptorRuntime(\n options: InterceptorRuntimeOptions = {},\n): InterceptorRuntime {\n const { emit, onCompile } = options\n const onError =\n options.onInterceptorError ??\n ((error: unknown, i: Interceptor<OpName>, ctx: AnyCtx) => {\n if (emit) {\n emit(\n 'DK_INTERCEPTOR_FAILED',\n { interceptor: i.name, op: ctx.op, slot: ctx.where },\n { cause: error, run: ctx.run, trigger: ctx.trigger, phase: ctx.phase },\n )\n } else {\n console.error(\n `[DataKable] interceptor \"${i.name}\" failed on ${ctx.op} and was skipped`,\n error,\n )\n }\n })\n // Dev-only (DK_HOT_INTERCEPTOR): `undefined` in production, with the code and its text.\n const onHotWarning = (process.env.NODE_ENV !== \"production\")\n ? (options.onHotWarning ??\n ((w: HotOpWarning) => {\n if (emit) emit('DK_HOT_INTERCEPTOR', { interceptor: w.interceptor.name, op: w.op })\n else console.warn(`[DataKable] ${w.message}`)\n }))\n : undefined\n const report = (error: unknown, i: Interceptor<OpName>, ctx: AnyCtx) => {\n try {\n onError(error, i, ctx)\n } catch (e) {\n // The reporter must never break the operation it reports on — except `strict: true`, whose\n // DatakableError is the requested behaviour.\n if (e instanceof DatakableError) throw e\n }\n }\n\n let list: readonly Interceptor<OpName>[] = []\n let boundary: Interceptor<OpName> | undefined\n const chains = new Map<string, Chain>()\n /** (interceptor, op) pairs already warned about, so recompiles do not repeat the warning. */\n const warned = (process.env.NODE_ENV !== \"production\") ? new WeakMap<Interceptor<OpName>, Set<string>>() : undefined\n\n function warnHot(i: Interceptor<OpName>, op: string) {\n if (!(process.env.NODE_ENV !== \"production\") || !warned || !onHotWarning) return // dev-only: production bundles drop the text below\n let ops = warned.get(i)\n if (ops?.has(op)) return\n if (!ops) {\n ops = new Set()\n warned.set(i, ops)\n }\n ops.add(op)\n try {\n onHotWarning({\n interceptor: i,\n op,\n message:\n `Interceptor \"${i.name}\" is attached to hot op \"${op}\" without hot: true. ` +\n // Measured by intercept/chain.bench.ts (Apple M4 Pro, Node 25.2.1). Inline here, inside\n // the (process.env.NODE_ENV !== \"production\")-only function, so production bundles carry none of it.\n 'It runs once per column per pipeline run; measured cost: ~10 ns per call per ' +\n 'interceptor (+15% on a per-cell format call, spec §9.2) on top of the interceptor ' +\n 'body, which runs columns × pipeline runs times. ' +\n 'Never loop per cell inside it. Set hot: true to accept the cost, ' +\n 'or attach it to a cold op.',\n })\n } catch {\n // A warning must never break compilation.\n }\n }\n\n function compile(op: string): Chain {\n const info = getOperation(op)\n if (!info) {\n throw internalError(op, `unknown-op|${proseArg(op)}`)\n }\n const mine = list.filter((i) => attaches(i, op))\n if (boundary && attaches(boundary, op)) mine.unshift(boundary)\n // Checked here, not when the list is set, so ops registered after creation are covered too.\n if ((process.env.NODE_ENV !== \"production\") && info.hot) for (const i of mine) if (!i.hot) warnHot(i, op)\n const mayBeAsync = info.kind !== 'sync'\n const chain = mine.reduceRight<Chain>((inner, i) => wrap(i, inner, mayBeAsync, report), direct)\n chains.set(op, chain)\n onCompile?.(op, mine.length)\n return chain\n }\n\n function compileAll() {\n chains.clear()\n for (const op of listOperations()) compile(op)\n }\n\n function setInterceptors(next: readonly Interceptor<OpName>[]) {\n list = [...next]\n compileAll()\n }\n\n setInterceptors(options.interceptors ?? [])\n\n return {\n run(op, ctx, core) {\n const chain = chains.get(op) ?? compile(op)\n return chain(ctx, core as AnyCore) as OpResult<typeof op>\n },\n setInterceptors,\n installBoundary(b) {\n if (boundary) {\n throw internalError('*', `boundary-twice|${proseArg(boundary.name)}|${proseArg(b.name)}`)\n }\n boundary = b\n compileAll()\n },\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// src/intercept/runtime.ts
|
|
2
2
|
import { DatakableError, internalError } from "../diagnostics/build.js";
|
|
3
3
|
import "../diagnostics/process-guard.js";
|
|
4
|
+
import { proseArg } from "../diagnostics/prose.js";
|
|
4
5
|
import { getOperation, listOperations } from "./operations.js";
|
|
5
6
|
var NOT_CALLED = 0;
|
|
6
7
|
var CALLED = 1;
|
|
@@ -98,7 +99,7 @@ function createInterceptorRuntime(options = {}) {
|
|
|
98
99
|
function compile(op) {
|
|
99
100
|
const info = getOperation(op);
|
|
100
101
|
if (!info) {
|
|
101
|
-
throw internalError(op, `unknown-op|${op}`);
|
|
102
|
+
throw internalError(op, `unknown-op|${proseArg(op)}`);
|
|
102
103
|
}
|
|
103
104
|
const mine = list.filter((i) => attaches(i, op));
|
|
104
105
|
if (boundary && attaches(boundary, op)) mine.unshift(boundary);
|
|
@@ -128,7 +129,7 @@ function createInterceptorRuntime(options = {}) {
|
|
|
128
129
|
setInterceptors,
|
|
129
130
|
installBoundary(b) {
|
|
130
131
|
if (boundary) {
|
|
131
|
-
throw internalError("*", `boundary-twice|${boundary.name}|${b.name}`);
|
|
132
|
+
throw internalError("*", `boundary-twice|${proseArg(boundary.name)}|${proseArg(b.name)}`);
|
|
132
133
|
}
|
|
133
134
|
boundary = b;
|
|
134
135
|
compileAll();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/intercept/runtime.ts"],"sourcesContent":["import { DatakableError, internalError } from '../diagnostics/build'\nimport '../diagnostics/process-guard'\nimport type { Emit } from '../diagnostics/types'\nimport type { InterceptorContext } from './context'\nimport type { Interceptor } from './define'\nimport { getOperation, listOperations, type OpName, type OpResult } from './operations'\n\nexport type Core<O extends OpName> = (ctx: InterceptorContext<O>) => OpResult<O>\n\nexport interface HotOpWarning {\n interceptor: Interceptor<OpName>\n op: string\n message: string\n}\n\nexport interface InterceptorRuntimeOptions {\n interceptors?: readonly Interceptor<OpName>[]\n /**\n * The table's diagnostic emitter. When given, the default hooks below report through it:\n * `DK_INTERCEPTOR_FAILED` and (dev only) `DK_HOT_INTERCEPTOR`. Without it they use the console.\n */\n emit?: Emit\n /**\n * An interceptor threw (or its promise rejected); it was skipped. Overrides the default report\n * (`DK_INTERCEPTOR_FAILED` via `emit`, else console.error).\n */\n onInterceptorError?: (\n error: unknown,\n interceptor: Interceptor<OpName>,\n ctx: InterceptorContext,\n ) => void\n /**\n * An interceptor is attached to a hot op without `hot: true` (checked when the op's chain is\n * compiled, once per interceptor + op). Overrides the default (`DK_HOT_INTERCEPTOR` via `emit`).\n */\n onHotWarning?: (warning: HotOpWarning) => void\n /** Called each time a chain is compiled (tracing / tests). `length` counts the boundary too. */\n onCompile?: (op: string, length: number) => void\n}\n\nexport interface InterceptorRuntime {\n /** Runs `core` for `op` through the compiled chain. */\n run<O extends OpName>(op: O, ctx: InterceptorContext<O>, core: NoInfer<Core<O>>): OpResult<O>\n /** Replaces the user / feature interceptors and recompiles. The boundary slot is kept. */\n setInterceptors(interceptors: readonly Interceptor<OpName>[]): void\n /** Installs the outermost, non-removable interceptor (errorBoundary, T06). Once only. */\n installBoundary(boundary: Interceptor<OpName>): void\n}\n\ntype AnyCtx = InterceptorContext\ntype AnyCore = (ctx: AnyCtx) => unknown\ntype Chain = (ctx: AnyCtx, core: AnyCore) => unknown\n\nconst NOT_CALLED = 0\nconst CALLED = 1\nconst FAILED_INSIDE = 2\n\nconst direct: Chain = (ctx, core) => core(ctx)\n\nconst isThenable = (v: unknown): v is PromiseLike<unknown> =>\n v != null && typeof (v as { then?: unknown }).then === 'function'\n\nconst attaches = (i: Interceptor<OpName>, op: string) =>\n i.on === '*' || (i.on as readonly string[]).includes(op)\n\n/**\n * Wraps one interceptor around `inner`. Skip semantics (§3.4): if the interceptor throws before\n * calling `next`, `next` runs directly; if it throws after, the result `next` produced is kept so\n * the core never runs twice. An error that came out of `next` belongs to an inner layer and is\n * rethrown untouched. Async results get the same rules on rejection.\n */\nfunction wrap(\n i: Interceptor<OpName>,\n inner: Chain,\n mayBeAsync: boolean,\n report: (error: unknown, i: Interceptor<OpName>, ctx: AnyCtx) => void,\n): Chain {\n const intercept = i.intercept as (ctx: AnyCtx, next: () => unknown) => unknown\n return (ctx, core) => {\n let state = NOT_CALLED\n let out: unknown\n const next = () => {\n state = CALLED\n try {\n out = inner(ctx, core)\n } catch (e) {\n state = FAILED_INSIDE\n throw e\n }\n if (mayBeAsync && isThenable(out)) {\n const p = Promise.resolve(out).then(undefined, (e: unknown) => {\n state = FAILED_INSIDE\n throw e\n })\n // Handled here so an interceptor that drops `next()` never causes an unhandled rejection;\n // whoever awaits `p` still sees the rejection.\n p.catch(() => {})\n out = p\n }\n return out\n }\n const recover = (e: unknown) => {\n if (state === FAILED_INSIDE) throw e\n report(e, i, ctx)\n return state === CALLED ? out : inner(ctx, core)\n }\n let r: unknown\n try {\n r = intercept(ctx, next)\n } catch (e) {\n return recover(e)\n }\n return mayBeAsync && isThenable(r) ? Promise.resolve(r).then(undefined, recover) : r\n }\n}\n\nexport function createInterceptorRuntime(\n options: InterceptorRuntimeOptions = {},\n): InterceptorRuntime {\n const { emit, onCompile } = options\n const onError =\n options.onInterceptorError ??\n ((error: unknown, i: Interceptor<OpName>, ctx: AnyCtx) => {\n if (emit) {\n emit(\n 'DK_INTERCEPTOR_FAILED',\n { interceptor: i.name, op: ctx.op, slot: ctx.where },\n { cause: error, run: ctx.run, trigger: ctx.trigger, phase: ctx.phase },\n )\n } else {\n console.error(\n `[DataKable] interceptor \"${i.name}\" failed on ${ctx.op} and was skipped`,\n error,\n )\n }\n })\n // Dev-only (DK_HOT_INTERCEPTOR): `undefined` in production, with the code and its text.\n const onHotWarning = (process.env.NODE_ENV !== \"production\")\n ? (options.onHotWarning ??\n ((w: HotOpWarning) => {\n if (emit) emit('DK_HOT_INTERCEPTOR', { interceptor: w.interceptor.name, op: w.op })\n else console.warn(`[DataKable] ${w.message}`)\n }))\n : undefined\n const report = (error: unknown, i: Interceptor<OpName>, ctx: AnyCtx) => {\n try {\n onError(error, i, ctx)\n } catch (e) {\n // The reporter must never break the operation it reports on — except `strict: true`, whose\n // DatakableError is the requested behaviour.\n if (e instanceof DatakableError) throw e\n }\n }\n\n let list: readonly Interceptor<OpName>[] = []\n let boundary: Interceptor<OpName> | undefined\n const chains = new Map<string, Chain>()\n /** (interceptor, op) pairs already warned about, so recompiles do not repeat the warning. */\n const warned = (process.env.NODE_ENV !== \"production\") ? new WeakMap<Interceptor<OpName>, Set<string>>() : undefined\n\n function warnHot(i: Interceptor<OpName>, op: string) {\n if (!(process.env.NODE_ENV !== \"production\") || !warned || !onHotWarning) return // dev-only: production bundles drop the text below\n let ops = warned.get(i)\n if (ops?.has(op)) return\n if (!ops) {\n ops = new Set()\n warned.set(i, ops)\n }\n ops.add(op)\n try {\n onHotWarning({\n interceptor: i,\n op,\n message:\n `Interceptor \"${i.name}\" is attached to hot op \"${op}\" without hot: true. ` +\n // Measured by intercept/chain.bench.ts (Apple M4 Pro, Node 25.2.1). Inline here, inside\n // the (process.env.NODE_ENV !== \"production\")-only function, so production bundles carry none of it.\n 'It runs once per column per pipeline run; measured cost: ~10 ns per call per ' +\n 'interceptor (+15% on a per-cell format call, spec §9.2) on top of the interceptor ' +\n 'body, which runs columns × pipeline runs times. ' +\n 'Never loop per cell inside it. Set hot: true to accept the cost, ' +\n 'or attach it to a cold op.',\n })\n } catch {\n // A warning must never break compilation.\n }\n }\n\n function compile(op: string): Chain {\n const info = getOperation(op)\n if (!info) {\n throw internalError(op, `unknown-op|${op}`)\n }\n const mine = list.filter((i) => attaches(i, op))\n if (boundary && attaches(boundary, op)) mine.unshift(boundary)\n // Checked here, not when the list is set, so ops registered after creation are covered too.\n if ((process.env.NODE_ENV !== \"production\") && info.hot) for (const i of mine) if (!i.hot) warnHot(i, op)\n const mayBeAsync = info.kind !== 'sync'\n const chain = mine.reduceRight<Chain>((inner, i) => wrap(i, inner, mayBeAsync, report), direct)\n chains.set(op, chain)\n onCompile?.(op, mine.length)\n return chain\n }\n\n function compileAll() {\n chains.clear()\n for (const op of listOperations()) compile(op)\n }\n\n function setInterceptors(next: readonly Interceptor<OpName>[]) {\n list = [...next]\n compileAll()\n }\n\n setInterceptors(options.interceptors ?? [])\n\n return {\n run(op, ctx, core) {\n const chain = chains.get(op) ?? compile(op)\n return chain(ctx, core as AnyCore) as OpResult<typeof op>\n },\n setInterceptors,\n installBoundary(b) {\n if (boundary) {\n throw internalError('*', `boundary-twice|${boundary.name}|${b.name}`)\n }\n boundary = b\n compileAll()\n },\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/intercept/runtime.ts"],"sourcesContent":["import { DatakableError, internalError } from '../diagnostics/build'\nimport '../diagnostics/process-guard'\nimport { proseArg } from '../diagnostics/prose'\nimport type { Emit } from '../diagnostics/types'\nimport type { InterceptorContext } from './context'\nimport type { Interceptor } from './define'\nimport { getOperation, listOperations, type OpName, type OpResult } from './operations'\n\nexport type Core<O extends OpName> = (ctx: InterceptorContext<O>) => OpResult<O>\n\nexport interface HotOpWarning {\n interceptor: Interceptor<OpName>\n op: string\n message: string\n}\n\nexport interface InterceptorRuntimeOptions {\n interceptors?: readonly Interceptor<OpName>[]\n /**\n * The table's diagnostic emitter. When given, the default hooks below report through it:\n * `DK_INTERCEPTOR_FAILED` and (dev only) `DK_HOT_INTERCEPTOR`. Without it they use the console.\n */\n emit?: Emit\n /**\n * An interceptor threw (or its promise rejected); it was skipped. Overrides the default report\n * (`DK_INTERCEPTOR_FAILED` via `emit`, else console.error).\n */\n onInterceptorError?: (\n error: unknown,\n interceptor: Interceptor<OpName>,\n ctx: InterceptorContext,\n ) => void\n /**\n * An interceptor is attached to a hot op without `hot: true` (checked when the op's chain is\n * compiled, once per interceptor + op). Overrides the default (`DK_HOT_INTERCEPTOR` via `emit`).\n */\n onHotWarning?: (warning: HotOpWarning) => void\n /** Called each time a chain is compiled (tracing / tests). `length` counts the boundary too. */\n onCompile?: (op: string, length: number) => void\n}\n\nexport interface InterceptorRuntime {\n /** Runs `core` for `op` through the compiled chain. */\n run<O extends OpName>(op: O, ctx: InterceptorContext<O>, core: NoInfer<Core<O>>): OpResult<O>\n /** Replaces the user / feature interceptors and recompiles. The boundary slot is kept. */\n setInterceptors(interceptors: readonly Interceptor<OpName>[]): void\n /** Installs the outermost, non-removable interceptor (errorBoundary, T06). Once only. */\n installBoundary(boundary: Interceptor<OpName>): void\n}\n\ntype AnyCtx = InterceptorContext\ntype AnyCore = (ctx: AnyCtx) => unknown\ntype Chain = (ctx: AnyCtx, core: AnyCore) => unknown\n\nconst NOT_CALLED = 0\nconst CALLED = 1\nconst FAILED_INSIDE = 2\n\nconst direct: Chain = (ctx, core) => core(ctx)\n\nconst isThenable = (v: unknown): v is PromiseLike<unknown> =>\n v != null && typeof (v as { then?: unknown }).then === 'function'\n\nconst attaches = (i: Interceptor<OpName>, op: string) =>\n i.on === '*' || (i.on as readonly string[]).includes(op)\n\n/**\n * Wraps one interceptor around `inner`. Skip semantics (§3.4): if the interceptor throws before\n * calling `next`, `next` runs directly; if it throws after, the result `next` produced is kept so\n * the core never runs twice. An error that came out of `next` belongs to an inner layer and is\n * rethrown untouched. Async results get the same rules on rejection.\n */\nfunction wrap(\n i: Interceptor<OpName>,\n inner: Chain,\n mayBeAsync: boolean,\n report: (error: unknown, i: Interceptor<OpName>, ctx: AnyCtx) => void,\n): Chain {\n const intercept = i.intercept as (ctx: AnyCtx, next: () => unknown) => unknown\n return (ctx, core) => {\n let state = NOT_CALLED\n let out: unknown\n const next = () => {\n state = CALLED\n try {\n out = inner(ctx, core)\n } catch (e) {\n state = FAILED_INSIDE\n throw e\n }\n if (mayBeAsync && isThenable(out)) {\n const p = Promise.resolve(out).then(undefined, (e: unknown) => {\n state = FAILED_INSIDE\n throw e\n })\n // Handled here so an interceptor that drops `next()` never causes an unhandled rejection;\n // whoever awaits `p` still sees the rejection.\n p.catch(() => {})\n out = p\n }\n return out\n }\n const recover = (e: unknown) => {\n if (state === FAILED_INSIDE) throw e\n report(e, i, ctx)\n return state === CALLED ? out : inner(ctx, core)\n }\n let r: unknown\n try {\n r = intercept(ctx, next)\n } catch (e) {\n return recover(e)\n }\n return mayBeAsync && isThenable(r) ? Promise.resolve(r).then(undefined, recover) : r\n }\n}\n\nexport function createInterceptorRuntime(\n options: InterceptorRuntimeOptions = {},\n): InterceptorRuntime {\n const { emit, onCompile } = options\n const onError =\n options.onInterceptorError ??\n ((error: unknown, i: Interceptor<OpName>, ctx: AnyCtx) => {\n if (emit) {\n emit(\n 'DK_INTERCEPTOR_FAILED',\n { interceptor: i.name, op: ctx.op, slot: ctx.where },\n { cause: error, run: ctx.run, trigger: ctx.trigger, phase: ctx.phase },\n )\n } else {\n console.error(\n `[DataKable] interceptor \"${i.name}\" failed on ${ctx.op} and was skipped`,\n error,\n )\n }\n })\n // Dev-only (DK_HOT_INTERCEPTOR): `undefined` in production, with the code and its text.\n const onHotWarning = (process.env.NODE_ENV !== \"production\")\n ? (options.onHotWarning ??\n ((w: HotOpWarning) => {\n if (emit) emit('DK_HOT_INTERCEPTOR', { interceptor: w.interceptor.name, op: w.op })\n else console.warn(`[DataKable] ${w.message}`)\n }))\n : undefined\n const report = (error: unknown, i: Interceptor<OpName>, ctx: AnyCtx) => {\n try {\n onError(error, i, ctx)\n } catch (e) {\n // The reporter must never break the operation it reports on — except `strict: true`, whose\n // DatakableError is the requested behaviour.\n if (e instanceof DatakableError) throw e\n }\n }\n\n let list: readonly Interceptor<OpName>[] = []\n let boundary: Interceptor<OpName> | undefined\n const chains = new Map<string, Chain>()\n /** (interceptor, op) pairs already warned about, so recompiles do not repeat the warning. */\n const warned = (process.env.NODE_ENV !== \"production\") ? new WeakMap<Interceptor<OpName>, Set<string>>() : undefined\n\n function warnHot(i: Interceptor<OpName>, op: string) {\n if (!(process.env.NODE_ENV !== \"production\") || !warned || !onHotWarning) return // dev-only: production bundles drop the text below\n let ops = warned.get(i)\n if (ops?.has(op)) return\n if (!ops) {\n ops = new Set()\n warned.set(i, ops)\n }\n ops.add(op)\n try {\n onHotWarning({\n interceptor: i,\n op,\n message:\n `Interceptor \"${i.name}\" is attached to hot op \"${op}\" without hot: true. ` +\n // Measured by intercept/chain.bench.ts (Apple M4 Pro, Node 25.2.1). Inline here, inside\n // the (process.env.NODE_ENV !== \"production\")-only function, so production bundles carry none of it.\n 'It runs once per column per pipeline run; measured cost: ~10 ns per call per ' +\n 'interceptor (+15% on a per-cell format call, spec §9.2) on top of the interceptor ' +\n 'body, which runs columns × pipeline runs times. ' +\n 'Never loop per cell inside it. Set hot: true to accept the cost, ' +\n 'or attach it to a cold op.',\n })\n } catch {\n // A warning must never break compilation.\n }\n }\n\n function compile(op: string): Chain {\n const info = getOperation(op)\n if (!info) {\n throw internalError(op, `unknown-op|${proseArg(op)}`)\n }\n const mine = list.filter((i) => attaches(i, op))\n if (boundary && attaches(boundary, op)) mine.unshift(boundary)\n // Checked here, not when the list is set, so ops registered after creation are covered too.\n if ((process.env.NODE_ENV !== \"production\") && info.hot) for (const i of mine) if (!i.hot) warnHot(i, op)\n const mayBeAsync = info.kind !== 'sync'\n const chain = mine.reduceRight<Chain>((inner, i) => wrap(i, inner, mayBeAsync, report), direct)\n chains.set(op, chain)\n onCompile?.(op, mine.length)\n return chain\n }\n\n function compileAll() {\n chains.clear()\n for (const op of listOperations()) compile(op)\n }\n\n function setInterceptors(next: readonly Interceptor<OpName>[]) {\n list = [...next]\n compileAll()\n }\n\n setInterceptors(options.interceptors ?? [])\n\n return {\n run(op, ctx, core) {\n const chain = chains.get(op) ?? compile(op)\n return chain(ctx, core as AnyCore) as OpResult<typeof op>\n },\n setInterceptors,\n installBoundary(b) {\n if (boundary) {\n throw internalError('*', `boundary-twice|${proseArg(boundary.name)}|${proseArg(b.name)}`)\n }\n boundary = b\n compileAll()\n },\n }\n}\n"],"mappings":"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","names":[]}
|
package/dist/messages/index.cjs
CHANGED
|
@@ -44,6 +44,7 @@ var import_codes11 = require("../source/codes.cjs");
|
|
|
44
44
|
var import_fetch_codes = require("../source/fetch-codes.cjs");
|
|
45
45
|
var import_codes12 = require("../table/codes.cjs");
|
|
46
46
|
var import_ssr_codes = require("../table/ssr-codes.cjs");
|
|
47
|
+
var import_state_codes = require("../table/state-codes.cjs");
|
|
47
48
|
var import_codes13 = require("../versioning/codes.cjs");
|
|
48
49
|
var allMessages = [
|
|
49
50
|
import_codes2.coreMessages,
|
|
@@ -54,6 +55,7 @@ var allMessages = [
|
|
|
54
55
|
import_codes10.pipelineMessages,
|
|
55
56
|
import_codes12.tableMessages,
|
|
56
57
|
import_ssr_codes.ssrMessages,
|
|
58
|
+
import_state_codes.stateMessages,
|
|
57
59
|
import_codes11.asyncMessages,
|
|
58
60
|
import_fetch_codes.fetchMessages,
|
|
59
61
|
import_row_key_codes.rowKeyMessages,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/messages/index.ts"],"sourcesContent":["/**\n * `@datakable/core/messages` (`datakable/messages`): full diagnostic text in production (§8.2).\n *\n * Production builds strip `problem` / `impact` / `fix` and keep `code`, `where`, `context` and a\n * docs URL. `import '@datakable/core/messages'` once (e.g. in the app entry) installs the text of\n * every code a production build can emit. Development builds already have it. This module is the\n * package's only side effect (`sideEffects` in package.json).\n */\nimport { optionMessages } from '../catalog/codes'\nimport { installMessages } from '../diagnostics/catalog'\nimport { coreMessages } from '../diagnostics/codes'\nimport { proseMessages } from '../diagnostics/prose'\nimport { redactionMessages } from '../diagnostics/redact'\nimport { featureMessages } from '../feature/codes'\nimport { columnFiltersMessages } from '../features/column-filters/codes'\nimport { paginationMessages } from '../features/pagination/codes'\nimport { searchMessages } from '../features/search/codes'\nimport { sortingMessages } from '../features/sorting/codes'\nimport { validityMessages } from '../features/validity/codes'\nimport { dataCheckMessages } from '../ingest/data-check-codes'\nimport { rowKeyMessages } from '../ingest/row-key-codes'\nimport { schemaMessages } from '../ingest/schema-codes'\nimport { boundaryMessages } from '../intercept/codes'\nimport { pipelineMessages } from '../pipeline/codes'\nimport { envMessages } from '../pipeline/env-codes'\nimport { asyncMessages } from '../source/codes'\nimport { fetchMessages } from '../source/fetch-codes'\nimport { tableMessages } from '../table/codes'\nimport { ssrMessages } from '../table/ssr-codes'\nimport { versioningMessages } from '../versioning/codes'\n\n/** Every message object core ships, one per module that owns codes. */\nexport const allMessages: ReadonlyArray<Readonly<Record<string, unknown>>> = [\n coreMessages,\n redactionMessages,\n optionMessages,\n featureMessages,\n boundaryMessages,\n pipelineMessages,\n tableMessages,\n ssrMessages,\n asyncMessages,\n fetchMessages,\n rowKeyMessages,\n schemaMessages,\n dataCheckMessages,\n versioningMessages,\n columnFiltersMessages,\n validityMessages,\n searchMessages,\n sortingMessages,\n paginationMessages,\n envMessages,\n // The detail sentences production keeps as keys (`fallback: 'cells-undefined'`).\n proseMessages,\n]\n\ninstallMessages(...allMessages)\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAQA,mBAA+B;AAC/B,qBAAgC;AAChC,IAAAA,gBAA6B;AAC7B,mBAA8B;AAC9B,oBAAkC;AAClC,IAAAA,gBAAgC;AAChC,IAAAA,gBAAsC;AACtC,IAAAA,gBAAmC;AACnC,IAAAA,gBAA+B;AAC/B,IAAAA,gBAAgC;AAChC,IAAAA,gBAAiC;AACjC,8BAAkC;AAClC,2BAA+B;AAC/B,0BAA+B;AAC/B,IAAAA,gBAAiC;AACjC,IAAAA,iBAAiC;AACjC,uBAA4B;AAC5B,IAAAA,iBAA8B;AAC9B,yBAA8B;AAC9B,IAAAA,iBAA8B;AAC9B,uBAA4B;AAC5B,IAAAA,iBAAmC;AAG5B,IAAM,cAAgE;AAAA,EAC3E;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AACF;AAAA,IAEA,gCAAgB,GAAG,WAAW;","names":["import_codes"]}
|
|
1
|
+
{"version":3,"sources":["../../src/messages/index.ts"],"sourcesContent":["/**\n * `@datakable/core/messages` (`datakable/messages`): full diagnostic text in production (§8.2).\n *\n * Production builds strip `problem` / `impact` / `fix` and keep `code`, `where`, `context` and a\n * docs URL. `import '@datakable/core/messages'` once (e.g. in the app entry) installs the text of\n * every code a production build can emit. Development builds already have it. This module is the\n * package's only side effect (`sideEffects` in package.json).\n */\nimport { optionMessages } from '../catalog/codes'\nimport { installMessages } from '../diagnostics/catalog'\nimport { coreMessages } from '../diagnostics/codes'\nimport { proseMessages } from '../diagnostics/prose'\nimport { redactionMessages } from '../diagnostics/redact'\nimport { featureMessages } from '../feature/codes'\nimport { columnFiltersMessages } from '../features/column-filters/codes'\nimport { paginationMessages } from '../features/pagination/codes'\nimport { searchMessages } from '../features/search/codes'\nimport { sortingMessages } from '../features/sorting/codes'\nimport { validityMessages } from '../features/validity/codes'\nimport { dataCheckMessages } from '../ingest/data-check-codes'\nimport { rowKeyMessages } from '../ingest/row-key-codes'\nimport { schemaMessages } from '../ingest/schema-codes'\nimport { boundaryMessages } from '../intercept/codes'\nimport { pipelineMessages } from '../pipeline/codes'\nimport { envMessages } from '../pipeline/env-codes'\nimport { asyncMessages } from '../source/codes'\nimport { fetchMessages } from '../source/fetch-codes'\nimport { tableMessages } from '../table/codes'\nimport { ssrMessages } from '../table/ssr-codes'\nimport { stateMessages } from '../table/state-codes'\nimport { versioningMessages } from '../versioning/codes'\n\n/** Every message object core ships, one per module that owns codes. */\nexport const allMessages: ReadonlyArray<Readonly<Record<string, unknown>>> = [\n coreMessages,\n redactionMessages,\n optionMessages,\n featureMessages,\n boundaryMessages,\n pipelineMessages,\n tableMessages,\n ssrMessages,\n stateMessages,\n asyncMessages,\n fetchMessages,\n rowKeyMessages,\n schemaMessages,\n dataCheckMessages,\n versioningMessages,\n columnFiltersMessages,\n validityMessages,\n searchMessages,\n sortingMessages,\n paginationMessages,\n envMessages,\n // The detail sentences production keeps as keys (`fallback: 'cells-undefined'`).\n proseMessages,\n]\n\ninstallMessages(...allMessages)\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAQA,mBAA+B;AAC/B,qBAAgC;AAChC,IAAAA,gBAA6B;AAC7B,mBAA8B;AAC9B,oBAAkC;AAClC,IAAAA,gBAAgC;AAChC,IAAAA,gBAAsC;AACtC,IAAAA,gBAAmC;AACnC,IAAAA,gBAA+B;AAC/B,IAAAA,gBAAgC;AAChC,IAAAA,gBAAiC;AACjC,8BAAkC;AAClC,2BAA+B;AAC/B,0BAA+B;AAC/B,IAAAA,gBAAiC;AACjC,IAAAA,iBAAiC;AACjC,uBAA4B;AAC5B,IAAAA,iBAA8B;AAC9B,yBAA8B;AAC9B,IAAAA,iBAA8B;AAC9B,uBAA4B;AAC5B,yBAA8B;AAC9B,IAAAA,iBAAmC;AAG5B,IAAM,cAAgE;AAAA,EAC3E;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AACF;AAAA,IAEA,gCAAgB,GAAG,WAAW;","names":["import_codes"]}
|