diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 476b4f1..aded997 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -42,6 +42,25 @@ jobs: # exists and every condition is beside the last. What breaks a # published package is the resolution instead, and only tsc and attw # read a package that way. + # + # The same job holds the API gate, because the gate needs the build + # this job already paid for. It is two links of one chain. The first + # asks whether binding.d.cts still says what the Rust says, since that + # file is generated and a committed generated file is a file that can + # go stale: change a signature, forget to rebuild, and the types ship + # describing a function that no longer exists. The second asks whether + # etc/zudb.api.md still says what binding.d.cts says, so that a change + # to what this package exports arrives as a diff in one small file + # somebody has to read rather than as a line buried in six hundred + # generated ones. + # + # What the report leaves out, said out loud: api-extractor reads + # declarations rather than the checker's merged view, so it does not + # follow the `declare module './binding.cjs'` augmentation in + # zudb.d.cts, and `stream` and `Symbol.asyncDispose` are missing from + # Connection there. Those two are held from the other side, by the + # fixtures under test/types that call both and are compiled by + # check:types under the settings a user's compiler would use. package: runs-on: ubuntu-latest steps: @@ -54,8 +73,24 @@ jobs: # The declarations are generated by the build, so there is nothing # to type-check until it has run. - run: npm run build:debug + - name: The generated declarations, still generated from this Rust + run: git diff --exit-code -- binding.d.cts - run: npm run check:types - run: npm run check:package + # The gate is validated the only way a gate can be: a change to + # the surface has to fail it. Renaming an exported function is the + # cheapest change that is unambiguously one, and the tree is put + # back before anything else looks at it. + - name: A surface change the gate is meant to catch, caught + run: | + sed -i 's/export declare function version(): string/export declare function versionRenamed(): string/' binding.d.cts + set +e + npm run check:api + rc=$? + set -e + git checkout -- binding.d.cts + test $rc -ne 0 || { echo "the api gate did not fire on a renamed export"; exit 1; } + - run: npm run check:api test: strategy: diff --git a/.gitignore b/.gitignore index 2148910..d123f53 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,10 @@ target/ node_modules/ dist/ +# Where api-extractor writes the report it just produced, before it is +# compared against the one in etc/ that is committed. +temp/ + # The built addon, which napi drops into the source tree so that the # tests load the same file a published package would. *.node diff --git a/api-extractor.json b/api-extractor.json new file mode 100644 index 0000000..12a92e1 --- /dev/null +++ b/api-extractor.json @@ -0,0 +1,54 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json", + + // projectFolder is said out loud because there is no tsconfig.json at + // the root to find it by. This package is Rust with a JavaScript face + // on it, and the only TypeScript configs it has are the two under + // tools and test. + "projectFolder": ".", + + // The CommonJS declarations, which are the ones written: the ESM file + // re-exports them so that a public API cannot exist in two copies and + // drift between them. + "mainEntryPointFilePath": "/zudb.d.cts", + + "compiler": { + "tsconfigFilePath": "/tools/api-extractor.tsconfig.json" + }, + + // The report is the point of running this at all. etc/zudb.api.md is + // committed, CI regenerates it and fails if it moved, and so every + // change to what this package exports arrives as a diff somebody has + // to read rather than as a line buried in six hundred generated ones. + "apiReport": { + "enabled": true, + "reportFileName": "zudb.api.md", + "reportFolder": "/etc/", + "reportTempFolder": "/temp/" + }, + + "docModel": { "enabled": false }, + "dtsRollup": { "enabled": false }, + "tsdocMetadata": { "enabled": false }, + + "messages": { + "compilerMessageReporting": { + "default": { "logLevel": "warning" } + }, + + // Release tags and doc comments are not how this package marks what + // is public: the exports map is, and everything reachable through + // it is public. So the two rules that ask for tags are off and the + // one that catches a type leaking out untyped is on. + "extractorMessageReporting": { + "default": { "logLevel": "warning" }, + "ae-missing-release-tag": { "logLevel": "none" }, + "ae-undocumented": { "logLevel": "none" }, + "ae-forgotten-export": { "logLevel": "error", "addToApiReportFile": true } + }, + + "tsdocMessageReporting": { + "default": { "logLevel": "none" } + } + } +} diff --git a/etc/zudb.api.md b/etc/zudb.api.md new file mode 100644 index 0000000..3672031 --- /dev/null +++ b/etc/zudb.api.md @@ -0,0 +1,282 @@ +## API Report File for "zudb" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts + +// @public +export function abiVersion(): string + +// @public +export function connect(path: string, options?: ConnectOptions | undefined | null): Promise + +// @public +export class Connection { + close(): void + cursor(statement: string, params?: Record | null, options?: ZuStreamOptions | null): ZuCursor + dispose(): Promise + exec(statement: string, params?: Record | null, options?: ZuStatementOptions | null): Promise + get open(): boolean + get path(): string + query>(statement: string, params?: Record | null, options?: ZuStatementOptions | null): Promise> + get readOnly(): boolean +} + +// @public +export interface ConnectOptions { + bigIntMode?: ZuBigIntMode + memoryLimit?: bigint + readOnly?: boolean + temporal?: boolean + threads?: number +} + +// @public +export function isZuError(value: unknown): value is ZuError + +// @public +export function version(): string + +// @public +export interface ZuBatch> extends Array { + // (undocumented) + readonly columns: string[] +} + +// @public +export type ZuBigIntMode = 'bigint' | 'number' + +// @public +export class ZuCursor { + cancel(): Promise + next(): Promise + get summary(): ZuSummary | null +} + +// @public +export class ZuDate { + constructor(days: number) + // (undocumented) + days: number + toJSON(): object + toTemporal(): ZuPlainDate +} + +// @public +export class ZuDuration { + get kind(): string + get months(): bigint + get nanos(): bigint + static ofMonths(months: bigint): ZuDuration + static ofNanos(nanos: bigint): ZuDuration + toJSON(): object + toTemporal(): ZuTemporalDuration +} + +// @public +export interface ZuError extends Error { + readonly code?: string + // (undocumented) + readonly column?: number + readonly condition?: string + // (undocumented) + readonly docUrl?: string + readonly excerpt?: string + readonly line?: number + readonly name: string + // (undocumented) + readonly offset?: number + readonly retryable: boolean + // (undocumented) + readonly severity?: 'success' | 'noData' | 'warning' | 'informational' | 'exception' +} + +// @public +export class ZuNode { + // (undocumented) + get offset(): bigint + // (undocumented) + get table(): string + toJSON(): object +} + +// @public +export interface ZuNotice { + // (undocumented) + readonly code: string + // (undocumented) + readonly condition: string + // (undocumented) + readonly docUrl: string + // (undocumented) + readonly message: string +} + +// @public +export type ZuParam = +| null +| undefined +| boolean +| number +| bigint +| string +| ZuDate +| ZuTime +| ZuTimestamp +| ZuDuration +| ZuTemporalValue +| ZuParam[] +| { [field: string]: ZuParam } + +// @public +export interface ZuPath { + // (undocumented) + readonly nodes: ZuNode[] + // (undocumented) + readonly rels: ZuRel[] +} + +// @public +export type ZuPlainDate = typeof globalThis extends { + Temporal: { PlainDate: new (...args: any[]) => infer Value } +} +? Value +: unknown + +// @public +export type ZuPlainDateTime = typeof globalThis extends { + Temporal: { PlainDateTime: new (...args: any[]) => infer Value } +} +? Value +: unknown + +// @public +export type ZuPlainTime = typeof globalThis extends { + Temporal: { PlainTime: new (...args: any[]) => infer Value } +} +? Value +: unknown + +// @public +export class ZuRel { + // (undocumented) + get dst(): bigint + // (undocumented) + get ord(): bigint + // (undocumented) + get src(): bigint + // (undocumented) + get table(): string + toJSON(): object +} + +// @public +export interface ZuRows> extends Array { + // (undocumented) + readonly columns: string[] + // (undocumented) + readonly gqlstatus: string + // (undocumented) + readonly notices: ZuNotice[] +} + +// @public +export interface ZuStatementOptions { + readonly bigIntMode?: ZuBigIntMode + readonly signal?: AbortSignal +} + +// @public +export class ZuStream> implements AsyncIterable, AsyncDisposable { + // (undocumented) + [Symbol.asyncDispose](): Promise + // (undocumented) + [Symbol.asyncIterator](): AsyncIterableIterator + batches(): AsyncIterableIterator> + cancel(): Promise + readonly columns: string[] | null + readonly summary: ZuSummary | null + toReadableStream(): ReadableStream +} + +// @public +export interface ZuStreamOptions extends ZuStatementOptions { + readonly batchRows?: number +} + +// @public +export interface ZuSummary { + // (undocumented) + readonly columns: string[] + // (undocumented) + readonly notices: ZuNotice[] + readonly rows: number + // (undocumented) + readonly stopped: boolean + readonly streamed: boolean +} + +// @public +export type ZuTemporalDuration = typeof globalThis extends { + Temporal: { Duration: new (...args: any[]) => infer Value } +} +? Value +: unknown + +// @public +export type ZuTemporalValue = typeof globalThis extends { + Temporal: { Instant: new (...args: any[]) => infer Instant } +} +? Instant | ZuPlainDate | ZuPlainTime | ZuPlainDateTime | ZuZonedDateTime | ZuTemporalDuration +: never + +// @public +export class ZuTime { + constructor(nanos: bigint, offset?: number | undefined | null) + // (undocumented) + get nanos(): bigint + // (undocumented) + offset?: number + toJSON(): object + toTemporal(): ZuPlainTime +} + +// @public +export class ZuTimestamp { + constructor(nanos: bigint, offset?: number | undefined | null) + // (undocumented) + get nanos(): bigint + // (undocumented) + offset?: number + toJSON(): object + toTemporal(): ZuPlainDateTime | ZuZonedDateTime +} + +// @public +export type ZuValue = +| null +| boolean +| number +| bigint +| string +| ZuNode +| ZuRel +| ZuPath +| ZuDate +| ZuTime +| ZuTimestamp +| ZuDuration +| ZuTemporalValue +| ZuValue[] +| { [field: string]: ZuValue } + +// @public +export type ZuZonedDateTime = typeof globalThis extends { + Temporal: { ZonedDateTime: new (...args: any[]) => infer Value } +} +? Value +: unknown + +// (No @packageDocumentation comment for this package) + +``` diff --git a/package-lock.json b/package-lock.json index 3448996..0d63c9b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "license": "Apache-2.0", "devDependencies": { "@arethetypeswrong/cli": "^0.18.2", + "@microsoft/api-extractor": "^7.58.12", "@napi-rs/cli": "^3.8.6", "@types/node": "^26.2.0", "typescript": "^5.9.3" @@ -487,6 +488,76 @@ "@braidai/lang": "^1.0.0" } }, + "node_modules/@microsoft/api-extractor": { + "version": "7.58.12", + "resolved": "https://registry.npmjs.org/@microsoft/api-extractor/-/api-extractor-7.58.12.tgz", + "integrity": "sha512-VNpgC/1LaroLbn+UKmwDYspq+9r3EHyj4vJ3qUy/g8vB0rKt+1Wgs7WFj/JGpgxhG8SNyXs1XwYwe7nqkk8IDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@microsoft/api-extractor-model": "7.33.10", + "@microsoft/tsdoc": "~0.16.0", + "@microsoft/tsdoc-config": "~0.18.1", + "@rushstack/node-core-library": "5.23.3", + "@rushstack/rig-package": "0.7.3", + "@rushstack/terminal": "0.24.2", + "@rushstack/ts-command-line": "5.3.12", + "diff": "~8.0.2", + "minimatch": "10.2.3", + "resolve": "~1.22.1", + "semver": "~7.7.4", + "source-map": "~0.6.1", + "typescript": "5.9.3" + }, + "bin": { + "api-extractor": "bin/api-extractor" + } + }, + "node_modules/@microsoft/api-extractor-model": { + "version": "7.33.10", + "resolved": "https://registry.npmjs.org/@microsoft/api-extractor-model/-/api-extractor-model-7.33.10.tgz", + "integrity": "sha512-uPUK17xGxeQ3av6TN7awp+dTTSTvx8fZC0XFL1gyt7hFapYuxND3XLXH8vkmI7UjfW92oogzFAFqHSifmJROaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@microsoft/tsdoc": "~0.16.0", + "@microsoft/tsdoc-config": "~0.18.1", + "@rushstack/node-core-library": "5.23.3" + } + }, + "node_modules/@microsoft/api-extractor/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@microsoft/tsdoc": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.16.0.tgz", + "integrity": "sha512-xgAyonlVVS+q7Vc7qLW0UrJU7rSFcETRWsqdXZtjzRU8dF+6CkozTK4V4y1LwOX7j8r/vHphjDeMeGI4tNGeGA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@microsoft/tsdoc-config": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc-config/-/tsdoc-config-0.18.1.tgz", + "integrity": "sha512-9brPoVdfN9k9g0dcWkFeA7IH9bbcttzDJlXvkf8b2OBzd5MueR1V2wkKBL0abn0otvmkHJC6aapBOTJDDeMCZg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@microsoft/tsdoc": "0.16.0", + "ajv": "~8.18.0", + "jju": "~1.4.0", + "resolve": "~1.22.2" + } + }, "node_modules/@napi-rs/cli": { "version": "3.8.6", "resolved": "https://registry.npmjs.org/@napi-rs/cli/-/cli-3.8.6.tgz", @@ -1792,6 +1863,146 @@ "@octokit/openapi-types": "^28.0.0" } }, + "node_modules/@rushstack/node-core-library": { + "version": "5.23.3", + "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-5.23.3.tgz", + "integrity": "sha512-f6uuza7Um65bwsIJgf0MRs7IPA5IG+A+zs1AYGQvpZmLjtTGdfHowhQw4kwF0pPhJCrU4UHNhK8Qa6tLygYZCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "~8.20.0", + "ajv-draft-04": "~1.0.0", + "ajv-formats": "~3.0.1", + "fs-extra": "~11.3.0", + "import-lazy": "~4.0.0", + "jju": "~1.4.0", + "resolve": "~1.22.1", + "semver": "~7.7.4" + }, + "peerDependencies": { + "@types/node": "*" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@rushstack/node-core-library/node_modules/ajv": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@rushstack/node-core-library/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@rushstack/problem-matcher": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@rushstack/problem-matcher/-/problem-matcher-0.2.1.tgz", + "integrity": "sha512-gulfhBs6n+I5b7DvjKRfhMGyUejtSgOHTclF/eONr8hcgF1APEDjhxIsfdUYYMzC3rvLwGluqLjbwCFZ8nxrog==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/node": "*" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@rushstack/rig-package": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/@rushstack/rig-package/-/rig-package-0.7.3.tgz", + "integrity": "sha512-aAA518n6wxxjCfnTAOjQnm7ngNE0FVHxHAw2pxKlIhxrMn0XQjGcXKF0oKWpjBgJOmsaJpVob/v+zr3zxgPWuA==", + "dev": true, + "license": "MIT", + "dependencies": { + "jju": "~1.4.0", + "resolve": "~1.22.1" + } + }, + "node_modules/@rushstack/terminal": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@rushstack/terminal/-/terminal-0.24.2.tgz", + "integrity": "sha512-KB7PpvzDyKMw/RGU3TxOwxTs3OwZ4gq6+WHlTJN/JfQH4ezliNtWIqver78jTaAJyz/ZAAlJGH7a/M1WyFLFSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rushstack/node-core-library": "5.23.3", + "@rushstack/problem-matcher": "0.2.1", + "supports-color": "~8.1.1" + }, + "peerDependencies": { + "@types/node": "*" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@rushstack/terminal/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/@rushstack/ts-command-line": { + "version": "5.3.12", + "resolved": "https://registry.npmjs.org/@rushstack/ts-command-line/-/ts-command-line-5.3.12.tgz", + "integrity": "sha512-Vg2n24arSf7JvUNga2DMHYTbxnVq9L5OtVCp4Gfr8YC/kmL/bmdR8FQhGcpMzMYNY9Vdw3+TaimG11Sf+z1Tpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rushstack/terminal": "0.24.2", + "@types/argparse": "1.0.38", + "argparse": "~1.0.9", + "string-argv": "~0.3.1" + } + }, + "node_modules/@rushstack/ts-command-line/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, "node_modules/@sindresorhus/is": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", @@ -1816,6 +2027,13 @@ "tslib": "^2.4.0" } }, + "node_modules/@types/argparse": { + "version": "1.0.38", + "resolved": "https://registry.npmjs.org/@types/argparse/-/argparse-1.0.38.tgz", + "integrity": "sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/node": { "version": "26.2.0", "resolved": "https://registry.npmjs.org/@types/node/-/node-26.2.0.tgz", @@ -1826,6 +2044,56 @@ "undici-types": "~8.3.0" } }, + "node_modules/ajv": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", + "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-draft-04": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz", + "integrity": "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "ajv": "^8.5.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-formats": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, "node_modules/ansi-escapes": { "version": "7.3.0", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.3.0.tgz", @@ -1885,6 +2153,16 @@ "dev": true, "license": "Python-2.0" }, + "node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, "node_modules/before-after-hook": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-4.0.0.tgz", @@ -1892,6 +2170,19 @@ "dev": true, "license": "Apache-2.0" }, + "node_modules/brace-expansion": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", + "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "20 || >=22" + } + }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -2078,6 +2369,16 @@ } } }, + "node_modules/diff": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/diff/-/diff-8.0.4.tgz", + "integrity": "sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -2105,6 +2406,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-toolkit": { "version": "1.51.0", "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.51.0.tgz", @@ -2128,6 +2439,13 @@ "node": ">=6" } }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, "node_modules/fast-string-truncated-width": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/fast-string-truncated-width/-/fast-string-truncated-width-3.0.3.tgz", @@ -2145,6 +2463,23 @@ "fast-string-truncated-width": "^3.0.2" } }, + "node_modules/fast-uri": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.5.tgz", + "integrity": "sha512-gHwA1O9LDIcKunMKhObS/HimwtehO1nPUECKAu5TpKgaO19fcWEl4bliWe1jWxVFvIXztJjjQ4L8XQ1EU9f7Jw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, "node_modules/fast-wrap-ansi": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/fast-wrap-ansi/-/fast-wrap-ansi-0.2.2.tgz", @@ -2162,6 +2497,31 @@ "dev": true, "license": "MIT" }, + "node_modules/fs-extra": { + "version": "11.3.6", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.6.tgz", + "integrity": "sha512-w8ZNZr2mKIc7qeNaQ9AVPT1+iFaI+Avd4xudVOvdDJ8VytREi1Ft5Ih7hd9jjehod8vAM5GMsfQ/TpPf4EyoEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -2172,6 +2532,13 @@ "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -2182,6 +2549,19 @@ "node": ">=8" } }, + "node_modules/hasown": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/highlight.js": { "version": "10.7.3", "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", @@ -2209,6 +2589,32 @@ "url": "https://opencollective.com/express" } }, + "node_modules/import-lazy": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz", + "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.16.2", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz", + "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -2219,6 +2625,13 @@ "node": ">=8" } }, + "node_modules/jju": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", + "integrity": "sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==", + "dev": true, + "license": "MIT" + }, "node_modules/js-yaml": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.1.tgz", @@ -2242,6 +2655,13 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, "node_modules/json-with-bigint": { "version": "3.5.12", "resolved": "https://registry.npmjs.org/json-with-bigint/-/json-with-bigint-3.5.12.tgz", @@ -2249,6 +2669,19 @@ "dev": true, "license": "MIT" }, + "node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, "node_modules/lru-cache": { "version": "11.5.2", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.2.tgz", @@ -2307,6 +2740,22 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/minimatch": { + "version": "10.2.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.3.tgz", + "integrity": "sha512-Rwi3pnapEqirPSbWbrZaa6N3nmqq4Xer/2XooiOKyV3q12ML06f7MOuc5DVH8ONZIFhwIYQ3yzPH4nt7iWHaTg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -2400,6 +2849,13 @@ "dev": true, "license": "MIT" }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -2410,6 +2866,38 @@ "node": ">=0.10.0" } }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.12", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz", + "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -2456,6 +2944,33 @@ "node": ">=8" } }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/string-argv": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", + "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6.19" + } + }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -2524,6 +3039,19 @@ "url": "https://github.com/chalk/supports-hyperlinks?sponsor=1" } }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/thenify": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", @@ -2603,6 +3131,16 @@ "dev": true, "license": "ISC" }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, "node_modules/validate-npm-package-name": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz", diff --git a/package.json b/package.json index 051aff6..105ccb1 100644 --- a/package.json +++ b/package.json @@ -67,11 +67,14 @@ "test:deno": "deno test --no-check --allow-read --allow-write --allow-env --allow-ffi \"test/*.test.mjs\"", "check:types": "tsc --noEmit --project test/types/tsconfig.json", "check:package": "attw --pack .", + "check:api": "api-extractor run --verbose", + "check:api:update": "api-extractor run --local", "bench": "node bench/query.mjs", "bench:temporal": "node --harmony-temporal bench/query.mjs" }, "devDependencies": { "@arethetypeswrong/cli": "^0.18.2", + "@microsoft/api-extractor": "^7.58.12", "@napi-rs/cli": "^3.8.6", "@types/node": "^26.2.0", "typescript": "^5.9.3" diff --git a/tools/api-extractor.tsconfig.json b/tools/api-extractor.tsconfig.json new file mode 100644 index 0000000..84b0c66 --- /dev/null +++ b/tools/api-extractor.tsconfig.json @@ -0,0 +1,23 @@ +{ + "//": [ + "The compiler settings api-extractor reads the public types with.", + "They are the ones in test/types/tsconfig.json, because the report", + "is meant to say what a TypeScript user sees and that file is what", + "a TypeScript user's compiler does. skipLibCheck is on here and off", + "there: this run is a reader rather than a checker, and the checking", + "is what the other one is for." + ], + "compilerOptions": { + "module": "node16", + "moduleResolution": "node16", + "target": "es2023", + "lib": ["ES2023", "ESNext.Disposable"], + "types": ["node"], + "strict": true, + "noEmit": true, + "skipLibCheck": true, + "exactOptionalPropertyTypes": true, + "noUncheckedIndexedAccess": true + }, + "files": ["../zudb.d.cts"] +}