@iqlabs-official/git-sdk 0.1.7 → 0.1.10
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/dist/browser/index.d.ts +1 -1
- package/dist/browser/index.js +14 -28
- package/dist/browser/index.js.map +1 -1
- package/dist/node/index.d.ts +1 -1
- package/dist/node/index.js +14 -28
- package/dist/node/index.js.map +1 -1
- package/dist/shared/index.d.ts +7 -12
- package/dist/shared/index.js +14 -28
- package/dist/shared/index.js.map +1 -1
- package/package.json +3 -3
package/dist/browser/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { Commit, FileTree, GitClient, GitClientConfig, IQGIT_ROOT_ID, REGISTRY_HINT, RegistryEntry, Repository, WriteEvent, bootstrapRegistry, commitTableHint, getGatewayUrls, loadBlob, loadTree, readCommitHistory,
|
|
1
|
+
export { Commit, FileTree, GitClient, GitClientConfig, IQGIT_ROOT_ID, REGISTRY_HINT, RegistryEntry, Repository, WriteEvent, bootstrapRegistry, commitTableHint, commitTablePda, getGatewayUrls, loadBlob, loadTree, readCommitHistory, readLatestCommit, readOwnerRepos, readRegistryPage, repoListHint, setGatewayUrls, setNetwork, uploadBlob, uploadTree, writeCommit } from '../shared/index.js';
|
|
2
2
|
export { SignerInput } from '@iqlabs-official/solana-sdk/utils';
|
|
3
3
|
import '@solana/web3.js';
|
package/dist/browser/index.js
CHANGED
|
@@ -152,10 +152,6 @@ async function readRowsByPda(pda, options) {
|
|
|
152
152
|
if (viaGateway !== null) return viaGateway;
|
|
153
153
|
return readTableRows(pda, options);
|
|
154
154
|
}
|
|
155
|
-
async function readLatestRow(hint) {
|
|
156
|
-
const rows = await readRows(hint, { limit: 1 });
|
|
157
|
-
return rows[0] ?? null;
|
|
158
|
-
}
|
|
159
155
|
async function codeIn(connection, signer, data, filename, filetype, onProgress, speed = "light") {
|
|
160
156
|
return codeIn$1(
|
|
161
157
|
{ connection, signer },
|
|
@@ -216,15 +212,14 @@ async function writeCommit(connection, signer, repo, commit) {
|
|
|
216
212
|
notifyGateways(tablePda(hint).toBase58(), sig, commit, owner);
|
|
217
213
|
return sig;
|
|
218
214
|
}
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
return row;
|
|
215
|
+
function commitTablePda(owner, repo) {
|
|
216
|
+
return tablePda(commitTableHint(owner, repo));
|
|
222
217
|
}
|
|
223
|
-
async function
|
|
224
|
-
const rows = await
|
|
225
|
-
return rows;
|
|
218
|
+
async function readLatestCommit(pda) {
|
|
219
|
+
const rows = await readRowsByPda(pda, { limit: 1 });
|
|
220
|
+
return rows[0] ?? null;
|
|
226
221
|
}
|
|
227
|
-
async function
|
|
222
|
+
async function readCommitHistory(pda, options) {
|
|
228
223
|
const rows = await readRowsByPda(pda, options);
|
|
229
224
|
return rows;
|
|
230
225
|
}
|
|
@@ -359,7 +354,7 @@ var GitClient = class {
|
|
|
359
354
|
async commit(repoName, message, scan) {
|
|
360
355
|
const { connection, signer } = this.cfg;
|
|
361
356
|
const owner = signer.publicKey.toBase58();
|
|
362
|
-
const latest = await readLatestCommit(
|
|
357
|
+
const latest = await readLatestCommit(commitTablePda(owner, repoName));
|
|
363
358
|
const oldTree = latest ? await loadTree(latest.treeTxId) : {};
|
|
364
359
|
const newTree = {};
|
|
365
360
|
for (const [path, content] of Object.entries(scan)) {
|
|
@@ -403,11 +398,12 @@ var GitClient = class {
|
|
|
403
398
|
async checkout(repoName, commitId, sink) {
|
|
404
399
|
const { connection, signer } = this.cfg;
|
|
405
400
|
const owner = signer.publicKey.toBase58();
|
|
401
|
+
const pda = commitTablePda(owner, repoName);
|
|
406
402
|
let target;
|
|
407
403
|
if (commitId === "latest") {
|
|
408
|
-
target = await readLatestCommit(
|
|
404
|
+
target = await readLatestCommit(pda);
|
|
409
405
|
} else {
|
|
410
|
-
const history = await readCommitHistory(
|
|
406
|
+
const history = await readCommitHistory(pda);
|
|
411
407
|
target = history.find((c) => c.id === commitId) ?? null;
|
|
412
408
|
}
|
|
413
409
|
if (!target) {
|
|
@@ -426,8 +422,7 @@ var GitClient = class {
|
|
|
426
422
|
* equal owner for reads.
|
|
427
423
|
*/
|
|
428
424
|
async clone(repoName, owner, sink) {
|
|
429
|
-
const
|
|
430
|
-
const target = await readLatestCommit(connection, owner, repoName);
|
|
425
|
+
const target = await readLatestCommit(commitTablePda(owner, repoName));
|
|
431
426
|
if (!target) {
|
|
432
427
|
throw new Error(`no commits in ${owner}/${repoName}`);
|
|
433
428
|
}
|
|
@@ -440,22 +435,13 @@ var GitClient = class {
|
|
|
440
435
|
}
|
|
441
436
|
/** Commit history for a repo. */
|
|
442
437
|
async log(owner, repoName, options) {
|
|
443
|
-
return readCommitHistory(
|
|
444
|
-
this.cfg.connection,
|
|
445
|
-
owner,
|
|
446
|
-
repoName,
|
|
447
|
-
options
|
|
448
|
-
);
|
|
438
|
+
return readCommitHistory(commitTablePda(owner, repoName), options);
|
|
449
439
|
}
|
|
450
440
|
/**
|
|
451
441
|
* Compare a current directory snapshot to the latest commit's tree.
|
|
452
442
|
*/
|
|
453
443
|
async status(owner, repoName, scan) {
|
|
454
|
-
const latest = await readLatestCommit(
|
|
455
|
-
this.cfg.connection,
|
|
456
|
-
owner,
|
|
457
|
-
repoName
|
|
458
|
-
);
|
|
444
|
+
const latest = await readLatestCommit(commitTablePda(owner, repoName));
|
|
459
445
|
const tree = latest ? await loadTree(latest.treeTxId) : {};
|
|
460
446
|
const added = [];
|
|
461
447
|
const modified = [];
|
|
@@ -476,6 +462,6 @@ var GitClient = class {
|
|
|
476
462
|
// src/browser.ts
|
|
477
463
|
setSha256(hashBrowser);
|
|
478
464
|
|
|
479
|
-
export { GitClient, IQGIT_ROOT_ID, REGISTRY_HINT, bootstrapRegistry, commitTableHint, getGatewayUrls, loadBlob, loadTree, readCommitHistory,
|
|
465
|
+
export { GitClient, IQGIT_ROOT_ID, REGISTRY_HINT, bootstrapRegistry, commitTableHint, commitTablePda, getGatewayUrls, loadBlob, loadTree, readCommitHistory, readLatestCommit, readOwnerRepos, readRegistryPage, repoListHint, setGatewayUrls, setNetwork, uploadBlob, uploadTree, writeCommit };
|
|
480
466
|
//# sourceMappingURL=index.js.map
|
|
481
467
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/core/hash.ts","../../src/platform/hash-browser.ts","../../src/core/seed.ts","../../src/layers/gateway.ts","../../src/layers/chain.ts","../../src/layers/commit.ts","../../src/layers/repo.ts","../../src/layers/storage.ts","../../src/layers/client.ts","../../src/browser.ts"],"names":["sdkCodeIn","sdkReadCodeIn","createTable","writeRow","tablePda"],"mappings":";;;;;;;;AAiBA,IAAI,IAAA;AAEG,SAAS,UAAU,EAAA,EAAqB;AAC7C,EAAA,IAAI,IAAA,EAAM;AACR,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KACF;AAAA,EACF;AACA,EAAA,IAAA,GAAO,EAAA;AACT;AAEA,eAAsB,UAAU,KAAA,EAAgC;AAC9D,EAAA,IAAI,CAAC,IAAA,EAAM;AACT,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KACF;AAAA,EACF;AACA,EAAA,OAAO,KAAK,KAAK,CAAA;AACnB;;;AC9BO,IAAM,WAAA,GAAyB,OAAO,KAAA,KAAU;AACrD,EAAA,MAAM,KAAA,GAAQ,IAAI,WAAA,EAAY,CAAE,OAAO,KAAK,CAAA;AAC5C,EAAA,MAAM,MAAA,GAAS,MAAM,MAAA,CAAO,MAAA,CAAO,MAAA;AAAA,IACjC,SAAA;AAAA,IACA,KAAA,CAAM,OAAO,KAAA,CAAM,KAAA,CAAM,YAAY,KAAA,CAAM,UAAA,GAAa,MAAM,UAAU;AAAA,GAC1E;AACA,EAAA,OAAO,KAAA,CAAM,KAAK,IAAI,UAAA,CAAW,MAAM,CAAC,CAAA,CACrC,IAAI,CAAC,CAAA,KAAM,EAAE,QAAA,CAAS,EAAE,EAAE,QAAA,CAAS,CAAA,EAAG,GAAG,CAAC,CAAA,CAC1C,KAAK,EAAE,CAAA;AACZ,CAAA;;;ACJO,IAAM,aAAA,GAAgB;AAGtB,IAAM,aAAA,GAAgB;AAOtB,SAAS,aAAa,KAAA,EAAuB;AAClD,EAAA,OAAO,gBAAgB,KAAK,CAAA,CAAA;AAC9B;AAOO,SAAS,eAAA,CAAgB,OAAe,IAAA,EAAsB;AACnE,EAAA,OAAO,CAAA,YAAA,EAAe,KAAK,CAAA,CAAA,EAAI,IAAI,CAAA,CAAA;AACrC;ACZA,IAAM,eAAA,GAAkB,4BAAA;AACxB,IAAM,cAAA,GAAiB,gCAAA;AACvB,IAAM,cAAA,GAAiB,GAAA;AAEvB,IAAI,eAAA,GAAmC,IAAA;AACvC,IAAI,eAAA,GAA+C,IAAA;AAI5C,SAAS,eAAe,IAAA,EAAsB;AACnD,EAAA,eAAA,GAAkB,IAAA,CAAK,MAAA,GAAS,CAAA,GAAI,IAAA,GAAO,IAAA;AAC7C;AAIO,SAAS,WAAW,OAAA,EAAqC;AAC9D,EAAA,eAAA,GAAkB,OAAA;AACpB;AAEA,SAAS,YAAA,GAAqC;AAC5C,EAAA,IAAI,iBAAiB,OAAO,eAAA;AAC5B,EAAA,MAAM,CAAA,GAAI,SAAA,EAAU,CAAE,WAAA,EAAY;AAClC,EAAA,IAAI,CAAA,CAAE,SAAS,QAAQ,CAAA,IAAK,EAAE,QAAA,CAAS,SAAS,GAAG,OAAO,QAAA;AAC1D,EAAA,OAAO,SAAA;AACT;AAEO,SAAS,cAAA,GAA2B;AACzC,EAAA,IAAI,iBAAiB,OAAO,eAAA;AAE5B,EAAA,MAAM,OAAO,OAAO,OAAA,KAAY,WAAA,IAAe,OAAA,CAAQ,KAAK,cAAA,KAAmB,EAAA;AAC/E,EAAA,IAAI,GAAA,EAAK,OAAO,GAAA,CAAI,KAAA,CAAM,GAAG,CAAA,CAAE,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,IAAA,EAAM,CAAA,CAAE,OAAO,OAAO,CAAA;AAElE,EAAA,OAAO,cAAa,KAAM,QAAA,GAAW,CAAC,cAAc,CAAA,GAAI,CAAC,eAAe,CAAA;AAC1E;AAEA,eAAe,WAAA,CACb,MACA,KAAA,EACmB;AACnB,EAAA,KAAA,MAAW,EAAA,IAAM,gBAAe,EAAG;AACjC,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,GAAO,IAAI,eAAA,EAAgB;AACjC,MAAA,MAAM,QAAQ,UAAA,CAAW,MAAM,IAAA,CAAK,KAAA,IAAS,cAAc,CAAA;AAC3D,MAAA,MAAM,GAAA,GAAM,MAAM,KAAA,CAAM,IAAA,CAAK,EAAE,GAAG,EAAE,MAAA,EAAQ,IAAA,CAAK,MAAA,EAAQ,CAAA;AACzD,MAAA,YAAA,CAAa,KAAK,CAAA;AAClB,MAAA,IAAI,GAAA,CAAI,EAAA,EAAI,OAAO,MAAM,MAAM,GAAG,CAAA;AAAA,IACpC,CAAA,CAAA,MAAQ;AAAA,IAER;AAAA,EACF;AACA,EAAA,OAAO,IAAA;AACT;AAIA,eAAsB,kBAAA,CACpB,WACA,OAAA,EACgD;AAChD,EAAA,MAAM,EAAA,GAAK,IAAI,eAAA,EAAgB;AAC/B,EAAA,IAAI,OAAA,EAAS,OAAO,EAAA,CAAG,GAAA,CAAI,SAAS,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAC,CAAA;AACzD,EAAA,IAAI,SAAS,MAAA,EAAQ,EAAA,CAAG,GAAA,CAAI,QAAA,EAAU,QAAQ,MAAM,CAAA;AACpD,EAAA,MAAM,SAAS,EAAA,CAAG,QAAA,EAAS,GAAI,CAAA,CAAA,EAAI,EAAE,CAAA,CAAA,GAAK,EAAA;AAE1C,EAAA,OAAO,WAAA;AAAA,IACL,CAAC,EAAA,KAAO,CAAA,EAAG,EAAE,CAAA,OAAA,EAAU,SAAS,QAAQ,MAAM,CAAA,CAAA;AAAA,IAC9C,OAAO,GAAA,KAAQ;AACb,MAAA,MAAM,IAAA,GAAQ,MAAM,GAAA,CAAI,IAAA,EAAK;AAC7B,MAAA,OAAQ,IAAA,CAAK,QAAQ,EAAC;AAAA,IACxB;AAAA,GACF;AACF;AAIA,eAAsB,qBACpB,KAAA,EAC2D;AAC3D,EAAA,OAAO,WAAA;AAAA,IACL,CAAC,EAAA,KAAO,CAAA,EAAG,EAAE,SAAS,KAAK,CAAA,CAAA;AAAA,IAC3B,OAAO,GAAA,KAAQ;AACb,MAAA,MAAM,IAAA,GAAQ,MAAM,GAAA,CAAI,IAAA,EAAK;AAC7B,MAAA,OAAO,EAAE,MAAM,IAAA,CAAK,IAAA,IAAQ,MAAM,QAAA,EAAU,IAAA,CAAK,YAAY,EAAA,EAAG;AAAA,IAClE;AAAA,GACF;AACF;AAKO,SAAS,cAAA,CACd,SAAA,EACA,KAAA,EACA,GAAA,EACA,MAAA,EACM;AACN,EAAA,MAAM,IAAA,GAAO,KAAK,SAAA,CAAU,EAAE,aAAa,KAAA,EAAO,GAAA,EAAK,QAAQ,CAAA;AAC/D,EAAA,KAAA,MAAW,EAAA,IAAM,gBAAe,EAAG;AACjC,IAAA,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA,OAAA,EAAU,SAAS,CAAA,OAAA,CAAA,EAAW;AAAA,MACvC,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA,EAAS,EAAE,cAAA,EAAgB,kBAAA,EAAmB;AAAA,MAC9C;AAAA,KACD,CAAA,CAAE,KAAA,CAAM,MAAM;AAAA,IAAC,CAAC,CAAA;AAAA,EACnB;AACF;;;AC5FO,IAAM,YAAA,GAAe,YAAY,aAAa,CAAA;AAC9C,IAAM,OAAA,GAAU,aAAa,YAAY,CAAA;AAQhD,eAAsB,YAAA,CACpB,YACA,MAAA,EACwB;AACxB,EAAA,IAAI,MAAM,aAAA,CAAc,UAAA,EAAY,OAAO,GAAG,OAAO,IAAA;AACrD,EAAA,MAAM,UAAU,wBAAA,EAAyB;AACzC,EAAA,MAAM,EAAA,GAAK,2BAAA;AAAA,IACT,OAAA;AAAA,IACA;AAAA,MACE,OAAA,EAAS,OAAA;AAAA,MACT,QAAQ,MAAA,CAAO,SAAA;AAAA,MACf,gBAAgB,aAAA,CAAc;AAAA,KAChC;AAAA,IACA,EAAE,YAAY,YAAA;AAAa,GAC7B;AACA,EAAA,MAAM,EAAA,GAAK,IAAI,WAAA,EAAY,CAAE,IAAI,EAAE,CAAA;AACnC,EAAA,MAAM,EAAE,SAAA,EAAW,oBAAA,EAAqB,GAAI,MAAM,WAAW,kBAAA,EAAmB;AAChF,EAAA,EAAA,CAAG,eAAA,GAAkB,SAAA;AACrB,EAAA,EAAA,CAAG,WAAW,MAAA,CAAO,SAAA;AACrB,EAAA,MAAM,MAAA,GAAS,MAAM,MAAA,CAAO,MAAA,EAAQ,EAAE,CAAA;AACtC,EAAA,MAAM,YAAY,MAAM,UAAA,CAAW,kBAAA,CAAmB,MAAA,CAAO,WAAW,CAAA;AACxE,EAAA,MAAM,WAAW,kBAAA,CAAmB,EAAE,SAAA,EAAW,SAAA,EAAW,sBAAsB,CAAA;AAClF,EAAA,OAAO,SAAA;AACT;AAMA,eAAe,MAAA,CAAO,QAAqB,EAAA,EAAuC;AAChF,EAAA,IAAI,MAAA,YAAkB,OAAA,IAAW,WAAA,IAAe,MAAA,EAAQ;AACtD,IAAA,EAAA,CAAG,YAAY,MAAiB,CAAA;AAChC,IAAA,OAAO,EAAA;AAAA,EACT;AACA,EAAA,OAAQ,MAAA,CAAwB,gBAAgB,EAAE,CAAA;AACpD;AAOA,eAAsB,QAAA,CACpB,MACA,OAAA,EACyC;AACzC,EAAA,OAAO,aAAA,CAAc,QAAA,CAAS,IAAI,CAAA,EAAG,OAAO,CAAA;AAC9C;AAOA,eAAsB,aAAA,CACpB,KACA,OAAA,EACyC;AACzC,EAAA,MAAM,aAAa,MAAM,kBAAA,CAAmB,GAAA,CAAI,QAAA,IAAY,OAAO,CAAA;AACnE,EAAA,IAAI,UAAA,KAAe,MAAM,OAAO,UAAA;AAChC,EAAA,OAAO,aAAA,CAAc,KAAK,OAAO,CAAA;AACnC;AAMA,eAAsB,cACpB,IAAA,EACyC;AACzC,EAAA,MAAM,OAAO,MAAM,QAAA,CAAS,MAAM,EAAE,KAAA,EAAO,GAAG,CAAA;AAC9C,EAAA,OAAO,IAAA,CAAK,CAAC,CAAA,IAAK,IAAA;AACpB;AAOA,eAAsB,MAAA,CACpB,YACA,MAAA,EACA,IAAA,EACA,UACA,QAAA,EACA,UAAA,EACA,QAAqC,OAAA,EACpB;AACjB,EAAA,OAAOA,QAAA;AAAA,IACL,EAAE,YAAY,MAAA,EAAO;AAAA,IACrB,IAAA;AAAA,IACA,QAAA;AAAA,IACA,CAAA;AAAA,IACA,QAAA;AAAA,IACA,UAAA;AAAA,IACA;AAAA,GACF;AACF;AAMA,eAAsB,WACpB,KAAA,EACoD;AACpD,EAAA,MAAM,UAAA,GAAa,MAAM,oBAAA,CAAqB,KAAK,CAAA;AACnD,EAAA,IAAI,UAAA,KAAe,MAAM,OAAO,UAAA;AAChC,EAAA,OAAOC,aAAc,KAAK,CAAA;AAC5B;AAGA,eAAsB,aAAA,CACpB,YACA,GAAA,EACkB;AAClB,EAAA,OAAQ,MAAM,UAAA,CAAW,cAAA,CAAe,GAAG,CAAA,KAAO,IAAA;AACpD;AAGO,SAAS,SAAS,IAAA,EAAyB;AAChD,EAAA,OAAO,WAAA,CAAY,OAAA,EAAS,WAAA,CAAY,IAAI,CAAC,CAAA;AAC/C;ACnJA,IAAM,cAAA,GAAiB;AAAA,EACrB,IAAA;AAAA,EACA,SAAA;AAAA,EACA,UAAA;AAAA,EACA,gBAAA;AAAA,EACA,WAAA;AAAA,EACA;AACF,CAAA;AAMA,eAAsB,iBAAA,CACpB,UAAA,EACA,MAAA,EACA,IAAA,EACwB;AACxB,EAAA,MAAM,OAAO,eAAA,CAAgB,MAAA,CAAO,SAAA,CAAU,QAAA,IAAY,IAAI,CAAA;AAC9D,EAAA,IAAI,MAAY,aAAA,CAAc,UAAA,EAAkB,SAAS,IAAI,CAAC,GAAG,OAAO,IAAA;AACxE,EAAA,OAAO,WAAA;AAAA,IACL,UAAA;AAAA,IACA,MAAA;AAAA,IACA,aAAA;AAAA,IACA,IAAA;AAAA,IACA,IAAA;AAAA,IACA,cAAA;AAAA,IACA,IAAA;AAAA,IACA,EAAC;AAAA,IACD,MAAA;AAAA,IACA,CAAC,OAAO,SAAS,CAAA;AAAA,IACjB;AAAA,GACF;AACF;AAUA,eAAsB,WAAA,CACpB,UAAA,EACA,MAAA,EACA,IAAA,EACA,MAAA,EACiB;AACjB,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,SAAA,CAAU,QAAA,EAAS;AACxC,EAAA,MAAM,IAAA,GAAO,eAAA,CAAgB,KAAA,EAAO,IAAI,CAAA;AACxC,EAAA,MAAM,MAAM,MAAM,QAAA;AAAA,IAChB,UAAA;AAAA,IACA,MAAA;AAAA,IACA,aAAA;AAAA,IACA,IAAA;AAAA,IACA,IAAA,CAAK,UAAU,MAAM;AAAA,GACvB;AACA,EAAA,cAAA,CAAqB,SAAS,IAAI,CAAA,CAAE,UAAS,EAAG,GAAA,EAAK,QAAQ,KAAK,CAAA;AAClE,EAAA,OAAO,GAAA;AACT;AAGA,eAAsB,gBAAA,CACpB,WAAA,EACA,KAAA,EACA,IAAA,EACwB;AACxB,EAAA,MAAM,MAAM,MAAY,aAAA,CAAc,eAAA,CAAgB,KAAA,EAAO,IAAI,CAAC,CAAA;AAClE,EAAA,OAAO,GAAA;AACT;AAGA,eAAsB,iBAAA,CACpB,WAAA,EACA,KAAA,EACA,IAAA,EACA,OAAA,EACmB;AACnB,EAAA,MAAM,OAAO,MAAY,QAAA,CAAS,gBAAgB,KAAA,EAAO,IAAI,GAAG,OAAO,CAAA;AACvE,EAAA,OAAO,IAAA;AACT;AAOA,eAAsB,sBAAA,CACpB,KACA,OAAA,EACmB;AACnB,EAAA,MAAM,IAAA,GAAO,MAAY,aAAA,CAAc,GAAA,EAAK,OAAO,CAAA;AACnD,EAAA,OAAO,IAAA;AACT;AC7FA,IAAM,YAAA,GAAe,CAAC,MAAA,EAAQ,aAAA,EAAe,YAAY,WAAW,CAAA;AACpE,IAAM,gBAAA,GAAmB,CAAC,OAAA,EAAS,MAAA,EAAQ,eAAe,WAAW,CAAA;AAYrE,eAAsB,UAAA,CACpB,UAAA,EACA,MAAA,EACA,IAAA,EACiE;AACjE,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,SAAA,CAAU,QAAA,EAAS;AACxC,EAAA,MAAM,QAAA,GAAW,aAAa,KAAK,CAAA;AACnC,EAAA,MAAM,SAAiE,EAAC;AAExE,EAAA,IAAI,CAAE,MAAY,aAAA,CAAc,YAAkB,QAAA,CAAS,QAAQ,CAAC,CAAA,EAAI;AACtE,IAAA,MAAMC,WAAAA;AAAA,MACJ,UAAA;AAAA,MACA,MAAA;AAAA,MACA,aAAA;AAAA,MACA,QAAA;AAAA,MACA,QAAA;AAAA,MACA,YAAA;AAAA,MACA,MAAA;AAAA,MACA,EAAC;AAAA,MACD,MAAA;AAAA,MACA,CAAC,OAAO,SAAS,CAAA;AAAA,MACjB;AAAA,KACF;AAAA,EACF;AAEA,EAAA,MAAM,GAAA,GAAM,MAAMC,QAAAA,CAAS,UAAA,EAAY,MAAA,EAAQ,eAAe,QAAA,EAAU,IAAA,CAAK,SAAA,CAAU,IAAI,CAAC,CAAA;AAC5F,EAAA,MAAA,CAAO,KAAK,EAAE,SAAA,EAAW,UAAU,GAAA,EAAK,GAAA,EAAK,MAAM,CAAA;AACnD,EAAA,cAAA,CAAqB,SAAS,QAAQ,CAAA,CAAE,UAAS,EAAG,GAAA,EAAK,MAAM,KAAK,CAAA;AAEpE,EAAA,IAAI,KAAK,QAAA,EAAU;AACjB,IAAA,MAAM,KAAA,GAAuB;AAAA,MAC3B,KAAA;AAAA,MACA,MAAM,IAAA,CAAK,IAAA;AAAA,MACX,aAAa,IAAA,CAAK,WAAA;AAAA,MAClB,WAAW,IAAA,CAAK;AAAA,KAClB;AACA,IAAA,MAAM,MAAA,GAAS,MAAMA,QAAAA,CAAS,UAAA,EAAY,MAAA,EAAQ,eAAe,aAAA,EAAe,IAAA,CAAK,SAAA,CAAU,KAAK,CAAC,CAAA;AACrG,IAAA,MAAA,CAAO,IAAA,CAAK,EAAE,SAAA,EAAW,aAAA,EAAe,KAAK,MAAA,EAAQ,GAAA,EAAK,OAAO,CAAA;AACjE,IAAA,cAAA,CAAqB,SAAS,aAAa,CAAA,CAAE,UAAS,EAAG,MAAA,EAAQ,OAAO,KAAK,CAAA;AAAA,EAC/E;AAEA,EAAA,OAAO,MAAA;AACT;AAGA,eAAsB,cAAA,CACpB,aACA,KAAA,EACuB;AACvB,EAAA,OAAQ,MAAY,QAAA,CAAS,YAAA,CAAa,KAAK,CAAC,CAAA;AAClD;AAOA,eAAsB,gBAAA,CACpB,aACA,OAAA,EAC0B;AAC1B,EAAA,OAAQ,MAAY,QAAA,CAAS,aAAA,EAAe,OAAO,CAAA;AACrD;AAOA,eAAsB,iBAAA,CACpB,YACA,MAAA,EACwB;AACxB,EAAA,MAAY,YAAA,CAAa,YAAY,MAAM,CAAA;AAC3C,EAAA,IAAI,MAAY,aAAA,CAAc,UAAA,EAAkB,QAAA,CAAS,aAAa,CAAC,CAAA,EAAG;AACxE,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,OAAOD,WAAAA;AAAA,IACL,UAAA;AAAA,IACA,MAAA;AAAA,IACA,aAAA;AAAA,IACA,aAAA;AAAA,IACA,aAAA;AAAA,IACA,gBAAA;AAAA,IACA,OAAA;AAAA,IACA,EAAC;AAAA,IACD,MAAA;AAAA,IACA,MAAA;AAAA,IACA;AAAA,GACF;AACF;;;AC/FA,eAAsB,WACpB,UAAA,EACA,MAAA,EACA,YAAA,EACA,aAAA,EACA,OACA,UAAA,EACyC;AACzC,EAAA,MAAM,IAAA,GAAO,MAAM,SAAA,CAAU,aAAa,CAAA;AAC1C,EAAA,MAAM,KAAA,GAAQ,MAAM,YAAY,CAAA;AAChC,EAAA,IAAI,KAAA,IAAS,KAAA,CAAM,IAAA,KAAS,IAAA,EAAM,OAAO,KAAA;AAMzC,EAAA,MAAM,WAAW,YAAA,CAAa,KAAA,CAAM,GAAG,CAAA,CAAE,KAAI,IAAK,YAAA;AAClD,EAAA,MAAM,OAAO,MAAY,MAAA;AAAA,IACvB,UAAA;AAAA,IACA,MAAA;AAAA,IACA,aAAA;AAAA,IACA,cAAc,QAAQ,CAAA,CAAA;AAAA,IACtB,0BAAA;AAAA,IACA;AAAA,GACF;AACA,EAAA,OAAO,EAAE,MAAM,IAAA,EAAK;AACtB;AAKA,eAAsB,UAAA,CACpB,UAAA,EACA,MAAA,EACA,IAAA,EACiB;AACjB,EAAA,OAAa,MAAA;AAAA,IACX,UAAA;AAAA,IACA,MAAA;AAAA,IACA,IAAA,CAAK,UAAU,IAAI,CAAA;AAAA,IACnB,YAAA;AAAA,IACA;AAAA,GACF;AACF;AAKA,eAAsB,SAAS,QAAA,EAAqC;AAClE,EAAA,MAAM,EAAE,IAAA,EAAK,GAAI,MAAY,WAAW,QAAQ,CAAA;AAChD,EAAA,IAAI,SAAS,IAAA,EAAM;AACjB,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,2BAAA,EAA8B,QAAQ,CAAA,CAAE,CAAA;AAAA,EAC1D;AACA,EAAA,OAAO,IAAA,CAAK,MAAM,IAAI,CAAA;AACxB;AAMA,eAAsB,SAAS,IAAA,EAA+B;AAC5D,EAAA,MAAM,EAAE,IAAA,EAAK,GAAI,MAAY,WAAW,IAAI,CAAA;AAC5C,EAAA,IAAI,SAAS,IAAA,EAAM;AACjB,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,sBAAA,EAAyB,IAAI,CAAA,CAAE,CAAA;AAAA,EACjD;AACA,EAAA,OAAO,IAAA;AACT;;;ACjDO,IAAM,YAAN,MAAgB;AAAA;AAAA,EAErB,YAA6B,GAAA,EAAsB;AAAtB,IAAA,IAAA,CAAA,GAAA,GAAA,GAAA;AAO3B,IAAA,SAAA,CAAU,GAAA,CAAI,WAAW,WAAW,CAAA;AAAA,EACtC;AAAA,EAR6B,GAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAc7B,MAAM,WAAW,IAAA,EAAiC;AAChD,IAAA,MAAM,EAAE,UAAA,EAAY,MAAA,EAAO,GAAI,IAAA,CAAK,GAAA;AACpC,IAAA,MAAM,MAAA,GAAS,MAAgB,UAAA,CAAW,UAAA,EAAY,QAAQ,IAAI,CAAA;AAClE,IAAA,MAAkB,iBAAA,CAAkB,UAAA,EAAY,MAAA,EAAQ,IAAA,CAAK,IAAI,CAAA;AACjE,IAAA,IAAA,CAAK,YAAY,MAAM,CAAA;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,MAAA,CACJ,QAAA,EACA,OAAA,EACA,IAAA,EACiB;AACjB,IAAA,MAAM,EAAE,UAAA,EAAY,MAAA,EAAO,GAAI,IAAA,CAAK,GAAA;AACpC,IAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,SAAA,CAAU,QAAA,EAAS;AAExC,IAAA,MAAM,MAAA,GAAS,MAAkB,gBAAA,CAAiB,UAAA,EAAY,OAAO,QAAQ,CAAA;AAC7E,IAAA,MAAM,UAAoB,MAAA,GAAS,MAAc,SAAS,MAAA,CAAO,QAAQ,IAAI,EAAC;AAE9E,IAAA,MAAM,UAAoB,EAAC;AAC3B,IAAA,KAAA,MAAW,CAAC,IAAA,EAAM,OAAO,KAAK,MAAA,CAAO,OAAA,CAAQ,IAAI,CAAA,EAAG;AAClD,MAAA,OAAA,CAAQ,IAAI,IAAI,MAAc,UAAA;AAAA,QAC5B,UAAA;AAAA,QACA,MAAA;AAAA,QACA,IAAA;AAAA,QACA,OAAA;AAAA,QACA;AAAA,OACF;AAAA,IACF;AAEA,IAAA,MAAM,QAAA,GAAW,MAAc,UAAA,CAAW,UAAA,EAAY,QAAQ,OAAO,CAAA;AAErE,IAAA,MAAM,MAAA,GAAiB;AAAA,MACrB,EAAA,EAAI,OAAO,UAAA,EAAW;AAAA,MACtB,OAAA;AAAA,MACA,QAAA;AAAA,MACA,gBAAgB,MAAA,EAAQ,EAAA;AAAA,MACxB,SAAA,EAAW,KAAK,GAAA,EAAI;AAAA,MACpB,MAAA,EAAQ;AAAA,KACV;AACA,IAAA,MAAM,MAAM,MAAkB,WAAA,CAAY,UAAA,EAAY,MAAA,EAAQ,UAAU,MAAM,CAAA;AAC9E,IAAA,IAAA,CAAK,WAAA,CAAY,CAAC,EAAE,SAAA,EAAW,eAAA,CAAgB,KAAA,EAAO,QAAQ,CAAA,EAAG,GAAA,EAAK,GAAA,EAAK,MAAA,EAAQ,CAAC,CAAA;AACpF,IAAA,OAAO,MAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKQ,YAAY,MAAA,EAAgE;AAClF,IAAA,IAAI,CAAC,IAAA,CAAK,GAAA,CAAI,OAAA,EAAS;AACvB,IAAA,KAAA,MAAW,KAAK,MAAA,EAAQ;AACtB,MAAA,MAAME,SAAAA,GAAiB,QAAA,CAAS,CAAA,CAAE,SAAS,EAAE,QAAA,EAAS;AACtD,MAAA,IAAA,CAAK,GAAA,CAAI,OAAA,CAAQ,EAAE,QAAA,EAAAA,WAAU,SAAA,EAAW,CAAA,CAAE,SAAA,EAAW,GAAA,EAAK,CAAA,CAAE,GAAA,EAAK,GAAA,EAAK,CAAA,CAAE,KAAK,CAAA;AAAA,IAC/E;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,QAAA,CACJ,QAAA,EACA,QAAA,EACA,IAAA,EACiB;AACjB,IAAA,MAAM,EAAE,UAAA,EAAY,MAAA,EAAO,GAAI,IAAA,CAAK,GAAA;AACpC,IAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,SAAA,CAAU,QAAA,EAAS;AAExC,IAAA,IAAI,MAAA;AACJ,IAAA,IAAI,aAAa,QAAA,EAAU;AACzB,MAAA,MAAA,GAAS,MAAkB,gBAAA,CAAiB,UAAA,EAAY,KAAA,EAAO,QAAQ,CAAA;AAAA,IACzE,CAAA,MAAO;AACL,MAAA,MAAM,OAAA,GAAU,MAAkB,iBAAA,CAAkB,UAAA,EAAY,OAAO,QAAQ,CAAA;AAC/E,MAAA,MAAA,GAAS,QAAQ,IAAA,CAAK,CAAC,MAAM,CAAA,CAAE,EAAA,KAAO,QAAQ,CAAA,IAAK,IAAA;AAAA,IACrD;AACA,IAAA,IAAI,CAAC,MAAA,EAAQ;AACX,MAAA,MAAM,IAAI,MAAM,CAAA,kBAAA,EAAqB,QAAQ,OAAO,KAAK,CAAA,CAAA,EAAI,QAAQ,CAAA,CAAE,CAAA;AAAA,IACzE;AAEA,IAAA,MAAM,IAAA,GAAO,MAAc,QAAA,CAAS,MAAA,CAAO,QAAQ,CAAA;AACnD,IAAA,KAAA,MAAW,CAAC,IAAA,EAAM,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,IAAI,CAAA,EAAG;AAChD,MAAA,MAAM,OAAA,GAAU,MAAc,QAAA,CAAS,KAAA,CAAM,IAAI,CAAA;AACjD,MAAA,MAAM,IAAA,CAAK,MAAM,OAAO,CAAA;AAAA,IAC1B;AACA,IAAA,OAAO,MAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,KAAA,CACJ,QAAA,EACA,KAAA,EACA,IAAA,EACiB;AACjB,IAAA,MAAM,EAAE,UAAA,EAAW,GAAI,IAAA,CAAK,GAAA;AAC5B,IAAA,MAAM,MAAA,GAAS,MAAkB,gBAAA,CAAiB,UAAA,EAAY,OAAO,QAAQ,CAAA;AAC7E,IAAA,IAAI,CAAC,MAAA,EAAQ;AACX,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,cAAA,EAAiB,KAAK,CAAA,CAAA,EAAI,QAAQ,CAAA,CAAE,CAAA;AAAA,IACtD;AACA,IAAA,MAAM,IAAA,GAAO,MAAc,QAAA,CAAS,MAAA,CAAO,QAAQ,CAAA;AACnD,IAAA,KAAA,MAAW,CAAC,IAAA,EAAM,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,IAAI,CAAA,EAAG;AAChD,MAAA,MAAM,OAAA,GAAU,MAAc,QAAA,CAAS,KAAA,CAAM,IAAI,CAAA;AACjD,MAAA,MAAM,IAAA,CAAK,MAAM,OAAO,CAAA;AAAA,IAC1B;AACA,IAAA,OAAO,MAAA;AAAA,EACT;AAAA;AAAA,EAGA,MAAM,GAAA,CACJ,KAAA,EACA,QAAA,EACA,OAAA,EACmB;AACnB,IAAA,OAAmB,iBAAA;AAAA,MACjB,KAAK,GAAA,CAAI,UAAA;AAAA,MACT,KAAA;AAAA,MACA,QAAA;AAAA,MACA;AAAA,KACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,MAAA,CACJ,KAAA,EACA,QAAA,EACA,IAAA,EACuE;AACvE,IAAA,MAAM,SAAS,MAAkB,gBAAA;AAAA,MAC/B,KAAK,GAAA,CAAI,UAAA;AAAA,MACT,KAAA;AAAA,MACA;AAAA,KACF;AACA,IAAA,MAAM,OAAiB,MAAA,GAAS,MAAc,SAAS,MAAA,CAAO,QAAQ,IAAI,EAAC;AAE3E,IAAA,MAAM,QAAkB,EAAC;AACzB,IAAA,MAAM,WAAqB,EAAC;AAC5B,IAAA,MAAM,YAAsB,EAAC;AAC7B,IAAA,KAAA,MAAW,CAAC,IAAA,EAAM,OAAO,KAAK,MAAA,CAAO,OAAA,CAAQ,IAAI,CAAA,EAAG;AAClD,MAAA,MAAM,KAAA,GAAQ,KAAK,IAAI,CAAA;AACvB,MAAA,IAAI,CAAC,KAAA,EAAO;AACV,QAAA,KAAA,CAAM,KAAK,IAAI,CAAA;AACf,QAAA;AAAA,MACF;AACA,MAAA,MAAM,IAAA,GAAO,MAAM,SAAA,CAAU,OAAO,CAAA;AACpC,MAAA,CAAC,MAAM,IAAA,KAAS,IAAA,GAAO,SAAA,GAAY,QAAA,EAAU,KAAK,IAAI,CAAA;AAAA,IACxD;AACA,IAAA,OAAO,EAAE,KAAA,EAAO,QAAA,EAAU,SAAA,EAAU;AAAA,EACtC;AACF;;;ACpNA,SAAA,CAAU,WAAW,CAAA","file":"index.js","sourcesContent":["// SHA-256 content hashing for the blob-dedup index. Runtime-specific\n// implementations live in `platform/hash-node.ts` and `platform/hash-browser.ts`;\n// this module just declares the interface the rest of the SDK uses.\n//\n// Do NOT use this for deriving table seeds — that path is owned by\n// `iqlabs.utils.toSeedBytes` (keccak) and must stay aligned with the SDK.\n\n/**\n * SHA-256 of a UTF-8 or base64 string, returned as a lowercase hex digest.\n * Implementation is injected by the platform entry (node.ts / browser.ts).\n */\nexport type Sha256Hex = (input: string) => Promise<string>;\n\n// Platform entries (src/node.ts, src/browser.ts) will call `setSha256(...)`\n// during module init so downstream layers never care which runtime they are in.\n// This indirection is the one place where a wrapper is justified (CODE-RULES §1)\n// because the behavior genuinely differs per runtime.\nlet impl: Sha256Hex | undefined;\n\nexport function setSha256(fn: Sha256Hex): void {\n if (impl) {\n throw new Error(\n \"@iqlabs-official/git-sdk: sha256 implementation already installed. Import exactly one of '@iqlabs-official/git-sdk/node' or '@iqlabs-official/git-sdk/browser'.\",\n );\n }\n impl = fn;\n}\n\nexport async function sha256Hex(input: string): Promise<string> {\n if (!impl) {\n throw new Error(\n \"@iqlabs-official/git-sdk: sha256 not installed. Import '@iqlabs-official/git-sdk/node' (Node) or '@iqlabs-official/git-sdk/browser' (browser) before using the SDK.\",\n );\n }\n return impl(input);\n}\n","// Browser SHA-256 implementation. Kept as a pure export; `src/browser.ts`\n// installs it via `setSha256` during its own module init.\n\nimport type { Sha256Hex } from \"../core/hash\";\n\nexport const hashBrowser: Sha256Hex = async (input) => {\n const bytes = new TextEncoder().encode(input);\n const digest = await crypto.subtle.digest(\n \"SHA-256\",\n bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength) as ArrayBuffer,\n );\n return Array.from(new Uint8Array(digest))\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n};\n","// The single source of truth for table_hint strings.\n//\n// Readers re-derive PDAs with `iqlabs.utils.toSeedBytes(hint)` →\n// `iqlabs.contract.getTablePda(...)`; writers pass the same hint into\n// `iqlabs.writer.createTable`. Keeping the naming convention in one place\n// prevents silent drift between writer and reader. CODE-RULES §2 — if any\n// caller ever wants to build one of these strings inline, route it here\n// instead.\n\n/** DbRoot id for every iq-git table. Bootstrap and every caller share this. */\nexport const IQGIT_ROOT_ID = \"iq-git-v1\";\n\n/** `git_repos:all` — open-writers registry that drives the public gallery. */\nexport const REGISTRY_HINT = \"git_repos:all\";\n\n/**\n * Hint for the per-owner personal repo list.\n * input: owner wallet base58\n * output: \"git_repos_v2_<owner>\"\n */\nexport function repoListHint(owner: string): string {\n return `git_repos_v2_${owner}`;\n}\n\n/**\n * Hint for the per-repo commit table.\n * input: owner wallet base58, repo name (any characters — SDK keccak-hashes)\n * output: \"git_commits:<owner>:<repo>\"\n */\nexport function commitTableHint(owner: string, repo: string): string {\n return `git_commits:${owner}:${repo}`;\n}\n","// L1.5 — iq-gateway HTTP helpers.\n//\n// chain.ts dispatches reads through here first; on a null return it falls\n// back to direct RPC. Writers fire-and-forget a notify so the gateway can\n// prepend the new row to its head-page cache without waiting on RPC\n// indexing.\n//\n// Configuration precedence (high → low):\n// 1. setGatewayUrls([...]) — explicit URL list\n// 2. IQGIT_GATEWAYS env (csv) — deployment-side pinning\n// 3. setNetwork(\"devnet\"|\"mainnet\") + the network's default gateway\n// 4. RPC URL hostname inference (`devnet` / `testnet` substring → devnet)\n// 5. Mainnet default — gateway.iqlabs.dev\n//\n// Everything here is best-effort: an unreachable, misconfigured, or\n// disabled gateway never breaks the SDK.\n\nimport { getRpcUrl } from \"@iqlabs-official/solana-sdk\";\n\nconst MAINNET_GATEWAY = \"https://gateway.iqlabs.dev\";\nconst DEVNET_GATEWAY = \"https://dev-gateway.iqlabs.dev\";\nconst REQ_TIMEOUT_MS = 5000;\n\nlet runtimeGateways: string[] | null = null;\nlet networkOverride: \"mainnet\" | \"devnet\" | null = null;\n\n/** Pin the gateway URL list explicitly. Highest precedence. Pass `[]` to\n * disable gateway dispatch entirely (RPC-only mode). */\nexport function setGatewayUrls(urls: string[]): void {\n runtimeGateways = urls.length > 0 ? urls : null;\n}\n\n/** Pin the network label when the RPC URL doesn't reveal it (private nodes,\n * proxies, etc.). Has no effect when setGatewayUrls() is also set. */\nexport function setNetwork(network: \"mainnet\" | \"devnet\"): void {\n networkOverride = network;\n}\n\nfunction inferNetwork(): \"mainnet\" | \"devnet\" {\n if (networkOverride) return networkOverride;\n const u = getRpcUrl().toLowerCase();\n if (u.includes(\"devnet\") || u.includes(\"testnet\")) return \"devnet\";\n return \"mainnet\";\n}\n\nexport function getGatewayUrls(): string[] {\n if (runtimeGateways) return runtimeGateways;\n\n const env = (typeof process !== \"undefined\" && process.env?.IQGIT_GATEWAYS) ?? \"\";\n if (env) return env.split(\",\").map((s) => s.trim()).filter(Boolean);\n\n return inferNetwork() === \"devnet\" ? [DEVNET_GATEWAY] : [MAINNET_GATEWAY];\n}\n\nasync function tryGateways<T>(\n path: (gw: string) => string,\n parse: (res: Response) => Promise<T>,\n): Promise<T | null> {\n for (const gw of getGatewayUrls()) {\n try {\n const ctrl = new AbortController();\n const timer = setTimeout(() => ctrl.abort(), REQ_TIMEOUT_MS);\n const res = await fetch(path(gw), { signal: ctrl.signal });\n clearTimeout(timer);\n if (res.ok) return await parse(res);\n } catch {\n // Try the next gateway.\n }\n }\n return null;\n}\n\n/** Fetch rows for a table PDA via /table/:pda/rows. Returns null when no\n * gateway is configured or all of them fail — caller falls back to RPC. */\nexport async function readRowsViaGateway(\n pdaBase58: string,\n options?: { limit?: number; before?: string },\n): Promise<Array<Record<string, unknown>> | null> {\n const qs = new URLSearchParams();\n if (options?.limit) qs.set(\"limit\", String(options.limit));\n if (options?.before) qs.set(\"before\", options.before);\n const suffix = qs.toString() ? `?${qs}` : \"\";\n\n return tryGateways(\n (gw) => `${gw}/table/${pdaBase58}/rows${suffix}`,\n async (res) => {\n const json = (await res.json()) as { rows?: unknown[] };\n return (json.rows ?? []) as Array<Record<string, unknown>>;\n },\n );\n}\n\n/** Fetch raw codeIn payload via /data/:sig. Gateway returns a superset of\n * what the SDK's readCodeIn produces; we extract just the matching fields. */\nexport async function readCodeInViaGateway(\n txSig: string,\n): Promise<{ data: string | null; metadata: string } | null> {\n return tryGateways(\n (gw) => `${gw}/data/${txSig}`,\n async (res) => {\n const json = (await res.json()) as { data?: string | null; metadata?: string };\n return { data: json.data ?? null, metadata: json.metadata ?? \"\" };\n },\n );\n}\n\n/** Fire-and-forget /notify after a successful write. Includes the row body\n * so the gateway can inject without an RPC roundtrip. Errors are swallowed\n * — the row is already on-chain, gateway hydration is opportunistic. */\nexport function notifyGateways(\n pdaBase58: string,\n txSig: string,\n row: object,\n signer: string,\n): void {\n const body = JSON.stringify({ txSignature: txSig, row, signer });\n for (const gw of getGatewayUrls()) {\n fetch(`${gw}/table/${pdaBase58}/notify`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body,\n }).catch(() => {});\n }\n}\n","// L1 — chain primitives shared by L2/L3. Kept tiny by design: each function\n// here either (a) hides PDA derivation so callers only deal with hints, or\n// (b) wraps a single iqlabs-sdk call to keep an iq-git-specific default\n// (chunk speed, root id, ...). Pure passthroughs like `createTable` /\n// `writeRow` live at the call site instead — wrapping them once more would\n// just bury the iqlabs-sdk surface (CODE-RULES §1).\n//\n// Read primitives transparently prefer the iq-gateway HTTP API and fall\n// back to direct RPC; the gateway dispatch lives here so commit/repo/\n// storage all benefit without each having to wire it up.\n\nimport {\n Keypair,\n SystemProgram,\n Transaction,\n type Connection,\n type PublicKey,\n} from \"@solana/web3.js\";\nimport {\n createInstructionBuilder,\n getDbRootPda,\n getTablePda,\n initializeDbRootInstruction,\n} from \"@iqlabs-official/solana-sdk/contract\";\nimport { readCodeIn as sdkReadCodeIn, readTableRows } from \"@iqlabs-official/solana-sdk/reader\";\nimport { toSeedBytes, type SignerInput, type WalletSigner } from \"@iqlabs-official/solana-sdk/utils\";\nimport { codeIn as sdkCodeIn } from \"@iqlabs-official/solana-sdk/writer\";\nimport { IQGIT_ROOT_ID } from \"../core/seed\";\nimport { readCodeInViaGateway, readRowsViaGateway } from \"./gateway\";\n\n/** DbRoot PDA for the `iq-git-v1` namespace — derived once, reused everywhere. */\nexport const DB_ROOT_SEED = toSeedBytes(IQGIT_ROOT_ID);\nexport const DB_ROOT = getDbRootPda(DB_ROOT_SEED);\n\n/**\n * Initialize the `iq-git-v1` DbRoot account if it doesn't exist. First-call\n * cost on a fresh network. Idempotent: returns null if already initialized.\n * Accepts any SignerInput so an admin can run it from a wallet, not just\n * from a Keypair.\n */\nexport async function ensureDbRoot(\n connection: Connection,\n signer: SignerInput,\n): Promise<string | null> {\n if (await accountExists(connection, DB_ROOT)) return null;\n const builder = createInstructionBuilder();\n const ix = initializeDbRootInstruction(\n builder,\n {\n db_root: DB_ROOT,\n signer: signer.publicKey,\n system_program: SystemProgram.programId,\n },\n { db_root_id: DB_ROOT_SEED },\n );\n const tx = new Transaction().add(ix);\n const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash();\n tx.recentBlockhash = blockhash;\n tx.feePayer = signer.publicKey;\n const signed = await signTx(signer, tx);\n const signature = await connection.sendRawTransaction(signed.serialize());\n await connection.confirmTransaction({ signature, blockhash, lastValidBlockHeight });\n return signature;\n}\n\n// Sign a single Transaction with whatever shape the signer takes. Keypair\n// has a `secretKey`; wallet adapters expose `signTransaction`. iqlabs-sdk's\n// own `sendTx` uses the same dispatch; we replicate it here so the helper\n// stays self-contained.\nasync function signTx(signer: SignerInput, tx: Transaction): Promise<Transaction> {\n if (signer instanceof Keypair || \"secretKey\" in signer) {\n tx.partialSign(signer as Keypair);\n return tx;\n }\n return (signer as WalletSigner).signTransaction(tx);\n}\n\n/**\n * Read rows from a table. Tries the iq-gateway HTTP cache first and falls\n * back to `iqlabs.reader.readTableRows` on miss. Callers see a uniform API\n * either way.\n */\nexport async function readRows(\n hint: string,\n options?: { limit?: number; before?: string },\n): Promise<Array<Record<string, unknown>>> {\n return readRowsByPda(tablePda(hint), options);\n}\n\n/**\n * Same as readRows but keyed by the table PDA directly — for callers that\n * already have the PDA (e.g. a .sol record pointing at a commit table) and\n * can't or shouldn't re-derive it from a hint.\n */\nexport async function readRowsByPda(\n pda: PublicKey,\n options?: { limit?: number; before?: string },\n): Promise<Array<Record<string, unknown>>> {\n const viaGateway = await readRowsViaGateway(pda.toBase58(), options);\n if (viaGateway !== null) return viaGateway;\n return readTableRows(pda, options);\n}\n\n/**\n * Fetch just the latest row of a table — the fast path for \"what is the\n * current commit\" and \"what is the pinned deploy\".\n */\nexport async function readLatestRow(\n hint: string,\n): Promise<Record<string, unknown> | null> {\n const rows = await readRows(hint, { limit: 1 });\n return rows[0] ?? null;\n}\n\n/**\n * Upload a blob via `iqlabs.writer.codeIn`. The SDK chunks internally when\n * `data` is a plain string. We default speed to \"light\" because that's the\n * Helius-friendly setting for git workloads (per-file uploads are bursty).\n */\nexport async function codeIn(\n connection: Connection,\n signer: SignerInput,\n data: string | string[],\n filename: string,\n filetype: string,\n onProgress?: (percent: number) => void,\n speed: \"light\" | \"medium\" | \"fast\" = \"light\",\n): Promise<string> {\n return sdkCodeIn(\n { connection, signer },\n data,\n filename,\n 0,\n filetype,\n onProgress,\n speed,\n );\n}\n\n/**\n * Read a codeIn payload by tx signature. Tries the gateway /data/:sig\n * cache first and falls back to the SDK's direct RPC decode.\n */\nexport async function readCodeIn(\n txSig: string,\n): Promise<{ data: string | null; metadata: string }> {\n const viaGateway = await readCodeInViaGateway(txSig);\n if (viaGateway !== null) return viaGateway;\n return sdkReadCodeIn(txSig);\n}\n\n/** Cheap existence check for a PDA. */\nexport async function accountExists(\n connection: Connection,\n pda: PublicKey,\n): Promise<boolean> {\n return (await connection.getAccountInfo(pda)) !== null;\n}\n\n/** Resolve a hint to its PDA. */\nexport function tablePda(hint: string): PublicKey {\n return getTablePda(DB_ROOT, toSeedBytes(hint));\n}\n","// L3 — per-repo commit table.\n//\n// v2's core invariant: each repo has its own table at hint\n// `git_commits:<owner>:<repo>`, with writers locked to [owner]. That means\n// \"the most recent successful tx in this table = the latest commit\", and we\n// read it as a single-row query (limit: 1).\n\nimport type { Connection, PublicKey } from \"@solana/web3.js\";\nimport { type SignerInput } from \"@iqlabs-official/solana-sdk/utils\";\nimport { createTable, writeRow } from \"@iqlabs-official/solana-sdk/writer\";\nimport { IQGIT_ROOT_ID, commitTableHint } from \"../core/seed\";\nimport type { Commit } from \"../core/types\";\nimport * as chain from \"./chain\";\nimport { notifyGateways } from \"./gateway\";\n\nconst COMMIT_COLUMNS = [\n \"id\",\n \"message\",\n \"treeTxId\",\n \"parentCommitId\",\n \"timestamp\",\n \"author\",\n];\n\n/**\n * Ensure the per-repo commit table exists with writers = [owner]. No-op if\n * it already exists.\n */\nexport async function ensureCommitTable(\n connection: Connection,\n signer: SignerInput,\n repo: string,\n): Promise<string | null> {\n const hint = commitTableHint(signer.publicKey.toBase58(), repo);\n if (await chain.accountExists(connection, chain.tablePda(hint))) return null;\n return createTable(\n connection,\n signer as never,\n IQGIT_ROOT_ID,\n hint,\n hint,\n COMMIT_COLUMNS,\n \"id\",\n [],\n undefined,\n [signer.publicKey],\n hint,\n );\n}\n\n/**\n * Append one commit row. Callers (workflow-level code) are responsible for\n * setting parentCommitId — the SDK does not auto-chain.\n *\n * After the row lands on-chain, fires a best-effort /notify so any\n * iq-gateway already caching this table prepends the new commit without\n * waiting for RPC sig indexing.\n */\nexport async function writeCommit(\n connection: Connection,\n signer: SignerInput,\n repo: string,\n commit: Commit,\n): Promise<string> {\n const owner = signer.publicKey.toBase58();\n const hint = commitTableHint(owner, repo);\n const sig = await writeRow(\n connection,\n signer,\n IQGIT_ROOT_ID,\n hint,\n JSON.stringify(commit),\n );\n notifyGateways(chain.tablePda(hint).toBase58(), sig, commit, owner);\n return sig;\n}\n\n/** Latest commit. Single-row, O(1) RPC path. */\nexport async function readLatestCommit(\n _connection: Connection,\n owner: string,\n repo: string,\n): Promise<Commit | null> {\n const row = await chain.readLatestRow(commitTableHint(owner, repo));\n return row as unknown as Commit | null;\n}\n\n/** Full commit history, newest first. */\nexport async function readCommitHistory(\n _connection: Connection,\n owner: string,\n repo: string,\n options?: { limit?: number; before?: string },\n): Promise<Commit[]> {\n const rows = await chain.readRows(commitTableHint(owner, repo), options);\n return rows as unknown as Commit[];\n}\n\n/**\n * Commit history keyed by the commit-table PDA directly — for callers that\n * resolved a repo to its PDA (e.g. via a .sol record) and don't have the\n * owner/repo to rebuild the hint.\n */\nexport async function readCommitHistoryByPda(\n pda: PublicKey,\n options?: { limit?: number; before?: string },\n): Promise<Commit[]> {\n const rows = await chain.readRowsByPda(pda, options);\n return rows as unknown as Commit[];\n}\n","// L3 — repo list and public registry.\n//\n// Covers the two \"directory\" tables:\n// • git_repos_v2_<owner> — owner's personal repo list (writers = [owner])\n// • git_repos:all — public gallery registry (writers = [])\n//\n// Commit tables are a separate concern — see `commit.ts`.\n\nimport type { Connection } from \"@solana/web3.js\";\nimport { type SignerInput } from \"@iqlabs-official/solana-sdk/utils\";\nimport { createTable, writeRow } from \"@iqlabs-official/solana-sdk/writer\";\nimport { IQGIT_ROOT_ID, REGISTRY_HINT, repoListHint } from \"../core/seed\";\nimport type { RegistryEntry, Repository } from \"../core/types\";\nimport * as chain from \"./chain\";\nimport { notifyGateways } from \"./gateway\";\n\nconst REPO_COLUMNS = [\"name\", \"description\", \"isPublic\", \"timestamp\"];\nconst REGISTRY_COLUMNS = [\"owner\", \"repo\", \"description\", \"timestamp\"];\n\n/**\n * Create a repo in the owner's personal list, and (if public) also register\n * it in the public gallery. Two transactions — the contract does not support\n * writing two tables atomically.\n *\n * Returns the writeRow tx signatures (and the table hint each one wrote to)\n * so a caller can notify gateways / build SSE streams for those tables. The\n * returned shape is `[]` from `createTable` calls because those don't write\n * a row, just allocate the account.\n */\nexport async function createRepo(\n connection: Connection,\n signer: SignerInput,\n meta: Repository,\n): Promise<Array<{ tableHint: string; sig: string; row: object }>> {\n const owner = signer.publicKey.toBase58();\n const listHint = repoListHint(owner);\n const writes: Array<{ tableHint: string; sig: string; row: object }> = [];\n\n if (!(await chain.accountExists(connection, chain.tablePda(listHint)))) {\n await createTable(\n connection,\n signer as never,\n IQGIT_ROOT_ID,\n listHint,\n listHint,\n REPO_COLUMNS,\n \"name\",\n [],\n undefined,\n [signer.publicKey],\n listHint,\n );\n }\n\n const sig = await writeRow(connection, signer, IQGIT_ROOT_ID, listHint, JSON.stringify(meta));\n writes.push({ tableHint: listHint, sig, row: meta });\n notifyGateways(chain.tablePda(listHint).toBase58(), sig, meta, owner);\n\n if (meta.isPublic) {\n const entry: RegistryEntry = {\n owner,\n repo: meta.name,\n description: meta.description,\n timestamp: meta.timestamp,\n };\n const regSig = await writeRow(connection, signer, IQGIT_ROOT_ID, REGISTRY_HINT, JSON.stringify(entry));\n writes.push({ tableHint: REGISTRY_HINT, sig: regSig, row: entry });\n notifyGateways(chain.tablePda(REGISTRY_HINT).toBase58(), regSig, entry, owner);\n }\n\n return writes;\n}\n\n/** List all repos owned by `owner`. */\nexport async function readOwnerRepos(\n _connection: Connection,\n owner: string,\n): Promise<Repository[]> {\n return (await chain.readRows(repoListHint(owner))) as unknown as Repository[];\n}\n\n/**\n * One page of the public-gallery registry. Callers should still check\n * `row.owner` shape before trusting it in UI; we do not filter at the SDK\n * boundary.\n */\nexport async function readRegistryPage(\n _connection: Connection,\n options?: { limit?: number; before?: string },\n): Promise<RegistryEntry[]> {\n return (await chain.readRows(REGISTRY_HINT, options)) as unknown as RegistryEntry[];\n}\n\n/**\n * One-time global bootstrap of the `git_repos:all` table. Run once per\n * network from an admin key; subsequent calls short-circuit because the\n * account already exists.\n */\nexport async function bootstrapRegistry(\n connection: Connection,\n signer: SignerInput,\n): Promise<string | null> {\n await chain.ensureDbRoot(connection, signer);\n if (await chain.accountExists(connection, chain.tablePda(REGISTRY_HINT))) {\n return null;\n }\n return createTable(\n connection,\n signer as never,\n IQGIT_ROOT_ID,\n REGISTRY_HINT,\n REGISTRY_HINT,\n REGISTRY_COLUMNS,\n \"owner\",\n [],\n undefined,\n undefined,\n REGISTRY_HINT,\n );\n}\n","// L2 — blob + tree storage.\n//\n// `uploadBlob` is the file-level \"don't re-upload what's already on-chain\"\n// primitive. Content is always a base64 string (matching iq-git v1) so the\n// hash / dedup comparison stays byte-for-byte compatible across commits.\n// The reuse-map is just a plain object so callers can build it any way they\n// like (path→entry, or hash→txId for rename-aware dedup — CODE-RULES §3\n// keeps this inlined at the call site instead of a new type).\n//\n// `uploadTree` / `loadTree` serialize FileTree <-> on-chain tree.json as raw\n// JSON (filetype `application/json`), again matching v1.\n\nimport type { Connection } from \"@solana/web3.js\";\nimport type { SignerInput } from \"@iqlabs-official/solana-sdk/utils\";\nimport { sha256Hex } from \"../core/hash\";\nimport type { FileTree } from \"../core/types\";\nimport * as chain from \"./chain\";\n\n/**\n * Upload one file unless an identical hash is already in `reuse` (blob dedup).\n *\n * input: connection, signer, relativePath, base64 content, reuse map, optional onProgress\n * output: { txId, hash } — either reused or freshly uploaded\n */\nexport async function uploadBlob(\n connection: Connection,\n signer: SignerInput,\n relativePath: string,\n base64Content: string,\n reuse: FileTree,\n onProgress?: (percent: number) => void,\n): Promise<{ txId: string; hash: string }> {\n const hash = await sha256Hex(base64Content);\n const prior = reuse[relativePath];\n if (prior && prior.hash === hash) return prior;\n\n // Tag the codeIn filename with our app marker so non-inline inventory\n // entries can be classified by inspecting metadata.filename alone (no row\n // body fetch needed). Format: \"iqgit-blob:<basename>\". Same scheme used\n // for trees (\"iqgit-tree\") and other writes across the IQ ecosystem.\n const basename = relativePath.split(\"/\").pop() || relativePath;\n const txId = await chain.codeIn(\n connection,\n signer,\n base64Content,\n `iqgit-blob:${basename}`,\n \"application/octet-stream\",\n onProgress,\n );\n return { txId, hash };\n}\n\n/**\n * Serialize a FileTree and upload it as one `tree.json` blob.\n */\nexport async function uploadTree(\n connection: Connection,\n signer: SignerInput,\n tree: FileTree,\n): Promise<string> {\n return chain.codeIn(\n connection,\n signer,\n JSON.stringify(tree),\n \"iqgit-tree\",\n \"application/json\",\n );\n}\n\n/**\n * Fetch and parse a `tree.json` blob by its tx signature.\n */\nexport async function loadTree(treeTxId: string): Promise<FileTree> {\n const { data } = await chain.readCodeIn(treeTxId);\n if (data === null) {\n throw new Error(`tree.json not found for tx ${treeTxId}`);\n }\n return JSON.parse(data) as FileTree;\n}\n\n/**\n * Retrieve a blob's bytes by its txId. Returns the raw string that was\n * uploaded — for blobs this is base64; the caller decodes.\n */\nexport async function loadBlob(txId: string): Promise<string> {\n const { data } = await chain.readCodeIn(txId);\n if (data === null) {\n throw new Error(`blob not found for tx ${txId}`);\n }\n return data;\n}\n","// L4 — GitClient facade. High-level workflows built by composing the\n// layers below. This is the surface consumers (CLI, frontend, migrator) use;\n// they should not reach into `chain` / `storage` / `repo` / `commit` directly.\n//\n// Keep workflow logic here, not inside lower layers (CODE-RULES §5). When a\n// command needs scanning, hashing, uploading, row writing — this file\n// orchestrates them all.\n\nimport type { Connection } from \"@solana/web3.js\";\nimport { setRpcUrl } from \"@iqlabs-official/solana-sdk\";\nimport type { SignerInput } from \"@iqlabs-official/solana-sdk/utils\";\nimport { sha256Hex } from \"../core/hash\";\nimport { commitTableHint } from \"../core/seed\";\nimport type { Commit, FileTree, Repository } from \"../core/types\";\nimport * as chain from \"./chain\";\nimport * as commitLayer from \"./commit\";\nimport * as repoLayer from \"./repo\";\nimport * as storage from \"./storage\";\n\n/** Information surfaced to the `onWrite` callback for every successful row\n * write the SDK performs. Consumers wire this to their gateway notify so\n * the gateway updates its cache / SSE stream immediately. */\nexport interface WriteEvent {\n /** Resolved table PDA, base58 — pass directly to gateway notify. */\n tablePda: string;\n /** The hint that derived the PDA, in case callers want to log it. */\n tableHint: string;\n /** writeRow tx signature. */\n sig: string;\n /** The row object that was written (already JSON.stringify-able). */\n row: object;\n}\n\nexport interface GitClientConfig {\n connection: Connection;\n signer: SignerInput;\n /** Fires after each successful row write inside the SDK. Fire-and-forget\n * callback for gateway notifies; throwing here will surface to the caller. */\n onWrite?: (event: WriteEvent) => void;\n}\n\nexport class GitClient {\n // CODE-RULES §3 — only one small shape; inlined rather than aliased.\n constructor(private readonly cfg: GitClientConfig) {\n // The solana-sdk reader path (readTableRows / readCodeIn → loadTree /\n // readLatestCommit) does not take a Connection — it resolves a\n // process-global one from env / setRpcUrl. Writes use `cfg.connection`,\n // so without this reads could hit a different RPC (e.g. the mainnet-beta\n // fallback when no env is set, as in a built browser bundle). Sync the\n // reader's RPC to the connection the caller actually gave us.\n setRpcUrl(cfg.connection.rpcEndpoint);\n }\n\n /**\n * Create a new repo. Wraps repo.createRepo + pre-creating the commit table\n * so the first `commit()` call doesn't need to pay createTable cost.\n */\n async createRepo(meta: Repository): Promise<void> {\n const { connection, signer } = this.cfg;\n const writes = await repoLayer.createRepo(connection, signer, meta);\n await commitLayer.ensureCommitTable(connection, signer, meta.name);\n this.fireOnWrite(writes);\n }\n\n /**\n * Incremental commit against a scanned directory snapshot.\n *\n * input: repoName, message, scan — a `{ [path]: base64Content }` map that\n * the caller produced (Node: fs walk + base64; browser: File input).\n * output: newly written Commit\n */\n async commit(\n repoName: string,\n message: string,\n scan: Record<string, string>,\n ): Promise<Commit> {\n const { connection, signer } = this.cfg;\n const owner = signer.publicKey.toBase58();\n\n const latest = await commitLayer.readLatestCommit(connection, owner, repoName);\n const oldTree: FileTree = latest ? await storage.loadTree(latest.treeTxId) : {};\n\n const newTree: FileTree = {};\n for (const [path, content] of Object.entries(scan)) {\n newTree[path] = await storage.uploadBlob(\n connection,\n signer,\n path,\n content,\n oldTree,\n );\n }\n\n const treeTxId = await storage.uploadTree(connection, signer, newTree);\n\n const commit: Commit = {\n id: crypto.randomUUID(),\n message,\n treeTxId,\n parentCommitId: latest?.id,\n timestamp: Date.now(),\n author: owner,\n };\n const sig = await commitLayer.writeCommit(connection, signer, repoName, commit);\n this.fireOnWrite([{ tableHint: commitTableHint(owner, repoName), sig, row: commit }]);\n return commit;\n }\n\n /** Resolve the table hint to a PDA and forward each write to `onWrite`.\n * Wrapped in try/catch per call so a misbehaving notify can't fail the\n * whole batch — but we still surface the error so the consumer knows. */\n private fireOnWrite(writes: Array<{ tableHint: string; sig: string; row: object }>) {\n if (!this.cfg.onWrite) return;\n for (const w of writes) {\n const tablePda = chain.tablePda(w.tableHint).toBase58();\n this.cfg.onWrite({ tablePda, tableHint: w.tableHint, sig: w.sig, row: w.row });\n }\n }\n\n /**\n * Restore a commit's files into a caller-provided sink. Runtime-neutral\n * shape mirrors `commit`: the caller decides how to write bytes to disk /\n * to a File System Access API handle / anywhere else. `content` is the\n * raw base64 string — the sink decodes.\n */\n async checkout(\n repoName: string,\n commitId: string | \"latest\",\n sink: (path: string, content: string) => Promise<void>,\n ): Promise<Commit> {\n const { connection, signer } = this.cfg;\n const owner = signer.publicKey.toBase58();\n\n let target: Commit | null;\n if (commitId === \"latest\") {\n target = await commitLayer.readLatestCommit(connection, owner, repoName);\n } else {\n const history = await commitLayer.readCommitHistory(connection, owner, repoName);\n target = history.find((c) => c.id === commitId) ?? null;\n }\n if (!target) {\n throw new Error(`commit not found: ${commitId} in ${owner}/${repoName}`);\n }\n\n const tree = await storage.loadTree(target.treeTxId);\n for (const [path, entry] of Object.entries(tree)) {\n const content = await storage.loadBlob(entry.txId);\n await sink(path, content);\n }\n return target;\n }\n\n /**\n * Whole-repo snapshot download — convenience on top of checkout(\"latest\")\n * but reading from someone else's `owner`. We do not require signer to\n * equal owner for reads.\n */\n async clone(\n repoName: string,\n owner: string,\n sink: (path: string, content: string) => Promise<void>,\n ): Promise<Commit> {\n const { connection } = this.cfg;\n const target = await commitLayer.readLatestCommit(connection, owner, repoName);\n if (!target) {\n throw new Error(`no commits in ${owner}/${repoName}`);\n }\n const tree = await storage.loadTree(target.treeTxId);\n for (const [path, entry] of Object.entries(tree)) {\n const content = await storage.loadBlob(entry.txId);\n await sink(path, content);\n }\n return target;\n }\n\n /** Commit history for a repo. */\n async log(\n owner: string,\n repoName: string,\n options?: { limit?: number; before?: string },\n ): Promise<Commit[]> {\n return commitLayer.readCommitHistory(\n this.cfg.connection,\n owner,\n repoName,\n options,\n );\n }\n\n /**\n * Compare a current directory snapshot to the latest commit's tree.\n */\n async status(\n owner: string,\n repoName: string,\n scan: Record<string, string>,\n ): Promise<{ added: string[]; modified: string[]; unchanged: string[] }> {\n const latest = await commitLayer.readLatestCommit(\n this.cfg.connection,\n owner,\n repoName,\n );\n const tree: FileTree = latest ? await storage.loadTree(latest.treeTxId) : {};\n\n const added: string[] = [];\n const modified: string[] = [];\n const unchanged: string[] = [];\n for (const [path, content] of Object.entries(scan)) {\n const prior = tree[path];\n if (!prior) {\n added.push(path);\n continue;\n }\n const hash = await sha256Hex(content);\n (prior.hash === hash ? unchanged : modified).push(path);\n }\n return { added, modified, unchanged };\n }\n}\n","// Browser entry. Installs the Web-Crypto SHA-256 hasher, then re-exports\n// everything from the shared root.\n\nimport { setSha256 } from \"./core/hash\";\nimport { hashBrowser } from \"./platform/hash-browser\";\n\nsetSha256(hashBrowser);\n\nexport * from \"./index\";\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/core/hash.ts","../../src/platform/hash-browser.ts","../../src/core/seed.ts","../../src/layers/gateway.ts","../../src/layers/chain.ts","../../src/layers/commit.ts","../../src/layers/repo.ts","../../src/layers/storage.ts","../../src/layers/client.ts","../../src/browser.ts"],"names":["sdkCodeIn","sdkReadCodeIn","createTable","writeRow","tablePda"],"mappings":"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","file":"index.js","sourcesContent":["// SHA-256 content hashing for the blob-dedup index. Runtime-specific\n// implementations live in `platform/hash-node.ts` and `platform/hash-browser.ts`;\n// this module just declares the interface the rest of the SDK uses.\n//\n// Do NOT use this for deriving table seeds — that path is owned by\n// `iqlabs.utils.toSeedBytes` (keccak) and must stay aligned with the SDK.\n\n/**\n * SHA-256 of a UTF-8 or base64 string, returned as a lowercase hex digest.\n * Implementation is injected by the platform entry (node.ts / browser.ts).\n */\nexport type Sha256Hex = (input: string) => Promise<string>;\n\n// Platform entries (src/node.ts, src/browser.ts) will call `setSha256(...)`\n// during module init so downstream layers never care which runtime they are in.\n// This indirection is the one place where a wrapper is justified (CODE-RULES §1)\n// because the behavior genuinely differs per runtime.\nlet impl: Sha256Hex | undefined;\n\nexport function setSha256(fn: Sha256Hex): void {\n if (impl) {\n throw new Error(\n \"@iqlabs-official/git-sdk: sha256 implementation already installed. Import exactly one of '@iqlabs-official/git-sdk/node' or '@iqlabs-official/git-sdk/browser'.\",\n );\n }\n impl = fn;\n}\n\nexport async function sha256Hex(input: string): Promise<string> {\n if (!impl) {\n throw new Error(\n \"@iqlabs-official/git-sdk: sha256 not installed. Import '@iqlabs-official/git-sdk/node' (Node) or '@iqlabs-official/git-sdk/browser' (browser) before using the SDK.\",\n );\n }\n return impl(input);\n}\n","// Browser SHA-256 implementation. Kept as a pure export; `src/browser.ts`\n// installs it via `setSha256` during its own module init.\n\nimport type { Sha256Hex } from \"../core/hash\";\n\nexport const hashBrowser: Sha256Hex = async (input) => {\n const bytes = new TextEncoder().encode(input);\n const digest = await crypto.subtle.digest(\n \"SHA-256\",\n bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength) as ArrayBuffer,\n );\n return Array.from(new Uint8Array(digest))\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n};\n","// The single source of truth for table_hint strings.\n//\n// Readers re-derive PDAs with `iqlabs.utils.toSeedBytes(hint)` →\n// `iqlabs.contract.getTablePda(...)`; writers pass the same hint into\n// `iqlabs.writer.createTable`. Keeping the naming convention in one place\n// prevents silent drift between writer and reader. CODE-RULES §2 — if any\n// caller ever wants to build one of these strings inline, route it here\n// instead.\n\n/** DbRoot id for every iq-git table. Bootstrap and every caller share this. */\nexport const IQGIT_ROOT_ID = \"iq-git-v1\";\n\n/** `git_repos:all` — open-writers registry that drives the public gallery. */\nexport const REGISTRY_HINT = \"git_repos:all\";\n\n/**\n * Hint for the per-owner personal repo list.\n * input: owner wallet base58\n * output: \"git_repos_v2_<owner>\"\n */\nexport function repoListHint(owner: string): string {\n return `git_repos_v2_${owner}`;\n}\n\n/**\n * Hint for the per-repo commit table.\n * input: owner wallet base58, repo name (any characters — SDK keccak-hashes)\n * output: \"git_commits:<owner>:<repo>\"\n */\nexport function commitTableHint(owner: string, repo: string): string {\n return `git_commits:${owner}:${repo}`;\n}\n","// L1.5 — iq-gateway HTTP helpers.\n//\n// chain.ts dispatches reads through here first; on a null return it falls\n// back to direct RPC. Writers fire-and-forget a notify so the gateway can\n// prepend the new row to its head-page cache without waiting on RPC\n// indexing.\n//\n// Configuration precedence (high → low):\n// 1. setGatewayUrls([...]) — explicit URL list\n// 2. IQGIT_GATEWAYS env (csv) — deployment-side pinning\n// 3. setNetwork(\"devnet\"|\"mainnet\") + the network's default gateway\n// 4. RPC URL hostname inference (`devnet` / `testnet` substring → devnet)\n// 5. Mainnet default — gateway.iqlabs.dev\n//\n// Everything here is best-effort: an unreachable, misconfigured, or\n// disabled gateway never breaks the SDK.\n\nimport { getRpcUrl } from \"@iqlabs-official/solana-sdk\";\n\nconst MAINNET_GATEWAY = \"https://gateway.iqlabs.dev\";\nconst DEVNET_GATEWAY = \"https://dev-gateway.iqlabs.dev\";\nconst REQ_TIMEOUT_MS = 5000;\n\nlet runtimeGateways: string[] | null = null;\nlet networkOverride: \"mainnet\" | \"devnet\" | null = null;\n\n/** Pin the gateway URL list explicitly. Highest precedence. Pass `[]` to\n * disable gateway dispatch entirely (RPC-only mode). */\nexport function setGatewayUrls(urls: string[]): void {\n runtimeGateways = urls.length > 0 ? urls : null;\n}\n\n/** Pin the network label when the RPC URL doesn't reveal it (private nodes,\n * proxies, etc.). Has no effect when setGatewayUrls() is also set. */\nexport function setNetwork(network: \"mainnet\" | \"devnet\"): void {\n networkOverride = network;\n}\n\nfunction inferNetwork(): \"mainnet\" | \"devnet\" {\n if (networkOverride) return networkOverride;\n const u = getRpcUrl().toLowerCase();\n if (u.includes(\"devnet\") || u.includes(\"testnet\")) return \"devnet\";\n return \"mainnet\";\n}\n\nexport function getGatewayUrls(): string[] {\n if (runtimeGateways) return runtimeGateways;\n\n const env = (typeof process !== \"undefined\" && process.env?.IQGIT_GATEWAYS) ?? \"\";\n if (env) return env.split(\",\").map((s) => s.trim()).filter(Boolean);\n\n return inferNetwork() === \"devnet\" ? [DEVNET_GATEWAY] : [MAINNET_GATEWAY];\n}\n\nasync function tryGateways<T>(\n path: (gw: string) => string,\n parse: (res: Response) => Promise<T>,\n): Promise<T | null> {\n for (const gw of getGatewayUrls()) {\n try {\n const ctrl = new AbortController();\n const timer = setTimeout(() => ctrl.abort(), REQ_TIMEOUT_MS);\n const res = await fetch(path(gw), { signal: ctrl.signal });\n clearTimeout(timer);\n if (res.ok) return await parse(res);\n } catch {\n // Try the next gateway.\n }\n }\n return null;\n}\n\n/** Fetch rows for a table PDA via /table/:pda/rows. Returns null when no\n * gateway is configured or all of them fail — caller falls back to RPC. */\nexport async function readRowsViaGateway(\n pdaBase58: string,\n options?: { limit?: number; before?: string },\n): Promise<Array<Record<string, unknown>> | null> {\n const qs = new URLSearchParams();\n if (options?.limit) qs.set(\"limit\", String(options.limit));\n if (options?.before) qs.set(\"before\", options.before);\n const suffix = qs.toString() ? `?${qs}` : \"\";\n\n return tryGateways(\n (gw) => `${gw}/table/${pdaBase58}/rows${suffix}`,\n async (res) => {\n const json = (await res.json()) as { rows?: unknown[] };\n return (json.rows ?? []) as Array<Record<string, unknown>>;\n },\n );\n}\n\n/** Fetch raw codeIn payload via /data/:sig. Gateway returns a superset of\n * what the SDK's readCodeIn produces; we extract just the matching fields. */\nexport async function readCodeInViaGateway(\n txSig: string,\n): Promise<{ data: string | null; metadata: string } | null> {\n return tryGateways(\n (gw) => `${gw}/data/${txSig}`,\n async (res) => {\n const json = (await res.json()) as { data?: string | null; metadata?: string };\n return { data: json.data ?? null, metadata: json.metadata ?? \"\" };\n },\n );\n}\n\n/** Fire-and-forget /notify after a successful write. Includes the row body\n * so the gateway can inject without an RPC roundtrip. Errors are swallowed\n * — the row is already on-chain, gateway hydration is opportunistic. */\nexport function notifyGateways(\n pdaBase58: string,\n txSig: string,\n row: object,\n signer: string,\n): void {\n const body = JSON.stringify({ txSignature: txSig, row, signer });\n for (const gw of getGatewayUrls()) {\n fetch(`${gw}/table/${pdaBase58}/notify`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body,\n }).catch(() => {});\n }\n}\n","// L1 — chain primitives shared by L2/L3. Kept tiny by design: each function\n// here either (a) hides PDA derivation so callers only deal with hints, or\n// (b) wraps a single iqlabs-sdk call to keep an iq-git-specific default\n// (chunk speed, root id, ...). Pure passthroughs like `createTable` /\n// `writeRow` live at the call site instead — wrapping them once more would\n// just bury the iqlabs-sdk surface (CODE-RULES §1).\n//\n// Read primitives transparently prefer the iq-gateway HTTP API and fall\n// back to direct RPC; the gateway dispatch lives here so commit/repo/\n// storage all benefit without each having to wire it up.\n\nimport {\n Keypair,\n SystemProgram,\n Transaction,\n type Connection,\n type PublicKey,\n} from \"@solana/web3.js\";\nimport {\n createInstructionBuilder,\n getDbRootPda,\n getTablePda,\n initializeDbRootInstruction,\n} from \"@iqlabs-official/solana-sdk/contract\";\nimport { readCodeIn as sdkReadCodeIn, readTableRows } from \"@iqlabs-official/solana-sdk/reader\";\nimport { toSeedBytes, type SignerInput, type WalletSigner } from \"@iqlabs-official/solana-sdk/utils\";\nimport { codeIn as sdkCodeIn } from \"@iqlabs-official/solana-sdk/writer\";\nimport { IQGIT_ROOT_ID } from \"../core/seed\";\nimport { readCodeInViaGateway, readRowsViaGateway } from \"./gateway\";\n\n/** DbRoot PDA for the `iq-git-v1` namespace — derived once, reused everywhere. */\nexport const DB_ROOT_SEED = toSeedBytes(IQGIT_ROOT_ID);\nexport const DB_ROOT = getDbRootPda(DB_ROOT_SEED);\n\n/**\n * Initialize the `iq-git-v1` DbRoot account if it doesn't exist. First-call\n * cost on a fresh network. Idempotent: returns null if already initialized.\n * Accepts any SignerInput so an admin can run it from a wallet, not just\n * from a Keypair.\n */\nexport async function ensureDbRoot(\n connection: Connection,\n signer: SignerInput,\n): Promise<string | null> {\n if (await accountExists(connection, DB_ROOT)) return null;\n const builder = createInstructionBuilder();\n const ix = initializeDbRootInstruction(\n builder,\n {\n db_root: DB_ROOT,\n signer: signer.publicKey,\n system_program: SystemProgram.programId,\n },\n { db_root_id: DB_ROOT_SEED },\n );\n const tx = new Transaction().add(ix);\n const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash();\n tx.recentBlockhash = blockhash;\n tx.feePayer = signer.publicKey;\n const signed = await signTx(signer, tx);\n const signature = await connection.sendRawTransaction(signed.serialize());\n await connection.confirmTransaction({ signature, blockhash, lastValidBlockHeight });\n return signature;\n}\n\n// Sign a single Transaction with whatever shape the signer takes. Keypair\n// has a `secretKey`; wallet adapters expose `signTransaction`. iqlabs-sdk's\n// own `sendTx` uses the same dispatch; we replicate it here so the helper\n// stays self-contained.\nasync function signTx(signer: SignerInput, tx: Transaction): Promise<Transaction> {\n if (signer instanceof Keypair || \"secretKey\" in signer) {\n tx.partialSign(signer as Keypair);\n return tx;\n }\n return (signer as WalletSigner).signTransaction(tx);\n}\n\n/**\n * Read rows from a table. Tries the iq-gateway HTTP cache first and falls\n * back to `iqlabs.reader.readTableRows` on miss. Callers see a uniform API\n * either way.\n */\nexport async function readRows(\n hint: string,\n options?: { limit?: number; before?: string },\n): Promise<Array<Record<string, unknown>>> {\n return readRowsByPda(tablePda(hint), options);\n}\n\n/**\n * Same as readRows but keyed by the table PDA directly — for callers that\n * already have the PDA (e.g. a .sol record pointing at a commit table) and\n * can't or shouldn't re-derive it from a hint.\n */\nexport async function readRowsByPda(\n pda: PublicKey,\n options?: { limit?: number; before?: string },\n): Promise<Array<Record<string, unknown>>> {\n const viaGateway = await readRowsViaGateway(pda.toBase58(), options);\n if (viaGateway !== null) return viaGateway;\n return readTableRows(pda, options);\n}\n\n/**\n * Fetch just the latest row of a table — the fast path for \"what is the\n * current commit\" and \"what is the pinned deploy\".\n */\nexport async function readLatestRow(\n hint: string,\n): Promise<Record<string, unknown> | null> {\n const rows = await readRows(hint, { limit: 1 });\n return rows[0] ?? null;\n}\n\n/**\n * Upload a blob via `iqlabs.writer.codeIn`. The SDK chunks internally when\n * `data` is a plain string. We default speed to \"light\" because that's the\n * Helius-friendly setting for git workloads (per-file uploads are bursty).\n */\nexport async function codeIn(\n connection: Connection,\n signer: SignerInput,\n data: string | string[],\n filename: string,\n filetype: string,\n onProgress?: (percent: number) => void,\n speed: \"light\" | \"medium\" | \"fast\" = \"light\",\n): Promise<string> {\n return sdkCodeIn(\n { connection, signer },\n data,\n filename,\n 0,\n filetype,\n onProgress,\n speed,\n );\n}\n\n/**\n * Read a codeIn payload by tx signature. Tries the gateway /data/:sig\n * cache first and falls back to the SDK's direct RPC decode.\n */\nexport async function readCodeIn(\n txSig: string,\n): Promise<{ data: string | null; metadata: string }> {\n const viaGateway = await readCodeInViaGateway(txSig);\n if (viaGateway !== null) return viaGateway;\n return sdkReadCodeIn(txSig);\n}\n\n/** Cheap existence check for a PDA. */\nexport async function accountExists(\n connection: Connection,\n pda: PublicKey,\n): Promise<boolean> {\n return (await connection.getAccountInfo(pda)) !== null;\n}\n\n/** Resolve a hint to its PDA. */\nexport function tablePda(hint: string): PublicKey {\n return getTablePda(DB_ROOT, toSeedBytes(hint));\n}\n","// L3 — per-repo commit table.\n//\n// v2's core invariant: each repo has its own table at hint\n// `git_commits:<owner>:<repo>`, with writers locked to [owner]. That means\n// \"the most recent successful tx in this table = the latest commit\", and we\n// read it as a single-row query (limit: 1).\n\nimport type { Connection, PublicKey } from \"@solana/web3.js\";\nimport { type SignerInput } from \"@iqlabs-official/solana-sdk/utils\";\nimport { createTable, writeRow } from \"@iqlabs-official/solana-sdk/writer\";\nimport { IQGIT_ROOT_ID, commitTableHint } from \"../core/seed\";\nimport type { Commit } from \"../core/types\";\nimport * as chain from \"./chain\";\nimport { notifyGateways } from \"./gateway\";\n\nconst COMMIT_COLUMNS = [\n \"id\",\n \"message\",\n \"treeTxId\",\n \"parentCommitId\",\n \"timestamp\",\n \"author\",\n];\n\n/**\n * Ensure the per-repo commit table exists with writers = [owner]. No-op if\n * it already exists.\n */\nexport async function ensureCommitTable(\n connection: Connection,\n signer: SignerInput,\n repo: string,\n): Promise<string | null> {\n const hint = commitTableHint(signer.publicKey.toBase58(), repo);\n if (await chain.accountExists(connection, chain.tablePda(hint))) return null;\n return createTable(\n connection,\n signer,\n IQGIT_ROOT_ID,\n hint,\n hint,\n COMMIT_COLUMNS,\n \"id\",\n [],\n undefined,\n [signer.publicKey],\n hint,\n );\n}\n\n/**\n * Append one commit row. Callers (workflow-level code) are responsible for\n * setting parentCommitId — the SDK does not auto-chain.\n *\n * After the row lands on-chain, fires a best-effort /notify so any\n * iq-gateway already caching this table prepends the new commit without\n * waiting for RPC sig indexing.\n */\nexport async function writeCommit(\n connection: Connection,\n signer: SignerInput,\n repo: string,\n commit: Commit,\n): Promise<string> {\n const owner = signer.publicKey.toBase58();\n const hint = commitTableHint(owner, repo);\n const sig = await writeRow(\n connection,\n signer,\n IQGIT_ROOT_ID,\n hint,\n JSON.stringify(commit),\n );\n notifyGateways(chain.tablePda(hint).toBase58(), sig, commit, owner);\n return sig;\n}\n\n/** The commit-table PDA for a repo. The one place owner/repo collapses to a\n * PDA — every read keys off the PDA, so callers that have a PDA already (a\n * .sol record, a dbroot match) skip this and pass it straight in. */\nexport function commitTablePda(owner: string, repo: string): PublicKey {\n return chain.tablePda(commitTableHint(owner, repo));\n}\n\n/** Latest commit. Single-row, O(1) RPC path. */\nexport async function readLatestCommit(pda: PublicKey): Promise<Commit | null> {\n const rows = await chain.readRowsByPda(pda, { limit: 1 });\n return (rows[0] as unknown as Commit) ?? null;\n}\n\n/** Full commit history, newest first. */\nexport async function readCommitHistory(\n pda: PublicKey,\n options?: { limit?: number; before?: string },\n): Promise<Commit[]> {\n const rows = await chain.readRowsByPda(pda, options);\n return rows as unknown as Commit[];\n}\n","// L3 — repo list and public registry.\n//\n// Covers the two \"directory\" tables:\n// • git_repos_v2_<owner> — owner's personal repo list (writers = [owner])\n// • git_repos:all — public gallery registry (writers = [])\n//\n// Commit tables are a separate concern — see `commit.ts`.\n\nimport type { Connection } from \"@solana/web3.js\";\nimport { type SignerInput } from \"@iqlabs-official/solana-sdk/utils\";\nimport { createTable, writeRow } from \"@iqlabs-official/solana-sdk/writer\";\nimport { IQGIT_ROOT_ID, REGISTRY_HINT, repoListHint } from \"../core/seed\";\nimport type { RegistryEntry, Repository } from \"../core/types\";\nimport * as chain from \"./chain\";\nimport { notifyGateways } from \"./gateway\";\n\nconst REPO_COLUMNS = [\"name\", \"description\", \"isPublic\", \"timestamp\"];\nconst REGISTRY_COLUMNS = [\"owner\", \"repo\", \"description\", \"timestamp\"];\n\n/**\n * Create a repo in the owner's personal list, and (if public) also register\n * it in the public gallery. Two transactions — the contract does not support\n * writing two tables atomically.\n *\n * Returns the writeRow tx signatures (and the table hint each one wrote to)\n * so a caller can notify gateways / build SSE streams for those tables. The\n * returned shape is `[]` from `createTable` calls because those don't write\n * a row, just allocate the account.\n */\nexport async function createRepo(\n connection: Connection,\n signer: SignerInput,\n meta: Repository,\n): Promise<Array<{ tableHint: string; sig: string; row: object }>> {\n const owner = signer.publicKey.toBase58();\n const listHint = repoListHint(owner);\n const writes: Array<{ tableHint: string; sig: string; row: object }> = [];\n\n if (!(await chain.accountExists(connection, chain.tablePda(listHint)))) {\n await createTable(\n connection,\n signer,\n IQGIT_ROOT_ID,\n listHint,\n listHint,\n REPO_COLUMNS,\n \"name\",\n [],\n undefined,\n [signer.publicKey],\n listHint,\n );\n }\n\n const sig = await writeRow(connection, signer, IQGIT_ROOT_ID, listHint, JSON.stringify(meta));\n writes.push({ tableHint: listHint, sig, row: meta });\n notifyGateways(chain.tablePda(listHint).toBase58(), sig, meta, owner);\n\n if (meta.isPublic) {\n const entry: RegistryEntry = {\n owner,\n repo: meta.name,\n description: meta.description,\n timestamp: meta.timestamp,\n };\n const regSig = await writeRow(connection, signer, IQGIT_ROOT_ID, REGISTRY_HINT, JSON.stringify(entry));\n writes.push({ tableHint: REGISTRY_HINT, sig: regSig, row: entry });\n notifyGateways(chain.tablePda(REGISTRY_HINT).toBase58(), regSig, entry, owner);\n }\n\n return writes;\n}\n\n/** List all repos owned by `owner`. */\nexport async function readOwnerRepos(\n _connection: Connection,\n owner: string,\n): Promise<Repository[]> {\n return (await chain.readRows(repoListHint(owner))) as unknown as Repository[];\n}\n\n/**\n * One page of the public-gallery registry. Callers should still check\n * `row.owner` shape before trusting it in UI; we do not filter at the SDK\n * boundary.\n */\nexport async function readRegistryPage(\n _connection: Connection,\n options?: { limit?: number; before?: string },\n): Promise<RegistryEntry[]> {\n return (await chain.readRows(REGISTRY_HINT, options)) as unknown as RegistryEntry[];\n}\n\n/**\n * One-time global bootstrap of the `git_repos:all` table. Run once per\n * network from an admin key; subsequent calls short-circuit because the\n * account already exists.\n */\nexport async function bootstrapRegistry(\n connection: Connection,\n signer: SignerInput,\n): Promise<string | null> {\n await chain.ensureDbRoot(connection, signer);\n if (await chain.accountExists(connection, chain.tablePda(REGISTRY_HINT))) {\n return null;\n }\n return createTable(\n connection,\n signer,\n IQGIT_ROOT_ID,\n REGISTRY_HINT,\n REGISTRY_HINT,\n REGISTRY_COLUMNS,\n \"owner\",\n [],\n undefined,\n undefined,\n REGISTRY_HINT,\n );\n}\n","// L2 — blob + tree storage.\n//\n// `uploadBlob` is the file-level \"don't re-upload what's already on-chain\"\n// primitive. Content is always a base64 string (matching iq-git v1) so the\n// hash / dedup comparison stays byte-for-byte compatible across commits.\n// The reuse-map is just a plain object so callers can build it any way they\n// like (path→entry, or hash→txId for rename-aware dedup — CODE-RULES §3\n// keeps this inlined at the call site instead of a new type).\n//\n// `uploadTree` / `loadTree` serialize FileTree <-> on-chain tree.json as raw\n// JSON (filetype `application/json`), again matching v1.\n\nimport type { Connection } from \"@solana/web3.js\";\nimport type { SignerInput } from \"@iqlabs-official/solana-sdk/utils\";\nimport { sha256Hex } from \"../core/hash\";\nimport type { FileTree } from \"../core/types\";\nimport * as chain from \"./chain\";\n\n/**\n * Upload one file unless an identical hash is already in `reuse` (blob dedup).\n *\n * input: connection, signer, relativePath, base64 content, reuse map, optional onProgress\n * output: { txId, hash } — either reused or freshly uploaded\n */\nexport async function uploadBlob(\n connection: Connection,\n signer: SignerInput,\n relativePath: string,\n base64Content: string,\n reuse: FileTree,\n onProgress?: (percent: number) => void,\n): Promise<{ txId: string; hash: string }> {\n const hash = await sha256Hex(base64Content);\n const prior = reuse[relativePath];\n if (prior && prior.hash === hash) return prior;\n\n // Tag the codeIn filename with our app marker so non-inline inventory\n // entries can be classified by inspecting metadata.filename alone (no row\n // body fetch needed). Format: \"iqgit-blob:<basename>\". Same scheme used\n // for trees (\"iqgit-tree\") and other writes across the IQ ecosystem.\n const basename = relativePath.split(\"/\").pop() || relativePath;\n const txId = await chain.codeIn(\n connection,\n signer,\n base64Content,\n `iqgit-blob:${basename}`,\n \"application/octet-stream\",\n onProgress,\n );\n return { txId, hash };\n}\n\n/**\n * Serialize a FileTree and upload it as one `tree.json` blob.\n */\nexport async function uploadTree(\n connection: Connection,\n signer: SignerInput,\n tree: FileTree,\n): Promise<string> {\n return chain.codeIn(\n connection,\n signer,\n JSON.stringify(tree),\n \"iqgit-tree\",\n \"application/json\",\n );\n}\n\n/**\n * Fetch and parse a `tree.json` blob by its tx signature.\n */\nexport async function loadTree(treeTxId: string): Promise<FileTree> {\n const { data } = await chain.readCodeIn(treeTxId);\n if (data === null) {\n throw new Error(`tree.json not found for tx ${treeTxId}`);\n }\n return JSON.parse(data) as FileTree;\n}\n\n/**\n * Retrieve a blob's bytes by its txId. Returns the raw string that was\n * uploaded — for blobs this is base64; the caller decodes.\n */\nexport async function loadBlob(txId: string): Promise<string> {\n const { data } = await chain.readCodeIn(txId);\n if (data === null) {\n throw new Error(`blob not found for tx ${txId}`);\n }\n return data;\n}\n","// L4 — GitClient facade. High-level workflows built by composing the\n// layers below. This is the surface consumers (CLI, frontend, migrator) use;\n// they should not reach into `chain` / `storage` / `repo` / `commit` directly.\n//\n// Keep workflow logic here, not inside lower layers (CODE-RULES §5). When a\n// command needs scanning, hashing, uploading, row writing — this file\n// orchestrates them all.\n\nimport type { Connection } from \"@solana/web3.js\";\nimport { setRpcUrl } from \"@iqlabs-official/solana-sdk\";\nimport type { SignerInput } from \"@iqlabs-official/solana-sdk/utils\";\nimport { sha256Hex } from \"../core/hash\";\nimport { commitTableHint } from \"../core/seed\";\nimport type { Commit, FileTree, Repository } from \"../core/types\";\nimport * as chain from \"./chain\";\nimport * as commitLayer from \"./commit\";\nimport * as repoLayer from \"./repo\";\nimport * as storage from \"./storage\";\n\n/** Information surfaced to the `onWrite` callback for every successful row\n * write the SDK performs. Consumers wire this to their gateway notify so\n * the gateway updates its cache / SSE stream immediately. */\nexport interface WriteEvent {\n /** Resolved table PDA, base58 — pass directly to gateway notify. */\n tablePda: string;\n /** The hint that derived the PDA, in case callers want to log it. */\n tableHint: string;\n /** writeRow tx signature. */\n sig: string;\n /** The row object that was written (already JSON.stringify-able). */\n row: object;\n}\n\nexport interface GitClientConfig {\n connection: Connection;\n signer: SignerInput;\n /** Fires after each successful row write inside the SDK. Fire-and-forget\n * callback for gateway notifies; throwing here will surface to the caller. */\n onWrite?: (event: WriteEvent) => void;\n}\n\nexport class GitClient {\n // CODE-RULES §3 — only one small shape; inlined rather than aliased.\n constructor(private readonly cfg: GitClientConfig) {\n // The solana-sdk reader path (readTableRows / readCodeIn → loadTree /\n // readLatestCommit) does not take a Connection — it resolves a\n // process-global one from env / setRpcUrl. Writes use `cfg.connection`,\n // so without this reads could hit a different RPC (e.g. the mainnet-beta\n // fallback when no env is set, as in a built browser bundle). Sync the\n // reader's RPC to the connection the caller actually gave us.\n setRpcUrl(cfg.connection.rpcEndpoint);\n }\n\n /**\n * Create a new repo. Wraps repo.createRepo + pre-creating the commit table\n * so the first `commit()` call doesn't need to pay createTable cost.\n */\n async createRepo(meta: Repository): Promise<void> {\n const { connection, signer } = this.cfg;\n const writes = await repoLayer.createRepo(connection, signer, meta);\n await commitLayer.ensureCommitTable(connection, signer, meta.name);\n this.fireOnWrite(writes);\n }\n\n /**\n * Incremental commit against a scanned directory snapshot.\n *\n * input: repoName, message, scan — a `{ [path]: base64Content }` map that\n * the caller produced (Node: fs walk + base64; browser: File input).\n * output: newly written Commit\n */\n async commit(\n repoName: string,\n message: string,\n scan: Record<string, string>,\n ): Promise<Commit> {\n const { connection, signer } = this.cfg;\n const owner = signer.publicKey.toBase58();\n\n const latest = await commitLayer.readLatestCommit(commitLayer.commitTablePda(owner, repoName));\n const oldTree: FileTree = latest ? await storage.loadTree(latest.treeTxId) : {};\n\n const newTree: FileTree = {};\n for (const [path, content] of Object.entries(scan)) {\n newTree[path] = await storage.uploadBlob(\n connection,\n signer,\n path,\n content,\n oldTree,\n );\n }\n\n const treeTxId = await storage.uploadTree(connection, signer, newTree);\n\n const commit: Commit = {\n id: crypto.randomUUID(),\n message,\n treeTxId,\n parentCommitId: latest?.id,\n timestamp: Date.now(),\n author: owner,\n };\n const sig = await commitLayer.writeCommit(connection, signer, repoName, commit);\n this.fireOnWrite([{ tableHint: commitTableHint(owner, repoName), sig, row: commit }]);\n return commit;\n }\n\n /** Resolve the table hint to a PDA and forward each write to `onWrite`.\n * Wrapped in try/catch per call so a misbehaving notify can't fail the\n * whole batch — but we still surface the error so the consumer knows. */\n private fireOnWrite(writes: Array<{ tableHint: string; sig: string; row: object }>) {\n if (!this.cfg.onWrite) return;\n for (const w of writes) {\n const tablePda = chain.tablePda(w.tableHint).toBase58();\n this.cfg.onWrite({ tablePda, tableHint: w.tableHint, sig: w.sig, row: w.row });\n }\n }\n\n /**\n * Restore a commit's files into a caller-provided sink. Runtime-neutral\n * shape mirrors `commit`: the caller decides how to write bytes to disk /\n * to a File System Access API handle / anywhere else. `content` is the\n * raw base64 string — the sink decodes.\n */\n async checkout(\n repoName: string,\n commitId: string | \"latest\",\n sink: (path: string, content: string) => Promise<void>,\n ): Promise<Commit> {\n const { connection, signer } = this.cfg;\n const owner = signer.publicKey.toBase58();\n\n const pda = commitLayer.commitTablePda(owner, repoName);\n let target: Commit | null;\n if (commitId === \"latest\") {\n target = await commitLayer.readLatestCommit(pda);\n } else {\n const history = await commitLayer.readCommitHistory(pda);\n target = history.find((c) => c.id === commitId) ?? null;\n }\n if (!target) {\n throw new Error(`commit not found: ${commitId} in ${owner}/${repoName}`);\n }\n\n const tree = await storage.loadTree(target.treeTxId);\n for (const [path, entry] of Object.entries(tree)) {\n const content = await storage.loadBlob(entry.txId);\n await sink(path, content);\n }\n return target;\n }\n\n /**\n * Whole-repo snapshot download — convenience on top of checkout(\"latest\")\n * but reading from someone else's `owner`. We do not require signer to\n * equal owner for reads.\n */\n async clone(\n repoName: string,\n owner: string,\n sink: (path: string, content: string) => Promise<void>,\n ): Promise<Commit> {\n const target = await commitLayer.readLatestCommit(commitLayer.commitTablePda(owner, repoName));\n if (!target) {\n throw new Error(`no commits in ${owner}/${repoName}`);\n }\n const tree = await storage.loadTree(target.treeTxId);\n for (const [path, entry] of Object.entries(tree)) {\n const content = await storage.loadBlob(entry.txId);\n await sink(path, content);\n }\n return target;\n }\n\n /** Commit history for a repo. */\n async log(\n owner: string,\n repoName: string,\n options?: { limit?: number; before?: string },\n ): Promise<Commit[]> {\n return commitLayer.readCommitHistory(commitLayer.commitTablePda(owner, repoName), options);\n }\n\n /**\n * Compare a current directory snapshot to the latest commit's tree.\n */\n async status(\n owner: string,\n repoName: string,\n scan: Record<string, string>,\n ): Promise<{ added: string[]; modified: string[]; unchanged: string[] }> {\n const latest = await commitLayer.readLatestCommit(commitLayer.commitTablePda(owner, repoName));\n const tree: FileTree = latest ? await storage.loadTree(latest.treeTxId) : {};\n\n const added: string[] = [];\n const modified: string[] = [];\n const unchanged: string[] = [];\n for (const [path, content] of Object.entries(scan)) {\n const prior = tree[path];\n if (!prior) {\n added.push(path);\n continue;\n }\n const hash = await sha256Hex(content);\n (prior.hash === hash ? unchanged : modified).push(path);\n }\n return { added, modified, unchanged };\n }\n}\n","// Browser entry. Installs the Web-Crypto SHA-256 hasher, then re-exports\n// everything from the shared root.\n\nimport { setSha256 } from \"./core/hash\";\nimport { hashBrowser } from \"./platform/hash-browser\";\n\nsetSha256(hashBrowser);\n\nexport * from \"./index\";\n"]}
|
package/dist/node/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { Commit, FileTree, GitClient, GitClientConfig, IQGIT_ROOT_ID, REGISTRY_HINT, RegistryEntry, Repository, WriteEvent, bootstrapRegistry, commitTableHint, getGatewayUrls, loadBlob, loadTree, readCommitHistory,
|
|
1
|
+
export { Commit, FileTree, GitClient, GitClientConfig, IQGIT_ROOT_ID, REGISTRY_HINT, RegistryEntry, Repository, WriteEvent, bootstrapRegistry, commitTableHint, commitTablePda, getGatewayUrls, loadBlob, loadTree, readCommitHistory, readLatestCommit, readOwnerRepos, readRegistryPage, repoListHint, setGatewayUrls, setNetwork, uploadBlob, uploadTree, writeCommit } from '../shared/index.js';
|
|
2
2
|
export { SignerInput } from '@iqlabs-official/solana-sdk/utils';
|
|
3
3
|
import '@solana/web3.js';
|
package/dist/node/index.js
CHANGED
|
@@ -144,10 +144,6 @@ async function readRowsByPda(pda, options) {
|
|
|
144
144
|
if (viaGateway !== null) return viaGateway;
|
|
145
145
|
return readTableRows(pda, options);
|
|
146
146
|
}
|
|
147
|
-
async function readLatestRow(hint) {
|
|
148
|
-
const rows = await readRows(hint, { limit: 1 });
|
|
149
|
-
return rows[0] ?? null;
|
|
150
|
-
}
|
|
151
147
|
async function codeIn(connection, signer, data, filename, filetype, onProgress, speed = "light") {
|
|
152
148
|
return codeIn$1(
|
|
153
149
|
{ connection, signer },
|
|
@@ -208,15 +204,14 @@ async function writeCommit(connection, signer, repo, commit) {
|
|
|
208
204
|
notifyGateways(tablePda(hint).toBase58(), sig, commit, owner);
|
|
209
205
|
return sig;
|
|
210
206
|
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
return row;
|
|
207
|
+
function commitTablePda(owner, repo) {
|
|
208
|
+
return tablePda(commitTableHint(owner, repo));
|
|
214
209
|
}
|
|
215
|
-
async function
|
|
216
|
-
const rows = await
|
|
217
|
-
return rows;
|
|
210
|
+
async function readLatestCommit(pda) {
|
|
211
|
+
const rows = await readRowsByPda(pda, { limit: 1 });
|
|
212
|
+
return rows[0] ?? null;
|
|
218
213
|
}
|
|
219
|
-
async function
|
|
214
|
+
async function readCommitHistory(pda, options) {
|
|
220
215
|
const rows = await readRowsByPda(pda, options);
|
|
221
216
|
return rows;
|
|
222
217
|
}
|
|
@@ -351,7 +346,7 @@ var GitClient = class {
|
|
|
351
346
|
async commit(repoName, message, scan) {
|
|
352
347
|
const { connection, signer } = this.cfg;
|
|
353
348
|
const owner = signer.publicKey.toBase58();
|
|
354
|
-
const latest = await readLatestCommit(
|
|
349
|
+
const latest = await readLatestCommit(commitTablePda(owner, repoName));
|
|
355
350
|
const oldTree = latest ? await loadTree(latest.treeTxId) : {};
|
|
356
351
|
const newTree = {};
|
|
357
352
|
for (const [path, content] of Object.entries(scan)) {
|
|
@@ -395,11 +390,12 @@ var GitClient = class {
|
|
|
395
390
|
async checkout(repoName, commitId, sink) {
|
|
396
391
|
const { connection, signer } = this.cfg;
|
|
397
392
|
const owner = signer.publicKey.toBase58();
|
|
393
|
+
const pda = commitTablePda(owner, repoName);
|
|
398
394
|
let target;
|
|
399
395
|
if (commitId === "latest") {
|
|
400
|
-
target = await readLatestCommit(
|
|
396
|
+
target = await readLatestCommit(pda);
|
|
401
397
|
} else {
|
|
402
|
-
const history = await readCommitHistory(
|
|
398
|
+
const history = await readCommitHistory(pda);
|
|
403
399
|
target = history.find((c) => c.id === commitId) ?? null;
|
|
404
400
|
}
|
|
405
401
|
if (!target) {
|
|
@@ -418,8 +414,7 @@ var GitClient = class {
|
|
|
418
414
|
* equal owner for reads.
|
|
419
415
|
*/
|
|
420
416
|
async clone(repoName, owner, sink) {
|
|
421
|
-
const
|
|
422
|
-
const target = await readLatestCommit(connection, owner, repoName);
|
|
417
|
+
const target = await readLatestCommit(commitTablePda(owner, repoName));
|
|
423
418
|
if (!target) {
|
|
424
419
|
throw new Error(`no commits in ${owner}/${repoName}`);
|
|
425
420
|
}
|
|
@@ -432,22 +427,13 @@ var GitClient = class {
|
|
|
432
427
|
}
|
|
433
428
|
/** Commit history for a repo. */
|
|
434
429
|
async log(owner, repoName, options) {
|
|
435
|
-
return readCommitHistory(
|
|
436
|
-
this.cfg.connection,
|
|
437
|
-
owner,
|
|
438
|
-
repoName,
|
|
439
|
-
options
|
|
440
|
-
);
|
|
430
|
+
return readCommitHistory(commitTablePda(owner, repoName), options);
|
|
441
431
|
}
|
|
442
432
|
/**
|
|
443
433
|
* Compare a current directory snapshot to the latest commit's tree.
|
|
444
434
|
*/
|
|
445
435
|
async status(owner, repoName, scan) {
|
|
446
|
-
const latest = await readLatestCommit(
|
|
447
|
-
this.cfg.connection,
|
|
448
|
-
owner,
|
|
449
|
-
repoName
|
|
450
|
-
);
|
|
436
|
+
const latest = await readLatestCommit(commitTablePda(owner, repoName));
|
|
451
437
|
const tree = latest ? await loadTree(latest.treeTxId) : {};
|
|
452
438
|
const added = [];
|
|
453
439
|
const modified = [];
|
|
@@ -468,6 +454,6 @@ var GitClient = class {
|
|
|
468
454
|
// src/node.ts
|
|
469
455
|
setSha256(hashNode);
|
|
470
456
|
|
|
471
|
-
export { GitClient, IQGIT_ROOT_ID, REGISTRY_HINT, bootstrapRegistry, commitTableHint, getGatewayUrls, loadBlob, loadTree, readCommitHistory,
|
|
457
|
+
export { GitClient, IQGIT_ROOT_ID, REGISTRY_HINT, bootstrapRegistry, commitTableHint, commitTablePda, getGatewayUrls, loadBlob, loadTree, readCommitHistory, readLatestCommit, readOwnerRepos, readRegistryPage, repoListHint, setGatewayUrls, setNetwork, uploadBlob, uploadTree, writeCommit };
|
|
472
458
|
//# sourceMappingURL=index.js.map
|
|
473
459
|
//# sourceMappingURL=index.js.map
|
package/dist/node/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/core/hash.ts","../../src/platform/hash-node.ts","../../src/core/seed.ts","../../src/layers/gateway.ts","../../src/layers/chain.ts","../../src/layers/commit.ts","../../src/layers/repo.ts","../../src/layers/storage.ts","../../src/layers/client.ts","../../src/node.ts"],"names":["sdkCodeIn","sdkReadCodeIn","createTable","writeRow","tablePda"],"mappings":"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","file":"index.js","sourcesContent":["// SHA-256 content hashing for the blob-dedup index. Runtime-specific\n// implementations live in `platform/hash-node.ts` and `platform/hash-browser.ts`;\n// this module just declares the interface the rest of the SDK uses.\n//\n// Do NOT use this for deriving table seeds — that path is owned by\n// `iqlabs.utils.toSeedBytes` (keccak) and must stay aligned with the SDK.\n\n/**\n * SHA-256 of a UTF-8 or base64 string, returned as a lowercase hex digest.\n * Implementation is injected by the platform entry (node.ts / browser.ts).\n */\nexport type Sha256Hex = (input: string) => Promise<string>;\n\n// Platform entries (src/node.ts, src/browser.ts) will call `setSha256(...)`\n// during module init so downstream layers never care which runtime they are in.\n// This indirection is the one place where a wrapper is justified (CODE-RULES §1)\n// because the behavior genuinely differs per runtime.\nlet impl: Sha256Hex | undefined;\n\nexport function setSha256(fn: Sha256Hex): void {\n if (impl) {\n throw new Error(\n \"@iqlabs-official/git-sdk: sha256 implementation already installed. Import exactly one of '@iqlabs-official/git-sdk/node' or '@iqlabs-official/git-sdk/browser'.\",\n );\n }\n impl = fn;\n}\n\nexport async function sha256Hex(input: string): Promise<string> {\n if (!impl) {\n throw new Error(\n \"@iqlabs-official/git-sdk: sha256 not installed. Import '@iqlabs-official/git-sdk/node' (Node) or '@iqlabs-official/git-sdk/browser' (browser) before using the SDK.\",\n );\n }\n return impl(input);\n}\n","// Node SHA-256 implementation. Kept as a pure export; `src/node.ts` installs\n// it via `setSha256` during its own module init.\n\nimport { createHash } from \"node:crypto\";\nimport type { Sha256Hex } from \"../core/hash\";\n\nexport const hashNode: Sha256Hex = async (input) =>\n createHash(\"sha256\").update(input).digest(\"hex\");\n","// The single source of truth for table_hint strings.\n//\n// Readers re-derive PDAs with `iqlabs.utils.toSeedBytes(hint)` →\n// `iqlabs.contract.getTablePda(...)`; writers pass the same hint into\n// `iqlabs.writer.createTable`. Keeping the naming convention in one place\n// prevents silent drift between writer and reader. CODE-RULES §2 — if any\n// caller ever wants to build one of these strings inline, route it here\n// instead.\n\n/** DbRoot id for every iq-git table. Bootstrap and every caller share this. */\nexport const IQGIT_ROOT_ID = \"iq-git-v1\";\n\n/** `git_repos:all` — open-writers registry that drives the public gallery. */\nexport const REGISTRY_HINT = \"git_repos:all\";\n\n/**\n * Hint for the per-owner personal repo list.\n * input: owner wallet base58\n * output: \"git_repos_v2_<owner>\"\n */\nexport function repoListHint(owner: string): string {\n return `git_repos_v2_${owner}`;\n}\n\n/**\n * Hint for the per-repo commit table.\n * input: owner wallet base58, repo name (any characters — SDK keccak-hashes)\n * output: \"git_commits:<owner>:<repo>\"\n */\nexport function commitTableHint(owner: string, repo: string): string {\n return `git_commits:${owner}:${repo}`;\n}\n","// L1.5 — iq-gateway HTTP helpers.\n//\n// chain.ts dispatches reads through here first; on a null return it falls\n// back to direct RPC. Writers fire-and-forget a notify so the gateway can\n// prepend the new row to its head-page cache without waiting on RPC\n// indexing.\n//\n// Configuration precedence (high → low):\n// 1. setGatewayUrls([...]) — explicit URL list\n// 2. IQGIT_GATEWAYS env (csv) — deployment-side pinning\n// 3. setNetwork(\"devnet\"|\"mainnet\") + the network's default gateway\n// 4. RPC URL hostname inference (`devnet` / `testnet` substring → devnet)\n// 5. Mainnet default — gateway.iqlabs.dev\n//\n// Everything here is best-effort: an unreachable, misconfigured, or\n// disabled gateway never breaks the SDK.\n\nimport { getRpcUrl } from \"@iqlabs-official/solana-sdk\";\n\nconst MAINNET_GATEWAY = \"https://gateway.iqlabs.dev\";\nconst DEVNET_GATEWAY = \"https://dev-gateway.iqlabs.dev\";\nconst REQ_TIMEOUT_MS = 5000;\n\nlet runtimeGateways: string[] | null = null;\nlet networkOverride: \"mainnet\" | \"devnet\" | null = null;\n\n/** Pin the gateway URL list explicitly. Highest precedence. Pass `[]` to\n * disable gateway dispatch entirely (RPC-only mode). */\nexport function setGatewayUrls(urls: string[]): void {\n runtimeGateways = urls.length > 0 ? urls : null;\n}\n\n/** Pin the network label when the RPC URL doesn't reveal it (private nodes,\n * proxies, etc.). Has no effect when setGatewayUrls() is also set. */\nexport function setNetwork(network: \"mainnet\" | \"devnet\"): void {\n networkOverride = network;\n}\n\nfunction inferNetwork(): \"mainnet\" | \"devnet\" {\n if (networkOverride) return networkOverride;\n const u = getRpcUrl().toLowerCase();\n if (u.includes(\"devnet\") || u.includes(\"testnet\")) return \"devnet\";\n return \"mainnet\";\n}\n\nexport function getGatewayUrls(): string[] {\n if (runtimeGateways) return runtimeGateways;\n\n const env = (typeof process !== \"undefined\" && process.env?.IQGIT_GATEWAYS) ?? \"\";\n if (env) return env.split(\",\").map((s) => s.trim()).filter(Boolean);\n\n return inferNetwork() === \"devnet\" ? [DEVNET_GATEWAY] : [MAINNET_GATEWAY];\n}\n\nasync function tryGateways<T>(\n path: (gw: string) => string,\n parse: (res: Response) => Promise<T>,\n): Promise<T | null> {\n for (const gw of getGatewayUrls()) {\n try {\n const ctrl = new AbortController();\n const timer = setTimeout(() => ctrl.abort(), REQ_TIMEOUT_MS);\n const res = await fetch(path(gw), { signal: ctrl.signal });\n clearTimeout(timer);\n if (res.ok) return await parse(res);\n } catch {\n // Try the next gateway.\n }\n }\n return null;\n}\n\n/** Fetch rows for a table PDA via /table/:pda/rows. Returns null when no\n * gateway is configured or all of them fail — caller falls back to RPC. */\nexport async function readRowsViaGateway(\n pdaBase58: string,\n options?: { limit?: number; before?: string },\n): Promise<Array<Record<string, unknown>> | null> {\n const qs = new URLSearchParams();\n if (options?.limit) qs.set(\"limit\", String(options.limit));\n if (options?.before) qs.set(\"before\", options.before);\n const suffix = qs.toString() ? `?${qs}` : \"\";\n\n return tryGateways(\n (gw) => `${gw}/table/${pdaBase58}/rows${suffix}`,\n async (res) => {\n const json = (await res.json()) as { rows?: unknown[] };\n return (json.rows ?? []) as Array<Record<string, unknown>>;\n },\n );\n}\n\n/** Fetch raw codeIn payload via /data/:sig. Gateway returns a superset of\n * what the SDK's readCodeIn produces; we extract just the matching fields. */\nexport async function readCodeInViaGateway(\n txSig: string,\n): Promise<{ data: string | null; metadata: string } | null> {\n return tryGateways(\n (gw) => `${gw}/data/${txSig}`,\n async (res) => {\n const json = (await res.json()) as { data?: string | null; metadata?: string };\n return { data: json.data ?? null, metadata: json.metadata ?? \"\" };\n },\n );\n}\n\n/** Fire-and-forget /notify after a successful write. Includes the row body\n * so the gateway can inject without an RPC roundtrip. Errors are swallowed\n * — the row is already on-chain, gateway hydration is opportunistic. */\nexport function notifyGateways(\n pdaBase58: string,\n txSig: string,\n row: object,\n signer: string,\n): void {\n const body = JSON.stringify({ txSignature: txSig, row, signer });\n for (const gw of getGatewayUrls()) {\n fetch(`${gw}/table/${pdaBase58}/notify`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body,\n }).catch(() => {});\n }\n}\n","// L1 — chain primitives shared by L2/L3. Kept tiny by design: each function\n// here either (a) hides PDA derivation so callers only deal with hints, or\n// (b) wraps a single iqlabs-sdk call to keep an iq-git-specific default\n// (chunk speed, root id, ...). Pure passthroughs like `createTable` /\n// `writeRow` live at the call site instead — wrapping them once more would\n// just bury the iqlabs-sdk surface (CODE-RULES §1).\n//\n// Read primitives transparently prefer the iq-gateway HTTP API and fall\n// back to direct RPC; the gateway dispatch lives here so commit/repo/\n// storage all benefit without each having to wire it up.\n\nimport {\n Keypair,\n SystemProgram,\n Transaction,\n type Connection,\n type PublicKey,\n} from \"@solana/web3.js\";\nimport {\n createInstructionBuilder,\n getDbRootPda,\n getTablePda,\n initializeDbRootInstruction,\n} from \"@iqlabs-official/solana-sdk/contract\";\nimport { readCodeIn as sdkReadCodeIn, readTableRows } from \"@iqlabs-official/solana-sdk/reader\";\nimport { toSeedBytes, type SignerInput, type WalletSigner } from \"@iqlabs-official/solana-sdk/utils\";\nimport { codeIn as sdkCodeIn } from \"@iqlabs-official/solana-sdk/writer\";\nimport { IQGIT_ROOT_ID } from \"../core/seed\";\nimport { readCodeInViaGateway, readRowsViaGateway } from \"./gateway\";\n\n/** DbRoot PDA for the `iq-git-v1` namespace — derived once, reused everywhere. */\nexport const DB_ROOT_SEED = toSeedBytes(IQGIT_ROOT_ID);\nexport const DB_ROOT = getDbRootPda(DB_ROOT_SEED);\n\n/**\n * Initialize the `iq-git-v1` DbRoot account if it doesn't exist. First-call\n * cost on a fresh network. Idempotent: returns null if already initialized.\n * Accepts any SignerInput so an admin can run it from a wallet, not just\n * from a Keypair.\n */\nexport async function ensureDbRoot(\n connection: Connection,\n signer: SignerInput,\n): Promise<string | null> {\n if (await accountExists(connection, DB_ROOT)) return null;\n const builder = createInstructionBuilder();\n const ix = initializeDbRootInstruction(\n builder,\n {\n db_root: DB_ROOT,\n signer: signer.publicKey,\n system_program: SystemProgram.programId,\n },\n { db_root_id: DB_ROOT_SEED },\n );\n const tx = new Transaction().add(ix);\n const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash();\n tx.recentBlockhash = blockhash;\n tx.feePayer = signer.publicKey;\n const signed = await signTx(signer, tx);\n const signature = await connection.sendRawTransaction(signed.serialize());\n await connection.confirmTransaction({ signature, blockhash, lastValidBlockHeight });\n return signature;\n}\n\n// Sign a single Transaction with whatever shape the signer takes. Keypair\n// has a `secretKey`; wallet adapters expose `signTransaction`. iqlabs-sdk's\n// own `sendTx` uses the same dispatch; we replicate it here so the helper\n// stays self-contained.\nasync function signTx(signer: SignerInput, tx: Transaction): Promise<Transaction> {\n if (signer instanceof Keypair || \"secretKey\" in signer) {\n tx.partialSign(signer as Keypair);\n return tx;\n }\n return (signer as WalletSigner).signTransaction(tx);\n}\n\n/**\n * Read rows from a table. Tries the iq-gateway HTTP cache first and falls\n * back to `iqlabs.reader.readTableRows` on miss. Callers see a uniform API\n * either way.\n */\nexport async function readRows(\n hint: string,\n options?: { limit?: number; before?: string },\n): Promise<Array<Record<string, unknown>>> {\n return readRowsByPda(tablePda(hint), options);\n}\n\n/**\n * Same as readRows but keyed by the table PDA directly — for callers that\n * already have the PDA (e.g. a .sol record pointing at a commit table) and\n * can't or shouldn't re-derive it from a hint.\n */\nexport async function readRowsByPda(\n pda: PublicKey,\n options?: { limit?: number; before?: string },\n): Promise<Array<Record<string, unknown>>> {\n const viaGateway = await readRowsViaGateway(pda.toBase58(), options);\n if (viaGateway !== null) return viaGateway;\n return readTableRows(pda, options);\n}\n\n/**\n * Fetch just the latest row of a table — the fast path for \"what is the\n * current commit\" and \"what is the pinned deploy\".\n */\nexport async function readLatestRow(\n hint: string,\n): Promise<Record<string, unknown> | null> {\n const rows = await readRows(hint, { limit: 1 });\n return rows[0] ?? null;\n}\n\n/**\n * Upload a blob via `iqlabs.writer.codeIn`. The SDK chunks internally when\n * `data` is a plain string. We default speed to \"light\" because that's the\n * Helius-friendly setting for git workloads (per-file uploads are bursty).\n */\nexport async function codeIn(\n connection: Connection,\n signer: SignerInput,\n data: string | string[],\n filename: string,\n filetype: string,\n onProgress?: (percent: number) => void,\n speed: \"light\" | \"medium\" | \"fast\" = \"light\",\n): Promise<string> {\n return sdkCodeIn(\n { connection, signer },\n data,\n filename,\n 0,\n filetype,\n onProgress,\n speed,\n );\n}\n\n/**\n * Read a codeIn payload by tx signature. Tries the gateway /data/:sig\n * cache first and falls back to the SDK's direct RPC decode.\n */\nexport async function readCodeIn(\n txSig: string,\n): Promise<{ data: string | null; metadata: string }> {\n const viaGateway = await readCodeInViaGateway(txSig);\n if (viaGateway !== null) return viaGateway;\n return sdkReadCodeIn(txSig);\n}\n\n/** Cheap existence check for a PDA. */\nexport async function accountExists(\n connection: Connection,\n pda: PublicKey,\n): Promise<boolean> {\n return (await connection.getAccountInfo(pda)) !== null;\n}\n\n/** Resolve a hint to its PDA. */\nexport function tablePda(hint: string): PublicKey {\n return getTablePda(DB_ROOT, toSeedBytes(hint));\n}\n","// L3 — per-repo commit table.\n//\n// v2's core invariant: each repo has its own table at hint\n// `git_commits:<owner>:<repo>`, with writers locked to [owner]. That means\n// \"the most recent successful tx in this table = the latest commit\", and we\n// read it as a single-row query (limit: 1).\n\nimport type { Connection, PublicKey } from \"@solana/web3.js\";\nimport { type SignerInput } from \"@iqlabs-official/solana-sdk/utils\";\nimport { createTable, writeRow } from \"@iqlabs-official/solana-sdk/writer\";\nimport { IQGIT_ROOT_ID, commitTableHint } from \"../core/seed\";\nimport type { Commit } from \"../core/types\";\nimport * as chain from \"./chain\";\nimport { notifyGateways } from \"./gateway\";\n\nconst COMMIT_COLUMNS = [\n \"id\",\n \"message\",\n \"treeTxId\",\n \"parentCommitId\",\n \"timestamp\",\n \"author\",\n];\n\n/**\n * Ensure the per-repo commit table exists with writers = [owner]. No-op if\n * it already exists.\n */\nexport async function ensureCommitTable(\n connection: Connection,\n signer: SignerInput,\n repo: string,\n): Promise<string | null> {\n const hint = commitTableHint(signer.publicKey.toBase58(), repo);\n if (await chain.accountExists(connection, chain.tablePda(hint))) return null;\n return createTable(\n connection,\n signer as never,\n IQGIT_ROOT_ID,\n hint,\n hint,\n COMMIT_COLUMNS,\n \"id\",\n [],\n undefined,\n [signer.publicKey],\n hint,\n );\n}\n\n/**\n * Append one commit row. Callers (workflow-level code) are responsible for\n * setting parentCommitId — the SDK does not auto-chain.\n *\n * After the row lands on-chain, fires a best-effort /notify so any\n * iq-gateway already caching this table prepends the new commit without\n * waiting for RPC sig indexing.\n */\nexport async function writeCommit(\n connection: Connection,\n signer: SignerInput,\n repo: string,\n commit: Commit,\n): Promise<string> {\n const owner = signer.publicKey.toBase58();\n const hint = commitTableHint(owner, repo);\n const sig = await writeRow(\n connection,\n signer,\n IQGIT_ROOT_ID,\n hint,\n JSON.stringify(commit),\n );\n notifyGateways(chain.tablePda(hint).toBase58(), sig, commit, owner);\n return sig;\n}\n\n/** Latest commit. Single-row, O(1) RPC path. */\nexport async function readLatestCommit(\n _connection: Connection,\n owner: string,\n repo: string,\n): Promise<Commit | null> {\n const row = await chain.readLatestRow(commitTableHint(owner, repo));\n return row as unknown as Commit | null;\n}\n\n/** Full commit history, newest first. */\nexport async function readCommitHistory(\n _connection: Connection,\n owner: string,\n repo: string,\n options?: { limit?: number; before?: string },\n): Promise<Commit[]> {\n const rows = await chain.readRows(commitTableHint(owner, repo), options);\n return rows as unknown as Commit[];\n}\n\n/**\n * Commit history keyed by the commit-table PDA directly — for callers that\n * resolved a repo to its PDA (e.g. via a .sol record) and don't have the\n * owner/repo to rebuild the hint.\n */\nexport async function readCommitHistoryByPda(\n pda: PublicKey,\n options?: { limit?: number; before?: string },\n): Promise<Commit[]> {\n const rows = await chain.readRowsByPda(pda, options);\n return rows as unknown as Commit[];\n}\n","// L3 — repo list and public registry.\n//\n// Covers the two \"directory\" tables:\n// • git_repos_v2_<owner> — owner's personal repo list (writers = [owner])\n// • git_repos:all — public gallery registry (writers = [])\n//\n// Commit tables are a separate concern — see `commit.ts`.\n\nimport type { Connection } from \"@solana/web3.js\";\nimport { type SignerInput } from \"@iqlabs-official/solana-sdk/utils\";\nimport { createTable, writeRow } from \"@iqlabs-official/solana-sdk/writer\";\nimport { IQGIT_ROOT_ID, REGISTRY_HINT, repoListHint } from \"../core/seed\";\nimport type { RegistryEntry, Repository } from \"../core/types\";\nimport * as chain from \"./chain\";\nimport { notifyGateways } from \"./gateway\";\n\nconst REPO_COLUMNS = [\"name\", \"description\", \"isPublic\", \"timestamp\"];\nconst REGISTRY_COLUMNS = [\"owner\", \"repo\", \"description\", \"timestamp\"];\n\n/**\n * Create a repo in the owner's personal list, and (if public) also register\n * it in the public gallery. Two transactions — the contract does not support\n * writing two tables atomically.\n *\n * Returns the writeRow tx signatures (and the table hint each one wrote to)\n * so a caller can notify gateways / build SSE streams for those tables. The\n * returned shape is `[]` from `createTable` calls because those don't write\n * a row, just allocate the account.\n */\nexport async function createRepo(\n connection: Connection,\n signer: SignerInput,\n meta: Repository,\n): Promise<Array<{ tableHint: string; sig: string; row: object }>> {\n const owner = signer.publicKey.toBase58();\n const listHint = repoListHint(owner);\n const writes: Array<{ tableHint: string; sig: string; row: object }> = [];\n\n if (!(await chain.accountExists(connection, chain.tablePda(listHint)))) {\n await createTable(\n connection,\n signer as never,\n IQGIT_ROOT_ID,\n listHint,\n listHint,\n REPO_COLUMNS,\n \"name\",\n [],\n undefined,\n [signer.publicKey],\n listHint,\n );\n }\n\n const sig = await writeRow(connection, signer, IQGIT_ROOT_ID, listHint, JSON.stringify(meta));\n writes.push({ tableHint: listHint, sig, row: meta });\n notifyGateways(chain.tablePda(listHint).toBase58(), sig, meta, owner);\n\n if (meta.isPublic) {\n const entry: RegistryEntry = {\n owner,\n repo: meta.name,\n description: meta.description,\n timestamp: meta.timestamp,\n };\n const regSig = await writeRow(connection, signer, IQGIT_ROOT_ID, REGISTRY_HINT, JSON.stringify(entry));\n writes.push({ tableHint: REGISTRY_HINT, sig: regSig, row: entry });\n notifyGateways(chain.tablePda(REGISTRY_HINT).toBase58(), regSig, entry, owner);\n }\n\n return writes;\n}\n\n/** List all repos owned by `owner`. */\nexport async function readOwnerRepos(\n _connection: Connection,\n owner: string,\n): Promise<Repository[]> {\n return (await chain.readRows(repoListHint(owner))) as unknown as Repository[];\n}\n\n/**\n * One page of the public-gallery registry. Callers should still check\n * `row.owner` shape before trusting it in UI; we do not filter at the SDK\n * boundary.\n */\nexport async function readRegistryPage(\n _connection: Connection,\n options?: { limit?: number; before?: string },\n): Promise<RegistryEntry[]> {\n return (await chain.readRows(REGISTRY_HINT, options)) as unknown as RegistryEntry[];\n}\n\n/**\n * One-time global bootstrap of the `git_repos:all` table. Run once per\n * network from an admin key; subsequent calls short-circuit because the\n * account already exists.\n */\nexport async function bootstrapRegistry(\n connection: Connection,\n signer: SignerInput,\n): Promise<string | null> {\n await chain.ensureDbRoot(connection, signer);\n if (await chain.accountExists(connection, chain.tablePda(REGISTRY_HINT))) {\n return null;\n }\n return createTable(\n connection,\n signer as never,\n IQGIT_ROOT_ID,\n REGISTRY_HINT,\n REGISTRY_HINT,\n REGISTRY_COLUMNS,\n \"owner\",\n [],\n undefined,\n undefined,\n REGISTRY_HINT,\n );\n}\n","// L2 — blob + tree storage.\n//\n// `uploadBlob` is the file-level \"don't re-upload what's already on-chain\"\n// primitive. Content is always a base64 string (matching iq-git v1) so the\n// hash / dedup comparison stays byte-for-byte compatible across commits.\n// The reuse-map is just a plain object so callers can build it any way they\n// like (path→entry, or hash→txId for rename-aware dedup — CODE-RULES §3\n// keeps this inlined at the call site instead of a new type).\n//\n// `uploadTree` / `loadTree` serialize FileTree <-> on-chain tree.json as raw\n// JSON (filetype `application/json`), again matching v1.\n\nimport type { Connection } from \"@solana/web3.js\";\nimport type { SignerInput } from \"@iqlabs-official/solana-sdk/utils\";\nimport { sha256Hex } from \"../core/hash\";\nimport type { FileTree } from \"../core/types\";\nimport * as chain from \"./chain\";\n\n/**\n * Upload one file unless an identical hash is already in `reuse` (blob dedup).\n *\n * input: connection, signer, relativePath, base64 content, reuse map, optional onProgress\n * output: { txId, hash } — either reused or freshly uploaded\n */\nexport async function uploadBlob(\n connection: Connection,\n signer: SignerInput,\n relativePath: string,\n base64Content: string,\n reuse: FileTree,\n onProgress?: (percent: number) => void,\n): Promise<{ txId: string; hash: string }> {\n const hash = await sha256Hex(base64Content);\n const prior = reuse[relativePath];\n if (prior && prior.hash === hash) return prior;\n\n // Tag the codeIn filename with our app marker so non-inline inventory\n // entries can be classified by inspecting metadata.filename alone (no row\n // body fetch needed). Format: \"iqgit-blob:<basename>\". Same scheme used\n // for trees (\"iqgit-tree\") and other writes across the IQ ecosystem.\n const basename = relativePath.split(\"/\").pop() || relativePath;\n const txId = await chain.codeIn(\n connection,\n signer,\n base64Content,\n `iqgit-blob:${basename}`,\n \"application/octet-stream\",\n onProgress,\n );\n return { txId, hash };\n}\n\n/**\n * Serialize a FileTree and upload it as one `tree.json` blob.\n */\nexport async function uploadTree(\n connection: Connection,\n signer: SignerInput,\n tree: FileTree,\n): Promise<string> {\n return chain.codeIn(\n connection,\n signer,\n JSON.stringify(tree),\n \"iqgit-tree\",\n \"application/json\",\n );\n}\n\n/**\n * Fetch and parse a `tree.json` blob by its tx signature.\n */\nexport async function loadTree(treeTxId: string): Promise<FileTree> {\n const { data } = await chain.readCodeIn(treeTxId);\n if (data === null) {\n throw new Error(`tree.json not found for tx ${treeTxId}`);\n }\n return JSON.parse(data) as FileTree;\n}\n\n/**\n * Retrieve a blob's bytes by its txId. Returns the raw string that was\n * uploaded — for blobs this is base64; the caller decodes.\n */\nexport async function loadBlob(txId: string): Promise<string> {\n const { data } = await chain.readCodeIn(txId);\n if (data === null) {\n throw new Error(`blob not found for tx ${txId}`);\n }\n return data;\n}\n","// L4 — GitClient facade. High-level workflows built by composing the\n// layers below. This is the surface consumers (CLI, frontend, migrator) use;\n// they should not reach into `chain` / `storage` / `repo` / `commit` directly.\n//\n// Keep workflow logic here, not inside lower layers (CODE-RULES §5). When a\n// command needs scanning, hashing, uploading, row writing — this file\n// orchestrates them all.\n\nimport type { Connection } from \"@solana/web3.js\";\nimport { setRpcUrl } from \"@iqlabs-official/solana-sdk\";\nimport type { SignerInput } from \"@iqlabs-official/solana-sdk/utils\";\nimport { sha256Hex } from \"../core/hash\";\nimport { commitTableHint } from \"../core/seed\";\nimport type { Commit, FileTree, Repository } from \"../core/types\";\nimport * as chain from \"./chain\";\nimport * as commitLayer from \"./commit\";\nimport * as repoLayer from \"./repo\";\nimport * as storage from \"./storage\";\n\n/** Information surfaced to the `onWrite` callback for every successful row\n * write the SDK performs. Consumers wire this to their gateway notify so\n * the gateway updates its cache / SSE stream immediately. */\nexport interface WriteEvent {\n /** Resolved table PDA, base58 — pass directly to gateway notify. */\n tablePda: string;\n /** The hint that derived the PDA, in case callers want to log it. */\n tableHint: string;\n /** writeRow tx signature. */\n sig: string;\n /** The row object that was written (already JSON.stringify-able). */\n row: object;\n}\n\nexport interface GitClientConfig {\n connection: Connection;\n signer: SignerInput;\n /** Fires after each successful row write inside the SDK. Fire-and-forget\n * callback for gateway notifies; throwing here will surface to the caller. */\n onWrite?: (event: WriteEvent) => void;\n}\n\nexport class GitClient {\n // CODE-RULES §3 — only one small shape; inlined rather than aliased.\n constructor(private readonly cfg: GitClientConfig) {\n // The solana-sdk reader path (readTableRows / readCodeIn → loadTree /\n // readLatestCommit) does not take a Connection — it resolves a\n // process-global one from env / setRpcUrl. Writes use `cfg.connection`,\n // so without this reads could hit a different RPC (e.g. the mainnet-beta\n // fallback when no env is set, as in a built browser bundle). Sync the\n // reader's RPC to the connection the caller actually gave us.\n setRpcUrl(cfg.connection.rpcEndpoint);\n }\n\n /**\n * Create a new repo. Wraps repo.createRepo + pre-creating the commit table\n * so the first `commit()` call doesn't need to pay createTable cost.\n */\n async createRepo(meta: Repository): Promise<void> {\n const { connection, signer } = this.cfg;\n const writes = await repoLayer.createRepo(connection, signer, meta);\n await commitLayer.ensureCommitTable(connection, signer, meta.name);\n this.fireOnWrite(writes);\n }\n\n /**\n * Incremental commit against a scanned directory snapshot.\n *\n * input: repoName, message, scan — a `{ [path]: base64Content }` map that\n * the caller produced (Node: fs walk + base64; browser: File input).\n * output: newly written Commit\n */\n async commit(\n repoName: string,\n message: string,\n scan: Record<string, string>,\n ): Promise<Commit> {\n const { connection, signer } = this.cfg;\n const owner = signer.publicKey.toBase58();\n\n const latest = await commitLayer.readLatestCommit(connection, owner, repoName);\n const oldTree: FileTree = latest ? await storage.loadTree(latest.treeTxId) : {};\n\n const newTree: FileTree = {};\n for (const [path, content] of Object.entries(scan)) {\n newTree[path] = await storage.uploadBlob(\n connection,\n signer,\n path,\n content,\n oldTree,\n );\n }\n\n const treeTxId = await storage.uploadTree(connection, signer, newTree);\n\n const commit: Commit = {\n id: crypto.randomUUID(),\n message,\n treeTxId,\n parentCommitId: latest?.id,\n timestamp: Date.now(),\n author: owner,\n };\n const sig = await commitLayer.writeCommit(connection, signer, repoName, commit);\n this.fireOnWrite([{ tableHint: commitTableHint(owner, repoName), sig, row: commit }]);\n return commit;\n }\n\n /** Resolve the table hint to a PDA and forward each write to `onWrite`.\n * Wrapped in try/catch per call so a misbehaving notify can't fail the\n * whole batch — but we still surface the error so the consumer knows. */\n private fireOnWrite(writes: Array<{ tableHint: string; sig: string; row: object }>) {\n if (!this.cfg.onWrite) return;\n for (const w of writes) {\n const tablePda = chain.tablePda(w.tableHint).toBase58();\n this.cfg.onWrite({ tablePda, tableHint: w.tableHint, sig: w.sig, row: w.row });\n }\n }\n\n /**\n * Restore a commit's files into a caller-provided sink. Runtime-neutral\n * shape mirrors `commit`: the caller decides how to write bytes to disk /\n * to a File System Access API handle / anywhere else. `content` is the\n * raw base64 string — the sink decodes.\n */\n async checkout(\n repoName: string,\n commitId: string | \"latest\",\n sink: (path: string, content: string) => Promise<void>,\n ): Promise<Commit> {\n const { connection, signer } = this.cfg;\n const owner = signer.publicKey.toBase58();\n\n let target: Commit | null;\n if (commitId === \"latest\") {\n target = await commitLayer.readLatestCommit(connection, owner, repoName);\n } else {\n const history = await commitLayer.readCommitHistory(connection, owner, repoName);\n target = history.find((c) => c.id === commitId) ?? null;\n }\n if (!target) {\n throw new Error(`commit not found: ${commitId} in ${owner}/${repoName}`);\n }\n\n const tree = await storage.loadTree(target.treeTxId);\n for (const [path, entry] of Object.entries(tree)) {\n const content = await storage.loadBlob(entry.txId);\n await sink(path, content);\n }\n return target;\n }\n\n /**\n * Whole-repo snapshot download — convenience on top of checkout(\"latest\")\n * but reading from someone else's `owner`. We do not require signer to\n * equal owner for reads.\n */\n async clone(\n repoName: string,\n owner: string,\n sink: (path: string, content: string) => Promise<void>,\n ): Promise<Commit> {\n const { connection } = this.cfg;\n const target = await commitLayer.readLatestCommit(connection, owner, repoName);\n if (!target) {\n throw new Error(`no commits in ${owner}/${repoName}`);\n }\n const tree = await storage.loadTree(target.treeTxId);\n for (const [path, entry] of Object.entries(tree)) {\n const content = await storage.loadBlob(entry.txId);\n await sink(path, content);\n }\n return target;\n }\n\n /** Commit history for a repo. */\n async log(\n owner: string,\n repoName: string,\n options?: { limit?: number; before?: string },\n ): Promise<Commit[]> {\n return commitLayer.readCommitHistory(\n this.cfg.connection,\n owner,\n repoName,\n options,\n );\n }\n\n /**\n * Compare a current directory snapshot to the latest commit's tree.\n */\n async status(\n owner: string,\n repoName: string,\n scan: Record<string, string>,\n ): Promise<{ added: string[]; modified: string[]; unchanged: string[] }> {\n const latest = await commitLayer.readLatestCommit(\n this.cfg.connection,\n owner,\n repoName,\n );\n const tree: FileTree = latest ? await storage.loadTree(latest.treeTxId) : {};\n\n const added: string[] = [];\n const modified: string[] = [];\n const unchanged: string[] = [];\n for (const [path, content] of Object.entries(scan)) {\n const prior = tree[path];\n if (!prior) {\n added.push(path);\n continue;\n }\n const hash = await sha256Hex(content);\n (prior.hash === hash ? unchanged : modified).push(path);\n }\n return { added, modified, unchanged };\n }\n}\n","// Node entry. Installs the node:crypto SHA-256 hasher, then re-exports\n// everything from the shared root. CLI / migrator / test harnesses all go\n// through here.\n\nimport { setSha256 } from \"./core/hash\";\nimport { hashNode } from \"./platform/hash-node\";\n\nsetSha256(hashNode);\n\nexport * from \"./index\";\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/core/hash.ts","../../src/platform/hash-node.ts","../../src/core/seed.ts","../../src/layers/gateway.ts","../../src/layers/chain.ts","../../src/layers/commit.ts","../../src/layers/repo.ts","../../src/layers/storage.ts","../../src/layers/client.ts","../../src/node.ts"],"names":["sdkCodeIn","sdkReadCodeIn","createTable","writeRow","tablePda"],"mappings":"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","file":"index.js","sourcesContent":["// SHA-256 content hashing for the blob-dedup index. Runtime-specific\n// implementations live in `platform/hash-node.ts` and `platform/hash-browser.ts`;\n// this module just declares the interface the rest of the SDK uses.\n//\n// Do NOT use this for deriving table seeds — that path is owned by\n// `iqlabs.utils.toSeedBytes` (keccak) and must stay aligned with the SDK.\n\n/**\n * SHA-256 of a UTF-8 or base64 string, returned as a lowercase hex digest.\n * Implementation is injected by the platform entry (node.ts / browser.ts).\n */\nexport type Sha256Hex = (input: string) => Promise<string>;\n\n// Platform entries (src/node.ts, src/browser.ts) will call `setSha256(...)`\n// during module init so downstream layers never care which runtime they are in.\n// This indirection is the one place where a wrapper is justified (CODE-RULES §1)\n// because the behavior genuinely differs per runtime.\nlet impl: Sha256Hex | undefined;\n\nexport function setSha256(fn: Sha256Hex): void {\n if (impl) {\n throw new Error(\n \"@iqlabs-official/git-sdk: sha256 implementation already installed. Import exactly one of '@iqlabs-official/git-sdk/node' or '@iqlabs-official/git-sdk/browser'.\",\n );\n }\n impl = fn;\n}\n\nexport async function sha256Hex(input: string): Promise<string> {\n if (!impl) {\n throw new Error(\n \"@iqlabs-official/git-sdk: sha256 not installed. Import '@iqlabs-official/git-sdk/node' (Node) or '@iqlabs-official/git-sdk/browser' (browser) before using the SDK.\",\n );\n }\n return impl(input);\n}\n","// Node SHA-256 implementation. Kept as a pure export; `src/node.ts` installs\n// it via `setSha256` during its own module init.\n\nimport { createHash } from \"node:crypto\";\nimport type { Sha256Hex } from \"../core/hash\";\n\nexport const hashNode: Sha256Hex = async (input) =>\n createHash(\"sha256\").update(input).digest(\"hex\");\n","// The single source of truth for table_hint strings.\n//\n// Readers re-derive PDAs with `iqlabs.utils.toSeedBytes(hint)` →\n// `iqlabs.contract.getTablePda(...)`; writers pass the same hint into\n// `iqlabs.writer.createTable`. Keeping the naming convention in one place\n// prevents silent drift between writer and reader. CODE-RULES §2 — if any\n// caller ever wants to build one of these strings inline, route it here\n// instead.\n\n/** DbRoot id for every iq-git table. Bootstrap and every caller share this. */\nexport const IQGIT_ROOT_ID = \"iq-git-v1\";\n\n/** `git_repos:all` — open-writers registry that drives the public gallery. */\nexport const REGISTRY_HINT = \"git_repos:all\";\n\n/**\n * Hint for the per-owner personal repo list.\n * input: owner wallet base58\n * output: \"git_repos_v2_<owner>\"\n */\nexport function repoListHint(owner: string): string {\n return `git_repos_v2_${owner}`;\n}\n\n/**\n * Hint for the per-repo commit table.\n * input: owner wallet base58, repo name (any characters — SDK keccak-hashes)\n * output: \"git_commits:<owner>:<repo>\"\n */\nexport function commitTableHint(owner: string, repo: string): string {\n return `git_commits:${owner}:${repo}`;\n}\n","// L1.5 — iq-gateway HTTP helpers.\n//\n// chain.ts dispatches reads through here first; on a null return it falls\n// back to direct RPC. Writers fire-and-forget a notify so the gateway can\n// prepend the new row to its head-page cache without waiting on RPC\n// indexing.\n//\n// Configuration precedence (high → low):\n// 1. setGatewayUrls([...]) — explicit URL list\n// 2. IQGIT_GATEWAYS env (csv) — deployment-side pinning\n// 3. setNetwork(\"devnet\"|\"mainnet\") + the network's default gateway\n// 4. RPC URL hostname inference (`devnet` / `testnet` substring → devnet)\n// 5. Mainnet default — gateway.iqlabs.dev\n//\n// Everything here is best-effort: an unreachable, misconfigured, or\n// disabled gateway never breaks the SDK.\n\nimport { getRpcUrl } from \"@iqlabs-official/solana-sdk\";\n\nconst MAINNET_GATEWAY = \"https://gateway.iqlabs.dev\";\nconst DEVNET_GATEWAY = \"https://dev-gateway.iqlabs.dev\";\nconst REQ_TIMEOUT_MS = 5000;\n\nlet runtimeGateways: string[] | null = null;\nlet networkOverride: \"mainnet\" | \"devnet\" | null = null;\n\n/** Pin the gateway URL list explicitly. Highest precedence. Pass `[]` to\n * disable gateway dispatch entirely (RPC-only mode). */\nexport function setGatewayUrls(urls: string[]): void {\n runtimeGateways = urls.length > 0 ? urls : null;\n}\n\n/** Pin the network label when the RPC URL doesn't reveal it (private nodes,\n * proxies, etc.). Has no effect when setGatewayUrls() is also set. */\nexport function setNetwork(network: \"mainnet\" | \"devnet\"): void {\n networkOverride = network;\n}\n\nfunction inferNetwork(): \"mainnet\" | \"devnet\" {\n if (networkOverride) return networkOverride;\n const u = getRpcUrl().toLowerCase();\n if (u.includes(\"devnet\") || u.includes(\"testnet\")) return \"devnet\";\n return \"mainnet\";\n}\n\nexport function getGatewayUrls(): string[] {\n if (runtimeGateways) return runtimeGateways;\n\n const env = (typeof process !== \"undefined\" && process.env?.IQGIT_GATEWAYS) ?? \"\";\n if (env) return env.split(\",\").map((s) => s.trim()).filter(Boolean);\n\n return inferNetwork() === \"devnet\" ? [DEVNET_GATEWAY] : [MAINNET_GATEWAY];\n}\n\nasync function tryGateways<T>(\n path: (gw: string) => string,\n parse: (res: Response) => Promise<T>,\n): Promise<T | null> {\n for (const gw of getGatewayUrls()) {\n try {\n const ctrl = new AbortController();\n const timer = setTimeout(() => ctrl.abort(), REQ_TIMEOUT_MS);\n const res = await fetch(path(gw), { signal: ctrl.signal });\n clearTimeout(timer);\n if (res.ok) return await parse(res);\n } catch {\n // Try the next gateway.\n }\n }\n return null;\n}\n\n/** Fetch rows for a table PDA via /table/:pda/rows. Returns null when no\n * gateway is configured or all of them fail — caller falls back to RPC. */\nexport async function readRowsViaGateway(\n pdaBase58: string,\n options?: { limit?: number; before?: string },\n): Promise<Array<Record<string, unknown>> | null> {\n const qs = new URLSearchParams();\n if (options?.limit) qs.set(\"limit\", String(options.limit));\n if (options?.before) qs.set(\"before\", options.before);\n const suffix = qs.toString() ? `?${qs}` : \"\";\n\n return tryGateways(\n (gw) => `${gw}/table/${pdaBase58}/rows${suffix}`,\n async (res) => {\n const json = (await res.json()) as { rows?: unknown[] };\n return (json.rows ?? []) as Array<Record<string, unknown>>;\n },\n );\n}\n\n/** Fetch raw codeIn payload via /data/:sig. Gateway returns a superset of\n * what the SDK's readCodeIn produces; we extract just the matching fields. */\nexport async function readCodeInViaGateway(\n txSig: string,\n): Promise<{ data: string | null; metadata: string } | null> {\n return tryGateways(\n (gw) => `${gw}/data/${txSig}`,\n async (res) => {\n const json = (await res.json()) as { data?: string | null; metadata?: string };\n return { data: json.data ?? null, metadata: json.metadata ?? \"\" };\n },\n );\n}\n\n/** Fire-and-forget /notify after a successful write. Includes the row body\n * so the gateway can inject without an RPC roundtrip. Errors are swallowed\n * — the row is already on-chain, gateway hydration is opportunistic. */\nexport function notifyGateways(\n pdaBase58: string,\n txSig: string,\n row: object,\n signer: string,\n): void {\n const body = JSON.stringify({ txSignature: txSig, row, signer });\n for (const gw of getGatewayUrls()) {\n fetch(`${gw}/table/${pdaBase58}/notify`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body,\n }).catch(() => {});\n }\n}\n","// L1 — chain primitives shared by L2/L3. Kept tiny by design: each function\n// here either (a) hides PDA derivation so callers only deal with hints, or\n// (b) wraps a single iqlabs-sdk call to keep an iq-git-specific default\n// (chunk speed, root id, ...). Pure passthroughs like `createTable` /\n// `writeRow` live at the call site instead — wrapping them once more would\n// just bury the iqlabs-sdk surface (CODE-RULES §1).\n//\n// Read primitives transparently prefer the iq-gateway HTTP API and fall\n// back to direct RPC; the gateway dispatch lives here so commit/repo/\n// storage all benefit without each having to wire it up.\n\nimport {\n Keypair,\n SystemProgram,\n Transaction,\n type Connection,\n type PublicKey,\n} from \"@solana/web3.js\";\nimport {\n createInstructionBuilder,\n getDbRootPda,\n getTablePda,\n initializeDbRootInstruction,\n} from \"@iqlabs-official/solana-sdk/contract\";\nimport { readCodeIn as sdkReadCodeIn, readTableRows } from \"@iqlabs-official/solana-sdk/reader\";\nimport { toSeedBytes, type SignerInput, type WalletSigner } from \"@iqlabs-official/solana-sdk/utils\";\nimport { codeIn as sdkCodeIn } from \"@iqlabs-official/solana-sdk/writer\";\nimport { IQGIT_ROOT_ID } from \"../core/seed\";\nimport { readCodeInViaGateway, readRowsViaGateway } from \"./gateway\";\n\n/** DbRoot PDA for the `iq-git-v1` namespace — derived once, reused everywhere. */\nexport const DB_ROOT_SEED = toSeedBytes(IQGIT_ROOT_ID);\nexport const DB_ROOT = getDbRootPda(DB_ROOT_SEED);\n\n/**\n * Initialize the `iq-git-v1` DbRoot account if it doesn't exist. First-call\n * cost on a fresh network. Idempotent: returns null if already initialized.\n * Accepts any SignerInput so an admin can run it from a wallet, not just\n * from a Keypair.\n */\nexport async function ensureDbRoot(\n connection: Connection,\n signer: SignerInput,\n): Promise<string | null> {\n if (await accountExists(connection, DB_ROOT)) return null;\n const builder = createInstructionBuilder();\n const ix = initializeDbRootInstruction(\n builder,\n {\n db_root: DB_ROOT,\n signer: signer.publicKey,\n system_program: SystemProgram.programId,\n },\n { db_root_id: DB_ROOT_SEED },\n );\n const tx = new Transaction().add(ix);\n const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash();\n tx.recentBlockhash = blockhash;\n tx.feePayer = signer.publicKey;\n const signed = await signTx(signer, tx);\n const signature = await connection.sendRawTransaction(signed.serialize());\n await connection.confirmTransaction({ signature, blockhash, lastValidBlockHeight });\n return signature;\n}\n\n// Sign a single Transaction with whatever shape the signer takes. Keypair\n// has a `secretKey`; wallet adapters expose `signTransaction`. iqlabs-sdk's\n// own `sendTx` uses the same dispatch; we replicate it here so the helper\n// stays self-contained.\nasync function signTx(signer: SignerInput, tx: Transaction): Promise<Transaction> {\n if (signer instanceof Keypair || \"secretKey\" in signer) {\n tx.partialSign(signer as Keypair);\n return tx;\n }\n return (signer as WalletSigner).signTransaction(tx);\n}\n\n/**\n * Read rows from a table. Tries the iq-gateway HTTP cache first and falls\n * back to `iqlabs.reader.readTableRows` on miss. Callers see a uniform API\n * either way.\n */\nexport async function readRows(\n hint: string,\n options?: { limit?: number; before?: string },\n): Promise<Array<Record<string, unknown>>> {\n return readRowsByPda(tablePda(hint), options);\n}\n\n/**\n * Same as readRows but keyed by the table PDA directly — for callers that\n * already have the PDA (e.g. a .sol record pointing at a commit table) and\n * can't or shouldn't re-derive it from a hint.\n */\nexport async function readRowsByPda(\n pda: PublicKey,\n options?: { limit?: number; before?: string },\n): Promise<Array<Record<string, unknown>>> {\n const viaGateway = await readRowsViaGateway(pda.toBase58(), options);\n if (viaGateway !== null) return viaGateway;\n return readTableRows(pda, options);\n}\n\n/**\n * Fetch just the latest row of a table — the fast path for \"what is the\n * current commit\" and \"what is the pinned deploy\".\n */\nexport async function readLatestRow(\n hint: string,\n): Promise<Record<string, unknown> | null> {\n const rows = await readRows(hint, { limit: 1 });\n return rows[0] ?? null;\n}\n\n/**\n * Upload a blob via `iqlabs.writer.codeIn`. The SDK chunks internally when\n * `data` is a plain string. We default speed to \"light\" because that's the\n * Helius-friendly setting for git workloads (per-file uploads are bursty).\n */\nexport async function codeIn(\n connection: Connection,\n signer: SignerInput,\n data: string | string[],\n filename: string,\n filetype: string,\n onProgress?: (percent: number) => void,\n speed: \"light\" | \"medium\" | \"fast\" = \"light\",\n): Promise<string> {\n return sdkCodeIn(\n { connection, signer },\n data,\n filename,\n 0,\n filetype,\n onProgress,\n speed,\n );\n}\n\n/**\n * Read a codeIn payload by tx signature. Tries the gateway /data/:sig\n * cache first and falls back to the SDK's direct RPC decode.\n */\nexport async function readCodeIn(\n txSig: string,\n): Promise<{ data: string | null; metadata: string }> {\n const viaGateway = await readCodeInViaGateway(txSig);\n if (viaGateway !== null) return viaGateway;\n return sdkReadCodeIn(txSig);\n}\n\n/** Cheap existence check for a PDA. */\nexport async function accountExists(\n connection: Connection,\n pda: PublicKey,\n): Promise<boolean> {\n return (await connection.getAccountInfo(pda)) !== null;\n}\n\n/** Resolve a hint to its PDA. */\nexport function tablePda(hint: string): PublicKey {\n return getTablePda(DB_ROOT, toSeedBytes(hint));\n}\n","// L3 — per-repo commit table.\n//\n// v2's core invariant: each repo has its own table at hint\n// `git_commits:<owner>:<repo>`, with writers locked to [owner]. That means\n// \"the most recent successful tx in this table = the latest commit\", and we\n// read it as a single-row query (limit: 1).\n\nimport type { Connection, PublicKey } from \"@solana/web3.js\";\nimport { type SignerInput } from \"@iqlabs-official/solana-sdk/utils\";\nimport { createTable, writeRow } from \"@iqlabs-official/solana-sdk/writer\";\nimport { IQGIT_ROOT_ID, commitTableHint } from \"../core/seed\";\nimport type { Commit } from \"../core/types\";\nimport * as chain from \"./chain\";\nimport { notifyGateways } from \"./gateway\";\n\nconst COMMIT_COLUMNS = [\n \"id\",\n \"message\",\n \"treeTxId\",\n \"parentCommitId\",\n \"timestamp\",\n \"author\",\n];\n\n/**\n * Ensure the per-repo commit table exists with writers = [owner]. No-op if\n * it already exists.\n */\nexport async function ensureCommitTable(\n connection: Connection,\n signer: SignerInput,\n repo: string,\n): Promise<string | null> {\n const hint = commitTableHint(signer.publicKey.toBase58(), repo);\n if (await chain.accountExists(connection, chain.tablePda(hint))) return null;\n return createTable(\n connection,\n signer,\n IQGIT_ROOT_ID,\n hint,\n hint,\n COMMIT_COLUMNS,\n \"id\",\n [],\n undefined,\n [signer.publicKey],\n hint,\n );\n}\n\n/**\n * Append one commit row. Callers (workflow-level code) are responsible for\n * setting parentCommitId — the SDK does not auto-chain.\n *\n * After the row lands on-chain, fires a best-effort /notify so any\n * iq-gateway already caching this table prepends the new commit without\n * waiting for RPC sig indexing.\n */\nexport async function writeCommit(\n connection: Connection,\n signer: SignerInput,\n repo: string,\n commit: Commit,\n): Promise<string> {\n const owner = signer.publicKey.toBase58();\n const hint = commitTableHint(owner, repo);\n const sig = await writeRow(\n connection,\n signer,\n IQGIT_ROOT_ID,\n hint,\n JSON.stringify(commit),\n );\n notifyGateways(chain.tablePda(hint).toBase58(), sig, commit, owner);\n return sig;\n}\n\n/** The commit-table PDA for a repo. The one place owner/repo collapses to a\n * PDA — every read keys off the PDA, so callers that have a PDA already (a\n * .sol record, a dbroot match) skip this and pass it straight in. */\nexport function commitTablePda(owner: string, repo: string): PublicKey {\n return chain.tablePda(commitTableHint(owner, repo));\n}\n\n/** Latest commit. Single-row, O(1) RPC path. */\nexport async function readLatestCommit(pda: PublicKey): Promise<Commit | null> {\n const rows = await chain.readRowsByPda(pda, { limit: 1 });\n return (rows[0] as unknown as Commit) ?? null;\n}\n\n/** Full commit history, newest first. */\nexport async function readCommitHistory(\n pda: PublicKey,\n options?: { limit?: number; before?: string },\n): Promise<Commit[]> {\n const rows = await chain.readRowsByPda(pda, options);\n return rows as unknown as Commit[];\n}\n","// L3 — repo list and public registry.\n//\n// Covers the two \"directory\" tables:\n// • git_repos_v2_<owner> — owner's personal repo list (writers = [owner])\n// • git_repos:all — public gallery registry (writers = [])\n//\n// Commit tables are a separate concern — see `commit.ts`.\n\nimport type { Connection } from \"@solana/web3.js\";\nimport { type SignerInput } from \"@iqlabs-official/solana-sdk/utils\";\nimport { createTable, writeRow } from \"@iqlabs-official/solana-sdk/writer\";\nimport { IQGIT_ROOT_ID, REGISTRY_HINT, repoListHint } from \"../core/seed\";\nimport type { RegistryEntry, Repository } from \"../core/types\";\nimport * as chain from \"./chain\";\nimport { notifyGateways } from \"./gateway\";\n\nconst REPO_COLUMNS = [\"name\", \"description\", \"isPublic\", \"timestamp\"];\nconst REGISTRY_COLUMNS = [\"owner\", \"repo\", \"description\", \"timestamp\"];\n\n/**\n * Create a repo in the owner's personal list, and (if public) also register\n * it in the public gallery. Two transactions — the contract does not support\n * writing two tables atomically.\n *\n * Returns the writeRow tx signatures (and the table hint each one wrote to)\n * so a caller can notify gateways / build SSE streams for those tables. The\n * returned shape is `[]` from `createTable` calls because those don't write\n * a row, just allocate the account.\n */\nexport async function createRepo(\n connection: Connection,\n signer: SignerInput,\n meta: Repository,\n): Promise<Array<{ tableHint: string; sig: string; row: object }>> {\n const owner = signer.publicKey.toBase58();\n const listHint = repoListHint(owner);\n const writes: Array<{ tableHint: string; sig: string; row: object }> = [];\n\n if (!(await chain.accountExists(connection, chain.tablePda(listHint)))) {\n await createTable(\n connection,\n signer,\n IQGIT_ROOT_ID,\n listHint,\n listHint,\n REPO_COLUMNS,\n \"name\",\n [],\n undefined,\n [signer.publicKey],\n listHint,\n );\n }\n\n const sig = await writeRow(connection, signer, IQGIT_ROOT_ID, listHint, JSON.stringify(meta));\n writes.push({ tableHint: listHint, sig, row: meta });\n notifyGateways(chain.tablePda(listHint).toBase58(), sig, meta, owner);\n\n if (meta.isPublic) {\n const entry: RegistryEntry = {\n owner,\n repo: meta.name,\n description: meta.description,\n timestamp: meta.timestamp,\n };\n const regSig = await writeRow(connection, signer, IQGIT_ROOT_ID, REGISTRY_HINT, JSON.stringify(entry));\n writes.push({ tableHint: REGISTRY_HINT, sig: regSig, row: entry });\n notifyGateways(chain.tablePda(REGISTRY_HINT).toBase58(), regSig, entry, owner);\n }\n\n return writes;\n}\n\n/** List all repos owned by `owner`. */\nexport async function readOwnerRepos(\n _connection: Connection,\n owner: string,\n): Promise<Repository[]> {\n return (await chain.readRows(repoListHint(owner))) as unknown as Repository[];\n}\n\n/**\n * One page of the public-gallery registry. Callers should still check\n * `row.owner` shape before trusting it in UI; we do not filter at the SDK\n * boundary.\n */\nexport async function readRegistryPage(\n _connection: Connection,\n options?: { limit?: number; before?: string },\n): Promise<RegistryEntry[]> {\n return (await chain.readRows(REGISTRY_HINT, options)) as unknown as RegistryEntry[];\n}\n\n/**\n * One-time global bootstrap of the `git_repos:all` table. Run once per\n * network from an admin key; subsequent calls short-circuit because the\n * account already exists.\n */\nexport async function bootstrapRegistry(\n connection: Connection,\n signer: SignerInput,\n): Promise<string | null> {\n await chain.ensureDbRoot(connection, signer);\n if (await chain.accountExists(connection, chain.tablePda(REGISTRY_HINT))) {\n return null;\n }\n return createTable(\n connection,\n signer,\n IQGIT_ROOT_ID,\n REGISTRY_HINT,\n REGISTRY_HINT,\n REGISTRY_COLUMNS,\n \"owner\",\n [],\n undefined,\n undefined,\n REGISTRY_HINT,\n );\n}\n","// L2 — blob + tree storage.\n//\n// `uploadBlob` is the file-level \"don't re-upload what's already on-chain\"\n// primitive. Content is always a base64 string (matching iq-git v1) so the\n// hash / dedup comparison stays byte-for-byte compatible across commits.\n// The reuse-map is just a plain object so callers can build it any way they\n// like (path→entry, or hash→txId for rename-aware dedup — CODE-RULES §3\n// keeps this inlined at the call site instead of a new type).\n//\n// `uploadTree` / `loadTree` serialize FileTree <-> on-chain tree.json as raw\n// JSON (filetype `application/json`), again matching v1.\n\nimport type { Connection } from \"@solana/web3.js\";\nimport type { SignerInput } from \"@iqlabs-official/solana-sdk/utils\";\nimport { sha256Hex } from \"../core/hash\";\nimport type { FileTree } from \"../core/types\";\nimport * as chain from \"./chain\";\n\n/**\n * Upload one file unless an identical hash is already in `reuse` (blob dedup).\n *\n * input: connection, signer, relativePath, base64 content, reuse map, optional onProgress\n * output: { txId, hash } — either reused or freshly uploaded\n */\nexport async function uploadBlob(\n connection: Connection,\n signer: SignerInput,\n relativePath: string,\n base64Content: string,\n reuse: FileTree,\n onProgress?: (percent: number) => void,\n): Promise<{ txId: string; hash: string }> {\n const hash = await sha256Hex(base64Content);\n const prior = reuse[relativePath];\n if (prior && prior.hash === hash) return prior;\n\n // Tag the codeIn filename with our app marker so non-inline inventory\n // entries can be classified by inspecting metadata.filename alone (no row\n // body fetch needed). Format: \"iqgit-blob:<basename>\". Same scheme used\n // for trees (\"iqgit-tree\") and other writes across the IQ ecosystem.\n const basename = relativePath.split(\"/\").pop() || relativePath;\n const txId = await chain.codeIn(\n connection,\n signer,\n base64Content,\n `iqgit-blob:${basename}`,\n \"application/octet-stream\",\n onProgress,\n );\n return { txId, hash };\n}\n\n/**\n * Serialize a FileTree and upload it as one `tree.json` blob.\n */\nexport async function uploadTree(\n connection: Connection,\n signer: SignerInput,\n tree: FileTree,\n): Promise<string> {\n return chain.codeIn(\n connection,\n signer,\n JSON.stringify(tree),\n \"iqgit-tree\",\n \"application/json\",\n );\n}\n\n/**\n * Fetch and parse a `tree.json` blob by its tx signature.\n */\nexport async function loadTree(treeTxId: string): Promise<FileTree> {\n const { data } = await chain.readCodeIn(treeTxId);\n if (data === null) {\n throw new Error(`tree.json not found for tx ${treeTxId}`);\n }\n return JSON.parse(data) as FileTree;\n}\n\n/**\n * Retrieve a blob's bytes by its txId. Returns the raw string that was\n * uploaded — for blobs this is base64; the caller decodes.\n */\nexport async function loadBlob(txId: string): Promise<string> {\n const { data } = await chain.readCodeIn(txId);\n if (data === null) {\n throw new Error(`blob not found for tx ${txId}`);\n }\n return data;\n}\n","// L4 — GitClient facade. High-level workflows built by composing the\n// layers below. This is the surface consumers (CLI, frontend, migrator) use;\n// they should not reach into `chain` / `storage` / `repo` / `commit` directly.\n//\n// Keep workflow logic here, not inside lower layers (CODE-RULES §5). When a\n// command needs scanning, hashing, uploading, row writing — this file\n// orchestrates them all.\n\nimport type { Connection } from \"@solana/web3.js\";\nimport { setRpcUrl } from \"@iqlabs-official/solana-sdk\";\nimport type { SignerInput } from \"@iqlabs-official/solana-sdk/utils\";\nimport { sha256Hex } from \"../core/hash\";\nimport { commitTableHint } from \"../core/seed\";\nimport type { Commit, FileTree, Repository } from \"../core/types\";\nimport * as chain from \"./chain\";\nimport * as commitLayer from \"./commit\";\nimport * as repoLayer from \"./repo\";\nimport * as storage from \"./storage\";\n\n/** Information surfaced to the `onWrite` callback for every successful row\n * write the SDK performs. Consumers wire this to their gateway notify so\n * the gateway updates its cache / SSE stream immediately. */\nexport interface WriteEvent {\n /** Resolved table PDA, base58 — pass directly to gateway notify. */\n tablePda: string;\n /** The hint that derived the PDA, in case callers want to log it. */\n tableHint: string;\n /** writeRow tx signature. */\n sig: string;\n /** The row object that was written (already JSON.stringify-able). */\n row: object;\n}\n\nexport interface GitClientConfig {\n connection: Connection;\n signer: SignerInput;\n /** Fires after each successful row write inside the SDK. Fire-and-forget\n * callback for gateway notifies; throwing here will surface to the caller. */\n onWrite?: (event: WriteEvent) => void;\n}\n\nexport class GitClient {\n // CODE-RULES §3 — only one small shape; inlined rather than aliased.\n constructor(private readonly cfg: GitClientConfig) {\n // The solana-sdk reader path (readTableRows / readCodeIn → loadTree /\n // readLatestCommit) does not take a Connection — it resolves a\n // process-global one from env / setRpcUrl. Writes use `cfg.connection`,\n // so without this reads could hit a different RPC (e.g. the mainnet-beta\n // fallback when no env is set, as in a built browser bundle). Sync the\n // reader's RPC to the connection the caller actually gave us.\n setRpcUrl(cfg.connection.rpcEndpoint);\n }\n\n /**\n * Create a new repo. Wraps repo.createRepo + pre-creating the commit table\n * so the first `commit()` call doesn't need to pay createTable cost.\n */\n async createRepo(meta: Repository): Promise<void> {\n const { connection, signer } = this.cfg;\n const writes = await repoLayer.createRepo(connection, signer, meta);\n await commitLayer.ensureCommitTable(connection, signer, meta.name);\n this.fireOnWrite(writes);\n }\n\n /**\n * Incremental commit against a scanned directory snapshot.\n *\n * input: repoName, message, scan — a `{ [path]: base64Content }` map that\n * the caller produced (Node: fs walk + base64; browser: File input).\n * output: newly written Commit\n */\n async commit(\n repoName: string,\n message: string,\n scan: Record<string, string>,\n ): Promise<Commit> {\n const { connection, signer } = this.cfg;\n const owner = signer.publicKey.toBase58();\n\n const latest = await commitLayer.readLatestCommit(commitLayer.commitTablePda(owner, repoName));\n const oldTree: FileTree = latest ? await storage.loadTree(latest.treeTxId) : {};\n\n const newTree: FileTree = {};\n for (const [path, content] of Object.entries(scan)) {\n newTree[path] = await storage.uploadBlob(\n connection,\n signer,\n path,\n content,\n oldTree,\n );\n }\n\n const treeTxId = await storage.uploadTree(connection, signer, newTree);\n\n const commit: Commit = {\n id: crypto.randomUUID(),\n message,\n treeTxId,\n parentCommitId: latest?.id,\n timestamp: Date.now(),\n author: owner,\n };\n const sig = await commitLayer.writeCommit(connection, signer, repoName, commit);\n this.fireOnWrite([{ tableHint: commitTableHint(owner, repoName), sig, row: commit }]);\n return commit;\n }\n\n /** Resolve the table hint to a PDA and forward each write to `onWrite`.\n * Wrapped in try/catch per call so a misbehaving notify can't fail the\n * whole batch — but we still surface the error so the consumer knows. */\n private fireOnWrite(writes: Array<{ tableHint: string; sig: string; row: object }>) {\n if (!this.cfg.onWrite) return;\n for (const w of writes) {\n const tablePda = chain.tablePda(w.tableHint).toBase58();\n this.cfg.onWrite({ tablePda, tableHint: w.tableHint, sig: w.sig, row: w.row });\n }\n }\n\n /**\n * Restore a commit's files into a caller-provided sink. Runtime-neutral\n * shape mirrors `commit`: the caller decides how to write bytes to disk /\n * to a File System Access API handle / anywhere else. `content` is the\n * raw base64 string — the sink decodes.\n */\n async checkout(\n repoName: string,\n commitId: string | \"latest\",\n sink: (path: string, content: string) => Promise<void>,\n ): Promise<Commit> {\n const { connection, signer } = this.cfg;\n const owner = signer.publicKey.toBase58();\n\n const pda = commitLayer.commitTablePda(owner, repoName);\n let target: Commit | null;\n if (commitId === \"latest\") {\n target = await commitLayer.readLatestCommit(pda);\n } else {\n const history = await commitLayer.readCommitHistory(pda);\n target = history.find((c) => c.id === commitId) ?? null;\n }\n if (!target) {\n throw new Error(`commit not found: ${commitId} in ${owner}/${repoName}`);\n }\n\n const tree = await storage.loadTree(target.treeTxId);\n for (const [path, entry] of Object.entries(tree)) {\n const content = await storage.loadBlob(entry.txId);\n await sink(path, content);\n }\n return target;\n }\n\n /**\n * Whole-repo snapshot download — convenience on top of checkout(\"latest\")\n * but reading from someone else's `owner`. We do not require signer to\n * equal owner for reads.\n */\n async clone(\n repoName: string,\n owner: string,\n sink: (path: string, content: string) => Promise<void>,\n ): Promise<Commit> {\n const target = await commitLayer.readLatestCommit(commitLayer.commitTablePda(owner, repoName));\n if (!target) {\n throw new Error(`no commits in ${owner}/${repoName}`);\n }\n const tree = await storage.loadTree(target.treeTxId);\n for (const [path, entry] of Object.entries(tree)) {\n const content = await storage.loadBlob(entry.txId);\n await sink(path, content);\n }\n return target;\n }\n\n /** Commit history for a repo. */\n async log(\n owner: string,\n repoName: string,\n options?: { limit?: number; before?: string },\n ): Promise<Commit[]> {\n return commitLayer.readCommitHistory(commitLayer.commitTablePda(owner, repoName), options);\n }\n\n /**\n * Compare a current directory snapshot to the latest commit's tree.\n */\n async status(\n owner: string,\n repoName: string,\n scan: Record<string, string>,\n ): Promise<{ added: string[]; modified: string[]; unchanged: string[] }> {\n const latest = await commitLayer.readLatestCommit(commitLayer.commitTablePda(owner, repoName));\n const tree: FileTree = latest ? await storage.loadTree(latest.treeTxId) : {};\n\n const added: string[] = [];\n const modified: string[] = [];\n const unchanged: string[] = [];\n for (const [path, content] of Object.entries(scan)) {\n const prior = tree[path];\n if (!prior) {\n added.push(path);\n continue;\n }\n const hash = await sha256Hex(content);\n (prior.hash === hash ? unchanged : modified).push(path);\n }\n return { added, modified, unchanged };\n }\n}\n","// Node entry. Installs the node:crypto SHA-256 hasher, then re-exports\n// everything from the shared root. CLI / migrator / test harnesses all go\n// through here.\n\nimport { setSha256 } from \"./core/hash\";\nimport { hashNode } from \"./platform/hash-node\";\n\nsetSha256(hashNode);\n\nexport * from \"./index\";\n"]}
|
package/dist/shared/index.d.ts
CHANGED
|
@@ -143,19 +143,14 @@ declare function bootstrapRegistry(connection: Connection, signer: SignerInput):
|
|
|
143
143
|
* waiting for RPC sig indexing.
|
|
144
144
|
*/
|
|
145
145
|
declare function writeCommit(connection: Connection, signer: SignerInput, repo: string, commit: Commit): Promise<string>;
|
|
146
|
+
/** The commit-table PDA for a repo. The one place owner/repo collapses to a
|
|
147
|
+
* PDA — every read keys off the PDA, so callers that have a PDA already (a
|
|
148
|
+
* .sol record, a dbroot match) skip this and pass it straight in. */
|
|
149
|
+
declare function commitTablePda(owner: string, repo: string): PublicKey;
|
|
146
150
|
/** Latest commit. Single-row, O(1) RPC path. */
|
|
147
|
-
declare function readLatestCommit(
|
|
151
|
+
declare function readLatestCommit(pda: PublicKey): Promise<Commit | null>;
|
|
148
152
|
/** Full commit history, newest first. */
|
|
149
|
-
declare function readCommitHistory(
|
|
150
|
-
limit?: number;
|
|
151
|
-
before?: string;
|
|
152
|
-
}): Promise<Commit[]>;
|
|
153
|
-
/**
|
|
154
|
-
* Commit history keyed by the commit-table PDA directly — for callers that
|
|
155
|
-
* resolved a repo to its PDA (e.g. via a .sol record) and don't have the
|
|
156
|
-
* owner/repo to rebuild the hint.
|
|
157
|
-
*/
|
|
158
|
-
declare function readCommitHistoryByPda(pda: PublicKey, options?: {
|
|
153
|
+
declare function readCommitHistory(pda: PublicKey, options?: {
|
|
159
154
|
limit?: number;
|
|
160
155
|
before?: string;
|
|
161
156
|
}): Promise<Commit[]>;
|
|
@@ -192,4 +187,4 @@ declare function setGatewayUrls(urls: string[]): void;
|
|
|
192
187
|
declare function setNetwork(network: "mainnet" | "devnet"): void;
|
|
193
188
|
declare function getGatewayUrls(): string[];
|
|
194
189
|
|
|
195
|
-
export { type Commit, type FileTree, GitClient, type GitClientConfig, IQGIT_ROOT_ID, REGISTRY_HINT, type RegistryEntry, type Repository, type WriteEvent, bootstrapRegistry, commitTableHint, getGatewayUrls, loadBlob, loadTree, readCommitHistory,
|
|
190
|
+
export { type Commit, type FileTree, GitClient, type GitClientConfig, IQGIT_ROOT_ID, REGISTRY_HINT, type RegistryEntry, type Repository, type WriteEvent, bootstrapRegistry, commitTableHint, commitTablePda, getGatewayUrls, loadBlob, loadTree, readCommitHistory, readLatestCommit, readOwnerRepos, readRegistryPage, repoListHint, setGatewayUrls, setNetwork, uploadBlob, uploadTree, writeCommit };
|
package/dist/shared/index.js
CHANGED
|
@@ -130,10 +130,6 @@ async function readRowsByPda(pda, options) {
|
|
|
130
130
|
if (viaGateway !== null) return viaGateway;
|
|
131
131
|
return readTableRows(pda, options);
|
|
132
132
|
}
|
|
133
|
-
async function readLatestRow(hint) {
|
|
134
|
-
const rows = await readRows(hint, { limit: 1 });
|
|
135
|
-
return rows[0] ?? null;
|
|
136
|
-
}
|
|
137
133
|
async function codeIn(connection, signer, data, filename, filetype, onProgress, speed = "light") {
|
|
138
134
|
return codeIn$1(
|
|
139
135
|
{ connection, signer },
|
|
@@ -194,15 +190,14 @@ async function writeCommit(connection, signer, repo, commit) {
|
|
|
194
190
|
notifyGateways(tablePda(hint).toBase58(), sig, commit, owner);
|
|
195
191
|
return sig;
|
|
196
192
|
}
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
return row;
|
|
193
|
+
function commitTablePda(owner, repo) {
|
|
194
|
+
return tablePda(commitTableHint(owner, repo));
|
|
200
195
|
}
|
|
201
|
-
async function
|
|
202
|
-
const rows = await
|
|
203
|
-
return rows;
|
|
196
|
+
async function readLatestCommit(pda) {
|
|
197
|
+
const rows = await readRowsByPda(pda, { limit: 1 });
|
|
198
|
+
return rows[0] ?? null;
|
|
204
199
|
}
|
|
205
|
-
async function
|
|
200
|
+
async function readCommitHistory(pda, options) {
|
|
206
201
|
const rows = await readRowsByPda(pda, options);
|
|
207
202
|
return rows;
|
|
208
203
|
}
|
|
@@ -337,7 +332,7 @@ var GitClient = class {
|
|
|
337
332
|
async commit(repoName, message, scan) {
|
|
338
333
|
const { connection, signer } = this.cfg;
|
|
339
334
|
const owner = signer.publicKey.toBase58();
|
|
340
|
-
const latest = await readLatestCommit(
|
|
335
|
+
const latest = await readLatestCommit(commitTablePda(owner, repoName));
|
|
341
336
|
const oldTree = latest ? await loadTree(latest.treeTxId) : {};
|
|
342
337
|
const newTree = {};
|
|
343
338
|
for (const [path, content] of Object.entries(scan)) {
|
|
@@ -381,11 +376,12 @@ var GitClient = class {
|
|
|
381
376
|
async checkout(repoName, commitId, sink) {
|
|
382
377
|
const { connection, signer } = this.cfg;
|
|
383
378
|
const owner = signer.publicKey.toBase58();
|
|
379
|
+
const pda = commitTablePda(owner, repoName);
|
|
384
380
|
let target;
|
|
385
381
|
if (commitId === "latest") {
|
|
386
|
-
target = await readLatestCommit(
|
|
382
|
+
target = await readLatestCommit(pda);
|
|
387
383
|
} else {
|
|
388
|
-
const history = await readCommitHistory(
|
|
384
|
+
const history = await readCommitHistory(pda);
|
|
389
385
|
target = history.find((c) => c.id === commitId) ?? null;
|
|
390
386
|
}
|
|
391
387
|
if (!target) {
|
|
@@ -404,8 +400,7 @@ var GitClient = class {
|
|
|
404
400
|
* equal owner for reads.
|
|
405
401
|
*/
|
|
406
402
|
async clone(repoName, owner, sink) {
|
|
407
|
-
const
|
|
408
|
-
const target = await readLatestCommit(connection, owner, repoName);
|
|
403
|
+
const target = await readLatestCommit(commitTablePda(owner, repoName));
|
|
409
404
|
if (!target) {
|
|
410
405
|
throw new Error(`no commits in ${owner}/${repoName}`);
|
|
411
406
|
}
|
|
@@ -418,22 +413,13 @@ var GitClient = class {
|
|
|
418
413
|
}
|
|
419
414
|
/** Commit history for a repo. */
|
|
420
415
|
async log(owner, repoName, options) {
|
|
421
|
-
return readCommitHistory(
|
|
422
|
-
this.cfg.connection,
|
|
423
|
-
owner,
|
|
424
|
-
repoName,
|
|
425
|
-
options
|
|
426
|
-
);
|
|
416
|
+
return readCommitHistory(commitTablePda(owner, repoName), options);
|
|
427
417
|
}
|
|
428
418
|
/**
|
|
429
419
|
* Compare a current directory snapshot to the latest commit's tree.
|
|
430
420
|
*/
|
|
431
421
|
async status(owner, repoName, scan) {
|
|
432
|
-
const latest = await readLatestCommit(
|
|
433
|
-
this.cfg.connection,
|
|
434
|
-
owner,
|
|
435
|
-
repoName
|
|
436
|
-
);
|
|
422
|
+
const latest = await readLatestCommit(commitTablePda(owner, repoName));
|
|
437
423
|
const tree = latest ? await loadTree(latest.treeTxId) : {};
|
|
438
424
|
const added = [];
|
|
439
425
|
const modified = [];
|
|
@@ -451,6 +437,6 @@ var GitClient = class {
|
|
|
451
437
|
}
|
|
452
438
|
};
|
|
453
439
|
|
|
454
|
-
export { GitClient, IQGIT_ROOT_ID, REGISTRY_HINT, bootstrapRegistry, commitTableHint, getGatewayUrls, loadBlob, loadTree, readCommitHistory,
|
|
440
|
+
export { GitClient, IQGIT_ROOT_ID, REGISTRY_HINT, bootstrapRegistry, commitTableHint, commitTablePda, getGatewayUrls, loadBlob, loadTree, readCommitHistory, readLatestCommit, readOwnerRepos, readRegistryPage, repoListHint, setGatewayUrls, setNetwork, uploadBlob, uploadTree, writeCommit };
|
|
455
441
|
//# sourceMappingURL=index.js.map
|
|
456
442
|
//# sourceMappingURL=index.js.map
|
package/dist/shared/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/core/seed.ts","../../src/core/hash.ts","../../src/layers/gateway.ts","../../src/layers/chain.ts","../../src/layers/commit.ts","../../src/layers/repo.ts","../../src/layers/storage.ts","../../src/layers/client.ts"],"names":["sdkCodeIn","sdkReadCodeIn","createTable","writeRow","tablePda"],"mappings":"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","file":"index.js","sourcesContent":["// The single source of truth for table_hint strings.\n//\n// Readers re-derive PDAs with `iqlabs.utils.toSeedBytes(hint)` →\n// `iqlabs.contract.getTablePda(...)`; writers pass the same hint into\n// `iqlabs.writer.createTable`. Keeping the naming convention in one place\n// prevents silent drift between writer and reader. CODE-RULES §2 — if any\n// caller ever wants to build one of these strings inline, route it here\n// instead.\n\n/** DbRoot id for every iq-git table. Bootstrap and every caller share this. */\nexport const IQGIT_ROOT_ID = \"iq-git-v1\";\n\n/** `git_repos:all` — open-writers registry that drives the public gallery. */\nexport const REGISTRY_HINT = \"git_repos:all\";\n\n/**\n * Hint for the per-owner personal repo list.\n * input: owner wallet base58\n * output: \"git_repos_v2_<owner>\"\n */\nexport function repoListHint(owner: string): string {\n return `git_repos_v2_${owner}`;\n}\n\n/**\n * Hint for the per-repo commit table.\n * input: owner wallet base58, repo name (any characters — SDK keccak-hashes)\n * output: \"git_commits:<owner>:<repo>\"\n */\nexport function commitTableHint(owner: string, repo: string): string {\n return `git_commits:${owner}:${repo}`;\n}\n","// SHA-256 content hashing for the blob-dedup index. Runtime-specific\n// implementations live in `platform/hash-node.ts` and `platform/hash-browser.ts`;\n// this module just declares the interface the rest of the SDK uses.\n//\n// Do NOT use this for deriving table seeds — that path is owned by\n// `iqlabs.utils.toSeedBytes` (keccak) and must stay aligned with the SDK.\n\n/**\n * SHA-256 of a UTF-8 or base64 string, returned as a lowercase hex digest.\n * Implementation is injected by the platform entry (node.ts / browser.ts).\n */\nexport type Sha256Hex = (input: string) => Promise<string>;\n\n// Platform entries (src/node.ts, src/browser.ts) will call `setSha256(...)`\n// during module init so downstream layers never care which runtime they are in.\n// This indirection is the one place where a wrapper is justified (CODE-RULES §1)\n// because the behavior genuinely differs per runtime.\nlet impl: Sha256Hex | undefined;\n\nexport function setSha256(fn: Sha256Hex): void {\n if (impl) {\n throw new Error(\n \"@iqlabs-official/git-sdk: sha256 implementation already installed. Import exactly one of '@iqlabs-official/git-sdk/node' or '@iqlabs-official/git-sdk/browser'.\",\n );\n }\n impl = fn;\n}\n\nexport async function sha256Hex(input: string): Promise<string> {\n if (!impl) {\n throw new Error(\n \"@iqlabs-official/git-sdk: sha256 not installed. Import '@iqlabs-official/git-sdk/node' (Node) or '@iqlabs-official/git-sdk/browser' (browser) before using the SDK.\",\n );\n }\n return impl(input);\n}\n","// L1.5 — iq-gateway HTTP helpers.\n//\n// chain.ts dispatches reads through here first; on a null return it falls\n// back to direct RPC. Writers fire-and-forget a notify so the gateway can\n// prepend the new row to its head-page cache without waiting on RPC\n// indexing.\n//\n// Configuration precedence (high → low):\n// 1. setGatewayUrls([...]) — explicit URL list\n// 2. IQGIT_GATEWAYS env (csv) — deployment-side pinning\n// 3. setNetwork(\"devnet\"|\"mainnet\") + the network's default gateway\n// 4. RPC URL hostname inference (`devnet` / `testnet` substring → devnet)\n// 5. Mainnet default — gateway.iqlabs.dev\n//\n// Everything here is best-effort: an unreachable, misconfigured, or\n// disabled gateway never breaks the SDK.\n\nimport { getRpcUrl } from \"@iqlabs-official/solana-sdk\";\n\nconst MAINNET_GATEWAY = \"https://gateway.iqlabs.dev\";\nconst DEVNET_GATEWAY = \"https://dev-gateway.iqlabs.dev\";\nconst REQ_TIMEOUT_MS = 5000;\n\nlet runtimeGateways: string[] | null = null;\nlet networkOverride: \"mainnet\" | \"devnet\" | null = null;\n\n/** Pin the gateway URL list explicitly. Highest precedence. Pass `[]` to\n * disable gateway dispatch entirely (RPC-only mode). */\nexport function setGatewayUrls(urls: string[]): void {\n runtimeGateways = urls.length > 0 ? urls : null;\n}\n\n/** Pin the network label when the RPC URL doesn't reveal it (private nodes,\n * proxies, etc.). Has no effect when setGatewayUrls() is also set. */\nexport function setNetwork(network: \"mainnet\" | \"devnet\"): void {\n networkOverride = network;\n}\n\nfunction inferNetwork(): \"mainnet\" | \"devnet\" {\n if (networkOverride) return networkOverride;\n const u = getRpcUrl().toLowerCase();\n if (u.includes(\"devnet\") || u.includes(\"testnet\")) return \"devnet\";\n return \"mainnet\";\n}\n\nexport function getGatewayUrls(): string[] {\n if (runtimeGateways) return runtimeGateways;\n\n const env = (typeof process !== \"undefined\" && process.env?.IQGIT_GATEWAYS) ?? \"\";\n if (env) return env.split(\",\").map((s) => s.trim()).filter(Boolean);\n\n return inferNetwork() === \"devnet\" ? [DEVNET_GATEWAY] : [MAINNET_GATEWAY];\n}\n\nasync function tryGateways<T>(\n path: (gw: string) => string,\n parse: (res: Response) => Promise<T>,\n): Promise<T | null> {\n for (const gw of getGatewayUrls()) {\n try {\n const ctrl = new AbortController();\n const timer = setTimeout(() => ctrl.abort(), REQ_TIMEOUT_MS);\n const res = await fetch(path(gw), { signal: ctrl.signal });\n clearTimeout(timer);\n if (res.ok) return await parse(res);\n } catch {\n // Try the next gateway.\n }\n }\n return null;\n}\n\n/** Fetch rows for a table PDA via /table/:pda/rows. Returns null when no\n * gateway is configured or all of them fail — caller falls back to RPC. */\nexport async function readRowsViaGateway(\n pdaBase58: string,\n options?: { limit?: number; before?: string },\n): Promise<Array<Record<string, unknown>> | null> {\n const qs = new URLSearchParams();\n if (options?.limit) qs.set(\"limit\", String(options.limit));\n if (options?.before) qs.set(\"before\", options.before);\n const suffix = qs.toString() ? `?${qs}` : \"\";\n\n return tryGateways(\n (gw) => `${gw}/table/${pdaBase58}/rows${suffix}`,\n async (res) => {\n const json = (await res.json()) as { rows?: unknown[] };\n return (json.rows ?? []) as Array<Record<string, unknown>>;\n },\n );\n}\n\n/** Fetch raw codeIn payload via /data/:sig. Gateway returns a superset of\n * what the SDK's readCodeIn produces; we extract just the matching fields. */\nexport async function readCodeInViaGateway(\n txSig: string,\n): Promise<{ data: string | null; metadata: string } | null> {\n return tryGateways(\n (gw) => `${gw}/data/${txSig}`,\n async (res) => {\n const json = (await res.json()) as { data?: string | null; metadata?: string };\n return { data: json.data ?? null, metadata: json.metadata ?? \"\" };\n },\n );\n}\n\n/** Fire-and-forget /notify after a successful write. Includes the row body\n * so the gateway can inject without an RPC roundtrip. Errors are swallowed\n * — the row is already on-chain, gateway hydration is opportunistic. */\nexport function notifyGateways(\n pdaBase58: string,\n txSig: string,\n row: object,\n signer: string,\n): void {\n const body = JSON.stringify({ txSignature: txSig, row, signer });\n for (const gw of getGatewayUrls()) {\n fetch(`${gw}/table/${pdaBase58}/notify`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body,\n }).catch(() => {});\n }\n}\n","// L1 — chain primitives shared by L2/L3. Kept tiny by design: each function\n// here either (a) hides PDA derivation so callers only deal with hints, or\n// (b) wraps a single iqlabs-sdk call to keep an iq-git-specific default\n// (chunk speed, root id, ...). Pure passthroughs like `createTable` /\n// `writeRow` live at the call site instead — wrapping them once more would\n// just bury the iqlabs-sdk surface (CODE-RULES §1).\n//\n// Read primitives transparently prefer the iq-gateway HTTP API and fall\n// back to direct RPC; the gateway dispatch lives here so commit/repo/\n// storage all benefit without each having to wire it up.\n\nimport {\n Keypair,\n SystemProgram,\n Transaction,\n type Connection,\n type PublicKey,\n} from \"@solana/web3.js\";\nimport {\n createInstructionBuilder,\n getDbRootPda,\n getTablePda,\n initializeDbRootInstruction,\n} from \"@iqlabs-official/solana-sdk/contract\";\nimport { readCodeIn as sdkReadCodeIn, readTableRows } from \"@iqlabs-official/solana-sdk/reader\";\nimport { toSeedBytes, type SignerInput, type WalletSigner } from \"@iqlabs-official/solana-sdk/utils\";\nimport { codeIn as sdkCodeIn } from \"@iqlabs-official/solana-sdk/writer\";\nimport { IQGIT_ROOT_ID } from \"../core/seed\";\nimport { readCodeInViaGateway, readRowsViaGateway } from \"./gateway\";\n\n/** DbRoot PDA for the `iq-git-v1` namespace — derived once, reused everywhere. */\nexport const DB_ROOT_SEED = toSeedBytes(IQGIT_ROOT_ID);\nexport const DB_ROOT = getDbRootPda(DB_ROOT_SEED);\n\n/**\n * Initialize the `iq-git-v1` DbRoot account if it doesn't exist. First-call\n * cost on a fresh network. Idempotent: returns null if already initialized.\n * Accepts any SignerInput so an admin can run it from a wallet, not just\n * from a Keypair.\n */\nexport async function ensureDbRoot(\n connection: Connection,\n signer: SignerInput,\n): Promise<string | null> {\n if (await accountExists(connection, DB_ROOT)) return null;\n const builder = createInstructionBuilder();\n const ix = initializeDbRootInstruction(\n builder,\n {\n db_root: DB_ROOT,\n signer: signer.publicKey,\n system_program: SystemProgram.programId,\n },\n { db_root_id: DB_ROOT_SEED },\n );\n const tx = new Transaction().add(ix);\n const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash();\n tx.recentBlockhash = blockhash;\n tx.feePayer = signer.publicKey;\n const signed = await signTx(signer, tx);\n const signature = await connection.sendRawTransaction(signed.serialize());\n await connection.confirmTransaction({ signature, blockhash, lastValidBlockHeight });\n return signature;\n}\n\n// Sign a single Transaction with whatever shape the signer takes. Keypair\n// has a `secretKey`; wallet adapters expose `signTransaction`. iqlabs-sdk's\n// own `sendTx` uses the same dispatch; we replicate it here so the helper\n// stays self-contained.\nasync function signTx(signer: SignerInput, tx: Transaction): Promise<Transaction> {\n if (signer instanceof Keypair || \"secretKey\" in signer) {\n tx.partialSign(signer as Keypair);\n return tx;\n }\n return (signer as WalletSigner).signTransaction(tx);\n}\n\n/**\n * Read rows from a table. Tries the iq-gateway HTTP cache first and falls\n * back to `iqlabs.reader.readTableRows` on miss. Callers see a uniform API\n * either way.\n */\nexport async function readRows(\n hint: string,\n options?: { limit?: number; before?: string },\n): Promise<Array<Record<string, unknown>>> {\n return readRowsByPda(tablePda(hint), options);\n}\n\n/**\n * Same as readRows but keyed by the table PDA directly — for callers that\n * already have the PDA (e.g. a .sol record pointing at a commit table) and\n * can't or shouldn't re-derive it from a hint.\n */\nexport async function readRowsByPda(\n pda: PublicKey,\n options?: { limit?: number; before?: string },\n): Promise<Array<Record<string, unknown>>> {\n const viaGateway = await readRowsViaGateway(pda.toBase58(), options);\n if (viaGateway !== null) return viaGateway;\n return readTableRows(pda, options);\n}\n\n/**\n * Fetch just the latest row of a table — the fast path for \"what is the\n * current commit\" and \"what is the pinned deploy\".\n */\nexport async function readLatestRow(\n hint: string,\n): Promise<Record<string, unknown> | null> {\n const rows = await readRows(hint, { limit: 1 });\n return rows[0] ?? null;\n}\n\n/**\n * Upload a blob via `iqlabs.writer.codeIn`. The SDK chunks internally when\n * `data` is a plain string. We default speed to \"light\" because that's the\n * Helius-friendly setting for git workloads (per-file uploads are bursty).\n */\nexport async function codeIn(\n connection: Connection,\n signer: SignerInput,\n data: string | string[],\n filename: string,\n filetype: string,\n onProgress?: (percent: number) => void,\n speed: \"light\" | \"medium\" | \"fast\" = \"light\",\n): Promise<string> {\n return sdkCodeIn(\n { connection, signer },\n data,\n filename,\n 0,\n filetype,\n onProgress,\n speed,\n );\n}\n\n/**\n * Read a codeIn payload by tx signature. Tries the gateway /data/:sig\n * cache first and falls back to the SDK's direct RPC decode.\n */\nexport async function readCodeIn(\n txSig: string,\n): Promise<{ data: string | null; metadata: string }> {\n const viaGateway = await readCodeInViaGateway(txSig);\n if (viaGateway !== null) return viaGateway;\n return sdkReadCodeIn(txSig);\n}\n\n/** Cheap existence check for a PDA. */\nexport async function accountExists(\n connection: Connection,\n pda: PublicKey,\n): Promise<boolean> {\n return (await connection.getAccountInfo(pda)) !== null;\n}\n\n/** Resolve a hint to its PDA. */\nexport function tablePda(hint: string): PublicKey {\n return getTablePda(DB_ROOT, toSeedBytes(hint));\n}\n","// L3 — per-repo commit table.\n//\n// v2's core invariant: each repo has its own table at hint\n// `git_commits:<owner>:<repo>`, with writers locked to [owner]. That means\n// \"the most recent successful tx in this table = the latest commit\", and we\n// read it as a single-row query (limit: 1).\n\nimport type { Connection, PublicKey } from \"@solana/web3.js\";\nimport { type SignerInput } from \"@iqlabs-official/solana-sdk/utils\";\nimport { createTable, writeRow } from \"@iqlabs-official/solana-sdk/writer\";\nimport { IQGIT_ROOT_ID, commitTableHint } from \"../core/seed\";\nimport type { Commit } from \"../core/types\";\nimport * as chain from \"./chain\";\nimport { notifyGateways } from \"./gateway\";\n\nconst COMMIT_COLUMNS = [\n \"id\",\n \"message\",\n \"treeTxId\",\n \"parentCommitId\",\n \"timestamp\",\n \"author\",\n];\n\n/**\n * Ensure the per-repo commit table exists with writers = [owner]. No-op if\n * it already exists.\n */\nexport async function ensureCommitTable(\n connection: Connection,\n signer: SignerInput,\n repo: string,\n): Promise<string | null> {\n const hint = commitTableHint(signer.publicKey.toBase58(), repo);\n if (await chain.accountExists(connection, chain.tablePda(hint))) return null;\n return createTable(\n connection,\n signer as never,\n IQGIT_ROOT_ID,\n hint,\n hint,\n COMMIT_COLUMNS,\n \"id\",\n [],\n undefined,\n [signer.publicKey],\n hint,\n );\n}\n\n/**\n * Append one commit row. Callers (workflow-level code) are responsible for\n * setting parentCommitId — the SDK does not auto-chain.\n *\n * After the row lands on-chain, fires a best-effort /notify so any\n * iq-gateway already caching this table prepends the new commit without\n * waiting for RPC sig indexing.\n */\nexport async function writeCommit(\n connection: Connection,\n signer: SignerInput,\n repo: string,\n commit: Commit,\n): Promise<string> {\n const owner = signer.publicKey.toBase58();\n const hint = commitTableHint(owner, repo);\n const sig = await writeRow(\n connection,\n signer,\n IQGIT_ROOT_ID,\n hint,\n JSON.stringify(commit),\n );\n notifyGateways(chain.tablePda(hint).toBase58(), sig, commit, owner);\n return sig;\n}\n\n/** Latest commit. Single-row, O(1) RPC path. */\nexport async function readLatestCommit(\n _connection: Connection,\n owner: string,\n repo: string,\n): Promise<Commit | null> {\n const row = await chain.readLatestRow(commitTableHint(owner, repo));\n return row as unknown as Commit | null;\n}\n\n/** Full commit history, newest first. */\nexport async function readCommitHistory(\n _connection: Connection,\n owner: string,\n repo: string,\n options?: { limit?: number; before?: string },\n): Promise<Commit[]> {\n const rows = await chain.readRows(commitTableHint(owner, repo), options);\n return rows as unknown as Commit[];\n}\n\n/**\n * Commit history keyed by the commit-table PDA directly — for callers that\n * resolved a repo to its PDA (e.g. via a .sol record) and don't have the\n * owner/repo to rebuild the hint.\n */\nexport async function readCommitHistoryByPda(\n pda: PublicKey,\n options?: { limit?: number; before?: string },\n): Promise<Commit[]> {\n const rows = await chain.readRowsByPda(pda, options);\n return rows as unknown as Commit[];\n}\n","// L3 — repo list and public registry.\n//\n// Covers the two \"directory\" tables:\n// • git_repos_v2_<owner> — owner's personal repo list (writers = [owner])\n// • git_repos:all — public gallery registry (writers = [])\n//\n// Commit tables are a separate concern — see `commit.ts`.\n\nimport type { Connection } from \"@solana/web3.js\";\nimport { type SignerInput } from \"@iqlabs-official/solana-sdk/utils\";\nimport { createTable, writeRow } from \"@iqlabs-official/solana-sdk/writer\";\nimport { IQGIT_ROOT_ID, REGISTRY_HINT, repoListHint } from \"../core/seed\";\nimport type { RegistryEntry, Repository } from \"../core/types\";\nimport * as chain from \"./chain\";\nimport { notifyGateways } from \"./gateway\";\n\nconst REPO_COLUMNS = [\"name\", \"description\", \"isPublic\", \"timestamp\"];\nconst REGISTRY_COLUMNS = [\"owner\", \"repo\", \"description\", \"timestamp\"];\n\n/**\n * Create a repo in the owner's personal list, and (if public) also register\n * it in the public gallery. Two transactions — the contract does not support\n * writing two tables atomically.\n *\n * Returns the writeRow tx signatures (and the table hint each one wrote to)\n * so a caller can notify gateways / build SSE streams for those tables. The\n * returned shape is `[]` from `createTable` calls because those don't write\n * a row, just allocate the account.\n */\nexport async function createRepo(\n connection: Connection,\n signer: SignerInput,\n meta: Repository,\n): Promise<Array<{ tableHint: string; sig: string; row: object }>> {\n const owner = signer.publicKey.toBase58();\n const listHint = repoListHint(owner);\n const writes: Array<{ tableHint: string; sig: string; row: object }> = [];\n\n if (!(await chain.accountExists(connection, chain.tablePda(listHint)))) {\n await createTable(\n connection,\n signer as never,\n IQGIT_ROOT_ID,\n listHint,\n listHint,\n REPO_COLUMNS,\n \"name\",\n [],\n undefined,\n [signer.publicKey],\n listHint,\n );\n }\n\n const sig = await writeRow(connection, signer, IQGIT_ROOT_ID, listHint, JSON.stringify(meta));\n writes.push({ tableHint: listHint, sig, row: meta });\n notifyGateways(chain.tablePda(listHint).toBase58(), sig, meta, owner);\n\n if (meta.isPublic) {\n const entry: RegistryEntry = {\n owner,\n repo: meta.name,\n description: meta.description,\n timestamp: meta.timestamp,\n };\n const regSig = await writeRow(connection, signer, IQGIT_ROOT_ID, REGISTRY_HINT, JSON.stringify(entry));\n writes.push({ tableHint: REGISTRY_HINT, sig: regSig, row: entry });\n notifyGateways(chain.tablePda(REGISTRY_HINT).toBase58(), regSig, entry, owner);\n }\n\n return writes;\n}\n\n/** List all repos owned by `owner`. */\nexport async function readOwnerRepos(\n _connection: Connection,\n owner: string,\n): Promise<Repository[]> {\n return (await chain.readRows(repoListHint(owner))) as unknown as Repository[];\n}\n\n/**\n * One page of the public-gallery registry. Callers should still check\n * `row.owner` shape before trusting it in UI; we do not filter at the SDK\n * boundary.\n */\nexport async function readRegistryPage(\n _connection: Connection,\n options?: { limit?: number; before?: string },\n): Promise<RegistryEntry[]> {\n return (await chain.readRows(REGISTRY_HINT, options)) as unknown as RegistryEntry[];\n}\n\n/**\n * One-time global bootstrap of the `git_repos:all` table. Run once per\n * network from an admin key; subsequent calls short-circuit because the\n * account already exists.\n */\nexport async function bootstrapRegistry(\n connection: Connection,\n signer: SignerInput,\n): Promise<string | null> {\n await chain.ensureDbRoot(connection, signer);\n if (await chain.accountExists(connection, chain.tablePda(REGISTRY_HINT))) {\n return null;\n }\n return createTable(\n connection,\n signer as never,\n IQGIT_ROOT_ID,\n REGISTRY_HINT,\n REGISTRY_HINT,\n REGISTRY_COLUMNS,\n \"owner\",\n [],\n undefined,\n undefined,\n REGISTRY_HINT,\n );\n}\n","// L2 — blob + tree storage.\n//\n// `uploadBlob` is the file-level \"don't re-upload what's already on-chain\"\n// primitive. Content is always a base64 string (matching iq-git v1) so the\n// hash / dedup comparison stays byte-for-byte compatible across commits.\n// The reuse-map is just a plain object so callers can build it any way they\n// like (path→entry, or hash→txId for rename-aware dedup — CODE-RULES §3\n// keeps this inlined at the call site instead of a new type).\n//\n// `uploadTree` / `loadTree` serialize FileTree <-> on-chain tree.json as raw\n// JSON (filetype `application/json`), again matching v1.\n\nimport type { Connection } from \"@solana/web3.js\";\nimport type { SignerInput } from \"@iqlabs-official/solana-sdk/utils\";\nimport { sha256Hex } from \"../core/hash\";\nimport type { FileTree } from \"../core/types\";\nimport * as chain from \"./chain\";\n\n/**\n * Upload one file unless an identical hash is already in `reuse` (blob dedup).\n *\n * input: connection, signer, relativePath, base64 content, reuse map, optional onProgress\n * output: { txId, hash } — either reused or freshly uploaded\n */\nexport async function uploadBlob(\n connection: Connection,\n signer: SignerInput,\n relativePath: string,\n base64Content: string,\n reuse: FileTree,\n onProgress?: (percent: number) => void,\n): Promise<{ txId: string; hash: string }> {\n const hash = await sha256Hex(base64Content);\n const prior = reuse[relativePath];\n if (prior && prior.hash === hash) return prior;\n\n // Tag the codeIn filename with our app marker so non-inline inventory\n // entries can be classified by inspecting metadata.filename alone (no row\n // body fetch needed). Format: \"iqgit-blob:<basename>\". Same scheme used\n // for trees (\"iqgit-tree\") and other writes across the IQ ecosystem.\n const basename = relativePath.split(\"/\").pop() || relativePath;\n const txId = await chain.codeIn(\n connection,\n signer,\n base64Content,\n `iqgit-blob:${basename}`,\n \"application/octet-stream\",\n onProgress,\n );\n return { txId, hash };\n}\n\n/**\n * Serialize a FileTree and upload it as one `tree.json` blob.\n */\nexport async function uploadTree(\n connection: Connection,\n signer: SignerInput,\n tree: FileTree,\n): Promise<string> {\n return chain.codeIn(\n connection,\n signer,\n JSON.stringify(tree),\n \"iqgit-tree\",\n \"application/json\",\n );\n}\n\n/**\n * Fetch and parse a `tree.json` blob by its tx signature.\n */\nexport async function loadTree(treeTxId: string): Promise<FileTree> {\n const { data } = await chain.readCodeIn(treeTxId);\n if (data === null) {\n throw new Error(`tree.json not found for tx ${treeTxId}`);\n }\n return JSON.parse(data) as FileTree;\n}\n\n/**\n * Retrieve a blob's bytes by its txId. Returns the raw string that was\n * uploaded — for blobs this is base64; the caller decodes.\n */\nexport async function loadBlob(txId: string): Promise<string> {\n const { data } = await chain.readCodeIn(txId);\n if (data === null) {\n throw new Error(`blob not found for tx ${txId}`);\n }\n return data;\n}\n","// L4 — GitClient facade. High-level workflows built by composing the\n// layers below. This is the surface consumers (CLI, frontend, migrator) use;\n// they should not reach into `chain` / `storage` / `repo` / `commit` directly.\n//\n// Keep workflow logic here, not inside lower layers (CODE-RULES §5). When a\n// command needs scanning, hashing, uploading, row writing — this file\n// orchestrates them all.\n\nimport type { Connection } from \"@solana/web3.js\";\nimport { setRpcUrl } from \"@iqlabs-official/solana-sdk\";\nimport type { SignerInput } from \"@iqlabs-official/solana-sdk/utils\";\nimport { sha256Hex } from \"../core/hash\";\nimport { commitTableHint } from \"../core/seed\";\nimport type { Commit, FileTree, Repository } from \"../core/types\";\nimport * as chain from \"./chain\";\nimport * as commitLayer from \"./commit\";\nimport * as repoLayer from \"./repo\";\nimport * as storage from \"./storage\";\n\n/** Information surfaced to the `onWrite` callback for every successful row\n * write the SDK performs. Consumers wire this to their gateway notify so\n * the gateway updates its cache / SSE stream immediately. */\nexport interface WriteEvent {\n /** Resolved table PDA, base58 — pass directly to gateway notify. */\n tablePda: string;\n /** The hint that derived the PDA, in case callers want to log it. */\n tableHint: string;\n /** writeRow tx signature. */\n sig: string;\n /** The row object that was written (already JSON.stringify-able). */\n row: object;\n}\n\nexport interface GitClientConfig {\n connection: Connection;\n signer: SignerInput;\n /** Fires after each successful row write inside the SDK. Fire-and-forget\n * callback for gateway notifies; throwing here will surface to the caller. */\n onWrite?: (event: WriteEvent) => void;\n}\n\nexport class GitClient {\n // CODE-RULES §3 — only one small shape; inlined rather than aliased.\n constructor(private readonly cfg: GitClientConfig) {\n // The solana-sdk reader path (readTableRows / readCodeIn → loadTree /\n // readLatestCommit) does not take a Connection — it resolves a\n // process-global one from env / setRpcUrl. Writes use `cfg.connection`,\n // so without this reads could hit a different RPC (e.g. the mainnet-beta\n // fallback when no env is set, as in a built browser bundle). Sync the\n // reader's RPC to the connection the caller actually gave us.\n setRpcUrl(cfg.connection.rpcEndpoint);\n }\n\n /**\n * Create a new repo. Wraps repo.createRepo + pre-creating the commit table\n * so the first `commit()` call doesn't need to pay createTable cost.\n */\n async createRepo(meta: Repository): Promise<void> {\n const { connection, signer } = this.cfg;\n const writes = await repoLayer.createRepo(connection, signer, meta);\n await commitLayer.ensureCommitTable(connection, signer, meta.name);\n this.fireOnWrite(writes);\n }\n\n /**\n * Incremental commit against a scanned directory snapshot.\n *\n * input: repoName, message, scan — a `{ [path]: base64Content }` map that\n * the caller produced (Node: fs walk + base64; browser: File input).\n * output: newly written Commit\n */\n async commit(\n repoName: string,\n message: string,\n scan: Record<string, string>,\n ): Promise<Commit> {\n const { connection, signer } = this.cfg;\n const owner = signer.publicKey.toBase58();\n\n const latest = await commitLayer.readLatestCommit(connection, owner, repoName);\n const oldTree: FileTree = latest ? await storage.loadTree(latest.treeTxId) : {};\n\n const newTree: FileTree = {};\n for (const [path, content] of Object.entries(scan)) {\n newTree[path] = await storage.uploadBlob(\n connection,\n signer,\n path,\n content,\n oldTree,\n );\n }\n\n const treeTxId = await storage.uploadTree(connection, signer, newTree);\n\n const commit: Commit = {\n id: crypto.randomUUID(),\n message,\n treeTxId,\n parentCommitId: latest?.id,\n timestamp: Date.now(),\n author: owner,\n };\n const sig = await commitLayer.writeCommit(connection, signer, repoName, commit);\n this.fireOnWrite([{ tableHint: commitTableHint(owner, repoName), sig, row: commit }]);\n return commit;\n }\n\n /** Resolve the table hint to a PDA and forward each write to `onWrite`.\n * Wrapped in try/catch per call so a misbehaving notify can't fail the\n * whole batch — but we still surface the error so the consumer knows. */\n private fireOnWrite(writes: Array<{ tableHint: string; sig: string; row: object }>) {\n if (!this.cfg.onWrite) return;\n for (const w of writes) {\n const tablePda = chain.tablePda(w.tableHint).toBase58();\n this.cfg.onWrite({ tablePda, tableHint: w.tableHint, sig: w.sig, row: w.row });\n }\n }\n\n /**\n * Restore a commit's files into a caller-provided sink. Runtime-neutral\n * shape mirrors `commit`: the caller decides how to write bytes to disk /\n * to a File System Access API handle / anywhere else. `content` is the\n * raw base64 string — the sink decodes.\n */\n async checkout(\n repoName: string,\n commitId: string | \"latest\",\n sink: (path: string, content: string) => Promise<void>,\n ): Promise<Commit> {\n const { connection, signer } = this.cfg;\n const owner = signer.publicKey.toBase58();\n\n let target: Commit | null;\n if (commitId === \"latest\") {\n target = await commitLayer.readLatestCommit(connection, owner, repoName);\n } else {\n const history = await commitLayer.readCommitHistory(connection, owner, repoName);\n target = history.find((c) => c.id === commitId) ?? null;\n }\n if (!target) {\n throw new Error(`commit not found: ${commitId} in ${owner}/${repoName}`);\n }\n\n const tree = await storage.loadTree(target.treeTxId);\n for (const [path, entry] of Object.entries(tree)) {\n const content = await storage.loadBlob(entry.txId);\n await sink(path, content);\n }\n return target;\n }\n\n /**\n * Whole-repo snapshot download — convenience on top of checkout(\"latest\")\n * but reading from someone else's `owner`. We do not require signer to\n * equal owner for reads.\n */\n async clone(\n repoName: string,\n owner: string,\n sink: (path: string, content: string) => Promise<void>,\n ): Promise<Commit> {\n const { connection } = this.cfg;\n const target = await commitLayer.readLatestCommit(connection, owner, repoName);\n if (!target) {\n throw new Error(`no commits in ${owner}/${repoName}`);\n }\n const tree = await storage.loadTree(target.treeTxId);\n for (const [path, entry] of Object.entries(tree)) {\n const content = await storage.loadBlob(entry.txId);\n await sink(path, content);\n }\n return target;\n }\n\n /** Commit history for a repo. */\n async log(\n owner: string,\n repoName: string,\n options?: { limit?: number; before?: string },\n ): Promise<Commit[]> {\n return commitLayer.readCommitHistory(\n this.cfg.connection,\n owner,\n repoName,\n options,\n );\n }\n\n /**\n * Compare a current directory snapshot to the latest commit's tree.\n */\n async status(\n owner: string,\n repoName: string,\n scan: Record<string, string>,\n ): Promise<{ added: string[]; modified: string[]; unchanged: string[] }> {\n const latest = await commitLayer.readLatestCommit(\n this.cfg.connection,\n owner,\n repoName,\n );\n const tree: FileTree = latest ? await storage.loadTree(latest.treeTxId) : {};\n\n const added: string[] = [];\n const modified: string[] = [];\n const unchanged: string[] = [];\n for (const [path, content] of Object.entries(scan)) {\n const prior = tree[path];\n if (!prior) {\n added.push(path);\n continue;\n }\n const hash = await sha256Hex(content);\n (prior.hash === hash ? unchanged : modified).push(path);\n }\n return { added, modified, unchanged };\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/core/seed.ts","../../src/core/hash.ts","../../src/layers/gateway.ts","../../src/layers/chain.ts","../../src/layers/commit.ts","../../src/layers/repo.ts","../../src/layers/storage.ts","../../src/layers/client.ts"],"names":["sdkCodeIn","sdkReadCodeIn","createTable","writeRow","tablePda"],"mappings":"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","file":"index.js","sourcesContent":["// The single source of truth for table_hint strings.\n//\n// Readers re-derive PDAs with `iqlabs.utils.toSeedBytes(hint)` →\n// `iqlabs.contract.getTablePda(...)`; writers pass the same hint into\n// `iqlabs.writer.createTable`. Keeping the naming convention in one place\n// prevents silent drift between writer and reader. CODE-RULES §2 — if any\n// caller ever wants to build one of these strings inline, route it here\n// instead.\n\n/** DbRoot id for every iq-git table. Bootstrap and every caller share this. */\nexport const IQGIT_ROOT_ID = \"iq-git-v1\";\n\n/** `git_repos:all` — open-writers registry that drives the public gallery. */\nexport const REGISTRY_HINT = \"git_repos:all\";\n\n/**\n * Hint for the per-owner personal repo list.\n * input: owner wallet base58\n * output: \"git_repos_v2_<owner>\"\n */\nexport function repoListHint(owner: string): string {\n return `git_repos_v2_${owner}`;\n}\n\n/**\n * Hint for the per-repo commit table.\n * input: owner wallet base58, repo name (any characters — SDK keccak-hashes)\n * output: \"git_commits:<owner>:<repo>\"\n */\nexport function commitTableHint(owner: string, repo: string): string {\n return `git_commits:${owner}:${repo}`;\n}\n","// SHA-256 content hashing for the blob-dedup index. Runtime-specific\n// implementations live in `platform/hash-node.ts` and `platform/hash-browser.ts`;\n// this module just declares the interface the rest of the SDK uses.\n//\n// Do NOT use this for deriving table seeds — that path is owned by\n// `iqlabs.utils.toSeedBytes` (keccak) and must stay aligned with the SDK.\n\n/**\n * SHA-256 of a UTF-8 or base64 string, returned as a lowercase hex digest.\n * Implementation is injected by the platform entry (node.ts / browser.ts).\n */\nexport type Sha256Hex = (input: string) => Promise<string>;\n\n// Platform entries (src/node.ts, src/browser.ts) will call `setSha256(...)`\n// during module init so downstream layers never care which runtime they are in.\n// This indirection is the one place where a wrapper is justified (CODE-RULES §1)\n// because the behavior genuinely differs per runtime.\nlet impl: Sha256Hex | undefined;\n\nexport function setSha256(fn: Sha256Hex): void {\n if (impl) {\n throw new Error(\n \"@iqlabs-official/git-sdk: sha256 implementation already installed. Import exactly one of '@iqlabs-official/git-sdk/node' or '@iqlabs-official/git-sdk/browser'.\",\n );\n }\n impl = fn;\n}\n\nexport async function sha256Hex(input: string): Promise<string> {\n if (!impl) {\n throw new Error(\n \"@iqlabs-official/git-sdk: sha256 not installed. Import '@iqlabs-official/git-sdk/node' (Node) or '@iqlabs-official/git-sdk/browser' (browser) before using the SDK.\",\n );\n }\n return impl(input);\n}\n","// L1.5 — iq-gateway HTTP helpers.\n//\n// chain.ts dispatches reads through here first; on a null return it falls\n// back to direct RPC. Writers fire-and-forget a notify so the gateway can\n// prepend the new row to its head-page cache without waiting on RPC\n// indexing.\n//\n// Configuration precedence (high → low):\n// 1. setGatewayUrls([...]) — explicit URL list\n// 2. IQGIT_GATEWAYS env (csv) — deployment-side pinning\n// 3. setNetwork(\"devnet\"|\"mainnet\") + the network's default gateway\n// 4. RPC URL hostname inference (`devnet` / `testnet` substring → devnet)\n// 5. Mainnet default — gateway.iqlabs.dev\n//\n// Everything here is best-effort: an unreachable, misconfigured, or\n// disabled gateway never breaks the SDK.\n\nimport { getRpcUrl } from \"@iqlabs-official/solana-sdk\";\n\nconst MAINNET_GATEWAY = \"https://gateway.iqlabs.dev\";\nconst DEVNET_GATEWAY = \"https://dev-gateway.iqlabs.dev\";\nconst REQ_TIMEOUT_MS = 5000;\n\nlet runtimeGateways: string[] | null = null;\nlet networkOverride: \"mainnet\" | \"devnet\" | null = null;\n\n/** Pin the gateway URL list explicitly. Highest precedence. Pass `[]` to\n * disable gateway dispatch entirely (RPC-only mode). */\nexport function setGatewayUrls(urls: string[]): void {\n runtimeGateways = urls.length > 0 ? urls : null;\n}\n\n/** Pin the network label when the RPC URL doesn't reveal it (private nodes,\n * proxies, etc.). Has no effect when setGatewayUrls() is also set. */\nexport function setNetwork(network: \"mainnet\" | \"devnet\"): void {\n networkOverride = network;\n}\n\nfunction inferNetwork(): \"mainnet\" | \"devnet\" {\n if (networkOverride) return networkOverride;\n const u = getRpcUrl().toLowerCase();\n if (u.includes(\"devnet\") || u.includes(\"testnet\")) return \"devnet\";\n return \"mainnet\";\n}\n\nexport function getGatewayUrls(): string[] {\n if (runtimeGateways) return runtimeGateways;\n\n const env = (typeof process !== \"undefined\" && process.env?.IQGIT_GATEWAYS) ?? \"\";\n if (env) return env.split(\",\").map((s) => s.trim()).filter(Boolean);\n\n return inferNetwork() === \"devnet\" ? [DEVNET_GATEWAY] : [MAINNET_GATEWAY];\n}\n\nasync function tryGateways<T>(\n path: (gw: string) => string,\n parse: (res: Response) => Promise<T>,\n): Promise<T | null> {\n for (const gw of getGatewayUrls()) {\n try {\n const ctrl = new AbortController();\n const timer = setTimeout(() => ctrl.abort(), REQ_TIMEOUT_MS);\n const res = await fetch(path(gw), { signal: ctrl.signal });\n clearTimeout(timer);\n if (res.ok) return await parse(res);\n } catch {\n // Try the next gateway.\n }\n }\n return null;\n}\n\n/** Fetch rows for a table PDA via /table/:pda/rows. Returns null when no\n * gateway is configured or all of them fail — caller falls back to RPC. */\nexport async function readRowsViaGateway(\n pdaBase58: string,\n options?: { limit?: number; before?: string },\n): Promise<Array<Record<string, unknown>> | null> {\n const qs = new URLSearchParams();\n if (options?.limit) qs.set(\"limit\", String(options.limit));\n if (options?.before) qs.set(\"before\", options.before);\n const suffix = qs.toString() ? `?${qs}` : \"\";\n\n return tryGateways(\n (gw) => `${gw}/table/${pdaBase58}/rows${suffix}`,\n async (res) => {\n const json = (await res.json()) as { rows?: unknown[] };\n return (json.rows ?? []) as Array<Record<string, unknown>>;\n },\n );\n}\n\n/** Fetch raw codeIn payload via /data/:sig. Gateway returns a superset of\n * what the SDK's readCodeIn produces; we extract just the matching fields. */\nexport async function readCodeInViaGateway(\n txSig: string,\n): Promise<{ data: string | null; metadata: string } | null> {\n return tryGateways(\n (gw) => `${gw}/data/${txSig}`,\n async (res) => {\n const json = (await res.json()) as { data?: string | null; metadata?: string };\n return { data: json.data ?? null, metadata: json.metadata ?? \"\" };\n },\n );\n}\n\n/** Fire-and-forget /notify after a successful write. Includes the row body\n * so the gateway can inject without an RPC roundtrip. Errors are swallowed\n * — the row is already on-chain, gateway hydration is opportunistic. */\nexport function notifyGateways(\n pdaBase58: string,\n txSig: string,\n row: object,\n signer: string,\n): void {\n const body = JSON.stringify({ txSignature: txSig, row, signer });\n for (const gw of getGatewayUrls()) {\n fetch(`${gw}/table/${pdaBase58}/notify`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body,\n }).catch(() => {});\n }\n}\n","// L1 — chain primitives shared by L2/L3. Kept tiny by design: each function\n// here either (a) hides PDA derivation so callers only deal with hints, or\n// (b) wraps a single iqlabs-sdk call to keep an iq-git-specific default\n// (chunk speed, root id, ...). Pure passthroughs like `createTable` /\n// `writeRow` live at the call site instead — wrapping them once more would\n// just bury the iqlabs-sdk surface (CODE-RULES §1).\n//\n// Read primitives transparently prefer the iq-gateway HTTP API and fall\n// back to direct RPC; the gateway dispatch lives here so commit/repo/\n// storage all benefit without each having to wire it up.\n\nimport {\n Keypair,\n SystemProgram,\n Transaction,\n type Connection,\n type PublicKey,\n} from \"@solana/web3.js\";\nimport {\n createInstructionBuilder,\n getDbRootPda,\n getTablePda,\n initializeDbRootInstruction,\n} from \"@iqlabs-official/solana-sdk/contract\";\nimport { readCodeIn as sdkReadCodeIn, readTableRows } from \"@iqlabs-official/solana-sdk/reader\";\nimport { toSeedBytes, type SignerInput, type WalletSigner } from \"@iqlabs-official/solana-sdk/utils\";\nimport { codeIn as sdkCodeIn } from \"@iqlabs-official/solana-sdk/writer\";\nimport { IQGIT_ROOT_ID } from \"../core/seed\";\nimport { readCodeInViaGateway, readRowsViaGateway } from \"./gateway\";\n\n/** DbRoot PDA for the `iq-git-v1` namespace — derived once, reused everywhere. */\nexport const DB_ROOT_SEED = toSeedBytes(IQGIT_ROOT_ID);\nexport const DB_ROOT = getDbRootPda(DB_ROOT_SEED);\n\n/**\n * Initialize the `iq-git-v1` DbRoot account if it doesn't exist. First-call\n * cost on a fresh network. Idempotent: returns null if already initialized.\n * Accepts any SignerInput so an admin can run it from a wallet, not just\n * from a Keypair.\n */\nexport async function ensureDbRoot(\n connection: Connection,\n signer: SignerInput,\n): Promise<string | null> {\n if (await accountExists(connection, DB_ROOT)) return null;\n const builder = createInstructionBuilder();\n const ix = initializeDbRootInstruction(\n builder,\n {\n db_root: DB_ROOT,\n signer: signer.publicKey,\n system_program: SystemProgram.programId,\n },\n { db_root_id: DB_ROOT_SEED },\n );\n const tx = new Transaction().add(ix);\n const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash();\n tx.recentBlockhash = blockhash;\n tx.feePayer = signer.publicKey;\n const signed = await signTx(signer, tx);\n const signature = await connection.sendRawTransaction(signed.serialize());\n await connection.confirmTransaction({ signature, blockhash, lastValidBlockHeight });\n return signature;\n}\n\n// Sign a single Transaction with whatever shape the signer takes. Keypair\n// has a `secretKey`; wallet adapters expose `signTransaction`. iqlabs-sdk's\n// own `sendTx` uses the same dispatch; we replicate it here so the helper\n// stays self-contained.\nasync function signTx(signer: SignerInput, tx: Transaction): Promise<Transaction> {\n if (signer instanceof Keypair || \"secretKey\" in signer) {\n tx.partialSign(signer as Keypair);\n return tx;\n }\n return (signer as WalletSigner).signTransaction(tx);\n}\n\n/**\n * Read rows from a table. Tries the iq-gateway HTTP cache first and falls\n * back to `iqlabs.reader.readTableRows` on miss. Callers see a uniform API\n * either way.\n */\nexport async function readRows(\n hint: string,\n options?: { limit?: number; before?: string },\n): Promise<Array<Record<string, unknown>>> {\n return readRowsByPda(tablePda(hint), options);\n}\n\n/**\n * Same as readRows but keyed by the table PDA directly — for callers that\n * already have the PDA (e.g. a .sol record pointing at a commit table) and\n * can't or shouldn't re-derive it from a hint.\n */\nexport async function readRowsByPda(\n pda: PublicKey,\n options?: { limit?: number; before?: string },\n): Promise<Array<Record<string, unknown>>> {\n const viaGateway = await readRowsViaGateway(pda.toBase58(), options);\n if (viaGateway !== null) return viaGateway;\n return readTableRows(pda, options);\n}\n\n/**\n * Fetch just the latest row of a table — the fast path for \"what is the\n * current commit\" and \"what is the pinned deploy\".\n */\nexport async function readLatestRow(\n hint: string,\n): Promise<Record<string, unknown> | null> {\n const rows = await readRows(hint, { limit: 1 });\n return rows[0] ?? null;\n}\n\n/**\n * Upload a blob via `iqlabs.writer.codeIn`. The SDK chunks internally when\n * `data` is a plain string. We default speed to \"light\" because that's the\n * Helius-friendly setting for git workloads (per-file uploads are bursty).\n */\nexport async function codeIn(\n connection: Connection,\n signer: SignerInput,\n data: string | string[],\n filename: string,\n filetype: string,\n onProgress?: (percent: number) => void,\n speed: \"light\" | \"medium\" | \"fast\" = \"light\",\n): Promise<string> {\n return sdkCodeIn(\n { connection, signer },\n data,\n filename,\n 0,\n filetype,\n onProgress,\n speed,\n );\n}\n\n/**\n * Read a codeIn payload by tx signature. Tries the gateway /data/:sig\n * cache first and falls back to the SDK's direct RPC decode.\n */\nexport async function readCodeIn(\n txSig: string,\n): Promise<{ data: string | null; metadata: string }> {\n const viaGateway = await readCodeInViaGateway(txSig);\n if (viaGateway !== null) return viaGateway;\n return sdkReadCodeIn(txSig);\n}\n\n/** Cheap existence check for a PDA. */\nexport async function accountExists(\n connection: Connection,\n pda: PublicKey,\n): Promise<boolean> {\n return (await connection.getAccountInfo(pda)) !== null;\n}\n\n/** Resolve a hint to its PDA. */\nexport function tablePda(hint: string): PublicKey {\n return getTablePda(DB_ROOT, toSeedBytes(hint));\n}\n","// L3 — per-repo commit table.\n//\n// v2's core invariant: each repo has its own table at hint\n// `git_commits:<owner>:<repo>`, with writers locked to [owner]. That means\n// \"the most recent successful tx in this table = the latest commit\", and we\n// read it as a single-row query (limit: 1).\n\nimport type { Connection, PublicKey } from \"@solana/web3.js\";\nimport { type SignerInput } from \"@iqlabs-official/solana-sdk/utils\";\nimport { createTable, writeRow } from \"@iqlabs-official/solana-sdk/writer\";\nimport { IQGIT_ROOT_ID, commitTableHint } from \"../core/seed\";\nimport type { Commit } from \"../core/types\";\nimport * as chain from \"./chain\";\nimport { notifyGateways } from \"./gateway\";\n\nconst COMMIT_COLUMNS = [\n \"id\",\n \"message\",\n \"treeTxId\",\n \"parentCommitId\",\n \"timestamp\",\n \"author\",\n];\n\n/**\n * Ensure the per-repo commit table exists with writers = [owner]. No-op if\n * it already exists.\n */\nexport async function ensureCommitTable(\n connection: Connection,\n signer: SignerInput,\n repo: string,\n): Promise<string | null> {\n const hint = commitTableHint(signer.publicKey.toBase58(), repo);\n if (await chain.accountExists(connection, chain.tablePda(hint))) return null;\n return createTable(\n connection,\n signer,\n IQGIT_ROOT_ID,\n hint,\n hint,\n COMMIT_COLUMNS,\n \"id\",\n [],\n undefined,\n [signer.publicKey],\n hint,\n );\n}\n\n/**\n * Append one commit row. Callers (workflow-level code) are responsible for\n * setting parentCommitId — the SDK does not auto-chain.\n *\n * After the row lands on-chain, fires a best-effort /notify so any\n * iq-gateway already caching this table prepends the new commit without\n * waiting for RPC sig indexing.\n */\nexport async function writeCommit(\n connection: Connection,\n signer: SignerInput,\n repo: string,\n commit: Commit,\n): Promise<string> {\n const owner = signer.publicKey.toBase58();\n const hint = commitTableHint(owner, repo);\n const sig = await writeRow(\n connection,\n signer,\n IQGIT_ROOT_ID,\n hint,\n JSON.stringify(commit),\n );\n notifyGateways(chain.tablePda(hint).toBase58(), sig, commit, owner);\n return sig;\n}\n\n/** The commit-table PDA for a repo. The one place owner/repo collapses to a\n * PDA — every read keys off the PDA, so callers that have a PDA already (a\n * .sol record, a dbroot match) skip this and pass it straight in. */\nexport function commitTablePda(owner: string, repo: string): PublicKey {\n return chain.tablePda(commitTableHint(owner, repo));\n}\n\n/** Latest commit. Single-row, O(1) RPC path. */\nexport async function readLatestCommit(pda: PublicKey): Promise<Commit | null> {\n const rows = await chain.readRowsByPda(pda, { limit: 1 });\n return (rows[0] as unknown as Commit) ?? null;\n}\n\n/** Full commit history, newest first. */\nexport async function readCommitHistory(\n pda: PublicKey,\n options?: { limit?: number; before?: string },\n): Promise<Commit[]> {\n const rows = await chain.readRowsByPda(pda, options);\n return rows as unknown as Commit[];\n}\n","// L3 — repo list and public registry.\n//\n// Covers the two \"directory\" tables:\n// • git_repos_v2_<owner> — owner's personal repo list (writers = [owner])\n// • git_repos:all — public gallery registry (writers = [])\n//\n// Commit tables are a separate concern — see `commit.ts`.\n\nimport type { Connection } from \"@solana/web3.js\";\nimport { type SignerInput } from \"@iqlabs-official/solana-sdk/utils\";\nimport { createTable, writeRow } from \"@iqlabs-official/solana-sdk/writer\";\nimport { IQGIT_ROOT_ID, REGISTRY_HINT, repoListHint } from \"../core/seed\";\nimport type { RegistryEntry, Repository } from \"../core/types\";\nimport * as chain from \"./chain\";\nimport { notifyGateways } from \"./gateway\";\n\nconst REPO_COLUMNS = [\"name\", \"description\", \"isPublic\", \"timestamp\"];\nconst REGISTRY_COLUMNS = [\"owner\", \"repo\", \"description\", \"timestamp\"];\n\n/**\n * Create a repo in the owner's personal list, and (if public) also register\n * it in the public gallery. Two transactions — the contract does not support\n * writing two tables atomically.\n *\n * Returns the writeRow tx signatures (and the table hint each one wrote to)\n * so a caller can notify gateways / build SSE streams for those tables. The\n * returned shape is `[]` from `createTable` calls because those don't write\n * a row, just allocate the account.\n */\nexport async function createRepo(\n connection: Connection,\n signer: SignerInput,\n meta: Repository,\n): Promise<Array<{ tableHint: string; sig: string; row: object }>> {\n const owner = signer.publicKey.toBase58();\n const listHint = repoListHint(owner);\n const writes: Array<{ tableHint: string; sig: string; row: object }> = [];\n\n if (!(await chain.accountExists(connection, chain.tablePda(listHint)))) {\n await createTable(\n connection,\n signer,\n IQGIT_ROOT_ID,\n listHint,\n listHint,\n REPO_COLUMNS,\n \"name\",\n [],\n undefined,\n [signer.publicKey],\n listHint,\n );\n }\n\n const sig = await writeRow(connection, signer, IQGIT_ROOT_ID, listHint, JSON.stringify(meta));\n writes.push({ tableHint: listHint, sig, row: meta });\n notifyGateways(chain.tablePda(listHint).toBase58(), sig, meta, owner);\n\n if (meta.isPublic) {\n const entry: RegistryEntry = {\n owner,\n repo: meta.name,\n description: meta.description,\n timestamp: meta.timestamp,\n };\n const regSig = await writeRow(connection, signer, IQGIT_ROOT_ID, REGISTRY_HINT, JSON.stringify(entry));\n writes.push({ tableHint: REGISTRY_HINT, sig: regSig, row: entry });\n notifyGateways(chain.tablePda(REGISTRY_HINT).toBase58(), regSig, entry, owner);\n }\n\n return writes;\n}\n\n/** List all repos owned by `owner`. */\nexport async function readOwnerRepos(\n _connection: Connection,\n owner: string,\n): Promise<Repository[]> {\n return (await chain.readRows(repoListHint(owner))) as unknown as Repository[];\n}\n\n/**\n * One page of the public-gallery registry. Callers should still check\n * `row.owner` shape before trusting it in UI; we do not filter at the SDK\n * boundary.\n */\nexport async function readRegistryPage(\n _connection: Connection,\n options?: { limit?: number; before?: string },\n): Promise<RegistryEntry[]> {\n return (await chain.readRows(REGISTRY_HINT, options)) as unknown as RegistryEntry[];\n}\n\n/**\n * One-time global bootstrap of the `git_repos:all` table. Run once per\n * network from an admin key; subsequent calls short-circuit because the\n * account already exists.\n */\nexport async function bootstrapRegistry(\n connection: Connection,\n signer: SignerInput,\n): Promise<string | null> {\n await chain.ensureDbRoot(connection, signer);\n if (await chain.accountExists(connection, chain.tablePda(REGISTRY_HINT))) {\n return null;\n }\n return createTable(\n connection,\n signer,\n IQGIT_ROOT_ID,\n REGISTRY_HINT,\n REGISTRY_HINT,\n REGISTRY_COLUMNS,\n \"owner\",\n [],\n undefined,\n undefined,\n REGISTRY_HINT,\n );\n}\n","// L2 — blob + tree storage.\n//\n// `uploadBlob` is the file-level \"don't re-upload what's already on-chain\"\n// primitive. Content is always a base64 string (matching iq-git v1) so the\n// hash / dedup comparison stays byte-for-byte compatible across commits.\n// The reuse-map is just a plain object so callers can build it any way they\n// like (path→entry, or hash→txId for rename-aware dedup — CODE-RULES §3\n// keeps this inlined at the call site instead of a new type).\n//\n// `uploadTree` / `loadTree` serialize FileTree <-> on-chain tree.json as raw\n// JSON (filetype `application/json`), again matching v1.\n\nimport type { Connection } from \"@solana/web3.js\";\nimport type { SignerInput } from \"@iqlabs-official/solana-sdk/utils\";\nimport { sha256Hex } from \"../core/hash\";\nimport type { FileTree } from \"../core/types\";\nimport * as chain from \"./chain\";\n\n/**\n * Upload one file unless an identical hash is already in `reuse` (blob dedup).\n *\n * input: connection, signer, relativePath, base64 content, reuse map, optional onProgress\n * output: { txId, hash } — either reused or freshly uploaded\n */\nexport async function uploadBlob(\n connection: Connection,\n signer: SignerInput,\n relativePath: string,\n base64Content: string,\n reuse: FileTree,\n onProgress?: (percent: number) => void,\n): Promise<{ txId: string; hash: string }> {\n const hash = await sha256Hex(base64Content);\n const prior = reuse[relativePath];\n if (prior && prior.hash === hash) return prior;\n\n // Tag the codeIn filename with our app marker so non-inline inventory\n // entries can be classified by inspecting metadata.filename alone (no row\n // body fetch needed). Format: \"iqgit-blob:<basename>\". Same scheme used\n // for trees (\"iqgit-tree\") and other writes across the IQ ecosystem.\n const basename = relativePath.split(\"/\").pop() || relativePath;\n const txId = await chain.codeIn(\n connection,\n signer,\n base64Content,\n `iqgit-blob:${basename}`,\n \"application/octet-stream\",\n onProgress,\n );\n return { txId, hash };\n}\n\n/**\n * Serialize a FileTree and upload it as one `tree.json` blob.\n */\nexport async function uploadTree(\n connection: Connection,\n signer: SignerInput,\n tree: FileTree,\n): Promise<string> {\n return chain.codeIn(\n connection,\n signer,\n JSON.stringify(tree),\n \"iqgit-tree\",\n \"application/json\",\n );\n}\n\n/**\n * Fetch and parse a `tree.json` blob by its tx signature.\n */\nexport async function loadTree(treeTxId: string): Promise<FileTree> {\n const { data } = await chain.readCodeIn(treeTxId);\n if (data === null) {\n throw new Error(`tree.json not found for tx ${treeTxId}`);\n }\n return JSON.parse(data) as FileTree;\n}\n\n/**\n * Retrieve a blob's bytes by its txId. Returns the raw string that was\n * uploaded — for blobs this is base64; the caller decodes.\n */\nexport async function loadBlob(txId: string): Promise<string> {\n const { data } = await chain.readCodeIn(txId);\n if (data === null) {\n throw new Error(`blob not found for tx ${txId}`);\n }\n return data;\n}\n","// L4 — GitClient facade. High-level workflows built by composing the\n// layers below. This is the surface consumers (CLI, frontend, migrator) use;\n// they should not reach into `chain` / `storage` / `repo` / `commit` directly.\n//\n// Keep workflow logic here, not inside lower layers (CODE-RULES §5). When a\n// command needs scanning, hashing, uploading, row writing — this file\n// orchestrates them all.\n\nimport type { Connection } from \"@solana/web3.js\";\nimport { setRpcUrl } from \"@iqlabs-official/solana-sdk\";\nimport type { SignerInput } from \"@iqlabs-official/solana-sdk/utils\";\nimport { sha256Hex } from \"../core/hash\";\nimport { commitTableHint } from \"../core/seed\";\nimport type { Commit, FileTree, Repository } from \"../core/types\";\nimport * as chain from \"./chain\";\nimport * as commitLayer from \"./commit\";\nimport * as repoLayer from \"./repo\";\nimport * as storage from \"./storage\";\n\n/** Information surfaced to the `onWrite` callback for every successful row\n * write the SDK performs. Consumers wire this to their gateway notify so\n * the gateway updates its cache / SSE stream immediately. */\nexport interface WriteEvent {\n /** Resolved table PDA, base58 — pass directly to gateway notify. */\n tablePda: string;\n /** The hint that derived the PDA, in case callers want to log it. */\n tableHint: string;\n /** writeRow tx signature. */\n sig: string;\n /** The row object that was written (already JSON.stringify-able). */\n row: object;\n}\n\nexport interface GitClientConfig {\n connection: Connection;\n signer: SignerInput;\n /** Fires after each successful row write inside the SDK. Fire-and-forget\n * callback for gateway notifies; throwing here will surface to the caller. */\n onWrite?: (event: WriteEvent) => void;\n}\n\nexport class GitClient {\n // CODE-RULES §3 — only one small shape; inlined rather than aliased.\n constructor(private readonly cfg: GitClientConfig) {\n // The solana-sdk reader path (readTableRows / readCodeIn → loadTree /\n // readLatestCommit) does not take a Connection — it resolves a\n // process-global one from env / setRpcUrl. Writes use `cfg.connection`,\n // so without this reads could hit a different RPC (e.g. the mainnet-beta\n // fallback when no env is set, as in a built browser bundle). Sync the\n // reader's RPC to the connection the caller actually gave us.\n setRpcUrl(cfg.connection.rpcEndpoint);\n }\n\n /**\n * Create a new repo. Wraps repo.createRepo + pre-creating the commit table\n * so the first `commit()` call doesn't need to pay createTable cost.\n */\n async createRepo(meta: Repository): Promise<void> {\n const { connection, signer } = this.cfg;\n const writes = await repoLayer.createRepo(connection, signer, meta);\n await commitLayer.ensureCommitTable(connection, signer, meta.name);\n this.fireOnWrite(writes);\n }\n\n /**\n * Incremental commit against a scanned directory snapshot.\n *\n * input: repoName, message, scan — a `{ [path]: base64Content }` map that\n * the caller produced (Node: fs walk + base64; browser: File input).\n * output: newly written Commit\n */\n async commit(\n repoName: string,\n message: string,\n scan: Record<string, string>,\n ): Promise<Commit> {\n const { connection, signer } = this.cfg;\n const owner = signer.publicKey.toBase58();\n\n const latest = await commitLayer.readLatestCommit(commitLayer.commitTablePda(owner, repoName));\n const oldTree: FileTree = latest ? await storage.loadTree(latest.treeTxId) : {};\n\n const newTree: FileTree = {};\n for (const [path, content] of Object.entries(scan)) {\n newTree[path] = await storage.uploadBlob(\n connection,\n signer,\n path,\n content,\n oldTree,\n );\n }\n\n const treeTxId = await storage.uploadTree(connection, signer, newTree);\n\n const commit: Commit = {\n id: crypto.randomUUID(),\n message,\n treeTxId,\n parentCommitId: latest?.id,\n timestamp: Date.now(),\n author: owner,\n };\n const sig = await commitLayer.writeCommit(connection, signer, repoName, commit);\n this.fireOnWrite([{ tableHint: commitTableHint(owner, repoName), sig, row: commit }]);\n return commit;\n }\n\n /** Resolve the table hint to a PDA and forward each write to `onWrite`.\n * Wrapped in try/catch per call so a misbehaving notify can't fail the\n * whole batch — but we still surface the error so the consumer knows. */\n private fireOnWrite(writes: Array<{ tableHint: string; sig: string; row: object }>) {\n if (!this.cfg.onWrite) return;\n for (const w of writes) {\n const tablePda = chain.tablePda(w.tableHint).toBase58();\n this.cfg.onWrite({ tablePda, tableHint: w.tableHint, sig: w.sig, row: w.row });\n }\n }\n\n /**\n * Restore a commit's files into a caller-provided sink. Runtime-neutral\n * shape mirrors `commit`: the caller decides how to write bytes to disk /\n * to a File System Access API handle / anywhere else. `content` is the\n * raw base64 string — the sink decodes.\n */\n async checkout(\n repoName: string,\n commitId: string | \"latest\",\n sink: (path: string, content: string) => Promise<void>,\n ): Promise<Commit> {\n const { connection, signer } = this.cfg;\n const owner = signer.publicKey.toBase58();\n\n const pda = commitLayer.commitTablePda(owner, repoName);\n let target: Commit | null;\n if (commitId === \"latest\") {\n target = await commitLayer.readLatestCommit(pda);\n } else {\n const history = await commitLayer.readCommitHistory(pda);\n target = history.find((c) => c.id === commitId) ?? null;\n }\n if (!target) {\n throw new Error(`commit not found: ${commitId} in ${owner}/${repoName}`);\n }\n\n const tree = await storage.loadTree(target.treeTxId);\n for (const [path, entry] of Object.entries(tree)) {\n const content = await storage.loadBlob(entry.txId);\n await sink(path, content);\n }\n return target;\n }\n\n /**\n * Whole-repo snapshot download — convenience on top of checkout(\"latest\")\n * but reading from someone else's `owner`. We do not require signer to\n * equal owner for reads.\n */\n async clone(\n repoName: string,\n owner: string,\n sink: (path: string, content: string) => Promise<void>,\n ): Promise<Commit> {\n const target = await commitLayer.readLatestCommit(commitLayer.commitTablePda(owner, repoName));\n if (!target) {\n throw new Error(`no commits in ${owner}/${repoName}`);\n }\n const tree = await storage.loadTree(target.treeTxId);\n for (const [path, entry] of Object.entries(tree)) {\n const content = await storage.loadBlob(entry.txId);\n await sink(path, content);\n }\n return target;\n }\n\n /** Commit history for a repo. */\n async log(\n owner: string,\n repoName: string,\n options?: { limit?: number; before?: string },\n ): Promise<Commit[]> {\n return commitLayer.readCommitHistory(commitLayer.commitTablePda(owner, repoName), options);\n }\n\n /**\n * Compare a current directory snapshot to the latest commit's tree.\n */\n async status(\n owner: string,\n repoName: string,\n scan: Record<string, string>,\n ): Promise<{ added: string[]; modified: string[]; unchanged: string[] }> {\n const latest = await commitLayer.readLatestCommit(commitLayer.commitTablePda(owner, repoName));\n const tree: FileTree = latest ? await storage.loadTree(latest.treeTxId) : {};\n\n const added: string[] = [];\n const modified: string[] = [];\n const unchanged: string[] = [];\n for (const [path, content] of Object.entries(scan)) {\n const prior = tree[path];\n if (!prior) {\n added.push(path);\n continue;\n }\n const hash = await sha256Hex(content);\n (prior.hash === hash ? unchanged : modified).push(path);\n }\n return { added, modified, unchanged };\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@iqlabs-official/git-sdk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.10",
|
|
4
4
|
"description": "Embed on-chain Git into your Solana dApp. Browser SDK for letting users browse, create, and commit to repositories from your website, with a Node entry for tooling.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"solana",
|
|
@@ -43,12 +43,12 @@
|
|
|
43
43
|
},
|
|
44
44
|
"peerDependencies": {
|
|
45
45
|
"@solana/web3.js": "^1.98.0",
|
|
46
|
-
"@iqlabs-official/solana-sdk": "^0.1.
|
|
46
|
+
"@iqlabs-official/solana-sdk": "^0.1.26",
|
|
47
47
|
"buffer": "^6.0.3"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@solana/web3.js": "^1.98.0",
|
|
51
|
-
"@iqlabs-official/solana-sdk": "^0.1.
|
|
51
|
+
"@iqlabs-official/solana-sdk": "^0.1.26",
|
|
52
52
|
"@types/node": "^20.0.0",
|
|
53
53
|
"buffer": "^6.0.3",
|
|
54
54
|
"eslint": "^9.0.0",
|