@catalyst-cloud/sdk 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -92,6 +92,8 @@ export declare function toWsOrigin(baseUrl: string): string;
92
92
  * is ever appended (the type system + this single construction point make a browser token leak
93
93
  * impossible). Token is ordered FIRST so a truncated log line still reveals the account.
94
94
  */
95
+ /** Strip trailing "/" without a backtracking regex (ReDoS-safe vs `/\/+$/`, CodeQL js/polynomial-redos). */
96
+ export declare function stripTrailingSlashes(s: string): string;
95
97
  export declare function buildConnectUrl(opts: {
96
98
  baseUrl: string;
97
99
  connectPath: string;
@@ -1 +1 @@
1
- {"version":3,"file":"live-sync-client.d.ts","sourceRoot":"","sources":["../src/live-sync-client.ts"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EAAE,WAAW,EAAe,WAAW,EAAa,MAAM,YAAY,CAAC;AAEnF;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5C,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,OAAO,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC;IACvC,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE;QAAE,IAAI,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC;IACpD,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,OAAO,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC;IACxC,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,OAAO,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC;CACzC;AAED,qGAAqG;AACrG,MAAM,MAAM,gBAAgB,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,aAAa,CAAC;AAE9D;;;;;;;;;GASG;AACH,MAAM,MAAM,YAAY,GAAG;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAC;AAEjF,gFAAgF;AAChF,MAAM,MAAM,cAAc,GACtB,YAAY,GACZ,MAAM,GACN,cAAc,GACd,WAAW,GACX,OAAO,GACP,SAAS,CAAC;AAEd,6BAA6B;AAC7B,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAEjD,kDAAkD;AAClD,MAAM,WAAW,qBAAqB;IACpC;;;;OAIG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB,iFAAiF;IACjF,SAAS,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wFAAwF;IACxF,IAAI,EAAE,YAAY,CAAC;IACnB;;;;;OAKG;IACH,MAAM,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IAC9B;;;;OAIG;IACH,SAAS,EAAE,MAAM,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAC3C;;;;OAIG;IACH,QAAQ,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;IACvC,iGAAiG;IACjG,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;IACvC,wEAAwE;IACxE,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,cAAc,KAAK,IAAI,CAAC;IAC5C,kGAAkG;IAClG,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uDAAuD;IACvD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kGAAkG;IAClG,SAAS,CAAC,EAAE,gBAAgB,CAAC;IAC7B,uDAAuD;IACvD,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;CAC/D;AAaD,wGAAwG;AACxG,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAElD;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,YAAY,CAAC;CACpB,GAAG,MAAM,CAMT;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAe;IACpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAwB;IAC/C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAkC;IAC5D,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA+B;IACxD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAA+B;IACxD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAmC;IAC7D,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAmB;IAC7C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAA4C;IAEhE,OAAO,CAAC,EAAE,CAA8B;IACxC,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,cAAc,CAA8C;IACpE,OAAO,CAAC,WAAW,CAA6B;gBAEpC,IAAI,EAAE,qBAAqB;IAoBvC;;;;;OAKG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAa5B,oGAAoG;IACpG,IAAI,IAAI,IAAI;IAaZ,8FAA8F;IAC9F,UAAU,IAAI,MAAM;IASpB,OAAO,CAAC,SAAS;IAQjB,OAAO,CAAC,UAAU;IAwClB,+FAA+F;IAC/F,OAAO,CAAC,WAAW;IAenB,OAAO,CAAC,iBAAiB;IAUzB,qEAAqE;IACrE,OAAO,CAAC,QAAQ;YAUF,WAAW;IAmBzB;;;;;OAKG;YACW,YAAY;CAe3B;AAED,0GAA0G;AAC1G,wBAAgB,UAAU,CAAC,IAAI,EAAE,OAAO,GAAG,WAAW,GAAG,IAAI,CAmB5D"}
1
+ {"version":3,"file":"live-sync-client.d.ts","sourceRoot":"","sources":["../src/live-sync-client.ts"],"names":[],"mappings":"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"}
@@ -40,8 +40,15 @@ export function toWsOrigin(baseUrl) {
40
40
  * is ever appended (the type system + this single construction point make a browser token leak
41
41
  * impossible). Token is ordered FIRST so a truncated log line still reveals the account.
42
42
  */
43
+ /** Strip trailing "/" without a backtracking regex (ReDoS-safe vs `/\/+$/`, CodeQL js/polynomial-redos). */
44
+ export function stripTrailingSlashes(s) {
45
+ let end = s.length;
46
+ while (end > 0 && s.charCodeAt(end - 1) === 47 /* "/" */)
47
+ end--;
48
+ return end === s.length ? s : s.slice(0, end);
49
+ }
43
50
  export function buildConnectUrl(opts) {
44
- const origin = toWsOrigin(opts.baseUrl.replace(/\/+$/, ""));
51
+ const origin = toWsOrigin(stripTrailingSlashes(opts.baseUrl));
45
52
  const params = new URLSearchParams();
46
53
  if (opts.auth.kind === "token")
47
54
  params.set("token", opts.auth.token);
@@ -69,7 +76,7 @@ export class LiveSyncClient {
69
76
  reconnectTimer = null;
70
77
  resolveDone = null;
71
78
  constructor(opts) {
72
- this.baseUrl = opts.baseUrl.replace(/\/+$/, "");
79
+ this.baseUrl = stripTrailingSlashes(opts.baseUrl);
73
80
  this.accountId = opts.accountId;
74
81
  this.connectPath = opts.connectPath ?? "/connect";
75
82
  this.auth = opts.auth;
@@ -1 +1 @@
1
- {"version":3,"file":"live-sync-client.js","sourceRoot":"","sources":["../src/live-sync-client.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,EAAE;AACF,+FAA+F;AAC/F,kGAAkG;AAClG,mGAAmG;AACnG,sGAAsG;AACtG,qGAAqG;AACrG,sCAAsC;AACtC,EAAE;AACF,oGAAoG;AACpG,mFAAmF;AACnF,EAAE;AACF,oGAAoG;AACpG,sGAAsG;AACtG,uGAAuG;AACvG,sGAAsG;AACtG,wFAAwF;AACxF,gGAAgG;AAChG,wEAAwE;AACxE,8FAA8F;AAC9F,kGAAkG;AAClG,8CAA8C;AAC9C,EAAE;AACF,oGAAoG;AACpG,wFAAwF;AA+FxF,gFAAgF;AAChF,SAAS,gBAAgB,CAAC,GAAW;IACnC,MAAM,IAAI,GAAI,UAA+D,CAAC,SAAS,CAAC;IACxF,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CACb,sFAAsF,CACvF,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC;AACvB,CAAC;AAED,wGAAwG;AACxG,MAAM,UAAU,UAAU,CAAC,OAAe;IACxC,OAAO,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;AACzC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,IAK/B;IACC,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC;IAC5D,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;IACrC,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,OAAO;QAAE,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrE,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;IACtC,OAAO,GAAG,MAAM,GAAG,IAAI,CAAC,WAAW,IAAI,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC;AAC7D,CAAC;AAED,MAAM,OAAO,cAAc;IACR,OAAO,CAAS;IAChB,SAAS,CAAS;IAClB,WAAW,CAAS;IACpB,IAAI,CAAe;IACnB,MAAM,CAAwB;IAC9B,SAAS,CAAkC;IAC3C,QAAQ,CAA+B;IACvC,OAAO,CAAgC;IACvC,QAAQ,CAAoC;IAC5C,SAAS,CAAS;IAClB,YAAY,CAAS;IACrB,SAAS,CAAmB;IAC5B,GAAG,CAA4C;IAExD,EAAE,GAAyB,IAAI,CAAC;IAChC,OAAO,GAAG,KAAK,CAAC;IAChB,SAAS,GAAG,KAAK,CAAC;IAClB,OAAO,CAAS;IAChB,cAAc,GAAyC,IAAI,CAAC;IAC5D,WAAW,GAAwB,IAAI,CAAC;IAEhD,YAAY,IAA2B;QACrC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAChD,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;QAChC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,IAAI,UAAU,CAAC;QAClD,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QACtB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC1B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;QAChC,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC9B,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;QAC5B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC9B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC;QACxC,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,YAAY,IAAI,MAAM,CAAC;QAChD,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,gBAAgB,CAAC;QACpD,IAAI,CAAC,GAAG;YACN,IAAI,CAAC,GAAG;gBACR,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,CACnB,OAAO,CAAC,GAAG,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,uBAAuB,GAAG,EAAE,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC;QAC3F,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC;IAChC,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,KAAK;QACT,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;QACrB,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;QAC/B,IAAI,KAAK,IAAI,IAAI,EAAE,CAAC;YAClB,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;YAC5B,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC;QACtB,CAAC;QACD,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;YACnC,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC;QAC7B,CAAC,CAAC,CAAC;IACL,CAAC;IAED,oGAAoG;IACpG,IAAI;QACF,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,IAAI,IAAI,CAAC,cAAc,IAAI,IAAI,EAAE,CAAC;YAChC,YAAY,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YAClC,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;QAC7B,CAAC;QACD,IAAI,CAAC,WAAW,EAAE,CAAC;QACnB,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;QAC1B,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC;QAC9B,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QACxB,IAAI,EAAE,EAAE,CAAC;IACX,CAAC;IAED,8FAA8F;IAC9F,UAAU;QACR,OAAO,eAAe,CAAC;YACrB,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,IAAI,EAAE,IAAI,CAAC,IAAI;SAChB,CAAC,CAAC;IACL,CAAC;IAEO,SAAS,CAAC,MAAsB;QACtC,IAAI,CAAC;YACH,IAAI,CAAC,QAAQ,EAAE,CAAC,MAAM,CAAC,CAAC;QAC1B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,wBAAwB,EAAE,GAAG,CAAC,CAAC;QAClD,CAAC;IACH,CAAC;IAEO,UAAU;QAChB,IAAI,IAAI,CAAC,OAAO;YAAE,OAAO;QACzB,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;QAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;QAChC,IAAI,EAAiB,CAAC;QACtB,IAAI,CAAC;YACH,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAC7B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,8CAA8C,EAAE,GAAG,CAAC,CAAC;YACvE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;YACxB,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACzB,OAAO;QACT,CAAC;QACD,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;QACb,EAAE,CAAC,MAAM,GAAG,GAAG,EAAE;YACf,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,4CAA4C;YAC3E,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;YACvB,IAAI,CAAC,QAAQ,EAAE,CAAC;QAClB,CAAC,CAAC;QACF,EAAE,CAAC,SAAS,GAAG,CAAC,EAAE,EAAE,EAAE;YACpB,KAAK,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;QACjC,CAAC,CAAC;QACF,EAAE,CAAC,OAAO,GAAG,GAAG,EAAE;YAChB,IAAI,IAAI,CAAC,EAAE,KAAK,EAAE;gBAAE,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC;YACnC,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS;gBAAE,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC;YACrE,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAC3B,CAAC,CAAC;QACF,EAAE,CAAC,OAAO,GAAG,CAAC,GAAG,EAAE,EAAE;YACnB,iGAAiG;YACjG,yCAAyC;YACzC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC;YAClC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;YACxB,IAAI,CAAC;gBACH,EAAE,CAAC,KAAK,EAAE,CAAC;YACb,CAAC;YAAC,MAAM,CAAC;gBACP,yBAAyB;YAC3B,CAAC;QACH,CAAC,CAAC;IACJ,CAAC;IAED,+FAA+F;IACvF,WAAW;QACjB,MAAM,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC;QACnB,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC;QACf,IAAI,CAAC,EAAE;YAAE,OAAO;QAChB,EAAE,CAAC,MAAM,GAAG,IAAI,CAAC;QACjB,EAAE,CAAC,SAAS,GAAG,IAAI,CAAC;QACpB,EAAE,CAAC,OAAO,GAAG,IAAI,CAAC;QAClB,EAAE,CAAC,OAAO,GAAG,IAAI,CAAC;QAClB,IAAI,CAAC;YACH,EAAE,CAAC,KAAK,EAAE,CAAC;QACb,CAAC;QAAC,MAAM,CAAC;YACP,iBAAiB;QACnB,CAAC;IACH,CAAC;IAEO,iBAAiB;QACvB,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,cAAc,IAAI,IAAI;YAAE,OAAO;QAC1E,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC;QAC3B,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,GAAG,CAAC,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;QAC7D,IAAI,CAAC,cAAc,GAAG,UAAU,CAAC,GAAG,EAAE;YACpC,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;YAC3B,IAAI,CAAC,UAAU,EAAE,CAAC;QACpB,CAAC,EAAE,KAAK,CAAC,CAAC;IACZ,CAAC;IAED,qEAAqE;IAC7D,QAAQ;QACd,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC;QACrC,MAAM,KAAK,GAAc,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;QACjD,IAAI,CAAC;YACH,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;QACvC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,kBAAkB,EAAE,GAAG,CAAC,CAAC;QAC7C,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,WAAW,CAAC,IAAa;QACrC,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,CAAC,KAAK;YAAE,OAAO;QACnB,IAAI,CAAC;YACH,IAAI,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC;QACxB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,uBAAuB,EAAE,GAAG,CAAC,CAAC;QACjD,CAAC;QACD,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC5B,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;YAC1B,OAAO;QACT,CAAC;QACD,IAAI,CAAC;YACH,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QACvB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,uBAAuB,KAAK,CAAC,MAAM,QAAQ,KAAK,CAAC,GAAG,EAAE,EAAE,GAAG,CAAC,CAAC;QACjF,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACK,KAAK,CAAC,YAAY;QACxB,IAAI,IAAI,CAAC,SAAS;YAAE,OAAO;QAC3B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;QAC5B,IAAI,CAAC,WAAW,EAAE,CAAC;QACnB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC;YACnC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,oBAAoB,MAAM,EAAE,CAAC,CAAC;QACjD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,+CAA+C,EAAE,GAAG,CAAC,CAAC;QAC1E,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;QACzB,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,IAAI,CAAC,UAAU,EAAE,CAAC;IACvC,CAAC;CACF;AAED,0GAA0G;AAC1G,MAAM,UAAU,UAAU,CAAC,IAAa;IACtC,MAAM,IAAI,GACR,OAAO,IAAI,KAAK,QAAQ;QACtB,CAAC,CAAC,IAAI;QACN,CAAC,CAAC,IAAI,YAAY,WAAW;YAC3B,CAAC,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC;YAChC,CAAC,CAAC,IAAI,CAAC;IACb,IAAI,IAAI,IAAI,IAAI;QAAE,OAAO,IAAI,CAAC;IAC9B,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAC/D,MAAM,IAAI,GAAI,MAA6B,CAAC,IAAI,CAAC;IACjD,IAAI,IAAI,KAAK,QAAQ;QAAE,OAAO,MAAqB,CAAC;IACpD,IAAI,IAAI,KAAK,QAAQ;QAAE,OAAO,MAAqB,CAAC;IACpD,OAAO,IAAI,CAAC;AACd,CAAC"}
1
+ {"version":3,"file":"live-sync-client.js","sourceRoot":"","sources":["../src/live-sync-client.ts"],"names":[],"mappings":"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"}
package/dist/node.d.ts ADDED
@@ -0,0 +1,8 @@
1
+ export { CatalystReplica, type CatalystReplicaOptions, type CatalystReplicaReadOnlyOptions, } from "./replica/catalyst-replica.js";
2
+ export { bunSqliteEngine, bunSqliteReadonlyEngine, nodeSqliteEngine, nodeSqliteReadonlyEngine, betterSqlite3Engine, betterSqlite3ReadonlyEngine, autoDetectEngine, autoDetectReadonlyEngine, type ReplicaEngine, type EngineFactory, type EngineBindable, type BetterSqlite3Driver, } from "./replica/engine.js";
3
+ export { claimWriterLock, type WriterGuardOptions, type WriterLockHandle, } from "./replica/writer-lock.js";
4
+ export { LiveSyncClient, type AuthStrategy, type LiveSyncStatus, type LogLevel, type WebSocketLike, type WebSocketFactory, } from "./live-sync-client.js";
5
+ export { ENTITY_NAMES, CHANGE_OPS, type AccountId, type EntityName, type ChangeOp, type ChangeFrame, } from "./types.js";
6
+ export type { SqlExecutor, SqlValue, IssueView, IssueDetailView, PullView, ProjectView, ProjectDetailView, InitiativeView, InitiativeDetailView, } from "@catalyst-cloud/read-model";
7
+ export { mirrorSchema, type MirrorEntityName } from "@catalyst-cloud/schema";
8
+ //# sourceMappingURL=node.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"AAWA,OAAO,EACL,eAAe,EACf,KAAK,sBAAsB,EAC3B,KAAK,8BAA8B,GACpC,MAAM,+BAA+B,CAAC;AAEvC,OAAO,EACL,eAAe,EACf,uBAAuB,EACvB,gBAAgB,EAChB,wBAAwB,EACxB,mBAAmB,EACnB,2BAA2B,EAC3B,gBAAgB,EAChB,wBAAwB,EACxB,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,mBAAmB,GACzB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,eAAe,EACf,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,GACtB,MAAM,0BAA0B,CAAC;AAGlC,OAAO,EACL,cAAc,EACd,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,QAAQ,EACb,KAAK,aAAa,EAClB,KAAK,gBAAgB,GACtB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,YAAY,EACZ,UAAU,EACV,KAAK,SAAS,EACd,KAAK,UAAU,EACf,KAAK,QAAQ,EACb,KAAK,WAAW,GACjB,MAAM,YAAY,CAAC;AAGpB,YAAY,EACV,WAAW,EACX,QAAQ,EACR,SAAS,EACT,eAAe,EACf,QAAQ,EACR,WAAW,EACX,iBAAiB,EACjB,cAAc,EACd,oBAAoB,GACrB,MAAM,4BAA4B,CAAC;AAMpC,OAAO,EAAE,YAAY,EAAE,KAAK,gBAAgB,EAAE,MAAM,wBAAwB,CAAC"}
package/dist/node.js ADDED
@@ -0,0 +1,22 @@
1
+ // @catalyst-cloud/sdk/node — the managed replica for node/bun (CTC-113).
2
+ //
3
+ // `CatalystReplica` is host-sync's writer + read seam behind ONE import: open + migrate a local
4
+ // SQLite replica, stream-seed /snapshot, subscribe to the live change feed (the SDK's LiveSyncClient),
5
+ // and serve the @catalyst-cloud/read-model `build*View` queries SYNCHRONOUSLY over it. Composed from
6
+ // the published @catalyst-cloud/{schema,read-model,replicate} packages; the sqlite driver is INJECTED
7
+ // (default auto-detect: bun:sqlite, else node:sqlite) so the SDK never hard-deps one.
8
+ //
9
+ // The root entrypoint ("@catalyst-cloud/sdk") stays the transport-only, isomorphic surface; this
10
+ // subpath adds the replica. Import this only from a node/bun backend.
11
+ export { CatalystReplica, } from "./replica/catalyst-replica.js";
12
+ export { bunSqliteEngine, bunSqliteReadonlyEngine, nodeSqliteEngine, nodeSqliteReadonlyEngine, betterSqlite3Engine, betterSqlite3ReadonlyEngine, autoDetectEngine, autoDetectReadonlyEngine, } from "./replica/engine.js";
13
+ export { claimWriterLock, } from "./replica/writer-lock.js";
14
+ // Re-export the transport surface so a consumer can stay on one import.
15
+ export { LiveSyncClient, } from "./live-sync-client.js";
16
+ export { ENTITY_NAMES, CHANGE_OPS, } from "./types.js";
17
+ // Re-export the Drizzle table schema so the `.handle` ad-hoc escape hatch is a one-liner — the
18
+ // read-model `build*View` results stay the primary read surface; this is for custom typed queries:
19
+ // import { drizzle } from "drizzle-orm/bun-sqlite";
20
+ // const db = drizzle(replica.handle as Database, { schema: mirrorSchema });
21
+ export { mirrorSchema } from "@catalyst-cloud/schema";
22
+ //# sourceMappingURL=node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node.js","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,EAAE;AACF,gGAAgG;AAChG,uGAAuG;AACvG,qGAAqG;AACrG,sGAAsG;AACtG,sFAAsF;AACtF,EAAE;AACF,iGAAiG;AACjG,sEAAsE;AAEtE,OAAO,EACL,eAAe,GAGhB,MAAM,+BAA+B,CAAC;AAEvC,OAAO,EACL,eAAe,EACf,uBAAuB,EACvB,gBAAgB,EAChB,wBAAwB,EACxB,mBAAmB,EACnB,2BAA2B,EAC3B,gBAAgB,EAChB,wBAAwB,GAKzB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,eAAe,GAGhB,MAAM,0BAA0B,CAAC;AAElC,wEAAwE;AACxE,OAAO,EACL,cAAc,GAMf,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,YAAY,EACZ,UAAU,GAKX,MAAM,YAAY,CAAC;AAepB,+FAA+F;AAC/F,mGAAmG;AACnG,sDAAsD;AACtD,8EAA8E;AAC9E,OAAO,EAAE,YAAY,EAAyB,MAAM,wBAAwB,CAAC"}
@@ -0,0 +1,153 @@
1
+ import { type SqlExecutor, type IssueView, type IssueDetailView, type PullView, type ProjectView, type ProjectDetailView, type InitiativeView, type InitiativeDetailView } from "@catalyst-cloud/read-model";
2
+ import { type AuthStrategy, type LiveSyncStatus, type LogLevel, type WebSocketFactory } from "../live-sync-client.js";
3
+ import { type EngineFactory, type ReplicaEngine } from "./engine.js";
4
+ import { type WriterGuardOptions } from "./writer-lock.js";
5
+ export interface CatalystReplicaOptions {
6
+ /** http(s) origin incl. any path prefix (…/api/v1); the scheme is swapped to ws(s) for /connect. */
7
+ baseUrl: string;
8
+ /** Tenant id = mirror name → `?account=` on every feed request. */
9
+ account: string;
10
+ /** How to authorize: {kind:'token',token} (host bearer rides /connect as ?token= and /snapshot as
11
+ * Authorization) | {kind:'cookie'} (same-origin session cookie). */
12
+ auth: AuthStrategy;
13
+ /** File path or ':memory:'. */
14
+ dbPath: string;
15
+ /** INJECTED sqlite engine, or a factory over dbPath. Default = auto-detect (bun:sqlite, else node:sqlite). */
16
+ engine?: ReplicaEngine | EngineFactory;
17
+ /** The connect route. Default '/connect'. */
18
+ connectPath?: string;
19
+ /** Snapshot/changes fetch. Default global fetch. */
20
+ fetchImpl?: typeof fetch;
21
+ /** Fired after each applied delta (live frame OR a completed seed) — a refetch hook. */
22
+ onChange?: () => void;
23
+ /** Connection lifecycle, for UI/logging. */
24
+ onStatus?: (status: LiveSyncStatus) => void;
25
+ /** Base reconnect backoff in ms. Default 1000. */
26
+ backoffMs?: number;
27
+ /** Reconnect backoff ceiling in ms. Default 30_000. */
28
+ maxBackoffMs?: number;
29
+ /** Injectable WebSocket factory (tests). Defaults to the runtime global WebSocket. */
30
+ wsFactory?: WebSocketFactory;
31
+ /** Optional structured logger; defaults to console. */
32
+ log?: (level: LogLevel, msg: string, extra?: unknown) => void;
33
+ /**
34
+ * Single-writer guard (a sidecar `dbPath + '.writer.lock'`). On `start()` the writer best-effort
35
+ * claims sole ownership of the file; a second LIVE writer on the same path makes `start()` throw a
36
+ * clear error (single-writer/many-reader, ADR-0008). Advisory, not a hard OS lock; a no-op for
37
+ * `:memory:`. Default: enabled. Set `{ disabled: true }` to skip, `{ override: true }` to steal.
38
+ */
39
+ writerGuard?: WriterGuardOptions;
40
+ }
41
+ /**
42
+ * Options for a READ-ONLY reader ({@link CatalystReplica.openReadOnly}). A reader needs only the file
43
+ * path (+ optional injected engine / logger): no `baseUrl`, `account`, or `auth`, because it opens NO
44
+ * socket and pulls NO snapshot.
45
+ */
46
+ export interface CatalystReplicaReadOnlyOptions {
47
+ /** File path to an EXISTING writer-seeded replica. `:memory:` makes no sense for a reader (a fresh,
48
+ * empty, per-connection DB) and is rejected. */
49
+ dbPath: string;
50
+ /** INJECTED read-only sqlite engine or a factory over dbPath. Default = auto-detect READ-ONLY
51
+ * (bun:sqlite/node:sqlite opened `{ readonly: true }`). Pass a writable engine at your own risk. */
52
+ engine?: ReplicaEngine | EngineFactory;
53
+ /** Optional structured logger; defaults to console. */
54
+ log?: (level: LogLevel, msg: string, extra?: unknown) => void;
55
+ }
56
+ export declare class CatalystReplica {
57
+ private readonly opts;
58
+ private readonly baseUrl;
59
+ private readonly fetchImpl;
60
+ private readonly log;
61
+ private engine;
62
+ private writeDb;
63
+ private sqlExecutor;
64
+ private client;
65
+ /** In-memory high-water of the last seq persisted, so each frame avoids re-reading the cursor row. */
66
+ private highWater;
67
+ private _status;
68
+ private started;
69
+ private closed;
70
+ /** READ-ONLY mode (opened via {@link CatalystReplica.openReadOnly}): no migrations, no seed, no
71
+ * socket; `start()` is a no-op and the write path is unreachable. */
72
+ private readonlyMode;
73
+ /** The claimed single-writer lock (writers only; null for readers / `:memory:` / disabled). */
74
+ private writerLock;
75
+ /** Resolved on the first 'live' status (start() = caught-up + ready to read); rejected on close /
76
+ * an initial seed failure. */
77
+ private liveResolve;
78
+ private liveReject;
79
+ constructor(opts: CatalystReplicaOptions);
80
+ /**
81
+ * Open a CatalystReplica as a READ-ONLY READER over a file another process owns as the WRITER
82
+ * (single-writer/many-reader, ADR-0008). The sqlite handle is opened read-only (`{ readonly: true }`
83
+ * + `busy_timeout`), so the reader runs NO migrations, pulls NO /snapshot, opens NO LiveSyncClient,
84
+ * and the write path is unreachable — it only serves the synchronous `build*View` reads, `.sql`,
85
+ * `.handle`, and `.cursor` off whatever the writer has already persisted. There is no live tailing:
86
+ * the reader sees the file's committed state at read time (a fresh `issues()` re-queries, so it
87
+ * reflects the writer's latest committed rows).
88
+ *
89
+ * Async because the default engine dynamic-imports its sqlite driver; once it resolves the replica
90
+ * is already open, so `start()` on the returned reader is a no-op.
91
+ */
92
+ static openReadOnly(opts: CatalystReplicaReadOnlyOptions): Promise<CatalystReplica>;
93
+ /**
94
+ * Open + migrate the replica, then open the live socket. Resolves when the replica is caught-up and
95
+ * ready to read (first 'live'); background sync continues until close(). A cold tenant stream-seeds
96
+ * /snapshot first (via the injected reseed inside LiveSyncClient.start), so 'live' implies
97
+ * seed-complete. NOTE: there is no built-in timeout — a stalled /snapshot or unreachable host can
98
+ * delay 'live'; drive progress via onStatus.
99
+ */
100
+ start(): Promise<void>;
101
+ /** Stop the socket, release the writer lock, close the DB. Idempotent. Rejects a still-pending
102
+ * start(). On a reader: no socket/lock to release — just closes the read-only handle. */
103
+ close(): Promise<void>;
104
+ /** The read-model SqlExecutor over the replica. `buildIssuesView(replica.sql, …)` is unchanged. */
105
+ get sql(): SqlExecutor;
106
+ issues(opts?: {
107
+ limit?: number;
108
+ offset?: number;
109
+ }): IssueView[];
110
+ issue(identifier: string): IssueDetailView | null;
111
+ pulls(opts?: {
112
+ limit?: number;
113
+ offset?: number;
114
+ }): PullView[];
115
+ projects(opts?: {
116
+ limit?: number;
117
+ offset?: number;
118
+ }): ProjectView[];
119
+ project(id: string): ProjectDetailView | null;
120
+ initiatives(opts?: {
121
+ limit?: number;
122
+ offset?: number;
123
+ }): InitiativeView[];
124
+ initiative(id: string): InitiativeDetailView | null;
125
+ /** The durable change-feed cursor (sync_meta), or null before the first seed. */
126
+ get cursor(): number | null;
127
+ /** The connection lifecycle status. */
128
+ get status(): LiveSyncStatus;
129
+ /** The raw driver Database the SDK owns — for `drizzle(replica.handle, { schema: mirrorSchema })`. */
130
+ get handle(): unknown;
131
+ private resolveEngine;
132
+ /**
133
+ * Open the read-only engine and wire ONLY the read ports — no migrations, no `sync_meta` DDL, no
134
+ * snapshot, no LiveSyncClient. The write-facing `writeDb` is a read-capable shim whose `run` throws,
135
+ * so reads (`sql`/`build*View`/`cursor`) work but any accidental write path is unreachable AND the
136
+ * underlying sqlite handle is itself read-only.
137
+ */
138
+ private openReadOnlyInternal;
139
+ private handleStatus;
140
+ private clearLiveDeferred;
141
+ /** Land one delta + advance the durable cursor atomically (a crash can't skip a seq), then signal. */
142
+ private applyFrame;
143
+ /**
144
+ * Stream-seed the replica from /snapshot and return the fresh cursor. Streams `response.body` as
145
+ * NDJSON (chunked, batched transactions) so a large tenant never materializes the whole snapshot in
146
+ * memory — the OOM fix vs host-sync's buffered seed. The cursor row is DELETED up front so an
147
+ * interrupted seed self-heals (getCursor → null → re-seed on the next start), preserving host-sync's
148
+ * atomic truncate+apply+setCursor safety without holding one giant transaction.
149
+ */
150
+ private seedFromSnapshot;
151
+ private feedHeaders;
152
+ }
153
+ //# sourceMappingURL=catalyst-replica.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalyst-replica.d.ts","sourceRoot":"","sources":["../../src/replica/catalyst-replica.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,409 @@
1
+ // @catalyst-cloud/sdk/node — CatalystReplica: host-sync's writer + read seam behind ONE import.
2
+ //
3
+ // Composed from the published @catalyst-cloud/{schema,read-model,replicate} packages + the SDK's own
4
+ // LiveSyncClient. It is the drop-in replacement for the hand-rolled writer loop in apps/host-sync
5
+ // (apply.ts + sync-client.ts + live-client.ts + read-adapter.ts), now engine-generic:
6
+ //
7
+ // start() = open DB (injected engine, default bun:sqlite/node:sqlite auto-detect)
8
+ // → applyMigrations(MIRROR_MIGRATIONS) + sync_meta DDL
9
+ // → open LiveSyncClient: if cursor==null it STREAM-seeds /snapshot (the injected reseed),
10
+ // then replays {type:"sync", after:cursor}, applyDelta + cursor per frame; {type:"resync"}
11
+ // re-seeds. RESOLVES WHEN FIRST 'live' (caught-up + ready to read); background sync
12
+ // continues until close(). This is the deliberate fork from the raw transport's
13
+ // resolve-on-stop.
14
+ // reads = SYNCHRONOUS over the read-model SqlExecutor (node/bun sqlite is sync). The
15
+ // `buildIssuesView(replica.sql, …)` calls are LITERALLY unchanged.
16
+ //
17
+ // Reads, writes, migrations, cursor and wire semantics are byte-identical to host-sync because this
18
+ // runs the SAME @catalyst-cloud/read-model builders over the SAME @catalyst-cloud/replicate write path
19
+ // and the SAME @catalyst-cloud/schema MIRROR_MIGRATIONS.
20
+ import { applyMigrations, MIRROR_MIGRATIONS } from "@catalyst-cloud/schema";
21
+ import { applyDelta, truncateReplica, getCursor, setCursor, } from "@catalyst-cloud/replicate";
22
+ import { buildIssuesView, buildIssueDetail, buildPullsView, buildProjectsView, buildProjectDetail, buildInitiativesView, buildInitiativeDetail, } from "@catalyst-cloud/read-model";
23
+ import { LiveSyncClient, stripTrailingSlashes, } from "../live-sync-client.js";
24
+ import { autoDetectEngine, autoDetectReadonlyEngine, } from "./engine.js";
25
+ import { claimWriterLock, } from "./writer-lock.js";
26
+ /** Host-sync bookkeeping table (NOT part of the DO mirror schema, so not in MIRROR_MIGRATIONS): the
27
+ * change-feed cursor, so a restart resumes from the live `{type:"sync", after}` replay (or /changes)
28
+ * instead of a full /snapshot every boot. */
29
+ const SYNC_META_DDL = `CREATE TABLE IF NOT EXISTS sync_meta (
30
+ key TEXT PRIMARY KEY, value TEXT
31
+ );`;
32
+ /** Rows per streamed seed transaction — bounds memory + fsync so a large tenant never OOMs the node/bun
33
+ * process the way host-sync's buffered `await res.text()` + `split("\n")` snapshot would. */
34
+ const SEED_BATCH_ROWS = 1000;
35
+ export class CatalystReplica {
36
+ opts;
37
+ baseUrl;
38
+ fetchImpl;
39
+ log;
40
+ engine = null;
41
+ writeDb = null;
42
+ sqlExecutor = null;
43
+ client = null;
44
+ /** In-memory high-water of the last seq persisted, so each frame avoids re-reading the cursor row. */
45
+ highWater = 0;
46
+ _status = "connecting";
47
+ started = false;
48
+ closed = false;
49
+ /** READ-ONLY mode (opened via {@link CatalystReplica.openReadOnly}): no migrations, no seed, no
50
+ * socket; `start()` is a no-op and the write path is unreachable. */
51
+ readonlyMode = false;
52
+ /** The claimed single-writer lock (writers only; null for readers / `:memory:` / disabled). */
53
+ writerLock = null;
54
+ /** Resolved on the first 'live' status (start() = caught-up + ready to read); rejected on close /
55
+ * an initial seed failure. */
56
+ liveResolve = null;
57
+ liveReject = null;
58
+ constructor(opts) {
59
+ this.opts = opts;
60
+ this.baseUrl = stripTrailingSlashes(opts.baseUrl);
61
+ this.fetchImpl = opts.fetchImpl ?? fetch;
62
+ this.log =
63
+ opts.log ??
64
+ ((lvl, msg, extra) => console[lvl === "error" ? "error" : "log"](`[catalyst-replica] ${msg}`, extra ?? ""));
65
+ }
66
+ /**
67
+ * Open a CatalystReplica as a READ-ONLY READER over a file another process owns as the WRITER
68
+ * (single-writer/many-reader, ADR-0008). The sqlite handle is opened read-only (`{ readonly: true }`
69
+ * + `busy_timeout`), so the reader runs NO migrations, pulls NO /snapshot, opens NO LiveSyncClient,
70
+ * and the write path is unreachable — it only serves the synchronous `build*View` reads, `.sql`,
71
+ * `.handle`, and `.cursor` off whatever the writer has already persisted. There is no live tailing:
72
+ * the reader sees the file's committed state at read time (a fresh `issues()` re-queries, so it
73
+ * reflects the writer's latest committed rows).
74
+ *
75
+ * Async because the default engine dynamic-imports its sqlite driver; once it resolves the replica
76
+ * is already open, so `start()` on the returned reader is a no-op.
77
+ */
78
+ static async openReadOnly(opts) {
79
+ if (!opts.dbPath || opts.dbPath === ":memory:" || opts.dbPath.startsWith("file::memory:")) {
80
+ throw new Error("CatalystReplica.openReadOnly: a reader needs a FILE path to a writer-seeded replica; " +
81
+ "':memory:' is a fresh per-connection DB with nothing to read.");
82
+ }
83
+ // Reuse the writer constructor with placeholders for the connect-only fields (never touched in
84
+ // read-only mode), then open the read-only engine eagerly.
85
+ const replica = new CatalystReplica({
86
+ baseUrl: "readonly://local",
87
+ account: "",
88
+ auth: { kind: "cookie" },
89
+ dbPath: opts.dbPath,
90
+ engine: opts.engine,
91
+ log: opts.log,
92
+ });
93
+ await replica.openReadOnlyInternal(opts);
94
+ return replica;
95
+ }
96
+ /**
97
+ * Open + migrate the replica, then open the live socket. Resolves when the replica is caught-up and
98
+ * ready to read (first 'live'); background sync continues until close(). A cold tenant stream-seeds
99
+ * /snapshot first (via the injected reseed inside LiveSyncClient.start), so 'live' implies
100
+ * seed-complete. NOTE: there is no built-in timeout — a stalled /snapshot or unreachable host can
101
+ * delay 'live'; drive progress via onStatus.
102
+ */
103
+ async start() {
104
+ // A reader is already open (openReadOnly opened the engine); start() is an inert no-op.
105
+ if (this.readonlyMode)
106
+ return;
107
+ if (this.closed)
108
+ throw new Error("CatalystReplica: start() after close()");
109
+ if (this.started)
110
+ throw new Error("CatalystReplica: start() already called");
111
+ this.started = true;
112
+ // Single-writer guard: claim sole ownership of the file BEFORE opening it, so a second concurrent
113
+ // writer rejects here instead of racing the cursor/seed. A no-op for ':memory:' or when disabled.
114
+ this.writerLock = claimWriterLock(this.opts.dbPath, this.opts.writerGuard ?? {}, this.log);
115
+ const engine = await this.resolveEngine();
116
+ this.engine = engine;
117
+ this.writeDb = {
118
+ run: (sql, ...bindings) => engine.run(sql, ...bindings),
119
+ get: (sql, ...bindings) => engine.get(sql, ...bindings),
120
+ };
121
+ this.sqlExecutor = {
122
+ exec: (query, ...bindings) => ({
123
+ toArray: () => engine.all(query, ...bindings.map(engine.toBindable)),
124
+ }),
125
+ };
126
+ // Migrate via the ~3-line MigrationDb adapter, then add the host-only cursor table.
127
+ const migrationDb = {
128
+ exec: (sql) => engine.exec(sql),
129
+ query: (sql) => engine.all(sql),
130
+ };
131
+ applyMigrations(migrationDb, MIRROR_MIGRATIONS);
132
+ engine.exec(SYNC_META_DDL);
133
+ this.highWater = getCursor(this.writeDb) ?? 0;
134
+ this.client = new LiveSyncClient({
135
+ baseUrl: this.baseUrl,
136
+ accountId: this.opts.account,
137
+ connectPath: this.opts.connectPath,
138
+ auth: this.opts.auth,
139
+ reseed: () => this.seedFromSnapshot(),
140
+ getCursor: () => getCursor(this.writeDb),
141
+ onChange: (frame) => this.applyFrame(frame),
142
+ onStatus: (status) => this.handleStatus(status),
143
+ backoffMs: this.opts.backoffMs,
144
+ maxBackoffMs: this.opts.maxBackoffMs,
145
+ wsFactory: this.opts.wsFactory,
146
+ log: this.log,
147
+ });
148
+ return new Promise((resolve, reject) => {
149
+ this.liveResolve = resolve;
150
+ this.liveReject = reject;
151
+ // The transport's start() resolves only on stop() ("runs forever"); we fork on first 'live'.
152
+ // Run it in the background and surface an initial seed/connect failure as a start() rejection.
153
+ void this.client.start().catch((err) => {
154
+ const rej = this.liveReject;
155
+ this.clearLiveDeferred();
156
+ rej?.(err);
157
+ });
158
+ });
159
+ }
160
+ /** Stop the socket, release the writer lock, close the DB. Idempotent. Rejects a still-pending
161
+ * start(). On a reader: no socket/lock to release — just closes the read-only handle. */
162
+ async close() {
163
+ if (this.closed)
164
+ return;
165
+ this.closed = true;
166
+ this.client?.stop();
167
+ const rej = this.liveReject;
168
+ this.clearLiveDeferred();
169
+ rej?.(new Error("CatalystReplica: closed before first 'live'"));
170
+ try {
171
+ this.writerLock?.release();
172
+ }
173
+ catch (err) {
174
+ this.log("warn", "writer-lock release threw", err);
175
+ }
176
+ this.writerLock = null;
177
+ try {
178
+ this.engine?.close();
179
+ }
180
+ catch (err) {
181
+ this.log("warn", "engine close threw", err);
182
+ }
183
+ }
184
+ // ── Reads ───────────────────────────────────────────────────────────────────────────────────────
185
+ /** The read-model SqlExecutor over the replica. `buildIssuesView(replica.sql, …)` is unchanged. */
186
+ get sql() {
187
+ if (!this.sqlExecutor)
188
+ throw new Error("CatalystReplica: call start() before reading");
189
+ return this.sqlExecutor;
190
+ }
191
+ issues(opts) {
192
+ return buildIssuesView(this.sql, opts?.limit, opts?.offset);
193
+ }
194
+ issue(identifier) {
195
+ return buildIssueDetail(this.sql, identifier);
196
+ }
197
+ pulls(opts) {
198
+ return buildPullsView(this.sql, opts?.limit, opts?.offset);
199
+ }
200
+ projects(opts) {
201
+ return buildProjectsView(this.sql, opts?.limit, opts?.offset);
202
+ }
203
+ project(id) {
204
+ return buildProjectDetail(this.sql, id);
205
+ }
206
+ initiatives(opts) {
207
+ return buildInitiativesView(this.sql, opts?.limit, opts?.offset);
208
+ }
209
+ initiative(id) {
210
+ return buildInitiativeDetail(this.sql, id);
211
+ }
212
+ /** The durable change-feed cursor (sync_meta), or null before the first seed. */
213
+ get cursor() {
214
+ return this.writeDb ? getCursor(this.writeDb) : null;
215
+ }
216
+ /** The connection lifecycle status. */
217
+ get status() {
218
+ return this._status;
219
+ }
220
+ /** The raw driver Database the SDK owns — for `drizzle(replica.handle, { schema: mirrorSchema })`. */
221
+ get handle() {
222
+ return this.engine?.handle;
223
+ }
224
+ // ── Internals ─────────────────────────────────────────────────────────────────────────────────
225
+ async resolveEngine() {
226
+ const e = this.opts.engine;
227
+ if (e === undefined)
228
+ return autoDetectEngine(this.opts.dbPath);
229
+ if (typeof e === "function")
230
+ return e(this.opts.dbPath);
231
+ return e;
232
+ }
233
+ /**
234
+ * Open the read-only engine and wire ONLY the read ports — no migrations, no `sync_meta` DDL, no
235
+ * snapshot, no LiveSyncClient. The write-facing `writeDb` is a read-capable shim whose `run` throws,
236
+ * so reads (`sql`/`build*View`/`cursor`) work but any accidental write path is unreachable AND the
237
+ * underlying sqlite handle is itself read-only.
238
+ */
239
+ async openReadOnlyInternal(opts) {
240
+ this.readonlyMode = true;
241
+ this.started = true; // already open → start() is a no-op
242
+ const e = opts.engine;
243
+ const engine = e === undefined
244
+ ? await autoDetectReadonlyEngine(opts.dbPath)
245
+ : typeof e === "function"
246
+ ? await e(opts.dbPath)
247
+ : e;
248
+ this.engine = engine;
249
+ this.sqlExecutor = {
250
+ exec: (query, ...bindings) => ({
251
+ toArray: () => engine.all(query, ...bindings.map(engine.toBindable)),
252
+ }),
253
+ };
254
+ // Read-capable cursor access; `run` is poisoned so the write path can never fire on a reader.
255
+ this.writeDb = {
256
+ get: (sql, ...bindings) => engine.get(sql, ...bindings),
257
+ run: () => {
258
+ throw new Error("CatalystReplica: this replica is READ-ONLY (opened via openReadOnly)");
259
+ },
260
+ };
261
+ this._status = "live"; // a reader is "live" the moment it is open (it has no socket)
262
+ }
263
+ handleStatus(status) {
264
+ this._status = status;
265
+ if (status === "live" && this.liveResolve) {
266
+ const res = this.liveResolve;
267
+ this.clearLiveDeferred();
268
+ res();
269
+ }
270
+ try {
271
+ this.opts.onStatus?.(status);
272
+ }
273
+ catch (err) {
274
+ this.log("warn", "onStatus handler threw", err);
275
+ }
276
+ }
277
+ clearLiveDeferred() {
278
+ this.liveResolve = null;
279
+ this.liveReject = null;
280
+ }
281
+ /** Land one delta + advance the durable cursor atomically (a crash can't skip a seq), then signal. */
282
+ applyFrame(frame) {
283
+ const engine = this.engine;
284
+ const writeDb = this.writeDb;
285
+ if (!engine || !writeDb)
286
+ return;
287
+ try {
288
+ engine.transaction(() => {
289
+ applyDelta(writeDb, { entity: frame.entity, op: frame.op, row: frame.row ?? {}, entityId: frame.entityId }, engine.toBindable);
290
+ // Advance to the seq we SAW (not just applied), so a stale-but-newer-seq delta still moves the
291
+ // cursor forward and a reconnect doesn't re-request it.
292
+ if (frame.seq > this.highWater)
293
+ setCursor(writeDb, frame.seq, engine.toBindable);
294
+ });
295
+ if (frame.seq > this.highWater)
296
+ this.highWater = frame.seq;
297
+ try {
298
+ this.opts.onChange?.();
299
+ }
300
+ catch (err) {
301
+ this.log("warn", "onChange handler threw", err);
302
+ }
303
+ }
304
+ catch (err) {
305
+ this.log("error", `apply failed for ${frame.entity} seq=${frame.seq}`, err);
306
+ }
307
+ }
308
+ /**
309
+ * Stream-seed the replica from /snapshot and return the fresh cursor. Streams `response.body` as
310
+ * NDJSON (chunked, batched transactions) so a large tenant never materializes the whole snapshot in
311
+ * memory — the OOM fix vs host-sync's buffered seed. The cursor row is DELETED up front so an
312
+ * interrupted seed self-heals (getCursor → null → re-seed on the next start), preserving host-sync's
313
+ * atomic truncate+apply+setCursor safety without holding one giant transaction.
314
+ */
315
+ async seedFromSnapshot() {
316
+ const engine = this.engine;
317
+ const writeDb = this.writeDb;
318
+ const url = `${this.baseUrl}/snapshot?account=${encodeURIComponent(this.opts.account)}`;
319
+ const res = await this.fetchImpl(url, { headers: this.feedHeaders() });
320
+ if (!res.ok)
321
+ throw new Error(`/snapshot ${res.status}`);
322
+ // Invalidate the cursor BEFORE truncating so a crash mid-seed re-seeds rather than going live over
323
+ // an empty replica from a stale cursor.
324
+ engine.run("DELETE FROM sync_meta WHERE key = 'cursor'");
325
+ engine.transaction(() => truncateReplica(writeDb));
326
+ let cursor = 0;
327
+ let batch = [];
328
+ const flush = () => {
329
+ if (batch.length === 0)
330
+ return;
331
+ const rows = batch;
332
+ batch = [];
333
+ engine.transaction(() => {
334
+ for (const rec of rows) {
335
+ if (rec.entity === undefined)
336
+ continue;
337
+ applyDelta(writeDb, { entity: rec.entity, op: rec.op ?? "upsert", row: rec.row ?? {} }, engine.toBindable);
338
+ }
339
+ });
340
+ };
341
+ let rowCount = 0;
342
+ for await (const line of iterateNdjson(res)) {
343
+ const rec = JSON.parse(line);
344
+ if (typeof rec.cursor === "number") {
345
+ cursor = rec.cursor; // the FINAL line carries the cursor
346
+ continue;
347
+ }
348
+ batch.push(rec);
349
+ rowCount++;
350
+ if (batch.length >= SEED_BATCH_ROWS)
351
+ flush();
352
+ }
353
+ flush();
354
+ engine.transaction(() => setCursor(writeDb, cursor, engine.toBindable));
355
+ this.highWater = cursor;
356
+ this.log("info", `snapshot seeded (${rowCount} rows), cursor=${cursor}`);
357
+ try {
358
+ this.opts.onChange?.();
359
+ }
360
+ catch (err) {
361
+ this.log("warn", "onChange handler threw", err);
362
+ }
363
+ return cursor;
364
+ }
365
+ feedHeaders() {
366
+ const h = { accept: "application/x-ndjson" };
367
+ if (this.opts.auth.kind === "token")
368
+ h["authorization"] = `Bearer ${this.opts.auth.token}`;
369
+ return h;
370
+ }
371
+ }
372
+ /**
373
+ * Iterate an NDJSON Response as non-empty lines. Streams `response.body` (chunked + partial-line
374
+ * buffered) when present — the production path that never buffers the whole snapshot; falls back to a
375
+ * buffered `await res.text()` when the body is absent (e.g. a test fetch stand-in).
376
+ */
377
+ async function* iterateNdjson(res) {
378
+ const body = res.body;
379
+ if (body && typeof body.getReader === "function") {
380
+ const reader = body.getReader();
381
+ const decoder = new TextDecoder();
382
+ let buf = "";
383
+ for (;;) {
384
+ const { done, value } = await reader.read();
385
+ if (done)
386
+ break;
387
+ buf += decoder.decode(value, { stream: true });
388
+ let nl;
389
+ while ((nl = buf.indexOf("\n")) >= 0) {
390
+ const line = buf.slice(0, nl);
391
+ buf = buf.slice(nl + 1);
392
+ if (line.length > 0)
393
+ yield line;
394
+ }
395
+ }
396
+ buf += decoder.decode();
397
+ if (buf.length > 0) {
398
+ for (const line of buf.split("\n"))
399
+ if (line.length > 0)
400
+ yield line;
401
+ }
402
+ return;
403
+ }
404
+ const text = await res.text();
405
+ for (const line of text.split("\n"))
406
+ if (line.length > 0)
407
+ yield line;
408
+ }
409
+ //# sourceMappingURL=catalyst-replica.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalyst-replica.js","sourceRoot":"","sources":["../../src/replica/catalyst-replica.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,67 @@
1
+ /** A bindable SQLite scalar on the node/bun side (booleans stored as 0/1 INTEGER; blobs as Uint8Array). */
2
+ export type EngineBindable = string | number | bigint | null | Uint8Array;
3
+ /**
4
+ * The portable sqlite engine the SDK owns and adapts. Generic over the bindable type `B` so a driver
5
+ * that binds binary/bigint differently can declare its own; the node/bun builtins use `EngineBindable`.
6
+ */
7
+ export interface ReplicaEngine<B = unknown> {
8
+ /** Execute DDL / migration statement(s) for side effect (no rows). */
9
+ exec(sql: string): void;
10
+ /** Run a parameterized SELECT → rows as plain objects (reads + the migration ledger). */
11
+ all(sql: string, ...bindings: B[]): Record<string, B>[];
12
+ /** Run a parameterized mutation → sqlite3_changes() (rows written). */
13
+ run(sql: string, ...bindings: B[]): number;
14
+ /** Run a single-row query → the first row, or undefined. */
15
+ get(sql: string, ...bindings: B[]): Record<string, B> | undefined;
16
+ /** Run `fn` inside one atomic transaction (snapshot-seed batch / delta apply). */
17
+ transaction<T>(fn: () => T): T;
18
+ /** Coerce ONE wire JSON value to an engine-bindable scalar (bool → 0/1, blob/bigint per engine). */
19
+ toBindable: (value: unknown) => B;
20
+ /** Close the underlying database handle. */
21
+ close(): void;
22
+ }
23
+ /** A factory that opens a `ReplicaEngine` over `dbPath`. May be async (drivers are dynamic-imported). */
24
+ export type EngineFactory = (dbPath: string) => ReplicaEngine | Promise<ReplicaEngine>;
25
+ /** A `ReplicaEngine` plus the raw driver `handle` (exposed via CatalystReplica.handle for drizzle). */
26
+ export type ReplicaEngineWithHandle = ReplicaEngine<EngineBindable> & {
27
+ readonly handle: unknown;
28
+ };
29
+ export declare function bunSqliteEngine(dbPath: string): Promise<ReplicaEngineWithHandle>;
30
+ /** Read-only `bun:sqlite` engine (`{ readonly: true }` + `busy_timeout`). See {@link openBun}. */
31
+ export declare function bunSqliteReadonlyEngine(dbPath: string): Promise<ReplicaEngineWithHandle>;
32
+ export declare function nodeSqliteEngine(dbPath: string): Promise<ReplicaEngineWithHandle>;
33
+ /** Read-only `node:sqlite` engine (`{ readOnly: true }` + `busy_timeout`). See {@link openNode}. */
34
+ export declare function nodeSqliteReadonlyEngine(dbPath: string): Promise<ReplicaEngineWithHandle>;
35
+ /** A statement handle the `better-sqlite3` default export hands back (typed structurally — no import). */
36
+ interface BetterSqlite3Statement {
37
+ all(...bindings: unknown[]): unknown[];
38
+ get(...bindings: unknown[]): unknown;
39
+ run(...bindings: unknown[]): {
40
+ changes: number | bigint;
41
+ lastInsertRowid: number | bigint;
42
+ };
43
+ }
44
+ /** The `better-sqlite3` Database surface this engine uses (typed structurally — no import / no peer pin). */
45
+ interface BetterSqlite3Database {
46
+ prepare(sql: string): BetterSqlite3Statement;
47
+ exec(sql: string): void;
48
+ pragma(source: string): unknown;
49
+ transaction<Args extends unknown[], R>(fn: (...args: Args) => R): (...args: Args) => R;
50
+ close(): void;
51
+ }
52
+ /** `import Database from "better-sqlite3"` is structurally assignable to this constructor type. */
53
+ export type BetterSqlite3Driver = new (path?: string, options?: unknown) => BetterSqlite3Database;
54
+ export declare function betterSqlite3Engine(driver: BetterSqlite3Driver, dbPath: string): ReplicaEngineWithHandle;
55
+ /** Read-only `better-sqlite3` engine (`{ readonly: true }` + `busy_timeout`). See {@link openBetter}. */
56
+ export declare function betterSqlite3ReadonlyEngine(driver: BetterSqlite3Driver, dbPath: string): ReplicaEngineWithHandle;
57
+ /**
58
+ * Auto-detect the default engine when `opts.engine` is omitted: Bun → `bunSqliteEngine`; else
59
+ * `node:sqlite` if available → `nodeSqliteEngine`; else throw a clear "pass opts.engine" error rather
60
+ * than pick an engine that resolves but breaks on first write.
61
+ */
62
+ export declare function autoDetectEngine(dbPath: string): Promise<ReplicaEngineWithHandle>;
63
+ /** READ-ONLY counterpart of {@link autoDetectEngine}: Bun → `bunSqliteReadonlyEngine`; else
64
+ * `nodeSqliteReadonlyEngine`. Used by `CatalystReplica.openReadOnly` when no engine is injected. */
65
+ export declare function autoDetectReadonlyEngine(dbPath: string): Promise<ReplicaEngineWithHandle>;
66
+ export {};
67
+ //# sourceMappingURL=engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/replica/engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,216 @@
1
+ // @catalyst-cloud/sdk/node — the portable sqlite ENGINE seam + the injected driver factories.
2
+ //
3
+ // CatalystReplica never statically imports a sqlite driver: that is how it avoids hard-depping one.
4
+ // It defines one tiny portable `ReplicaEngine` — the union of replicate's `ReplicaWriteDb` (run/get),
5
+ // read-model's `SqlExecutor` (all), and schema's `MigrationDb` (exec/query) primitives, plus a
6
+ // per-engine `toBindable` (wire JSON → engine-bindable) and `transaction`/`close`. CatalystReplica
7
+ // adapts THIS one object into the three ports it needs.
8
+ //
9
+ // Drivers are INJECTED, not imported. The SDK ships three factory adapters, each dynamic-import()ing
10
+ // its driver only when called:
11
+ // • bunSqliteEngine(dbPath) — `await import("bun:sqlite")` (runtime builtin → never in package.json)
12
+ // • nodeSqliteEngine(dbPath) — `await import("node:sqlite")` { DatabaseSync } (Node >=22.5, builtin)
13
+ // • betterSqlite3Engine(driver, …) — the consumer passes `import Database from "better-sqlite3"`
14
+ // (an OPTIONAL peer, never statically imported here).
15
+ // Any other driver (D1, sql.js, …) is supported by passing a custom `ReplicaEngine`.
16
+ // Load RUNTIME-BUILTIN drivers (`bun:sqlite` / `node:sqlite`) via `createRequire`, NOT a literal
17
+ // `import("…")`. Vite/vitest and esbuild rewrite (and break) a literal dynamic import of a builtin —
18
+ // they strip the `node:`/`bun:` prefix and fail to resolve a bare `sqlite`; and a `new Function`
19
+ // import throws "dynamic import callback was not specified" under node ESM. `require` of a builtin is
20
+ // untouched by the bundler and resolves natively on both node and Bun. This keeps the drivers OUT of
21
+ // package.json (they are platform builtins) and loaded only when a factory is called.
22
+ import { createRequire } from "node:module";
23
+ const requireBuiltin = createRequire(import.meta.url);
24
+ /** Require a RUNTIME-BUILTIN driver module; the type is supplied by the caller via `typeof import(...)`. */
25
+ function importBuiltin(specifier) {
26
+ return Promise.resolve(requireBuiltin(specifier));
27
+ }
28
+ /** Coerce a wire JSON value to a node/bun-bindable scalar. Booleans → 0/1, blobs → Uint8Array, nested
29
+ * object/array → JSON text (DO rows are flat scalars; this just keeps one odd field from wedging sync). */
30
+ function toBindable(value) {
31
+ if (value === null || value === undefined)
32
+ return null;
33
+ if (typeof value === "boolean")
34
+ return value ? 1 : 0;
35
+ if (typeof value === "string" || typeof value === "number" || typeof value === "bigint")
36
+ return value;
37
+ if (value instanceof Uint8Array)
38
+ return value;
39
+ if (value instanceof ArrayBuffer)
40
+ return new Uint8Array(value);
41
+ return JSON.stringify(value);
42
+ }
43
+ /** Fold a driver into the portable engine. `all`/`run`/`get` re-prepare per call (bounded read path,
44
+ * and applyDelta's SQL varies per row anyway, so statement caching would not help). */
45
+ function makeEngine(driver) {
46
+ return {
47
+ handle: driver.handle,
48
+ exec: (sql) => driver.exec(sql),
49
+ all: (sql, ...bindings) => driver.prepare(sql).all(...bindings),
50
+ run: (sql, ...bindings) => driver.prepare(sql).run(...bindings),
51
+ get: (sql, ...bindings) => driver.prepare(sql).get(...bindings),
52
+ transaction: (fn) => driver.transaction(fn),
53
+ toBindable,
54
+ close: () => driver.close(),
55
+ };
56
+ }
57
+ /**
58
+ * `bun:sqlite` engine. `db.query(sql)` prepares; `.run().changes` is the write count; WAL keeps
59
+ * concurrent readers non-blocking. `bun:sqlite` is a Bun runtime builtin → dynamic-imported, never a
60
+ * package.json dependency.
61
+ *
62
+ * The WRITER opens read-write + WAL. The READER (`readonly`) opens `{ readonly: true }` and sets
63
+ * `busy_timeout = 250` instead of WAL — exactly how CTL's replica-read.mjs opens the same file: under
64
+ * the single-writer/many-reader topology (ADR-0008) a checkpoint can briefly hold the lock, so a
65
+ * reader waits a beat rather than failing. A readonly handle runs NO migrations and rejects writes at
66
+ * the sqlite layer.
67
+ */
68
+ async function openBun(dbPath, readonly) {
69
+ const { Database } = await importBuiltin("bun:sqlite");
70
+ const db = readonly ? new Database(dbPath, { readonly: true }) : new Database(dbPath);
71
+ try {
72
+ db.run(readonly ? "PRAGMA busy_timeout = 250" : "PRAGMA journal_mode = WAL");
73
+ }
74
+ catch {
75
+ // :memory: rejects WAL on some builds; busy_timeout is harmless either way.
76
+ }
77
+ return makeEngine({
78
+ handle: db,
79
+ exec: (sql) => db.exec(sql),
80
+ prepare: (sql) => {
81
+ const st = db.query(sql);
82
+ return {
83
+ all: (...b) => st.all(...b),
84
+ get: (...b) => (st.get(...b) ?? undefined),
85
+ run: (...b) => st.run(...b).changes,
86
+ };
87
+ },
88
+ transaction: (fn) => db.transaction(fn)(),
89
+ close: () => db.close(),
90
+ });
91
+ }
92
+ export function bunSqliteEngine(dbPath) {
93
+ return openBun(dbPath, false);
94
+ }
95
+ /** Read-only `bun:sqlite` engine (`{ readonly: true }` + `busy_timeout`). See {@link openBun}. */
96
+ export function bunSqliteReadonlyEngine(dbPath) {
97
+ return openBun(dbPath, true);
98
+ }
99
+ /**
100
+ * `node:sqlite` engine (Node >=22.5; may need `--experimental-sqlite` on some 22.x). `DatabaseSync`
101
+ * has no `.transaction()` helper, so we wrap BEGIN/COMMIT/ROLLBACK. Also a runtime builtin → never a
102
+ * package.json dependency. The `readonly` variant opens `{ readOnly: true }` (node:sqlite's spelling)
103
+ * + `busy_timeout`; see {@link openBun} for the read-only rationale.
104
+ */
105
+ async function openNode(dbPath, readonly) {
106
+ const { DatabaseSync } = await importBuiltin("node:sqlite");
107
+ const db = readonly ? new DatabaseSync(dbPath, { readOnly: true }) : new DatabaseSync(dbPath);
108
+ try {
109
+ db.exec(readonly ? "PRAGMA busy_timeout = 250" : "PRAGMA journal_mode = WAL");
110
+ }
111
+ catch {
112
+ // :memory: cannot WAL — harmless; busy_timeout is allowed on a readonly handle.
113
+ }
114
+ return makeEngine({
115
+ handle: db,
116
+ exec: (sql) => db.exec(sql),
117
+ prepare: (sql) => {
118
+ const st = db.prepare(sql);
119
+ return {
120
+ all: (...b) => st.all(...b),
121
+ get: (...b) => (st.get(...b) ?? undefined),
122
+ run: (...b) => Number(st.run(...b).changes),
123
+ };
124
+ },
125
+ transaction: (fn) => {
126
+ db.exec("BEGIN");
127
+ try {
128
+ const out = fn();
129
+ db.exec("COMMIT");
130
+ return out;
131
+ }
132
+ catch (err) {
133
+ db.exec("ROLLBACK");
134
+ throw err;
135
+ }
136
+ },
137
+ close: () => db.close(),
138
+ });
139
+ }
140
+ export function nodeSqliteEngine(dbPath) {
141
+ return openNode(dbPath, false);
142
+ }
143
+ /** Read-only `node:sqlite` engine (`{ readOnly: true }` + `busy_timeout`). See {@link openNode}. */
144
+ export function nodeSqliteReadonlyEngine(dbPath) {
145
+ return openNode(dbPath, true);
146
+ }
147
+ /**
148
+ * `better-sqlite3` engine. The consumer passes the driver constructor (`import Database from
149
+ * "better-sqlite3"`) so the SDK never statically imports it — it stays an OPTIONAL peer the consumer's
150
+ * bundler resolves. Synchronous (the driver is already loaded), so no dynamic import here. The
151
+ * `readonly` variant opens `{ readonly: true }` + `busy_timeout`; see {@link openBun}.
152
+ */
153
+ function openBetter(driver, dbPath, readonly) {
154
+ const db = readonly ? new driver(dbPath, { readonly: true }) : new driver(dbPath);
155
+ try {
156
+ db.pragma(readonly ? "busy_timeout = 250" : "journal_mode = WAL");
157
+ }
158
+ catch {
159
+ // :memory: cannot WAL — harmless; busy_timeout is allowed on a readonly handle.
160
+ }
161
+ return makeEngine({
162
+ handle: db,
163
+ exec: (sql) => db.exec(sql),
164
+ prepare: (sql) => {
165
+ const st = db.prepare(sql);
166
+ return {
167
+ all: (...b) => st.all(...b),
168
+ get: (...b) => (st.get(...b) ?? undefined),
169
+ run: (...b) => Number(st.run(...b).changes),
170
+ };
171
+ },
172
+ transaction: (fn) => db.transaction(fn)(),
173
+ close: () => db.close(),
174
+ });
175
+ }
176
+ export function betterSqlite3Engine(driver, dbPath) {
177
+ return openBetter(driver, dbPath, false);
178
+ }
179
+ /** Read-only `better-sqlite3` engine (`{ readonly: true }` + `busy_timeout`). See {@link openBetter}. */
180
+ export function betterSqlite3ReadonlyEngine(driver, dbPath) {
181
+ return openBetter(driver, dbPath, true);
182
+ }
183
+ /**
184
+ * Auto-detect the default engine when `opts.engine` is omitted: Bun → `bunSqliteEngine`; else
185
+ * `node:sqlite` if available → `nodeSqliteEngine`; else throw a clear "pass opts.engine" error rather
186
+ * than pick an engine that resolves but breaks on first write.
187
+ */
188
+ export async function autoDetectEngine(dbPath) {
189
+ if (typeof globalThis.Bun !== "undefined") {
190
+ return bunSqliteEngine(dbPath);
191
+ }
192
+ try {
193
+ return await nodeSqliteEngine(dbPath);
194
+ }
195
+ catch (err) {
196
+ throw new Error("CatalystReplica: no sqlite engine available — pass opts.engine. " +
197
+ "Auto-detect needs Bun (bun:sqlite) or Node >=22.5 (node:sqlite). " +
198
+ `Underlying error: ${err instanceof Error ? err.message : String(err)}`);
199
+ }
200
+ }
201
+ /** READ-ONLY counterpart of {@link autoDetectEngine}: Bun → `bunSqliteReadonlyEngine`; else
202
+ * `nodeSqliteReadonlyEngine`. Used by `CatalystReplica.openReadOnly` when no engine is injected. */
203
+ export async function autoDetectReadonlyEngine(dbPath) {
204
+ if (typeof globalThis.Bun !== "undefined") {
205
+ return bunSqliteReadonlyEngine(dbPath);
206
+ }
207
+ try {
208
+ return await nodeSqliteReadonlyEngine(dbPath);
209
+ }
210
+ catch (err) {
211
+ throw new Error("CatalystReplica: no read-only sqlite engine available — pass opts.engine. " +
212
+ "Auto-detect needs Bun (bun:sqlite) or Node >=22.5 (node:sqlite). " +
213
+ `Underlying error: ${err instanceof Error ? err.message : String(err)}`);
214
+ }
215
+ }
216
+ //# sourceMappingURL=engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/replica/engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import type { LogLevel } from "../live-sync-client.js";
2
+ /** Config for the single-writer guard. Passed as `CatalystReplicaOptions.writerGuard`. */
3
+ export interface WriterGuardOptions {
4
+ /** Disable the guard entirely (claim nothing). Default false — the guard is ON for file replicas. */
5
+ disabled?: boolean;
6
+ /** Steal an existing LIVE lock instead of throwing (the configurable override). Default false. */
7
+ override?: boolean;
8
+ /** A lock with no heartbeat newer than this many ms is treated as abandoned + reclaimed. Default 15000. */
9
+ staleMs?: number;
10
+ /** How often the owning writer rewrites its heartbeat. Default max(1000, staleMs/3). */
11
+ heartbeatMs?: number;
12
+ }
13
+ /** A claimed writer lock. `release()` stops the heartbeat and removes the file if still ours. Idempotent. */
14
+ export interface WriterLockHandle {
15
+ /** The sidecar lock file path (`dbPath + '.writer.lock'`). */
16
+ readonly path: string;
17
+ release(): void;
18
+ }
19
+ type Logger = (level: LogLevel, msg: string, extra?: unknown) => void;
20
+ /**
21
+ * Best-effort claim sole ownership of `dbPath` for a writer. Returns a {@link WriterLockHandle} (or
22
+ * `null` when the guard is disabled or `dbPath` is in-memory). Throws a clear error when another LIVE
23
+ * writer already holds the lock and `override` is not set.
24
+ */
25
+ export declare function claimWriterLock(dbPath: string, opts: WriterGuardOptions, log?: Logger): WriterLockHandle | null;
26
+ export {};
27
+ //# sourceMappingURL=writer-lock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"writer-lock.d.ts","sourceRoot":"","sources":["../../src/replica/writer-lock.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAEvD,0FAA0F;AAC1F,MAAM,WAAW,kBAAkB;IACjC,qGAAqG;IACrG,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,kGAAkG;IAClG,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,2GAA2G;IAC3G,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wFAAwF;IACxF,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,6GAA6G;AAC7G,MAAM,WAAW,gBAAgB;IAC/B,8DAA8D;IAC9D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,OAAO,IAAI,IAAI,CAAC;CACjB;AAWD,KAAK,MAAM,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;AA4BtE;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,kBAAkB,EACxB,GAAG,CAAC,EAAE,MAAM,GACX,gBAAgB,GAAG,IAAI,CA0EzB"}
@@ -0,0 +1,125 @@
1
+ // @catalyst-cloud/sdk/node — the single-writer guard for a CatalystReplica writer (CTC-113).
2
+ //
3
+ // The managed replica is single-writer/many-reader (ADR-0008): ONE process owns the SQLite file and
4
+ // applies the change feed; everyone else opens it READ-ONLY (`CatalystReplica.openReadOnly`). Two
5
+ // concurrent WRITERS on the same file would race the cursor + truncate-and-reseed and silently
6
+ // diverge. This guard makes that mistake LOUD: when a writer `start()`s it best-effort claims sole
7
+ // ownership of `dbPath` via a sidecar lock file `dbPath + '.writer.lock'` carrying `{pid, owner,
8
+ // heartbeat}`. A second live writer on the same path throws a clear error instead of corrupting the
9
+ // replica.
10
+ //
11
+ // LIMITS — this is deliberately ADVISORY, not a hard OS lock:
12
+ // • It is cooperative: it only stops OTHER CatalystReplica writers. A raw `new Database(path)` from
13
+ // unrelated code is not blocked (use OS file locking / WAL for that).
14
+ // • Liveness has two signals. The HEARTBEAT (a timestamp rewritten on an interval) is the portable,
15
+ // cross-host signal — a lock older than `staleMs` with no heartbeat is treated as abandoned and
16
+ // reclaimed. The PID probe (`process.kill(pid,0)`) only means anything SAME-HOST; cross-host or
17
+ // when it can't probe, it conservatively assumes the holder is alive and relies on the heartbeat.
18
+ // • A hard `kill -9` can leave a stale lock until `staleMs` elapses; the next writer reclaims it.
19
+ // • `:memory:` (and `file::memory:`) replicas are per-connection, never shared, so the guard is a
20
+ // no-op for them.
21
+ import * as fs from "node:fs";
22
+ const DEFAULT_STALE_MS = 15_000;
23
+ function readLock(lockPath) {
24
+ try {
25
+ const rec = JSON.parse(fs.readFileSync(lockPath, "utf8"));
26
+ if (rec && typeof rec.pid === "number" && typeof rec.heartbeat === "number")
27
+ return rec;
28
+ return null;
29
+ }
30
+ catch {
31
+ return null; // absent, partial write, or garbage → treat as no lock
32
+ }
33
+ }
34
+ /** SAME-HOST liveness probe. Returns true when it cannot tell (assume the holder is alive — the
35
+ * heartbeat staleness check is the portable signal that ultimately reclaims a dead lock). */
36
+ function pidAlive(pid) {
37
+ const proc = globalThis.process;
38
+ if (!proc?.kill || !pid)
39
+ return true;
40
+ try {
41
+ proc.kill(pid, 0); // signal 0 = existence check, never delivered
42
+ return true;
43
+ }
44
+ catch (err) {
45
+ if (err.code === "ESRCH")
46
+ return false; // no such process
47
+ return true; // EPERM: exists but owned by another user → alive
48
+ }
49
+ }
50
+ /**
51
+ * Best-effort claim sole ownership of `dbPath` for a writer. Returns a {@link WriterLockHandle} (or
52
+ * `null` when the guard is disabled or `dbPath` is in-memory). Throws a clear error when another LIVE
53
+ * writer already holds the lock and `override` is not set.
54
+ */
55
+ export function claimWriterLock(dbPath, opts, log) {
56
+ if (opts.disabled)
57
+ return null;
58
+ if (!dbPath || dbPath === ":memory:" || dbPath.startsWith("file::memory:"))
59
+ return null;
60
+ const lockPath = `${dbPath}.writer.lock`;
61
+ const staleMs = opts.staleMs ?? DEFAULT_STALE_MS;
62
+ const heartbeatMs = opts.heartbeatMs ?? Math.max(1000, Math.floor(staleMs / 3));
63
+ const pid = globalThis.process?.pid ?? 0;
64
+ const owner = `${pid}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;
65
+ const serialize = () => JSON.stringify({ pid, owner, heartbeat: Date.now() });
66
+ const writeFresh = () => fs.writeFileSync(lockPath, serialize());
67
+ // Atomic exclusive create: wins the claim outright if no file exists.
68
+ let created = false;
69
+ try {
70
+ const fd = fs.openSync(lockPath, "wx");
71
+ fs.writeSync(fd, serialize());
72
+ fs.closeSync(fd);
73
+ created = true;
74
+ }
75
+ catch (err) {
76
+ if (err.code !== "EEXIST")
77
+ throw err;
78
+ }
79
+ if (!created) {
80
+ const existing = readLock(lockPath);
81
+ const held = existing != null && Date.now() - existing.heartbeat < staleMs && pidAlive(existing.pid);
82
+ if (held && !opts.override) {
83
+ throw new Error(`CatalystReplica: another writer owns this replica at ${dbPath} ` +
84
+ `(pid=${existing.pid}, last heartbeat ${Date.now() - existing.heartbeat}ms ago). ` +
85
+ `Only ONE writer may hold a replica file (ADR-0008 single-writer/many-reader); open it ` +
86
+ `read-only with CatalystReplica.openReadOnly() instead. Pass writerGuard:{override:true} ` +
87
+ `to take it over, or writerGuard:{disabled:true} to skip the check. NOTE: this guard is ` +
88
+ `advisory (a sidecar ${lockPath}), not a hard OS lock.`);
89
+ }
90
+ log?.("warn", held
91
+ ? `writer-lock: overriding a live writer at ${lockPath} (writerGuard.override)`
92
+ : `writer-lock: reclaiming a stale/abandoned lock at ${lockPath}`);
93
+ writeFresh();
94
+ }
95
+ // Keep the lock fresh so peers see it's alive; unref so it never holds the event loop open.
96
+ const timer = setInterval(() => {
97
+ try {
98
+ writeFresh();
99
+ }
100
+ catch (err) {
101
+ log?.("warn", "writer-lock heartbeat failed", err);
102
+ }
103
+ }, heartbeatMs);
104
+ timer.unref?.();
105
+ let released = false;
106
+ return {
107
+ path: lockPath,
108
+ release() {
109
+ if (released)
110
+ return;
111
+ released = true;
112
+ clearInterval(timer);
113
+ const cur = readLock(lockPath);
114
+ if (cur && cur.owner === owner) {
115
+ try {
116
+ fs.unlinkSync(lockPath);
117
+ }
118
+ catch {
119
+ // already gone — fine
120
+ }
121
+ }
122
+ },
123
+ };
124
+ }
125
+ //# sourceMappingURL=writer-lock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"writer-lock.js","sourceRoot":"","sources":["../../src/replica/writer-lock.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@catalyst-cloud/sdk",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "Keep a live local copy of your Linear and GitHub project data — pushed in real time, without polling rate limits or webhook tunnels.",
5
5
  "license": "MIT",
6
6
  "author": "Coalesce Labs",
@@ -24,6 +24,11 @@
24
24
  "types": "./dist/index.d.ts",
25
25
  "import": "./dist/index.js",
26
26
  "default": "./dist/index.js"
27
+ },
28
+ "./node": {
29
+ "types": "./dist/node.d.ts",
30
+ "import": "./dist/node.js",
31
+ "default": "./dist/node.js"
27
32
  }
28
33
  },
29
34
  "files": [
@@ -51,5 +56,22 @@
51
56
  "devDependencies": {
52
57
  "typescript": "^5.6.3",
53
58
  "vitest": "^2.1.8"
59
+ },
60
+ "dependencies": {
61
+ "@catalyst-cloud/read-model": "^0.1.0",
62
+ "@catalyst-cloud/replicate": "^0.1.0",
63
+ "@catalyst-cloud/schema": "^0.1.0"
64
+ },
65
+ "peerDependencies": {
66
+ "@sqlite.org/sqlite-wasm": "*",
67
+ "better-sqlite3": "*"
68
+ },
69
+ "peerDependenciesMeta": {
70
+ "better-sqlite3": {
71
+ "optional": true
72
+ },
73
+ "@sqlite.org/sqlite-wasm": {
74
+ "optional": true
75
+ }
54
76
  }
55
77
  }