@datakable/core 2.0.2 → 2.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/dist/{codes-AX8XkMNY.d.cts → codes-4sYQv_7J.d.cts} +36 -10
- package/dist/{codes-AX8XkMNY.d.ts → codes-4sYQv_7J.d.ts} +36 -10
- package/dist/column-filters.d.cts +2 -2
- package/dist/column-filters.d.ts +2 -2
- package/dist/diagnostics/build.cjs +1 -1
- package/dist/diagnostics/build.cjs.map +1 -1
- package/dist/diagnostics/build.js +2 -2
- package/dist/diagnostics/build.js.map +1 -1
- package/dist/diagnostics/console.cjs +15 -4
- package/dist/diagnostics/console.cjs.map +1 -1
- package/dist/diagnostics/console.js +15 -4
- package/dist/diagnostics/console.js.map +1 -1
- package/dist/diagnostics/prose.cjs +10 -1
- package/dist/diagnostics/prose.cjs.map +1 -1
- package/dist/diagnostics/prose.js +9 -1
- package/dist/diagnostics/prose.js.map +1 -1
- package/dist/{explain-pKAnnxEW.d.cts → explain-DmwN_RG9.d.cts} +11 -4
- package/dist/{explain-BVE3ln3G.d.ts → explain-Dr3SmMNY.d.ts} +11 -4
- package/dist/feature/install.cjs +2 -1
- package/dist/feature/install.cjs.map +1 -1
- package/dist/feature/install.js +2 -1
- package/dist/feature/install.js.map +1 -1
- package/dist/feature/slice-guard.cjs +76 -0
- package/dist/feature/slice-guard.cjs.map +1 -0
- package/dist/feature/slice-guard.js +50 -0
- package/dist/feature/slice-guard.js.map +1 -0
- package/dist/features/column-filters/codes.cjs +2 -19
- package/dist/features/column-filters/codes.cjs.map +1 -1
- package/dist/features/column-filters/codes.js +2 -19
- package/dist/features/column-filters/codes.js.map +1 -1
- package/dist/features/column-filters/column-filters.cjs +37 -22
- package/dist/features/column-filters/column-filters.cjs.map +1 -1
- package/dist/features/column-filters/column-filters.js +37 -22
- package/dist/features/column-filters/column-filters.js.map +1 -1
- package/dist/features/column-filters/match.cjs +6 -2
- package/dist/features/column-filters/match.cjs.map +1 -1
- package/dist/features/column-filters/match.js +6 -2
- package/dist/features/column-filters/match.js.map +1 -1
- package/dist/features/pagination/pagination.cjs +2 -2
- package/dist/features/pagination/pagination.cjs.map +1 -1
- package/dist/features/pagination/pagination.js +2 -2
- package/dist/features/pagination/pagination.js.map +1 -1
- package/dist/features/search/codes.cjs +18 -2
- package/dist/features/search/codes.cjs.map +1 -1
- package/dist/features/search/codes.js +16 -1
- package/dist/features/search/codes.js.map +1 -1
- package/dist/features/search/search-engine.cjs +24 -5
- package/dist/features/search/search-engine.cjs.map +1 -1
- package/dist/features/search/search-engine.js +25 -6
- package/dist/features/search/search-engine.js.map +1 -1
- package/dist/features/search/search-index.cjs +23 -44
- package/dist/features/search/search-index.cjs.map +1 -1
- package/dist/features/search/search-index.js +24 -45
- package/dist/features/search/search-index.js.map +1 -1
- package/dist/features/sorting/ranks.cjs +117 -50
- package/dist/features/sorting/ranks.cjs.map +1 -1
- package/dist/features/sorting/ranks.js +117 -50
- package/dist/features/sorting/ranks.js.map +1 -1
- package/dist/features/sorting/sorting.cjs +87 -32
- package/dist/features/sorting/sorting.cjs.map +1 -1
- package/dist/features/sorting/sorting.js +87 -32
- package/dist/features/sorting/sorting.js.map +1 -1
- package/dist/index.d.cts +26 -17
- package/dist/index.d.ts +26 -17
- package/dist/intercept/runtime.cjs +3 -2
- package/dist/intercept/runtime.cjs.map +1 -1
- package/dist/intercept/runtime.js +3 -2
- package/dist/intercept/runtime.js.map +1 -1
- package/dist/messages/index.cjs +2 -0
- package/dist/messages/index.cjs.map +1 -1
- package/dist/messages/index.js +2 -0
- package/dist/messages/index.js.map +1 -1
- package/dist/pagination.d.cts +2 -2
- package/dist/pagination.d.ts +2 -2
- package/dist/pipeline/column-cache.cjs +6 -2
- package/dist/pipeline/column-cache.cjs.map +1 -1
- package/dist/pipeline/column-cache.js +6 -2
- package/dist/pipeline/column-cache.js.map +1 -1
- package/dist/pipeline/release.cjs +34 -0
- package/dist/pipeline/release.cjs.map +1 -0
- package/dist/pipeline/release.js +8 -0
- package/dist/pipeline/release.js.map +1 -0
- package/dist/pipeline/runner.cjs +15 -1
- package/dist/pipeline/runner.cjs.map +1 -1
- package/dist/pipeline/runner.js +15 -1
- package/dist/pipeline/runner.js.map +1 -1
- package/dist/schema.d.cts +2 -2
- package/dist/schema.d.ts +2 -2
- package/dist/{search-async-entry-ByMJbHjc.d.cts → search-async-entry-BiemO3JT.d.cts} +2 -2
- package/dist/{search-async-entry-CFQODE08.d.ts → search-async-entry-GRj0E06n.d.ts} +2 -2
- package/dist/search-async.d.cts +3 -3
- package/dist/search-async.d.ts +3 -3
- package/dist/search.d.cts +4 -4
- package/dist/search.d.ts +4 -4
- package/dist/server.d.cts +3 -3
- package/dist/server.d.ts +3 -3
- package/dist/sorting.d.cts +2 -2
- package/dist/sorting.d.ts +2 -2
- package/dist/source/async-control.cjs +2 -1
- package/dist/source/async-control.cjs.map +1 -1
- package/dist/source/async-control.js +2 -1
- package/dist/source/async-control.js.map +1 -1
- package/dist/source/fetcher.cjs.map +1 -1
- package/dist/source/fetcher.js.map +1 -1
- package/dist/source/server.cjs +58 -5
- package/dist/source/server.cjs.map +1 -1
- package/dist/source/server.js +58 -5
- package/dist/source/server.js.map +1 -1
- package/dist/table/create-table.cjs +33 -20
- package/dist/table/create-table.cjs.map +1 -1
- package/dist/table/create-table.js +33 -20
- package/dist/table/create-table.js.map +1 -1
- package/dist/table/index.cjs +3 -0
- package/dist/table/index.cjs.map +1 -1
- package/dist/table/index.js +5 -1
- package/dist/table/index.js.map +1 -1
- package/dist/table/state-codes.cjs +72 -0
- package/dist/table/state-codes.cjs.map +1 -0
- package/dist/table/state-codes.js +45 -0
- package/dist/table/state-codes.js.map +1 -0
- package/dist/table/types.cjs.map +1 -1
- package/dist/table/types.js.map +1 -1
- package/dist/validity.d.cts +2 -2
- package/dist/validity.d.ts +2 -2
- package/dist/version.cjs +1 -1
- package/dist/version.cjs.map +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/package.json +3 -3
- package/dist/ingest/test-schemas.cjs +0 -73
- package/dist/ingest/test-schemas.cjs.map +0 -1
- package/dist/ingest/test-schemas.js +0 -46
- package/dist/ingest/test-schemas.js.map +0 -1
|
@@ -732,6 +732,14 @@ declare module '@datakable/core' {
|
|
|
732
732
|
/** Whether a previous `searchFn` result is shown (`false`: none applied yet). */
|
|
733
733
|
hadResults: boolean;
|
|
734
734
|
};
|
|
735
|
+
DK_SEARCH_UNKNOWN_KEYS: {
|
|
736
|
+
/** Returned `{ keys }` that match no row's key (compared as strings). */
|
|
737
|
+
count: number;
|
|
738
|
+
/** How many keys `searchFn` returned. */
|
|
739
|
+
returned: number;
|
|
740
|
+
/** A sample of the unmatched keys (first few; redacted as row keys). */
|
|
741
|
+
keys: readonly unknown[];
|
|
742
|
+
};
|
|
735
743
|
DK_SEARCH_COLUMN_SKIPPED: {
|
|
736
744
|
/** Column id (`key` or `id`). */
|
|
737
745
|
column: string;
|
|
@@ -1066,6 +1074,32 @@ declare module '@datakable/core' {
|
|
|
1066
1074
|
/** SSR codes (§7.2, §8.3): kept by `createDeferred` (ssr.ts) and `@datakable/react`. */
|
|
1067
1075
|
declare const ssrDiagnostics: (DiagnosticDefinition<"DK_SSR_ASYNC_DEFERRED"> | DiagnosticDefinition<"DK_HYDRATION_MISMATCH">)[];
|
|
1068
1076
|
|
|
1077
|
+
declare module '@datakable/core' {
|
|
1078
|
+
interface DiagnosticCatalog {
|
|
1079
|
+
DK_STATE_UNKNOWN_KEY: {
|
|
1080
|
+
/** The state slice holding the key, e.g. `columnFilters`; `''` for a top-level state key. */
|
|
1081
|
+
slice: string;
|
|
1082
|
+
/** The key that names no column (or `__proto__`, which is never applied, #102). */
|
|
1083
|
+
key: string;
|
|
1084
|
+
/** The table's column ids (did-you-mean); empty for `__proto__`. */
|
|
1085
|
+
known: readonly string[];
|
|
1086
|
+
};
|
|
1087
|
+
DK_INVALID_STATE: {
|
|
1088
|
+
/** The feature slice, e.g. `sorting`. */
|
|
1089
|
+
slice: string;
|
|
1090
|
+
/** What the slice was (`describeValue`), or what was wrong with it, e.g. `by[1] null`. */
|
|
1091
|
+
received: string;
|
|
1092
|
+
/** What was stored instead. */
|
|
1093
|
+
fallback: string;
|
|
1094
|
+
};
|
|
1095
|
+
}
|
|
1096
|
+
}
|
|
1097
|
+
/**
|
|
1098
|
+
* Codes about the state itself, shared by core and features (§7.2, §8.3). `DK_INVALID_STATE` is
|
|
1099
|
+
* reported by the development-only slice guard (`feature/slice-guard.ts`), which defines it.
|
|
1100
|
+
*/
|
|
1101
|
+
declare const stateDiagnostics: DiagnosticDefinition<"DK_STATE_UNKNOWN_KEY">[];
|
|
1102
|
+
|
|
1069
1103
|
declare module '@datakable/core' {
|
|
1070
1104
|
interface DiagnosticCatalog {
|
|
1071
1105
|
DK_DEPRECATED: {
|
|
@@ -1135,17 +1169,9 @@ declare module '@datakable/core' {
|
|
|
1135
1169
|
/** A sample of their row indices (first few, in order). */
|
|
1136
1170
|
rows: readonly number[];
|
|
1137
1171
|
};
|
|
1138
|
-
DK_STATE_UNKNOWN_KEY: {
|
|
1139
|
-
/** The state slice holding the key, e.g. `columnFilters`. */
|
|
1140
|
-
slice: string;
|
|
1141
|
-
/** The key that names no column. */
|
|
1142
|
-
key: string;
|
|
1143
|
-
/** The table's column ids (did-you-mean). */
|
|
1144
|
-
known: readonly string[];
|
|
1145
|
-
};
|
|
1146
1172
|
}
|
|
1147
1173
|
}
|
|
1148
1174
|
/** Codes owned by the `columnFilters` feature (§6.1, §8.3). */
|
|
1149
|
-
declare const columnFiltersDiagnostics: (DiagnosticDefinition<"
|
|
1175
|
+
declare const columnFiltersDiagnostics: (DiagnosticDefinition<"DK_STATE_UNKNOWN_KEY"> | DiagnosticDefinition<"DK_FILTER_TYPE_MISMATCH">)[];
|
|
1150
1176
|
|
|
1151
|
-
export { defineSlot as $, type Redactor as A, type BadResponse as B, SCHEMA_INGEST as C, type Diagnostic as D, type Emit as E, type FlaggedRow as F, SENSITIVE as G, type SchemaIssueColumn as H, type InvalidRowsMode as I, type SchemaOutcome as J, type SlotDefinition as K, type Location as L, type SlotReturns as M, asyncDiagnostics as N, boundaryDiagnostics as O, type Phase as P, buildDiagnostic as Q, type RowIssue as R, StandardSchemaV1 as S, type Trigger as T, columnFiltersDiagnostics as U, type ValidRow as V, comparatorDiagnostics as W, coreDiagnostics as X, dataCheckDiagnostics as Y, dataMutationDiagnostics as Z, defineDiagnostic as _, type EmitOptions as a, describeReturn as a0, describeValue as a1, envDiagnostics as a2, featureDiagnostics as a3, fetchDiagnostics as a4, formatSlot as a5, formatWhere as a6, getDiagnosticDefinition as a7, getDiagnosticText as a8, getSlot as a9, hasMessages as aa, hashRowKey as ab, installMessages as ac, isStandardSchema as ad, keepDiagnostics as ae, listDiagnosticCodes as af, matchesSlot as ag, optionDiagnostics as ah, paginationDiagnostics as ai, pipelineDiagnostics as aj, resolveRedaction as ak, rowKeyDiagnostics as al, schemaDiagnostics as am, scrubError as an, scrubSchemaIssue as ao, searchDiagnostics as ap, slotDiagnostics as aq, sortingDiagnostics as ar, ssrDiagnostics as as,
|
|
1177
|
+
export { defineSlot as $, type Redactor as A, type BadResponse as B, SCHEMA_INGEST as C, type Diagnostic as D, type Emit as E, type FlaggedRow as F, SENSITIVE as G, type SchemaIssueColumn as H, type InvalidRowsMode as I, type SchemaOutcome as J, type SlotDefinition as K, type Location as L, type SlotReturns as M, asyncDiagnostics as N, boundaryDiagnostics as O, type Phase as P, buildDiagnostic as Q, type RowIssue as R, StandardSchemaV1 as S, type Trigger as T, columnFiltersDiagnostics as U, type ValidRow as V, comparatorDiagnostics as W, coreDiagnostics as X, dataCheckDiagnostics as Y, dataMutationDiagnostics as Z, defineDiagnostic as _, type EmitOptions as a, describeReturn as a0, describeValue as a1, envDiagnostics as a2, featureDiagnostics as a3, fetchDiagnostics as a4, formatSlot as a5, formatWhere as a6, getDiagnosticDefinition as a7, getDiagnosticText as a8, getSlot as a9, hasMessages as aa, hashRowKey as ab, installMessages as ac, isStandardSchema as ad, keepDiagnostics as ae, listDiagnosticCodes as af, matchesSlot as ag, optionDiagnostics as ah, paginationDiagnostics as ai, pipelineDiagnostics as aj, resolveRedaction as ak, rowKeyDiagnostics as al, schemaDiagnostics as am, scrubError as an, scrubSchemaIssue as ao, searchDiagnostics as ap, slotDiagnostics as aq, sortingDiagnostics as ar, ssrDiagnostics as as, stateDiagnostics as at, stepDiagnostics as au, tableDiagnostics as av, throwConfigError as aw, validityDiagnostics as ax, versioningDiagnostics as ay, Row as b, type DiagnosticCode as c, type DiagnosticDetails as d, type TableSchema as e, type RedactLevel as f, type RedactFn as g, type InvalidRow as h, type RowKey as i, type DiagnosticStateSummary as j, type RedactionOptions as k, type DiagnosticDefinition as l, type BuildInput as m, DK_UNSAFE_REDACTION as n, DatakableConfigError as o, DatakableError as p, DatakableSchemaError as q, type DiagnosticCatalog as r, type DiagnosticContext as s, type DiagnosticLevel as t, type DiagnosticMessages as u, type DiagnosticMeta as v, type DiagnosticText as w, type FlaggedInvalidRow as x, REDACTED as y, type RedactField as z };
|
|
@@ -732,6 +732,14 @@ declare module '@datakable/core' {
|
|
|
732
732
|
/** Whether a previous `searchFn` result is shown (`false`: none applied yet). */
|
|
733
733
|
hadResults: boolean;
|
|
734
734
|
};
|
|
735
|
+
DK_SEARCH_UNKNOWN_KEYS: {
|
|
736
|
+
/** Returned `{ keys }` that match no row's key (compared as strings). */
|
|
737
|
+
count: number;
|
|
738
|
+
/** How many keys `searchFn` returned. */
|
|
739
|
+
returned: number;
|
|
740
|
+
/** A sample of the unmatched keys (first few; redacted as row keys). */
|
|
741
|
+
keys: readonly unknown[];
|
|
742
|
+
};
|
|
735
743
|
DK_SEARCH_COLUMN_SKIPPED: {
|
|
736
744
|
/** Column id (`key` or `id`). */
|
|
737
745
|
column: string;
|
|
@@ -1066,6 +1074,32 @@ declare module '@datakable/core' {
|
|
|
1066
1074
|
/** SSR codes (§7.2, §8.3): kept by `createDeferred` (ssr.ts) and `@datakable/react`. */
|
|
1067
1075
|
declare const ssrDiagnostics: (DiagnosticDefinition<"DK_SSR_ASYNC_DEFERRED"> | DiagnosticDefinition<"DK_HYDRATION_MISMATCH">)[];
|
|
1068
1076
|
|
|
1077
|
+
declare module '@datakable/core' {
|
|
1078
|
+
interface DiagnosticCatalog {
|
|
1079
|
+
DK_STATE_UNKNOWN_KEY: {
|
|
1080
|
+
/** The state slice holding the key, e.g. `columnFilters`; `''` for a top-level state key. */
|
|
1081
|
+
slice: string;
|
|
1082
|
+
/** The key that names no column (or `__proto__`, which is never applied, #102). */
|
|
1083
|
+
key: string;
|
|
1084
|
+
/** The table's column ids (did-you-mean); empty for `__proto__`. */
|
|
1085
|
+
known: readonly string[];
|
|
1086
|
+
};
|
|
1087
|
+
DK_INVALID_STATE: {
|
|
1088
|
+
/** The feature slice, e.g. `sorting`. */
|
|
1089
|
+
slice: string;
|
|
1090
|
+
/** What the slice was (`describeValue`), or what was wrong with it, e.g. `by[1] null`. */
|
|
1091
|
+
received: string;
|
|
1092
|
+
/** What was stored instead. */
|
|
1093
|
+
fallback: string;
|
|
1094
|
+
};
|
|
1095
|
+
}
|
|
1096
|
+
}
|
|
1097
|
+
/**
|
|
1098
|
+
* Codes about the state itself, shared by core and features (§7.2, §8.3). `DK_INVALID_STATE` is
|
|
1099
|
+
* reported by the development-only slice guard (`feature/slice-guard.ts`), which defines it.
|
|
1100
|
+
*/
|
|
1101
|
+
declare const stateDiagnostics: DiagnosticDefinition<"DK_STATE_UNKNOWN_KEY">[];
|
|
1102
|
+
|
|
1069
1103
|
declare module '@datakable/core' {
|
|
1070
1104
|
interface DiagnosticCatalog {
|
|
1071
1105
|
DK_DEPRECATED: {
|
|
@@ -1135,17 +1169,9 @@ declare module '@datakable/core' {
|
|
|
1135
1169
|
/** A sample of their row indices (first few, in order). */
|
|
1136
1170
|
rows: readonly number[];
|
|
1137
1171
|
};
|
|
1138
|
-
DK_STATE_UNKNOWN_KEY: {
|
|
1139
|
-
/** The state slice holding the key, e.g. `columnFilters`. */
|
|
1140
|
-
slice: string;
|
|
1141
|
-
/** The key that names no column. */
|
|
1142
|
-
key: string;
|
|
1143
|
-
/** The table's column ids (did-you-mean). */
|
|
1144
|
-
known: readonly string[];
|
|
1145
|
-
};
|
|
1146
1172
|
}
|
|
1147
1173
|
}
|
|
1148
1174
|
/** Codes owned by the `columnFilters` feature (§6.1, §8.3). */
|
|
1149
|
-
declare const columnFiltersDiagnostics: (DiagnosticDefinition<"
|
|
1175
|
+
declare const columnFiltersDiagnostics: (DiagnosticDefinition<"DK_STATE_UNKNOWN_KEY"> | DiagnosticDefinition<"DK_FILTER_TYPE_MISMATCH">)[];
|
|
1150
1176
|
|
|
1151
|
-
export { defineSlot as $, type Redactor as A, type BadResponse as B, SCHEMA_INGEST as C, type Diagnostic as D, type Emit as E, type FlaggedRow as F, SENSITIVE as G, type SchemaIssueColumn as H, type InvalidRowsMode as I, type SchemaOutcome as J, type SlotDefinition as K, type Location as L, type SlotReturns as M, asyncDiagnostics as N, boundaryDiagnostics as O, type Phase as P, buildDiagnostic as Q, type RowIssue as R, StandardSchemaV1 as S, type Trigger as T, columnFiltersDiagnostics as U, type ValidRow as V, comparatorDiagnostics as W, coreDiagnostics as X, dataCheckDiagnostics as Y, dataMutationDiagnostics as Z, defineDiagnostic as _, type EmitOptions as a, describeReturn as a0, describeValue as a1, envDiagnostics as a2, featureDiagnostics as a3, fetchDiagnostics as a4, formatSlot as a5, formatWhere as a6, getDiagnosticDefinition as a7, getDiagnosticText as a8, getSlot as a9, hasMessages as aa, hashRowKey as ab, installMessages as ac, isStandardSchema as ad, keepDiagnostics as ae, listDiagnosticCodes as af, matchesSlot as ag, optionDiagnostics as ah, paginationDiagnostics as ai, pipelineDiagnostics as aj, resolveRedaction as ak, rowKeyDiagnostics as al, schemaDiagnostics as am, scrubError as an, scrubSchemaIssue as ao, searchDiagnostics as ap, slotDiagnostics as aq, sortingDiagnostics as ar, ssrDiagnostics as as,
|
|
1177
|
+
export { defineSlot as $, type Redactor as A, type BadResponse as B, SCHEMA_INGEST as C, type Diagnostic as D, type Emit as E, type FlaggedRow as F, SENSITIVE as G, type SchemaIssueColumn as H, type InvalidRowsMode as I, type SchemaOutcome as J, type SlotDefinition as K, type Location as L, type SlotReturns as M, asyncDiagnostics as N, boundaryDiagnostics as O, type Phase as P, buildDiagnostic as Q, type RowIssue as R, StandardSchemaV1 as S, type Trigger as T, columnFiltersDiagnostics as U, type ValidRow as V, comparatorDiagnostics as W, coreDiagnostics as X, dataCheckDiagnostics as Y, dataMutationDiagnostics as Z, defineDiagnostic as _, type EmitOptions as a, describeReturn as a0, describeValue as a1, envDiagnostics as a2, featureDiagnostics as a3, fetchDiagnostics as a4, formatSlot as a5, formatWhere as a6, getDiagnosticDefinition as a7, getDiagnosticText as a8, getSlot as a9, hasMessages as aa, hashRowKey as ab, installMessages as ac, isStandardSchema as ad, keepDiagnostics as ae, listDiagnosticCodes as af, matchesSlot as ag, optionDiagnostics as ah, paginationDiagnostics as ai, pipelineDiagnostics as aj, resolveRedaction as ak, rowKeyDiagnostics as al, schemaDiagnostics as am, scrubError as an, scrubSchemaIssue as ao, searchDiagnostics as ap, slotDiagnostics as aq, sortingDiagnostics as ar, ssrDiagnostics as as, stateDiagnostics as at, stepDiagnostics as au, tableDiagnostics as av, throwConfigError as aw, validityDiagnostics as ax, versioningDiagnostics as ay, Row as b, type DiagnosticCode as c, type DiagnosticDetails as d, type TableSchema as e, type RedactLevel as f, type RedactFn as g, type InvalidRow as h, type RowKey as i, type DiagnosticStateSummary as j, type RedactionOptions as k, type DiagnosticDefinition as l, type BuildInput as m, DK_UNSAFE_REDACTION as n, DatakableConfigError as o, DatakableError as p, DatakableSchemaError as q, type DiagnosticCatalog as r, type DiagnosticContext as s, type DiagnosticLevel as t, type DiagnosticMessages as u, type DiagnosticMeta as v, type DiagnosticText as w, type FlaggedInvalidRow as x, REDACTED as y, type RedactField as z };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { U as columnFiltersDiagnostics } from './codes-
|
|
2
|
-
import { G as FilterFor, a1 as Path, P as LooseRow, a2 as PathValue, e as FeatureTypes, F as Feature } from './explain-
|
|
1
|
+
export { U as columnFiltersDiagnostics } from './codes-4sYQv_7J.cjs';
|
|
2
|
+
import { G as FilterFor, a1 as Path, P as LooseRow, a2 as PathValue, e as FeatureTypes, F as Feature } from './explain-DmwN_RG9.cjs';
|
|
3
3
|
import { a as DataMode } from './mode-DFV8ryXo.cjs';
|
|
4
4
|
|
|
5
5
|
/** The value a filter compares against: the element type for array-valued cells (§6.1). */
|
package/dist/column-filters.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { U as columnFiltersDiagnostics } from './codes-
|
|
2
|
-
import { G as FilterFor, a1 as Path, P as LooseRow, a2 as PathValue, e as FeatureTypes, F as Feature } from './explain-
|
|
1
|
+
export { U as columnFiltersDiagnostics } from './codes-4sYQv_7J.js';
|
|
2
|
+
import { G as FilterFor, a1 as Path, P as LooseRow, a2 as PathValue, e as FeatureTypes, F as Feature } from './explain-Dr3SmMNY.js';
|
|
3
3
|
import { a as DataMode } from './mode-DFV8ryXo.js';
|
|
4
4
|
|
|
5
5
|
/** The value a filter compares against: the element type for array-valued cells (§6.1). */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/diagnostics/build.ts"],"sourcesContent":["import { VERSION } from '../version'\nimport {\n type DiagnosticCode,\n type DiagnosticDefinition,\n type DiagnosticDetails,\n type DiagnosticText,\n getDiagnosticDefinition,\n getDiagnosticText,\n hasMessages,\n} from './catalog'\nimport { coreDiagnostics } from './codes'\nimport './process-guard'\nimport { expandDetails } from './prose'\nimport {\n type RedactField,\n type Redactor,\n redactDetails,\n redactLocation,\n resolveRedaction,\n} from './redact'\nimport { toSafeJson } from './safe-json'\nimport type {\n Diagnostic,\n DiagnosticContext,\n DiagnosticLevel,\n DiagnosticStateSummary,\n Location,\n Phase,\n Trigger,\n} from './types'\n\nexport const PACKAGE = `@datakable/core@${VERSION}`\nconst DOCS = 'https://github.com/Ink01101011/datakable/blob/main/docs/errors.md'\n\n// Referencing the core entries keeps them in the bundle (`sideEffects: false`).\nconst INTERNAL = coreDiagnostics.find((d) => d.code === 'DK_INTERNAL') as DiagnosticDefinition\n\n/** Everything the enrich step adds; all optional so a diagnostic can be built outside a table. */\nexport interface BuildInput {\n table?: string\n createdAt?: string\n trigger?: Trigger\n run?: number\n phase?: Phase\n mode?: Record<string, 'client' | 'server'>\n state?: DiagnosticStateSummary\n /** Timestamp for `occurrences` (epoch ms). Default `wallClock()`. */\n now?: number\n cause?: unknown\n causedBy?: string\n /** Build the problem / impact / fix text. Default: development builds only (§8.2); production\n * builds also build it once `@datakable/core/messages` is installed. */\n dev?: boolean\n /** Redaction policy (§8.2). Default: `'keys'` when `dev`, else `'safe'`. */\n redaction?: Redactor\n}\n\n/**\n * Epoch ms read through `performance`, never `Date` (#7): Next 16 `cacheComponents` aborts a\n * prerender that reads `Date.now()` and reserves `performance` for introspection like this.\n */\nexport const wallClock = (): number =>\n typeof performance === 'object' && performance?.timeOrigin\n ? Math.floor(performance.timeOrigin + performance.now())\n : Date.now()\n\nexport const defaultPhase = (): Phase => (typeof document === 'undefined' ? 'ssr' : 'client')\n\nexport function formatWhere(where: Location): string {\n switch (where.kind) {\n case 'column':\n return `columns[${where.index}] (id \"${where.id}\")`\n case 'feature':\n return `feature \"${where.name}\"`\n case 'option':\n return `options.${where.path}`\n case 'row':\n return where.key === undefined\n ? `row #${where.index}`\n : `row #${where.index} (key ${where.key})`\n case 'interceptor':\n return `interceptor \"${where.name}\" on ${where.op}`\n case 'operation':\n return where.slot ? `operation ${where.op} at ${where.slot}` : `operation ${where.op}`\n }\n}\n\nclass DiagnosticRecord implements Diagnostic {\n constructor(\n public code: DiagnosticCode,\n public level: DiagnosticLevel,\n public problem: string,\n public where: Location,\n public impact: string,\n public fix: string[],\n public docs: string,\n public details: Record<string, unknown>,\n public context: DiagnosticContext,\n public fingerprint: string,\n ) {}\n\n toJSON(): object {\n const { cause: _cause, ...context } = this.context\n return {\n code: this.code,\n level: this.level,\n problem: this.problem,\n where: toSafeJson(this.where),\n impact: this.impact,\n fix: this.fix,\n docs: this.docs,\n details: toSafeJson(this.details),\n context: toSafeJson(context),\n fingerprint: this.fingerprint,\n }\n }\n}\n\n/**\n * Builds a diagnostic from a catalog code + details (the `enrich` step). Never throws for an unknown\n * code: that becomes `DK_INTERNAL`, so a typo in a plugin cannot take the logger down.\n */\nexport function buildDiagnostic<C extends DiagnosticCode>(\n code: C,\n details: DiagnosticDetails<C>,\n input: BuildInput = {},\n): Diagnostic {\n let def = getDiagnosticDefinition(code)\n let d = details as Record<string, unknown>\n if (!def) {\n def = INTERNAL\n d = {\n op: 'diagnostic:emit',\n problem: `unknown-code|${code}`,\n }\n }\n const b = def as unknown as DiagnosticDefinition<'DK_INTERNAL'>\n const dev = input.dev ?? (process.env.NODE_ENV !== \"production\")\n // Detail prose keys (`fallback: 'cells-undefined'`) read as sentences wherever text is built.\n if (dev || hasMessages()) d = expandDetails(d, dev)\n // Redact first: `where`, the text builders, the fingerprint and the docs URL only ever see\n // redacted data, so no consumer downstream (interceptors, sinks, strict errors) can leak it.\n const r = input.redaction ?? resolveRedaction(undefined, dev)\n const where = redactLocation(b.where(d as DiagnosticDetails<'DK_INTERNAL'>), r)\n d = redactDetails(\n d,\n def.redact as Readonly<Record<string, RedactField | undefined>> | undefined,\n where,\n r,\n )\n const dd = d as DiagnosticDetails<'DK_INTERNAL'>\n // Text: development builds, or production with `@datakable/core/messages` installed (§8.2).\n const t =\n dev || hasMessages()\n ? (getDiagnosticText(def.code) as DiagnosticText<'DK_INTERNAL'> | undefined)\n : undefined\n const whereText = formatWhere(where)\n const now = input.now ?? wallClock()\n const context: DiagnosticContext = {\n table: input.table ?? '(global)',\n package: PACKAGE,\n trigger: input.trigger ?? 'init',\n run: input.run ?? 0,\n phase: input.phase ?? defaultPhase(),\n mode: input.mode ?? {},\n state: input.state ?? { searchLength: 0, activeFilters: [], sort: [], page: 0 },\n occurrences: { count: 1, first: now, last: now },\n }\n if (input.createdAt !== undefined) context.createdAt = input.createdAt\n if (input.causedBy !== undefined) context.causedBy = input.causedBy\n if (input.cause !== undefined) context.cause = input.cause\n let docs = def.docs ?? `${DOCS}#${def.code.toLowerCase()}`\n if (!dev) {\n const hash = docs.indexOf('#')\n const params = `?v=${VERSION}&where=${encodeURIComponent(whereText)}`\n docs = hash < 0 ? docs + params : docs.slice(0, hash) + params + docs.slice(hash)\n }\n return new DiagnosticRecord(\n def.code,\n def.level,\n t ? t.problem(dd) : '',\n where,\n t ? t.impact(dd) : '',\n t ? t.fix(dd) : [],\n docs,\n d,\n context,\n `${def.code}@${whereText}`,\n )\n}\n\n/** Thrown under `strict: true` for error-level diagnostics, and for core invariants (§8.2). */\nexport class DatakableError extends Error {\n override name = 'DatakableError'\n readonly code: DiagnosticCode\n readonly level: DiagnosticLevel\n readonly problem: string\n readonly where: Location\n readonly impact: string\n readonly fix: string[]\n readonly docs: string\n readonly diagnostic: Diagnostic\n\n constructor(d: Diagnostic) {\n const lines = [`${d.code}: ${d.problem || '(see docs)'}`, ` where ${formatWhere(d.where)}`]\n d.fix.forEach((f, i) => {\n lines.push(`${i === 0 ? ' fix ' : ' '}${i + 1}. ${f}`)\n })\n lines.push(` docs ${d.docs}`)\n super(lines.join('\\n'), d.context.cause === undefined ? undefined : { cause: d.context.cause })\n this.code = d.code\n this.level = d.level\n this.problem = d.problem\n this.where = d.where\n this.impact = d.impact\n this.fix = d.fix\n this.docs = d.docs\n this.diagnostic = d\n }\n}\n\n/** Deterministic programmer errors thrown at creation (`error (config)` codes, §8.6). */\nexport class DatakableConfigError extends DatakableError {\n override name = 'DatakableConfigError'\n}\n\nexport function throwConfigError<C extends DiagnosticCode>(\n code: C,\n details: DiagnosticDetails<C>,\n input?: BuildInput,\n): never {\n throw new DatakableConfigError(buildDiagnostic(code, details, input))\n}\n\n/** A core invariant broke (unregistered op, boundary installed twice): `DK_INTERNAL`. */\nexport function internalError(op: string, problem: string): DatakableError {\n return new DatakableError(buildDiagnostic('DK_INTERNAL', { op, problem }))\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/diagnostics/build.ts"],"sourcesContent":["import { VERSION } from '../version'\nimport {\n type DiagnosticCode,\n type DiagnosticDefinition,\n type DiagnosticDetails,\n type DiagnosticText,\n getDiagnosticDefinition,\n getDiagnosticText,\n hasMessages,\n} from './catalog'\nimport { coreDiagnostics } from './codes'\nimport './process-guard'\nimport { expandDetails, proseArg } from './prose'\nimport {\n type RedactField,\n type Redactor,\n redactDetails,\n redactLocation,\n resolveRedaction,\n} from './redact'\nimport { toSafeJson } from './safe-json'\nimport type {\n Diagnostic,\n DiagnosticContext,\n DiagnosticLevel,\n DiagnosticStateSummary,\n Location,\n Phase,\n Trigger,\n} from './types'\n\nexport const PACKAGE = `@datakable/core@${VERSION}`\nconst DOCS = 'https://github.com/Ink01101011/datakable/blob/main/docs/errors.md'\n\n// Referencing the core entries keeps them in the bundle (`sideEffects: false`).\nconst INTERNAL = coreDiagnostics.find((d) => d.code === 'DK_INTERNAL') as DiagnosticDefinition\n\n/** Everything the enrich step adds; all optional so a diagnostic can be built outside a table. */\nexport interface BuildInput {\n table?: string\n createdAt?: string\n trigger?: Trigger\n run?: number\n phase?: Phase\n mode?: Record<string, 'client' | 'server'>\n state?: DiagnosticStateSummary\n /** Timestamp for `occurrences` (epoch ms). Default `wallClock()`. */\n now?: number\n cause?: unknown\n causedBy?: string\n /** Build the problem / impact / fix text. Default: development builds only (§8.2); production\n * builds also build it once `@datakable/core/messages` is installed. */\n dev?: boolean\n /** Redaction policy (§8.2). Default: `'keys'` when `dev`, else `'safe'`. */\n redaction?: Redactor\n}\n\n/**\n * Epoch ms read through `performance`, never `Date` (#7): Next 16 `cacheComponents` aborts a\n * prerender that reads `Date.now()` and reserves `performance` for introspection like this.\n */\nexport const wallClock = (): number =>\n typeof performance === 'object' && performance?.timeOrigin\n ? Math.floor(performance.timeOrigin + performance.now())\n : Date.now()\n\nexport const defaultPhase = (): Phase => (typeof document === 'undefined' ? 'ssr' : 'client')\n\nexport function formatWhere(where: Location): string {\n switch (where.kind) {\n case 'column':\n return `columns[${where.index}] (id \"${where.id}\")`\n case 'feature':\n return `feature \"${where.name}\"`\n case 'option':\n return `options.${where.path}`\n case 'row':\n return where.key === undefined\n ? `row #${where.index}`\n : `row #${where.index} (key ${where.key})`\n case 'interceptor':\n return `interceptor \"${where.name}\" on ${where.op}`\n case 'operation':\n return where.slot ? `operation ${where.op} at ${where.slot}` : `operation ${where.op}`\n }\n}\n\nclass DiagnosticRecord implements Diagnostic {\n constructor(\n public code: DiagnosticCode,\n public level: DiagnosticLevel,\n public problem: string,\n public where: Location,\n public impact: string,\n public fix: string[],\n public docs: string,\n public details: Record<string, unknown>,\n public context: DiagnosticContext,\n public fingerprint: string,\n ) {}\n\n toJSON(): object {\n const { cause: _cause, ...context } = this.context\n return {\n code: this.code,\n level: this.level,\n problem: this.problem,\n where: toSafeJson(this.where),\n impact: this.impact,\n fix: this.fix,\n docs: this.docs,\n details: toSafeJson(this.details),\n context: toSafeJson(context),\n fingerprint: this.fingerprint,\n }\n }\n}\n\n/**\n * Builds a diagnostic from a catalog code + details (the `enrich` step). Never throws for an unknown\n * code: that becomes `DK_INTERNAL`, so a typo in a plugin cannot take the logger down.\n */\nexport function buildDiagnostic<C extends DiagnosticCode>(\n code: C,\n details: DiagnosticDetails<C>,\n input: BuildInput = {},\n): Diagnostic {\n let def = getDiagnosticDefinition(code)\n let d = details as Record<string, unknown>\n if (!def) {\n def = INTERNAL\n d = {\n op: 'diagnostic:emit',\n problem: `unknown-code|${proseArg(code)}`,\n }\n }\n const b = def as unknown as DiagnosticDefinition<'DK_INTERNAL'>\n const dev = input.dev ?? (process.env.NODE_ENV !== \"production\")\n // Detail prose keys (`fallback: 'cells-undefined'`) read as sentences wherever text is built.\n if (dev || hasMessages()) d = expandDetails(d, dev)\n // Redact first: `where`, the text builders, the fingerprint and the docs URL only ever see\n // redacted data, so no consumer downstream (interceptors, sinks, strict errors) can leak it.\n const r = input.redaction ?? resolveRedaction(undefined, dev)\n const where = redactLocation(b.where(d as DiagnosticDetails<'DK_INTERNAL'>), r)\n d = redactDetails(\n d,\n def.redact as Readonly<Record<string, RedactField | undefined>> | undefined,\n where,\n r,\n )\n const dd = d as DiagnosticDetails<'DK_INTERNAL'>\n // Text: development builds, or production with `@datakable/core/messages` installed (§8.2).\n const t =\n dev || hasMessages()\n ? (getDiagnosticText(def.code) as DiagnosticText<'DK_INTERNAL'> | undefined)\n : undefined\n const whereText = formatWhere(where)\n const now = input.now ?? wallClock()\n const context: DiagnosticContext = {\n table: input.table ?? '(global)',\n package: PACKAGE,\n trigger: input.trigger ?? 'init',\n run: input.run ?? 0,\n phase: input.phase ?? defaultPhase(),\n mode: input.mode ?? {},\n state: input.state ?? { searchLength: 0, activeFilters: [], sort: [], page: 0 },\n occurrences: { count: 1, first: now, last: now },\n }\n if (input.createdAt !== undefined) context.createdAt = input.createdAt\n if (input.causedBy !== undefined) context.causedBy = input.causedBy\n if (input.cause !== undefined) context.cause = input.cause\n let docs = def.docs ?? `${DOCS}#${def.code.toLowerCase()}`\n if (!dev) {\n const hash = docs.indexOf('#')\n const params = `?v=${VERSION}&where=${encodeURIComponent(whereText)}`\n docs = hash < 0 ? docs + params : docs.slice(0, hash) + params + docs.slice(hash)\n }\n return new DiagnosticRecord(\n def.code,\n def.level,\n t ? t.problem(dd) : '',\n where,\n t ? t.impact(dd) : '',\n t ? t.fix(dd) : [],\n docs,\n d,\n context,\n `${def.code}@${whereText}`,\n )\n}\n\n/** Thrown under `strict: true` for error-level diagnostics, and for core invariants (§8.2). */\nexport class DatakableError extends Error {\n override name = 'DatakableError'\n readonly code: DiagnosticCode\n readonly level: DiagnosticLevel\n readonly problem: string\n readonly where: Location\n readonly impact: string\n readonly fix: string[]\n readonly docs: string\n readonly diagnostic: Diagnostic\n\n constructor(d: Diagnostic) {\n const lines = [`${d.code}: ${d.problem || '(see docs)'}`, ` where ${formatWhere(d.where)}`]\n d.fix.forEach((f, i) => {\n lines.push(`${i === 0 ? ' fix ' : ' '}${i + 1}. ${f}`)\n })\n lines.push(` docs ${d.docs}`)\n super(lines.join('\\n'), d.context.cause === undefined ? undefined : { cause: d.context.cause })\n this.code = d.code\n this.level = d.level\n this.problem = d.problem\n this.where = d.where\n this.impact = d.impact\n this.fix = d.fix\n this.docs = d.docs\n this.diagnostic = d\n }\n}\n\n/** Deterministic programmer errors thrown at creation (`error (config)` codes, §8.6). */\nexport class DatakableConfigError extends DatakableError {\n override name = 'DatakableConfigError'\n}\n\nexport function throwConfigError<C extends DiagnosticCode>(\n code: C,\n details: DiagnosticDetails<C>,\n input?: BuildInput,\n): never {\n throw new DatakableConfigError(buildDiagnostic(code, details, input))\n}\n\n/** A core invariant broke (unregistered op, boundary installed twice): `DK_INTERNAL`. */\nexport function internalError(op: string, problem: string): DatakableError {\n return new DatakableError(buildDiagnostic('DK_INTERNAL', { op, problem }))\n}\n"],"mappings":"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","names":[]}
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
} from "./catalog.js";
|
|
8
8
|
import { coreDiagnostics } from "./codes.js";
|
|
9
9
|
import "./process-guard.js";
|
|
10
|
-
import { expandDetails } from "./prose.js";
|
|
10
|
+
import { expandDetails, proseArg } from "./prose.js";
|
|
11
11
|
import {
|
|
12
12
|
redactDetails,
|
|
13
13
|
redactLocation,
|
|
@@ -71,7 +71,7 @@ function buildDiagnostic(code, details, input = {}) {
|
|
|
71
71
|
def = INTERNAL;
|
|
72
72
|
d = {
|
|
73
73
|
op: "diagnostic:emit",
|
|
74
|
-
problem: `unknown-code|${code}`
|
|
74
|
+
problem: `unknown-code|${proseArg(code)}`
|
|
75
75
|
};
|
|
76
76
|
}
|
|
77
77
|
const b = def;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/diagnostics/build.ts"],"sourcesContent":["import { VERSION } from '../version'\nimport {\n type DiagnosticCode,\n type DiagnosticDefinition,\n type DiagnosticDetails,\n type DiagnosticText,\n getDiagnosticDefinition,\n getDiagnosticText,\n hasMessages,\n} from './catalog'\nimport { coreDiagnostics } from './codes'\nimport './process-guard'\nimport { expandDetails } from './prose'\nimport {\n type RedactField,\n type Redactor,\n redactDetails,\n redactLocation,\n resolveRedaction,\n} from './redact'\nimport { toSafeJson } from './safe-json'\nimport type {\n Diagnostic,\n DiagnosticContext,\n DiagnosticLevel,\n DiagnosticStateSummary,\n Location,\n Phase,\n Trigger,\n} from './types'\n\nexport const PACKAGE = `@datakable/core@${VERSION}`\nconst DOCS = 'https://github.com/Ink01101011/datakable/blob/main/docs/errors.md'\n\n// Referencing the core entries keeps them in the bundle (`sideEffects: false`).\nconst INTERNAL = coreDiagnostics.find((d) => d.code === 'DK_INTERNAL') as DiagnosticDefinition\n\n/** Everything the enrich step adds; all optional so a diagnostic can be built outside a table. */\nexport interface BuildInput {\n table?: string\n createdAt?: string\n trigger?: Trigger\n run?: number\n phase?: Phase\n mode?: Record<string, 'client' | 'server'>\n state?: DiagnosticStateSummary\n /** Timestamp for `occurrences` (epoch ms). Default `wallClock()`. */\n now?: number\n cause?: unknown\n causedBy?: string\n /** Build the problem / impact / fix text. Default: development builds only (§8.2); production\n * builds also build it once `@datakable/core/messages` is installed. */\n dev?: boolean\n /** Redaction policy (§8.2). Default: `'keys'` when `dev`, else `'safe'`. */\n redaction?: Redactor\n}\n\n/**\n * Epoch ms read through `performance`, never `Date` (#7): Next 16 `cacheComponents` aborts a\n * prerender that reads `Date.now()` and reserves `performance` for introspection like this.\n */\nexport const wallClock = (): number =>\n typeof performance === 'object' && performance?.timeOrigin\n ? Math.floor(performance.timeOrigin + performance.now())\n : Date.now()\n\nexport const defaultPhase = (): Phase => (typeof document === 'undefined' ? 'ssr' : 'client')\n\nexport function formatWhere(where: Location): string {\n switch (where.kind) {\n case 'column':\n return `columns[${where.index}] (id \"${where.id}\")`\n case 'feature':\n return `feature \"${where.name}\"`\n case 'option':\n return `options.${where.path}`\n case 'row':\n return where.key === undefined\n ? `row #${where.index}`\n : `row #${where.index} (key ${where.key})`\n case 'interceptor':\n return `interceptor \"${where.name}\" on ${where.op}`\n case 'operation':\n return where.slot ? `operation ${where.op} at ${where.slot}` : `operation ${where.op}`\n }\n}\n\nclass DiagnosticRecord implements Diagnostic {\n constructor(\n public code: DiagnosticCode,\n public level: DiagnosticLevel,\n public problem: string,\n public where: Location,\n public impact: string,\n public fix: string[],\n public docs: string,\n public details: Record<string, unknown>,\n public context: DiagnosticContext,\n public fingerprint: string,\n ) {}\n\n toJSON(): object {\n const { cause: _cause, ...context } = this.context\n return {\n code: this.code,\n level: this.level,\n problem: this.problem,\n where: toSafeJson(this.where),\n impact: this.impact,\n fix: this.fix,\n docs: this.docs,\n details: toSafeJson(this.details),\n context: toSafeJson(context),\n fingerprint: this.fingerprint,\n }\n }\n}\n\n/**\n * Builds a diagnostic from a catalog code + details (the `enrich` step). Never throws for an unknown\n * code: that becomes `DK_INTERNAL`, so a typo in a plugin cannot take the logger down.\n */\nexport function buildDiagnostic<C extends DiagnosticCode>(\n code: C,\n details: DiagnosticDetails<C>,\n input: BuildInput = {},\n): Diagnostic {\n let def = getDiagnosticDefinition(code)\n let d = details as Record<string, unknown>\n if (!def) {\n def = INTERNAL\n d = {\n op: 'diagnostic:emit',\n problem: `unknown-code|${code}`,\n }\n }\n const b = def as unknown as DiagnosticDefinition<'DK_INTERNAL'>\n const dev = input.dev ?? (process.env.NODE_ENV !== \"production\")\n // Detail prose keys (`fallback: 'cells-undefined'`) read as sentences wherever text is built.\n if (dev || hasMessages()) d = expandDetails(d, dev)\n // Redact first: `where`, the text builders, the fingerprint and the docs URL only ever see\n // redacted data, so no consumer downstream (interceptors, sinks, strict errors) can leak it.\n const r = input.redaction ?? resolveRedaction(undefined, dev)\n const where = redactLocation(b.where(d as DiagnosticDetails<'DK_INTERNAL'>), r)\n d = redactDetails(\n d,\n def.redact as Readonly<Record<string, RedactField | undefined>> | undefined,\n where,\n r,\n )\n const dd = d as DiagnosticDetails<'DK_INTERNAL'>\n // Text: development builds, or production with `@datakable/core/messages` installed (§8.2).\n const t =\n dev || hasMessages()\n ? (getDiagnosticText(def.code) as DiagnosticText<'DK_INTERNAL'> | undefined)\n : undefined\n const whereText = formatWhere(where)\n const now = input.now ?? wallClock()\n const context: DiagnosticContext = {\n table: input.table ?? '(global)',\n package: PACKAGE,\n trigger: input.trigger ?? 'init',\n run: input.run ?? 0,\n phase: input.phase ?? defaultPhase(),\n mode: input.mode ?? {},\n state: input.state ?? { searchLength: 0, activeFilters: [], sort: [], page: 0 },\n occurrences: { count: 1, first: now, last: now },\n }\n if (input.createdAt !== undefined) context.createdAt = input.createdAt\n if (input.causedBy !== undefined) context.causedBy = input.causedBy\n if (input.cause !== undefined) context.cause = input.cause\n let docs = def.docs ?? `${DOCS}#${def.code.toLowerCase()}`\n if (!dev) {\n const hash = docs.indexOf('#')\n const params = `?v=${VERSION}&where=${encodeURIComponent(whereText)}`\n docs = hash < 0 ? docs + params : docs.slice(0, hash) + params + docs.slice(hash)\n }\n return new DiagnosticRecord(\n def.code,\n def.level,\n t ? t.problem(dd) : '',\n where,\n t ? t.impact(dd) : '',\n t ? t.fix(dd) : [],\n docs,\n d,\n context,\n `${def.code}@${whereText}`,\n )\n}\n\n/** Thrown under `strict: true` for error-level diagnostics, and for core invariants (§8.2). */\nexport class DatakableError extends Error {\n override name = 'DatakableError'\n readonly code: DiagnosticCode\n readonly level: DiagnosticLevel\n readonly problem: string\n readonly where: Location\n readonly impact: string\n readonly fix: string[]\n readonly docs: string\n readonly diagnostic: Diagnostic\n\n constructor(d: Diagnostic) {\n const lines = [`${d.code}: ${d.problem || '(see docs)'}`, ` where ${formatWhere(d.where)}`]\n d.fix.forEach((f, i) => {\n lines.push(`${i === 0 ? ' fix ' : ' '}${i + 1}. ${f}`)\n })\n lines.push(` docs ${d.docs}`)\n super(lines.join('\\n'), d.context.cause === undefined ? undefined : { cause: d.context.cause })\n this.code = d.code\n this.level = d.level\n this.problem = d.problem\n this.where = d.where\n this.impact = d.impact\n this.fix = d.fix\n this.docs = d.docs\n this.diagnostic = d\n }\n}\n\n/** Deterministic programmer errors thrown at creation (`error (config)` codes, §8.6). */\nexport class DatakableConfigError extends DatakableError {\n override name = 'DatakableConfigError'\n}\n\nexport function throwConfigError<C extends DiagnosticCode>(\n code: C,\n details: DiagnosticDetails<C>,\n input?: BuildInput,\n): never {\n throw new DatakableConfigError(buildDiagnostic(code, details, input))\n}\n\n/** A core invariant broke (unregistered op, boundary installed twice): `DK_INTERNAL`. */\nexport function internalError(op: string, problem: string): DatakableError {\n return new DatakableError(buildDiagnostic('DK_INTERNAL', { op, problem }))\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/diagnostics/build.ts"],"sourcesContent":["import { VERSION } from '../version'\nimport {\n type DiagnosticCode,\n type DiagnosticDefinition,\n type DiagnosticDetails,\n type DiagnosticText,\n getDiagnosticDefinition,\n getDiagnosticText,\n hasMessages,\n} from './catalog'\nimport { coreDiagnostics } from './codes'\nimport './process-guard'\nimport { expandDetails, proseArg } from './prose'\nimport {\n type RedactField,\n type Redactor,\n redactDetails,\n redactLocation,\n resolveRedaction,\n} from './redact'\nimport { toSafeJson } from './safe-json'\nimport type {\n Diagnostic,\n DiagnosticContext,\n DiagnosticLevel,\n DiagnosticStateSummary,\n Location,\n Phase,\n Trigger,\n} from './types'\n\nexport const PACKAGE = `@datakable/core@${VERSION}`\nconst DOCS = 'https://github.com/Ink01101011/datakable/blob/main/docs/errors.md'\n\n// Referencing the core entries keeps them in the bundle (`sideEffects: false`).\nconst INTERNAL = coreDiagnostics.find((d) => d.code === 'DK_INTERNAL') as DiagnosticDefinition\n\n/** Everything the enrich step adds; all optional so a diagnostic can be built outside a table. */\nexport interface BuildInput {\n table?: string\n createdAt?: string\n trigger?: Trigger\n run?: number\n phase?: Phase\n mode?: Record<string, 'client' | 'server'>\n state?: DiagnosticStateSummary\n /** Timestamp for `occurrences` (epoch ms). Default `wallClock()`. */\n now?: number\n cause?: unknown\n causedBy?: string\n /** Build the problem / impact / fix text. Default: development builds only (§8.2); production\n * builds also build it once `@datakable/core/messages` is installed. */\n dev?: boolean\n /** Redaction policy (§8.2). Default: `'keys'` when `dev`, else `'safe'`. */\n redaction?: Redactor\n}\n\n/**\n * Epoch ms read through `performance`, never `Date` (#7): Next 16 `cacheComponents` aborts a\n * prerender that reads `Date.now()` and reserves `performance` for introspection like this.\n */\nexport const wallClock = (): number =>\n typeof performance === 'object' && performance?.timeOrigin\n ? Math.floor(performance.timeOrigin + performance.now())\n : Date.now()\n\nexport const defaultPhase = (): Phase => (typeof document === 'undefined' ? 'ssr' : 'client')\n\nexport function formatWhere(where: Location): string {\n switch (where.kind) {\n case 'column':\n return `columns[${where.index}] (id \"${where.id}\")`\n case 'feature':\n return `feature \"${where.name}\"`\n case 'option':\n return `options.${where.path}`\n case 'row':\n return where.key === undefined\n ? `row #${where.index}`\n : `row #${where.index} (key ${where.key})`\n case 'interceptor':\n return `interceptor \"${where.name}\" on ${where.op}`\n case 'operation':\n return where.slot ? `operation ${where.op} at ${where.slot}` : `operation ${where.op}`\n }\n}\n\nclass DiagnosticRecord implements Diagnostic {\n constructor(\n public code: DiagnosticCode,\n public level: DiagnosticLevel,\n public problem: string,\n public where: Location,\n public impact: string,\n public fix: string[],\n public docs: string,\n public details: Record<string, unknown>,\n public context: DiagnosticContext,\n public fingerprint: string,\n ) {}\n\n toJSON(): object {\n const { cause: _cause, ...context } = this.context\n return {\n code: this.code,\n level: this.level,\n problem: this.problem,\n where: toSafeJson(this.where),\n impact: this.impact,\n fix: this.fix,\n docs: this.docs,\n details: toSafeJson(this.details),\n context: toSafeJson(context),\n fingerprint: this.fingerprint,\n }\n }\n}\n\n/**\n * Builds a diagnostic from a catalog code + details (the `enrich` step). Never throws for an unknown\n * code: that becomes `DK_INTERNAL`, so a typo in a plugin cannot take the logger down.\n */\nexport function buildDiagnostic<C extends DiagnosticCode>(\n code: C,\n details: DiagnosticDetails<C>,\n input: BuildInput = {},\n): Diagnostic {\n let def = getDiagnosticDefinition(code)\n let d = details as Record<string, unknown>\n if (!def) {\n def = INTERNAL\n d = {\n op: 'diagnostic:emit',\n problem: `unknown-code|${proseArg(code)}`,\n }\n }\n const b = def as unknown as DiagnosticDefinition<'DK_INTERNAL'>\n const dev = input.dev ?? (process.env.NODE_ENV !== \"production\")\n // Detail prose keys (`fallback: 'cells-undefined'`) read as sentences wherever text is built.\n if (dev || hasMessages()) d = expandDetails(d, dev)\n // Redact first: `where`, the text builders, the fingerprint and the docs URL only ever see\n // redacted data, so no consumer downstream (interceptors, sinks, strict errors) can leak it.\n const r = input.redaction ?? resolveRedaction(undefined, dev)\n const where = redactLocation(b.where(d as DiagnosticDetails<'DK_INTERNAL'>), r)\n d = redactDetails(\n d,\n def.redact as Readonly<Record<string, RedactField | undefined>> | undefined,\n where,\n r,\n )\n const dd = d as DiagnosticDetails<'DK_INTERNAL'>\n // Text: development builds, or production with `@datakable/core/messages` installed (§8.2).\n const t =\n dev || hasMessages()\n ? (getDiagnosticText(def.code) as DiagnosticText<'DK_INTERNAL'> | undefined)\n : undefined\n const whereText = formatWhere(where)\n const now = input.now ?? wallClock()\n const context: DiagnosticContext = {\n table: input.table ?? '(global)',\n package: PACKAGE,\n trigger: input.trigger ?? 'init',\n run: input.run ?? 0,\n phase: input.phase ?? defaultPhase(),\n mode: input.mode ?? {},\n state: input.state ?? { searchLength: 0, activeFilters: [], sort: [], page: 0 },\n occurrences: { count: 1, first: now, last: now },\n }\n if (input.createdAt !== undefined) context.createdAt = input.createdAt\n if (input.causedBy !== undefined) context.causedBy = input.causedBy\n if (input.cause !== undefined) context.cause = input.cause\n let docs = def.docs ?? `${DOCS}#${def.code.toLowerCase()}`\n if (!dev) {\n const hash = docs.indexOf('#')\n const params = `?v=${VERSION}&where=${encodeURIComponent(whereText)}`\n docs = hash < 0 ? docs + params : docs.slice(0, hash) + params + docs.slice(hash)\n }\n return new DiagnosticRecord(\n def.code,\n def.level,\n t ? t.problem(dd) : '',\n where,\n t ? t.impact(dd) : '',\n t ? t.fix(dd) : [],\n docs,\n d,\n context,\n `${def.code}@${whereText}`,\n )\n}\n\n/** Thrown under `strict: true` for error-level diagnostics, and for core invariants (§8.2). */\nexport class DatakableError extends Error {\n override name = 'DatakableError'\n readonly code: DiagnosticCode\n readonly level: DiagnosticLevel\n readonly problem: string\n readonly where: Location\n readonly impact: string\n readonly fix: string[]\n readonly docs: string\n readonly diagnostic: Diagnostic\n\n constructor(d: Diagnostic) {\n const lines = [`${d.code}: ${d.problem || '(see docs)'}`, ` where ${formatWhere(d.where)}`]\n d.fix.forEach((f, i) => {\n lines.push(`${i === 0 ? ' fix ' : ' '}${i + 1}. ${f}`)\n })\n lines.push(` docs ${d.docs}`)\n super(lines.join('\\n'), d.context.cause === undefined ? undefined : { cause: d.context.cause })\n this.code = d.code\n this.level = d.level\n this.problem = d.problem\n this.where = d.where\n this.impact = d.impact\n this.fix = d.fix\n this.docs = d.docs\n this.diagnostic = d\n }\n}\n\n/** Deterministic programmer errors thrown at creation (`error (config)` codes, §8.6). */\nexport class DatakableConfigError extends DatakableError {\n override name = 'DatakableConfigError'\n}\n\nexport function throwConfigError<C extends DiagnosticCode>(\n code: C,\n details: DiagnosticDetails<C>,\n input?: BuildInput,\n): never {\n throw new DatakableConfigError(buildDiagnostic(code, details, input))\n}\n\n/** A core invariant broke (unregistered op, boundary installed twice): `DK_INTERNAL`. */\nexport function internalError(op: string, problem: string): DatakableError {\n return new DatakableError(buildDiagnostic('DK_INTERNAL', { op, problem }))\n}\n"],"mappings":"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","names":[]}
|
|
@@ -27,8 +27,17 @@ module.exports = __toCommonJS(console_exports);
|
|
|
27
27
|
var import_build = require("./build.cjs");
|
|
28
28
|
var import_process_guard = require("./process-guard.cjs");
|
|
29
29
|
var ICON = { error: "\u2716", warn: "\u26A0", info: "\u2139" };
|
|
30
|
+
var printable = (s) => (
|
|
31
|
+
// biome-ignore lint/suspicious/noControlCharactersInRegex: the characters to escape
|
|
32
|
+
s.replace(
|
|
33
|
+
/[\u0000-\u001f\u007f-\u009f\u2028\u2029]/g,
|
|
34
|
+
(c) => c === "\n" ? "\\n" : `\\u${(c.charCodeAt(0) + 65536).toString(16).slice(1)}`
|
|
35
|
+
)
|
|
36
|
+
);
|
|
30
37
|
function formatDiagnostic(d) {
|
|
31
|
-
const header =
|
|
38
|
+
const header = printable(
|
|
39
|
+
`${ICON[d.level]} [DataKable ${d.context.table}] ${d.code}: ${d.problem}`
|
|
40
|
+
);
|
|
32
41
|
const lines = [` where ${(0, import_build.formatWhere)(d.where)}`];
|
|
33
42
|
if (d.impact) lines.push(` impact ${d.impact}`);
|
|
34
43
|
d.fix.forEach((f, i) => {
|
|
@@ -37,7 +46,7 @@ function formatDiagnostic(d) {
|
|
|
37
46
|
lines.push(` docs ${d.docs}`);
|
|
38
47
|
const c = d.context;
|
|
39
48
|
lines.push(` context trigger=${c.trigger} run=${c.run} phase=${c.phase}`);
|
|
40
|
-
return { header, body: lines.join("\n") };
|
|
49
|
+
return { header, body: lines.map(printable).join("\n") };
|
|
41
50
|
}
|
|
42
51
|
function createConsoleSink(o) {
|
|
43
52
|
let windowStart = Number.NEGATIVE_INFINITY;
|
|
@@ -49,7 +58,7 @@ function createConsoleSink(o) {
|
|
|
49
58
|
if (t - windowStart >= o.rateLimit.windowMs) {
|
|
50
59
|
if (suppressed > 0) {
|
|
51
60
|
console.warn(
|
|
52
|
-
`[DataKable ${o.table}] ${suppressed} diagnostics were not printed (rate limit); read them with getDiagnostics() or onDiagnostic`
|
|
61
|
+
`[DataKable ${printable(o.table)}] ${suppressed} diagnostics were not printed (rate limit); read them with getDiagnostics() or onDiagnostic`
|
|
53
62
|
);
|
|
54
63
|
}
|
|
55
64
|
windowStart = t;
|
|
@@ -74,7 +83,9 @@ ${body}`);
|
|
|
74
83
|
console.groupEnd();
|
|
75
84
|
return;
|
|
76
85
|
}
|
|
77
|
-
console.error(
|
|
86
|
+
console.error(
|
|
87
|
+
printable(`[DataKable ${o.table}] ${d.code} at ${(0, import_build.formatWhere)(d.where)} \u2014 ${d.docs}`)
|
|
88
|
+
);
|
|
78
89
|
};
|
|
79
90
|
}
|
|
80
91
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/diagnostics/console.ts"],"sourcesContent":["import { formatWhere } from './build'\nimport './process-guard'\nimport type { Diagnostic } from './types'\n\nconst ICON = { error: '✖', warn: '⚠', info: 'ℹ' } as const\n\n
|
|
1
|
+
{"version":3,"sources":["../../src/diagnostics/console.ts"],"sourcesContent":["import { formatWhere } from './build'\nimport './process-guard'\nimport type { Diagnostic } from './types'\n\nconst ICON = { error: '✖', warn: '⚠', info: 'ℹ' } as const\n\n/**\n * Console text is printed with its C0 / C1 control characters, DEL and line breaks escaped\n * (`\\u001b`, `\\n`, ...): ids, keys and table names can come from URLs or data, and must not\n * forge a line or send terminal escapes (#104). The diagnostic object keeps the raw values.\n */\nconst printable = (s: string): string =>\n // biome-ignore lint/suspicious/noControlCharactersInRegex: the characters to escape\n s.replace(/[\\u0000-\\u001f\\u007f-\\u009f\\u2028\\u2029]/g, (c) =>\n c === '\\n' ? '\\\\n' : `\\\\u${(c.charCodeAt(0) + 0x10000).toString(16).slice(1)}`,\n )\n\n/**\n * The §8.1 console text: header + aligned body, each line {@link printable}. Also usable by\n * explain() and tests.\n */\nexport function formatDiagnostic(d: Diagnostic): { header: string; body: string } {\n const header = printable(\n `${ICON[d.level]} [DataKable ${d.context.table}] ${d.code}: ${d.problem}`,\n )\n const lines = [` where ${formatWhere(d.where)}`]\n if (d.impact) lines.push(` impact ${d.impact}`)\n d.fix.forEach((f, i) => {\n lines.push(`${i === 0 ? ' fix ' : ' '}${i + 1}. ${f}`)\n })\n lines.push(` docs ${d.docs}`)\n const c = d.context\n lines.push(` context trigger=${c.trigger} run=${c.run} phase=${c.phase}`)\n return { header, body: lines.map(printable).join('\\n') }\n}\n\nexport interface ConsoleSinkOptions {\n table: string\n dev: boolean\n rateLimit: { max: number; windowMs: number }\n now: () => number\n}\n\n/**\n * Default console sink (§8.2): dev prints one collapsed group per diagnostic; prod prints\n * error level only, on one line. A fixed-window rate limit protects the console; what it holds back\n * is still in getDiagnostics() and onDiagnostic.\n */\nexport function createConsoleSink(o: ConsoleSinkOptions): (d: Diagnostic) => void {\n let windowStart = Number.NEGATIVE_INFINITY\n let printed = 0\n let suppressed = 0\n // The grouped format is development-only: a production build prints one line (§8.2). `(process.env.NODE_ENV !== \"production\")` is\n // read inline so the bundler drops the grouped branch.\n return (d) => {\n if ((!(process.env.NODE_ENV !== \"production\") || !o.dev) && d.level !== 'error') return\n const t = o.now()\n if (t - windowStart >= o.rateLimit.windowMs) {\n if (suppressed > 0) {\n console.warn(\n `[DataKable ${printable(o.table)}] ${suppressed} diagnostics were not printed (rate limit); ` +\n 'read them with getDiagnostics() or onDiagnostic',\n )\n }\n windowStart = t\n printed = 0\n suppressed = 0\n }\n if (printed >= o.rateLimit.max) {\n suppressed++\n return\n }\n printed++\n // `(process.env.NODE_ENV !== \"production\") &&` first, not an early `if (!(process.env.NODE_ENV !== \"production\")) return`: a branch that folds to `false` is removed\n // while parsing, so a production bundle keeps no `formatDiagnostic` (code after a folded early\n // return is dropped only when printing, after tree shaking kept what it calls).\n if ((process.env.NODE_ENV !== \"production\") && o.dev) {\n const { header, body } = formatDiagnostic(d)\n const log = d.level === 'error' ? 'error' : d.level === 'warn' ? 'warn' : 'info'\n // Runtimes without console groups (the Edge Runtime: log/info/warn/error/debug only) get the\n // same text as one call.\n if (typeof console.groupCollapsed !== 'function' || typeof console.groupEnd !== 'function') {\n console[log](`${header}\\n${body}`)\n return\n }\n console.groupCollapsed(header)\n console[log](body)\n console.groupEnd()\n return\n }\n console.error(\n printable(`[DataKable ${o.table}] ${d.code} at ${formatWhere(d.where)} — ${d.docs}`),\n )\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAA4B;AAC5B,2BAAO;AAGP,IAAM,OAAO,EAAE,OAAO,UAAK,MAAM,UAAK,MAAM,SAAI;AAOhD,IAAM,YAAY,CAAC;AAAA;AAAA,EAEjB,EAAE;AAAA,IAAQ;AAAA,IAA6C,CAAC,MACtD,MAAM,OAAO,QAAQ,OAAO,EAAE,WAAW,CAAC,IAAI,OAAS,SAAS,EAAE,EAAE,MAAM,CAAC,CAAC;AAAA,EAC9E;AAAA;AAMK,SAAS,iBAAiB,GAAiD;AAChF,QAAM,SAAS;AAAA,IACb,GAAG,KAAK,EAAE,KAAK,CAAC,eAAe,EAAE,QAAQ,KAAK,KAAK,EAAE,IAAI,KAAK,EAAE,OAAO;AAAA,EACzE;AACA,QAAM,QAAQ,CAAC,iBAAa,0BAAY,EAAE,KAAK,CAAC,EAAE;AAClD,MAAI,EAAE,OAAQ,OAAM,KAAK,aAAa,EAAE,MAAM,EAAE;AAChD,IAAE,IAAI,QAAQ,CAAC,GAAG,MAAM;AACtB,UAAM,KAAK,GAAG,MAAM,IAAI,eAAe,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE;AAAA,EACrE,CAAC;AACD,QAAM,KAAK,aAAa,EAAE,IAAI,EAAE;AAChC,QAAM,IAAI,EAAE;AACZ,QAAM,KAAK,qBAAqB,EAAE,OAAO,QAAQ,EAAE,GAAG,UAAU,EAAE,KAAK,EAAE;AACzE,SAAO,EAAE,QAAQ,MAAM,MAAM,IAAI,SAAS,EAAE,KAAK,IAAI,EAAE;AACzD;AAcO,SAAS,kBAAkB,GAAgD;AAChF,MAAI,cAAc,OAAO;AACzB,MAAI,UAAU;AACd,MAAI,aAAa;AAGjB,SAAO,CAAC,MAAM;AACZ,SAAK,EAAE,QAAQ,IAAI,aAAa,iBAAiB,CAAC,EAAE,QAAQ,EAAE,UAAU,QAAS;AACjF,UAAM,IAAI,EAAE,IAAI;AAChB,QAAI,IAAI,eAAe,EAAE,UAAU,UAAU;AAC3C,UAAI,aAAa,GAAG;AAClB,gBAAQ;AAAA,UACN,cAAc,UAAU,EAAE,KAAK,CAAC,KAAK,UAAU;AAAA,QAEjD;AAAA,MACF;AACA,oBAAc;AACd,gBAAU;AACV,mBAAa;AAAA,IACf;AACA,QAAI,WAAW,EAAE,UAAU,KAAK;AAC9B;AACA;AAAA,IACF;AACA;AAIA,QAAK,QAAQ,IAAI,aAAa,gBAAiB,EAAE,KAAK;AACpD,YAAM,EAAE,QAAQ,KAAK,IAAI,iBAAiB,CAAC;AAC3C,YAAM,MAAM,EAAE,UAAU,UAAU,UAAU,EAAE,UAAU,SAAS,SAAS;AAG1E,UAAI,OAAO,QAAQ,mBAAmB,cAAc,OAAO,QAAQ,aAAa,YAAY;AAC1F,gBAAQ,GAAG,EAAE,GAAG,MAAM;AAAA,EAAK,IAAI,EAAE;AACjC;AAAA,MACF;AACA,cAAQ,eAAe,MAAM;AAC7B,cAAQ,GAAG,EAAE,IAAI;AACjB,cAAQ,SAAS;AACjB;AAAA,IACF;AACA,YAAQ;AAAA,MACN,UAAU,cAAc,EAAE,KAAK,KAAK,EAAE,IAAI,WAAO,0BAAY,EAAE,KAAK,CAAC,WAAM,EAAE,IAAI,EAAE;AAAA,IACrF;AAAA,EACF;AACF;","names":[]}
|
|
@@ -2,8 +2,17 @@
|
|
|
2
2
|
import { formatWhere } from "./build.js";
|
|
3
3
|
import "./process-guard.js";
|
|
4
4
|
var ICON = { error: "\u2716", warn: "\u26A0", info: "\u2139" };
|
|
5
|
+
var printable = (s) => (
|
|
6
|
+
// biome-ignore lint/suspicious/noControlCharactersInRegex: the characters to escape
|
|
7
|
+
s.replace(
|
|
8
|
+
/[\u0000-\u001f\u007f-\u009f\u2028\u2029]/g,
|
|
9
|
+
(c) => c === "\n" ? "\\n" : `\\u${(c.charCodeAt(0) + 65536).toString(16).slice(1)}`
|
|
10
|
+
)
|
|
11
|
+
);
|
|
5
12
|
function formatDiagnostic(d) {
|
|
6
|
-
const header =
|
|
13
|
+
const header = printable(
|
|
14
|
+
`${ICON[d.level]} [DataKable ${d.context.table}] ${d.code}: ${d.problem}`
|
|
15
|
+
);
|
|
7
16
|
const lines = [` where ${formatWhere(d.where)}`];
|
|
8
17
|
if (d.impact) lines.push(` impact ${d.impact}`);
|
|
9
18
|
d.fix.forEach((f, i) => {
|
|
@@ -12,7 +21,7 @@ function formatDiagnostic(d) {
|
|
|
12
21
|
lines.push(` docs ${d.docs}`);
|
|
13
22
|
const c = d.context;
|
|
14
23
|
lines.push(` context trigger=${c.trigger} run=${c.run} phase=${c.phase}`);
|
|
15
|
-
return { header, body: lines.join("\n") };
|
|
24
|
+
return { header, body: lines.map(printable).join("\n") };
|
|
16
25
|
}
|
|
17
26
|
function createConsoleSink(o) {
|
|
18
27
|
let windowStart = Number.NEGATIVE_INFINITY;
|
|
@@ -24,7 +33,7 @@ function createConsoleSink(o) {
|
|
|
24
33
|
if (t - windowStart >= o.rateLimit.windowMs) {
|
|
25
34
|
if (suppressed > 0) {
|
|
26
35
|
console.warn(
|
|
27
|
-
`[DataKable ${o.table}] ${suppressed} diagnostics were not printed (rate limit); read them with getDiagnostics() or onDiagnostic`
|
|
36
|
+
`[DataKable ${printable(o.table)}] ${suppressed} diagnostics were not printed (rate limit); read them with getDiagnostics() or onDiagnostic`
|
|
28
37
|
);
|
|
29
38
|
}
|
|
30
39
|
windowStart = t;
|
|
@@ -49,7 +58,9 @@ ${body}`);
|
|
|
49
58
|
console.groupEnd();
|
|
50
59
|
return;
|
|
51
60
|
}
|
|
52
|
-
console.error(
|
|
61
|
+
console.error(
|
|
62
|
+
printable(`[DataKable ${o.table}] ${d.code} at ${formatWhere(d.where)} \u2014 ${d.docs}`)
|
|
63
|
+
);
|
|
53
64
|
};
|
|
54
65
|
}
|
|
55
66
|
export {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/diagnostics/console.ts"],"sourcesContent":["import { formatWhere } from './build'\nimport './process-guard'\nimport type { Diagnostic } from './types'\n\nconst ICON = { error: '✖', warn: '⚠', info: 'ℹ' } as const\n\n
|
|
1
|
+
{"version":3,"sources":["../../src/diagnostics/console.ts"],"sourcesContent":["import { formatWhere } from './build'\nimport './process-guard'\nimport type { Diagnostic } from './types'\n\nconst ICON = { error: '✖', warn: '⚠', info: 'ℹ' } as const\n\n/**\n * Console text is printed with its C0 / C1 control characters, DEL and line breaks escaped\n * (`\\u001b`, `\\n`, ...): ids, keys and table names can come from URLs or data, and must not\n * forge a line or send terminal escapes (#104). The diagnostic object keeps the raw values.\n */\nconst printable = (s: string): string =>\n // biome-ignore lint/suspicious/noControlCharactersInRegex: the characters to escape\n s.replace(/[\\u0000-\\u001f\\u007f-\\u009f\\u2028\\u2029]/g, (c) =>\n c === '\\n' ? '\\\\n' : `\\\\u${(c.charCodeAt(0) + 0x10000).toString(16).slice(1)}`,\n )\n\n/**\n * The §8.1 console text: header + aligned body, each line {@link printable}. Also usable by\n * explain() and tests.\n */\nexport function formatDiagnostic(d: Diagnostic): { header: string; body: string } {\n const header = printable(\n `${ICON[d.level]} [DataKable ${d.context.table}] ${d.code}: ${d.problem}`,\n )\n const lines = [` where ${formatWhere(d.where)}`]\n if (d.impact) lines.push(` impact ${d.impact}`)\n d.fix.forEach((f, i) => {\n lines.push(`${i === 0 ? ' fix ' : ' '}${i + 1}. ${f}`)\n })\n lines.push(` docs ${d.docs}`)\n const c = d.context\n lines.push(` context trigger=${c.trigger} run=${c.run} phase=${c.phase}`)\n return { header, body: lines.map(printable).join('\\n') }\n}\n\nexport interface ConsoleSinkOptions {\n table: string\n dev: boolean\n rateLimit: { max: number; windowMs: number }\n now: () => number\n}\n\n/**\n * Default console sink (§8.2): dev prints one collapsed group per diagnostic; prod prints\n * error level only, on one line. A fixed-window rate limit protects the console; what it holds back\n * is still in getDiagnostics() and onDiagnostic.\n */\nexport function createConsoleSink(o: ConsoleSinkOptions): (d: Diagnostic) => void {\n let windowStart = Number.NEGATIVE_INFINITY\n let printed = 0\n let suppressed = 0\n // The grouped format is development-only: a production build prints one line (§8.2). `(process.env.NODE_ENV !== \"production\")` is\n // read inline so the bundler drops the grouped branch.\n return (d) => {\n if ((!(process.env.NODE_ENV !== \"production\") || !o.dev) && d.level !== 'error') return\n const t = o.now()\n if (t - windowStart >= o.rateLimit.windowMs) {\n if (suppressed > 0) {\n console.warn(\n `[DataKable ${printable(o.table)}] ${suppressed} diagnostics were not printed (rate limit); ` +\n 'read them with getDiagnostics() or onDiagnostic',\n )\n }\n windowStart = t\n printed = 0\n suppressed = 0\n }\n if (printed >= o.rateLimit.max) {\n suppressed++\n return\n }\n printed++\n // `(process.env.NODE_ENV !== \"production\") &&` first, not an early `if (!(process.env.NODE_ENV !== \"production\")) return`: a branch that folds to `false` is removed\n // while parsing, so a production bundle keeps no `formatDiagnostic` (code after a folded early\n // return is dropped only when printing, after tree shaking kept what it calls).\n if ((process.env.NODE_ENV !== \"production\") && o.dev) {\n const { header, body } = formatDiagnostic(d)\n const log = d.level === 'error' ? 'error' : d.level === 'warn' ? 'warn' : 'info'\n // Runtimes without console groups (the Edge Runtime: log/info/warn/error/debug only) get the\n // same text as one call.\n if (typeof console.groupCollapsed !== 'function' || typeof console.groupEnd !== 'function') {\n console[log](`${header}\\n${body}`)\n return\n }\n console.groupCollapsed(header)\n console[log](body)\n console.groupEnd()\n return\n }\n console.error(\n printable(`[DataKable ${o.table}] ${d.code} at ${formatWhere(d.where)} — ${d.docs}`),\n )\n }\n}\n"],"mappings":";AAAA,SAAS,mBAAmB;AAC5B,OAAO;AAGP,IAAM,OAAO,EAAE,OAAO,UAAK,MAAM,UAAK,MAAM,SAAI;AAOhD,IAAM,YAAY,CAAC;AAAA;AAAA,EAEjB,EAAE;AAAA,IAAQ;AAAA,IAA6C,CAAC,MACtD,MAAM,OAAO,QAAQ,OAAO,EAAE,WAAW,CAAC,IAAI,OAAS,SAAS,EAAE,EAAE,MAAM,CAAC,CAAC;AAAA,EAC9E;AAAA;AAMK,SAAS,iBAAiB,GAAiD;AAChF,QAAM,SAAS;AAAA,IACb,GAAG,KAAK,EAAE,KAAK,CAAC,eAAe,EAAE,QAAQ,KAAK,KAAK,EAAE,IAAI,KAAK,EAAE,OAAO;AAAA,EACzE;AACA,QAAM,QAAQ,CAAC,aAAa,YAAY,EAAE,KAAK,CAAC,EAAE;AAClD,MAAI,EAAE,OAAQ,OAAM,KAAK,aAAa,EAAE,MAAM,EAAE;AAChD,IAAE,IAAI,QAAQ,CAAC,GAAG,MAAM;AACtB,UAAM,KAAK,GAAG,MAAM,IAAI,eAAe,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE;AAAA,EACrE,CAAC;AACD,QAAM,KAAK,aAAa,EAAE,IAAI,EAAE;AAChC,QAAM,IAAI,EAAE;AACZ,QAAM,KAAK,qBAAqB,EAAE,OAAO,QAAQ,EAAE,GAAG,UAAU,EAAE,KAAK,EAAE;AACzE,SAAO,EAAE,QAAQ,MAAM,MAAM,IAAI,SAAS,EAAE,KAAK,IAAI,EAAE;AACzD;AAcO,SAAS,kBAAkB,GAAgD;AAChF,MAAI,cAAc,OAAO;AACzB,MAAI,UAAU;AACd,MAAI,aAAa;AAGjB,SAAO,CAAC,MAAM;AACZ,SAAK,EAAE,QAAQ,IAAI,aAAa,iBAAiB,CAAC,EAAE,QAAQ,EAAE,UAAU,QAAS;AACjF,UAAM,IAAI,EAAE,IAAI;AAChB,QAAI,IAAI,eAAe,EAAE,UAAU,UAAU;AAC3C,UAAI,aAAa,GAAG;AAClB,gBAAQ;AAAA,UACN,cAAc,UAAU,EAAE,KAAK,CAAC,KAAK,UAAU;AAAA,QAEjD;AAAA,MACF;AACA,oBAAc;AACd,gBAAU;AACV,mBAAa;AAAA,IACf;AACA,QAAI,WAAW,EAAE,UAAU,KAAK;AAC9B;AACA;AAAA,IACF;AACA;AAIA,QAAK,QAAQ,IAAI,aAAa,gBAAiB,EAAE,KAAK;AACpD,YAAM,EAAE,QAAQ,KAAK,IAAI,iBAAiB,CAAC;AAC3C,YAAM,MAAM,EAAE,UAAU,UAAU,UAAU,EAAE,UAAU,SAAS,SAAS;AAG1E,UAAI,OAAO,QAAQ,mBAAmB,cAAc,OAAO,QAAQ,aAAa,YAAY;AAC1F,gBAAQ,GAAG,EAAE,GAAG,MAAM;AAAA,EAAK,IAAI,EAAE;AACjC;AAAA,MACF;AACA,cAAQ,eAAe,MAAM;AAC7B,cAAQ,GAAG,EAAE,IAAI;AACjB,cAAQ,SAAS;AACjB;AAAA,IACF;AACA,YAAQ;AAAA,MACN,UAAU,cAAc,EAAE,KAAK,KAAK,EAAE,IAAI,OAAO,YAAY,EAAE,KAAK,CAAC,WAAM,EAAE,IAAI,EAAE;AAAA,IACrF;AAAA,EACF;AACF;","names":[]}
|
|
@@ -22,6 +22,7 @@ var prose_exports = {};
|
|
|
22
22
|
__export(prose_exports, {
|
|
23
23
|
expandDetails: () => expandDetails,
|
|
24
24
|
expandProse: () => expandProse,
|
|
25
|
+
proseArg: () => proseArg,
|
|
25
26
|
proseMessages: () => proseMessages
|
|
26
27
|
});
|
|
27
28
|
module.exports = __toCommonJS(prose_exports);
|
|
@@ -88,6 +89,7 @@ var proseMessages = {
|
|
|
88
89
|
"prims-or-dates": "an array of primitives or Dates",
|
|
89
90
|
"prim-or-date": "a primitive or a Date",
|
|
90
91
|
"range-bound": "number | bigint or a valid Date bound",
|
|
92
|
+
"not-nan": "a value other than NaN (NaN equals no cell)",
|
|
91
93
|
"same-type": "min and max of the same type ({0})",
|
|
92
94
|
// An option given without its wrapper (`DK_INVALID_OPTION` expected).
|
|
93
95
|
wrapped: "{0}({1}) from '@datakable/core/{2}'",
|
|
@@ -97,10 +99,16 @@ var proseMessages = {
|
|
|
97
99
|
"unknown-op": 'Unknown operation "{0}": register it with registerOperation()',
|
|
98
100
|
"boundary-twice": 'A boundary interceptor is already installed ("{0}"); "{1}" was rejected'
|
|
99
101
|
};
|
|
102
|
+
function proseArg(v) {
|
|
103
|
+
return v.replace(/[%|]/g, encodeURIComponent);
|
|
104
|
+
}
|
|
100
105
|
function expandProse(v, dev) {
|
|
101
106
|
const [key, ...args] = v.split("|");
|
|
102
107
|
const text = (process.env.NODE_ENV !== "production" && dev ? proseMessages[key] : void 0) ?? (0, import_catalog.installedText)(key);
|
|
103
|
-
return typeof text === "string" ? text.replace(/\{(\d)\}/g, (_, n) =>
|
|
108
|
+
return typeof text === "string" ? text.replace(/\{(\d)\}/g, (_, n) => {
|
|
109
|
+
const a = args[n] ?? "";
|
|
110
|
+
return a.includes("%") ? decodeURIComponent(a) : expandProse(a, dev);
|
|
111
|
+
}) : v;
|
|
104
112
|
}
|
|
105
113
|
var FIELDS = ["fallback", "reason", "problem", "expected"];
|
|
106
114
|
function expandDetails(details, dev) {
|
|
@@ -115,6 +123,7 @@ function expandDetails(details, dev) {
|
|
|
115
123
|
0 && (module.exports = {
|
|
116
124
|
expandDetails,
|
|
117
125
|
expandProse,
|
|
126
|
+
proseArg,
|
|
118
127
|
proseMessages
|
|
119
128
|
});
|
|
120
129
|
//# sourceMappingURL=prose.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/diagnostics/prose.ts"],"sourcesContent":["import { installedText } from './catalog'\nimport './process-guard'\n\n/**\n * Production detail prose (§8.2, §9.3): the sentences some details carry (`fallback`, `reason`,\n * `problem`) are written as short keys at the emit site, e.g. `fallback: 'cells-undefined'`, or\n * `'page-size|10'` with arguments. A diagnostic built in development, or in production with\n * `@datakable/core/messages` installed, reads the full sentence (the key is expanded when it is\n * built); production without the messages keeps the key, so the bundle carries no prose. A value\n * that is not a known key (a plugin's own `registerFallback` text) is kept as written.\n *\n * `{0}`, `{1}` are the arguments after the key, separated by
|
|
1
|
+
{"version":3,"sources":["../../src/diagnostics/prose.ts"],"sourcesContent":["import { installedText } from './catalog'\nimport './process-guard'\n\n/**\n * Production detail prose (§8.2, §9.3): the sentences some details carry (`fallback`, `reason`,\n * `problem`) are written as short keys at the emit site, e.g. `fallback: 'cells-undefined'`, or\n * `'page-size|10'` with arguments. A diagnostic built in development, or in production with\n * `@datakable/core/messages` installed, reads the full sentence (the key is expanded when it is\n * built); production without the messages keeps the key, so the bundle carries no prose. A value\n * that is not a known key (a plugin's own `registerFallback` text) is kept as written.\n *\n * `{0}`, `{1}` are the arguments after the key, separated by `|`. A value the library does not\n * write itself (a user's option, a column id, a plugin's name) is packed with {@link proseArg}, so\n * a `|` inside it does not split it (#92).\n */\nexport const proseMessages: Readonly<Record<string, string>> = {\n // Cell slots (`DK_CALLBACK_FAILED` / `DK_CALLBACK_BAD_RETURN` fallback).\n 'cells-coerced': 'those cells were coerced with the default formatter',\n 'cells-warn': 'those cells rendered ⚠', // `<DataTable />` (@datakable/react)\n 'cells-undefined': 'the failed cells read as undefined',\n 'cells-empty': \"the failed cells render ''\",\n 'rows-unmatched': 'the failed rows are treated as non-matching',\n 'rows-last': 'the failed rows sort as missing values (last)',\n 'cell-undefined': 'the cell reads as undefined',\n 'row-key-index': \"those rows use the fallback key '#<index>'\",\n 'sorted-native': 'the rows were sorted with the native algorithm',\n 'sorted-default': 'the column was sorted with the default comparator',\n // Operation fallbacks (`intercept/fallbacks.ts`, the boundary's reports).\n 'init-continued': 'table creation continued without the failed step',\n 'options-kept': 'the previous options were kept',\n 'destroy-continued': 'teardown continued; the table is destroyed',\n 'update-dropped': 'the update was dropped (state unchanged)',\n 'data-kept': 'the previous data was kept',\n 'row-model-kept': 'the last good row model was kept',\n 'step-passthrough': 'the step passed its input through',\n 'batch-fallback':\n \"the column's cells use the slot fallback ('' for format, undefined for accessor, \" +\n 'non-matching for filterFn, missing (sorted last) for sortBy)',\n 'results-kept': \"the previous results were kept (status: 'error')\",\n 'diagnostic-dropped': 'the diagnostic was dropped (the logger never kills the table)',\n 'returned-undefined': 'the operation returned undefined',\n // Features.\n 'slice-undefined': 'the slice starts as undefined',\n 'api-not-installed': 'its API was not installed',\n 'call-ignored': 'the call was ignored',\n 'api-missing': 'table.{0}() did nothing (the API of that feature was not installed)',\n 'apis-missing': 'table.{0}() did nothing (the API of those features was not installed)',\n 'page-reset': 'the pagination state was reset to its initial value',\n 'page-index-0': 'pageIndex was replaced by 0',\n 'page-size': 'pageSize was replaced by {0}',\n 'validity-ignored': 'the call was ignored; the validity filter is unchanged',\n 'validity-all': \"the table shows every row, as with 'all'\",\n 'validity-needs-flag':\n 'validity filters rows flagged by schema validation, which needs `schema` and ' +\n \"`invalidRows: 'flag'` (without a schema no row is invalid; with 'drop' invalid rows \" +\n \"are removed, with 'throw' they throw)\",\n 'not-searchable': 'no column is searchable: give the columns to search a `search` weight',\n collation: 'the runtime\\'s collation for \"{0}\"',\n 'not-algorithm':\n '{0} is not a sort algorithm (accepted: auto, tim, radix, counting, native, or a function); ' +\n 'auto was used',\n 'exsorted-failed': 'exsorted {0}Sort could not sort these keys; auto was used',\n 'exsorted-range':\n 'exsorted {0}Sort could not sort these keys (key range above 1,000,000); auto was used',\n 'needs-int-keys':\n '{0} sorts a single column of safe integer keys (numbers or Dates, no sortFn); auto was used',\n // Sorting reasons (DK_SORT_STRATEGY, `debug: true`).\n 'custom-threw': 'the custom algorithm threw',\n 'custom-bad': 'the custom algorithm returned a bad value',\n 'not-safe-int': 'keys are not all safe integers',\n ranks: '{0}, strings as collation ranks',\n 'int-keys': '{0}, safe-integer keys',\n 'auto-nearly': 'auto: safe integers, nearly sorted ({0} descents)',\n 'auto-range': 'auto: safe integers, key range {0} ≤ 4n',\n 'auto-wide': 'auto: safe integers, wide range, n ≥ 10k',\n 'auto-wide-small': 'auto: safe integers, wide range, n < 10k',\n 'auto-ranked-nearly':\n 'auto: collation ranks of a string column, safe integers, nearly sorted ({0} descents)',\n 'auto-ranked-range':\n 'auto: collation ranks of a string column, safe integers, key range {0} ≤ 4n',\n 'auto-ranked-wide':\n 'auto: collation ranks of a string column, safe integers, wide range, n ≥ 10k',\n 'auto-ranked-wide-small':\n 'auto: collation ranks of a string column, safe integers, wide range, n < 10k',\n // Filter values (`DK_FILTER_TYPE_MISMATCH` expected).\n 'prims-or-dates': 'an array of primitives or Dates',\n 'prim-or-date': 'a primitive or a Date',\n 'range-bound': 'number | bigint or a valid Date bound',\n 'not-nan': 'a value other than NaN (NaN equals no cell)',\n 'same-type': 'min and max of the same type ({0})',\n // An option given without its wrapper (`DK_INVALID_OPTION` expected).\n wrapped: \"{0}({1}) from '@datakable/core/{2}'\",\n // DK_INTERNAL problems.\n escaped: 'an exception escaped DataKable code',\n 'unknown-code': 'unknown diagnostic code \"{0}\": define it with defineDiagnostic() first',\n 'unknown-op': 'Unknown operation \"{0}\": register it with registerOperation()',\n 'boundary-twice': 'A boundary interceptor is already installed (\"{0}\"); \"{1}\" was rejected',\n}\n\n/**\n * A user value as one prose argument (`` `unknown-op|${proseArg(op)}` ``): `%` and `|` are\n * escaped (`%25`, `%7C`), so a value holding them is read back whole, not split or expanded.\n */\nexport function proseArg(v: string): string {\n return v.replace(/[%|]/g, encodeURIComponent)\n}\n\n/**\n * The sentence of a prose key (`'page-size|10'` → `'pageSize was replaced by 10'`): from\n * {@link proseMessages} in development (`dev`), else from the installed messages; `v` itself when\n * neither has the key.\n */\nexport function expandProse(v: string, dev: boolean): string {\n const [key, ...args] = v.split('|') as [string, ...string[]]\n const text = ((process.env.NODE_ENV !== \"production\") && dev ? proseMessages[key] : undefined) ?? installedText(key)\n // An argument may be a key itself (`'ranks|custom-threw'`); a missing one reads as ''. An\n // escaped one ({@link proseArg}) is a value. (`n` is the digit string: `args['0']` indexes like\n // `args[0]`.)\n return typeof text === 'string'\n ? text.replace(/\\{(\\d)\\}/g, (_, n: number) => {\n const a = args[n] ?? ''\n return a.includes('%') ? decodeURIComponent(a) : expandProse(a, dev)\n })\n : v\n}\n\n/** The detail fields that may hold a prose key. */\nconst FIELDS = ['fallback', 'reason', 'problem', 'expected'] as const\n\n/** A copy of `details` with its prose keys expanded. */\nexport function expandDetails(\n details: Record<string, unknown>,\n dev: boolean,\n): Record<string, unknown> {\n const out = { ...details }\n for (const f of FIELDS) {\n const v = details[f]\n if (typeof v === 'string') out[f] = expandProse(v, dev)\n }\n return out\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAA8B;AAC9B,2BAAO;AAcA,IAAM,gBAAkD;AAAA;AAAA,EAE7D,iBAAiB;AAAA,EACjB,cAAc;AAAA;AAAA,EACd,mBAAmB;AAAA,EACnB,eAAe;AAAA,EACf,kBAAkB;AAAA,EAClB,aAAa;AAAA,EACb,kBAAkB;AAAA,EAClB,iBAAiB;AAAA,EACjB,iBAAiB;AAAA,EACjB,kBAAkB;AAAA;AAAA,EAElB,kBAAkB;AAAA,EAClB,gBAAgB;AAAA,EAChB,qBAAqB;AAAA,EACrB,kBAAkB;AAAA,EAClB,aAAa;AAAA,EACb,kBAAkB;AAAA,EAClB,oBAAoB;AAAA,EACpB,kBACE;AAAA,EAEF,gBAAgB;AAAA,EAChB,sBAAsB;AAAA,EACtB,sBAAsB;AAAA;AAAA,EAEtB,mBAAmB;AAAA,EACnB,qBAAqB;AAAA,EACrB,gBAAgB;AAAA,EAChB,eAAe;AAAA,EACf,gBAAgB;AAAA,EAChB,cAAc;AAAA,EACd,gBAAgB;AAAA,EAChB,aAAa;AAAA,EACb,oBAAoB;AAAA,EACpB,gBAAgB;AAAA,EAChB,uBACE;AAAA,EAGF,kBAAkB;AAAA,EAClB,WAAW;AAAA,EACX,iBACE;AAAA,EAEF,mBAAmB;AAAA,EACnB,kBACE;AAAA,EACF,kBACE;AAAA;AAAA,EAEF,gBAAgB;AAAA,EAChB,cAAc;AAAA,EACd,gBAAgB;AAAA,EAChB,OAAO;AAAA,EACP,YAAY;AAAA,EACZ,eAAe;AAAA,EACf,cAAc;AAAA,EACd,aAAa;AAAA,EACb,mBAAmB;AAAA,EACnB,sBACE;AAAA,EACF,qBACE;AAAA,EACF,oBACE;AAAA,EACF,0BACE;AAAA;AAAA,EAEF,kBAAkB;AAAA,EAClB,gBAAgB;AAAA,EAChB,eAAe;AAAA,EACf,WAAW;AAAA,EACX,aAAa;AAAA;AAAA,EAEb,SAAS;AAAA;AAAA,EAET,SAAS;AAAA,EACT,gBAAgB;AAAA,EAChB,cAAc;AAAA,EACd,kBAAkB;AACpB;AAMO,SAAS,SAAS,GAAmB;AAC1C,SAAO,EAAE,QAAQ,SAAS,kBAAkB;AAC9C;AAOO,SAAS,YAAY,GAAW,KAAsB;AAC3D,QAAM,CAAC,KAAK,GAAG,IAAI,IAAI,EAAE,MAAM,GAAG;AAClC,QAAM,QAAS,QAAQ,IAAI,aAAa,gBAAiB,MAAM,cAAc,GAAG,IAAI,eAAc,8BAAc,GAAG;AAInH,SAAO,OAAO,SAAS,WACnB,KAAK,QAAQ,aAAa,CAAC,GAAG,MAAc;AAC1C,UAAM,IAAI,KAAK,CAAC,KAAK;AACrB,WAAO,EAAE,SAAS,GAAG,IAAI,mBAAmB,CAAC,IAAI,YAAY,GAAG,GAAG;AAAA,EACrE,CAAC,IACD;AACN;AAGA,IAAM,SAAS,CAAC,YAAY,UAAU,WAAW,UAAU;AAGpD,SAAS,cACd,SACA,KACyB;AACzB,QAAM,MAAM,EAAE,GAAG,QAAQ;AACzB,aAAW,KAAK,QAAQ;AACtB,UAAM,IAAI,QAAQ,CAAC;AACnB,QAAI,OAAO,MAAM,SAAU,KAAI,CAAC,IAAI,YAAY,GAAG,GAAG;AAAA,EACxD;AACA,SAAO;AACT;","names":[]}
|
|
@@ -62,6 +62,7 @@ var proseMessages = {
|
|
|
62
62
|
"prims-or-dates": "an array of primitives or Dates",
|
|
63
63
|
"prim-or-date": "a primitive or a Date",
|
|
64
64
|
"range-bound": "number | bigint or a valid Date bound",
|
|
65
|
+
"not-nan": "a value other than NaN (NaN equals no cell)",
|
|
65
66
|
"same-type": "min and max of the same type ({0})",
|
|
66
67
|
// An option given without its wrapper (`DK_INVALID_OPTION` expected).
|
|
67
68
|
wrapped: "{0}({1}) from '@datakable/core/{2}'",
|
|
@@ -71,10 +72,16 @@ var proseMessages = {
|
|
|
71
72
|
"unknown-op": 'Unknown operation "{0}": register it with registerOperation()',
|
|
72
73
|
"boundary-twice": 'A boundary interceptor is already installed ("{0}"); "{1}" was rejected'
|
|
73
74
|
};
|
|
75
|
+
function proseArg(v) {
|
|
76
|
+
return v.replace(/[%|]/g, encodeURIComponent);
|
|
77
|
+
}
|
|
74
78
|
function expandProse(v, dev) {
|
|
75
79
|
const [key, ...args] = v.split("|");
|
|
76
80
|
const text = (process.env.NODE_ENV !== "production" && dev ? proseMessages[key] : void 0) ?? installedText(key);
|
|
77
|
-
return typeof text === "string" ? text.replace(/\{(\d)\}/g, (_, n) =>
|
|
81
|
+
return typeof text === "string" ? text.replace(/\{(\d)\}/g, (_, n) => {
|
|
82
|
+
const a = args[n] ?? "";
|
|
83
|
+
return a.includes("%") ? decodeURIComponent(a) : expandProse(a, dev);
|
|
84
|
+
}) : v;
|
|
78
85
|
}
|
|
79
86
|
var FIELDS = ["fallback", "reason", "problem", "expected"];
|
|
80
87
|
function expandDetails(details, dev) {
|
|
@@ -88,6 +95,7 @@ function expandDetails(details, dev) {
|
|
|
88
95
|
export {
|
|
89
96
|
expandDetails,
|
|
90
97
|
expandProse,
|
|
98
|
+
proseArg,
|
|
91
99
|
proseMessages
|
|
92
100
|
};
|
|
93
101
|
//# sourceMappingURL=prose.js.map
|