inillucent 0.1.4 → 0.1.5

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 CHANGED
@@ -1,102 +1,102 @@
1
- # inillucent
2
-
3
- An embedded SQL database that speaks SQLite's dialect on its own storage, with
4
- full-text and vector search built in — the job of PostgreSQL + pgvector + an
5
- embedding server, in one process and one file.
6
-
7
- ```sh
8
- npm install -g inillucent
9
- # or, without installing anything permanently:
10
- npx inillucent help
11
- ```
12
-
13
- No native build step and no postinstall download: the binaries ship as
14
- per-platform packages that npm installs only where they run, so `npm ci` works
15
- offline and behind a proxy.
16
-
17
- ## Four programs
18
-
19
- | | |
20
- |---|---|
21
- | `inillucent` | the command line: `query`, `exec`, `describe`, `import`, `export`, `search`, and twenty more |
22
- | `inillucent-shell` | an interactive shell shaped like `sqlite3`, with all 63 of its dot commands |
23
- | `inillucent-mcp` | the same commands served to an AI agent over MCP |
24
- | `inillucent-migrate` | builds an inillucent database from a SQLite file |
25
-
26
- ## From a shell
27
-
28
- ```sh
29
- inillucent create app.rdb
30
- inillucent --db app.rdb exec "CREATE TABLE notes (id INTEGER PRIMARY KEY, body TEXT)"
31
- inillucent --db app.rdb exec "INSERT INTO notes (body) VALUES (?1)" --params '["hello"]'
32
- inillucent --db app.rdb query "SELECT * FROM notes"
33
- inillucent --db app.rdb describe notes
34
- inillucent help
35
- ```
36
-
37
- Exit codes carry meaning: `0` success, `1` failed, `2` a command line nobody
38
- could act on, and **`3` a construct the engine has not built yet** — so a script
39
- can branch on "not yet" without matching on a message.
40
-
41
- ## From Node
42
-
43
- ```js
44
- import { query, inillucent } from 'inillucent';
45
-
46
- const rows = await query('SELECT id, body FROM notes WHERE id > ?1', {
47
- db: 'app.rdb',
48
- params: [3],
49
- });
50
- // [{ id: 4, body: 'hello' }]
51
-
52
- const described = await inillucent('describe', { db: 'app.rdb', table: 'notes' });
53
- console.log(described.ddl, described.indexes, described.row_count_in_table);
54
- ```
55
-
56
- Each call is a process, so this is the right tool for the dozen calls a build
57
- script or a tool wrapper makes and the wrong one for a loop over a million rows.
58
- For that, write a binding over the C ABI — the header ships in this package's
59
- platform dependency under `include/`, and
60
- [`drivers/README.md`](https://github.com/Black-Rainbow-Labs/Inillucent/blob/main/drivers/README.md)
61
- is written to be followed.
62
-
63
- ## For an agent
64
-
65
- ```json
66
- {
67
- "mcpServers": {
68
- "inillucent": {
69
- "command": "npx",
70
- "args": ["-y", "inillucent-mcp", "--db", "app.rdb"]
71
- }
72
- }
73
- }
74
- ```
75
-
76
- 27 tools, generated from the same command table the CLI reads, so the two can
77
- never drift. `--readonly` refuses every statement that changes something, and
78
- `--root DIR` refuses every path outside a directory.
79
-
80
- ## Licence
81
-
82
- MIT. Source: <https://github.com/Black-Rainbow-Labs/Inillucent>
83
-
84
- ## The API
85
-
86
- Every method this binding has. The worked example each one appears in is the link; nothing here is
87
- a summary of a method that does not exist, because
88
- `cargo test -p inillucent-compat --test documentation` reads this table and fails on a name the
89
- binding source does not declare.
90
-
91
- | what | one line |
92
- |---|---|
93
- | `inillucent(command, options)` | run one command of the command line and return its parsed JSON. `options.db` names the file, `options.args` the rest. |
94
- | `query(sql, options)` | run one `SELECT` and return its rows. `options.params` binds `?1`, `?2`; `options.limit` caps the rows kept. |
95
- | `resolveBinary(program)` | the path to one of the four programs on this platform, from the platform package npm installed. |
96
- | `platformPackage()` | the name of the platform package this machine needs, which is what an install failure should name. |
97
- | `PROGRAMS` | the four programs and what each is for, as an object. |
98
-
99
- Every call goes through the command line rather than through the C ABI: the four programs are what
100
- the platform package ships, and `--output json` is the same object every other binding sees. That
101
- is why there is no `Connection` here and no transaction - a command is one process, and a
102
- transaction that spanned two of them would be a transaction nothing held open.
1
+ # inillucent
2
+
3
+ An embedded SQL database that speaks SQLite's dialect on its own storage, with
4
+ full-text and vector search built in — the job of PostgreSQL + pgvector + an
5
+ embedding server, in one process and one file.
6
+
7
+ ```sh
8
+ npm install -g inillucent
9
+ # or, without installing anything permanently:
10
+ npx inillucent help
11
+ ```
12
+
13
+ No native build step and no postinstall download: the binaries ship as
14
+ per-platform packages that npm installs only where they run, so `npm ci` works
15
+ offline and behind a proxy.
16
+
17
+ ## Four programs
18
+
19
+ | | |
20
+ |---|---|
21
+ | `inillucent` | the command line: `query`, `exec`, `describe`, `import`, `export`, `search`, and twenty more |
22
+ | `inillucent-shell` | an interactive shell shaped like `sqlite3`, with all 63 of its dot commands |
23
+ | `inillucent-mcp` | the same commands served to an AI agent over MCP |
24
+ | `inillucent-migrate` | builds an inillucent database from a SQLite file |
25
+
26
+ ## From a shell
27
+
28
+ ```sh
29
+ inillucent create app.rdb
30
+ inillucent --db app.rdb exec "CREATE TABLE notes (id INTEGER PRIMARY KEY, body TEXT)"
31
+ inillucent --db app.rdb exec "INSERT INTO notes (body) VALUES (?1)" --params '["hello"]'
32
+ inillucent --db app.rdb query "SELECT * FROM notes"
33
+ inillucent --db app.rdb describe notes
34
+ inillucent help
35
+ ```
36
+
37
+ Exit codes carry meaning: `0` success, `1` failed, `2` a command line nobody
38
+ could act on, and **`3` a construct the engine has not built yet** — so a script
39
+ can branch on "not yet" without matching on a message.
40
+
41
+ ## From Node
42
+
43
+ ```js
44
+ import { query, inillucent } from 'inillucent';
45
+
46
+ const rows = await query('SELECT id, body FROM notes WHERE id > ?1', {
47
+ db: 'app.rdb',
48
+ params: [3],
49
+ });
50
+ // [{ id: 4, body: 'hello' }]
51
+
52
+ const described = await inillucent('describe', { db: 'app.rdb', table: 'notes' });
53
+ console.log(described.ddl, described.indexes, described.row_count_in_table);
54
+ ```
55
+
56
+ Each call is a process, so this is the right tool for the dozen calls a build
57
+ script or a tool wrapper makes and the wrong one for a loop over a million rows.
58
+ For that, write a binding over the C ABI — the header ships in this package's
59
+ platform dependency under `include/`, and
60
+ [`drivers/README.md`](https://github.com/Black-Rainbow-Labs/Inillucent/blob/main/drivers/README.md)
61
+ is written to be followed.
62
+
63
+ ## For an agent
64
+
65
+ ```json
66
+ {
67
+ "mcpServers": {
68
+ "inillucent": {
69
+ "command": "npx",
70
+ "args": ["-y", "inillucent-mcp", "--db", "app.rdb"]
71
+ }
72
+ }
73
+ }
74
+ ```
75
+
76
+ 27 tools, generated from the same command table the CLI reads, so the two can
77
+ never drift. `--readonly` refuses every statement that changes something, and
78
+ `--root DIR` refuses every path outside a directory.
79
+
80
+ ## Licence
81
+
82
+ MIT. Source: <https://github.com/Black-Rainbow-Labs/Inillucent>
83
+
84
+ ## The API
85
+
86
+ Every method this binding has. The worked example each one appears in is the link; nothing here is
87
+ a summary of a method that does not exist, because
88
+ `cargo test -p inillucent-compat --test documentation` reads this table and fails on a name the
89
+ binding source does not declare.
90
+
91
+ | what | one line |
92
+ |---|---|
93
+ | `inillucent(command, options)` | run one command of the command line and return its parsed JSON. `options.db` names the file, `options.args` the rest. |
94
+ | `query(sql, options)` | run one `SELECT` and return its rows. `options.params` binds `?1`, `?2`; `options.limit` caps the rows kept. |
95
+ | `resolveBinary(program)` | the path to one of the four programs on this platform, from the platform package npm installed. |
96
+ | `platformPackage()` | the name of the platform package this machine needs, which is what an install failure should name. |
97
+ | `PROGRAMS` | the four programs and what each is for, as an object. |
98
+
99
+ Every call goes through the command line rather than through the C ABI: the four programs are what
100
+ the platform package ships, and `--output json` is the same object every other binding sees. That
101
+ is why there is no `Connection` here and no transaction - a command is one process, and a
102
+ transaction that spanned two of them would be a transaction nothing held open.
@@ -1,33 +1,33 @@
1
- #!/usr/bin/env node
2
- // The `inillucent-mcp` shim: resolve the platform binary and become it.
3
- //
4
- // `spawn` with `stdio: 'inherit'` rather than an exec, because Node has no
5
- // execve and this has to work on Windows. The child's exit code and its signal
6
- // are both passed back up: a wrapper that always exited 0 would break every
7
- // script that branches on the exit code, and inillucent's exit codes carry
8
- // meaning - 3 is "the engine has not built that".
9
- import { spawn } from 'node:child_process';
10
- import { resolveBinary } from '../resolve.mjs';
11
-
12
- let binary;
13
- try {
14
- binary = resolveBinary('inillucent-mcp');
15
- } catch (why) {
16
- process.stderr.write(String(why.message ?? why) + '\n');
17
- process.exit(1);
18
- }
19
-
20
- const child = spawn(binary, process.argv.slice(2), { stdio: 'inherit' });
21
- child.on('error', (why) => {
22
- process.stderr.write(`inillucent: could not run ${binary}: ${why.message}\n`);
23
- process.exit(1);
24
- });
25
- child.on('exit', (code, signal) => {
26
- if (signal) {
27
- // Re-raise it on ourselves so a shell sees the same thing it would have
28
- // seen from the real program, rather than a plain exit.
29
- process.kill(process.pid, signal);
30
- return;
31
- }
32
- process.exit(code ?? 0);
33
- });
1
+ #!/usr/bin/env node
2
+ // The `inillucent-mcp` shim: resolve the platform binary and become it.
3
+ //
4
+ // `spawn` with `stdio: 'inherit'` rather than an exec, because Node has no
5
+ // execve and this has to work on Windows. The child's exit code and its signal
6
+ // are both passed back up: a wrapper that always exited 0 would break every
7
+ // script that branches on the exit code, and inillucent's exit codes carry
8
+ // meaning - 3 is "the engine has not built that".
9
+ import { spawn } from 'node:child_process';
10
+ import { resolveBinary } from '../resolve.mjs';
11
+
12
+ let binary;
13
+ try {
14
+ binary = resolveBinary('inillucent-mcp');
15
+ } catch (why) {
16
+ process.stderr.write(String(why.message ?? why) + '\n');
17
+ process.exit(1);
18
+ }
19
+
20
+ const child = spawn(binary, process.argv.slice(2), { stdio: 'inherit' });
21
+ child.on('error', (why) => {
22
+ process.stderr.write(`inillucent: could not run ${binary}: ${why.message}\n`);
23
+ process.exit(1);
24
+ });
25
+ child.on('exit', (code, signal) => {
26
+ if (signal) {
27
+ // Re-raise it on ourselves so a shell sees the same thing it would have
28
+ // seen from the real program, rather than a plain exit.
29
+ process.kill(process.pid, signal);
30
+ return;
31
+ }
32
+ process.exit(code ?? 0);
33
+ });
@@ -1,33 +1,33 @@
1
- #!/usr/bin/env node
2
- // The `inillucent-migrate` shim: resolve the platform binary and become it.
3
- //
4
- // `spawn` with `stdio: 'inherit'` rather than an exec, because Node has no
5
- // execve and this has to work on Windows. The child's exit code and its signal
6
- // are both passed back up: a wrapper that always exited 0 would break every
7
- // script that branches on the exit code, and inillucent's exit codes carry
8
- // meaning - 3 is "the engine has not built that".
9
- import { spawn } from 'node:child_process';
10
- import { resolveBinary } from '../resolve.mjs';
11
-
12
- let binary;
13
- try {
14
- binary = resolveBinary('inillucent-migrate');
15
- } catch (why) {
16
- process.stderr.write(String(why.message ?? why) + '\n');
17
- process.exit(1);
18
- }
19
-
20
- const child = spawn(binary, process.argv.slice(2), { stdio: 'inherit' });
21
- child.on('error', (why) => {
22
- process.stderr.write(`inillucent: could not run ${binary}: ${why.message}\n`);
23
- process.exit(1);
24
- });
25
- child.on('exit', (code, signal) => {
26
- if (signal) {
27
- // Re-raise it on ourselves so a shell sees the same thing it would have
28
- // seen from the real program, rather than a plain exit.
29
- process.kill(process.pid, signal);
30
- return;
31
- }
32
- process.exit(code ?? 0);
33
- });
1
+ #!/usr/bin/env node
2
+ // The `inillucent-migrate` shim: resolve the platform binary and become it.
3
+ //
4
+ // `spawn` with `stdio: 'inherit'` rather than an exec, because Node has no
5
+ // execve and this has to work on Windows. The child's exit code and its signal
6
+ // are both passed back up: a wrapper that always exited 0 would break every
7
+ // script that branches on the exit code, and inillucent's exit codes carry
8
+ // meaning - 3 is "the engine has not built that".
9
+ import { spawn } from 'node:child_process';
10
+ import { resolveBinary } from '../resolve.mjs';
11
+
12
+ let binary;
13
+ try {
14
+ binary = resolveBinary('inillucent-migrate');
15
+ } catch (why) {
16
+ process.stderr.write(String(why.message ?? why) + '\n');
17
+ process.exit(1);
18
+ }
19
+
20
+ const child = spawn(binary, process.argv.slice(2), { stdio: 'inherit' });
21
+ child.on('error', (why) => {
22
+ process.stderr.write(`inillucent: could not run ${binary}: ${why.message}\n`);
23
+ process.exit(1);
24
+ });
25
+ child.on('exit', (code, signal) => {
26
+ if (signal) {
27
+ // Re-raise it on ourselves so a shell sees the same thing it would have
28
+ // seen from the real program, rather than a plain exit.
29
+ process.kill(process.pid, signal);
30
+ return;
31
+ }
32
+ process.exit(code ?? 0);
33
+ });
@@ -1,33 +1,33 @@
1
- #!/usr/bin/env node
2
- // The `inillucent-shell` shim: resolve the platform binary and become it.
3
- //
4
- // `spawn` with `stdio: 'inherit'` rather than an exec, because Node has no
5
- // execve and this has to work on Windows. The child's exit code and its signal
6
- // are both passed back up: a wrapper that always exited 0 would break every
7
- // script that branches on the exit code, and inillucent's exit codes carry
8
- // meaning - 3 is "the engine has not built that".
9
- import { spawn } from 'node:child_process';
10
- import { resolveBinary } from '../resolve.mjs';
11
-
12
- let binary;
13
- try {
14
- binary = resolveBinary('inillucent-shell');
15
- } catch (why) {
16
- process.stderr.write(String(why.message ?? why) + '\n');
17
- process.exit(1);
18
- }
19
-
20
- const child = spawn(binary, process.argv.slice(2), { stdio: 'inherit' });
21
- child.on('error', (why) => {
22
- process.stderr.write(`inillucent: could not run ${binary}: ${why.message}\n`);
23
- process.exit(1);
24
- });
25
- child.on('exit', (code, signal) => {
26
- if (signal) {
27
- // Re-raise it on ourselves so a shell sees the same thing it would have
28
- // seen from the real program, rather than a plain exit.
29
- process.kill(process.pid, signal);
30
- return;
31
- }
32
- process.exit(code ?? 0);
33
- });
1
+ #!/usr/bin/env node
2
+ // The `inillucent-shell` shim: resolve the platform binary and become it.
3
+ //
4
+ // `spawn` with `stdio: 'inherit'` rather than an exec, because Node has no
5
+ // execve and this has to work on Windows. The child's exit code and its signal
6
+ // are both passed back up: a wrapper that always exited 0 would break every
7
+ // script that branches on the exit code, and inillucent's exit codes carry
8
+ // meaning - 3 is "the engine has not built that".
9
+ import { spawn } from 'node:child_process';
10
+ import { resolveBinary } from '../resolve.mjs';
11
+
12
+ let binary;
13
+ try {
14
+ binary = resolveBinary('inillucent-shell');
15
+ } catch (why) {
16
+ process.stderr.write(String(why.message ?? why) + '\n');
17
+ process.exit(1);
18
+ }
19
+
20
+ const child = spawn(binary, process.argv.slice(2), { stdio: 'inherit' });
21
+ child.on('error', (why) => {
22
+ process.stderr.write(`inillucent: could not run ${binary}: ${why.message}\n`);
23
+ process.exit(1);
24
+ });
25
+ child.on('exit', (code, signal) => {
26
+ if (signal) {
27
+ // Re-raise it on ourselves so a shell sees the same thing it would have
28
+ // seen from the real program, rather than a plain exit.
29
+ process.kill(process.pid, signal);
30
+ return;
31
+ }
32
+ process.exit(code ?? 0);
33
+ });
@@ -1,33 +1,33 @@
1
- #!/usr/bin/env node
2
- // The `inillucent` shim: resolve the platform binary and become it.
3
- //
4
- // `spawn` with `stdio: 'inherit'` rather than an exec, because Node has no
5
- // execve and this has to work on Windows. The child's exit code and its signal
6
- // are both passed back up: a wrapper that always exited 0 would break every
7
- // script that branches on the exit code, and inillucent's exit codes carry
8
- // meaning - 3 is "the engine has not built that".
9
- import { spawn } from 'node:child_process';
10
- import { resolveBinary } from '../resolve.mjs';
11
-
12
- let binary;
13
- try {
14
- binary = resolveBinary('inillucent');
15
- } catch (why) {
16
- process.stderr.write(String(why.message ?? why) + '\n');
17
- process.exit(1);
18
- }
19
-
20
- const child = spawn(binary, process.argv.slice(2), { stdio: 'inherit' });
21
- child.on('error', (why) => {
22
- process.stderr.write(`inillucent: could not run ${binary}: ${why.message}\n`);
23
- process.exit(1);
24
- });
25
- child.on('exit', (code, signal) => {
26
- if (signal) {
27
- // Re-raise it on ourselves so a shell sees the same thing it would have
28
- // seen from the real program, rather than a plain exit.
29
- process.kill(process.pid, signal);
30
- return;
31
- }
32
- process.exit(code ?? 0);
33
- });
1
+ #!/usr/bin/env node
2
+ // The `inillucent` shim: resolve the platform binary and become it.
3
+ //
4
+ // `spawn` with `stdio: 'inherit'` rather than an exec, because Node has no
5
+ // execve and this has to work on Windows. The child's exit code and its signal
6
+ // are both passed back up: a wrapper that always exited 0 would break every
7
+ // script that branches on the exit code, and inillucent's exit codes carry
8
+ // meaning - 3 is "the engine has not built that".
9
+ import { spawn } from 'node:child_process';
10
+ import { resolveBinary } from '../resolve.mjs';
11
+
12
+ let binary;
13
+ try {
14
+ binary = resolveBinary('inillucent');
15
+ } catch (why) {
16
+ process.stderr.write(String(why.message ?? why) + '\n');
17
+ process.exit(1);
18
+ }
19
+
20
+ const child = spawn(binary, process.argv.slice(2), { stdio: 'inherit' });
21
+ child.on('error', (why) => {
22
+ process.stderr.write(`inillucent: could not run ${binary}: ${why.message}\n`);
23
+ process.exit(1);
24
+ });
25
+ child.on('exit', (code, signal) => {
26
+ if (signal) {
27
+ // Re-raise it on ourselves so a shell sees the same thing it would have
28
+ // seen from the real program, rather than a plain exit.
29
+ process.kill(process.pid, signal);
30
+ return;
31
+ }
32
+ process.exit(code ?? 0);
33
+ });
package/package.json CHANGED
@@ -1,52 +1,52 @@
1
- {
2
- "name": "inillucent",
3
- "version": "0.1.4",
4
- "description": "Embedded SQL database with full-text and vector search, an MCP server, and a sqlite3-shaped shell. No native build step: the binaries ship as platform packages.",
5
- "keywords": [
6
- "database",
7
- "sql",
8
- "sqlite",
9
- "vector",
10
- "embedding",
11
- "search",
12
- "mcp",
13
- "cli",
14
- "rag"
15
- ],
16
- "homepage": "https://github.com/Black-Rainbow-Labs/Inillucent#readme",
17
- "bugs": "https://github.com/Black-Rainbow-Labs/Inillucent/issues",
18
- "repository": {
19
- "type": "git",
20
- "url": "git+https://github.com/Black-Rainbow-Labs/Inillucent.git",
21
- "directory": "packages/npm/inillucent"
22
- },
23
- "license": "MIT",
24
- "author": "Black Rainbow Labs",
25
- "type": "module",
26
- "engines": {
27
- "node": ">=18"
28
- },
29
- "bin": {
30
- "inillucent": "bin/inillucent.mjs",
31
- "inillucent-shell": "bin/inillucent-shell.mjs",
32
- "inillucent-mcp": "bin/inillucent-mcp.mjs",
33
- "inillucent-migrate": "bin/inillucent-migrate.mjs"
34
- },
35
- "main": "index.mjs",
36
- "exports": {
37
- ".": "./index.mjs"
38
- },
39
- "files": [
40
- "bin",
41
- "index.mjs",
42
- "resolve.mjs",
43
- "README.md"
44
- ],
45
- "optionalDependencies": {
46
- "@blackrainbowlabs/cli-win32-x64": "0.1.4",
47
- "@blackrainbowlabs/cli-darwin-arm64": "0.1.4",
48
- "@blackrainbowlabs/cli-darwin-x64": "0.1.4",
49
- "@blackrainbowlabs/cli-linux-x64": "0.1.4",
50
- "@blackrainbowlabs/cli-linux-arm64": "0.1.4"
51
- }
52
- }
1
+ {
2
+ "name": "inillucent",
3
+ "version": "0.1.5",
4
+ "description": "Embedded SQL database with full-text and vector search, an MCP server, and a sqlite3-shaped shell. No native build step: the binaries ship as platform packages.",
5
+ "keywords": [
6
+ "database",
7
+ "sql",
8
+ "sqlite",
9
+ "vector",
10
+ "embedding",
11
+ "search",
12
+ "mcp",
13
+ "cli",
14
+ "rag"
15
+ ],
16
+ "homepage": "https://github.com/Black-Rainbow-Labs/Inillucent#readme",
17
+ "bugs": "https://github.com/Black-Rainbow-Labs/Inillucent/issues",
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "git+https://github.com/Black-Rainbow-Labs/Inillucent.git",
21
+ "directory": "packages/npm/inillucent"
22
+ },
23
+ "license": "MIT",
24
+ "author": "Black Rainbow Labs",
25
+ "type": "module",
26
+ "engines": {
27
+ "node": ">=18"
28
+ },
29
+ "bin": {
30
+ "inillucent": "bin/inillucent.mjs",
31
+ "inillucent-shell": "bin/inillucent-shell.mjs",
32
+ "inillucent-mcp": "bin/inillucent-mcp.mjs",
33
+ "inillucent-migrate": "bin/inillucent-migrate.mjs"
34
+ },
35
+ "main": "index.mjs",
36
+ "exports": {
37
+ ".": "./index.mjs"
38
+ },
39
+ "files": [
40
+ "bin",
41
+ "index.mjs",
42
+ "resolve.mjs",
43
+ "README.md"
44
+ ],
45
+ "optionalDependencies": {
46
+ "@blackrainbowlabs/cli-win32-x64": "0.1.5",
47
+ "@blackrainbowlabs/cli-darwin-arm64": "0.1.5",
48
+ "@blackrainbowlabs/cli-darwin-x64": "0.1.5",
49
+ "@blackrainbowlabs/cli-linux-x64": "0.1.5",
50
+ "@blackrainbowlabs/cli-linux-arm64": "0.1.5"
51
+ }
52
+ }
package/resolve.mjs CHANGED
@@ -1,114 +1,122 @@
1
- // Finds the binary for the machine this is running on.
2
- //
3
- // The arrangement is esbuild's, and it is the right one: the binaries live in
4
- // per-platform packages listed as `optionalDependencies`, npm installs only the
5
- // one that matches, and this package's `bin` entries are tiny shims that
6
- // resolve it and hand over. There is no postinstall script and nothing is
7
- // downloaded at install time, which means `npm ci` works offline, in a locked
8
- // CI, and behind a registry proxy - none of which is true of a package that
9
- // fetches a binary from GitHub when it is installed.
10
- //
11
- // The cost is that a platform without a published package cannot install, and
12
- // the failure has to say so in a sentence somebody can act on rather than as an
13
- // unresolved import. That is what `resolveBinary` is for.
14
-
15
- import { createRequire } from 'node:module';
16
- import { accessSync, constants, existsSync } from 'node:fs';
17
- import { dirname, join } from 'node:path';
18
-
19
- const require = createRequire(import.meta.url);
20
-
21
- /** The platform packages, by the `process.platform`-`process.arch` pair each serves. */
22
- const PACKAGES = {
23
- 'win32-x64': '@inillucent/cli-win32-x64',
24
- 'darwin-arm64': '@inillucent/cli-darwin-arm64',
25
- 'darwin-x64': '@inillucent/cli-darwin-x64',
26
- 'linux-x64': '@inillucent/cli-linux-x64',
27
- 'linux-arm64': '@inillucent/cli-linux-arm64',
28
- };
29
-
30
- /** The four programs the release ships, and what each one is for. */
31
- export const PROGRAMS = {
32
- inillucent: 'the command line: query, exec, describe, import, export, search',
33
- 'inillucent-shell': 'the interactive sqlite3-shaped shell',
34
- 'inillucent-mcp': 'the MCP server, for an agent',
35
- 'inillucent-migrate': 'builds an inillucent database from a SQLite file',
36
- };
37
-
38
- /**
39
- * Returns the platform package name for this machine, or null if there is none.
40
- */
41
- export function platformPackage() {
42
- return PACKAGES[`${process.platform}-${process.arch}`] ?? null;
43
- }
44
-
45
- /**
46
- * Returns the absolute path of one of the four programs on this machine.
47
- *
48
- * @param program - which program, as it is named in PROGRAMS
49
- */
50
- export function resolveBinary(program) {
51
- if (!(program in PROGRAMS)) {
52
- throw new Error(`inillucent has no program called ${program}`);
53
- }
54
- // **`INILLUCENT_BIN` wins, the way it already does for the Go and PHP
55
- // wrappers (task-1969, 4.5).** It names the `inillucent` binary; the others
56
- // are looked for beside it, which is where a build and an install both put
57
- // them. Without this the wrappers stage of `tools/validate` could point the
58
- // other two languages at a freshly built binary and had no way to point this
59
- // one, so the only npm test that could run was the one that reads the
60
- // platform table as text.
61
- //
62
- // It throws rather than falling through when the named binary is not there:
63
- // a caller who says where the binary is and is wrong wants to know, not to
64
- // have the resolver quietly go looking somewhere else.
65
- const named = process.env.INILLUCENT_BIN;
66
- if (named) {
67
- const suffix = process.platform === 'win32' ? '.exe' : '';
68
- const beside = program === 'inillucent'
69
- ? named
70
- : join(dirname(named), `${program}${suffix}`);
71
- if (!existsSync(beside)) {
72
- throw new Error(
73
- `INILLUCENT_BIN is set and ${beside} is not there.
74
- ` +
75
- ` Unset INILLUCENT_BIN to look for an installed copy instead.`,
76
- );
77
- }
78
- return beside;
79
- }
80
- const name = platformPackage();
81
- if (!name) {
82
- throw new Error(
83
- `inillucent has no prebuilt binary for ${process.platform}-${process.arch}.\n` +
84
- ` Build it from source instead: cargo install inillucent-cli\n` +
85
- ` Or open an issue: https://github.com/Black-Rainbow-Labs/Inillucent/issues`,
86
- );
87
- }
88
- const suffix = process.platform === 'win32' ? '.exe' : '';
89
- let path;
90
- try {
91
- // The platform package's own entry point tells us where its bin directory
92
- // is, rather than this package guessing at a node_modules layout - which
93
- // pnpm, yarn's pnp and a hoisted npm tree all arrange differently.
94
- path = require.resolve(`${name}/bin/${program}${suffix}`);
95
- } catch {
96
- throw new Error(
97
- `inillucent's binary for ${process.platform}-${process.arch} is not installed.\n` +
98
- ` The package ${name} should have been installed as an optional dependency.\n` +
99
- ` If your installer was run with --no-optional, install it directly:\n` +
100
- ` npm install ${name}\n`,
101
- );
102
- }
103
- try {
104
- accessSync(path, constants.X_OK);
105
- } catch {
106
- // An npm tarball does not always preserve the executable bit, and the
107
- // failure it produces otherwise is EACCES from execve with no explanation.
108
- throw new Error(
109
- `${path} is not executable.\n Fix it with: chmod +x ${path}\n` +
110
- ` Then please report it: https://github.com/Black-Rainbow-Labs/Inillucent/issues`,
111
- );
112
- }
113
- return path;
114
- }
1
+ // Finds the binary for the machine this is running on.
2
+ //
3
+ // The arrangement is esbuild's, and it is the right one: the binaries live in
4
+ // per-platform packages listed as `optionalDependencies`, npm installs only the
5
+ // one that matches, and this package's `bin` entries are tiny shims that
6
+ // resolve it and hand over. There is no postinstall script and nothing is
7
+ // downloaded at install time, which means `npm ci` works offline, in a locked
8
+ // CI, and behind a registry proxy - none of which is true of a package that
9
+ // fetches a binary from GitHub when it is installed.
10
+ //
11
+ // The cost is that a platform without a published package cannot install, and
12
+ // the failure has to say so in a sentence somebody can act on rather than as an
13
+ // unresolved import. That is what `resolveBinary` is for.
14
+
15
+ import { createRequire } from 'node:module';
16
+ import { accessSync, constants, existsSync } from 'node:fs';
17
+ import { dirname, join } from 'node:path';
18
+
19
+ const require = createRequire(import.meta.url);
20
+
21
+ // **The scope here is the scope they are published under, and the two came apart (task-1995).**
22
+ // The packages were renamed from `@inillucent/*` to `@blackrainbowlabs/*` in build.mjs and in this
23
+ // package's optionalDependencies, and this table was missed. npm then installed
24
+ // `@blackrainbowlabs/cli-win32-x64` correctly and the shim looked for `@inillucent/cli-win32-x64`,
25
+ // so every install on every platform ended at "inillucent's binary for win32-x64 is not installed"
26
+ // - naming a package that does not exist. It reached the registry, where a version cannot be
27
+ // replaced. resolve.test.mjs compares this table against package.json and against build.mjs, and it
28
+ // no longer hard-codes a scope, so a rename that touches one of the three fails here instead.
29
+ /** The platform packages, by the `process.platform`-`process.arch` pair each serves. */
30
+ const PACKAGES = {
31
+ 'win32-x64': '@blackrainbowlabs/cli-win32-x64',
32
+ 'darwin-arm64': '@blackrainbowlabs/cli-darwin-arm64',
33
+ 'darwin-x64': '@blackrainbowlabs/cli-darwin-x64',
34
+ 'linux-x64': '@blackrainbowlabs/cli-linux-x64',
35
+ 'linux-arm64': '@blackrainbowlabs/cli-linux-arm64',
36
+ };
37
+
38
+ /** The four programs the release ships, and what each one is for. */
39
+ export const PROGRAMS = {
40
+ inillucent: 'the command line: query, exec, describe, import, export, search',
41
+ 'inillucent-shell': 'the interactive sqlite3-shaped shell',
42
+ 'inillucent-mcp': 'the MCP server, for an agent',
43
+ 'inillucent-migrate': 'builds an inillucent database from a SQLite file',
44
+ };
45
+
46
+ /**
47
+ * Returns the platform package name for this machine, or null if there is none.
48
+ */
49
+ export function platformPackage() {
50
+ return PACKAGES[`${process.platform}-${process.arch}`] ?? null;
51
+ }
52
+
53
+ /**
54
+ * Returns the absolute path of one of the four programs on this machine.
55
+ *
56
+ * @param program - which program, as it is named in PROGRAMS
57
+ */
58
+ export function resolveBinary(program) {
59
+ if (!(program in PROGRAMS)) {
60
+ throw new Error(`inillucent has no program called ${program}`);
61
+ }
62
+ // **`INILLUCENT_BIN` wins, the way it already does for the Go and PHP
63
+ // wrappers (task-1969, 4.5).** It names the `inillucent` binary; the others
64
+ // are looked for beside it, which is where a build and an install both put
65
+ // them. Without this the wrappers stage of `tools/validate` could point the
66
+ // other two languages at a freshly built binary and had no way to point this
67
+ // one, so the only npm test that could run was the one that reads the
68
+ // platform table as text.
69
+ //
70
+ // It throws rather than falling through when the named binary is not there:
71
+ // a caller who says where the binary is and is wrong wants to know, not to
72
+ // have the resolver quietly go looking somewhere else.
73
+ const named = process.env.INILLUCENT_BIN;
74
+ if (named) {
75
+ const suffix = process.platform === 'win32' ? '.exe' : '';
76
+ const beside = program === 'inillucent'
77
+ ? named
78
+ : join(dirname(named), `${program}${suffix}`);
79
+ if (!existsSync(beside)) {
80
+ throw new Error(
81
+ `INILLUCENT_BIN is set and ${beside} is not there.
82
+ ` +
83
+ ` Unset INILLUCENT_BIN to look for an installed copy instead.`,
84
+ );
85
+ }
86
+ return beside;
87
+ }
88
+ const name = platformPackage();
89
+ if (!name) {
90
+ throw new Error(
91
+ `inillucent has no prebuilt binary for ${process.platform}-${process.arch}.\n` +
92
+ ` Build it from source instead: cargo install inillucent-cli\n` +
93
+ ` Or open an issue: https://github.com/Black-Rainbow-Labs/Inillucent/issues`,
94
+ );
95
+ }
96
+ const suffix = process.platform === 'win32' ? '.exe' : '';
97
+ let path;
98
+ try {
99
+ // The platform package's own entry point tells us where its bin directory
100
+ // is, rather than this package guessing at a node_modules layout - which
101
+ // pnpm, yarn's pnp and a hoisted npm tree all arrange differently.
102
+ path = require.resolve(`${name}/bin/${program}${suffix}`);
103
+ } catch {
104
+ throw new Error(
105
+ `inillucent's binary for ${process.platform}-${process.arch} is not installed.\n` +
106
+ ` The package ${name} should have been installed as an optional dependency.\n` +
107
+ ` If your installer was run with --no-optional, install it directly:\n` +
108
+ ` npm install ${name}\n`,
109
+ );
110
+ }
111
+ try {
112
+ accessSync(path, constants.X_OK);
113
+ } catch {
114
+ // An npm tarball does not always preserve the executable bit, and the
115
+ // failure it produces otherwise is EACCES from execve with no explanation.
116
+ throw new Error(
117
+ `${path} is not executable.\n Fix it with: chmod +x ${path}\n` +
118
+ ` Then please report it: https://github.com/Black-Rainbow-Labs/Inillucent/issues`,
119
+ );
120
+ }
121
+ return path;
122
+ }