@gesetz/sqlite-compat 3.0.0-rc.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +65 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.js +86 -0
- package/package.json +31 -0
package/README.md
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# `@gesetz/sqlite-compat`
|
|
2
|
+
|
|
3
|
+
Optional SQLite cache driver for **gesetz** on runtimes without a usable
|
|
4
|
+
`node:sqlite` module — Node < 23.4, or Bun.
|
|
5
|
+
|
|
6
|
+
## Why this is separate
|
|
7
|
+
|
|
8
|
+
`@gesetz/core` must stay dependency-light, so it never depends on a native
|
|
9
|
+
SQLite binding. It exposes a driver registry instead, and this package registers
|
|
10
|
+
a `better-sqlite3`-backed implementation under the `sqlite` kind.
|
|
11
|
+
|
|
12
|
+
## Install
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
pnpm add -D @gesetz/sqlite-compat
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
`better-sqlite3` is a dependency of this package, so this pulls the native
|
|
19
|
+
module too. It is never a dependency of `@gesetz/core`.
|
|
20
|
+
|
|
21
|
+
## Use
|
|
22
|
+
|
|
23
|
+
Import it once from `gesetz.config.ts`. The import is the entire opt-in — it
|
|
24
|
+
registers the driver as a side effect:
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
// gesetz.config.ts
|
|
28
|
+
import '@gesetz/sqlite-compat';
|
|
29
|
+
import { defineConfig } from 'gesetz';
|
|
30
|
+
|
|
31
|
+
export default defineConfig({
|
|
32
|
+
rules: [
|
|
33
|
+
/* … */
|
|
34
|
+
],
|
|
35
|
+
});
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
That is the whole change — the default shared cache then works on this runtime.
|
|
39
|
+
(To keep the cache somewhere specific instead, set
|
|
40
|
+
`storage: { kind: 'sqlite', path: '…' }`.)
|
|
41
|
+
|
|
42
|
+
`gesetz check` then uses `better-sqlite3` automatically whenever `node:sqlite`
|
|
43
|
+
is unavailable. Driver selection is automatic and is **not** a user-facing
|
|
44
|
+
setting: `storage` only says *whether* and *where* to cache.
|
|
45
|
+
|
|
46
|
+
If `better-sqlite3` cannot be resolved, importing this module is a no-op and
|
|
47
|
+
gesetz runs without a cache.
|
|
48
|
+
|
|
49
|
+
## API
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
import { createBetterSqliteStore, registerBetterSqliteDriver } from '@gesetz/sqlite-compat';
|
|
53
|
+
|
|
54
|
+
// Register explicitly instead of relying on the import side effect.
|
|
55
|
+
registerBetterSqliteDriver(); // false when better-sqlite3 is not installed
|
|
56
|
+
|
|
57
|
+
// Build a store directly.
|
|
58
|
+
const store = await createBetterSqliteStore('/path/to/cache.db', { namespace: projectRoot });
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
- `createBetterSqliteStore(path, options?)` — throws with an actionable message
|
|
62
|
+
when `better-sqlite3` cannot be resolved. `options.ctor` and `options.load`
|
|
63
|
+
exist for tests.
|
|
64
|
+
- `registerBetterSqliteDriver(load?)` — registers the driver and returns whether
|
|
65
|
+
it succeeded.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { CacheStore, SqliteLikeDatabase, SqliteStoreNamespaceOptions } from "@gesetz/core";
|
|
2
|
+
|
|
3
|
+
//#region src/index.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* The subset of the `better-sqlite3` constructor we use. Declared structurally
|
|
6
|
+
* so this package typechecks without `@types/better-sqlite3` installed.
|
|
7
|
+
*/
|
|
8
|
+
interface BetterSqliteConstructor {
|
|
9
|
+
new (path: string): SqliteLikeDatabase;
|
|
10
|
+
}
|
|
11
|
+
/** Loads the raw `better-sqlite3` module export. Injectable for tests. */
|
|
12
|
+
type BetterSqliteLoader = () => unknown | Promise<unknown>;
|
|
13
|
+
interface CreateBetterSqliteStoreOptions extends SqliteStoreNamespaceOptions {
|
|
14
|
+
/** Use an already-resolved constructor instead of loading `better-sqlite3`. */
|
|
15
|
+
readonly ctor?: BetterSqliteConstructor | undefined;
|
|
16
|
+
/** Override the module loader. Intended for tests. */
|
|
17
|
+
readonly load?: BetterSqliteLoader | undefined;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Creates a cache store backed by `better-sqlite3`.
|
|
21
|
+
*
|
|
22
|
+
* Throws with an actionable message when `better-sqlite3` is not installed.
|
|
23
|
+
*/
|
|
24
|
+
declare function createBetterSqliteStore(path: string, options?: CreateBetterSqliteStoreOptions): Promise<CacheStore>;
|
|
25
|
+
/**
|
|
26
|
+
* Registers the `better-sqlite3` driver with `@gesetz/core`.
|
|
27
|
+
* Returns false (and registers nothing) when `better-sqlite3` is unavailable.
|
|
28
|
+
*/
|
|
29
|
+
declare function registerBetterSqliteDriver(load?: BetterSqliteLoader): boolean;
|
|
30
|
+
//#endregion
|
|
31
|
+
export { BetterSqliteConstructor, BetterSqliteLoader, CreateBetterSqliteStoreOptions, createBetterSqliteStore, registerBetterSqliteDriver };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
import { createSqliteStoreFromDatabase, registerCacheDriver } from "@gesetz/core";
|
|
3
|
+
//#region src/index.ts
|
|
4
|
+
/**
|
|
5
|
+
* `@gesetz/sqlite-compat` — optional SQLite cache driver for runtimes without a
|
|
6
|
+
* usable `node:sqlite` module (Node < 23.4, or Bun).
|
|
7
|
+
*
|
|
8
|
+
* ## Why this is a separate package
|
|
9
|
+
*
|
|
10
|
+
* `@gesetz/core` must stay dependency-light, so it never depends on a native
|
|
11
|
+
* SQLite binding. Instead it exposes a driver registry, and this package
|
|
12
|
+
* registers a `better-sqlite3`-backed implementation under the `sqlite` kind.
|
|
13
|
+
*
|
|
14
|
+
* ## Usage
|
|
15
|
+
*
|
|
16
|
+
* Install `better-sqlite3` and this package, then import it once from
|
|
17
|
+
* `gesetz.config.ts` — the registration is the entire opt-in:
|
|
18
|
+
*
|
|
19
|
+
* ```ts
|
|
20
|
+
* // gesetz.config.ts
|
|
21
|
+
* import '@gesetz/sqlite-compat';
|
|
22
|
+
* import { defineConfig } from 'gesetz';
|
|
23
|
+
*
|
|
24
|
+
* export default defineConfig({
|
|
25
|
+
* storage: { kind: 'sqlite', path: '.gesetz/cache.db' },
|
|
26
|
+
* rules: [/* … *\/],
|
|
27
|
+
* });
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* `gesetz check` will then use `better-sqlite3` automatically when
|
|
31
|
+
* `node:sqlite` is unavailable. To force it even where `node:sqlite` exists,
|
|
32
|
+
* set `storage: { kind: 'sqlite', path, driver: 'compat' }`.
|
|
33
|
+
*
|
|
34
|
+
* If `better-sqlite3` cannot be resolved, importing this module is a no-op and
|
|
35
|
+
* gesetz falls back to the JSON cache.
|
|
36
|
+
*/
|
|
37
|
+
const SQLITE_MODULE = "better-sqlite3";
|
|
38
|
+
/** Accepts either `module.exports = Ctor` or `{ default: Ctor }`. */
|
|
39
|
+
function resolveConstructor(module) {
|
|
40
|
+
if (typeof module === "function") return module;
|
|
41
|
+
if (module !== null && typeof module === "object") {
|
|
42
|
+
const candidate = module.default;
|
|
43
|
+
if (typeof candidate === "function") return candidate;
|
|
44
|
+
}
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
let cachedConstructor;
|
|
48
|
+
function loadConstructor() {
|
|
49
|
+
cachedConstructor ??= (() => {
|
|
50
|
+
try {
|
|
51
|
+
return resolveConstructor(createRequire(import.meta.url)(SQLITE_MODULE));
|
|
52
|
+
} catch {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
})();
|
|
56
|
+
return cachedConstructor;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Creates a cache store backed by `better-sqlite3`.
|
|
60
|
+
*
|
|
61
|
+
* Throws with an actionable message when `better-sqlite3` is not installed.
|
|
62
|
+
*/
|
|
63
|
+
async function createBetterSqliteStore(path, options = {}) {
|
|
64
|
+
const ctor = options.ctor ?? (options.load !== void 0 ? resolveConstructor(await options.load()) : loadConstructor());
|
|
65
|
+
if (ctor === null) throw new Error(`gesetz: ${SQLITE_MODULE} is not installed, so @gesetz/sqlite-compat cannot back the cache. Install it with: pnpm add -D ${SQLITE_MODULE}`);
|
|
66
|
+
return createSqliteStoreFromDatabase(new ctor(path), {
|
|
67
|
+
namespace: options.namespace,
|
|
68
|
+
ttlMs: options.ttlMs
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Registers the `better-sqlite3` driver with `@gesetz/core`.
|
|
73
|
+
* Returns false (and registers nothing) when `better-sqlite3` is unavailable.
|
|
74
|
+
*/
|
|
75
|
+
function registerBetterSqliteDriver(load = () => loadConstructor()) {
|
|
76
|
+
const resolved = resolveConstructor(load());
|
|
77
|
+
if (resolved === null) return false;
|
|
78
|
+
registerCacheDriver("sqlite", (path, options) => createBetterSqliteStore(path, {
|
|
79
|
+
ctor: resolved,
|
|
80
|
+
...options ?? {}
|
|
81
|
+
}));
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
registerBetterSqliteDriver();
|
|
85
|
+
//#endregion
|
|
86
|
+
export { createBetterSqliteStore, registerBetterSqliteDriver };
|
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@gesetz/sqlite-compat",
|
|
3
|
+
"version": "3.0.0-rc.8",
|
|
4
|
+
"description": "Optional better-sqlite3 cache driver for gesetz on runtimes without node:sqlite",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": {
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"import": "./dist/index.js"
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"better-sqlite3": "^13.0.0",
|
|
14
|
+
"@gesetz/core": "3.0.0-rc.8"
|
|
15
|
+
},
|
|
16
|
+
"devDependencies": {
|
|
17
|
+
"@types/node": "^22.0.0",
|
|
18
|
+
"typescript": "^5.8.0",
|
|
19
|
+
"vitest": "^4.0.0"
|
|
20
|
+
},
|
|
21
|
+
"types": "./dist/index.d.ts",
|
|
22
|
+
"files": [
|
|
23
|
+
"dist"
|
|
24
|
+
],
|
|
25
|
+
"scripts": {
|
|
26
|
+
"test": "vitest run",
|
|
27
|
+
"test:watch": "vitest",
|
|
28
|
+
"typecheck": "tsc --noEmit",
|
|
29
|
+
"build": "tsdown"
|
|
30
|
+
}
|
|
31
|
+
}
|