@noy-db/core 0.1.0 → 0.2.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 +56 -0
- package/dist/index.cjs +1 -20
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -20
- package/dist/index.js.map +1 -1
- package/package.json +26 -9
package/README.md
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# @noy-db/core
|
|
2
|
+
|
|
3
|
+
> Zero-knowledge, offline-first, encrypted document store — core library.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@noy-db/core)
|
|
6
|
+
[](https://github.com/vLannaAi/noy-db/blob/main/LICENSE)
|
|
7
|
+
|
|
8
|
+
Part of [**noy-db**](https://github.com/vLannaAi/noy-db) — *"None Of Your Damn Business"*.
|
|
9
|
+
|
|
10
|
+
## Install
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
pnpm add @noy-db/core @noy-db/memory
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
You need `@noy-db/core` plus at least one adapter: [`@noy-db/memory`](https://npmjs.com/package/@noy-db/memory), [`@noy-db/file`](https://npmjs.com/package/@noy-db/file), [`@noy-db/browser`](https://npmjs.com/package/@noy-db/browser), [`@noy-db/dynamo`](https://npmjs.com/package/@noy-db/dynamo), [`@noy-db/s3`](https://npmjs.com/package/@noy-db/s3).
|
|
17
|
+
|
|
18
|
+
## Quick start
|
|
19
|
+
|
|
20
|
+
```ts
|
|
21
|
+
import { createNoydb } from '@noy-db/core'
|
|
22
|
+
import { memory } from '@noy-db/memory'
|
|
23
|
+
|
|
24
|
+
type Invoice = { id: string; amount: number; customer: string }
|
|
25
|
+
|
|
26
|
+
const db = await createNoydb({
|
|
27
|
+
adapter: memory(),
|
|
28
|
+
userId: 'alice',
|
|
29
|
+
passphrase: 'correct horse battery staple',
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
const c101 = await db.openCompartment('C101')
|
|
33
|
+
const invoices = c101.collection<Invoice>('invoices')
|
|
34
|
+
|
|
35
|
+
await invoices.put('INV-001', { id: 'INV-001', amount: 8500, customer: 'ABC Trading' })
|
|
36
|
+
const all = await invoices.list()
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## What it does
|
|
40
|
+
|
|
41
|
+
- **Zero-knowledge encryption** — AES-256-GCM + PBKDF2 (600K iterations) + AES-KW, all via Web Crypto API
|
|
42
|
+
- **Per-collection keys** — one DEK per collection, wrapped with a per-user KEK
|
|
43
|
+
- **Multi-user access control** — owner, admin, operator, viewer, client roles
|
|
44
|
+
- **Offline-first sync** — push/pull with optimistic concurrency on encrypted envelopes
|
|
45
|
+
- **Audit history** — full-copy snapshots with `history()`, `diff()`, `revert()`, `pruneHistory()`
|
|
46
|
+
- **Zero runtime dependencies**
|
|
47
|
+
|
|
48
|
+
## Documentation
|
|
49
|
+
|
|
50
|
+
- Full docs: https://github.com/vLannaAi/noy-db#readme
|
|
51
|
+
- Spec: https://github.com/vLannaAi/noy-db/blob/main/NOYDB_SPEC.md
|
|
52
|
+
- AI reference: https://github.com/vLannaAi/noy-db/blob/main/docs/NOYDB_FOR_AI.md
|
|
53
|
+
|
|
54
|
+
## License
|
|
55
|
+
|
|
56
|
+
MIT © vLannaAi
|
package/dist/index.cjs
CHANGED
|
@@ -54,24 +54,6 @@ __export(index_exports, {
|
|
|
54
54
|
});
|
|
55
55
|
module.exports = __toCommonJS(index_exports);
|
|
56
56
|
|
|
57
|
-
// src/env-check.ts
|
|
58
|
-
function checkEnvironment() {
|
|
59
|
-
if (typeof process !== "undefined" && process.versions?.node) {
|
|
60
|
-
const major = parseInt(process.versions.node.split(".")[0], 10);
|
|
61
|
-
if (major < 18) {
|
|
62
|
-
throw new Error(
|
|
63
|
-
`@noy-db/core requires Node.js 18 or later (found ${process.versions.node}). Node.js 18+ is required for the Web Crypto API (crypto.subtle).`
|
|
64
|
-
);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
if (typeof globalThis.crypto?.subtle === "undefined") {
|
|
68
|
-
throw new Error(
|
|
69
|
-
"@noy-db/core requires the Web Crypto API (crypto.subtle). Ensure you are running Node.js 18+ or a modern browser (Chrome 63+, Firefox 57+, Safari 13+)."
|
|
70
|
-
);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
checkEnvironment();
|
|
74
|
-
|
|
75
57
|
// src/types.ts
|
|
76
58
|
var NOYDB_FORMAT_VERSION = 1;
|
|
77
59
|
var NOYDB_KEYRING_VERSION = 1;
|
|
@@ -411,7 +393,6 @@ async function rotateKeys(adapter, compartment, callerKeyring, collections) {
|
|
|
411
393
|
const userEnvelope = await adapter.get(compartment, "_keyring", userId);
|
|
412
394
|
if (!userEnvelope) continue;
|
|
413
395
|
const userKeyringFile = JSON.parse(userEnvelope._data);
|
|
414
|
-
const userKek = null;
|
|
415
396
|
const updatedDeks = { ...userKeyringFile.deks };
|
|
416
397
|
for (const collName of collections) {
|
|
417
398
|
delete updatedDeks[collName];
|
|
@@ -543,7 +524,7 @@ async function saveHistory(adapter, compartment, collection, recordId, envelope)
|
|
|
543
524
|
async function getHistory(adapter, compartment, collection, recordId, options) {
|
|
544
525
|
const allIds = await adapter.list(compartment, HISTORY_COLLECTION);
|
|
545
526
|
const matchingIds = allIds.filter((id) => matchesPrefix(id, collection, recordId)).sort().reverse();
|
|
546
|
-
|
|
527
|
+
const entries = [];
|
|
547
528
|
for (const id of matchingIds) {
|
|
548
529
|
const envelope = await adapter.get(compartment, HISTORY_COLLECTION, id);
|
|
549
530
|
if (!envelope) continue;
|