@serfab/quereus-plugin-sereus 0.8.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.
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Quereus plugin entry point for Sereus strand connections (Node).
3
+ *
4
+ * Loaded via Quoomb's `.plugin install` or config file, or via `registerPlugin()`.
5
+ * Parses SqlValue config and delegates to `connectToStrand`.
6
+ *
7
+ * Browser/Worker consumers should load `./plugin-browser` instead, which uses
8
+ * the TCP-free libp2p entry and IndexedDB-backed default storage.
9
+ */
10
+ import type { Database, SqlValue } from '@quereus/quereus';
11
+ import { parseConfig } from './parse-config.js';
12
+ import type { SereusPluginResult } from './types.js';
13
+ export { parseConfig };
14
+ /**
15
+ * Default export: Quereus plugin registration function.
16
+ */
17
+ export default function register(db: Database, config?: Record<string, SqlValue>): Promise<SereusPluginResult>;
package/dist/plugin.js ADDED
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Quereus plugin entry point for Sereus strand connections (Node).
3
+ *
4
+ * Loaded via Quoomb's `.plugin install` or config file, or via `registerPlugin()`.
5
+ * Parses SqlValue config and delegates to `connectToStrand`.
6
+ *
7
+ * Browser/Worker consumers should load `./plugin-browser` instead, which uses
8
+ * the TCP-free libp2p entry and IndexedDB-backed default storage.
9
+ */
10
+ import { connectToStrand } from './connect.js';
11
+ import { parseConfig } from './parse-config.js';
12
+ export { parseConfig };
13
+ /**
14
+ * Default export: Quereus plugin registration function.
15
+ */
16
+ export default async function register(db, config = {}) {
17
+ const options = parseConfig(config);
18
+ // `storage_path` is a Node-only loader convenience: a `Record<string, SqlValue>`
19
+ // cannot carry an `IRawStorage`, so the path is resolved to a concrete
20
+ // `FileRawStorage` here (not in the platform-agnostic `parseConfig`). The
21
+ // dynamic import keeps `@optimystic/db-p2p-storage-fs` (and its `node:fs`
22
+ // dependency) out of the browser/RN module graph.
23
+ const storagePath = config.storage_path;
24
+ if (typeof storagePath === 'string' && storagePath) {
25
+ const { FileRawStorage } = await import('@optimystic/db-p2p-storage-fs');
26
+ options.storage = new FileRawStorage(storagePath);
27
+ }
28
+ return connectToStrand(db, options);
29
+ }
30
+ //# sourceMappingURL=plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGhD,OAAO,EAAE,WAAW,EAAE,CAAC;AAEvB;;GAEG;AACH,MAAM,CAAC,OAAO,CAAC,KAAK,UAAU,QAAQ,CACrC,EAAY,EACZ,SAAmC,EAAE;IAErC,MAAM,OAAO,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IAEpC,iFAAiF;IACjF,uEAAuE;IACvE,0EAA0E;IAC1E,0EAA0E;IAC1E,kDAAkD;IAClD,MAAM,WAAW,GAAG,MAAM,CAAC,YAAY,CAAC;IACxC,IAAI,OAAO,WAAW,KAAK,QAAQ,IAAI,WAAW,EAAE,CAAC;QACpD,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,MAAM,CAAC,+BAA+B,CAAC,CAAC;QACzE,OAAO,CAAC,OAAO,GAAG,IAAI,cAAc,CAAC,WAAW,CAAC,CAAC;IACnD,CAAC;IAED,OAAO,eAAe,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;AACrC,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Embedded strand membership/RBAC schema for cross-platform compatibility.
3
+ *
4
+ * This is the authoritative runtime copy of the `Strand` membership schema. It
5
+ * is duplicated from `schemas/strand.qsql` so that React Native and other
6
+ * filesystem-less environments get the schema without a runtime file read —
7
+ * the same pattern `CONTROL_SCHEMA` (cadre-core) uses for the control schema.
8
+ *
9
+ * `STRAND_SCHEMA` holds only the *body* (the inner table declarations). The
10
+ * shared composition (`composeStrand`) wraps it in
11
+ * `declare schema Strand { ... } apply schema Strand;`, mirroring how the sApp
12
+ * schema is wrapped in `declare schema App { ... }`.
13
+ *
14
+ * Drift discipline: the table declarations here MUST stay byte-equivalent to the
15
+ * body of `schemas/strand.qsql` (the on-disk canonical copy). Any edit here must
16
+ * be mirrored there and vice versa — the same invariant the planned
17
+ * `control-schema-drift-guard` enforces for the control schema.
18
+ *
19
+ * Crypto idiom (matches `schemas/control.qsql` and the sApp RBAC fixture
20
+ * `packages/integration-tests/fixtures/simple-sapp.qsql`): every signed write
21
+ * proves itself with `verify(digest(<concatenated payload>, 'sha256', 'utf8'),
22
+ * <signature>, <pubkey>, 'ed25519')`. Member keys are ed25519, so the explicit
23
+ * curve arg is REQUIRED (verify() otherwise defaults to secp256k1).
24
+ *
25
+ * Population note: this ticket applies the schema and makes its constraints
26
+ * active — it does NOT write membership rows at runtime. Inserting the `Header`,
27
+ * the founding `Authority`/`Member`, and the invite/peer flows is owned by
28
+ * `strand-membership-lifecycle-population`.
29
+ */
30
+ export declare const STRAND_SCHEMA = " table Header (\n Id text, -- UUID of this network - generated at inception - immutable\n\n -- Types: 'o' = Open, 'c' = Closed\n -- Any peers can join an open network, but only members can join a closed network\n -- Open can still control writes in the app, but only Closed prevents reads\n Type text check (Type in ('o', 'c')),\n\n -- The app that this strand faciliates - public key from author to prevent tampering\n sAppId text,\n\n -- The version of the sApp that this strand faciliates\n sAppVersion text,\n\n -- The schema of the sApp that this strand faciliates\n sAppSchema text,\n\n -- The author's signature on the schema to guarantee authorship\n sAppSignature text,\n\n -- The engine (rules logic system) that is assumed to manage this strand\n Engine text,\n\n -- The version of the engine that is assumed to manage this strand\n EngineVersion text,\n\n primary key (/* empty - singleton */),\n constraint InsertOnly check on update, delete (false), -- One-time insert only for now - TODO: revisit for versioning\n );\n\n -- An invitation to join a strand as a member\n table Invite (\n Key text primary key,\n Expiration datetime null,\n -- TODO: ability to deactivate?\n constraint InsertOnly check on update, delete (false),\n constraint OnlyClosed check (\n exists (select 1 from Header H where H.Type = 'c')\n ),\n constraint InviteValid check on insert (\n -- Can only be inserted by an authority,\n exists (select 1 from Authority A\n where A.MemberKey = context.AuthorityKey\n and verify(digest(new.Key || '|' || coalesce(new.Expiration, ''), 'sha256', 'utf8'), context.AuthoritySignature, A.MemberKey, 'ed25519')\n )\n -- and must also prove invite private key held by issuing authority\n and verify(digest(new.Key || '|' || coalesce(new.Expiration, ''), 'sha256', 'utf8'), context.InviteSignature, new.Key, 'ed25519')\n )\n ) with context (AuthorityKey text null, AuthoritySignature text null, InviteSignature text null);\n\n -- Invite [InviteKey] has been used to add [MemberKey] as a member\n table ConsumedInvite (\n InviteKey text primary key,\n MemberKey text,\n constraint InsertOnly check on update, delete (false),\n constraint InviteExists check (exists (select 1 from Invite I where I.Key = new.InviteKey)),\n constraint MemberExists check (exists (select 1 from Member M where M.Key = new.MemberKey)),\n constraint ValidUsage check on insert (\n exists (select 1 from Invite I where I.Key = new.InviteKey and verify(digest(new.InviteKey || '|' || new.MemberKey, 'sha256', 'utf8'), context.InviteSignature, new.InviteKey, 'ed25519'))\n ),\n constraint MemberValid check (exists (select 1 from Member M where M.Key = new.MemberKey))\n ) with context (InviteSignature text null);\n\n -- A party in the closed strand network\n table Member (\n Key text primary key,\n constraint NoUpdate check on update (false),\n constraint OnlyClosed check (\n exists (select 1 from Header H where H.Type = 'c')\n ),\n constraint Authorized check on insert (\n -- There are no other records - first member needs no authorization\n (select count(1) from Member) <= 1\n\n -- or added directly by authority\n or exists (\n select 1 from Authority A\n where A.MemberKey = context.AuthorityKey\n and verify(digest(new.Key, 'sha256', 'utf8'), context.AuthoritySignature, A.MemberKey, 'ed25519')\n )\n\n -- or added by invite\n or exists (\n select 1 from ConsumedInvite CI where CI.MemberKey = new.Key\n )\n ),\n -- TODO: handle member revocation constraint\n ) with context (AuthorityKey text null, AuthoritySignature text null);\n\n -- A member-associated peer (node)\n table MemberPeer (\n MemberKey text,\n PeerId text,\n primary key (MemberKey, PeerId),\n constraint MemberExists check (exists (select 1 from Member M where M.Key = new.MemberKey)),\n constraint Authorized check (\n verify(\n digest(coalesce(new.MemberKey, old.MemberKey) || '|' || coalesce(new.PeerId, old.PeerId), 'sha256', 'utf8'),\n context.Signature,\n coalesce(new.MemberKey, old.MemberKey),\n 'ed25519'\n )\n ),\n ) with context (Signature text null);\n\n -- An authority is a member that can issue invites, authorize members, and rotate authorities\n table Authority (\n MemberKey text primary key,\n constraint OnlyClosed check (\n exists (select 1 from Header H where H.Type = 'c')\n ),\n constraint Authorized check (\n -- There are no existing records - first authority needs no authorization\n (select count(1) from Authority) <= 1\n\n -- or authorized by this former authority\n or (\n old.MemberKey is not null\n and old.MemberKey = context.AuthorityKey\n and verify(digest(old.MemberKey, 'sha256', 'utf8'), context.Signature, old.MemberKey, 'ed25519')\n )\n\n -- or authorized by another existing authority\n or exists (\n select 1 from Authority A\n where A.MemberKey = context.AuthorityKey\n and verify(digest(coalesce(new.MemberKey, old.MemberKey), 'sha256', 'utf8'), context.Signature, A.MemberKey, 'ed25519')\n )\n )\n ) with context (AuthorityKey text null, Signature text null);\n";
@@ -0,0 +1,161 @@
1
+ /**
2
+ * Embedded strand membership/RBAC schema for cross-platform compatibility.
3
+ *
4
+ * This is the authoritative runtime copy of the `Strand` membership schema. It
5
+ * is duplicated from `schemas/strand.qsql` so that React Native and other
6
+ * filesystem-less environments get the schema without a runtime file read —
7
+ * the same pattern `CONTROL_SCHEMA` (cadre-core) uses for the control schema.
8
+ *
9
+ * `STRAND_SCHEMA` holds only the *body* (the inner table declarations). The
10
+ * shared composition (`composeStrand`) wraps it in
11
+ * `declare schema Strand { ... } apply schema Strand;`, mirroring how the sApp
12
+ * schema is wrapped in `declare schema App { ... }`.
13
+ *
14
+ * Drift discipline: the table declarations here MUST stay byte-equivalent to the
15
+ * body of `schemas/strand.qsql` (the on-disk canonical copy). Any edit here must
16
+ * be mirrored there and vice versa — the same invariant the planned
17
+ * `control-schema-drift-guard` enforces for the control schema.
18
+ *
19
+ * Crypto idiom (matches `schemas/control.qsql` and the sApp RBAC fixture
20
+ * `packages/integration-tests/fixtures/simple-sapp.qsql`): every signed write
21
+ * proves itself with `verify(digest(<concatenated payload>, 'sha256', 'utf8'),
22
+ * <signature>, <pubkey>, 'ed25519')`. Member keys are ed25519, so the explicit
23
+ * curve arg is REQUIRED (verify() otherwise defaults to secp256k1).
24
+ *
25
+ * Population note: this ticket applies the schema and makes its constraints
26
+ * active — it does NOT write membership rows at runtime. Inserting the `Header`,
27
+ * the founding `Authority`/`Member`, and the invite/peer flows is owned by
28
+ * `strand-membership-lifecycle-population`.
29
+ */
30
+ export const STRAND_SCHEMA = ` table Header (
31
+ Id text, -- UUID of this network - generated at inception - immutable
32
+
33
+ -- Types: 'o' = Open, 'c' = Closed
34
+ -- Any peers can join an open network, but only members can join a closed network
35
+ -- Open can still control writes in the app, but only Closed prevents reads
36
+ Type text check (Type in ('o', 'c')),
37
+
38
+ -- The app that this strand faciliates - public key from author to prevent tampering
39
+ sAppId text,
40
+
41
+ -- The version of the sApp that this strand faciliates
42
+ sAppVersion text,
43
+
44
+ -- The schema of the sApp that this strand faciliates
45
+ sAppSchema text,
46
+
47
+ -- The author's signature on the schema to guarantee authorship
48
+ sAppSignature text,
49
+
50
+ -- The engine (rules logic system) that is assumed to manage this strand
51
+ Engine text,
52
+
53
+ -- The version of the engine that is assumed to manage this strand
54
+ EngineVersion text,
55
+
56
+ primary key (/* empty - singleton */),
57
+ constraint InsertOnly check on update, delete (false), -- One-time insert only for now - TODO: revisit for versioning
58
+ );
59
+
60
+ -- An invitation to join a strand as a member
61
+ table Invite (
62
+ Key text primary key,
63
+ Expiration datetime null,
64
+ -- TODO: ability to deactivate?
65
+ constraint InsertOnly check on update, delete (false),
66
+ constraint OnlyClosed check (
67
+ exists (select 1 from Header H where H.Type = 'c')
68
+ ),
69
+ constraint InviteValid check on insert (
70
+ -- Can only be inserted by an authority,
71
+ exists (select 1 from Authority A
72
+ where A.MemberKey = context.AuthorityKey
73
+ and verify(digest(new.Key || '|' || coalesce(new.Expiration, ''), 'sha256', 'utf8'), context.AuthoritySignature, A.MemberKey, 'ed25519')
74
+ )
75
+ -- and must also prove invite private key held by issuing authority
76
+ and verify(digest(new.Key || '|' || coalesce(new.Expiration, ''), 'sha256', 'utf8'), context.InviteSignature, new.Key, 'ed25519')
77
+ )
78
+ ) with context (AuthorityKey text null, AuthoritySignature text null, InviteSignature text null);
79
+
80
+ -- Invite [InviteKey] has been used to add [MemberKey] as a member
81
+ table ConsumedInvite (
82
+ InviteKey text primary key,
83
+ MemberKey text,
84
+ constraint InsertOnly check on update, delete (false),
85
+ constraint InviteExists check (exists (select 1 from Invite I where I.Key = new.InviteKey)),
86
+ constraint MemberExists check (exists (select 1 from Member M where M.Key = new.MemberKey)),
87
+ constraint ValidUsage check on insert (
88
+ exists (select 1 from Invite I where I.Key = new.InviteKey and verify(digest(new.InviteKey || '|' || new.MemberKey, 'sha256', 'utf8'), context.InviteSignature, new.InviteKey, 'ed25519'))
89
+ ),
90
+ constraint MemberValid check (exists (select 1 from Member M where M.Key = new.MemberKey))
91
+ ) with context (InviteSignature text null);
92
+
93
+ -- A party in the closed strand network
94
+ table Member (
95
+ Key text primary key,
96
+ constraint NoUpdate check on update (false),
97
+ constraint OnlyClosed check (
98
+ exists (select 1 from Header H where H.Type = 'c')
99
+ ),
100
+ constraint Authorized check on insert (
101
+ -- There are no other records - first member needs no authorization
102
+ (select count(1) from Member) <= 1
103
+
104
+ -- or added directly by authority
105
+ or exists (
106
+ select 1 from Authority A
107
+ where A.MemberKey = context.AuthorityKey
108
+ and verify(digest(new.Key, 'sha256', 'utf8'), context.AuthoritySignature, A.MemberKey, 'ed25519')
109
+ )
110
+
111
+ -- or added by invite
112
+ or exists (
113
+ select 1 from ConsumedInvite CI where CI.MemberKey = new.Key
114
+ )
115
+ ),
116
+ -- TODO: handle member revocation constraint
117
+ ) with context (AuthorityKey text null, AuthoritySignature text null);
118
+
119
+ -- A member-associated peer (node)
120
+ table MemberPeer (
121
+ MemberKey text,
122
+ PeerId text,
123
+ primary key (MemberKey, PeerId),
124
+ constraint MemberExists check (exists (select 1 from Member M where M.Key = new.MemberKey)),
125
+ constraint Authorized check (
126
+ verify(
127
+ digest(coalesce(new.MemberKey, old.MemberKey) || '|' || coalesce(new.PeerId, old.PeerId), 'sha256', 'utf8'),
128
+ context.Signature,
129
+ coalesce(new.MemberKey, old.MemberKey),
130
+ 'ed25519'
131
+ )
132
+ ),
133
+ ) with context (Signature text null);
134
+
135
+ -- An authority is a member that can issue invites, authorize members, and rotate authorities
136
+ table Authority (
137
+ MemberKey text primary key,
138
+ constraint OnlyClosed check (
139
+ exists (select 1 from Header H where H.Type = 'c')
140
+ ),
141
+ constraint Authorized check (
142
+ -- There are no existing records - first authority needs no authorization
143
+ (select count(1) from Authority) <= 1
144
+
145
+ -- or authorized by this former authority
146
+ or (
147
+ old.MemberKey is not null
148
+ and old.MemberKey = context.AuthorityKey
149
+ and verify(digest(old.MemberKey, 'sha256', 'utf8'), context.Signature, old.MemberKey, 'ed25519')
150
+ )
151
+
152
+ -- or authorized by another existing authority
153
+ or exists (
154
+ select 1 from Authority A
155
+ where A.MemberKey = context.AuthorityKey
156
+ and verify(digest(coalesce(new.MemberKey, old.MemberKey), 'sha256', 'utf8'), context.Signature, A.MemberKey, 'ed25519')
157
+ )
158
+ )
159
+ ) with context (AuthorityKey text null, Signature text null);
160
+ `;
161
+ //# sourceMappingURL=strand-schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"strand-schema.js","sourceRoot":"","sources":["../src/strand-schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkI5B,CAAC"}
@@ -0,0 +1,69 @@
1
+ import type { Libp2p } from '@libp2p/interface';
2
+ import type { IRepo } from '@optimystic/db-core';
3
+ import type { IRawStorage } from '@optimystic/db-p2p';
4
+ export interface StrandConnectionOptions {
5
+ /** UUID of the strand to connect to */
6
+ strandId: string;
7
+ /** Bootstrap multiaddrs for peer discovery */
8
+ bootstrapNodes?: string[];
9
+ /** sApp schema DDL to apply (optional - omit if schema already exists on strand) */
10
+ schema?: string;
11
+ /** sApp author public key */
12
+ sAppId?: string;
13
+ /** sApp version */
14
+ sAppVersion?: string;
15
+ /** libp2p listening port (default: 0 = random) */
16
+ port?: number;
17
+ /** Enable optimystic caching (default: true) */
18
+ enableCache?: boolean;
19
+ /** FRET profile (default: 'edge') */
20
+ fretProfile?: 'edge' | 'core';
21
+ /** Inject an existing libp2p node instead of creating one */
22
+ libp2pNode?: Libp2p;
23
+ /** Required when libp2pNode is provided */
24
+ coordinatedRepo?: IRepo;
25
+ /**
26
+ * Lifecycle mode. `'networked'` (default) uses the network transactor and
27
+ * is appropriate for multi-peer participation. `'bootstrap'` switches to a
28
+ * local transactor so a solo node can apply schema and accept DML with no
29
+ * peer round trips; pair it with a persistent `storage` to survive restart.
30
+ */
31
+ mode?: 'bootstrap' | 'networked';
32
+ /**
33
+ * Persistent raw storage. When provided:
34
+ * - it is passed to `createLibp2pNode` as `storage` so the libp2p data path uses it,
35
+ * - in `bootstrap` mode it is also handed to the optimystic plugin as
36
+ * `rawStorageFactory: () => storage` so the local transactor persists DML
37
+ * on the same instance (avoids cache divergence between the two consumers).
38
+ *
39
+ * The plugin treats `storage` as borrowed — it is NOT closed on `shutdown()`.
40
+ */
41
+ storage?: IRawStorage;
42
+ /** @internal Override transactor type. Used by unit tests with `'test'`. When set, takes precedence only if `mode` is not specified. */
43
+ transactor?: string;
44
+ }
45
+ export interface SereusPluginResult {
46
+ vtables: [];
47
+ functions: [];
48
+ collations: [];
49
+ /**
50
+ * Catalog-hydration counts from the warm-restart hydrate that runs before
51
+ * `apply schema App;`. On a cold start (empty storage) both are 0; on a warm
52
+ * restart they report the persisted tables/indexes the catalog was primed
53
+ * with — so a test can assert hydration actually ran. `undefined` only if
54
+ * composition threw before hydrate.
55
+ */
56
+ hydrated?: {
57
+ tables: number;
58
+ indexes: number;
59
+ };
60
+ /** Shuts down the libp2p node and collection factory. Call when done. */
61
+ shutdown: () => Promise<void>;
62
+ }
63
+ /**
64
+ * Extended Libp2p node type with coordinatedRepo attached by createLibp2pNode.
65
+ * @internal
66
+ */
67
+ export interface Libp2pNodeWithRepo extends Libp2p {
68
+ coordinatedRepo: IRepo;
69
+ }
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,145 @@
1
+ {
2
+ "name": "@serfab/quereus-plugin-sereus",
3
+ "version": "0.8.0",
4
+ "type": "module",
5
+ "description": "Quereus plugin that connects to a Sereus strand for SQL access",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "files": [
9
+ "src",
10
+ "dist",
11
+ "!dist/test",
12
+ "!**/*.tsbuildinfo"
13
+ ],
14
+ "exports": {
15
+ ".": {
16
+ "types": "./dist/index.d.ts",
17
+ "import": "./dist/index.js"
18
+ },
19
+ "./plugin": {
20
+ "types": "./dist/plugin.d.ts",
21
+ "browser": "./dist/plugin-browser.js",
22
+ "import": "./dist/plugin.js"
23
+ },
24
+ "./plugin-browser": {
25
+ "types": "./dist/plugin-browser.d.ts",
26
+ "import": "./dist/plugin-browser.js"
27
+ }
28
+ },
29
+ "repository": {
30
+ "type": "git",
31
+ "url": "https://github.com/gotchoices/sereus.git",
32
+ "directory": "packages/quereus-plugin-sereus"
33
+ },
34
+ "author": "Got Choices Foundation",
35
+ "license": "MIT",
36
+ "keywords": [
37
+ "quereus-plugin",
38
+ "quereus",
39
+ "sereus",
40
+ "strand",
41
+ "distributed",
42
+ "database",
43
+ "sql",
44
+ "p2p"
45
+ ],
46
+ "scripts": {
47
+ "clean": "rimraf dist",
48
+ "build": "tsc -p tsconfig.build.json && node scripts/build-browser.mjs",
49
+ "typecheck": "tsc -p tsconfig.typecheck.json --noEmit",
50
+ "test": "vitest run",
51
+ "test:e2e": "vitest run --project e2e",
52
+ "dev:test": "vitest"
53
+ },
54
+ "devDependencies": {
55
+ "@types/debug": "^4.1.12",
56
+ "@types/node": "^25.0.10",
57
+ "@vitest/coverage-v8": "^4.0.17",
58
+ "acorn": "^8.12.0",
59
+ "esbuild": "^0.27.2",
60
+ "fake-indexeddb": "^6.2.4",
61
+ "jsdom": "^25.0.1",
62
+ "rimraf": "^6.1.2",
63
+ "typescript": "^5.9.3",
64
+ "vitest": "^4.0.17"
65
+ },
66
+ "dependencies": {
67
+ "@libp2p/circuit-relay-v2": "^4.1.3",
68
+ "@libp2p/interface": "^3.1.0",
69
+ "@libp2p/websockets": "^10.1.3",
70
+ "@optimystic/db-core": "^0.13.5",
71
+ "@optimystic/db-p2p": "^0.13.5",
72
+ "@optimystic/db-p2p-storage-fs": "^0.13.5",
73
+ "@optimystic/db-p2p-storage-web": "^0.13.5",
74
+ "@optimystic/quereus-plugin-crypto": "^0.13.5",
75
+ "@optimystic/quereus-plugin-optimystic": "^0.13.5",
76
+ "@quereus/quereus": "^3.2.1",
77
+ "debug": "^4.4.3"
78
+ },
79
+ "quereus": {
80
+ "provides": {
81
+ "vtables": [
82
+ "optimystic"
83
+ ],
84
+ "functions": [
85
+ "StampId",
86
+ "digest",
87
+ "sign",
88
+ "verify",
89
+ "randomBytes"
90
+ ]
91
+ },
92
+ "settings": [
93
+ {
94
+ "key": "strand_id",
95
+ "type": "string"
96
+ },
97
+ {
98
+ "key": "bootstrap_nodes",
99
+ "type": "string",
100
+ "default": ""
101
+ },
102
+ {
103
+ "key": "schema",
104
+ "type": "string"
105
+ },
106
+ {
107
+ "key": "sapp_id",
108
+ "type": "string",
109
+ "default": "unknown"
110
+ },
111
+ {
112
+ "key": "sapp_version",
113
+ "type": "string",
114
+ "default": "1.0.0"
115
+ },
116
+ {
117
+ "key": "port",
118
+ "type": "number",
119
+ "default": 0
120
+ },
121
+ {
122
+ "key": "enable_cache",
123
+ "type": "boolean",
124
+ "default": true
125
+ },
126
+ {
127
+ "key": "fret_profile",
128
+ "type": "string",
129
+ "default": "edge"
130
+ },
131
+ {
132
+ "key": "mode",
133
+ "type": "string"
134
+ },
135
+ {
136
+ "key": "transactor",
137
+ "type": "string"
138
+ },
139
+ {
140
+ "key": "storage_path",
141
+ "type": "string"
142
+ }
143
+ ]
144
+ }
145
+ }