nedb-engine 6.1.0 → 8.0.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/README.md +192 -40
- package/native.d.ts +24 -0
- package/nedb.darwin-arm64.node +0 -0
- package/nedb.darwin-x64.node +0 -0
- package/nedb.linux-arm64-gnu.node +0 -0
- package/nedb.linux-arm64-musl.node +0 -0
- package/nedb.linux-x64-gnu.node +0 -0
- package/nedb.linux-x64-musl.node +0 -0
- package/nedb.win32-x64-msvc.node +0 -0
- package/nedbd-v2-darwin-arm64 +0 -0
- package/nedbd-v2-darwin-x64 +0 -0
- package/nedbd-v2-linux-arm64 +0 -0
- package/nedbd-v2-linux-arm64-musl +0 -0
- package/nedbd-v2-linux-x64 +0 -0
- package/nedbd-v2-linux-x64-musl +0 -0
- package/nedbd-v2-win-x64.exe +0 -0
- package/nesql.js +90 -0
- package/package.json +6 -3
package/README.md
CHANGED
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
**Content-addressed Merkle DAG · Hash-chained · Time-traveling · Bi-temporal · Causally-provable embedded database.**
|
|
6
6
|
|
|
7
7
|
Replay-protected · idempotent · relational · filterable · sortable · searchable · concurrent.
|
|
8
|
-
One Rust core → ships to **PyPI** and **
|
|
8
|
+
One Rust core → ships to **PyPI**, **npm** and **crates.io** from a single source,
|
|
9
|
+
at the same version on the same tag.
|
|
9
10
|
|
|
10
11
|
[](https://pypi.org/project/nedb-engine/)
|
|
11
12
|
[](https://crates.io/crates/nedb-engine)
|
|
@@ -31,28 +32,139 @@ One Rust core → ships to **PyPI** and **npm** from a single source.
|
|
|
31
32
|
|
|
32
33
|
---
|
|
33
34
|
|
|
34
|
-
##
|
|
35
|
+
## [neSQL](https://github.com/Eth-Interchained/neSQL) — the language this engine speaks
|
|
35
36
|
|
|
36
|
-
Nobody should have to learn a query language to use a database.
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
Nobody should have to learn a query language to use a database. That sentence cost
|
|
38
|
+
us one.
|
|
39
|
+
|
|
40
|
+
NEDB's PostgreSQL endpoint answers `psql`, SQLAlchemy Core **and** ORM, asyncpg and
|
|
41
|
+
node-postgres against a live store. It used to get there by *translating* SQL into
|
|
39
42
|
NQL, and a translation can only reach as far as the target language's shape.
|
|
40
43
|
|
|
41
|
-
**
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
**neSQL is the name for what replaced that**, and it is exactly as much of an
|
|
45
|
+
addition as it sounds like:
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
neSQL = PostgreSQL SQL · inherited whole, not reimplemented
|
|
49
|
+
+ NEDB SQL · what a permanent, hash-chained store can answer
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**We inherit, then we gain.** The left-hand side is PostgreSQL's real grammar —
|
|
53
|
+
`gram.y`, 19,513 lines and 492 keywords, vendored from 17.4 at
|
|
54
|
+
[`vendor/postgresql/`](vendor/postgresql/) with its licence intact. Not a subset,
|
|
55
|
+
not a lookalike: the definition every other tool in the world was built against.
|
|
56
|
+
If it is valid PostgreSQL and the evaluator can parse it, it runs.
|
|
57
|
+
|
|
58
|
+
The right-hand side is what NEDB adds because it can — `AS OF SYSTEM TIME`,
|
|
59
|
+
`VALID AS OF`, `SEARCH`, `TRACE`, `TRAVERSE`. These are clauses PostgreSQL has no
|
|
60
|
+
spelling for, because a store that overwrites has nothing to point them at. They
|
|
61
|
+
are additions **to** the vendored grammar, never deviations **from** it.
|
|
62
|
+
|
|
63
|
+
So neSQL is not a dialect of SQL that you have to learn around. It is PostgreSQL
|
|
64
|
+
plus the questions a database with permanent memory can be asked. Anything you
|
|
65
|
+
already write keeps working; the new clauses are there when you need them.
|
|
66
|
+
|
|
67
|
+
Which half a statement is read as is decided **structurally**, never guessed:
|
|
68
|
+
NQL's own form begins `FROM`, PostgreSQL has no statement form that begins with
|
|
69
|
+
`FROM`, so the leading keyword partitions the two vocabularies rather than hinting
|
|
70
|
+
at them. A first word in neither is refused *naming both*.
|
|
71
|
+
|
|
72
|
+
This section is not a roadmap. Everything below ships in this release — the
|
|
73
|
+
evaluator with no flag to set, the `nesql` CLI likewise.
|
|
46
74
|
|
|
47
75
|
[](https://pypi.org/project/nesql/)
|
|
48
76
|
[](https://crates.io/crates/nesql)
|
|
49
77
|
[](https://www.npmjs.com/package/nesql-engine)
|
|
50
78
|
|
|
51
|
-
|
|
79
|
+
Those three badges read **0.0.1** next to an engine at 6.1.0, and that is
|
|
80
|
+
deliberate rather than neglected. They are **reserved names**: each package loads,
|
|
81
|
+
reports the vendored PostgreSQL release, and answers `is_release() == false`,
|
|
82
|
+
because a package that imports cleanly and then lies is worse than one that is not
|
|
83
|
+
published. The engine you actually install is `nedb-engine`. The
|
|
84
|
+
[neSQL repository](https://github.com/Eth-Interchained/neSQL) holds the language —
|
|
85
|
+
both halves of the grammar and the CLI's source, side by side.
|
|
86
|
+
|
|
87
|
+
### `nesql` — the CLI, and it speaks neSQL
|
|
88
|
+
|
|
89
|
+
Ships in this release, no flag. `nesql` opens a store directly — no daemon, no
|
|
90
|
+
port — and answers both halves of the language through **one** `query` command:
|
|
91
|
+
|
|
92
|
+
```console
|
|
93
|
+
$ nesql --db ./store query "SELECT who, total FROM orders ORDER BY total DESC"
|
|
94
|
+
{"who":"globex","total":250,...}
|
|
95
|
+
{"who":"acme","total":100,...}
|
|
96
|
+
(2 rows)
|
|
97
|
+
|
|
98
|
+
$ nesql --db ./store query "FROM orders WHERE total > 150"
|
|
99
|
+
{"who":"globex","total":250,...}
|
|
100
|
+
(1 rows, 1 scanned)
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Same command, two dialects, routed on the leading keyword. `--nql` / `--sql`
|
|
104
|
+
force one when you want *that dialect's* error rather than a routing error —
|
|
105
|
+
`query --nql "SELECT 1"` tells you `expected keyword FROM`, which is the useful
|
|
106
|
+
answer when you are debugging why something was rejected.
|
|
107
|
+
|
|
108
|
+
It is built for scripts as much as for people. `--json` emits exactly one JSON
|
|
109
|
+
object on stdout — engine diagnostics go to stderr, so a pipe stays clean — and
|
|
110
|
+
the exit code carries the verdict:
|
|
111
|
+
|
|
112
|
+
| | |
|
|
113
|
+
| --- | --- |
|
|
114
|
+
| `0` | success — the thing was done, or the check ran and passed |
|
|
115
|
+
| `1` | failure — the operation ran and did not succeed |
|
|
116
|
+
| `2` | usage — the command line was not understood, or was ambiguous |
|
|
117
|
+
| `3` | **could not determine** — the check could not run (history pruned) |
|
|
118
|
+
| `4` | not found |
|
|
119
|
+
| `5` | unsupported — a version or format this build does not know |
|
|
120
|
+
|
|
121
|
+
**`3` is the one that matters.** A pruned history is not a corrupt one, and an
|
|
122
|
+
operator who cannot tell those apart will either ignore a real alarm or panic at
|
|
123
|
+
a routine one. `root verify` reports the stored record and the recomputation as
|
|
124
|
+
two independent facts and never collapses them:
|
|
125
|
+
|
|
126
|
+
```console
|
|
127
|
+
$ nesql --db ./store root verify
|
|
128
|
+
at_seq 2
|
|
129
|
+
root_record valid
|
|
130
|
+
recomputation matches
|
|
131
|
+
exit 0
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
`root_record valid` / `recomputation unavailable` with exit 3 is a pruned store
|
|
135
|
+
answering honestly. Only `recomputation DIFFERS` means something is wrong.
|
|
136
|
+
|
|
137
|
+
The rest of the surface: `status`, `log`, `inspect` (a collection, a document, a
|
|
138
|
+
sequence, or a persisted root — named by kind, because a bare `42` could be
|
|
139
|
+
`seq:42` or `root:42` and the CLI refuses to pick), `diff`, immutable `tag`,
|
|
140
|
+
`branch`, `merge` with first-class conflicts, and `grammar` / `constitution`,
|
|
141
|
+
which publish the command surface and the engine's guarantees with digests you
|
|
142
|
+
can compare across builds.
|
|
143
|
+
|
|
144
|
+
```console
|
|
145
|
+
$ nesql constitution
|
|
146
|
+
engine 6.1.0
|
|
147
|
+
nesql 6.1.0
|
|
148
|
+
verdict compatible with gaps
|
|
149
|
+
nql grammar ef0f1696... (agrees — same grammar this build compiled against)
|
|
150
|
+
```
|
|
52
151
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
152
|
+
### One evaluator, no flag
|
|
153
|
+
|
|
154
|
+
The SQL evaluator answers **every `SELECT` it can parse** — user collections
|
|
155
|
+
included, with nothing to turn on. `NEDBD_SQL_ENGINE` is gone; a deployment
|
|
156
|
+
still exporting it is told the variable is inert rather than left believing it
|
|
157
|
+
holds a switch.
|
|
158
|
+
|
|
159
|
+
It used to be opt-in, and the honest reason it is not any more is that the two
|
|
160
|
+
sides were never two correct answers. `SELECT who FROM orders` returned
|
|
161
|
+
`who, total, _id, _hash, _seq, _coll` on the translator, because NQL has no
|
|
162
|
+
projection to translate a column list into. A flag whose positions give
|
|
163
|
+
different answers to the same correct SQL is not a parity switch.
|
|
164
|
+
|
|
165
|
+
What did not change is the fallthrough, which was never the flag: a statement
|
|
166
|
+
the evaluator cannot **parse** still goes to the translator, and that is how
|
|
167
|
+
every write is served.
|
|
56
168
|
|
|
57
169
|
```sql
|
|
58
170
|
SELECT o._id, d.name FROM orders o JOIN drivers d ON o.driver = d._id;
|
|
@@ -91,11 +203,10 @@ the other. `AS OF SYSTEM TIME`, `VALID AS OF` and `SEARCH` are **unreserved
|
|
|
91
203
|
keywords**: a collection aliased `search`, or a column named `valid`, keeps
|
|
92
204
|
working exactly as before.
|
|
93
205
|
|
|
94
|
-
**
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
divergences: `SELECT *` returned its columns in a different order on each
|
|
206
|
+
**What earned the flag's removal**, stated plainly because the reason is the
|
|
207
|
+
interesting part. A parity harness runs the same corpus through both paths and
|
|
208
|
+
asserts identical answers — 44 checks, in CI — and it is that, rather than a
|
|
209
|
+
benchmark, that earned it. It found two real divergences: `SELECT *` returned its columns in a different order on each
|
|
99
210
|
engine, and the SQL evaluator built its column list from the **first row alone**,
|
|
100
211
|
so a field only later documents carried silently did not appear at all.
|
|
101
212
|
|
|
@@ -108,7 +219,7 @@ the bar for changing that written down.
|
|
|
108
219
|
|
|
109
220
|
---
|
|
110
221
|
|
|
111
|
-
##
|
|
222
|
+
## The query language grew up · *landed in 3.3.0*
|
|
112
223
|
|
|
113
224
|
`WHERE` was six operators wide (`= != > < >= <=`) joined by an implicit `AND`.
|
|
114
225
|
It now takes a full boolean expression, in **both** engines, and the clauses
|
|
@@ -254,13 +365,23 @@ Provenance is selectable like any other column:
|
|
|
254
365
|
SELECT _id, _hash, _seq FROM audit ORDER BY _seq;
|
|
255
366
|
```
|
|
256
367
|
|
|
257
|
-
**
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
rewrite can only
|
|
368
|
+
**NEDB speaks SQL. That sentence used to carry a caveat, and no longer does.**
|
|
369
|
+
|
|
370
|
+
For most of this project's life it was true that the endpoint served a
|
|
371
|
+
documented *subset* of `SELECT` **translated** into NQL — and every refusal in
|
|
372
|
+
the table below traced to that one cause: a rewrite can only reach as far as the
|
|
373
|
+
target language's shape, and NQL's shape is single-collection with no projection.
|
|
374
|
+
|
|
375
|
+
That translator no longer answers `SELECT`. The evaluator does, for every
|
|
376
|
+
statement it can parse, with nothing to enable. It is kept for writes and for
|
|
377
|
+
anything outside the `SELECT` grammar, which is why a statement it cannot parse
|
|
378
|
+
still gets an answer rather than an error.
|
|
262
379
|
|
|
263
|
-
|
|
380
|
+
The table is preserved below as history, because the distinction between "the
|
|
381
|
+
engine could never do this" and "the translator could not reach it" is the whole
|
|
382
|
+
story of how neSQL happened — and only one of those was ever true.
|
|
383
|
+
|
|
384
|
+
| Expressible in NQL | Not expressible there, and why | the evaluator |
|
|
264
385
|
| --- | --- | --- |
|
|
265
386
|
| `*`, a column list, `COUNT(*)`, `SUM`/`AVG`/`MIN`/`MAX(col)` | `JOIN` — NQL is single-collection | ✅ **works** (nested-loop + hash) |
|
|
266
387
|
| `WHERE` — the whole NQL predicate surface | subqueries, `UNION`, window functions | ✅ **subqueries, `EXISTS`, `UNION`/`INTERSECT`/`EXCEPT` work**; window functions arrive with the grammar |
|
|
@@ -278,7 +399,7 @@ NEDB is append-only *so that history cannot be discarded* — that is the produc
|
|
|
278
399
|
not a gap — and DDL is refused because collections are created by the first write
|
|
279
400
|
to them. Those answers do not change.
|
|
280
401
|
|
|
281
|
-
### Every other row on that table was a translation artefact — and
|
|
402
|
+
### Every other row on that table was a translation artefact — and they are gone
|
|
282
403
|
|
|
283
404
|
> ### 🆕 [**neSQL**](https://github.com/Eth-Interchained/neSQL) — PostgreSQL's grammar, NEDB's memory
|
|
284
405
|
>
|
|
@@ -286,7 +407,7 @@ to them. Those answers do not change.
|
|
|
286
407
|
> nested-loop and hash joins, subqueries, `EXISTS`, quantified comparisons, set
|
|
287
408
|
> operations, `array_agg(x ORDER BY y)` and derived tables for some time — they
|
|
288
409
|
> were simply unreachable *through a translator*, because the translator's
|
|
289
|
-
> target was NQL.
|
|
410
|
+
> target was NQL. They are reachable now, with nothing to set.
|
|
290
411
|
>
|
|
291
412
|
> neSQL vendors PostgreSQL's **real grammar** — `gram.y`, 19,513 lines and 492
|
|
292
413
|
> keywords, from 17.4, licence intact — and extends it with the clauses NEDB
|
|
@@ -427,7 +548,7 @@ SQL `UPDATE`, the prior value is still readable at its original sequence.
|
|
|
427
548
|
|
|
428
549
|
---
|
|
429
550
|
|
|
430
|
-
##
|
|
551
|
+
## Wrap the databases you already run · *landed in 3.2.0*
|
|
431
552
|
|
|
432
553
|
NEDB adds **tamper-evident causal provenance to a database you already have**, in one line, without
|
|
433
554
|
rip-and-replace. Five adapters, one surface:
|
|
@@ -522,7 +643,7 @@ permissive, and the two Python runtime dependencies are BSD and Apache.
|
|
|
522
643
|
**Versions 3.0.0 – 3.3.1 stay MIT, irrevocably.** If you already have NEDB at 3.3.1 or earlier, your
|
|
523
644
|
rights in that copy are untouched. This applies to 4.0.0 and later only.
|
|
524
645
|
|
|
525
|
-
### Also in 3.2.0
|
|
646
|
+
### Also landed in 3.2.0
|
|
526
647
|
|
|
527
648
|
- **A durability defect that pinned every embedded database.** The background flush ticker held a
|
|
528
649
|
strong `Arc<Db>` in an unconditional loop, so the handle was never dropped: the exclusive data-dir
|
|
@@ -542,7 +663,7 @@ rights in that copy are untouched. This applies to 4.0.0 and later only.
|
|
|
542
663
|
|
|
543
664
|
---
|
|
544
665
|
|
|
545
|
-
##
|
|
666
|
+
## Durability & recovery · *landed in 2.8.6*
|
|
546
667
|
|
|
547
668
|
Three defects found by killing a real engine at every persistence boundary and by filling a real
|
|
548
669
|
filesystem to zero free blocks. **If you are on 2.8.5 or earlier, upgrade.**
|
|
@@ -587,11 +708,11 @@ value. Ten writes drain as nine records. Changing the convention would break exi
|
|
|
587
708
|
|
|
588
709
|
---
|
|
589
710
|
|
|
590
|
-
##
|
|
711
|
+
## Distribution — three aligned distributions, one tag
|
|
591
712
|
|
|
592
|
-
|
|
713
|
+
NEDB ships as **three version-aligned distributions** on one tag — `nedb-engine` (flagship), `crypto-database` (verifiable v2/v3 DAG), and `aof-db` (fast append-only) — across npm / PyPI / crates.io with native addons for **macOS (arm64 + x86_64), Linux (x86_64 + aarch64, glibc + musl) and Windows x86_64** (see [**Releasing**](#releasing) below). All native wheels (Linux + Windows on GitHub Actions; macOS on Codemagic M2 Mac Minis) **plus** the universal pure-Python wheel ship from a single `v*` tag, with the `nedbd-v2` binary bundled inside `pip install nedb-engine`.
|
|
593
714
|
|
|
594
|
-
###
|
|
715
|
+
### Cast — the database understands English · *landed in 2.8.0*
|
|
595
716
|
|
|
596
717
|
`POST /v1/databases/<name>/cast` turns a short English prompt into NQL, using a **3.33M-parameter model that runs locally on CPU**. No API key, no network call, no per-token bill.
|
|
597
718
|
|
|
@@ -634,9 +755,9 @@ nedbd --dag --data ./data
|
|
|
634
755
|
NEDBD_DAG=1 NEDB_TMK=<32-byte-hex> nedbd --data ./data
|
|
635
756
|
|
|
636
757
|
curl http://127.0.0.1:7070/health
|
|
637
|
-
# {"ok":true,"version":"
|
|
758
|
+
# {"ok":true,"version":"7.2.0","service":"nedbd","engine":"dag","startup_ready":true,"encrypted":true}
|
|
638
759
|
|
|
639
|
-
# Tail the live event stream (
|
|
760
|
+
# Tail the live event stream (since 2.2.31)
|
|
640
761
|
curl http://127.0.0.1:7070/events
|
|
641
762
|
# event: scan data: {"objects":730000,"of":1310703,"rate":21043,"eta_s":28}
|
|
642
763
|
# event: ready data: {"seq":1310703,"head":"b2:9c14e07a…"}
|
|
@@ -660,7 +781,9 @@ curl http://127.0.0.1:7070/events
|
|
|
660
781
|
|
|
661
782
|
**v1 AOF engine is still shipped and unchanged** — `nedbd` (no flag) runs v1.
|
|
662
783
|
|
|
663
|
-
**Production status:** [vision.interchained.org](https://vision.interchained.org) is live
|
|
784
|
+
**Production status:** [vision.interchained.org](https://vision.interchained.org) is live — verified reachable 15 Sep 2026.
|
|
785
|
+
|
|
786
|
+
The deployment figures below are a **dated snapshot**, not a live readout: **1,310,703 sequences** indexed, AES-256-GCM encrypted at rest, block height **620,989**, measured on engine **v2.2.31**. The engine version a deployment runs is not exposed on its public surface, so treat the version here as the one those numbers were taken on rather than as what is running today.
|
|
664
787
|
|
|
665
788
|
---
|
|
666
789
|
|
|
@@ -893,7 +1016,7 @@ nedbd --dag --data ./data # v2 DAG engine (or NEDBD_DAG=1)
|
|
|
893
1016
|
NEDBD_RESP2_PORT=6380 nedbd # also speak RESP2 (redis-cli compatible)
|
|
894
1017
|
nedbd --log-level 2 # 0=errors 1=requests 2=deploy 3=verbose
|
|
895
1018
|
|
|
896
|
-
# Live event stream (
|
|
1019
|
+
# Live event stream (since 2.2.31) — SSE: scan progress, ready, per-write head
|
|
897
1020
|
curl http://127.0.0.1:7070/events
|
|
898
1021
|
```
|
|
899
1022
|
|
|
@@ -901,7 +1024,7 @@ curl http://127.0.0.1:7070/events
|
|
|
901
1024
|
|
|
902
1025
|
Alongside the daemon, `cargo install nedb-engine` ships **`nedb-cli`** — operate on a store directory offline (`head`/`status`/`verify`/`get`/`scan`/`flush`/`repair`/`export`) — and **`nedb-inspector`**, a deterministic checker that warns when a durable open lacks flush-on-exit wiring. Full reference: [**docs/CLI.md**](docs/CLI.md).
|
|
903
1026
|
|
|
904
|
-
### Startup modes
|
|
1027
|
+
### Startup modes
|
|
905
1028
|
|
|
906
1029
|
- **Warm start** — every restart after the first open reads the `MANIFEST` file and restores `seq` + Merkle `head` in **O(1)**. No scan, no replay, independent of dataset size. Boots in milliseconds.
|
|
907
1030
|
- **Cold start** — first open of an existing dataset spawns the integrity scan in a background thread *and accepts connections immediately*. Reads serve instantly from the content-addressed DAG; writes return `HTTP 503 startup in progress` until the `startup_ready` gate flips. Progress (objects, rate, ETA) streams over `GET /events`.
|
|
@@ -929,9 +1052,38 @@ curl -X POST :7070/v1/databases -d '{
|
|
|
929
1052
|
"links": [["users:u1","buys","orders:o1"]]
|
|
930
1053
|
}}'
|
|
931
1054
|
|
|
932
|
-
# Query
|
|
1055
|
+
# Query — the endpoint speaks neSQL: SQL *or* NQL, routed on the first keyword
|
|
1056
|
+
curl -X POST :7070/v1/databases/shop/query \
|
|
1057
|
+
-d '{"nql":"SELECT name FROM users WHERE status = '"'"'active'"'"' ORDER BY name"}'
|
|
1058
|
+
# → {"rows":[{"name":"Alice"}],"count":1,"dialect":"sql", ...}
|
|
1059
|
+
|
|
933
1060
|
curl -X POST :7070/v1/databases/shop/query \
|
|
934
1061
|
-d '{"nql":"FROM users WHERE status = \"active\" ORDER BY name ASC"}'
|
|
1062
|
+
# → {"rows":[...],"count":1,"dialect":"nql", ...}
|
|
1063
|
+
|
|
1064
|
+
|
|
1065
|
+
**The field is still called `nql`, and its contents no longer have to be.** This
|
|
1066
|
+
endpoint accepts **neSQL** — NQL *or* PostgreSQL SQL — and answers with the
|
|
1067
|
+
`dialect` it chose. The name is unchanged because every existing HTTP client
|
|
1068
|
+
sends it; renaming would break them to gain nothing. Old NQL clients are
|
|
1069
|
+
unaffected.
|
|
1070
|
+
|
|
1071
|
+
Routing is **structural, not guessed**. NQL statements begin `FROM`; PostgreSQL
|
|
1072
|
+
has no statement form that begins with `FROM`, so the leading keyword partitions
|
|
1073
|
+
the two vocabularies rather than hinting at them. A first word in neither is
|
|
1074
|
+
refused *naming both* — never handed to whichever parser seems likelier.
|
|
1075
|
+
|
|
1076
|
+
```bash
|
|
1077
|
+
curl -X POST :7070/v1/databases/shop/query -d '{"nql":"GRANT ALL ON users"}'
|
|
1078
|
+
# → 400 "GRANT" does not begin a statement in either half of neSQL
|
|
1079
|
+
# NQL statements begin with: FROM
|
|
1080
|
+
# SQL statements begin with: SELECT, INSERT, UPDATE, ...
|
|
1081
|
+
```
|
|
1082
|
+
|
|
1083
|
+
It is the **same router** `nesql query` uses — `nedb_engine::neql::route`, which
|
|
1084
|
+
the CLI re-exports rather than copies. Two implementations of that decision
|
|
1085
|
+
would let the daemon and the CLI disagree about what a statement *means*, which
|
|
1086
|
+
is worse than disagreeing about a result: nothing looks broken when it happens.
|
|
935
1087
|
|
|
936
1088
|
# Verify the hash chain
|
|
937
1089
|
curl :7070/v1/databases/shop/verify
|
package/native.d.ts
CHANGED
|
@@ -28,7 +28,31 @@ export declare class NedbCore {
|
|
|
28
28
|
unlink(frm: string, rel: string, to: string): void
|
|
29
29
|
get(coll: string, id: string): string | null
|
|
30
30
|
getAsOf(coll: string, id: string, asOf: bigint): string | null
|
|
31
|
+
/**
|
|
32
|
+
* Run **neSQL** — PostgreSQL SQL, or NQL. The parameter keeps its
|
|
33
|
+
* `nqlStr` name because existing callers pass it; what CHANGED is what
|
|
34
|
+
* it accepts.
|
|
35
|
+
*
|
|
36
|
+
* This was NQL-only, and an earlier version of this comment defended
|
|
37
|
+
* that as avoiding the risk of widening an existing method. Wrong twice:
|
|
38
|
+
* routing is STRUCTURAL and TOTAL (NQL begins `FROM`; PostgreSQL has no
|
|
39
|
+
* `FROM`-initial statement), so there is no ambiguity to introduce — and
|
|
40
|
+
* SQL is the FRONT DOOR. A binding that answered `SELECT who FROM orders`
|
|
41
|
+
* with "expected keyword FROM" would reproduce, one layer down, the exact
|
|
42
|
+
* "NEDB does not understand SQL" experience neSQL exists to end.
|
|
43
|
+
*/
|
|
31
44
|
query(nqlStr: string): Array<string>
|
|
45
|
+
/**
|
|
46
|
+
* `query()` under the language's own name. One implementation; `query`
|
|
47
|
+
* delegates here.
|
|
48
|
+
*
|
|
49
|
+
* Routing comes from `nedb_engine::nesql::route`, the SAME function the
|
|
50
|
+
* `nesql` CLI and `POST /query` use. Three front doors, one decision about
|
|
51
|
+
* what a statement means.
|
|
52
|
+
*/
|
|
53
|
+
nesql(statement: string): Array<string>
|
|
54
|
+
/** Which half of neSQL a statement is written in: `"nql"` or `"sql"`. */
|
|
55
|
+
nesqlDialect(statement: string): string
|
|
32
56
|
neighbors(frm: string, rel: string): Array<string>
|
|
33
57
|
neighborsAsOf(frm: string, rel: string, asOf: bigint): Array<string>
|
|
34
58
|
inbound(to: string, rel: string): Array<string>
|
package/nedb.darwin-arm64.node
CHANGED
|
Binary file
|
package/nedb.darwin-x64.node
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/nedb.linux-x64-gnu.node
CHANGED
|
Binary file
|
package/nedb.linux-x64-musl.node
CHANGED
|
Binary file
|
package/nedb.win32-x64-msvc.node
CHANGED
|
Binary file
|
package/nedbd-v2-darwin-arm64
CHANGED
|
Binary file
|
package/nedbd-v2-darwin-x64
CHANGED
|
Binary file
|
package/nedbd-v2-linux-arm64
CHANGED
|
Binary file
|
|
Binary file
|
package/nedbd-v2-linux-x64
CHANGED
|
Binary file
|
package/nedbd-v2-linux-x64-musl
CHANGED
|
Binary file
|
package/nedbd-v2-win-x64.exe
CHANGED
|
Binary file
|
package/nesql.js
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// SPDX-FileCopyrightText: 2026 INTERCHAINED LLC
|
|
3
|
+
// SPDX-License-Identifier: BUSL-1.1
|
|
4
|
+
// NEDB · © 2026 INTERCHAINED LLC × Eth-Interchained × Vex (Claude Opus 5)
|
|
5
|
+
|
|
6
|
+
// nesql — thin platform shim that locates and spawns the prebuilt neSQL CLI
|
|
7
|
+
// binary for the current platform/arch.
|
|
8
|
+
//
|
|
9
|
+
// The binaries ship alongside this file in the npm package root, using the
|
|
10
|
+
// same naming convention as nedbd-v2 so the release workflow stages both the
|
|
11
|
+
// same way:
|
|
12
|
+
//
|
|
13
|
+
// Linux x64 -> nesql-linux-x64
|
|
14
|
+
// Windows x64 -> nesql-win-x64.exe
|
|
15
|
+
// macOS arm64 -> nesql-darwin-arm64
|
|
16
|
+
// macOS x64 -> nesql-darwin-x64
|
|
17
|
+
//
|
|
18
|
+
// # The exit code is the contract
|
|
19
|
+
//
|
|
20
|
+
// `nesql` distinguishes 0 success / 1 failure / 2 usage / 3 could-not-determine
|
|
21
|
+
// / 4 not found / 5 unsupported, and callers script against those. So this shim
|
|
22
|
+
// propagates the child's code EXACTLY and never substitutes one of its own for
|
|
23
|
+
// a successful spawn. `npx nesql …` has to be indistinguishable from invoking
|
|
24
|
+
// the binary, or the codes stop meaning anything.
|
|
25
|
+
//
|
|
26
|
+
// A shim failure — unsupported platform, missing binary — exits 5
|
|
27
|
+
// (unsupported), which is the CLI's own word for "this build cannot do that".
|
|
28
|
+
// Exiting 1 would claim the command ran and failed.
|
|
29
|
+
|
|
30
|
+
"use strict";
|
|
31
|
+
|
|
32
|
+
const { spawn } = require("child_process");
|
|
33
|
+
const path = require("path");
|
|
34
|
+
const fs = require("fs");
|
|
35
|
+
|
|
36
|
+
const SUPPORTED = {
|
|
37
|
+
"linux-x64": "nesql-linux-x64",
|
|
38
|
+
"win32-x64": "nesql-win-x64.exe",
|
|
39
|
+
"darwin-arm64": "nesql-darwin-arm64",
|
|
40
|
+
"darwin-x64": "nesql-darwin-x64",
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
function main() {
|
|
44
|
+
const key = `${process.platform}-${process.arch}`;
|
|
45
|
+
const name = SUPPORTED[key];
|
|
46
|
+
|
|
47
|
+
if (!name) {
|
|
48
|
+
process.stderr.write(
|
|
49
|
+
`nesql: unsupported platform/arch: ${key}\n` +
|
|
50
|
+
`Supported: ${Object.keys(SUPPORTED).join(", ")}\n` +
|
|
51
|
+
`Build from source instead: cargo install nesql\n`
|
|
52
|
+
);
|
|
53
|
+
process.exit(5);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const binPath = path.join(__dirname, name);
|
|
57
|
+
if (!fs.existsSync(binPath)) {
|
|
58
|
+
process.stderr.write(
|
|
59
|
+
`nesql: the prebuilt binary is missing for this platform.\n` +
|
|
60
|
+
` expected: ${binPath}\n` +
|
|
61
|
+
` platform: ${key}\n\n` +
|
|
62
|
+
`This nedb-engine install did not include it. Fixes:\n` +
|
|
63
|
+
` npm install --force nedb-engine\n` +
|
|
64
|
+
` cargo install nesql # builds from source, any platform\n`
|
|
65
|
+
);
|
|
66
|
+
process.exit(5);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const child = spawn(binPath, process.argv.slice(2), { stdio: "inherit" });
|
|
70
|
+
|
|
71
|
+
child.on("error", (err) => {
|
|
72
|
+
// Named rather than swallowed: a spawn failure and a non-zero exit from a
|
|
73
|
+
// binary that DID run are different diagnoses, and collapsing them sends
|
|
74
|
+
// the reader looking in the wrong place.
|
|
75
|
+
process.stderr.write(`nesql: failed to execute ${binPath}: ${err.message}\n`);
|
|
76
|
+
process.exit(5);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
child.on("exit", (code, signal) => {
|
|
80
|
+
if (signal) {
|
|
81
|
+
// Reproduce the signal death rather than translating it to a number,
|
|
82
|
+
// so a Ctrl-C through npx behaves like a Ctrl-C to the binary.
|
|
83
|
+
process.kill(process.pid, signal);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
process.exit(code === null ? 5 : code);
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
main();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nedb-engine",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "8.0.0",
|
|
4
4
|
"description": "NEDB \u2014 hash-chained, time-traveling, bi-temporal embedded database with Rust native core. SQL, Redis, MongoDB adapters. Causal Write Provenance. RESP2 wire protocol.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"exports": {
|
|
@@ -14,7 +14,8 @@
|
|
|
14
14
|
"bin": {
|
|
15
15
|
"nedbd-v2": "./nedbd-v2.js",
|
|
16
16
|
"nedbdv2": "./nedbd-v2.js",
|
|
17
|
-
"nedb-inspector": "./nedb-inspector.mjs"
|
|
17
|
+
"nedb-inspector": "./nedb-inspector.mjs",
|
|
18
|
+
"nesql": "./nesql.js"
|
|
18
19
|
},
|
|
19
20
|
"files": [
|
|
20
21
|
"index.js",
|
|
@@ -29,7 +30,9 @@
|
|
|
29
30
|
"test/smoke.mjs",
|
|
30
31
|
"test/durability.test.mjs",
|
|
31
32
|
"README.md",
|
|
32
|
-
"LICENSE"
|
|
33
|
+
"LICENSE",
|
|
34
|
+
"nesql.js",
|
|
35
|
+
"nesql-*"
|
|
33
36
|
],
|
|
34
37
|
"license": "BUSL-1.1",
|
|
35
38
|
"homepage": "https://github.com/aiassistsecure/nedb#readme",
|