diff --git a/crates/bindings/npm/.gitignore b/crates/bindings/npm/.gitignore new file mode 100644 index 0000000..c2658d7 --- /dev/null +++ b/crates/bindings/npm/.gitignore @@ -0,0 +1 @@ +node_modules/ diff --git a/crates/bindings/npm/build.sh b/crates/bindings/npm/build.sh index a73e851..f704e64 100755 --- a/crates/bindings/npm/build.sh +++ b/crates/bindings/npm/build.sh @@ -44,6 +44,17 @@ done mv "$out/node/catena.js" "$out/node/catena.cjs" mv "$out/node/catena.d.ts" "$out/node/catena.d.cts" +# The declarations are hand-written, so nothing but a type checker would +# notice them going wrong. Skipped where TypeScript is not installed rather +# than made a dependency of building at all. +if [ -x node_modules/.bin/tsc ]; then + node_modules/.bin/tsc --noEmit --strict --target es2022 --module es2022 \ + --moduleResolution bundler typecheck.ts + echo "declarations typecheck" +else + echo "skipped typecheck: npm install --no-save typescript" >&2 +fi + sed "s/@VERSION@/$version/" package.json.in >"$out/package.json" cp README.md "$out/README.md" cp ../LICENSE "$out/LICENSE" diff --git a/crates/bindings/npm/typecheck.ts b/crates/bindings/npm/typecheck.ts new file mode 100644 index 0000000..fef0c35 --- /dev/null +++ b/crates/bindings/npm/typecheck.ts @@ -0,0 +1,38 @@ +// Checked, not run: every line here must compile against the declarations the +// package ships. A binding whose types say `any` is one TypeScript cannot +// check, and nothing else would notice. +import { + chunkMarkdown, scrub, countTokens, parseSubtitles, packCues, + splitCollection, fuseHits, identify, + type Chunk, type Cue, type Section, type Hit, type Doc, +} from "./dist/web/catena.js"; + +const chunks: Chunk[] = chunkMarkdown("# One\n\nbody\n", 512, 64, 50, 768); +const page: number | null = chunks[0].page; +const chapter: string | null = chunks[0].chapter; +const flags: string[] = chunks[0].flags; + +const clean: string = scrub("# One\n", true); +const tokens: number = countTokens(clean); + +const cues: Cue[] = parseSubtitles("1\n00:00:01,000 --> 00:00:04,000\nline\n\n"); +const start: number = cues[0].start; +const packed: Chunk[] = packCues(cues, 75, 512); + +const works: Section[] = splitCollection("# One\n\nbody\n"); +const slug: string = works[0].slug; + +const hits: Hit[] = [{ v: 1, id: "a", channel: "vec", rank: 1, score: 0.5, payload: {} }]; +const fused: Hit[] = fuseHits(hits, 60, { vec: 2, fts: 1 }, 10); + +const doc: Doc = identify("book.pdf", new Uint8Array([0x25, 0x50])); +const kind: string = doc.kind; +const notes: string[] = doc.notes; + +// Optional arguments really are optional. +chunkMarkdown("x"); +parseSubtitles("x"); +packCues(cues); +fuseHits(hits); + +export const checked = [page, chapter, flags, clean, tokens, start, packed, slug, fused, kind, notes];