zonemapdb 0.8.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/LICENSE +21 -0
- package/README.md +71 -0
- package/dist/block-fetch.d.ts +11 -0
- package/dist/block-fetch.d.ts.map +1 -0
- package/dist/block-fetch.js +29 -0
- package/dist/block-fetch.js.map +1 -0
- package/dist/client.d.ts +3 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +584 -0
- package/dist/client.js.map +1 -0
- package/dist/errors.d.ts +40 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +24 -0
- package/dist/errors.js.map +1 -0
- package/dist/fetch-file.d.ts +39 -0
- package/dist/fetch-file.d.ts.map +1 -0
- package/dist/fetch-file.js +179 -0
- package/dist/fetch-file.js.map +1 -0
- package/dist/filter.d.ts +9 -0
- package/dist/filter.d.ts.map +1 -0
- package/dist/filter.js +104 -0
- package/dist/filter.js.map +1 -0
- package/dist/index-fetch.d.ts +3 -0
- package/dist/index-fetch.d.ts.map +1 -0
- package/dist/index-fetch.js +5 -0
- package/dist/index-fetch.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/manifest.d.ts +127 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +86 -0
- package/dist/manifest.js.map +1 -0
- package/dist/normalize.d.ts +25 -0
- package/dist/normalize.d.ts.map +1 -0
- package/dist/normalize.js +43 -0
- package/dist/normalize.js.map +1 -0
- package/dist/secondary-index.d.ts +32 -0
- package/dist/secondary-index.d.ts.map +1 -0
- package/dist/secondary-index.js +80 -0
- package/dist/secondary-index.js.map +1 -0
- package/dist/types.d.ts +319 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +164 -0
- package/dist/types.js.map +1 -0
- package/dist/version.d.ts +9 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +9 -0
- package/dist/version.js.map +1 -0
- package/dist/zonemap-fetch.d.ts +9 -0
- package/dist/zonemap-fetch.d.ts.map +1 -0
- package/dist/zonemap-fetch.js +11 -0
- package/dist/zonemap-fetch.js.map +1 -0
- package/dist/zonemap.d.ts +35 -0
- package/dist/zonemap.d.ts.map +1 -0
- package/dist/zonemap.js +139 -0
- package/dist/zonemap.js.map +1 -0
- package/package.json +53 -0
package/dist/manifest.js
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { ZonemapDbError } from "./errors.js";
|
|
2
|
+
import { compressionSuffix, decompressionFormat } from "./types.js";
|
|
3
|
+
import { blockRelPath } from "./block-fetch.js";
|
|
4
|
+
import { fetchCompressedText, fetchJson, parseCorruptible } from "./fetch-file.js";
|
|
5
|
+
import { FORMAT_VERSION } from "./version.js";
|
|
6
|
+
/**
|
|
7
|
+
* Fetches the root manifest. `gzipped` says the deploy pre-compressed it (ADR-0002 §8) — unlike index
|
|
8
|
+
* chunks and zonemap sidecars, whose `.gz` paths come FROM the manifest and so describe themselves,
|
|
9
|
+
* this is the bootstrap fetch: nothing has been read yet that could tell the client the encoding. The
|
|
10
|
+
* generated client carries the answer instead, stamped by the same `build` that wrote the file, so the
|
|
11
|
+
* two cannot drift.
|
|
12
|
+
*
|
|
13
|
+
* `cache` defaults to `"no-cache"` (#32): the manifest is the one stable-named file, and a host that
|
|
14
|
+
* caches everything for minutes (GitHub Pages sends `max-age=600`) would otherwise hand back the
|
|
15
|
+
* previous deploy's copy after a redeploy. Revalidating costs a 304 when nothing changed. The client
|
|
16
|
+
* passes `"reload"` when a referenced file 404s and it needs to know what the deploy says now.
|
|
17
|
+
*/
|
|
18
|
+
export async function fetchManifest(basePath, fetchImpl, compression = "none", cache = "no-cache") {
|
|
19
|
+
const url = `${basePath}/manifest.json${compressionSuffix(compression)}`;
|
|
20
|
+
const format = decompressionFormat(compression);
|
|
21
|
+
let parsed;
|
|
22
|
+
if (format === undefined) {
|
|
23
|
+
parsed = (await fetchJson(url, "manifest", fetchImpl, undefined, cache));
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
const text = await fetchCompressedText(url, "manifest", format, fetchImpl, undefined, cache);
|
|
27
|
+
parsed = parseCorruptible(url, () => JSON.parse(text));
|
|
28
|
+
}
|
|
29
|
+
// JSON-valid but not a manifest — the body "won't parse" into one (ADR-0007 §5).
|
|
30
|
+
if (typeof parsed.formatVersion !== "number") {
|
|
31
|
+
throw new ZonemapDbError({
|
|
32
|
+
code: "CORRUPT_DATA",
|
|
33
|
+
url,
|
|
34
|
+
message: `zonemapdb: the manifest at "${url}" parsed as JSON but has no numeric formatVersion — the deploy is corrupt. Re-run \`zonemapdb build\` and redeploy.`,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
// ADR-0005: same major → always compatible (SemVer); major mismatch → fail loud.
|
|
38
|
+
if (parsed.formatVersion !== FORMAT_VERSION) {
|
|
39
|
+
throw new ZonemapDbError({
|
|
40
|
+
code: "FORMAT_VERSION",
|
|
41
|
+
url,
|
|
42
|
+
message: `zonemapdb: the dataset at "${url}" was built with zonemapdb major ${String(parsed.formatVersion)} ` +
|
|
43
|
+
`but this runtime is major ${FORMAT_VERSION} — align versions and re-run \`zonemapdb build\`.`,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
// ADR-0013 added each field's `pruning` list inside major 0. The rider rule can't be enforced
|
|
47
|
+
// without it, so a tree built before it is refused like any format mismatch rather than guessed at.
|
|
48
|
+
if (Object.values(parsed.schema?.fields ?? {}).some((field) => !Array.isArray(field.pruning))) {
|
|
49
|
+
throw new ZonemapDbError({
|
|
50
|
+
code: "FORMAT_VERSION",
|
|
51
|
+
url,
|
|
52
|
+
message: `zonemapdb: the dataset at "${url}" was built by a zonemapdb older than this runtime (before 0.3.0, which ` +
|
|
53
|
+
`added which operators prune) — re-run \`zonemapdb build\` with the current version and redeploy.`,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
return parsed;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* How this deploy compressed the files the manifest points at. Reads the modern `compression` field
|
|
60
|
+
* and falls back to the original `gzip: true`, so a tree built before the field existed still works.
|
|
61
|
+
*/
|
|
62
|
+
export function datasetCompression(manifest) {
|
|
63
|
+
return manifest.dataset.compression ?? (manifest.dataset.gzip === true ? "gzip" : "none");
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Whether `manifest` points at `url` — a block, an index chunk (base, reversed or trigram) or a
|
|
67
|
+
* zonemap sidecar. The client asks this of a freshly fetched manifest after a referenced file 404s
|
|
68
|
+
* (#32): if the fresh manifest still names the file the deploy really is missing it, and if not, the
|
|
69
|
+
* 404 came from a stale manifest and the query is worth one retry.
|
|
70
|
+
*/
|
|
71
|
+
export function manifestReferences(manifest, basePath, url) {
|
|
72
|
+
const prefix = `${basePath}/`;
|
|
73
|
+
if (!url.startsWith(prefix))
|
|
74
|
+
return false;
|
|
75
|
+
const path = url.slice(prefix.length);
|
|
76
|
+
const compression = datasetCompression(manifest);
|
|
77
|
+
if (manifest.blocks.some((block) => blockRelPath(block.hash, manifest.blocks.length, compression) === path))
|
|
78
|
+
return true;
|
|
79
|
+
for (const index of Object.values(manifest.indexes)) {
|
|
80
|
+
const directories = [index.chunks, index.reversed?.chunks ?? [], index.trigram?.chunks ?? []];
|
|
81
|
+
if (directories.some((chunks) => chunks.some((chunk) => chunk.file === path)))
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
return Object.values(manifest.zonemap).some((entry) => "sidecar" in entry && entry.sidecar === path);
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=manifest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAoB,MAAM,YAAY,CAAC;AACtF,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,mBAAmB,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnF,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AA6G9C;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,QAAgB,EAChB,SAAuB,EACvB,WAAW,GAAgB,MAAM,EACjC,KAAK,GAAiB,UAAU;IAEhC,MAAM,GAAG,GAAG,GAAG,QAAQ,iBAAiB,iBAAiB,CAAC,WAAW,CAAC,EAAE,CAAC;IACzE,MAAM,MAAM,GAAG,mBAAmB,CAAC,WAAW,CAAC,CAAC;IAChD,IAAI,MAAgB,CAAC;IACrB,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,MAAM,GAAG,CAAC,MAAM,SAAS,CAAC,GAAG,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,CAAC,CAAa,CAAC;IACvF,CAAC;SAAM,CAAC;QACN,MAAM,IAAI,GAAG,MAAM,mBAAmB,CAAC,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC;QAC7F,MAAM,GAAG,gBAAgB,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAa,CAAC,CAAC;IACrE,CAAC;IACD,iFAAiF;IACjF,IAAI,OAAO,MAAM,CAAC,aAAa,KAAK,QAAQ,EAAE,CAAC;QAC7C,MAAM,IAAI,cAAc,CAAC;YACvB,IAAI,EAAE,cAAc;YACpB,GAAG;YACH,OAAO,EAAE,+BAA+B,GAAG,qHAAqH;SACjK,CAAC,CAAC;IACL,CAAC;IACD,iFAAiF;IACjF,IAAI,MAAM,CAAC,aAAa,KAAK,cAAc,EAAE,CAAC;QAC5C,MAAM,IAAI,cAAc,CAAC;YACvB,IAAI,EAAE,gBAAgB;YACtB,GAAG;YACH,OAAO,EACL,8BAA8B,GAAG,oCAAoC,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,GAAG;gBACpG,6BAA6B,cAAc,mDAAmD;SACjG,CAAC,CAAC;IACL,CAAC;IACD,8FAA8F;IAC9F,oGAAoG;IACpG,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;QAC9F,MAAM,IAAI,cAAc,CAAC;YACvB,IAAI,EAAE,gBAAgB;YACtB,GAAG;YACH,OAAO,EACL,8BAA8B,GAAG,0EAA0E;gBAC3G,kGAAkG;SACrG,CAAC,CAAC;IACL,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,QAAkB;IACnD,OAAO,QAAQ,CAAC,OAAO,CAAC,WAAW,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;AAC5F,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAC,QAAkB,EAAE,QAAgB,EAAE,GAAW;IAClF,MAAM,MAAM,GAAG,GAAG,QAAQ,GAAG,CAAC;IAC9B,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC;QAAE,OAAO,KAAK,CAAC;IAC1C,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAEtC,MAAM,WAAW,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IACjD,IAAI,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,KAAK,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAEzH,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QACpD,MAAM,WAAW,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,QAAQ,EAAE,MAAM,IAAI,EAAE,EAAE,KAAK,CAAC,OAAO,EAAE,MAAM,IAAI,EAAE,CAAC,CAAC;QAC9F,IAAI,WAAW,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;YAAE,OAAO,IAAI,CAAC;IAC7F,CAAC;IAED,OAAO,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,SAAS,IAAI,KAAK,IAAI,KAAK,CAAC,OAAO,KAAK,IAAI,CAAC,CAAC;AACvG,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The derived-field normalizers (ADR-0009), for normalizing a QUERY value the same way the build
|
|
3
|
+
* normalized the column it targets. A `name_fold` column holds `fold(name)`, so a search box has to
|
|
4
|
+
* send `normalize("fold", input)` or its trigrams won't line up with the index.
|
|
5
|
+
*
|
|
6
|
+
* This duplicates `zonemapdb-cli/src/normalize.ts` rather than importing it, like the other
|
|
7
|
+
* cli/runtime pairs: the runtime stays dependency-free, and the CLI's test suite checks the two
|
|
8
|
+
* produce identical output.
|
|
9
|
+
*/
|
|
10
|
+
declare const NORMALIZERS: {
|
|
11
|
+
numeric(value: unknown): number | null;
|
|
12
|
+
lowercase(value: unknown): string | null;
|
|
13
|
+
trim(value: unknown): string | null;
|
|
14
|
+
fold(value: unknown): string | null;
|
|
15
|
+
};
|
|
16
|
+
export type NormalizerName = keyof typeof NORMALIZERS;
|
|
17
|
+
/**
|
|
18
|
+
* Applies a derived-field normalizer. `null` means "no derivable value" — the build omits the derived
|
|
19
|
+
* key for such records, so there is nothing a query with that value could match.
|
|
20
|
+
*/
|
|
21
|
+
export declare function normalize(using: "numeric", value: unknown): number | null;
|
|
22
|
+
export declare function normalize(using: "lowercase" | "trim" | "fold", value: unknown): string | null;
|
|
23
|
+
export declare function normalize(using: NormalizerName, value: unknown): string | number | null;
|
|
24
|
+
export {};
|
|
25
|
+
//# sourceMappingURL=normalize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../src/normalize.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AASH,QAAA,MAAM,WAAW;IACf,OAAO,QAAQ,OAAO,GAAG,MAAM,GAAG,IAAI;IAOtC,SAAS,QAAQ,OAAO,GAAG,MAAM,GAAG,IAAI;IAIxC,IAAI,QAAQ,OAAO,GAAG,MAAM,GAAG,IAAI;IAInC,IAAI,QAAQ,OAAO,GAAG,MAAM,GAAG,IAAI;CAKpC,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,MAAM,OAAO,WAAW,CAAC;AAEtD;;;GAGG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAAC;AAC3E,wBAAgB,SAAS,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,GAAG,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAAC;AAC/F,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The derived-field normalizers (ADR-0009), for normalizing a QUERY value the same way the build
|
|
3
|
+
* normalized the column it targets. A `name_fold` column holds `fold(name)`, so a search box has to
|
|
4
|
+
* send `normalize("fold", input)` or its trigrams won't line up with the index.
|
|
5
|
+
*
|
|
6
|
+
* This duplicates `zonemapdb-cli/src/normalize.ts` rather than importing it, like the other
|
|
7
|
+
* cli/runtime pairs: the runtime stays dependency-free, and the CLI's test suite checks the two
|
|
8
|
+
* produce identical output.
|
|
9
|
+
*/
|
|
10
|
+
/** Combining marks left behind by NFD, stripped to fold `û` → `u`. */
|
|
11
|
+
const COMBINING_MARKS = /\p{M}/gu;
|
|
12
|
+
function asString(value) {
|
|
13
|
+
return typeof value === "string" ? value : undefined;
|
|
14
|
+
}
|
|
15
|
+
const NORMALIZERS = {
|
|
16
|
+
numeric(value) {
|
|
17
|
+
if (typeof value === "number")
|
|
18
|
+
return Number.isFinite(value) ? value : null;
|
|
19
|
+
const text = asString(value)?.trim();
|
|
20
|
+
if (text === undefined || text.length === 0)
|
|
21
|
+
return null;
|
|
22
|
+
const parsed = Number(text);
|
|
23
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
24
|
+
},
|
|
25
|
+
lowercase(value) {
|
|
26
|
+
const text = asString(value);
|
|
27
|
+
return text === undefined ? null : text.toLowerCase();
|
|
28
|
+
},
|
|
29
|
+
trim(value) {
|
|
30
|
+
const text = asString(value)?.trim();
|
|
31
|
+
return text === undefined || text.length === 0 ? null : text;
|
|
32
|
+
},
|
|
33
|
+
fold(value) {
|
|
34
|
+
const text = asString(value);
|
|
35
|
+
if (text === undefined)
|
|
36
|
+
return null;
|
|
37
|
+
return text.normalize("NFD").replace(COMBINING_MARKS, "").normalize("NFC").toLowerCase();
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
export function normalize(using, value) {
|
|
41
|
+
return NORMALIZERS[using](value);
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=normalize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize.js","sourceRoot":"","sources":["../src/normalize.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,sEAAsE;AACtE,MAAM,eAAe,GAAG,SAAS,CAAC;AAElC,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AACvD,CAAC;AAED,MAAM,WAAW,GAAG;IAClB,OAAO,CAAC,KAAc;QACpB,IAAI,OAAO,KAAK,KAAK,QAAQ;YAAE,OAAO,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;QAC5E,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC;QACrC,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QACzD,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;QAC5B,OAAO,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;IACjD,CAAC;IACD,SAAS,CAAC,KAAc;QACtB,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;QAC7B,OAAO,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;IACxD,CAAC;IACD,IAAI,CAAC,KAAc;QACjB,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC;QACrC,OAAO,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;IAC/D,CAAC;IACD,IAAI,CAAC,KAAc;QACjB,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;QAC7B,IAAI,IAAI,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC;QACpC,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC;IAC3F,CAAC;CACF,CAAC;AAWF,MAAM,UAAU,SAAS,CAAC,KAAqB,EAAE,KAAc;IAC7D,OAAO,WAAW,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC;AACnC,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { IndexChunkDirEntry } from "./manifest.js";
|
|
2
|
+
import type { FieldKind } from "./types.js";
|
|
3
|
+
export interface IndexChunkEntry {
|
|
4
|
+
/** Chars shared with the PREVIOUS entry's canonical key; 0 for a chunk's first entry (ADR-0003 §4). */
|
|
5
|
+
prefixLen: number;
|
|
6
|
+
suffix: string;
|
|
7
|
+
/** Delta-encoded ascending block ordinals — cumulative-sum from 0 reconstructs them (ADR-0003 §5). */
|
|
8
|
+
postings: number[];
|
|
9
|
+
}
|
|
10
|
+
export interface IndexChunkFile {
|
|
11
|
+
entries: IndexChunkEntry[];
|
|
12
|
+
}
|
|
13
|
+
export interface DecodedIndexEntry {
|
|
14
|
+
value: unknown;
|
|
15
|
+
blockIndices: number[];
|
|
16
|
+
}
|
|
17
|
+
/** Reconstructs a chunk's front-coded dictionary + delta-encoded postings into typed values. */
|
|
18
|
+
export declare function decodeIndexChunk(file: IndexChunkFile, kind: FieldKind): DecodedIndexEntry[];
|
|
19
|
+
export interface SecondaryFieldFilter {
|
|
20
|
+
equals?: unknown;
|
|
21
|
+
in?: unknown[];
|
|
22
|
+
startsWith?: string;
|
|
23
|
+
}
|
|
24
|
+
/** The chunk directory entries a filter could possibly match — routes which chunks to fetch. */
|
|
25
|
+
export declare function chunksForFilter(chunks: IndexChunkDirEntry[], filter: SecondaryFieldFilter): IndexChunkDirEntry[];
|
|
26
|
+
/** The union of block ordinals whose decoded entry value satisfies the filter. */
|
|
27
|
+
export declare function blockIndicesForFilter(decoded: DecodedIndexEntry[], filter: SecondaryFieldFilter): Set<number>;
|
|
28
|
+
/** Codepoint-safe reversal (ADR-0003 §7): `endsWith(suffix)` becomes `startsWith` on the reversed index once both sides are reversed. */
|
|
29
|
+
export declare function reverseString(value: string): string;
|
|
30
|
+
/** Every sliding 3-char window of `value` — the query-side counterpart of the trigram index's dictionary keys (ADR-0003 §7). */
|
|
31
|
+
export declare function trigramsOf(value: string): string[];
|
|
32
|
+
//# sourceMappingURL=secondary-index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secondary-index.d.ts","sourceRoot":"","sources":["../src/secondary-index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,MAAM,WAAW,eAAe;IAC9B,uGAAuG;IACvG,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,sGAAsG;IACtG,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,eAAe,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,OAAO,CAAC;IACf,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAQD,gGAAgG;AAChG,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,SAAS,GAAG,iBAAiB,EAAE,CAQ3F;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAYD,gGAAgG;AAChG,wBAAgB,eAAe,CAAC,MAAM,EAAE,kBAAkB,EAAE,EAAE,MAAM,EAAE,oBAAoB,GAAG,kBAAkB,EAAE,CAYhH;AASD,kFAAkF;AAClF,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,iBAAiB,EAAE,EAAE,MAAM,EAAE,oBAAoB,GAAG,GAAG,CAAC,MAAM,CAAC,CAM7G;AAED,yIAAyI;AACzI,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED,gIAAgI;AAChI,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAIlD"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// Secondary-field pruning (ADR-0003): decode a chunked inverted-index chunk,
|
|
2
|
+
// pick the chunk(s) a filter could touch from the (always-in-manifest) chunk
|
|
3
|
+
// directory, and resolve which blocks actually hold a matching value.
|
|
4
|
+
function fromCanonicalKey(key, kind) {
|
|
5
|
+
if (kind === "number")
|
|
6
|
+
return Number(key);
|
|
7
|
+
if (kind === "boolean")
|
|
8
|
+
return key === "true";
|
|
9
|
+
return key; // string | date — dates are already ISO strings
|
|
10
|
+
}
|
|
11
|
+
/** Reconstructs a chunk's front-coded dictionary + delta-encoded postings into typed values. */
|
|
12
|
+
export function decodeIndexChunk(file, kind) {
|
|
13
|
+
let prevKey = "";
|
|
14
|
+
return file.entries.map((entry) => {
|
|
15
|
+
prevKey = prevKey.slice(0, entry.prefixLen) + entry.suffix;
|
|
16
|
+
let acc = 0;
|
|
17
|
+
const blockIndices = entry.postings.map((delta) => (acc += delta));
|
|
18
|
+
return { value: fromCanonicalKey(prevKey, kind), blockIndices };
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
function overlapsValue(dir, value) {
|
|
22
|
+
return dir.from <= value && value <= dir.to;
|
|
23
|
+
}
|
|
24
|
+
/** Any string with `prefix` lies lexicographically within [prefix, prefix + a sentinel higher than any real char]. */
|
|
25
|
+
function overlapsPrefix(dir, prefix) {
|
|
26
|
+
const sentinel = prefix + "";
|
|
27
|
+
return dir.from <= sentinel && dir.to >= prefix;
|
|
28
|
+
}
|
|
29
|
+
/** The chunk directory entries a filter could possibly match — routes which chunks to fetch. */
|
|
30
|
+
export function chunksForFilter(chunks, filter) {
|
|
31
|
+
const matched = new Set();
|
|
32
|
+
if (filter.equals !== undefined) {
|
|
33
|
+
for (const chunk of chunks)
|
|
34
|
+
if (overlapsValue(chunk, filter.equals))
|
|
35
|
+
matched.add(chunk);
|
|
36
|
+
}
|
|
37
|
+
if (filter.in !== undefined) {
|
|
38
|
+
for (const value of filter.in)
|
|
39
|
+
for (const chunk of chunks)
|
|
40
|
+
if (overlapsValue(chunk, value))
|
|
41
|
+
matched.add(chunk);
|
|
42
|
+
}
|
|
43
|
+
if (filter.startsWith !== undefined) {
|
|
44
|
+
for (const chunk of chunks)
|
|
45
|
+
if (overlapsPrefix(chunk, filter.startsWith))
|
|
46
|
+
matched.add(chunk);
|
|
47
|
+
}
|
|
48
|
+
return [...matched];
|
|
49
|
+
}
|
|
50
|
+
function matchesEntryValue(value, filter) {
|
|
51
|
+
if (filter.equals !== undefined && value !== filter.equals)
|
|
52
|
+
return false;
|
|
53
|
+
if (filter.in !== undefined && !filter.in.includes(value))
|
|
54
|
+
return false;
|
|
55
|
+
if (filter.startsWith !== undefined && !value.startsWith(filter.startsWith))
|
|
56
|
+
return false;
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
/** The union of block ordinals whose decoded entry value satisfies the filter. */
|
|
60
|
+
export function blockIndicesForFilter(decoded, filter) {
|
|
61
|
+
const blockIndices = new Set();
|
|
62
|
+
for (const entry of decoded) {
|
|
63
|
+
if (matchesEntryValue(entry.value, filter))
|
|
64
|
+
for (const s of entry.blockIndices)
|
|
65
|
+
blockIndices.add(s);
|
|
66
|
+
}
|
|
67
|
+
return blockIndices;
|
|
68
|
+
}
|
|
69
|
+
/** Codepoint-safe reversal (ADR-0003 §7): `endsWith(suffix)` becomes `startsWith` on the reversed index once both sides are reversed. */
|
|
70
|
+
export function reverseString(value) {
|
|
71
|
+
return [...value].reverse().join("");
|
|
72
|
+
}
|
|
73
|
+
/** Every sliding 3-char window of `value` — the query-side counterpart of the trigram index's dictionary keys (ADR-0003 §7). */
|
|
74
|
+
export function trigramsOf(value) {
|
|
75
|
+
const grams = [];
|
|
76
|
+
for (let i = 0; i <= value.length - 3; i++)
|
|
77
|
+
grams.push(value.slice(i, i + 3));
|
|
78
|
+
return grams;
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=secondary-index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secondary-index.js","sourceRoot":"","sources":["../src/secondary-index.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,6EAA6E;AAC7E,sEAAsE;AAsBtE,SAAS,gBAAgB,CAAC,GAAW,EAAE,IAAe;IACpD,IAAI,IAAI,KAAK,QAAQ;QAAE,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC;IAC1C,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,GAAG,KAAK,MAAM,CAAC;IAC9C,OAAO,GAAG,CAAC,CAAC,gDAAgD;AAC9D,CAAC;AAED,gGAAgG;AAChG,MAAM,UAAU,gBAAgB,CAAC,IAAoB,EAAE,IAAe;IACpE,IAAI,OAAO,GAAG,EAAE,CAAC;IACjB,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;QAChC,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC;QAC3D,IAAI,GAAG,GAAG,CAAC,CAAC;QACZ,MAAM,YAAY,GAAG,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,GAAG,IAAI,KAAK,CAAC,CAAC,CAAC;QACnE,OAAO,EAAE,KAAK,EAAE,gBAAgB,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,YAAY,EAAE,CAAC;IAClE,CAAC,CAAC,CAAC;AACL,CAAC;AAQD,SAAS,aAAa,CAAC,GAAuB,EAAE,KAAc;IAC5D,OAAQ,GAAG,CAAC,IAAc,IAAK,KAAe,IAAK,KAAe,IAAK,GAAG,CAAC,EAAY,CAAC;AAC1F,CAAC;AAED,sHAAsH;AACtH,SAAS,cAAc,CAAC,GAAuB,EAAE,MAAc;IAC7D,MAAM,QAAQ,GAAG,MAAM,GAAG,GAAG,CAAC;IAC9B,OAAQ,GAAG,CAAC,IAAe,IAAI,QAAQ,IAAK,GAAG,CAAC,EAAa,IAAI,MAAM,CAAC;AAC1E,CAAC;AAED,gGAAgG;AAChG,MAAM,UAAU,eAAe,CAAC,MAA4B,EAAE,MAA4B;IACxF,MAAM,OAAO,GAAG,IAAI,GAAG,EAAsB,CAAC;IAC9C,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAChC,KAAK,MAAM,KAAK,IAAI,MAAM;YAAE,IAAI,aAAa,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC;gBAAE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAC1F,CAAC;IACD,IAAI,MAAM,CAAC,EAAE,KAAK,SAAS,EAAE,CAAC;QAC5B,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,EAAE;YAAE,KAAK,MAAM,KAAK,IAAI,MAAM;gBAAE,IAAI,aAAa,CAAC,KAAK,EAAE,KAAK,CAAC;oBAAE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACjH,CAAC;IACD,IAAI,MAAM,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;QACpC,KAAK,MAAM,KAAK,IAAI,MAAM;YAAE,IAAI,cAAc,CAAC,KAAK,EAAE,MAAM,CAAC,UAAU,CAAC;gBAAE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAC/F,CAAC;IACD,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC;AACtB,CAAC;AAED,SAAS,iBAAiB,CAAC,KAAc,EAAE,MAA4B;IACrE,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,IAAI,KAAK,KAAK,MAAM,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IACzE,IAAI,MAAM,CAAC,EAAE,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACxE,IAAI,MAAM,CAAC,UAAU,KAAK,SAAS,IAAI,CAAE,KAAgB,CAAC,UAAU,CAAC,MAAM,CAAC,UAAU,CAAC;QAAE,OAAO,KAAK,CAAC;IACtG,OAAO,IAAI,CAAC;AACd,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,qBAAqB,CAAC,OAA4B,EAAE,MAA4B;IAC9F,MAAM,YAAY,GAAG,IAAI,GAAG,EAAU,CAAC;IACvC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,iBAAiB,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,CAAC;YAAE,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,YAAY;gBAAE,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACtG,CAAC;IACD,OAAO,YAAY,CAAC;AACtB,CAAC;AAED,yIAAyI;AACzI,MAAM,UAAU,aAAa,CAAC,KAAa;IACzC,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACvC,CAAC;AAED,gIAAgI;AAChI,MAAM,UAAU,UAAU,CAAC,KAAa;IACtC,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,EAAE;QAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAC9E,OAAO,KAAK,CAAC;AACf,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How the deploy pre-compresses every file it serves (ADR-0002 §8). `"none"` is the default: most
|
|
3
|
+
* hosts apply `Content-Encoding` themselves, which negotiates per client, whereas a pre-compressed
|
|
4
|
+
* file cannot — a baked `.br` is unreadable to a client without brotli, with no fallback.
|
|
5
|
+
*
|
|
6
|
+
* Note the mismatch the file extension hides: the served suffix is `.br` (matching `Content-Encoding:
|
|
7
|
+
* br`), but the DecompressionStream format string is `"brotli"`.
|
|
8
|
+
*/
|
|
9
|
+
export type Compression = "none" | "gzip" | "brotli";
|
|
10
|
+
/** The suffix a compressed file carries. Duplicated in both packages and pinned by an equivalence test — the runtime must derive block paths without reading anything the CLI wrote. */
|
|
11
|
+
export declare function compressionSuffix(compression: Compression): string;
|
|
12
|
+
/** The `DecompressionStream` format name for a compression, or `undefined` when nothing was applied. */
|
|
13
|
+
export declare function decompressionFormat(compression: Compression): "gzip" | "brotli" | undefined;
|
|
14
|
+
/**
|
|
15
|
+
* `json` is a payload-only field (an object, or a list of objects): no value operators and no
|
|
16
|
+
* ordering, but a field marked `absent`/`nullable` still gets the missing-value operators (ADR-0012),
|
|
17
|
+
* which is why codegen emits it into the schema at all.
|
|
18
|
+
*/
|
|
19
|
+
export type FieldKind = "string" | "number" | "date" | "boolean" | "json";
|
|
20
|
+
export interface FieldMeta {
|
|
21
|
+
readonly kind: FieldKind;
|
|
22
|
+
/** Every operator a `where` may write on this field (ADR-0013). */
|
|
23
|
+
readonly operators: readonly string[];
|
|
24
|
+
/**
|
|
25
|
+
* The subset of `operators` that narrows which blocks a query reads; the others are riders. Always
|
|
26
|
+
* emitted by codegen. A hand-written schema that omits it falls back to "every operator but `not`
|
|
27
|
+
* and the missing-value operators prunes".
|
|
28
|
+
*/
|
|
29
|
+
readonly pruning?: readonly string[];
|
|
30
|
+
/** Multi-valued (string[]) → the list operators `some`/`every`/`hasEvery`/`isEmpty` (ADR-0010). */
|
|
31
|
+
readonly multi?: boolean;
|
|
32
|
+
/** This field is the user PK. */
|
|
33
|
+
readonly pk?: boolean;
|
|
34
|
+
/** The key may be missing from a record. Informational: `isAbsent`/`exists` arrive via `operators`. */
|
|
35
|
+
readonly absent?: boolean;
|
|
36
|
+
/** The value may be `null`. Informational: `isNull`/`exists` arrive via `operators`. */
|
|
37
|
+
readonly nullable?: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* The field's observed value set, baked in by codegen for low-cardinality string fields (an
|
|
40
|
+
* "enum-like" field: MTG colours, a rarity, a status). Narrows the *equality-shaped* operators so
|
|
41
|
+
* they autocomplete; absent → those operators accept any `string`.
|
|
42
|
+
*/
|
|
43
|
+
readonly values?: readonly string[];
|
|
44
|
+
}
|
|
45
|
+
export interface CollectionMeta {
|
|
46
|
+
/** Present ⟺ a user PK was declared → `get(id)` is emitted. */
|
|
47
|
+
readonly pk?: string;
|
|
48
|
+
readonly fields: {
|
|
49
|
+
readonly [field: string]: FieldMeta;
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
export interface SchemaMeta {
|
|
53
|
+
readonly [collection: string]: CollectionMeta;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* `V` is the field's value union when codegen baked one in (else `string`). Only the
|
|
57
|
+
* equality-shaped operators narrow to it: `startsWith`/`contains`/`endsWith` match a *fragment* of
|
|
58
|
+
* a value, and a fragment of an enum member is not itself an enum member — narrowing those would
|
|
59
|
+
* reject `contains: "art"` against a value of `"artifact"`.
|
|
60
|
+
*/
|
|
61
|
+
type AllStringOps<V extends string = string> = {
|
|
62
|
+
equals: V;
|
|
63
|
+
not: V;
|
|
64
|
+
in: V[];
|
|
65
|
+
startsWith: string;
|
|
66
|
+
contains: string;
|
|
67
|
+
endsWith: string;
|
|
68
|
+
gt: string;
|
|
69
|
+
gte: string;
|
|
70
|
+
lt: string;
|
|
71
|
+
lte: string;
|
|
72
|
+
};
|
|
73
|
+
type AllNumberOps = {
|
|
74
|
+
equals: number;
|
|
75
|
+
not: number;
|
|
76
|
+
in: number[];
|
|
77
|
+
gt: number;
|
|
78
|
+
gte: number;
|
|
79
|
+
lt: number;
|
|
80
|
+
lte: number;
|
|
81
|
+
};
|
|
82
|
+
type AllDateOps = {
|
|
83
|
+
equals: string;
|
|
84
|
+
not: string;
|
|
85
|
+
in: string[];
|
|
86
|
+
gt: string;
|
|
87
|
+
gte: string;
|
|
88
|
+
lt: string;
|
|
89
|
+
lte: string;
|
|
90
|
+
};
|
|
91
|
+
type AllBoolOps = {
|
|
92
|
+
equals: boolean;
|
|
93
|
+
not: boolean;
|
|
94
|
+
};
|
|
95
|
+
type PickOps<All, Ops extends string> = {
|
|
96
|
+
[K in Extract<keyof All, Ops>]?: All[K];
|
|
97
|
+
};
|
|
98
|
+
/** The missing-value operators, offered per field through its `operators` like any other. */
|
|
99
|
+
type MissingValueOps = {
|
|
100
|
+
isNull: true;
|
|
101
|
+
isAbsent: true;
|
|
102
|
+
exists: boolean;
|
|
103
|
+
};
|
|
104
|
+
/**
|
|
105
|
+
* A field's baked value union, or `string` when codegen didn't bake one (high-cardinality field, or
|
|
106
|
+
* a schema typed loosely as `SchemaMeta` rather than an `as const` literal — which degrades to the
|
|
107
|
+
* previous wide behavior rather than breaking).
|
|
108
|
+
*/
|
|
109
|
+
type ValuesOf<F extends FieldMeta> = F extends {
|
|
110
|
+
values: readonly (infer V extends string)[];
|
|
111
|
+
} ? V : string;
|
|
112
|
+
/** `{ some: value }` ≡ `{ some: { equals: value } }` (ADR-0001) — only offered where `equals` is itself enabled. */
|
|
113
|
+
type SomeShorthand<F extends FieldMeta> = "equals" extends F["operators"][number] ? ValuesOf<F> : never;
|
|
114
|
+
/** What `some` and `every` apply to each element: the field's own operators, or the equals shorthand. */
|
|
115
|
+
type ElementFilter<F extends FieldMeta> = PickOps<AllStringOps<ValuesOf<F>>, F["operators"][number]> | SomeShorthand<F>;
|
|
116
|
+
/** A multi-valued field's list operators (T7 `some`, ADR-0010 the rest). Keys on one field AND together. */
|
|
117
|
+
type ListOps<F extends FieldMeta> = {
|
|
118
|
+
some?: ElementFilter<F>;
|
|
119
|
+
every?: ElementFilter<F>;
|
|
120
|
+
hasEvery?: ValuesOf<F>[];
|
|
121
|
+
isEmpty?: true;
|
|
122
|
+
};
|
|
123
|
+
type FilterFor<F extends FieldMeta> = F extends {
|
|
124
|
+
kind: "string";
|
|
125
|
+
multi: true;
|
|
126
|
+
} ? ListOps<F> : F extends {
|
|
127
|
+
kind: "string";
|
|
128
|
+
} ? PickOps<AllStringOps<ValuesOf<F>> & MissingValueOps, F["operators"][number]> : F extends {
|
|
129
|
+
kind: "number";
|
|
130
|
+
} ? PickOps<AllNumberOps & MissingValueOps, F["operators"][number]> : F extends {
|
|
131
|
+
kind: "date";
|
|
132
|
+
} ? PickOps<AllDateOps & MissingValueOps, F["operators"][number]> : F extends {
|
|
133
|
+
kind: "boolean";
|
|
134
|
+
} ? PickOps<AllBoolOps & MissingValueOps, F["operators"][number]> : F extends {
|
|
135
|
+
kind: "json";
|
|
136
|
+
} ? PickOps<MissingValueOps, F["operators"][number]> : never;
|
|
137
|
+
/** The where type: every queryable field, each with ONLY its valid operators. */
|
|
138
|
+
export type WhereOf<C extends CollectionMeta> = {
|
|
139
|
+
[K in keyof C["fields"]]?: FilterFor<C["fields"][K]>;
|
|
140
|
+
};
|
|
141
|
+
/**
|
|
142
|
+
* orderBy over every queryable field — sorting happens in memory, so an index doesn't matter
|
|
143
|
+
* (ADR-0013). Not `json` fields: an object has no order.
|
|
144
|
+
*/
|
|
145
|
+
export type OrderByOf<C extends CollectionMeta> = {
|
|
146
|
+
[K in keyof C["fields"] as C["fields"][K]["kind"] extends "json" ? never : K]?: "asc" | "desc";
|
|
147
|
+
};
|
|
148
|
+
type ValidateFilter<F, Allowed> = {
|
|
149
|
+
[Op in keyof F]: Op extends keyof Allowed ? Allowed[Op] : never;
|
|
150
|
+
};
|
|
151
|
+
export type ValidateWhere<W, C extends CollectionMeta> = {
|
|
152
|
+
[K in keyof W]: K extends keyof C["fields"] ? ValidateFilter<NonNullable<W[K]>, FilterFor<C["fields"][K]>> : never;
|
|
153
|
+
};
|
|
154
|
+
type RiderOp = "not" | "isNull" | "isAbsent" | "exists";
|
|
155
|
+
type PruningOp<F extends FieldMeta> = F extends {
|
|
156
|
+
pruning: infer P extends readonly string[];
|
|
157
|
+
} ? P[number] : Exclude<F["operators"][number], RiderOp>;
|
|
158
|
+
/** A list field's `some`/`every` prune through their element filter; `hasEvery` and `isEmpty` do by name (their values are checked at runtime, by `wherePrunes`). */
|
|
159
|
+
type ElementPrunes<E, F extends FieldMeta> = E extends object ? Extract<keyof E, PruningOp<F>> extends never ? false : true : "equals" extends PruningOp<F> ? true : false;
|
|
160
|
+
type ListFilterPrunes<Filter, F extends FieldMeta> = Extract<keyof Filter, "hasEvery" | "isEmpty"> extends never ? true extends (Filter extends {
|
|
161
|
+
some: infer E;
|
|
162
|
+
} ? ElementPrunes<E, F> : false) | (Filter extends {
|
|
163
|
+
every: infer E;
|
|
164
|
+
} ? ElementPrunes<E, F> : false) ? true : false : true;
|
|
165
|
+
type FilterPrunes<Filter, F extends FieldMeta> = Filter extends object ? F extends {
|
|
166
|
+
multi: true;
|
|
167
|
+
} ? ListFilterPrunes<Filter, F> : Extract<keyof Filter, PruningOp<F>> extends never ? false : true : false;
|
|
168
|
+
type AnyPrunes<W, C extends CollectionMeta> = true extends {
|
|
169
|
+
[K in keyof W]: K extends keyof C["fields"] ? FilterPrunes<NonNullable<W[K]>, C["fields"][K]> : false;
|
|
170
|
+
}[keyof W] ? true : false;
|
|
171
|
+
export type RiderGuard<W, C extends CollectionMeta> = [keyof W] extends [never] ? {} : AnyPrunes<W, C> extends true ? {} : {
|
|
172
|
+
"❌ every filter here is a rider — add one on the sort field or an indexed field, so the query doesn't read every block": never;
|
|
173
|
+
};
|
|
174
|
+
/**
|
|
175
|
+
* `where` with every `undefined` left out: a filter set to `undefined`, an operator whose value is
|
|
176
|
+
* `undefined`, and a filter (or a list field's element filter) left empty by that. `undefined` means
|
|
177
|
+
* "no filter here", so `{ set: chosen ? { equals: chosen } : undefined }` and `{ year: { gte: from } }`
|
|
178
|
+
* with no `from` both drop out, the way they read. `findMany`, `count` and `wherePrunes` all see the
|
|
179
|
+
* compacted form, so the rider check and the query agree on what the `where` says.
|
|
180
|
+
*/
|
|
181
|
+
export declare function compactWhere(where: Record<string, Record<string, unknown> | undefined> | undefined): Record<string, Record<string, unknown>> | undefined;
|
|
182
|
+
/** The fields a pruning check reads: each field's operators and, when codegen emitted it, its `pruning` list. */
|
|
183
|
+
type PruningSchema = {
|
|
184
|
+
fields: Record<string, {
|
|
185
|
+
operators: readonly string[];
|
|
186
|
+
pruning?: readonly string[];
|
|
187
|
+
multi?: true | boolean;
|
|
188
|
+
}>;
|
|
189
|
+
};
|
|
190
|
+
/**
|
|
191
|
+
* Whether `where` has at least one filter that narrows which blocks are read, which is the rule
|
|
192
|
+
* `findMany` enforces with `NEEDS_PRUNING` (ADR-0013). For a `where` built from UI input: check it,
|
|
193
|
+
* and fall back (add a sort-field range, say) instead of catching the error. Pass the collection's
|
|
194
|
+
* `getSchema()`. An empty or missing `where` counts as pruning, since it is allowed.
|
|
195
|
+
*
|
|
196
|
+
* The rules the types can't see, because they depend on the value: `contains` prunes only with 3 or
|
|
197
|
+
* more characters (a shorter needle has no trigram to look up), and an empty `startsWith`/`endsWith`,
|
|
198
|
+
* an empty `hasEvery` and `isEmpty: false` match every block. Each of these rides.
|
|
199
|
+
*/
|
|
200
|
+
export declare function wherePrunes(where: Record<string, Record<string, unknown> | undefined> | undefined, schema: PruningSchema): boolean;
|
|
201
|
+
/**
|
|
202
|
+
* The rider rule at runtime (ADR-0013), for untyped JS callers and `where` objects built dynamically
|
|
203
|
+
* (e.g. from UI input) that the compiler never sees. Throws `NEEDS_PRUNING` naming the fields that
|
|
204
|
+
* could prune on this dataset. `wherePrunes` is the non-throwing check.
|
|
205
|
+
*/
|
|
206
|
+
export declare function assertWhereHasPruning(where: Record<string, Record<string, unknown>> | undefined, schema: PruningSchema & {
|
|
207
|
+
sortField: string;
|
|
208
|
+
}): void;
|
|
209
|
+
type PkField<C extends CollectionMeta> = C extends {
|
|
210
|
+
pk: infer P extends string;
|
|
211
|
+
} ? P : never;
|
|
212
|
+
type KindValueType<K extends FieldKind> = K extends "number" ? number : K extends "boolean" ? boolean : string;
|
|
213
|
+
type PkIdOf<C extends CollectionMeta> = PkField<C> extends keyof C["fields"] ? KindValueType<C["fields"][PkField<C>]["kind"]> : never;
|
|
214
|
+
type GetMember<C extends CollectionMeta, Rec> = PkField<C> extends never ? {} : {
|
|
215
|
+
get(id: PkIdOf<C>, opts?: QueryOptions): Promise<Rec | null>;
|
|
216
|
+
};
|
|
217
|
+
/**
|
|
218
|
+
* Per-query options every collection method accepts. `signal` cancels the query: its pending block,
|
|
219
|
+
* index and sidecar fetches are aborted and the call rejects with `ZonemapDbError` code `ABORTED`.
|
|
220
|
+
* The manifest fetch, shared by every query on the client, is never cancelled: an aborted query only
|
|
221
|
+
* stops waiting for it. For search-as-you-type, abort the previous keystroke's query before starting
|
|
222
|
+
* the next.
|
|
223
|
+
*/
|
|
224
|
+
export interface QueryOptions {
|
|
225
|
+
signal?: AbortSignal;
|
|
226
|
+
}
|
|
227
|
+
export interface FindManyArgs<C extends CollectionMeta, W extends WhereOf<C>> extends QueryOptions {
|
|
228
|
+
where?: W & ValidateWhere<W, C> & RiderGuard<W, C>;
|
|
229
|
+
orderBy?: OrderByOf<C>;
|
|
230
|
+
limit?: number;
|
|
231
|
+
offset?: number;
|
|
232
|
+
scan?: never;
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* A `findMany` that may filter on riders alone, by walking the data files in sort order until the
|
|
236
|
+
* page is full. Needs a `limit`, and no `orderBy` other than the sort field (checked at runtime, which
|
|
237
|
+
* is where the sort field is known), because that is what lets the walk stop early.
|
|
238
|
+
*
|
|
239
|
+
* Opt-in because the cost depends on the data: a rider most records match fills the page from the
|
|
240
|
+
* first file or two, and one few records match can read most of the dataset before it does. Use it
|
|
241
|
+
* for a browse-style search where either outcome is acceptable, not as a way around NEEDS_PRUNING.
|
|
242
|
+
*/
|
|
243
|
+
export interface BlockOrderScanArgs<C extends CollectionMeta, W extends WhereOf<C>> extends QueryOptions {
|
|
244
|
+
where?: W & ValidateWhere<W, C>;
|
|
245
|
+
scan: "block-order";
|
|
246
|
+
orderBy?: OrderByOf<C>;
|
|
247
|
+
limit: number;
|
|
248
|
+
offset?: number;
|
|
249
|
+
}
|
|
250
|
+
export interface FindManyResult<Rec> {
|
|
251
|
+
records: Rec[];
|
|
252
|
+
hasMore: boolean;
|
|
253
|
+
/**
|
|
254
|
+
* The EXACT number of records matching `where`, present only when answering the query already
|
|
255
|
+
* required seeing all of them (refines ADR-0008 §5). Free when it appears — the engine had the
|
|
256
|
+
* match set in hand and would otherwise have discarded its size.
|
|
257
|
+
*
|
|
258
|
+
* Present when every candidate block was read: any `orderBy` on a non-sort field (ordering can't be
|
|
259
|
+
* decided without them), no `limit`, or a block walk that ran out of candidates before it filled the
|
|
260
|
+
* page. Absent when the walk stopped early, which is exactly when the engine has NOT seen the tail.
|
|
261
|
+
*
|
|
262
|
+
* Prefer this over `count()` whenever it is present: `count()` is a zero-fetch upper bound that can
|
|
263
|
+
* be an order of magnitude high, while this is the truth. It is not `offset + records.length` — on a
|
|
264
|
+
* page past the end that formula returns the offset, not the total.
|
|
265
|
+
*/
|
|
266
|
+
total?: number;
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Approximate upper bound for pagination totals (ADR-0008 §2/§3): `exact: true`
|
|
270
|
+
* only for an empty where (→ recordCount) and pruned-to-zero (→ 0), so
|
|
271
|
+
* `count === 0` is always a trustworthy existence check.
|
|
272
|
+
*/
|
|
273
|
+
export interface CountResult {
|
|
274
|
+
count: number;
|
|
275
|
+
exact: boolean;
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Reserved for the deferred v2 exact mode — 1.0 locks the slot to `false`, so
|
|
279
|
+
* passing `exact: true` is a compile-time error (ADR-0008 §4).
|
|
280
|
+
*/
|
|
281
|
+
export interface CountOptions extends QueryOptions {
|
|
282
|
+
exact?: false;
|
|
283
|
+
}
|
|
284
|
+
interface CollectionBase<C extends CollectionMeta, Rec> {
|
|
285
|
+
findMany<W extends WhereOf<C>>(args?: FindManyArgs<C, W>): Promise<FindManyResult<Rec>>;
|
|
286
|
+
findMany<W extends WhereOf<C>>(args: BlockOrderScanArgs<C, W>): Promise<FindManyResult<Rec>>;
|
|
287
|
+
count<W extends WhereOf<C>>(where?: W & ValidateWhere<W, C>, opts?: CountOptions): Promise<CountResult>;
|
|
288
|
+
getSchema(): C;
|
|
289
|
+
}
|
|
290
|
+
export type Collection<C extends CollectionMeta, Rec> = CollectionBase<C, Rec> & GetMember<C, Rec>;
|
|
291
|
+
export interface ClientOptions {
|
|
292
|
+
basePath: string;
|
|
293
|
+
/**
|
|
294
|
+
* Injectable for non-browser / testing; defaults to global `fetch`. The manifest request passes
|
|
295
|
+
* `cache: "no-cache"` (and `"reload"` when recovering from a stale one, #32) in its `init`; a
|
|
296
|
+
* wrapper should forward `init` so the browser sees it.
|
|
297
|
+
*/
|
|
298
|
+
fetch?: typeof fetch;
|
|
299
|
+
/**
|
|
300
|
+
* Client-level result ceiling (default 10_000), a guardrail distinct from
|
|
301
|
+
* per-query `limit` — fail-loud (ADR-0004/0007): an explicit `limit` above
|
|
302
|
+
* it throws `LIMIT_EXCEEDED`, and an unbounded query that would match more
|
|
303
|
+
* than it throws rather than silently truncating.
|
|
304
|
+
*/
|
|
305
|
+
maxResults?: number;
|
|
306
|
+
/**
|
|
307
|
+
* Set by codegen when the build pre-compressed the manifest. Only the manifest needs telling:
|
|
308
|
+
* everything else it points at carries `.gz`/`.br` in its own path. Hand-written callers of
|
|
309
|
+
* `createClient` must match their deploy; the generated `connect()` already does.
|
|
310
|
+
*/
|
|
311
|
+
manifestCompression?: Compression;
|
|
312
|
+
/** @deprecated Use `manifestCompression: "gzip"`. */
|
|
313
|
+
manifestGzip?: boolean;
|
|
314
|
+
}
|
|
315
|
+
export type GenericClient<S extends SchemaMeta, Records> = {
|
|
316
|
+
[K in keyof S]: K extends keyof Records ? Collection<S[K], Records[K]> : never;
|
|
317
|
+
};
|
|
318
|
+
export {};
|
|
319
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|