codequill 0.8.1-beta.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 +21 -0
- package/README.md +121 -0
- package/dist/commands/attest.js +442 -0
- package/dist/commands/attest.js.map +1 -0
- package/dist/commands/backup.js +370 -0
- package/dist/commands/backup.js.map +1 -0
- package/dist/commands/claim.js +104 -0
- package/dist/commands/claim.js.map +1 -0
- package/dist/commands/log.js +188 -0
- package/dist/commands/log.js.map +1 -0
- package/dist/commands/login.js +147 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/prove.js +244 -0
- package/dist/commands/prove.js.map +1 -0
- package/dist/commands/publish.js +243 -0
- package/dist/commands/publish.js.map +1 -0
- package/dist/commands/pull.js +174 -0
- package/dist/commands/pull.js.map +1 -0
- package/dist/commands/quota.js +94 -0
- package/dist/commands/quota.js.map +1 -0
- package/dist/commands/revoke.js +97 -0
- package/dist/commands/revoke.js.map +1 -0
- package/dist/commands/snapshot.js +128 -0
- package/dist/commands/snapshot.js.map +1 -0
- package/dist/commands/status.js +234 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/verifyAttestation.js +212 -0
- package/dist/commands/verifyAttestation.js.map +1 -0
- package/dist/commands/verifyProof.js +145 -0
- package/dist/commands/verifyProof.js.map +1 -0
- package/dist/commands/wait.js +36 -0
- package/dist/commands/wait.js.map +1 -0
- package/dist/commands/who.js +55 -0
- package/dist/commands/who.js.map +1 -0
- package/dist/commands/why.js +412 -0
- package/dist/commands/why.js.map +1 -0
- package/dist/index.js +50 -0
- package/dist/index.js.map +1 -0
- package/dist/launcher.js +69 -0
- package/dist/launcher.js.map +1 -0
- package/dist/services/api.js +51 -0
- package/dist/services/api.js.map +1 -0
- package/dist/services/apiClient.js +166 -0
- package/dist/services/apiClient.js.map +1 -0
- package/dist/services/authStore.js +84 -0
- package/dist/services/authStore.js.map +1 -0
- package/dist/services/config.js +19 -0
- package/dist/services/config.js.map +1 -0
- package/dist/services/confirm.js +58 -0
- package/dist/services/confirm.js.map +1 -0
- package/dist/services/crypto.js +38 -0
- package/dist/services/crypto.js.map +1 -0
- package/dist/services/errors.js +17 -0
- package/dist/services/errors.js.map +1 -0
- package/dist/services/fs.js +25 -0
- package/dist/services/fs.js.map +1 -0
- package/dist/services/git.js +121 -0
- package/dist/services/git.js.map +1 -0
- package/dist/services/manifests/attestationManifest.js +35 -0
- package/dist/services/manifests/attestationManifest.js.map +1 -0
- package/dist/services/manifests/proofManifest.js +151 -0
- package/dist/services/manifests/proofManifest.js.map +1 -0
- package/dist/services/manifests/snapshotManifest.js +214 -0
- package/dist/services/manifests/snapshotManifest.js.map +1 -0
- package/dist/services/merkle.js +92 -0
- package/dist/services/merkle.js.map +1 -0
- package/dist/services/paths.js +16 -0
- package/dist/services/paths.js.map +1 -0
- package/dist/services/snapshotIndex.js +401 -0
- package/dist/services/snapshotIndex.js.map +1 -0
- package/dist/services/txWaiter.js +84 -0
- package/dist/services/txWaiter.js.map +1 -0
- package/dist/services/ui.js +98 -0
- package/dist/services/ui.js.map +1 -0
- package/dist/services/utilities.js +45 -0
- package/dist/services/utilities.js.map +1 -0
- package/dist/services/zip.js +24 -0
- package/dist/services/zip.js.map +1 -0
- package/dist/types/api.js +2 -0
- package/dist/types/api.js.map +1 -0
- package/dist/version.js +7 -0
- package/dist/version.js.map +1 -0
- package/package.json +52 -0
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { ensureDir, fileExists } from "./fs.js";
|
|
4
|
+
export function defaultSnapshotIndexPaths() {
|
|
5
|
+
const codequillDir = '.codequill';
|
|
6
|
+
const snapshotsDir = path.join(codequillDir, 'snapshots');
|
|
7
|
+
return {
|
|
8
|
+
codequillDir,
|
|
9
|
+
snapshotsDir,
|
|
10
|
+
indexFile: path.join(snapshotsDir, 'index.json'),
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
function nowSec() {
|
|
14
|
+
return Math.floor(Date.now() / 1000);
|
|
15
|
+
}
|
|
16
|
+
function safeNum(n, fallback = 0) {
|
|
17
|
+
const v = typeof n === 'number' && Number.isFinite(n) ? n : fallback;
|
|
18
|
+
return v;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Atomic JSON write:
|
|
22
|
+
* - write tmp in same directory
|
|
23
|
+
* - rename over target
|
|
24
|
+
*/
|
|
25
|
+
async function writeJsonAtomic(filePath, obj) {
|
|
26
|
+
const dir = path.dirname(filePath);
|
|
27
|
+
await ensureDir(dir);
|
|
28
|
+
const tmp = `${filePath}.tmp`;
|
|
29
|
+
await fs.writeFile(tmp, JSON.stringify(obj, null, 2), 'utf8');
|
|
30
|
+
await fs.rename(tmp, filePath);
|
|
31
|
+
}
|
|
32
|
+
function sortNewestFirst(a, b) {
|
|
33
|
+
const ap = safeNum(a.published?.published_at, 0);
|
|
34
|
+
const bp = safeNum(b.published?.published_at, 0);
|
|
35
|
+
// Prefer published timestamp if exists; else fall back to manifest timestamp.
|
|
36
|
+
const at = ap > 0 ? ap : safeNum(a.timestamp, 0);
|
|
37
|
+
const bt = bp > 0 ? bp : safeNum(b.timestamp, 0);
|
|
38
|
+
if (bt !== at)
|
|
39
|
+
return bt - at;
|
|
40
|
+
// stable tie-breakers
|
|
41
|
+
const ar = String(a.merkle_root);
|
|
42
|
+
const br = String(b.merkle_root);
|
|
43
|
+
if (ar !== br)
|
|
44
|
+
return ar.localeCompare(br);
|
|
45
|
+
const af = String(a.file ?? '');
|
|
46
|
+
const bf = String(b.file ?? '');
|
|
47
|
+
return af.localeCompare(bf);
|
|
48
|
+
}
|
|
49
|
+
function computeLatest(idx) {
|
|
50
|
+
// latest.local: newest item that has a local file (local or pulled)
|
|
51
|
+
const localCandidate = idx.items
|
|
52
|
+
.filter((it) => it.file && (it.kind === 'local' || it.kind === 'pulled'))
|
|
53
|
+
.sort(sortNewestFirst)[0];
|
|
54
|
+
// latest.published: newest item that has published meta (could be remote-only)
|
|
55
|
+
const pubCandidate = idx.items
|
|
56
|
+
.filter((it) => !!it.published)
|
|
57
|
+
.sort(sortNewestFirst)[0];
|
|
58
|
+
idx.latest = {
|
|
59
|
+
local: localCandidate?.merkle_root ?? null,
|
|
60
|
+
published: pubCandidate?.merkle_root ?? null,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
async function readJsonFileSafe(filePathAbs) {
|
|
64
|
+
try {
|
|
65
|
+
const raw = await fs.readFile(filePathAbs, 'utf8');
|
|
66
|
+
if (!raw)
|
|
67
|
+
return null;
|
|
68
|
+
return JSON.parse(raw);
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
export class SnapshotIndex {
|
|
75
|
+
repoRoot;
|
|
76
|
+
repoName;
|
|
77
|
+
paths;
|
|
78
|
+
idx = null;
|
|
79
|
+
constructor(args) {
|
|
80
|
+
this.repoRoot = path.resolve(args.repoRoot);
|
|
81
|
+
this.repoName = args.repoName;
|
|
82
|
+
this.paths = args.paths ?? defaultSnapshotIndexPaths();
|
|
83
|
+
}
|
|
84
|
+
abs(rel) {
|
|
85
|
+
return path.join(this.repoRoot, rel);
|
|
86
|
+
}
|
|
87
|
+
get indexFileAbs() {
|
|
88
|
+
return this.abs(this.paths.indexFile);
|
|
89
|
+
}
|
|
90
|
+
get snapshotsDirAbs() {
|
|
91
|
+
return this.abs(this.paths.snapshotsDir);
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Load index if present & valid; otherwise rebuild from disk.
|
|
95
|
+
* Always ensures .codequill/snapshots exists.
|
|
96
|
+
*/
|
|
97
|
+
async load() {
|
|
98
|
+
await ensureDir(this.snapshotsDirAbs);
|
|
99
|
+
const file = this.indexFileAbs;
|
|
100
|
+
if (!(await fileExists(file))) {
|
|
101
|
+
// no index -> rebuild
|
|
102
|
+
this.idx = await this.rebuildFromDisk();
|
|
103
|
+
await this.save();
|
|
104
|
+
return this.idx;
|
|
105
|
+
}
|
|
106
|
+
const parsed = await readJsonFileSafe(file);
|
|
107
|
+
if (!parsed || parsed.version !== 'codequill-index:v1' || !Array.isArray(parsed.items) || typeof parsed.repo_name !== 'string') {
|
|
108
|
+
this.idx = await this.rebuildFromDisk();
|
|
109
|
+
await this.save();
|
|
110
|
+
return this.idx;
|
|
111
|
+
}
|
|
112
|
+
// Accept it, but still self-heal repo name & missing files quickly.
|
|
113
|
+
const idx = parsed;
|
|
114
|
+
idx.repo_name = this.repoName;
|
|
115
|
+
idx.updated_at = nowSec();
|
|
116
|
+
// Drop items pointing to missing files (they can come back on rebuild/pull)
|
|
117
|
+
idx.items = await this.filterMissingFiles(idx.items);
|
|
118
|
+
// Normalize roots + recompute latest/sort
|
|
119
|
+
idx.items = this.normalizeItems(idx.items);
|
|
120
|
+
idx.items.sort(sortNewestFirst);
|
|
121
|
+
computeLatest(idx);
|
|
122
|
+
this.idx = idx;
|
|
123
|
+
await this.save();
|
|
124
|
+
return idx;
|
|
125
|
+
}
|
|
126
|
+
get() {
|
|
127
|
+
if (!this.idx)
|
|
128
|
+
throw new Error('SnapshotIndex not loaded. Call await index.load() first.');
|
|
129
|
+
return this.idx;
|
|
130
|
+
}
|
|
131
|
+
async save() {
|
|
132
|
+
const idx = this.get();
|
|
133
|
+
idx.updated_at = nowSec();
|
|
134
|
+
idx.items = this.normalizeItems(idx.items);
|
|
135
|
+
idx.items.sort(sortNewestFirst);
|
|
136
|
+
computeLatest(idx);
|
|
137
|
+
await writeJsonAtomic(this.indexFileAbs, idx);
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Hard rebuild from disk (snapshot folder is the source of truth).
|
|
141
|
+
* This is safe to call anytime (index deleted/corrupt, etc).
|
|
142
|
+
*/
|
|
143
|
+
async rebuildFromDisk() {
|
|
144
|
+
await ensureDir(this.snapshotsDirAbs);
|
|
145
|
+
let entries = [];
|
|
146
|
+
try {
|
|
147
|
+
entries = await fs.readdir(this.snapshotsDirAbs);
|
|
148
|
+
}
|
|
149
|
+
catch {
|
|
150
|
+
entries = [];
|
|
151
|
+
}
|
|
152
|
+
const jsonFiles = entries
|
|
153
|
+
.filter((f) => f.toLowerCase().endsWith('.json'))
|
|
154
|
+
.filter((f) => f.toLowerCase() !== 'index.json');
|
|
155
|
+
const byRoot = new Map();
|
|
156
|
+
for (const fname of jsonFiles) {
|
|
157
|
+
const fileAbs = path.join(this.snapshotsDirAbs, fname);
|
|
158
|
+
const obj = await readJsonFileSafe(fileAbs);
|
|
159
|
+
if (!obj || typeof obj !== 'object')
|
|
160
|
+
continue;
|
|
161
|
+
const commit = String(obj.commit ?? '').trim();
|
|
162
|
+
const rootRaw = String(obj.merkle_root ?? '').trim();
|
|
163
|
+
const ts = safeNum(obj.timestamp, 0);
|
|
164
|
+
if (!rootRaw || !commit)
|
|
165
|
+
continue;
|
|
166
|
+
const relFile = path.join(this.paths.snapshotsDir, fname).split(path.sep).join('/');
|
|
167
|
+
const kind = fname.toLowerCase().startsWith('published-') ? 'pulled' : 'local';
|
|
168
|
+
const next = {
|
|
169
|
+
merkle_root: rootRaw,
|
|
170
|
+
commit,
|
|
171
|
+
timestamp: ts,
|
|
172
|
+
file: relFile,
|
|
173
|
+
kind,
|
|
174
|
+
published: null,
|
|
175
|
+
};
|
|
176
|
+
const existing = byRoot.get(rootRaw);
|
|
177
|
+
if (!existing) {
|
|
178
|
+
byRoot.set(rootRaw, next);
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
// ✅ Dedup rule: prefer LOCAL over PULLED, otherwise prefer newer timestamp
|
|
182
|
+
const existingScore = (existing.kind === 'local' ? 10 : 0) + safeNum(existing.timestamp, 0);
|
|
183
|
+
const nextScore = (next.kind === 'local' ? 10 : 0) + safeNum(next.timestamp, 0);
|
|
184
|
+
if (nextScore > existingScore) {
|
|
185
|
+
// keep published meta if it was already attached on the existing entry
|
|
186
|
+
byRoot.set(rootRaw, { ...next, published: existing.published ?? null });
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
const items = Array.from(byRoot.values());
|
|
190
|
+
const idx = {
|
|
191
|
+
version: 'codequill-index:v1',
|
|
192
|
+
repo_name: this.repoName,
|
|
193
|
+
updated_at: nowSec(),
|
|
194
|
+
items,
|
|
195
|
+
latest: { local: null, published: null },
|
|
196
|
+
};
|
|
197
|
+
idx.items = this.normalizeItems(idx.items);
|
|
198
|
+
idx.items.sort(sortNewestFirst);
|
|
199
|
+
computeLatest(idx);
|
|
200
|
+
this.idx = idx;
|
|
201
|
+
return idx;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Optional: enrich index with backend "published" list.
|
|
205
|
+
* - Matches by merkle_root (primary)
|
|
206
|
+
* - If a published snapshot exists but no local file exists, we add a remote-only item
|
|
207
|
+
* so `log --on-chain` can still show it.
|
|
208
|
+
*/
|
|
209
|
+
enrichFromBackend(published) {
|
|
210
|
+
const idx = this.get();
|
|
211
|
+
const byRoot = new Map();
|
|
212
|
+
for (const p of published) {
|
|
213
|
+
const r = p.merkle_root;
|
|
214
|
+
if (r)
|
|
215
|
+
byRoot.set(r, p);
|
|
216
|
+
}
|
|
217
|
+
// Attach to existing items
|
|
218
|
+
for (const it of idx.items) {
|
|
219
|
+
const p = byRoot.get(it.merkle_root);
|
|
220
|
+
if (!p)
|
|
221
|
+
continue;
|
|
222
|
+
it.published = {
|
|
223
|
+
snapshot_id: p.snapshot_id,
|
|
224
|
+
published_at: safeNum(p.published_at, 0),
|
|
225
|
+
tx_hash: p.tx_hash,
|
|
226
|
+
chain_id: p.chain_id,
|
|
227
|
+
manifest_cid: p.manifest_cid,
|
|
228
|
+
wallet_address: p.wallet_address,
|
|
229
|
+
};
|
|
230
|
+
// If file exists locally but was marked remote earlier, fix kind.
|
|
231
|
+
if (it.file && it.kind === 'remote') {
|
|
232
|
+
it.kind = it.file.toLowerCase().includes('published-') ? 'pulled' : 'local';
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
// Add remote-only items for published snapshots not present locally
|
|
236
|
+
const localRoots = new Set(idx.items.map((x) => x.merkle_root).filter(Boolean));
|
|
237
|
+
for (const p of published) {
|
|
238
|
+
const r = p.merkle_root;
|
|
239
|
+
if (!r || localRoots.has(r))
|
|
240
|
+
continue;
|
|
241
|
+
idx.items.push({
|
|
242
|
+
merkle_root: r,
|
|
243
|
+
commit: String(p.commit_hash ?? '').trim(),
|
|
244
|
+
timestamp: 0,
|
|
245
|
+
file: null,
|
|
246
|
+
kind: 'remote',
|
|
247
|
+
published: {
|
|
248
|
+
snapshot_id: p.snapshot_id,
|
|
249
|
+
published_at: safeNum(p.published_at, 0),
|
|
250
|
+
tx_hash: p.tx_hash,
|
|
251
|
+
chain_id: p.chain_id,
|
|
252
|
+
manifest_cid: p.manifest_cid,
|
|
253
|
+
wallet_address: p.wallet_address,
|
|
254
|
+
},
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
idx.items = this.normalizeItems(idx.items);
|
|
258
|
+
idx.items.sort(sortNewestFirst);
|
|
259
|
+
computeLatest(idx);
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Convenience: after you write a manifest file (snapshot/pull),
|
|
263
|
+
* call this to upsert the disk item without scanning the whole folder.
|
|
264
|
+
* (Still safe even if you forget; rebuildFromDisk will fix.)
|
|
265
|
+
*/
|
|
266
|
+
upsertFromManifestFile(args) {
|
|
267
|
+
const idx = this.get();
|
|
268
|
+
const commit = String(args.manifest?.commit ?? '').trim();
|
|
269
|
+
const root = String(args.manifest?.merkle_root ?? '').trim();
|
|
270
|
+
const ts = safeNum(args.manifest?.timestamp, 0);
|
|
271
|
+
if (!commit || !root)
|
|
272
|
+
return;
|
|
273
|
+
const kind = args.kind ?? 'local';
|
|
274
|
+
const file = String(args.manifestFileRel ?? '').split(path.sep).join('/');
|
|
275
|
+
// ✅ Uniqueness by file path
|
|
276
|
+
const existingIdx = idx.items.findIndex((it) => {
|
|
277
|
+
if (!it.file)
|
|
278
|
+
return false;
|
|
279
|
+
const f = String(it.file).split(path.sep).join('/');
|
|
280
|
+
return f === file;
|
|
281
|
+
});
|
|
282
|
+
if (existingIdx >= 0) {
|
|
283
|
+
const existing = idx.items[existingIdx];
|
|
284
|
+
// 🚫 If that indexed file is already published, do NOT replace it
|
|
285
|
+
if (existing.published) {
|
|
286
|
+
throw new Error(`Refusing to overwrite a published snapshot in the index.\n` +
|
|
287
|
+
`File: ${file}\n` +
|
|
288
|
+
`Published snapshot_id: ${existing.published.snapshot_id}\n` +
|
|
289
|
+
`Tip: create a new snapshot for a different commit, or publish a different manifest file.`);
|
|
290
|
+
}
|
|
291
|
+
// Replace/update the existing local entry for that file
|
|
292
|
+
idx.items[existingIdx] = {
|
|
293
|
+
...existing,
|
|
294
|
+
merkle_root: root,
|
|
295
|
+
commit,
|
|
296
|
+
timestamp: ts,
|
|
297
|
+
file,
|
|
298
|
+
kind,
|
|
299
|
+
published: null, // stays unpublished
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
else {
|
|
303
|
+
idx.items.push({
|
|
304
|
+
merkle_root: root,
|
|
305
|
+
commit,
|
|
306
|
+
timestamp: ts,
|
|
307
|
+
file,
|
|
308
|
+
kind,
|
|
309
|
+
published: null,
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
idx.items = this.normalizeItems(idx.items);
|
|
313
|
+
idx.items.sort(sortNewestFirst);
|
|
314
|
+
computeLatest(idx);
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Convenience: after publish succeeds, attach published meta by merkle_root.
|
|
318
|
+
*/
|
|
319
|
+
attachPublishedByRoot(args) {
|
|
320
|
+
const idx = this.get();
|
|
321
|
+
const r = args.merkle_root;
|
|
322
|
+
if (!r)
|
|
323
|
+
return;
|
|
324
|
+
const item = idx.items.find((x) => x.merkle_root === r);
|
|
325
|
+
if (item) {
|
|
326
|
+
item.published = args.meta;
|
|
327
|
+
}
|
|
328
|
+
else {
|
|
329
|
+
// If we don't have the manifest locally, still record as remote-only
|
|
330
|
+
idx.items.push({
|
|
331
|
+
merkle_root: r,
|
|
332
|
+
commit: '',
|
|
333
|
+
timestamp: 0,
|
|
334
|
+
file: null,
|
|
335
|
+
kind: 'remote',
|
|
336
|
+
published: args.meta,
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
idx.items = this.normalizeItems(idx.items);
|
|
340
|
+
idx.items.sort(sortNewestFirst);
|
|
341
|
+
computeLatest(idx);
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Helper for status/log: list items (already sorted after load/save).
|
|
345
|
+
*/
|
|
346
|
+
list() {
|
|
347
|
+
return this.get().items;
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Quick accessors
|
|
351
|
+
*/
|
|
352
|
+
latestLocalRoot() {
|
|
353
|
+
return this.get().latest.local ?? null;
|
|
354
|
+
}
|
|
355
|
+
latestPublishedRoot() {
|
|
356
|
+
return this.get().latest.published ?? null;
|
|
357
|
+
}
|
|
358
|
+
// ------------------------
|
|
359
|
+
// internal helpers
|
|
360
|
+
// ------------------------
|
|
361
|
+
normalizeItems(items) {
|
|
362
|
+
return items
|
|
363
|
+
.map((it) => {
|
|
364
|
+
const mr = it.merkle_root;
|
|
365
|
+
return {
|
|
366
|
+
...it,
|
|
367
|
+
merkle_root: mr || (String(it.merkle_root ?? '')) || String(it.merkle_root ?? '').trim().toLowerCase(),
|
|
368
|
+
commit: String(it.commit ?? '').trim(),
|
|
369
|
+
timestamp: safeNum(it.timestamp, 0),
|
|
370
|
+
file: it.file ? String(it.file) : null,
|
|
371
|
+
kind: it.kind ?? (it.file ? 'local' : 'remote'),
|
|
372
|
+
published: it.published
|
|
373
|
+
? {
|
|
374
|
+
snapshot_id: String(it.published.snapshot_id),
|
|
375
|
+
published_at: safeNum(it.published.published_at, 0),
|
|
376
|
+
tx_hash: it.published.tx_hash ? String(it.published.tx_hash) : undefined,
|
|
377
|
+
chain_id: typeof it.published.chain_id === 'number' ? it.published.chain_id : undefined,
|
|
378
|
+
manifest_cid: it.published.manifest_cid ? String(it.published.manifest_cid) : undefined,
|
|
379
|
+
wallet_address: it.published.wallet_address ? String(it.published.wallet_address) : undefined,
|
|
380
|
+
}
|
|
381
|
+
: null,
|
|
382
|
+
};
|
|
383
|
+
})
|
|
384
|
+
.filter((it) => !!it.merkle_root); // require root
|
|
385
|
+
}
|
|
386
|
+
async filterMissingFiles(items) {
|
|
387
|
+
const out = [];
|
|
388
|
+
for (const it of items) {
|
|
389
|
+
if (!it.file) {
|
|
390
|
+
out.push(it);
|
|
391
|
+
continue;
|
|
392
|
+
}
|
|
393
|
+
const absP = this.abs(it.file);
|
|
394
|
+
if (await fileExists(absP))
|
|
395
|
+
out.push(it);
|
|
396
|
+
// if file missing, drop it; rebuild/pull can restore
|
|
397
|
+
}
|
|
398
|
+
return out;
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
//# sourceMappingURL=snapshotIndex.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshotIndex.js","sourceRoot":"","sources":["../../src/services/snapshotIndex.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { spinner, colors } from './ui.js';
|
|
2
|
+
import { apiClient } from './apiClient.js';
|
|
3
|
+
import { ApiError } from './errors.js';
|
|
4
|
+
/**
|
|
5
|
+
* Wait for a tx to be confirmed (or fail), using backend polling (seamless for npm CLI).
|
|
6
|
+
* Backend endpoint expected:
|
|
7
|
+
* GET /v1/cli/tx/:txHash?chain_id=137
|
|
8
|
+
*/
|
|
9
|
+
export async function waitForTxConfirmation(opts) {
|
|
10
|
+
const confirmationsTarget = Math.max(1, Number(opts.confirmations ?? 1));
|
|
11
|
+
const pollIntervalMs = Math.max(500, Number(opts.pollIntervalMs ?? 3000));
|
|
12
|
+
const timeoutMs = Math.max(10_000, Number(opts.timeoutMs ?? 5 * 60_000));
|
|
13
|
+
const endpointBase = (opts.endpointBase ?? '/v1/cli/tx').replace(/\/+$/, '');
|
|
14
|
+
const txHash = String(opts.txHash);
|
|
15
|
+
const s = spinner(`Waiting for confirmation (${confirmationsTarget}+ conf)…`, opts.silent);
|
|
16
|
+
const started = Date.now();
|
|
17
|
+
let last = null;
|
|
18
|
+
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
19
|
+
try {
|
|
20
|
+
while (true) {
|
|
21
|
+
const elapsed = Date.now() - started;
|
|
22
|
+
if (elapsed > timeoutMs) {
|
|
23
|
+
s.fail(colors.warn('Timed out waiting for confirmation.'));
|
|
24
|
+
const hint = last?.explorer_url ? `\nExplorer: ${last.explorer_url}` : '';
|
|
25
|
+
throw new Error(`Timeout waiting for tx ${txHash}.${hint}`);
|
|
26
|
+
}
|
|
27
|
+
let res;
|
|
28
|
+
try {
|
|
29
|
+
res = await apiClient.get(`${endpointBase}/${txHash}`);
|
|
30
|
+
last = res;
|
|
31
|
+
}
|
|
32
|
+
catch (e) {
|
|
33
|
+
// If backend endpoint not implemented yet, make this error helpful
|
|
34
|
+
if (e instanceof ApiError) {
|
|
35
|
+
s.fail(colors.error('Failed to check tx status.'));
|
|
36
|
+
const extra = [
|
|
37
|
+
`Status: ${e.status}`,
|
|
38
|
+
e.requestId ? `Request ID: ${e.requestId}` : null,
|
|
39
|
+
e.method && e.url ? `Endpoint: ${e.method} ${e.url}` : null,
|
|
40
|
+
'',
|
|
41
|
+
'Hint: backend needs a tx status endpoint:',
|
|
42
|
+
` GET ${endpointBase}/:txHash?chain_id=<id>`,
|
|
43
|
+
].filter(Boolean).join('\n');
|
|
44
|
+
throw new Error(`${e.message}\n${extra}`);
|
|
45
|
+
}
|
|
46
|
+
s.fail(colors.error('Failed to check tx status.'));
|
|
47
|
+
throw e;
|
|
48
|
+
}
|
|
49
|
+
if (res.status === 'failed') {
|
|
50
|
+
s.fail(colors.error('Transaction failed.'));
|
|
51
|
+
const reason = res.reason ? `\nReason: ${res.reason}` : '';
|
|
52
|
+
const hint = res.explorer_url ? `\nExplorer: ${res.explorer_url}` : '';
|
|
53
|
+
throw new Error(`Tx failed: ${txHash}.${reason}${hint}`);
|
|
54
|
+
}
|
|
55
|
+
if (res.status === 'confirmed') {
|
|
56
|
+
const confNow = Number(res.confirmations ?? confirmationsTarget);
|
|
57
|
+
if (confNow >= confirmationsTarget) {
|
|
58
|
+
const blockTxt = res.block_number ? `block ${res.block_number}` : 'confirmed';
|
|
59
|
+
s.succeed(colors.success(`Confirmed (${blockTxt})`));
|
|
60
|
+
return res;
|
|
61
|
+
}
|
|
62
|
+
s.text = `Waiting for confirmation (${confNow}/${confirmationsTarget})…`;
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
// pending
|
|
66
|
+
const confNow = Number(res.confirmations ?? 0);
|
|
67
|
+
s.text = confNow > 0
|
|
68
|
+
? `Waiting for confirmation (${confNow}/${confirmationsTarget})…`
|
|
69
|
+
: `Waiting for transaction to be mined…`;
|
|
70
|
+
}
|
|
71
|
+
const waitMs = Math.max(500, Number(res.next_poll_ms ?? pollIntervalMs));
|
|
72
|
+
await sleep(waitMs);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
catch (e) {
|
|
76
|
+
// ensure spinner stops
|
|
77
|
+
try {
|
|
78
|
+
s.stop();
|
|
79
|
+
}
|
|
80
|
+
catch { }
|
|
81
|
+
throw e;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=txWaiter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"txWaiter.js","sourceRoot":"","sources":["../../src/services/txWaiter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import kleur from 'kleur';
|
|
2
|
+
import ora from 'ora';
|
|
3
|
+
import { spawn } from 'node:child_process';
|
|
4
|
+
export const colors = {
|
|
5
|
+
success: (s) => kleur.green(s),
|
|
6
|
+
error: (s) => kleur.red(s),
|
|
7
|
+
warn: (s) => kleur.yellow(s),
|
|
8
|
+
info: (s) => kleur.cyan(s),
|
|
9
|
+
bold: (s) => kleur.bold(s),
|
|
10
|
+
dim: (s) => kleur.dim(s),
|
|
11
|
+
};
|
|
12
|
+
export function spinner(text, silent) {
|
|
13
|
+
const s = ora({ text, spinner: 'dots' });
|
|
14
|
+
if (silent) {
|
|
15
|
+
// @ts-ignore
|
|
16
|
+
s.start = () => s;
|
|
17
|
+
// @ts-ignore
|
|
18
|
+
s.stop = () => s;
|
|
19
|
+
// @ts-ignore
|
|
20
|
+
s.succeed = () => s;
|
|
21
|
+
// @ts-ignore
|
|
22
|
+
s.fail = () => s;
|
|
23
|
+
// @ts-ignore
|
|
24
|
+
s.stopAndPersist = () => s;
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
s.start();
|
|
28
|
+
}
|
|
29
|
+
return s;
|
|
30
|
+
}
|
|
31
|
+
export function shortAddr(a) {
|
|
32
|
+
const x = String(a || '').trim();
|
|
33
|
+
if (!x)
|
|
34
|
+
return '—';
|
|
35
|
+
if (x.length <= 18)
|
|
36
|
+
return x;
|
|
37
|
+
return `${x.slice(0, 6)}...${x.slice(-4)}`;
|
|
38
|
+
}
|
|
39
|
+
export function shortHash(hash, length = 12) {
|
|
40
|
+
const s = String(hash ?? '');
|
|
41
|
+
return s.length > length ? s.slice(0, length) : s;
|
|
42
|
+
}
|
|
43
|
+
export function shortCommit(commit, length = 12) {
|
|
44
|
+
const s = String(commit ?? '').trim();
|
|
45
|
+
return s.length > 12 ? s.slice(0, 12) : s;
|
|
46
|
+
}
|
|
47
|
+
export function fmtTime(ts) {
|
|
48
|
+
if (!ts || !Number.isFinite(ts))
|
|
49
|
+
return '—';
|
|
50
|
+
try {
|
|
51
|
+
return new Date(ts * 1000).toISOString().replace('T', ' ').replace('.000Z', ' UTC');
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
return '—';
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
export function relativeTime(ts) {
|
|
58
|
+
const now = Math.floor(Date.now() / 1000);
|
|
59
|
+
const diff = Math.max(0, now - ts);
|
|
60
|
+
const min = Math.floor(diff / 60);
|
|
61
|
+
const hr = Math.floor(diff / 3600);
|
|
62
|
+
const day = Math.floor(diff / 86400);
|
|
63
|
+
const wk = Math.floor(diff / 604800);
|
|
64
|
+
if (diff < 60)
|
|
65
|
+
return 'just now';
|
|
66
|
+
if (min < 60)
|
|
67
|
+
return `${min} min ago`;
|
|
68
|
+
if (hr < 48)
|
|
69
|
+
return `${hr} hour${hr === 1 ? '' : 's'} ago`;
|
|
70
|
+
if (day < 14)
|
|
71
|
+
return `${day} day${day === 1 ? '' : 's'} ago`;
|
|
72
|
+
return `${wk} week${wk === 1 ? '' : 's'} ago`;
|
|
73
|
+
}
|
|
74
|
+
export function tryOpenBrowser(url) {
|
|
75
|
+
const platform = process.platform;
|
|
76
|
+
let cmd;
|
|
77
|
+
let args = [];
|
|
78
|
+
if (platform === 'darwin') {
|
|
79
|
+
cmd = 'open';
|
|
80
|
+
args = [url];
|
|
81
|
+
}
|
|
82
|
+
else if (platform === 'win32') {
|
|
83
|
+
cmd = 'cmd';
|
|
84
|
+
args = ['/c', 'start', '""', url];
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
cmd = 'xdg-open';
|
|
88
|
+
args = [url];
|
|
89
|
+
}
|
|
90
|
+
try {
|
|
91
|
+
const child = spawn(cmd, args, { stdio: 'ignore', detached: true });
|
|
92
|
+
child.unref();
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
// ignore
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=ui.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui.js","sourceRoot":"","sources":["../../src/services/ui.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { isExpired, loadTokens } from "./authStore.js";
|
|
2
|
+
import { colors } from "./ui.js";
|
|
3
|
+
import { getConfigFilePath } from "./config.js";
|
|
4
|
+
import { randomBytes } from "node:crypto";
|
|
5
|
+
import { createRequire } from "node:module";
|
|
6
|
+
export function assertAuthenticated() {
|
|
7
|
+
const tokens = loadTokens();
|
|
8
|
+
if (!tokens) {
|
|
9
|
+
console.error(colors.error('Not logged in. Run `codequill login` first.'));
|
|
10
|
+
console.error(colors.dim(`No tokens found at: ${getConfigFilePath()}`));
|
|
11
|
+
process.exitCode = 1;
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
if (isExpired(tokens) && !tokens.refresh_token) {
|
|
15
|
+
console.error(colors.error('Session expired. Run `codequill login` to re-authenticate.'));
|
|
16
|
+
console.error(colors.dim(`Token file: ${getConfigFilePath()}`));
|
|
17
|
+
process.exitCode = 1;
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
export function getCliVersion() {
|
|
23
|
+
// ESM-safe way to read package.json
|
|
24
|
+
try {
|
|
25
|
+
const require = createRequire(import.meta.url);
|
|
26
|
+
const pkg = require('../../package.json');
|
|
27
|
+
return String(pkg?.version ?? 'unknown');
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return 'unknown';
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
export function randomSaltHex32() {
|
|
34
|
+
return randomBytes(32).toString('hex');
|
|
35
|
+
}
|
|
36
|
+
export function chainName(chainId) {
|
|
37
|
+
if (!chainId || !Number.isFinite(chainId))
|
|
38
|
+
return null;
|
|
39
|
+
if (chainId === 11155111)
|
|
40
|
+
return 'Sepolia Testnet';
|
|
41
|
+
if (chainId === 1)
|
|
42
|
+
return 'Ethereum Mainnet';
|
|
43
|
+
return `chain ${chainId}`;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=utilities.js.map
|