@bluefields/cli 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/LICENSE +661 -0
- package/README.md +181 -0
- package/dist/anchor.d.ts +24 -0
- package/dist/anchor.js +48 -0
- package/dist/anchor.js.map +1 -0
- package/dist/attestation.d.ts +50 -0
- package/dist/attestation.js +90 -0
- package/dist/attestation.js.map +1 -0
- package/dist/bluefield.d.ts +180 -0
- package/dist/bluefield.js +382 -0
- package/dist/bluefield.js.map +1 -0
- package/dist/cli.d.ts +19 -0
- package/dist/cli.js +310 -0
- package/dist/cli.js.map +1 -0
- package/dist/constants.d.ts +28 -0
- package/dist/constants.js +30 -0
- package/dist/constants.js.map +1 -0
- package/dist/fs-storage.d.ts +20 -0
- package/dist/fs-storage.js +60 -0
- package/dist/fs-storage.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/keystore.d.ts +40 -0
- package/dist/keystore.js +77 -0
- package/dist/keystore.js.map +1 -0
- package/dist/mcp-server.d.ts +40 -0
- package/dist/mcp-server.js +252 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/paths.d.ts +52 -0
- package/dist/paths.js +77 -0
- package/dist/paths.js.map +1 -0
- package/dist/quiet.d.ts +11 -0
- package/dist/quiet.js +14 -0
- package/dist/quiet.js.map +1 -0
- package/dist/store.d.ts +46 -0
- package/dist/store.js +233 -0
- package/dist/store.js.map +1 -0
- package/package.json +63 -0
package/dist/store.js
ADDED
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
/**
|
|
3
|
+
* The local metadata store — an embedded Postgres (PGlite, WASM, in-process)
|
|
4
|
+
* that satisfies the `DbClient` the engine injects. NO hosted Postgres, no
|
|
5
|
+
* network, no KMS. The full Drizzle schema is applied to a file-backed PGlite
|
|
6
|
+
* data directory under `<store>/db`, so snapshot history survives across CLI
|
|
7
|
+
* invocations and `log`/`diff`/`watch`/`export` can query it with real SQL.
|
|
8
|
+
*
|
|
9
|
+
* This reuses the QA real-DB harness pattern (statement-by-statement, tolerant
|
|
10
|
+
* apply): a handful of migrations use Neon/pg_cron/pg_partman features PGlite
|
|
11
|
+
* lacks; those statements skip harmlessly while the engine tables are created
|
|
12
|
+
* from plain DDL. Two extra local adaptations then run:
|
|
13
|
+
*
|
|
14
|
+
* 1. DEFAULT partitions — `snapshots` / `cost_records` / `events` /
|
|
15
|
+
* `audit_log` are declared `PARTITION BY RANGE`, and without pg_partman
|
|
16
|
+
* they have no child partitions, so INSERTs would fail. We attach a
|
|
17
|
+
* `<table>_default DEFAULT` partition to each so rows land locally.
|
|
18
|
+
* 2. A single seed `customers` row — `cost_records.customer_id` is a NOT-NULL
|
|
19
|
+
* FK to `customers`, and the engine writes a cost row per fetch. One fixed
|
|
20
|
+
* local customer keeps the engine's billing plumbing satisfied with zero
|
|
21
|
+
* behavioural change.
|
|
22
|
+
*/
|
|
23
|
+
import { mkdirSync, readFileSync, readdirSync } from 'node:fs';
|
|
24
|
+
import { dirname, resolve } from 'node:path';
|
|
25
|
+
import { fileURLToPath } from 'node:url';
|
|
26
|
+
import { customers } from '@bluefields/db';
|
|
27
|
+
import { PGlite } from '@electric-sql/pglite';
|
|
28
|
+
import { drizzle } from 'drizzle-orm/pglite';
|
|
29
|
+
/**
|
|
30
|
+
* Fixed local identity for the single-user store. `cost_records` and
|
|
31
|
+
* `snapshots` are attributed to this synthetic customer; it never leaves the
|
|
32
|
+
* machine and carries no billing meaning.
|
|
33
|
+
*/
|
|
34
|
+
export const LOCAL_CUSTOMER_ID = '00000000-0000-4000-8000-000000000001';
|
|
35
|
+
export const LOCAL_CUSTOMER_EMAIL = 'local@bluefield.invalid';
|
|
36
|
+
export const LOCAL_SUBSCRIPTION_ID = null;
|
|
37
|
+
/** Partitioned parents that need a DEFAULT partition to accept rows locally. */
|
|
38
|
+
const PARTITIONED_TABLES = ['snapshots', 'cost_records', 'events', 'audit_log'];
|
|
39
|
+
/** Resolve the engine's migrations directory (overridable for tests/packaging). */
|
|
40
|
+
function migrationsDir() {
|
|
41
|
+
const override = process.env.BF_MIGRATIONS_DIR;
|
|
42
|
+
if (override?.trim())
|
|
43
|
+
return resolve(override.trim());
|
|
44
|
+
// Works from both `src/` (tsx) and `dist/` — both are direct children of
|
|
45
|
+
// `packages/cli`, so `../../db/src/migrations` lands in `@bluefields/db`.
|
|
46
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
47
|
+
return resolve(here, '../../db/src/migrations');
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Open (or create) the file-backed local store at `dbDir` and return an
|
|
51
|
+
* engine-compatible `DbClient`. Idempotent: re-opening an existing store
|
|
52
|
+
* re-applies DDL tolerantly (`IF NOT EXISTS` / already-exists skips) and
|
|
53
|
+
* re-seeds via `ON CONFLICT DO NOTHING`.
|
|
54
|
+
*/
|
|
55
|
+
export async function openStore(dbDir) {
|
|
56
|
+
// PGlite's node fs backend creates only the leaf data dir, not its parents.
|
|
57
|
+
mkdirSync(dbDir, { recursive: true });
|
|
58
|
+
const client = new PGlite(dbDir);
|
|
59
|
+
await client.waitReady;
|
|
60
|
+
let skipped = 0;
|
|
61
|
+
const alreadyInitialized = await tableExists(client, 'snapshots');
|
|
62
|
+
if (!alreadyInitialized) {
|
|
63
|
+
skipped = await applyMigrations(client);
|
|
64
|
+
}
|
|
65
|
+
await ensureDefaultPartitions(client);
|
|
66
|
+
const db = drizzle(client);
|
|
67
|
+
await seedLocalCustomer(db);
|
|
68
|
+
return {
|
|
69
|
+
db,
|
|
70
|
+
client,
|
|
71
|
+
skipped,
|
|
72
|
+
async close() {
|
|
73
|
+
await client.close();
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/** True if a public-schema table exists. */
|
|
78
|
+
async function tableExists(client, table) {
|
|
79
|
+
const r = await client.query(`SELECT to_regclass('public.${table}') AS reg;`);
|
|
80
|
+
return Boolean(r.rows[0]?.reg);
|
|
81
|
+
}
|
|
82
|
+
/** Apply every migration statement-by-statement with per-statement tolerance. */
|
|
83
|
+
async function applyMigrations(client) {
|
|
84
|
+
const dir = migrationsDir();
|
|
85
|
+
const files = readdirSync(dir)
|
|
86
|
+
.filter((f) => f.endsWith('.sql'))
|
|
87
|
+
.sort();
|
|
88
|
+
let skipped = 0;
|
|
89
|
+
for (const f of files) {
|
|
90
|
+
const text = readFileSync(resolve(dir, f), 'utf8');
|
|
91
|
+
for (const stmt of splitSql(text)) {
|
|
92
|
+
const bare = stmt.replace(/--[^\n]*/g, ' ').trim();
|
|
93
|
+
if (!bare)
|
|
94
|
+
continue;
|
|
95
|
+
// Drop transaction control so one incompatible DDL can't abort a whole
|
|
96
|
+
// file: each statement applies in its own autocommit.
|
|
97
|
+
if (/^(begin|commit|rollback|start\s+transaction)$/i.test(bare))
|
|
98
|
+
continue;
|
|
99
|
+
try {
|
|
100
|
+
await client.exec(stmt);
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
skipped += 1; // Neon/pg_cron/partman-only — irrelevant to the engine tables.
|
|
104
|
+
try {
|
|
105
|
+
await client.exec('ROLLBACK');
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
/* no transaction open */
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return skipped;
|
|
114
|
+
}
|
|
115
|
+
/** Attach a DEFAULT partition to each partitioned parent (idempotent). */
|
|
116
|
+
async function ensureDefaultPartitions(client) {
|
|
117
|
+
for (const table of PARTITIONED_TABLES) {
|
|
118
|
+
if (!(await tableExists(client, table)))
|
|
119
|
+
continue;
|
|
120
|
+
try {
|
|
121
|
+
await client.exec(`CREATE TABLE IF NOT EXISTS ${table}_default PARTITION OF ${table} DEFAULT;`);
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
// Already partitioned by partman, or not actually partitioned in this
|
|
125
|
+
// build — either way rows can land. Clear any aborted tx state.
|
|
126
|
+
try {
|
|
127
|
+
await client.exec('ROLLBACK');
|
|
128
|
+
}
|
|
129
|
+
catch {
|
|
130
|
+
/* no transaction open */
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
/** Insert the fixed local customer if absent. */
|
|
136
|
+
async function seedLocalCustomer(db) {
|
|
137
|
+
await db
|
|
138
|
+
.insert(customers)
|
|
139
|
+
.values({ id: LOCAL_CUSTOMER_ID, email: LOCAL_CUSTOMER_EMAIL, plan: 'free' })
|
|
140
|
+
.onConflictDoNothing();
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Split a migration file into individual statements, respecting `$tag$…$tag$`
|
|
144
|
+
* dollar-quoted bodies (functions / DO blocks) so we don't split inside them.
|
|
145
|
+
* Ported verbatim from the QA real-DB harness.
|
|
146
|
+
*/
|
|
147
|
+
function splitSql(sqlText) {
|
|
148
|
+
const out = [];
|
|
149
|
+
let cur = '';
|
|
150
|
+
let dollarTag = null;
|
|
151
|
+
let inLine = false; // -- line comment
|
|
152
|
+
let inBlock = false; // /* block comment */
|
|
153
|
+
let inStr = false; // '...' string literal
|
|
154
|
+
for (let i = 0; i < sqlText.length; i++) {
|
|
155
|
+
const ch = sqlText[i];
|
|
156
|
+
const next = sqlText[i + 1];
|
|
157
|
+
if (inLine) {
|
|
158
|
+
cur += ch;
|
|
159
|
+
if (ch === '\n')
|
|
160
|
+
inLine = false;
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
if (inBlock) {
|
|
164
|
+
cur += ch;
|
|
165
|
+
if (ch === '*' && next === '/') {
|
|
166
|
+
cur += next;
|
|
167
|
+
i += 1;
|
|
168
|
+
inBlock = false;
|
|
169
|
+
}
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
if (inStr) {
|
|
173
|
+
cur += ch;
|
|
174
|
+
if (ch === "'") {
|
|
175
|
+
if (next === "'") {
|
|
176
|
+
cur += next;
|
|
177
|
+
i += 1;
|
|
178
|
+
}
|
|
179
|
+
else
|
|
180
|
+
inStr = false;
|
|
181
|
+
}
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
if (dollarTag) {
|
|
185
|
+
if (ch === '$') {
|
|
186
|
+
const m = sqlText.slice(i).match(/^\$[A-Za-z0-9_]*\$/);
|
|
187
|
+
if (m && m[0] === dollarTag) {
|
|
188
|
+
cur += m[0];
|
|
189
|
+
i += m[0].length - 1;
|
|
190
|
+
dollarTag = null;
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
cur += ch;
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
// Not inside any comment/string/dollar-quote:
|
|
198
|
+
if (ch === '-' && next === '-') {
|
|
199
|
+
inLine = true;
|
|
200
|
+
cur += ch;
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
203
|
+
if (ch === '/' && next === '*') {
|
|
204
|
+
inBlock = true;
|
|
205
|
+
cur += ch;
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
if (ch === "'") {
|
|
209
|
+
inStr = true;
|
|
210
|
+
cur += ch;
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
if (ch === '$') {
|
|
214
|
+
const m = sqlText.slice(i).match(/^\$[A-Za-z0-9_]*\$/);
|
|
215
|
+
if (m) {
|
|
216
|
+
dollarTag = m[0];
|
|
217
|
+
cur += m[0];
|
|
218
|
+
i += m[0].length - 1;
|
|
219
|
+
continue;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
if (ch === ';') {
|
|
223
|
+
out.push(cur);
|
|
224
|
+
cur = '';
|
|
225
|
+
continue;
|
|
226
|
+
}
|
|
227
|
+
cur += ch;
|
|
228
|
+
}
|
|
229
|
+
if (cur.trim())
|
|
230
|
+
out.push(cur);
|
|
231
|
+
return out;
|
|
232
|
+
}
|
|
233
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@bluefields/cli",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Bluefield — git for web data. A local-first CLI + library that snapshots web pages into a content-addressed store on your own disk and signs each capture with an offline-verifiable Ed25519 provenance manifest. No server, no account, no telemetry.",
|
|
5
|
+
"license": "AGPL-3.0-or-later",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "dist/index.js",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"bin": {
|
|
10
|
+
"bf": "dist/cli.js",
|
|
11
|
+
"bluefields": "dist/cli.js"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"dist",
|
|
15
|
+
"README.md",
|
|
16
|
+
"LICENSE"
|
|
17
|
+
],
|
|
18
|
+
"engines": {
|
|
19
|
+
"node": ">=22"
|
|
20
|
+
},
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "https://github.com/danielvhofmann/bluefield.git",
|
|
24
|
+
"directory": "packages/cli"
|
|
25
|
+
},
|
|
26
|
+
"keywords": [
|
|
27
|
+
"bluefield",
|
|
28
|
+
"web-scraping",
|
|
29
|
+
"provenance",
|
|
30
|
+
"attestation",
|
|
31
|
+
"content-addressed",
|
|
32
|
+
"snapshot",
|
|
33
|
+
"watch",
|
|
34
|
+
"diff",
|
|
35
|
+
"local-first",
|
|
36
|
+
"offline",
|
|
37
|
+
"ed25519",
|
|
38
|
+
"git-for-web-data",
|
|
39
|
+
"mcp"
|
|
40
|
+
],
|
|
41
|
+
"publishConfig": {
|
|
42
|
+
"access": "public"
|
|
43
|
+
},
|
|
44
|
+
"dependencies": {
|
|
45
|
+
"@electric-sql/pglite": "^0.5.3",
|
|
46
|
+
"drizzle-orm": "0.36.4",
|
|
47
|
+
"@bluefields/attest": "0.2.0",
|
|
48
|
+
"@bluefields/db": "0.2.0",
|
|
49
|
+
"@bluefields/extractor": "0.2.0",
|
|
50
|
+
"@bluefields/fetcher": "0.2.0",
|
|
51
|
+
"@bluefields/differ": "0.2.0",
|
|
52
|
+
"@bluefields/primitives": "0.2.0"
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"@types/node": "22.9.0"
|
|
56
|
+
},
|
|
57
|
+
"scripts": {
|
|
58
|
+
"build": "tsc -p .",
|
|
59
|
+
"start": "tsx src/cli.ts",
|
|
60
|
+
"typecheck": "tsc --noEmit -p .",
|
|
61
|
+
"test": "vitest run"
|
|
62
|
+
}
|
|
63
|
+
}
|