@datakable/core 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -2
- package/dist/catalog/codes.cjs +12 -8
- package/dist/catalog/codes.cjs.map +1 -1
- package/dist/catalog/codes.js +12 -8
- package/dist/catalog/codes.js.map +1 -1
- package/dist/catalog/slots.cjs +10 -6
- package/dist/catalog/slots.cjs.map +1 -1
- package/dist/catalog/slots.js +10 -6
- package/dist/catalog/slots.js.map +1 -1
- package/dist/{codes-BKdS9EiO.d.cts → codes-B9bCK73-.d.cts} +46 -8
- package/dist/{codes-BKdS9EiO.d.ts → codes-B9bCK73-.d.ts} +46 -8
- package/dist/column/column-def.cjs.map +1 -1
- package/dist/column/get-value.cjs +6 -1
- package/dist/column/get-value.cjs.map +1 -1
- package/dist/column/get-value.js +6 -1
- package/dist/column/get-value.js.map +1 -1
- package/dist/column-filters.d.cts +2 -2
- package/dist/column-filters.d.ts +2 -2
- package/dist/diagnostics/build.cjs +10 -4
- package/dist/diagnostics/build.cjs.map +1 -1
- package/dist/diagnostics/build.js +8 -3
- package/dist/diagnostics/build.js.map +1 -1
- package/dist/diagnostics/catalog.cjs +11 -5
- package/dist/diagnostics/catalog.cjs.map +1 -1
- package/dist/diagnostics/catalog.js +10 -5
- package/dist/diagnostics/catalog.js.map +1 -1
- package/dist/diagnostics/codes.cjs +12 -8
- package/dist/diagnostics/codes.cjs.map +1 -1
- package/dist/diagnostics/codes.js +12 -8
- package/dist/diagnostics/codes.js.map +1 -1
- package/dist/diagnostics/console.cjs +13 -6
- package/dist/diagnostics/console.cjs.map +1 -1
- package/dist/diagnostics/console.js +13 -6
- package/dist/diagnostics/console.js.map +1 -1
- package/dist/diagnostics/env.cjs +1 -0
- package/dist/diagnostics/env.cjs.map +1 -1
- package/dist/diagnostics/env.js +1 -0
- package/dist/diagnostics/env.js.map +1 -1
- package/dist/diagnostics/explain-text.cjs +2 -1
- package/dist/diagnostics/explain-text.cjs.map +1 -1
- package/dist/diagnostics/explain-text.js +2 -1
- package/dist/diagnostics/explain-text.js.map +1 -1
- package/dist/diagnostics/explain.cjs +3 -2
- package/dist/diagnostics/explain.cjs.map +1 -1
- package/dist/diagnostics/explain.js +3 -2
- package/dist/diagnostics/explain.js.map +1 -1
- package/dist/diagnostics/hub.cjs +6 -5
- package/dist/diagnostics/hub.cjs.map +1 -1
- package/dist/diagnostics/hub.js +7 -6
- package/dist/diagnostics/hub.js.map +1 -1
- package/dist/diagnostics/process-guard.cjs +26 -0
- package/dist/diagnostics/process-guard.cjs.map +1 -0
- package/dist/diagnostics/process-guard.js +9 -0
- package/dist/diagnostics/process-guard.js.map +1 -0
- package/dist/diagnostics/prose.cjs +120 -0
- package/dist/diagnostics/prose.cjs.map +1 -0
- package/dist/diagnostics/prose.js +93 -0
- package/dist/diagnostics/prose.js.map +1 -0
- package/dist/diagnostics/redact.cjs +7 -4
- package/dist/diagnostics/redact.cjs.map +1 -1
- package/dist/diagnostics/redact.js +6 -4
- package/dist/diagnostics/redact.js.map +1 -1
- package/dist/diagnostics/trace-store.cjs +6 -0
- package/dist/diagnostics/trace-store.cjs.map +1 -1
- package/dist/diagnostics/trace-store.js +4 -0
- package/dist/diagnostics/trace-store.js.map +1 -1
- package/dist/diagnostics/tracer.cjs +74 -13
- package/dist/diagnostics/tracer.cjs.map +1 -1
- package/dist/diagnostics/tracer.js +75 -14
- package/dist/diagnostics/tracer.js.map +1 -1
- package/dist/diagnostics/types.cjs.map +1 -1
- package/dist/{explain-aagaYHcy.d.cts → explain-Q8Cg0cZy.d.cts} +13 -4
- package/dist/{explain-DcUZfFh5.d.ts → explain-i0OATi_W.d.ts} +13 -4
- package/dist/feature/codes.cjs +1 -0
- package/dist/feature/codes.cjs.map +1 -1
- package/dist/feature/codes.js +1 -0
- package/dist/feature/codes.js.map +1 -1
- package/dist/feature/define.cjs +3 -1
- package/dist/feature/define.cjs.map +1 -1
- package/dist/feature/define.js +3 -1
- package/dist/feature/define.js.map +1 -1
- package/dist/feature/install.cjs +4 -3
- package/dist/feature/install.cjs.map +1 -1
- package/dist/feature/install.js +4 -3
- package/dist/feature/install.js.map +1 -1
- package/dist/feature/runtime.cjs.map +1 -1
- package/dist/feature/runtime.js.map +1 -1
- package/dist/features/column-filters/codes.cjs +1 -0
- package/dist/features/column-filters/codes.cjs.map +1 -1
- package/dist/features/column-filters/codes.js +1 -0
- package/dist/features/column-filters/codes.js.map +1 -1
- package/dist/features/column-filters/column-filters.cjs +4 -2
- package/dist/features/column-filters/column-filters.cjs.map +1 -1
- package/dist/features/column-filters/column-filters.js +4 -2
- package/dist/features/column-filters/column-filters.js.map +1 -1
- package/dist/features/column-filters/match.cjs +5 -5
- package/dist/features/column-filters/match.cjs.map +1 -1
- package/dist/features/column-filters/match.js +5 -5
- package/dist/features/column-filters/match.js.map +1 -1
- package/dist/features/pagination/codes.cjs +6 -3
- package/dist/features/pagination/codes.cjs.map +1 -1
- package/dist/features/pagination/codes.js +6 -3
- package/dist/features/pagination/codes.js.map +1 -1
- package/dist/features/pagination/pagination.cjs +19 -14
- package/dist/features/pagination/pagination.cjs.map +1 -1
- package/dist/features/pagination/pagination.js +19 -14
- package/dist/features/pagination/pagination.js.map +1 -1
- package/dist/features/search/codes.cjs +1 -0
- package/dist/features/search/codes.cjs.map +1 -1
- package/dist/features/search/codes.js +1 -0
- package/dist/features/search/codes.js.map +1 -1
- package/dist/features/search/search-index.cjs +105 -48
- package/dist/features/search/search-index.cjs.map +1 -1
- package/dist/features/search/search-index.js +106 -49
- package/dist/features/search/search-index.js.map +1 -1
- package/dist/features/search/search.cjs +82 -24
- package/dist/features/search/search.cjs.map +1 -1
- package/dist/features/search/search.js +82 -24
- package/dist/features/search/search.js.map +1 -1
- package/dist/features/search/skipped-codes.cjs +45 -0
- package/dist/features/search/skipped-codes.cjs.map +1 -0
- package/dist/features/search/skipped-codes.js +20 -0
- package/dist/features/search/skipped-codes.js.map +1 -0
- package/dist/features/sorting/codes.cjs +1 -0
- package/dist/features/sorting/codes.cjs.map +1 -1
- package/dist/features/sorting/codes.js +1 -0
- package/dist/features/sorting/codes.js.map +1 -1
- package/dist/features/sorting/sorting.cjs +19 -23
- package/dist/features/sorting/sorting.cjs.map +1 -1
- package/dist/features/sorting/sorting.js +19 -23
- package/dist/features/sorting/sorting.js.map +1 -1
- package/dist/features/sorting/strategy.cjs +4 -4
- package/dist/features/sorting/strategy.cjs.map +1 -1
- package/dist/features/sorting/strategy.js +4 -4
- package/dist/features/sorting/strategy.js.map +1 -1
- package/dist/features/validity/codes.cjs +1 -0
- package/dist/features/validity/codes.cjs.map +1 -1
- package/dist/features/validity/codes.js +1 -0
- package/dist/features/validity/codes.js.map +1 -1
- package/dist/features/validity/validity.cjs +3 -3
- package/dist/features/validity/validity.cjs.map +1 -1
- package/dist/features/validity/validity.js +3 -3
- package/dist/features/validity/validity.js.map +1 -1
- package/dist/index.d.cts +16 -11
- package/dist/index.d.ts +16 -11
- package/dist/ingest/data-check-codes.cjs +4 -2
- package/dist/ingest/data-check-codes.cjs.map +1 -1
- package/dist/ingest/data-check-codes.js +4 -2
- package/dist/ingest/data-check-codes.js.map +1 -1
- package/dist/ingest/data-checks.cjs +1 -1
- package/dist/ingest/data-checks.cjs.map +1 -1
- package/dist/ingest/data-checks.js +1 -1
- package/dist/ingest/data-checks.js.map +1 -1
- package/dist/ingest/row-key-codes.cjs +1 -0
- package/dist/ingest/row-key-codes.cjs.map +1 -1
- package/dist/ingest/row-key-codes.js +1 -0
- package/dist/ingest/row-key-codes.js.map +1 -1
- package/dist/ingest/row-key.cjs +23 -20
- package/dist/ingest/row-key.cjs.map +1 -1
- package/dist/ingest/row-key.js +23 -20
- package/dist/ingest/row-key.js.map +1 -1
- package/dist/ingest/schema-codes.cjs +1 -0
- package/dist/ingest/schema-codes.cjs.map +1 -1
- package/dist/ingest/schema-codes.js +1 -0
- package/dist/ingest/schema-codes.js.map +1 -1
- package/dist/ingest/unique-fields.cjs +2 -2
- package/dist/ingest/unique-fields.cjs.map +1 -1
- package/dist/ingest/unique-fields.js +2 -2
- package/dist/ingest/unique-fields.js.map +1 -1
- package/dist/intercept/boundary.cjs +4 -2
- package/dist/intercept/boundary.cjs.map +1 -1
- package/dist/intercept/boundary.js +4 -2
- package/dist/intercept/boundary.js.map +1 -1
- package/dist/intercept/cell-batch.cjs +7 -4
- package/dist/intercept/cell-batch.cjs.map +1 -1
- package/dist/intercept/cell-batch.js +7 -4
- package/dist/intercept/cell-batch.js.map +1 -1
- package/dist/intercept/codes.cjs +1 -0
- package/dist/intercept/codes.cjs.map +1 -1
- package/dist/intercept/codes.js +1 -0
- package/dist/intercept/codes.js.map +1 -1
- package/dist/intercept/fallbacks.cjs +12 -20
- package/dist/intercept/fallbacks.cjs.map +1 -1
- package/dist/intercept/fallbacks.js +12 -20
- package/dist/intercept/fallbacks.js.map +1 -1
- package/dist/intercept/runtime.cjs +7 -9
- package/dist/intercept/runtime.cjs.map +1 -1
- package/dist/intercept/runtime.js +7 -9
- package/dist/intercept/runtime.js.map +1 -1
- package/dist/messages/index.cjs +4 -1
- package/dist/messages/index.cjs.map +1 -1
- package/dist/messages/index.js +4 -1
- package/dist/messages/index.js.map +1 -1
- package/dist/pagination.d.cts +2 -2
- package/dist/pagination.d.ts +2 -2
- package/dist/pipeline/codes.cjs +1 -0
- package/dist/pipeline/codes.cjs.map +1 -1
- package/dist/pipeline/codes.js +1 -0
- package/dist/pipeline/codes.js.map +1 -1
- package/dist/pipeline/column-cache.cjs +94 -76
- package/dist/pipeline/column-cache.cjs.map +1 -1
- package/dist/pipeline/column-cache.js +92 -75
- package/dist/pipeline/column-cache.js.map +1 -1
- package/dist/pipeline/dev-checks.cjs +1 -0
- package/dist/pipeline/dev-checks.cjs.map +1 -1
- package/dist/pipeline/dev-checks.js +1 -0
- package/dist/pipeline/dev-checks.js.map +1 -1
- package/dist/pipeline/env-codes.cjs +3 -2
- package/dist/pipeline/env-codes.cjs.map +1 -1
- package/dist/pipeline/env-codes.js +3 -2
- package/dist/pipeline/env-codes.js.map +1 -1
- package/dist/pipeline/perf-codes.cjs +1 -0
- package/dist/pipeline/perf-codes.cjs.map +1 -1
- package/dist/pipeline/perf-codes.js +1 -0
- package/dist/pipeline/perf-codes.js.map +1 -1
- package/dist/pipeline/row.cjs +8 -7
- package/dist/pipeline/row.cjs.map +1 -1
- package/dist/pipeline/row.js +8 -7
- package/dist/pipeline/row.js.map +1 -1
- package/dist/pipeline/runner.cjs +17 -9
- package/dist/pipeline/runner.cjs.map +1 -1
- package/dist/pipeline/runner.js +17 -9
- package/dist/pipeline/runner.js.map +1 -1
- package/dist/pipeline/slice.cjs +3 -1
- package/dist/pipeline/slice.cjs.map +1 -1
- package/dist/pipeline/slice.js +3 -1
- package/dist/pipeline/slice.js.map +1 -1
- package/dist/schema.d.cts +2 -2
- package/dist/schema.d.ts +2 -2
- package/dist/{search-async-entry-C3mXxLP8.d.cts → search-async-entry-CuLYPfY_.d.cts} +2 -2
- package/dist/{search-async-entry-BmQYT120.d.ts → search-async-entry-Cx7xpuVZ.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 +8 -6
- package/dist/search.d.ts +8 -6
- package/dist/server.d.cts +3 -3
- package/dist/server.d.ts +3 -3
- package/dist/sorting.d.cts +6 -3
- package/dist/sorting.d.ts +6 -3
- package/dist/source/codes.cjs +1 -0
- package/dist/source/codes.cjs.map +1 -1
- package/dist/source/codes.js +1 -0
- package/dist/source/codes.js.map +1 -1
- package/dist/source/fetch-codes.cjs +1 -0
- package/dist/source/fetch-codes.cjs.map +1 -1
- package/dist/source/fetch-codes.js +1 -0
- package/dist/source/fetch-codes.js.map +1 -1
- package/dist/table/codes.cjs +1 -0
- package/dist/table/codes.cjs.map +1 -1
- package/dist/table/codes.js +1 -0
- package/dist/table/codes.js.map +1 -1
- package/dist/table/create-table.cjs +39 -9
- package/dist/table/create-table.cjs.map +1 -1
- package/dist/table/create-table.js +39 -9
- package/dist/table/create-table.js.map +1 -1
- package/dist/table/data-mutation.cjs +1 -0
- package/dist/table/data-mutation.cjs.map +1 -1
- package/dist/table/data-mutation.js +1 -0
- package/dist/table/data-mutation.js.map +1 -1
- package/dist/table/internals.cjs.map +1 -1
- package/dist/table/internals.js.map +1 -1
- package/dist/table/ssr-codes.cjs +1 -0
- package/dist/table/ssr-codes.cjs.map +1 -1
- package/dist/table/ssr-codes.js +1 -0
- package/dist/table/ssr-codes.js.map +1 -1
- package/dist/table/ssr.cjs +4 -1
- package/dist/table/ssr.cjs.map +1 -1
- package/dist/table/ssr.js +4 -1
- package/dist/table/ssr.js.map +1 -1
- package/dist/table/state-feedback.cjs +19 -0
- package/dist/table/state-feedback.cjs.map +1 -1
- package/dist/table/state-feedback.js +19 -0
- package/dist/table/state-feedback.js.map +1 -1
- 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/dist/versioning/codes.cjs +18 -0
- package/dist/versioning/codes.cjs.map +1 -1
- package/dist/versioning/codes.js +18 -0
- package/dist/versioning/codes.js.map +1 -1
- package/dist/versioning/registry.cjs +4 -2
- package/dist/versioning/registry.cjs.map +1 -1
- package/dist/versioning/registry.js +4 -2
- package/dist/versioning/registry.js.map +1 -1
- package/package.json +39 -3
|
@@ -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 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\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 /** Locale(s) of the string collator (`Intl.Collator(locale, { numeric: true })`); default: the runtime's. */\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 as string | string[] | undefined\n let supported = true\n try {\n collator = new Intl.Collator(locale, { numeric: true })\n supported = locale === undefined || 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: `the runtime's collation for \"${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) => ctx.setState({ by: by.slice() }),\n clearSorting: () => ctx.setState({ by: [] }),\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(\n `${JSON.stringify(requested)} is not a sort algorithm (accepted: ${ALGORITHMS.join(', ')}, ` +\n 'or a function); auto was used',\n )\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('the custom algorithm 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('the custom algorithm returned a bad value')\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 = `${by}, safe-integer keys`\n return out\n } catch {\n noEffect(\n `exsorted ${want}Sort could not sort these keys` +\n (want === 'counting' ? ' (key range above 1,000,000)' : '') +\n '; auto was used',\n )\n }\n } else if (needsIntKeys(want)) {\n noEffect(\n `${want} sorts a single column of safe integer keys (numbers or Dates, no sortFn); ` +\n 'auto was used',\n )\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\n ? 'keys are not all safe integers'\n : entries.length > 1\n ? 'multi-column'\n : 'custom sortFn',\n )\n }\n const choice = chooseAuto(keys)\n algorithm = choice.algorithm\n reason = `auto: ${ranked ? 'collation ranks of a string column, ' : ''}${choice.reason}`\n return sortIntKeys(keys, choice.algorithm)\n }\n const native = (why: string) => {\n algorithm = 'native'\n reason = ranked ? `${why}, strings as collation ranks` : 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 = 'the rows were sorted with the native algorithm'\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: 'the column was sorted with the default comparator',\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 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"]}
|
|
@@ -85,13 +85,13 @@ function chooseAuto(k) {
|
|
|
85
85
|
const m = k.present;
|
|
86
86
|
const range = m > 0 ? k.max - k.min + 1 : 0;
|
|
87
87
|
if (k.descents * 64 <= m) {
|
|
88
|
-
return { algorithm: "tim", reason: `
|
|
88
|
+
return { algorithm: "tim", reason: `nearly|${k.descents}` };
|
|
89
89
|
}
|
|
90
90
|
if (range <= 4 * m && range <= COUNTING_MAX_RANGE) {
|
|
91
|
-
return { algorithm: "counting", reason: `
|
|
91
|
+
return { algorithm: "counting", reason: `range|${range}` };
|
|
92
92
|
}
|
|
93
|
-
if (m >= 1e4) return { algorithm: "radix", reason:
|
|
94
|
-
return { algorithm: "tim", reason: "
|
|
93
|
+
if (m >= 1e4) return { algorithm: "radix", reason: "wide" };
|
|
94
|
+
return { algorithm: "tim", reason: "wide-small" };
|
|
95
95
|
}
|
|
96
96
|
function sortIntKeys(k, algorithm) {
|
|
97
97
|
const { rows, present, keys } = k;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/features/sorting/strategy.ts"],"sourcesContent":["import { countingSort } from 'exsorted/counting'\nimport { radixSort } from 'exsorted/radix'\nimport { timSort } from 'exsorted/tim'\nimport type { ColumnValues } from '../../pipeline/types'\nimport type { IndexComparator } from './compare'\n\n/** The built-in algorithms of `sorting({ algorithm })` / a column's `sortAlgorithm` (§6.4). */\nexport type BuiltinAlgorithm = 'tim' | 'radix' | 'counting' | 'native'\n\n/** Algorithms that need safe-integer keys (they ignore comparators). */\nexport const needsIntKeys = (a: string) => a === 'radix' || a === 'counting'\n\n/**\n * exsorted's `countingSort` refuses a key range above this (it throws `RangeError`); `auto` never\n * picks it beyond.\n */\nconst COUNTING_MAX_RANGE = 1_000_000\n\n/**\n * The integer keys of a single-column sort, from one O(n) scan over the input indices (§6.4).\n * Rows with a missing key (`null`, `undefined`, `NaN`, invalid `Date`) are split off: they go last\n * in input order whatever the direction.\n */\nexport interface IntKeys {\n /** `rows[0..present)`: rows with a key, in input order; `rows[present..)`: missing, reversed. */\n readonly rows: Uint32Array\n readonly present: number\n /** `keys[p]`: the key of `rows[p]`, negated for `desc` (ascending order of keys = output order). */\n readonly keys: Float64Array\n readonly min: number\n readonly max: number\n /** Adjacent pairs out of order (`keys[p] < keys[p - 1]`). */\n readonly descents: number\n}\n\n/**\n * Scans `values` at `indices`: every non-missing key must be a safe integer of one kind (numbers,\n * or `Date`s by `getTime()`), else `undefined` (the caller sorts with a comparator). Stops at the\n * first non-integer, so strings and floats cost one read.\n */\nexport function intKeys(\n values: ColumnValues,\n indices: Uint32Array,\n desc: boolean,\n): IntKeys | undefined {\n const n = indices.length\n const numeric = values instanceof Float64Array\n const rows = new Uint32Array(n)\n const keys = new Float64Array(n)\n const sign = desc ? -1 : 1\n let present = 0\n let back = n\n let kind = 0 // 1 = number, 2 = Date\n let min = Number.POSITIVE_INFINITY\n let max = Number.NEGATIVE_INFINITY\n let descents = 0\n let prev = 0\n for (let i = 0; i < n; i++) {\n const r = indices[i] as number\n let k: number\n if (numeric) {\n k = values[r] as number\n } else {\n const v = (values as readonly unknown[])[r]\n if (typeof v === 'number') {\n if (kind === 2) return undefined\n kind = 1\n k = v\n } else if (v instanceof Date) {\n if (kind === 1) return undefined\n kind = 2\n k = v.getTime()\n } else if (v === null || v === undefined) {\n rows[--back] = r\n continue\n } else return undefined\n }\n if (Number.isNaN(k)) {\n rows[--back] = r\n continue\n }\n if (!Number.isSafeInteger(k)) return undefined\n k *= sign\n if (k < min) min = k\n if (k > max) max = k\n if (present > 0 && k < prev) descents++\n prev = k\n rows[present] = r\n keys[present++] = k\n }\n return { rows, present, keys, min, max, descents }\n}\n\n
|
|
1
|
+
{"version":3,"sources":["../../../src/features/sorting/strategy.ts"],"sourcesContent":["import { countingSort } from 'exsorted/counting'\nimport { radixSort } from 'exsorted/radix'\nimport { timSort } from 'exsorted/tim'\nimport type { ColumnValues } from '../../pipeline/types'\nimport type { IndexComparator } from './compare'\n\n/** The built-in algorithms of `sorting({ algorithm })` / a column's `sortAlgorithm` (§6.4). */\nexport type BuiltinAlgorithm = 'tim' | 'radix' | 'counting' | 'native'\n\n/** Algorithms that need safe-integer keys (they ignore comparators). */\nexport const needsIntKeys = (a: string) => a === 'radix' || a === 'counting'\n\n/**\n * exsorted's `countingSort` refuses a key range above this (it throws `RangeError`); `auto` never\n * picks it beyond.\n */\nconst COUNTING_MAX_RANGE = 1_000_000\n\n/**\n * The integer keys of a single-column sort, from one O(n) scan over the input indices (§6.4).\n * Rows with a missing key (`null`, `undefined`, `NaN`, invalid `Date`) are split off: they go last\n * in input order whatever the direction.\n */\nexport interface IntKeys {\n /** `rows[0..present)`: rows with a key, in input order; `rows[present..)`: missing, reversed. */\n readonly rows: Uint32Array\n readonly present: number\n /** `keys[p]`: the key of `rows[p]`, negated for `desc` (ascending order of keys = output order). */\n readonly keys: Float64Array\n readonly min: number\n readonly max: number\n /** Adjacent pairs out of order (`keys[p] < keys[p - 1]`). */\n readonly descents: number\n}\n\n/**\n * Scans `values` at `indices`: every non-missing key must be a safe integer of one kind (numbers,\n * or `Date`s by `getTime()`), else `undefined` (the caller sorts with a comparator). Stops at the\n * first non-integer, so strings and floats cost one read.\n */\nexport function intKeys(\n values: ColumnValues,\n indices: Uint32Array,\n desc: boolean,\n): IntKeys | undefined {\n const n = indices.length\n const numeric = values instanceof Float64Array\n const rows = new Uint32Array(n)\n const keys = new Float64Array(n)\n const sign = desc ? -1 : 1\n let present = 0\n let back = n\n let kind = 0 // 1 = number, 2 = Date\n let min = Number.POSITIVE_INFINITY\n let max = Number.NEGATIVE_INFINITY\n let descents = 0\n let prev = 0\n for (let i = 0; i < n; i++) {\n const r = indices[i] as number\n let k: number\n if (numeric) {\n k = values[r] as number\n } else {\n const v = (values as readonly unknown[])[r]\n if (typeof v === 'number') {\n if (kind === 2) return undefined\n kind = 1\n k = v\n } else if (v instanceof Date) {\n if (kind === 1) return undefined\n kind = 2\n k = v.getTime()\n } else if (v === null || v === undefined) {\n rows[--back] = r\n continue\n } else return undefined\n }\n if (Number.isNaN(k)) {\n rows[--back] = r\n continue\n }\n if (!Number.isSafeInteger(k)) return undefined\n k *= sign\n if (k < min) min = k\n if (k > max) max = k\n if (present > 0 && k < prev) descents++\n prev = k\n rows[present] = r\n keys[present++] = k\n }\n return { rows, present, keys, min, max, descents }\n}\n\n/**\n * `auto`'s choice for integer keys (§6.4 table), with the reason (DK_SORT_STRATEGY): the end of a\n * prose key, `auto-<reason>` (diagnostics/prose.ts).\n */\nexport function chooseAuto(k: IntKeys): { algorithm: BuiltinAlgorithm; reason: string } {\n const m = k.present\n const range = m > 0 ? k.max - k.min + 1 : 0\n // Nearly sorted: natural runs average ≥ 64 keys, so tim merges few runs (~O(n)).\n if (k.descents * 64 <= m) {\n return { algorithm: 'tim', reason: `nearly|${k.descents}` }\n }\n if (range <= 4 * m && range <= COUNTING_MAX_RANGE) {\n return { algorithm: 'counting', reason: `range|${range}` }\n }\n if (m >= 10_000) return { algorithm: 'radix', reason: 'wide' }\n return { algorithm: 'tim', reason: 'wide-small' }\n}\n\n/**\n * Sorts integer keys with `algorithm` (any built-in but `native`): exsorted works on a plain array\n * of positions (radix / counting require `Array.isArray`), never on the caller's indices. Missing\n * rows are appended in input order. exsorted throws on keys it cannot take (e.g. counting over a\n * range above 1e6): the caller falls back.\n */\nexport function sortIntKeys(k: IntKeys, algorithm: BuiltinAlgorithm): Uint32Array {\n const { rows, present, keys } = k\n const n = rows.length\n const pos = new Array<number>(present)\n for (let p = 0; p < present; p++) pos[p] = p\n const key = (p: number) => keys[p] as number\n const cmp = (a: number, b: number) => (keys[a] as number) - (keys[b] as number)\n const order =\n algorithm === 'radix'\n ? radixSort(pos, key)\n : algorithm === 'counting'\n ? countingSort(pos, key)\n : algorithm === 'tim'\n ? timSort(pos, cmp)\n : pos.sort(cmp)\n const out = new Uint32Array(n)\n for (let j = 0; j < present; j++) out[j] = rows[order[j] as number] as number\n for (let j = present, b = n - 1; j < n; j++, b--) out[j] = rows[b] as number\n return out\n}\n\n/** Sorts a copy of `indices` with a comparator: native, or exsorted tim (stable). */\nexport function sortWithComparator(\n indices: Uint32Array,\n cmp: IndexComparator,\n algorithm: 'tim' | 'native',\n): Uint32Array {\n if (algorithm === 'native') return indices.slice().sort(cmp)\n return Uint32Array.from(timSort(Array.from(indices), cmp))\n}\n\n/** exsorted's algorithms are usable (§8.5): checked once per feature instance. */\nexport const hasExsorted = () =>\n typeof timSort === 'function' &&\n typeof radixSort === 'function' &&\n typeof countingSort === 'function'\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sBAA6B;AAC7B,mBAA0B;AAC1B,iBAAwB;AAQjB,IAAM,eAAe,CAAC,MAAc,MAAM,WAAW,MAAM;AAMlE,IAAM,qBAAqB;AAwBpB,SAAS,QACd,QACA,SACA,MACqB;AACrB,QAAM,IAAI,QAAQ;AAClB,QAAM,UAAU,kBAAkB;AAClC,QAAM,OAAO,IAAI,YAAY,CAAC;AAC9B,QAAM,OAAO,IAAI,aAAa,CAAC;AAC/B,QAAM,OAAO,OAAO,KAAK;AACzB,MAAI,UAAU;AACd,MAAI,OAAO;AACX,MAAI,OAAO;AACX,MAAI,MAAM,OAAO;AACjB,MAAI,MAAM,OAAO;AACjB,MAAI,WAAW;AACf,MAAI,OAAO;AACX,WAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,UAAM,IAAI,QAAQ,CAAC;AACnB,QAAI;AACJ,QAAI,SAAS;AACX,UAAI,OAAO,CAAC;AAAA,IACd,OAAO;AACL,YAAM,IAAK,OAA8B,CAAC;AAC1C,UAAI,OAAO,MAAM,UAAU;AACzB,YAAI,SAAS,EAAG,QAAO;AACvB,eAAO;AACP,YAAI;AAAA,MACN,WAAW,aAAa,MAAM;AAC5B,YAAI,SAAS,EAAG,QAAO;AACvB,eAAO;AACP,YAAI,EAAE,QAAQ;AAAA,MAChB,WAAW,MAAM,QAAQ,MAAM,QAAW;AACxC,aAAK,EAAE,IAAI,IAAI;AACf;AAAA,MACF,MAAO,QAAO;AAAA,IAChB;AACA,QAAI,OAAO,MAAM,CAAC,GAAG;AACnB,WAAK,EAAE,IAAI,IAAI;AACf;AAAA,IACF;AACA,QAAI,CAAC,OAAO,cAAc,CAAC,EAAG,QAAO;AACrC,SAAK;AACL,QAAI,IAAI,IAAK,OAAM;AACnB,QAAI,IAAI,IAAK,OAAM;AACnB,QAAI,UAAU,KAAK,IAAI,KAAM;AAC7B,WAAO;AACP,SAAK,OAAO,IAAI;AAChB,SAAK,SAAS,IAAI;AAAA,EACpB;AACA,SAAO,EAAE,MAAM,SAAS,MAAM,KAAK,KAAK,SAAS;AACnD;AAMO,SAAS,WAAW,GAA6D;AACtF,QAAM,IAAI,EAAE;AACZ,QAAM,QAAQ,IAAI,IAAI,EAAE,MAAM,EAAE,MAAM,IAAI;AAE1C,MAAI,EAAE,WAAW,MAAM,GAAG;AACxB,WAAO,EAAE,WAAW,OAAO,QAAQ,UAAU,EAAE,QAAQ,GAAG;AAAA,EAC5D;AACA,MAAI,SAAS,IAAI,KAAK,SAAS,oBAAoB;AACjD,WAAO,EAAE,WAAW,YAAY,QAAQ,SAAS,KAAK,GAAG;AAAA,EAC3D;AACA,MAAI,KAAK,IAAQ,QAAO,EAAE,WAAW,SAAS,QAAQ,OAAO;AAC7D,SAAO,EAAE,WAAW,OAAO,QAAQ,aAAa;AAClD;AAQO,SAAS,YAAY,GAAY,WAA0C;AAChF,QAAM,EAAE,MAAM,SAAS,KAAK,IAAI;AAChC,QAAM,IAAI,KAAK;AACf,QAAM,MAAM,IAAI,MAAc,OAAO;AACrC,WAAS,IAAI,GAAG,IAAI,SAAS,IAAK,KAAI,CAAC,IAAI;AAC3C,QAAM,MAAM,CAAC,MAAc,KAAK,CAAC;AACjC,QAAM,MAAM,CAAC,GAAW,MAAe,KAAK,CAAC,IAAgB,KAAK,CAAC;AACnE,QAAM,QACJ,cAAc,cACV,wBAAU,KAAK,GAAG,IAClB,cAAc,iBACZ,8BAAa,KAAK,GAAG,IACrB,cAAc,YACZ,oBAAQ,KAAK,GAAG,IAChB,IAAI,KAAK,GAAG;AACtB,QAAM,MAAM,IAAI,YAAY,CAAC;AAC7B,WAAS,IAAI,GAAG,IAAI,SAAS,IAAK,KAAI,CAAC,IAAI,KAAK,MAAM,CAAC,CAAW;AAClE,WAAS,IAAI,SAAS,IAAI,IAAI,GAAG,IAAI,GAAG,KAAK,IAAK,KAAI,CAAC,IAAI,KAAK,CAAC;AACjE,SAAO;AACT;AAGO,SAAS,mBACd,SACA,KACA,WACa;AACb,MAAI,cAAc,SAAU,QAAO,QAAQ,MAAM,EAAE,KAAK,GAAG;AAC3D,SAAO,YAAY,SAAK,oBAAQ,MAAM,KAAK,OAAO,GAAG,GAAG,CAAC;AAC3D;AAGO,IAAM,cAAc,MACzB,OAAO,uBAAY,cACnB,OAAO,2BAAc,cACrB,OAAO,iCAAiB;","names":[]}
|
|
@@ -56,13 +56,13 @@ function chooseAuto(k) {
|
|
|
56
56
|
const m = k.present;
|
|
57
57
|
const range = m > 0 ? k.max - k.min + 1 : 0;
|
|
58
58
|
if (k.descents * 64 <= m) {
|
|
59
|
-
return { algorithm: "tim", reason: `
|
|
59
|
+
return { algorithm: "tim", reason: `nearly|${k.descents}` };
|
|
60
60
|
}
|
|
61
61
|
if (range <= 4 * m && range <= COUNTING_MAX_RANGE) {
|
|
62
|
-
return { algorithm: "counting", reason: `
|
|
62
|
+
return { algorithm: "counting", reason: `range|${range}` };
|
|
63
63
|
}
|
|
64
|
-
if (m >= 1e4) return { algorithm: "radix", reason:
|
|
65
|
-
return { algorithm: "tim", reason: "
|
|
64
|
+
if (m >= 1e4) return { algorithm: "radix", reason: "wide" };
|
|
65
|
+
return { algorithm: "tim", reason: "wide-small" };
|
|
66
66
|
}
|
|
67
67
|
function sortIntKeys(k, algorithm) {
|
|
68
68
|
const { rows, present, keys } = k;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/features/sorting/strategy.ts"],"sourcesContent":["import { countingSort } from 'exsorted/counting'\nimport { radixSort } from 'exsorted/radix'\nimport { timSort } from 'exsorted/tim'\nimport type { ColumnValues } from '../../pipeline/types'\nimport type { IndexComparator } from './compare'\n\n/** The built-in algorithms of `sorting({ algorithm })` / a column's `sortAlgorithm` (§6.4). */\nexport type BuiltinAlgorithm = 'tim' | 'radix' | 'counting' | 'native'\n\n/** Algorithms that need safe-integer keys (they ignore comparators). */\nexport const needsIntKeys = (a: string) => a === 'radix' || a === 'counting'\n\n/**\n * exsorted's `countingSort` refuses a key range above this (it throws `RangeError`); `auto` never\n * picks it beyond.\n */\nconst COUNTING_MAX_RANGE = 1_000_000\n\n/**\n * The integer keys of a single-column sort, from one O(n) scan over the input indices (§6.4).\n * Rows with a missing key (`null`, `undefined`, `NaN`, invalid `Date`) are split off: they go last\n * in input order whatever the direction.\n */\nexport interface IntKeys {\n /** `rows[0..present)`: rows with a key, in input order; `rows[present..)`: missing, reversed. */\n readonly rows: Uint32Array\n readonly present: number\n /** `keys[p]`: the key of `rows[p]`, negated for `desc` (ascending order of keys = output order). */\n readonly keys: Float64Array\n readonly min: number\n readonly max: number\n /** Adjacent pairs out of order (`keys[p] < keys[p - 1]`). */\n readonly descents: number\n}\n\n/**\n * Scans `values` at `indices`: every non-missing key must be a safe integer of one kind (numbers,\n * or `Date`s by `getTime()`), else `undefined` (the caller sorts with a comparator). Stops at the\n * first non-integer, so strings and floats cost one read.\n */\nexport function intKeys(\n values: ColumnValues,\n indices: Uint32Array,\n desc: boolean,\n): IntKeys | undefined {\n const n = indices.length\n const numeric = values instanceof Float64Array\n const rows = new Uint32Array(n)\n const keys = new Float64Array(n)\n const sign = desc ? -1 : 1\n let present = 0\n let back = n\n let kind = 0 // 1 = number, 2 = Date\n let min = Number.POSITIVE_INFINITY\n let max = Number.NEGATIVE_INFINITY\n let descents = 0\n let prev = 0\n for (let i = 0; i < n; i++) {\n const r = indices[i] as number\n let k: number\n if (numeric) {\n k = values[r] as number\n } else {\n const v = (values as readonly unknown[])[r]\n if (typeof v === 'number') {\n if (kind === 2) return undefined\n kind = 1\n k = v\n } else if (v instanceof Date) {\n if (kind === 1) return undefined\n kind = 2\n k = v.getTime()\n } else if (v === null || v === undefined) {\n rows[--back] = r\n continue\n } else return undefined\n }\n if (Number.isNaN(k)) {\n rows[--back] = r\n continue\n }\n if (!Number.isSafeInteger(k)) return undefined\n k *= sign\n if (k < min) min = k\n if (k > max) max = k\n if (present > 0 && k < prev) descents++\n prev = k\n rows[present] = r\n keys[present++] = k\n }\n return { rows, present, keys, min, max, descents }\n}\n\n
|
|
1
|
+
{"version":3,"sources":["../../../src/features/sorting/strategy.ts"],"sourcesContent":["import { countingSort } from 'exsorted/counting'\nimport { radixSort } from 'exsorted/radix'\nimport { timSort } from 'exsorted/tim'\nimport type { ColumnValues } from '../../pipeline/types'\nimport type { IndexComparator } from './compare'\n\n/** The built-in algorithms of `sorting({ algorithm })` / a column's `sortAlgorithm` (§6.4). */\nexport type BuiltinAlgorithm = 'tim' | 'radix' | 'counting' | 'native'\n\n/** Algorithms that need safe-integer keys (they ignore comparators). */\nexport const needsIntKeys = (a: string) => a === 'radix' || a === 'counting'\n\n/**\n * exsorted's `countingSort` refuses a key range above this (it throws `RangeError`); `auto` never\n * picks it beyond.\n */\nconst COUNTING_MAX_RANGE = 1_000_000\n\n/**\n * The integer keys of a single-column sort, from one O(n) scan over the input indices (§6.4).\n * Rows with a missing key (`null`, `undefined`, `NaN`, invalid `Date`) are split off: they go last\n * in input order whatever the direction.\n */\nexport interface IntKeys {\n /** `rows[0..present)`: rows with a key, in input order; `rows[present..)`: missing, reversed. */\n readonly rows: Uint32Array\n readonly present: number\n /** `keys[p]`: the key of `rows[p]`, negated for `desc` (ascending order of keys = output order). */\n readonly keys: Float64Array\n readonly min: number\n readonly max: number\n /** Adjacent pairs out of order (`keys[p] < keys[p - 1]`). */\n readonly descents: number\n}\n\n/**\n * Scans `values` at `indices`: every non-missing key must be a safe integer of one kind (numbers,\n * or `Date`s by `getTime()`), else `undefined` (the caller sorts with a comparator). Stops at the\n * first non-integer, so strings and floats cost one read.\n */\nexport function intKeys(\n values: ColumnValues,\n indices: Uint32Array,\n desc: boolean,\n): IntKeys | undefined {\n const n = indices.length\n const numeric = values instanceof Float64Array\n const rows = new Uint32Array(n)\n const keys = new Float64Array(n)\n const sign = desc ? -1 : 1\n let present = 0\n let back = n\n let kind = 0 // 1 = number, 2 = Date\n let min = Number.POSITIVE_INFINITY\n let max = Number.NEGATIVE_INFINITY\n let descents = 0\n let prev = 0\n for (let i = 0; i < n; i++) {\n const r = indices[i] as number\n let k: number\n if (numeric) {\n k = values[r] as number\n } else {\n const v = (values as readonly unknown[])[r]\n if (typeof v === 'number') {\n if (kind === 2) return undefined\n kind = 1\n k = v\n } else if (v instanceof Date) {\n if (kind === 1) return undefined\n kind = 2\n k = v.getTime()\n } else if (v === null || v === undefined) {\n rows[--back] = r\n continue\n } else return undefined\n }\n if (Number.isNaN(k)) {\n rows[--back] = r\n continue\n }\n if (!Number.isSafeInteger(k)) return undefined\n k *= sign\n if (k < min) min = k\n if (k > max) max = k\n if (present > 0 && k < prev) descents++\n prev = k\n rows[present] = r\n keys[present++] = k\n }\n return { rows, present, keys, min, max, descents }\n}\n\n/**\n * `auto`'s choice for integer keys (§6.4 table), with the reason (DK_SORT_STRATEGY): the end of a\n * prose key, `auto-<reason>` (diagnostics/prose.ts).\n */\nexport function chooseAuto(k: IntKeys): { algorithm: BuiltinAlgorithm; reason: string } {\n const m = k.present\n const range = m > 0 ? k.max - k.min + 1 : 0\n // Nearly sorted: natural runs average ≥ 64 keys, so tim merges few runs (~O(n)).\n if (k.descents * 64 <= m) {\n return { algorithm: 'tim', reason: `nearly|${k.descents}` }\n }\n if (range <= 4 * m && range <= COUNTING_MAX_RANGE) {\n return { algorithm: 'counting', reason: `range|${range}` }\n }\n if (m >= 10_000) return { algorithm: 'radix', reason: 'wide' }\n return { algorithm: 'tim', reason: 'wide-small' }\n}\n\n/**\n * Sorts integer keys with `algorithm` (any built-in but `native`): exsorted works on a plain array\n * of positions (radix / counting require `Array.isArray`), never on the caller's indices. Missing\n * rows are appended in input order. exsorted throws on keys it cannot take (e.g. counting over a\n * range above 1e6): the caller falls back.\n */\nexport function sortIntKeys(k: IntKeys, algorithm: BuiltinAlgorithm): Uint32Array {\n const { rows, present, keys } = k\n const n = rows.length\n const pos = new Array<number>(present)\n for (let p = 0; p < present; p++) pos[p] = p\n const key = (p: number) => keys[p] as number\n const cmp = (a: number, b: number) => (keys[a] as number) - (keys[b] as number)\n const order =\n algorithm === 'radix'\n ? radixSort(pos, key)\n : algorithm === 'counting'\n ? countingSort(pos, key)\n : algorithm === 'tim'\n ? timSort(pos, cmp)\n : pos.sort(cmp)\n const out = new Uint32Array(n)\n for (let j = 0; j < present; j++) out[j] = rows[order[j] as number] as number\n for (let j = present, b = n - 1; j < n; j++, b--) out[j] = rows[b] as number\n return out\n}\n\n/** Sorts a copy of `indices` with a comparator: native, or exsorted tim (stable). */\nexport function sortWithComparator(\n indices: Uint32Array,\n cmp: IndexComparator,\n algorithm: 'tim' | 'native',\n): Uint32Array {\n if (algorithm === 'native') return indices.slice().sort(cmp)\n return Uint32Array.from(timSort(Array.from(indices), cmp))\n}\n\n/** exsorted's algorithms are usable (§8.5): checked once per feature instance. */\nexport const hasExsorted = () =>\n typeof timSort === 'function' &&\n typeof radixSort === 'function' &&\n typeof countingSort === 'function'\n"],"mappings":"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","names":[]}
|
|
@@ -25,6 +25,7 @@ __export(codes_exports, {
|
|
|
25
25
|
});
|
|
26
26
|
module.exports = __toCommonJS(codes_exports);
|
|
27
27
|
var import_catalog = require("../../diagnostics/catalog.cjs");
|
|
28
|
+
var import_process_guard = require("../../diagnostics/process-guard.cjs");
|
|
28
29
|
var ACCEPTED = "'all' | 'valid' | 'invalid'";
|
|
29
30
|
var validityMessages = {
|
|
30
31
|
DK_INVALID_VALIDITY: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/features/validity/codes.ts"],"sourcesContent":["import { type DiagnosticMessages, defineDiagnostic } from '../../diagnostics/catalog'\n\ndeclare module '../../diagnostics/catalog' {\n interface DiagnosticCatalog {\n DK_INVALID_VALIDITY: {\n /** The API method that received the value, or `'state'` for a slice written to the store. */\n source: 'setValidity' | 'state'\n /** A short constant (`\"broken\"`) or the value's type only. */\n received: string\n /** What was done instead. */\n fallback: string\n }\n }\n}\n\nconst ACCEPTED = \"'all' | 'valid' | 'invalid'\"\n\n/** Message text (§8.2): development builds, or production via `@datakable/core/messages`. */\nexport const validityMessages: DiagnosticMessages<'DK_INVALID_VALIDITY'> = {\n DK_INVALID_VALIDITY: {\n problem: (d) =>\n d.source === 'state'\n ? `the validity state is ${d.received}; it must be ${ACCEPTED}`\n : `setValidity() received ${d.received}; it must be ${ACCEPTED}`,\n impact: (d) => d.fallback,\n fix: (d) => [\n d.source === 'state'\n ? `write validity as ${ACCEPTED} (check initialState, setState and the controlled ` +\n 'options.state)'\n : `pass ${ACCEPTED} to setValidity()`,\n ],\n },\n}\n\n/** Codes owned by the `validity` feature (§6.2). */\nexport const validityDiagnostics = [\n defineDiagnostic(\n {\n code: 'DK_INVALID_VALIDITY',\n level: 'warn',\n where: (d) =>\n d.source === 'state'\n ? { kind: 'option', path: 'state.validity' }\n : { kind: 'operation', op: 'table.setValidity' },\n },\n (process.env.NODE_ENV !== \"production\") && validityMessages.DK_INVALID_VALIDITY,\n ),\n]\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAA0D;
|
|
1
|
+
{"version":3,"sources":["../../../src/features/validity/codes.ts"],"sourcesContent":["import { type DiagnosticMessages, defineDiagnostic } from '../../diagnostics/catalog'\nimport '../../diagnostics/process-guard'\n\ndeclare module '../../diagnostics/catalog' {\n interface DiagnosticCatalog {\n DK_INVALID_VALIDITY: {\n /** The API method that received the value, or `'state'` for a slice written to the store. */\n source: 'setValidity' | 'state'\n /** A short constant (`\"broken\"`) or the value's type only. */\n received: string\n /** What was done instead. */\n fallback: string\n }\n }\n}\n\nconst ACCEPTED = \"'all' | 'valid' | 'invalid'\"\n\n/** Message text (§8.2): development builds, or production via `@datakable/core/messages`. */\nexport const validityMessages: DiagnosticMessages<'DK_INVALID_VALIDITY'> = {\n DK_INVALID_VALIDITY: {\n problem: (d) =>\n d.source === 'state'\n ? `the validity state is ${d.received}; it must be ${ACCEPTED}`\n : `setValidity() received ${d.received}; it must be ${ACCEPTED}`,\n impact: (d) => d.fallback,\n fix: (d) => [\n d.source === 'state'\n ? `write validity as ${ACCEPTED} (check initialState, setState and the controlled ` +\n 'options.state)'\n : `pass ${ACCEPTED} to setValidity()`,\n ],\n },\n}\n\n/** Codes owned by the `validity` feature (§6.2). */\nexport const validityDiagnostics = [\n defineDiagnostic(\n {\n code: 'DK_INVALID_VALIDITY',\n level: 'warn',\n where: (d) =>\n d.source === 'state'\n ? { kind: 'option', path: 'state.validity' }\n : { kind: 'operation', op: 'table.setValidity' },\n },\n (process.env.NODE_ENV !== \"production\") && validityMessages.DK_INVALID_VALIDITY,\n ),\n]\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAA0D;AAC1D,2BAAO;AAeP,IAAM,WAAW;AAGV,IAAM,mBAA8D;AAAA,EACzE,qBAAqB;AAAA,IACnB,SAAS,CAAC,MACR,EAAE,WAAW,UACT,yBAAyB,EAAE,QAAQ,gBAAgB,QAAQ,KAC3D,0BAA0B,EAAE,QAAQ,gBAAgB,QAAQ;AAAA,IAClE,QAAQ,CAAC,MAAM,EAAE;AAAA,IACjB,KAAK,CAAC,MAAM;AAAA,MACV,EAAE,WAAW,UACT,qBAAqB,QAAQ,qEAE7B,QAAQ,QAAQ;AAAA,IACtB;AAAA,EACF;AACF;AAGO,IAAM,sBAAsB;AAAA,MACjC;AAAA,IACE;AAAA,MACE,MAAM;AAAA,MACN,OAAO;AAAA,MACP,OAAO,CAAC,MACN,EAAE,WAAW,UACT,EAAE,MAAM,UAAU,MAAM,iBAAiB,IACzC,EAAE,MAAM,aAAa,IAAI,oBAAoB;AAAA,IACrD;AAAA,IACC,QAAQ,IAAI,aAAa,gBAAiB,iBAAiB;AAAA,EAC9D;AACF;","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/features/validity/codes.ts"],"sourcesContent":["import { type DiagnosticMessages, defineDiagnostic } from '../../diagnostics/catalog'\n\ndeclare module '../../diagnostics/catalog' {\n interface DiagnosticCatalog {\n DK_INVALID_VALIDITY: {\n /** The API method that received the value, or `'state'` for a slice written to the store. */\n source: 'setValidity' | 'state'\n /** A short constant (`\"broken\"`) or the value's type only. */\n received: string\n /** What was done instead. */\n fallback: string\n }\n }\n}\n\nconst ACCEPTED = \"'all' | 'valid' | 'invalid'\"\n\n/** Message text (§8.2): development builds, or production via `@datakable/core/messages`. */\nexport const validityMessages: DiagnosticMessages<'DK_INVALID_VALIDITY'> = {\n DK_INVALID_VALIDITY: {\n problem: (d) =>\n d.source === 'state'\n ? `the validity state is ${d.received}; it must be ${ACCEPTED}`\n : `setValidity() received ${d.received}; it must be ${ACCEPTED}`,\n impact: (d) => d.fallback,\n fix: (d) => [\n d.source === 'state'\n ? `write validity as ${ACCEPTED} (check initialState, setState and the controlled ` +\n 'options.state)'\n : `pass ${ACCEPTED} to setValidity()`,\n ],\n },\n}\n\n/** Codes owned by the `validity` feature (§6.2). */\nexport const validityDiagnostics = [\n defineDiagnostic(\n {\n code: 'DK_INVALID_VALIDITY',\n level: 'warn',\n where: (d) =>\n d.source === 'state'\n ? { kind: 'option', path: 'state.validity' }\n : { kind: 'operation', op: 'table.setValidity' },\n },\n (process.env.NODE_ENV !== \"production\") && validityMessages.DK_INVALID_VALIDITY,\n ),\n]\n"],"mappings":";AAAA,SAAkC,wBAAwB;
|
|
1
|
+
{"version":3,"sources":["../../../src/features/validity/codes.ts"],"sourcesContent":["import { type DiagnosticMessages, defineDiagnostic } from '../../diagnostics/catalog'\nimport '../../diagnostics/process-guard'\n\ndeclare module '../../diagnostics/catalog' {\n interface DiagnosticCatalog {\n DK_INVALID_VALIDITY: {\n /** The API method that received the value, or `'state'` for a slice written to the store. */\n source: 'setValidity' | 'state'\n /** A short constant (`\"broken\"`) or the value's type only. */\n received: string\n /** What was done instead. */\n fallback: string\n }\n }\n}\n\nconst ACCEPTED = \"'all' | 'valid' | 'invalid'\"\n\n/** Message text (§8.2): development builds, or production via `@datakable/core/messages`. */\nexport const validityMessages: DiagnosticMessages<'DK_INVALID_VALIDITY'> = {\n DK_INVALID_VALIDITY: {\n problem: (d) =>\n d.source === 'state'\n ? `the validity state is ${d.received}; it must be ${ACCEPTED}`\n : `setValidity() received ${d.received}; it must be ${ACCEPTED}`,\n impact: (d) => d.fallback,\n fix: (d) => [\n d.source === 'state'\n ? `write validity as ${ACCEPTED} (check initialState, setState and the controlled ` +\n 'options.state)'\n : `pass ${ACCEPTED} to setValidity()`,\n ],\n },\n}\n\n/** Codes owned by the `validity` feature (§6.2). */\nexport const validityDiagnostics = [\n defineDiagnostic(\n {\n code: 'DK_INVALID_VALIDITY',\n level: 'warn',\n where: (d) =>\n d.source === 'state'\n ? { kind: 'option', path: 'state.validity' }\n : { kind: 'operation', op: 'table.setValidity' },\n },\n (process.env.NODE_ENV !== \"production\") && validityMessages.DK_INVALID_VALIDITY,\n ),\n]\n"],"mappings":";AAAA,SAAkC,wBAAwB;AAC1D,OAAO;AAeP,IAAM,WAAW;AAGV,IAAM,mBAA8D;AAAA,EACzE,qBAAqB;AAAA,IACnB,SAAS,CAAC,MACR,EAAE,WAAW,UACT,yBAAyB,EAAE,QAAQ,gBAAgB,QAAQ,KAC3D,0BAA0B,EAAE,QAAQ,gBAAgB,QAAQ;AAAA,IAClE,QAAQ,CAAC,MAAM,EAAE;AAAA,IACjB,KAAK,CAAC,MAAM;AAAA,MACV,EAAE,WAAW,UACT,qBAAqB,QAAQ,qEAE7B,QAAQ,QAAQ;AAAA,IACtB;AAAA,EACF;AACF;AAGO,IAAM,sBAAsB;AAAA,EACjC;AAAA,IACE;AAAA,MACE,MAAM;AAAA,MACN,OAAO;AAAA,MACP,OAAO,CAAC,MACN,EAAE,WAAW,UACT,EAAE,MAAM,UAAU,MAAM,iBAAiB,IACzC,EAAE,MAAM,aAAa,IAAI,oBAAoB;AAAA,IACrD;AAAA,IACC,QAAQ,IAAI,aAAa,gBAAiB,iBAAiB;AAAA,EAC9D;AACF;","names":[]}
|
|
@@ -42,7 +42,7 @@ var validity = () => (0, import_define.defineFeature)({
|
|
|
42
42
|
ctx.emit("DK_INVALID_VALIDITY", {
|
|
43
43
|
source: "setValidity",
|
|
44
44
|
received: received(value),
|
|
45
|
-
fallback: "
|
|
45
|
+
fallback: "validity-ignored"
|
|
46
46
|
});
|
|
47
47
|
return;
|
|
48
48
|
}
|
|
@@ -54,7 +54,7 @@ var validity = () => (0, import_define.defineFeature)({
|
|
|
54
54
|
ctx.emit("DK_INVALID_VALIDITY", {
|
|
55
55
|
source: "state",
|
|
56
56
|
received: received(state),
|
|
57
|
-
fallback: "
|
|
57
|
+
fallback: "validity-all"
|
|
58
58
|
});
|
|
59
59
|
return indices;
|
|
60
60
|
}
|
|
@@ -64,7 +64,7 @@ var validity = () => (0, import_define.defineFeature)({
|
|
|
64
64
|
ctx.emit("DK_OPTION_NO_EFFECT", {
|
|
65
65
|
path: "state.validity",
|
|
66
66
|
feature: NAME,
|
|
67
|
-
reason: "validity
|
|
67
|
+
reason: "validity-needs-flag",
|
|
68
68
|
once: false
|
|
69
69
|
});
|
|
70
70
|
return indices;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/features/validity/validity.ts"],"sourcesContent":["import { optionDiagnostics } from '../../catalog/codes'\nimport { keepDiagnostics } from '../../diagnostics/catalog'\nimport { describeValue } from '../../diagnostics/redact'\nimport { defineFeature } from '../../feature/define'\nimport type { FeatureContext } from '../../feature/types'\nimport { validityDiagnostics } from './codes'\n\nkeepDiagnostics(validityDiagnostics, optionDiagnostics)\n\n/** Which rows the `validity` step keeps (§6.2). */\nexport type ValidityState = 'all' | 'valid' | 'invalid'\n\nexport interface ValidityApi {\n /** Shows every row, only the rows that passed the schema, or only the flagged ones. */\n setValidity(value: ValidityState): void\n}\n\nconst NAME = 'validity'\n\nconst isValidity = (v: unknown): v is ValidityState =>\n v === 'all' || v === 'valid' || v === 'invalid'\n\n/** A short string as written (`\"broken\"`); anything else by its type only. */\nconst received = (v: unknown) =>\n typeof v === 'string' && v.length <= 20 ? JSON.stringify(v) : describeValue(v)\n\n/**\n * Filters rows by schema validity (§6.2, §5.1). State `'all' | 'valid' | 'invalid'` (default\n * `'all'`); stage `filter`, so it runs with `columnFilters` before search.\n *\n * - Active only with `schema` + `invalidRows: 'flag'`. In any other mode the step passes its input\n * through, and a value other than `'all'` reports `DK_OPTION_NO_EFFECT` — from the step, so\n * `setValidity`, `setState`, `initialState` and controlled state are all covered.\n * - A slice that is not one of the three values reads as `'all'` (`DK_INVALID_VALIDITY`);\n * `setValidity` with one is ignored (same code).\n */\nexport const validity = () =>\n defineFeature({\n name: NAME,\n stage: 'filter',\n initialState: (): ValidityState => 'all',\n createApi: (ctx: FeatureContext<ValidityState>): ValidityApi => ({\n setValidity(value) {\n if (!isValidity(value)) {\n ctx.emit('DK_INVALID_VALIDITY', {\n source: 'setValidity',\n received: received(value),\n fallback: '
|
|
1
|
+
{"version":3,"sources":["../../../src/features/validity/validity.ts"],"sourcesContent":["import { optionDiagnostics } from '../../catalog/codes'\nimport { keepDiagnostics } from '../../diagnostics/catalog'\nimport { describeValue } from '../../diagnostics/redact'\nimport { defineFeature } from '../../feature/define'\nimport type { FeatureContext } from '../../feature/types'\nimport { validityDiagnostics } from './codes'\n\nkeepDiagnostics(validityDiagnostics, optionDiagnostics)\n\n/** Which rows the `validity` step keeps (§6.2). */\nexport type ValidityState = 'all' | 'valid' | 'invalid'\n\nexport interface ValidityApi {\n /** Shows every row, only the rows that passed the schema, or only the flagged ones. */\n setValidity(value: ValidityState): void\n}\n\nconst NAME = 'validity'\n\nconst isValidity = (v: unknown): v is ValidityState =>\n v === 'all' || v === 'valid' || v === 'invalid'\n\n/** A short string as written (`\"broken\"`); anything else by its type only. */\nconst received = (v: unknown) =>\n typeof v === 'string' && v.length <= 20 ? JSON.stringify(v) : describeValue(v)\n\n/**\n * Filters rows by schema validity (§6.2, §5.1). State `'all' | 'valid' | 'invalid'` (default\n * `'all'`); stage `filter`, so it runs with `columnFilters` before search.\n *\n * - Active only with `schema` + `invalidRows: 'flag'`. In any other mode the step passes its input\n * through, and a value other than `'all'` reports `DK_OPTION_NO_EFFECT` — from the step, so\n * `setValidity`, `setState`, `initialState` and controlled state are all covered.\n * - A slice that is not one of the three values reads as `'all'` (`DK_INVALID_VALIDITY`);\n * `setValidity` with one is ignored (same code).\n */\nexport const validity = () =>\n defineFeature({\n name: NAME,\n stage: 'filter',\n initialState: (): ValidityState => 'all',\n createApi: (ctx: FeatureContext<ValidityState>): ValidityApi => ({\n setValidity(value) {\n if (!isValidity(value)) {\n ctx.emit('DK_INVALID_VALIDITY', {\n source: 'setValidity',\n received: received(value),\n fallback: 'validity-ignored',\n })\n return\n }\n if (value !== ctx.getState()) ctx.setState(value)\n },\n }),\n rowModel: (indices, state, ctx) => {\n if (!isValidity(state)) {\n ctx.emit('DK_INVALID_VALIDITY', {\n source: 'state',\n received: received(state),\n fallback: 'validity-all',\n })\n return indices\n }\n if (state === 'all') return indices\n const flagged = ctx.flagged\n if (!flagged) {\n ctx.emit('DK_OPTION_NO_EFFECT', {\n path: 'state.validity',\n feature: NAME,\n reason: 'validity-needs-flag',\n once: false,\n })\n return indices\n }\n const keep = state === 'invalid'\n const out = new Uint32Array(indices.length)\n let n = 0\n for (let i = 0; i < indices.length; i++) {\n const r = indices[i] as number\n if ((flagged(r) !== undefined) === keep) out[n++] = r\n }\n return n === indices.length ? indices : out.subarray(0, n)\n },\n })\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAkC;AAClC,qBAAgC;AAChC,oBAA8B;AAC9B,oBAA8B;AAE9B,IAAAA,gBAAoC;AAAA,IAEpC,gCAAgB,mCAAqB,8BAAiB;AAUtD,IAAM,OAAO;AAEb,IAAM,aAAa,CAAC,MAClB,MAAM,SAAS,MAAM,WAAW,MAAM;AAGxC,IAAM,WAAW,CAAC,MAChB,OAAO,MAAM,YAAY,EAAE,UAAU,KAAK,KAAK,UAAU,CAAC,QAAI,6BAAc,CAAC;AAYxE,IAAM,WAAW,UACtB,6BAAc;AAAA,EACZ,MAAM;AAAA,EACN,OAAO;AAAA,EACP,cAAc,MAAqB;AAAA,EACnC,WAAW,CAAC,SAAqD;AAAA,IAC/D,YAAY,OAAO;AACjB,UAAI,CAAC,WAAW,KAAK,GAAG;AACtB,YAAI,KAAK,uBAAuB;AAAA,UAC9B,QAAQ;AAAA,UACR,UAAU,SAAS,KAAK;AAAA,UACxB,UAAU;AAAA,QACZ,CAAC;AACD;AAAA,MACF;AACA,UAAI,UAAU,IAAI,SAAS,EAAG,KAAI,SAAS,KAAK;AAAA,IAClD;AAAA,EACF;AAAA,EACA,UAAU,CAAC,SAAS,OAAO,QAAQ;AACjC,QAAI,CAAC,WAAW,KAAK,GAAG;AACtB,UAAI,KAAK,uBAAuB;AAAA,QAC9B,QAAQ;AAAA,QACR,UAAU,SAAS,KAAK;AAAA,QACxB,UAAU;AAAA,MACZ,CAAC;AACD,aAAO;AAAA,IACT;AACA,QAAI,UAAU,MAAO,QAAO;AAC5B,UAAM,UAAU,IAAI;AACpB,QAAI,CAAC,SAAS;AACZ,UAAI,KAAK,uBAAuB;AAAA,QAC9B,MAAM;AAAA,QACN,SAAS;AAAA,QACT,QAAQ;AAAA,QACR,MAAM;AAAA,MACR,CAAC;AACD,aAAO;AAAA,IACT;AACA,UAAM,OAAO,UAAU;AACvB,UAAM,MAAM,IAAI,YAAY,QAAQ,MAAM;AAC1C,QAAI,IAAI;AACR,aAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACvC,YAAM,IAAI,QAAQ,CAAC;AACnB,UAAK,QAAQ,CAAC,MAAM,WAAe,KAAM,KAAI,GAAG,IAAI;AAAA,IACtD;AACA,WAAO,MAAM,QAAQ,SAAS,UAAU,IAAI,SAAS,GAAG,CAAC;AAAA,EAC3D;AACF,CAAC;","names":["import_codes"]}
|
|
@@ -18,7 +18,7 @@ var validity = () => defineFeature({
|
|
|
18
18
|
ctx.emit("DK_INVALID_VALIDITY", {
|
|
19
19
|
source: "setValidity",
|
|
20
20
|
received: received(value),
|
|
21
|
-
fallback: "
|
|
21
|
+
fallback: "validity-ignored"
|
|
22
22
|
});
|
|
23
23
|
return;
|
|
24
24
|
}
|
|
@@ -30,7 +30,7 @@ var validity = () => defineFeature({
|
|
|
30
30
|
ctx.emit("DK_INVALID_VALIDITY", {
|
|
31
31
|
source: "state",
|
|
32
32
|
received: received(state),
|
|
33
|
-
fallback: "
|
|
33
|
+
fallback: "validity-all"
|
|
34
34
|
});
|
|
35
35
|
return indices;
|
|
36
36
|
}
|
|
@@ -40,7 +40,7 @@ var validity = () => defineFeature({
|
|
|
40
40
|
ctx.emit("DK_OPTION_NO_EFFECT", {
|
|
41
41
|
path: "state.validity",
|
|
42
42
|
feature: NAME,
|
|
43
|
-
reason: "validity
|
|
43
|
+
reason: "validity-needs-flag",
|
|
44
44
|
once: false
|
|
45
45
|
});
|
|
46
46
|
return indices;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/features/validity/validity.ts"],"sourcesContent":["import { optionDiagnostics } from '../../catalog/codes'\nimport { keepDiagnostics } from '../../diagnostics/catalog'\nimport { describeValue } from '../../diagnostics/redact'\nimport { defineFeature } from '../../feature/define'\nimport type { FeatureContext } from '../../feature/types'\nimport { validityDiagnostics } from './codes'\n\nkeepDiagnostics(validityDiagnostics, optionDiagnostics)\n\n/** Which rows the `validity` step keeps (§6.2). */\nexport type ValidityState = 'all' | 'valid' | 'invalid'\n\nexport interface ValidityApi {\n /** Shows every row, only the rows that passed the schema, or only the flagged ones. */\n setValidity(value: ValidityState): void\n}\n\nconst NAME = 'validity'\n\nconst isValidity = (v: unknown): v is ValidityState =>\n v === 'all' || v === 'valid' || v === 'invalid'\n\n/** A short string as written (`\"broken\"`); anything else by its type only. */\nconst received = (v: unknown) =>\n typeof v === 'string' && v.length <= 20 ? JSON.stringify(v) : describeValue(v)\n\n/**\n * Filters rows by schema validity (§6.2, §5.1). State `'all' | 'valid' | 'invalid'` (default\n * `'all'`); stage `filter`, so it runs with `columnFilters` before search.\n *\n * - Active only with `schema` + `invalidRows: 'flag'`. In any other mode the step passes its input\n * through, and a value other than `'all'` reports `DK_OPTION_NO_EFFECT` — from the step, so\n * `setValidity`, `setState`, `initialState` and controlled state are all covered.\n * - A slice that is not one of the three values reads as `'all'` (`DK_INVALID_VALIDITY`);\n * `setValidity` with one is ignored (same code).\n */\nexport const validity = () =>\n defineFeature({\n name: NAME,\n stage: 'filter',\n initialState: (): ValidityState => 'all',\n createApi: (ctx: FeatureContext<ValidityState>): ValidityApi => ({\n setValidity(value) {\n if (!isValidity(value)) {\n ctx.emit('DK_INVALID_VALIDITY', {\n source: 'setValidity',\n received: received(value),\n fallback: '
|
|
1
|
+
{"version":3,"sources":["../../../src/features/validity/validity.ts"],"sourcesContent":["import { optionDiagnostics } from '../../catalog/codes'\nimport { keepDiagnostics } from '../../diagnostics/catalog'\nimport { describeValue } from '../../diagnostics/redact'\nimport { defineFeature } from '../../feature/define'\nimport type { FeatureContext } from '../../feature/types'\nimport { validityDiagnostics } from './codes'\n\nkeepDiagnostics(validityDiagnostics, optionDiagnostics)\n\n/** Which rows the `validity` step keeps (§6.2). */\nexport type ValidityState = 'all' | 'valid' | 'invalid'\n\nexport interface ValidityApi {\n /** Shows every row, only the rows that passed the schema, or only the flagged ones. */\n setValidity(value: ValidityState): void\n}\n\nconst NAME = 'validity'\n\nconst isValidity = (v: unknown): v is ValidityState =>\n v === 'all' || v === 'valid' || v === 'invalid'\n\n/** A short string as written (`\"broken\"`); anything else by its type only. */\nconst received = (v: unknown) =>\n typeof v === 'string' && v.length <= 20 ? JSON.stringify(v) : describeValue(v)\n\n/**\n * Filters rows by schema validity (§6.2, §5.1). State `'all' | 'valid' | 'invalid'` (default\n * `'all'`); stage `filter`, so it runs with `columnFilters` before search.\n *\n * - Active only with `schema` + `invalidRows: 'flag'`. In any other mode the step passes its input\n * through, and a value other than `'all'` reports `DK_OPTION_NO_EFFECT` — from the step, so\n * `setValidity`, `setState`, `initialState` and controlled state are all covered.\n * - A slice that is not one of the three values reads as `'all'` (`DK_INVALID_VALIDITY`);\n * `setValidity` with one is ignored (same code).\n */\nexport const validity = () =>\n defineFeature({\n name: NAME,\n stage: 'filter',\n initialState: (): ValidityState => 'all',\n createApi: (ctx: FeatureContext<ValidityState>): ValidityApi => ({\n setValidity(value) {\n if (!isValidity(value)) {\n ctx.emit('DK_INVALID_VALIDITY', {\n source: 'setValidity',\n received: received(value),\n fallback: 'validity-ignored',\n })\n return\n }\n if (value !== ctx.getState()) ctx.setState(value)\n },\n }),\n rowModel: (indices, state, ctx) => {\n if (!isValidity(state)) {\n ctx.emit('DK_INVALID_VALIDITY', {\n source: 'state',\n received: received(state),\n fallback: 'validity-all',\n })\n return indices\n }\n if (state === 'all') return indices\n const flagged = ctx.flagged\n if (!flagged) {\n ctx.emit('DK_OPTION_NO_EFFECT', {\n path: 'state.validity',\n feature: NAME,\n reason: 'validity-needs-flag',\n once: false,\n })\n return indices\n }\n const keep = state === 'invalid'\n const out = new Uint32Array(indices.length)\n let n = 0\n for (let i = 0; i < indices.length; i++) {\n const r = indices[i] as number\n if ((flagged(r) !== undefined) === keep) out[n++] = r\n }\n return n === indices.length ? indices : out.subarray(0, n)\n },\n })\n"],"mappings":";AAAA,SAAS,yBAAyB;AAClC,SAAS,uBAAuB;AAChC,SAAS,qBAAqB;AAC9B,SAAS,qBAAqB;AAE9B,SAAS,2BAA2B;AAEpC,gBAAgB,qBAAqB,iBAAiB;AAUtD,IAAM,OAAO;AAEb,IAAM,aAAa,CAAC,MAClB,MAAM,SAAS,MAAM,WAAW,MAAM;AAGxC,IAAM,WAAW,CAAC,MAChB,OAAO,MAAM,YAAY,EAAE,UAAU,KAAK,KAAK,UAAU,CAAC,IAAI,cAAc,CAAC;AAYxE,IAAM,WAAW,MACtB,cAAc;AAAA,EACZ,MAAM;AAAA,EACN,OAAO;AAAA,EACP,cAAc,MAAqB;AAAA,EACnC,WAAW,CAAC,SAAqD;AAAA,IAC/D,YAAY,OAAO;AACjB,UAAI,CAAC,WAAW,KAAK,GAAG;AACtB,YAAI,KAAK,uBAAuB;AAAA,UAC9B,QAAQ;AAAA,UACR,UAAU,SAAS,KAAK;AAAA,UACxB,UAAU;AAAA,QACZ,CAAC;AACD;AAAA,MACF;AACA,UAAI,UAAU,IAAI,SAAS,EAAG,KAAI,SAAS,KAAK;AAAA,IAClD;AAAA,EACF;AAAA,EACA,UAAU,CAAC,SAAS,OAAO,QAAQ;AACjC,QAAI,CAAC,WAAW,KAAK,GAAG;AACtB,UAAI,KAAK,uBAAuB;AAAA,QAC9B,QAAQ;AAAA,QACR,UAAU,SAAS,KAAK;AAAA,QACxB,UAAU;AAAA,MACZ,CAAC;AACD,aAAO;AAAA,IACT;AACA,QAAI,UAAU,MAAO,QAAO;AAC5B,UAAM,UAAU,IAAI;AACpB,QAAI,CAAC,SAAS;AACZ,UAAI,KAAK,uBAAuB;AAAA,QAC9B,MAAM;AAAA,QACN,SAAS;AAAA,QACT,QAAQ;AAAA,QACR,MAAM;AAAA,MACR,CAAC;AACD,aAAO;AAAA,IACT;AACA,UAAM,OAAO,UAAU;AACvB,UAAM,MAAM,IAAI,YAAY,QAAQ,MAAM;AAC1C,QAAI,IAAI;AACR,aAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACvC,YAAM,IAAI,QAAQ,CAAC;AACnB,UAAK,QAAQ,CAAC,MAAM,WAAe,KAAM,KAAI,GAAG,IAAI;AAAA,IACtD;AACA,WAAO,MAAM,QAAQ,SAAS,UAAU,IAAI,SAAS,GAAG,CAAC;AAAA,EAC3D;AACF,CAAC;","names":[]}
|
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 stepDiagnostics, au as tableDiagnostics, av as throwConfigError, aw as validityDiagnostics, ax as versioningDiagnostics } from './codes-
|
|
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-B9bCK73-.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 stepDiagnostics, au as tableDiagnostics, av as throwConfigError, aw as validityDiagnostics, ax as versioningDiagnostics } from './codes-B9bCK73-.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-Q8Cg0cZy.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-Q8Cg0cZy.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-CuLYPfY_.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-CuLYPfY_.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';
|
|
@@ -37,7 +37,8 @@ type CompiledPath = readonly string[];
|
|
|
37
37
|
declare function compilePath(path: string): CompiledPath;
|
|
38
38
|
/**
|
|
39
39
|
* Reads the value at `path` of `row`, defensively (§4.3): a `null`, `undefined` or non-object
|
|
40
|
-
* (primitive, function) part-way through yields `undefined`. Arrays are walked by index.
|
|
40
|
+
* (primitive, function) part-way through yields `undefined`. Arrays are walked by index. An
|
|
41
|
+
* inherited method or `__proto__` (`constructor`, `toString`, `map`) yields `undefined`. Never
|
|
41
42
|
* throws: a throwing getter or Proxy trap yields `undefined` and is passed to `onError`.
|
|
42
43
|
*
|
|
43
44
|
* Hot paths should pass a {@link compilePath} result so the walk allocates nothing per cell.
|
|
@@ -110,6 +111,7 @@ interface DiagnosticsOptions {
|
|
|
110
111
|
max: number;
|
|
111
112
|
windowMs: number;
|
|
112
113
|
};
|
|
114
|
+
/** Clock (epoch ms) for `occurrences` and the rate limit. Default `wallClock` (never `Date`, #7). */
|
|
113
115
|
now?: () => number;
|
|
114
116
|
}
|
|
115
117
|
interface Diagnostics {
|
|
@@ -141,12 +143,12 @@ declare function createDiagnostics(options?: DiagnosticsOptions): Diagnostics;
|
|
|
141
143
|
*/
|
|
142
144
|
declare function toSafeJson(value: unknown): unknown;
|
|
143
145
|
|
|
144
|
-
type Traced = 'pipeline:run' | 'pipeline:step' | 'state:dispatch';
|
|
146
|
+
type Traced = 'pipeline:run' | 'pipeline:step' | 'state:dispatch' | 'column:batch';
|
|
145
147
|
/**
|
|
146
148
|
* The `tracer` interceptor (§3.4): timings and per-step counts of the last pipeline run, read by
|
|
147
149
|
* `table.explain()`. `createTable` installs it in development; in production it is off (§8.2) and
|
|
148
150
|
* opt-in with `createTable({ interceptors: [tracer()] })`. Keeps the last run only: counts, never
|
|
149
|
-
* rows.
|
|
151
|
+
* rows. Time-sliced work (§9.1) is added to the step that waited on it (#61).
|
|
150
152
|
*/
|
|
151
153
|
declare function tracer(): Interceptor<Traced>;
|
|
152
154
|
|
|
@@ -157,7 +159,8 @@ interface FixedFeatureDefinition<Name extends string, S, A> extends Omit<Feature
|
|
|
157
159
|
rowModel?: (indices: Uint32Array, state: S, ctx: RowModelContext<AnyRow>) => Uint32Array;
|
|
158
160
|
}
|
|
159
161
|
/**
|
|
160
|
-
* Defines a feature (§3.3).
|
|
162
|
+
* Defines a feature (§3.3). Returns `definition` as is (it exists for typing) and installs the
|
|
163
|
+
* feature runtime.
|
|
161
164
|
*
|
|
162
165
|
* Row-typed feature (all built-ins): declare the types interface and pass both type arguments.
|
|
163
166
|
*
|
|
@@ -311,7 +314,9 @@ declare function createTable<T, S extends TableState = never, const Fs extends r
|
|
|
311
314
|
* starts no async work. The fetcher's first request and a `searchFn` for an initial query wait for
|
|
312
315
|
* `startTable(table)`; meanwhile the row model has `status: 'pending'`. Nothing is started, so a
|
|
313
316
|
* server render leaves no request, timer or microtask chain behind. On the server (no
|
|
314
|
-
* `document`), each deferred source reports `DK_SSR_ASYNC_DEFERRED` (info)
|
|
317
|
+
* `document`), each deferred source reports `DK_SSR_ASYNC_DEFERRED` (info), printed once per process
|
|
318
|
+
* in development for a table name and source (#38: a dev server renders a page several times per
|
|
319
|
+
* request).
|
|
315
320
|
*
|
|
316
321
|
* `@datakable/react`'s `useDataTable` creates its table this way and starts it after the commit;
|
|
317
322
|
* effects never run on the server.
|