mpb-localkit 1.4.15 → 1.4.16
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/cli/index.js +11 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/core/index.js +30 -0
- package/dist/core/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -121,6 +121,17 @@ auth.post('/signup', async (c) => {
|
|
|
121
121
|
return c.json({ user: { id: userId, email }, token }, 201)
|
|
122
122
|
})
|
|
123
123
|
|
|
124
|
+
auth.post('/hash', async (c) => {
|
|
125
|
+
const { email } = await c.req.json<{ email: string }>()
|
|
126
|
+
if (!email) return c.json({ error: 'email required' }, 400)
|
|
127
|
+
|
|
128
|
+
const raw = await c.env.KV.get(AUTH_KEY(email))
|
|
129
|
+
if (!raw) return c.json({ error: 'User not found' }, 404)
|
|
130
|
+
|
|
131
|
+
const user = JSON.parse(raw) as StoredUser
|
|
132
|
+
return c.json({ passwordHash: user.passwordHash })
|
|
133
|
+
})
|
|
134
|
+
|
|
124
135
|
auth.post('/signin', async (c) => {
|
|
125
136
|
const { email, passwordHash } = await c.req.json<{ email: string; passwordHash: string }>()
|
|
126
137
|
if (!email || !passwordHash) return c.json({ error: 'email and passwordHash required' }, 400)
|
package/dist/cli/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/cli/utils.ts","../../src/cli/commands/dev.ts","../../src/cli/generator/templates/index.ts","../../src/cli/generator/templates/auth.ts","../../src/cli/generator/templates/sync.ts","../../src/cli/generator/templates/ws.ts","../../src/cli/generator/templates/errors.ts","../../src/cli/generator/templates/health.ts","../../src/cli/generator/templates/r2-storage.ts","../../src/cli/generator/templates/kv-storage.ts","../../src/cli/generator/templates/wrangler.ts","../../src/cli/generator/index.ts","../../src/cli/targets/cloudflare.ts","../../src/cli/targets/node.ts","../../src/cli/commands/build.ts","../../src/cli/commands/deploy.ts","../../src/cli/commands/eject.ts","../../src/cli/index.ts"],"names":["program","join","mkdirSync","writeFileSync","resolve","existsSync","targets","require"],"mappings":";;;;;;;;AAIA,IAAM,MAAA,GAAS;AAAA,EACb,KAAA,EAAO,CAAC,CAAA,KAAc,CAAA,QAAA,EAAW,CAAC,CAAA,OAAA,CAAA;AAAA,EAClC,MAAA,EAAQ,CAAC,CAAA,KAAc,CAAA,QAAA,EAAW,CAAC,CAAA,OAAA,CAAA;AAAA,EACnC,GAAA,EAAK,CAAC,CAAA,KAAc,CAAA,QAAA,EAAW,CAAC,CAAA,OAAA,CAAA;AAAA,EAChC,IAAA,EAAM,CAAC,CAAA,KAAc,CAAA,QAAA,EAAW,CAAC,CAAA,OAAA,CAAA;AAAA,EACjC,IAAA,EAAM,CAAC,CAAA,KAAc,CAAA,OAAA,EAAU,CAAC,CAAA,OAAA,CAAA;AAAA,EAChC,GAAA,EAAK,CAAC,CAAA,KAAc,CAAA,OAAA,EAAU,CAAC,CAAA,OAAA;AACjC,CAAA;AAEO,IAAM,GAAA,GAAM;AAAA,EACjB,IAAA,EAAM,CAAC,GAAA,KAAgB,OAAA,CAAQ,GAAA,CAAI,CAAA,EAAG,MAAA,CAAO,IAAA,CAAK,QAAG,CAAC,CAAA,CAAA,EAAI,GAAG,CAAA,CAAE,CAAA;AAAA,EAC/D,OAAA,EAAS,CAAC,GAAA,KAAgB,OAAA,CAAQ,GAAA,CAAI,CAAA,EAAG,MAAA,CAAO,KAAA,CAAM,QAAG,CAAC,CAAA,CAAA,EAAI,GAAG,CAAA,CAAE,CAAA;AAAA,EACnE,IAAA,EAAM,CAAC,GAAA,KAAgB,OAAA,CAAQ,IAAA,CAAK,CAAA,EAAG,MAAA,CAAO,MAAA,CAAO,QAAG,CAAC,CAAA,CAAA,EAAI,GAAG,CAAA,CAAE,CAAA;AAAA,EAClE,KAAA,EAAO,CAAC,GAAA,KAAgB,OAAA,CAAQ,KAAA,CAAM,CAAA,EAAG,MAAA,CAAO,GAAA,CAAI,QAAG,CAAC,CAAA,CAAA,EAAI,GAAG,CAAA,CAAE,CAAA;AAAA,EACjE,IAAA,EAAM,CAAC,GAAA,KAAgB,OAAA,CAAQ,IAAI,MAAA,CAAO,IAAA,CAAK,GAAG,CAAC,CAAA;AAAA,EACnD,GAAA,EAAK,CAAC,GAAA,KAAgB,OAAA,CAAQ,IAAI,MAAA,CAAO,GAAA,CAAI,GAAG,CAAC;AACnD,CAAA;;;ACjBO,SAAS,YAAYA,QAAAA,EAAwB;AAClD,EAAAA,QAAAA,CACG,QAAQ,KAAK,CAAA,CACb,YAAY,mDAAmD,CAAA,CAC/D,OAAO,MAAM;AACZ,IAAA,OAAA,CAAQ,GAAA,CAAI,iBAAiB,CAAA,GAAI,OAAA;AACjC,IAAA,GAAA,CAAI,KAAK,mBAAmB,CAAA;AAC5B,IAAA,GAAA,CAAI,KAAK,4CAA4C,CAAA;AACrD,IAAA,GAAA,CAAI,IAAI,+CAA+C,CAAA;AAAA,EACzD,CAAC,CAAA;AACL;;;ACZO,SAAS,oBAAoB,QAAA,EAA0B;AAC5D,EAAA,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA,CAAA,CAiCP,SAAA,EAAU;AACZ;;;ACnCO,SAAS,YAAA,GAAuB;AACrC,EAAA,OAAO;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA,CAoEP,SAAA,EAAU;AACZ;;;ACtEO,SAAS,YAAA,GAAuB;AACrC,EAAA,OAAO;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA,CAAA,CA6DP,SAAA,EAAU;AACZ;;;AC/DO,SAAS,UAAA,GAAqB;AACnC,EAAA,OAAO,CAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA,CAAA,CAiIP,SAAA,EAAU;AACZ;;;ACnIO,SAAS,cAAA,GAAyB;AACvC,EAAA,OAAO;AAAA;AAAA;AAAA;;AAAA;;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA,CAAA,CAwBP,SAAA,EAAU;AACZ;;;AC1BO,SAAS,cAAA,GAAyB;AACvC,EAAA,OAAO;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA,CAAA,CAQP,SAAA,EAAU;AACZ;;;ACVO,SAAS,iBAAA,GAA4B;AAC1C,EAAA,OAAO;AAAA;AAAA;;AAAA;AAAA;AAAA,CAAA,CAMP,SAAA,EAAU;AACZ;;;ACRO,SAAS,iBAAA,GAA4B;AAC1C,EAAA,OAAO;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA,CAqBP,SAAA,EAAU;AACZ;;;ACvBO,SAAS,gBAAA,CAAiB,SAAiB,aAAA,EAAgC;AAChF,EAAA,MAAM,OAAO,OAAA,CAAQ,WAAA,EAAY,CAAE,OAAA,CAAQ,eAAe,GAAG,CAAA;AAC7D,EAAA,OAAO,WAAW,IAAI,CAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA,eAAA,EAOP,IAAI,CAAA;;AAAA;AAAA;AAAA,MAAA,EAIb,iBAAiB,8BAA8B,CAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA,CAAA;AAavD;;;ACLO,SAAS,eAAe,OAAA,EAAiC;AAC9D,EAAA,MAAM,EAAE,OAAA,EAAS,MAAA,EAAQ,aAAA,EAAc,GAAI,OAAA;AAG3C,EAAA,MAAM,IAAA,GAAO;AAAA,IACX,MAAA;AAAA,IACA,IAAA,CAAK,QAAQ,KAAK,CAAA;AAAA,IAClB,IAAA,CAAK,MAAA,EAAQ,KAAA,EAAO,QAAQ,CAAA;AAAA,IAC5B,IAAA,CAAK,MAAA,EAAQ,KAAA,EAAO,SAAS;AAAA,GAC/B;AACA,EAAA,KAAA,MAAW,OAAO,IAAA,EAAM,SAAA,CAAU,KAAK,EAAE,SAAA,EAAW,MAAM,CAAA;AAE1D,EAAA,MAAM,KAAA,GAA4B;AAAA,IAChC,CAAC,KAAK,MAAA,EAAQ,eAAe,GAAG,gBAAA,CAAiB,OAAA,EAAS,aAAa,CAAC,CAAA;AAAA,IACxE,CAAC,KAAK,MAAA,EAAQ,KAAA,EAAO,UAAU,CAAA,EAAG,mBAAA,CAA2B,CAAC,CAAA;AAAA,IAC9D,CAAC,KAAK,MAAA,EAAQ,KAAA,EAAO,UAAU,SAAS,CAAA,EAAG,cAAc,CAAA;AAAA,IACzD,CAAC,KAAK,MAAA,EAAQ,KAAA,EAAO,UAAU,SAAS,CAAA,EAAG,cAAc,CAAA;AAAA,IACzD,CAAC,KAAK,MAAA,EAAQ,KAAA,EAAO,UAAU,OAAO,CAAA,EAAG,YAAY,CAAA;AAAA,IACrD,CAAC,KAAK,MAAA,EAAQ,KAAA,EAAO,UAAU,WAAW,CAAA,EAAG,gBAAgB,CAAA;AAAA,IAC7D,CAAC,KAAK,MAAA,EAAQ,KAAA,EAAO,UAAU,WAAW,CAAA,EAAG,gBAAgB,CAAA;AAAA,IAC7D,CAAC,KAAK,MAAA,EAAQ,KAAA,EAAO,WAAW,OAAO,CAAA,EAAG,mBAAmB,CAAA;AAAA,IAC7D,CAAC,KAAK,MAAA,EAAQ,KAAA,EAAO,WAAW,OAAO,CAAA,EAAG,mBAAmB,CAAA;AAAA,IAC7D,CAAC,IAAA,CAAK,MAAA,EAAQ,cAAc,CAAA,EAAG,iBAAA,CAAkB,OAAO,CAAC,CAAA;AAAA,IACzD,CAAC,IAAA,CAAK,MAAA,EAAQ,eAAe,CAAA,EAAG,gBAAgB;AAAA,GAClD;AAEA,EAAA,KAAA,MAAW,CAAC,IAAA,EAAM,OAAO,CAAA,IAAK,KAAA,EAAO;AACnC,IAAA,aAAA,CAAc,IAAA,EAAM,SAAS,MAAM,CAAA;AAAA,EACrC;AAEA,EAAA,MAAM,SAAA,GAAY,gBACd,EAAA,GACA,oFAAA;AACJ,EAAA,OAAA,CAAQ,IAAA;AAAA,IACN,oKAAA,GAEA;AAAA,GACF;AACF;AAEA,SAAS,kBAAkB,OAAA,EAAyB;AAClD,EAAA,MAAM,OAAO,OAAA,CAAQ,WAAA,EAAY,CAAE,OAAA,CAAQ,eAAe,GAAG,CAAA;AAC7D,EAAA,OAAO,IAAA,CAAK,SAAA;AAAA,IACV;AAAA,MACE,IAAA,EAAM,GAAG,IAAI,CAAA,OAAA,CAAA;AAAA,MACb,OAAA,EAAS,OAAA;AAAA,MACT,IAAA,EAAM,QAAA;AAAA,MACN,OAAA,EAAS;AAAA,QACP,GAAA,EAAK,cAAA;AAAA,QACL,MAAA,EAAQ,iBAAA;AAAA,QACR,YAAA,EAAc;AAAA,OAChB;AAAA,MACA,YAAA,EAAc;AAAA,QACZ,IAAA,EAAM;AAAA,OACR;AAAA,MACA,eAAA,EAAiB;AAAA,QACf,2BAAA,EAA6B,QAAA;AAAA,QAC7B,UAAA,EAAY,QAAA;AAAA,QACZ,QAAA,EAAU;AAAA;AACZ,KACF;AAAA,IACA,IAAA;AAAA,IACA;AAAA,GACF;AACF;AAEA,SAAS,cAAA,GAAyB;AAChC,EAAA,OAAO,IAAA,CAAK,SAAA;AAAA,IACV;AAAA,MACE,eAAA,EAAiB;AAAA,QACf,MAAA,EAAQ,QAAA;AAAA,QACR,MAAA,EAAQ,QAAA;AAAA,QACR,gBAAA,EAAkB,SAAA;AAAA,QAClB,GAAA,EAAK,CAAC,QAAQ,CAAA;AAAA,QACd,KAAA,EAAO,CAAC,2BAA2B,CAAA;AAAA,QACnC,MAAA,EAAQ,IAAA;AAAA,QACR,YAAA,EAAc;AAAA,OAChB;AAAA,MACA,OAAA,EAAS,CAAC,UAAU;AAAA,KACtB;AAAA,IACA,IAAA;AAAA,IACA;AAAA,GACF;AACF;;;ACtGO,IAAM,gBAAA,GAAiC;AAAA,EAC5C,IAAA,EAAM,YAAA;AAAA,EACN,QAAA,CAAS,EAAE,OAAA,EAAS,MAAA,EAAQ,eAAc,EAAsE;AAC9G,IAAA,cAAA,CAAe,EAAE,OAAA,EAAS,MAAA,EAAQ,aAAA,EAAe,CAAA;AAAA,EACnD;AACF,CAAA;ACGO,IAAM,UAAA,GAA2B;AAAA,EACtC,IAAA,EAAM,MAAA;AAAA,EACN,QAAA,CAAS,EAAE,OAAA,EAAS,MAAA,EAAO,EAA8C;AACvE,IAAA,MAAM,IAAA,GAAO;AAAA,MACX,MAAA;AAAA,MACAC,IAAAA,CAAK,QAAQ,KAAK,CAAA;AAAA,MAClBA,IAAAA,CAAK,MAAA,EAAQ,KAAA,EAAO,QAAQ,CAAA;AAAA,MAC5BA,IAAAA,CAAK,MAAA,EAAQ,KAAA,EAAO,SAAS;AAAA,KAC/B;AACA,IAAA,KAAA,MAAW,GAAA,IAAO,MAAMC,SAAAA,CAAU,KAAK,EAAE,SAAA,EAAW,MAAM,CAAA;AAE1D,IAAA,MAAM,WAAA,GAAc,gBAAgB,OAAO,CAAA;AAE3C,IAAA,MAAM,KAAA,GAA4B;AAAA,MAChC,CAACD,IAAAA,CAAK,MAAA,EAAQ,KAAA,EAAO,UAAU,GAAG,WAAW,CAAA;AAAA,MAC7C,CAACA,KAAK,MAAA,EAAQ,KAAA,EAAO,UAAU,SAAS,CAAA,EAAG,cAAc,CAAA;AAAA,MACzD,CAACA,KAAK,MAAA,EAAQ,KAAA,EAAO,UAAU,SAAS,CAAA,EAAG,cAAc,CAAA;AAAA,MACzD,CAACA,KAAK,MAAA,EAAQ,KAAA,EAAO,UAAU,OAAO,CAAA,EAAG,YAAY,CAAA;AAAA,MACrD,CAACA,KAAK,MAAA,EAAQ,KAAA,EAAO,UAAU,WAAW,CAAA,EAAG,gBAAgB,CAAA;AAAA,MAC7D,CAACA,KAAK,MAAA,EAAQ,KAAA,EAAO,UAAU,WAAW,CAAA,EAAG,gBAAgB,CAAA;AAAA,MAC7D,CAACA,KAAK,MAAA,EAAQ,KAAA,EAAO,WAAW,OAAO,CAAA,EAAG,mBAAmB,CAAA;AAAA,MAC7D,CAACA,KAAK,MAAA,EAAQ,KAAA,EAAO,WAAW,OAAO,CAAA,EAAG,mBAAmB,CAAA;AAAA,MAC7D,CAACA,IAAAA,CAAK,MAAA,EAAQ,cAAc,CAAA,EAAG,eAAA,CAAgB,OAAO,CAAC,CAAA;AAAA,MACvD,CAACA,IAAAA,CAAK,MAAA,EAAQ,eAAe,CAAA,EAAG,cAAc;AAAA,KAChD;AAEA,IAAA,KAAA,MAAW,CAAC,IAAA,EAAM,OAAO,CAAA,IAAK,KAAA,EAAO;AACnC,MAAAE,aAAAA,CAAc,IAAA,EAAM,OAAA,EAAS,MAAM,CAAA;AAAA,IACrC;AAAA,EACF;AACF,CAAA;AAEA,SAAS,gBAAgB,OAAA,EAAyB;AAChD,EAAA,OAAO,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA,cAAA,EA2DO,OAAO,CAAA;;AAAA;AAAA;AAAA,CAAA;AAKvB;AAEA,SAAS,gBAAgB,OAAA,EAAyB;AAChD,EAAA,MAAM,OAAO,OAAA,CAAQ,WAAA,EAAY,CAAE,OAAA,CAAQ,eAAe,GAAG,CAAA;AAC7D,EAAA,OAAO,IAAA,CAAK,SAAA;AAAA,IACV;AAAA,MACE,IAAA,EAAM,GAAG,IAAI,CAAA,OAAA,CAAA;AAAA,MACb,OAAA,EAAS,OAAA;AAAA,MACT,IAAA,EAAM,QAAA;AAAA,MACN,OAAA,EAAS;AAAA,QACP,GAAA,EAAK,wBAAA;AAAA,QACL,KAAA,EAAO,oBAAA;AAAA,QACP,KAAA,EAAO;AAAA,OACT;AAAA,MACA,YAAA,EAAc;AAAA,QACZ,IAAA,EAAM,QAAA;AAAA,QACN,mBAAA,EAAqB,SAAA;AAAA,QACrB,eAAA,EAAiB;AAAA,OACnB;AAAA,MACA,eAAA,EAAiB;AAAA,QACf,UAAA,EAAY,QAAA;AAAA,QACZ,GAAA,EAAK,QAAA;AAAA,QACL,aAAA,EAAe;AAAA;AACjB,KACF;AAAA,IACA,IAAA;AAAA,IACA;AAAA,GACF;AACF;AAEA,SAAS,YAAA,GAAuB;AAC9B,EAAA,OAAO,IAAA,CAAK,SAAA;AAAA,IACV;AAAA,MACE,eAAA,EAAiB;AAAA,QACf,MAAA,EAAQ,QAAA;AAAA,QACR,MAAA,EAAQ,QAAA;AAAA,QACR,gBAAA,EAAkB,SAAA;AAAA,QAClB,GAAA,EAAK,CAAC,QAAQ,CAAA;AAAA,QACd,KAAA,EAAO,CAAC,MAAM,CAAA;AAAA,QACd,MAAA,EAAQ,IAAA;AAAA,QACR,YAAA,EAAc,IAAA;AAAA,QACd,MAAA,EAAQ;AAAA,OACV;AAAA,MACA,OAAA,EAAS,CAAC,UAAU;AAAA,KACtB;AAAA,IACA,IAAA;AAAA,IACA;AAAA,GACF;AACF;;;ACtJA,IAAM,OAAA,GAAU,EAAE,UAAA,EAAY,gBAAA,EAAkB,MAAM,UAAA,EAAW;AAE1D,SAAS,cAAcH,QAAAA,EAAwB;AACpD,EAAAA,QAAAA,CACG,OAAA,CAAQ,OAAO,CAAA,CACf,WAAA,CAAY,mCAAmC,CAAA,CAC/C,MAAA,CAAO,iBAAA,EAAmB,kBAAA,EAAoB,oBAAoB,CAAA,CAClE,OAAO,mBAAA,EAAqB,yBAAA,EAA2B,cAAc,CAAA,CACrE,MAAA,CAAO,uBAAA,EAAyB,qCAAqC,YAAY,CAAA,CACjF,MAAA,CAAO,OAAO,IAAA,KAAwD;AACrE,IAAA,GAAA,CAAI,KAAK,gBAAgB,CAAA;AAEzB,IAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,IAAA,CAAK,MAA8B,CAAA;AAC1D,IAAA,IAAI,CAAC,MAAA,EAAQ;AACX,MAAA,GAAA,CAAI,KAAA,CAAM,CAAA,gBAAA,EAAmB,IAAA,CAAK,MAAM,CAAA,iBAAA,EAAoB,MAAA,CAAO,IAAA,CAAK,OAAO,CAAA,CAAE,IAAA,CAAK,IAAI,CAAC,CAAA,CAAE,CAAA;AAC7F,MAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,IAChB;AAEA,IAAA,MAAM,SAASI,OAAAA,CAAQ,OAAA,CAAQ,GAAA,EAAI,EAAG,KAAK,GAAG,CAAA;AAC9C,IAAA,GAAA,CAAI,KAAK,CAAA,WAAA,EAAc,MAAA,CAAO,IAAI,CAAA,aAAA,EAAgB,MAAM,CAAA,CAAE,CAAA;AAE1D,IAAA,IAAI;AACF,MAAA,MAAA,CAAO,SAAS,EAAE,OAAA,EAAS,IAAA,CAAK,IAAA,EAAM,QAAQ,CAAA;AAC9C,MAAA,GAAA,CAAI,OAAA,CAAQ,CAAA,qBAAA,EAAwB,MAAM,CAAA,CAAE,CAAA;AAC5C,MAAA,IAAI,IAAA,CAAK,WAAW,MAAA,EAAQ;AAC1B,QAAA,GAAA,CAAI,GAAA,CAAI,CAAA,QAAA,EAAW,IAAA,CAAK,GAAG,CAAA,8BAAA,CAAgC,CAAA;AAAA,MAC7D,CAAA,MAAO;AACL,QAAA,GAAA,CAAI,GAAA,CAAI,CAAA,QAAA,EAAW,IAAA,CAAK,GAAG,CAAA,kCAAA,CAAoC,CAAA;AAAA,MACjE;AAAA,IACF,SAAS,GAAA,EAAK;AACZ,MAAA,GAAA,CAAI,KAAA,CAAM,iBAAiB,GAAA,YAAe,KAAA,GAAQ,IAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC,CAAA,CAAE,CAAA;AAC7E,MAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,IAChB;AAAA,EACF,CAAC,CAAA;AACL;ACdO,SAAS,WAAA,CACd,MACA,OAAA,EACgB;AAChB,EAAA,MAAM,MAAA,GAAS,SAAA,CAAU,UAAA,EAAY,IAAA,EAAM;AAAA,IACzC,QAAA,EAAU,MAAA;AAAA,IACV,KAAA,EAAO,CAAC,MAAA,EAAQ,MAAA,EAAQ,MAAM,CAAA;AAAA,IAC9B,GAAG;AAAA,GACJ,CAAA;AACD,EAAA,OAAO;AAAA,IACL,MAAA,EAAQ,OAAO,MAAA,IAAU,EAAA;AAAA,IACzB,MAAA,EAAQ,OAAO,MAAA,IAAU,EAAA;AAAA,IACzB,QAAQ,MAAA,CAAO;AAAA,GACjB;AACF;AAEA,SAAS,aAAA,GAA+B;AACtC,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,GAAS,SAAS,oBAAA,EAAsB;AAAA,MAC5C,QAAA,EAAU,MAAA;AAAA,MACV,KAAA,EAAO,CAAC,QAAA,EAAU,MAAA,EAAQ,QAAQ;AAAA,KACnC,CAAA;AACD,IAAA,OAAO,OAAO,IAAA,EAAK;AAAA,EACrB,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAEO,SAAS,SAAA,GAAqB;AACnC,EAAA,MAAM,MAAA,GAAS,WAAA,CAAY,CAAC,QAAQ,CAAC,CAAA;AACrC,EAAA,OAAO,OAAO,MAAA,KAAW,CAAA;AAC3B;AAEO,SAAS,eAAe,IAAA,EAAoB;AACjD,EAAA,GAAA,CAAI,IAAA,CAAK,CAAA,oBAAA,EAAuB,IAAI,CAAA,CAAE,CAAA;AACtC,EAAA,MAAM,SAAS,WAAA,CAAY,CAAC,MAAM,QAAA,EAAU,QAAA,EAAU,IAAI,CAAC,CAAA;AAC3D,EAAA,IAAI,MAAA,CAAO,WAAW,CAAA,EAAG;AACvB,IAAA,IAAI,MAAA,CAAO,MAAA,CAAO,QAAA,CAAS,gBAAgB,CAAA,EAAG;AAC5C,MAAA,GAAA,CAAI,IAAA,CAAK,CAAA,WAAA,EAAc,IAAI,CAAA,4BAAA,CAA8B,CAAA;AACzD,MAAA;AAAA,IACF;AACA,IAAA,IAAI,MAAA,CAAO,MAAA,CAAO,QAAA,CAAS,IAAI,KAAK,MAAA,CAAO,MAAA,CAAO,QAAA,CAAS,aAAa,CAAA,IAAK,MAAA,CAAO,MAAA,CAAO,QAAA,CAAS,aAAa,CAAA,EAAG;AAClH,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAA,4BAAA,EAA+B,OAAO,MAAM;AAAA,sHAAA;AAAA,OAE9C;AAAA,IACF;AACA,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,4BAAA,EAA+B,MAAA,CAAO,MAAM,CAAA,CAAE,CAAA;AAAA,EAChE;AACA,EAAA,GAAA,CAAI,OAAA,CAAQ,CAAA,WAAA,EAAc,IAAI,CAAA,SAAA,CAAW,CAAA;AAC3C;AAEO,SAAS,kBAAkB,EAAA,EAAqB;AACrD,EAAA,MAAM,SAAS,WAAA,CAAY,CAAC,MAAM,WAAA,EAAa,MAAA,EAAQ,QAAQ,CAAC,CAAA;AAChE,EAAA,IAAI,MAAA,CAAO,MAAA,KAAW,CAAA,EAAG,OAAO,KAAA;AAChC,EAAA,IAAI;AACF,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,KAAA,CAAM,MAAA,CAAO,MAAM,CAAA;AAC3C,IAAA,OAAO,WAAW,IAAA,CAAK,CAAC,EAAA,KAAO,EAAA,CAAG,OAAO,EAAE,CAAA;AAAA,EAC7C,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAEO,SAAS,kBAAkB,IAAA,EAAsB;AACtD,EAAA,GAAA,CAAI,IAAA,CAAK,CAAA,uBAAA,EAA0B,IAAI,CAAA,CAAE,CAAA;AACzC,EAAA,MAAM,SAAS,WAAA,CAAY,CAAC,MAAM,WAAA,EAAa,QAAA,EAAU,IAAI,CAAC,CAAA;AAE9D,EAAA,IAAI,MAAA,CAAO,WAAW,CAAA,EAAG;AAEvB,IAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,MAAA,CAAO,KAAA,CAAM,wBAAwB,CAAA;AAC1D,IAAA,IAAI,KAAA,EAAO;AACT,MAAA,GAAA,CAAI,QAAQ,CAAA,cAAA,EAAiB,IAAI,sBAAsB,KAAA,CAAM,CAAC,CAAC,CAAA,CAAE,CAAA;AACjE,MAAA,OAAO,MAAM,CAAC,CAAA;AAAA,IAChB;AAEA,IAAA,IAAI;AACF,MAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,MAAA,CAAO,MAAM,CAAA;AACvC,MAAA,IAAI,MAAA,CAAO,EAAA,EAAI,OAAO,MAAA,CAAO,EAAA;AAAA,IAC/B,CAAA,CAAA,MAAQ;AAAA,IAER;AAAA,EACF;AAGA,EAAA,IAAI,OAAO,MAAA,CAAO,QAAA,CAAS,gBAAgB,CAAA,IAAK,MAAA,CAAO,WAAW,CAAA,EAAG;AACnE,IAAA,GAAA,CAAI,IAAA,CAAK,CAAA,cAAA,EAAiB,IAAI,CAAA,qCAAA,CAAuC,CAAA;AACrE,IAAA,MAAM,aAAa,WAAA,CAAY,CAAC,MAAM,WAAA,EAAa,MAAA,EAAQ,QAAQ,CAAC,CAAA;AACpE,IAAA,IAAI,UAAA,CAAW,WAAW,CAAA,EAAG;AAC3B,MAAA,IAAI;AACF,QAAA,MAAM,UAAA,GAAa,IAAA,CAAK,KAAA,CAAM,UAAA,CAAW,MAAM,CAAA;AAI/C,QAAA,MAAM,QAAQ,UAAA,CAAW,IAAA,CAAK,CAAC,EAAA,KAAO,EAAA,CAAG,UAAU,IAAI,CAAA;AACvD,QAAA,IAAI,KAAA,EAAO;AACT,UAAA,GAAA,CAAI,QAAQ,CAAA,6BAAA,EAAgC,IAAI,CAAA,WAAA,EAAc,KAAA,CAAM,EAAE,CAAA,CAAE,CAAA;AACxE,UAAA,OAAO,KAAA,CAAM,EAAA;AAAA,QACf;AAAA,MACF,CAAA,CAAA,MAAQ;AACN,QAAA,GAAA,CAAI,KAAK,+DAA+D,CAAA;AAAA,MAC1E;AAEA,MAAA,MAAM,OAAA,GAAU,UAAA,CAAW,MAAA,CAAO,KAAA,CAAM,wBAAwB,CAAA;AAChE,MAAA,IAAI,OAAA,EAAS,OAAO,OAAA,CAAQ,CAAC,CAAA;AAAA,IAC/B;AAAA,EACF;AAEA,EAAA,MAAM,IAAI,KAAA;AAAA,IACR,0CAA0C,IAAI,CAAA,WAAA,EACjC,OAAO,MAAM,CAAA,UAAA,EAAa,OAAO,MAAM,CAAA;AAAA,GACtD;AACF;AAEO,SAAS,SAAA,CAAU,IAAA,EAAc,KAAA,EAAe,GAAA,EAAmB;AACxE,EAAA,GAAA,CAAI,IAAA,CAAK,CAAA,gBAAA,EAAmB,IAAI,CAAA,CAAE,CAAA;AAClC,EAAA,MAAM,MAAA,GAAS,WAAA,CAAY,CAAC,QAAA,EAAU,KAAA,EAAO,IAAI,CAAA,EAAG,EAAE,GAAA,EAAK,KAAA,EAAO,KAAA,EAAO,CAAA;AACzE,EAAA,IAAI,MAAA,CAAO,WAAW,CAAA,EAAG;AACvB,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,qBAAA,EAAwB,IAAI,CAAA,EAAA,EAAK,MAAA,CAAO,MAAM,CAAA,CAAE,CAAA;AAAA,EAClE;AACA,EAAA,GAAA,CAAI,OAAA,CAAQ,CAAA,QAAA,EAAW,IAAI,CAAA,KAAA,CAAO,CAAA;AACpC;AAEO,SAAS,gBAAgB,MAAA,EAAoC;AAClE,EAAA,MAAM,SAAA,GAAYA,OAAAA,CAAQ,MAAA,EAAQ,IAAA,EAAM,mBAAmB,CAAA;AAC3D,EAAA,IAAI,CAACC,UAAAA,CAAW,SAAS,CAAA,EAAG,OAAO,IAAA;AACnC,EAAA,IAAI;AACF,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,YAAA,CAAa,SAAA,EAAW,MAAM,CAAC,CAAA;AAAA,EACnD,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAEO,SAAS,gBAAA,CAAiB,QAAgB,KAAA,EAA0B;AACzE,EAAA,MAAM,SAAA,GAAYD,OAAAA,CAAQ,MAAA,EAAQ,IAAA,EAAM,mBAAmB,CAAA;AAC3D,EAAAF,UAAU,OAAA,CAAQ,SAAS,GAAG,EAAE,SAAA,EAAW,MAAM,CAAA;AACjD,EAAAC,aAAAA,CAAc,WAAW,IAAA,CAAK,SAAA,CAAU,OAAO,IAAA,EAAM,CAAC,GAAG,MAAM,CAAA;AACjE;AAIO,SAAS,mBAAA,CACd,OAAA,EACA,OAAA,EACA,MAAA,EACqE;AACrE,EAAA,MAAM,OAAO,OAAA,CAAQ,WAAA,EAAY,CAAE,OAAA,CAAQ,eAAe,GAAG,CAAA;AAC7D,EAAA,MAAM,YAAA,GAAe,GAAG,IAAI,CAAA,QAAA,CAAA;AAC5B,EAAA,MAAM,OAAA,GAAU,GAAG,IAAI,CAAA,GAAA,CAAA;AACvB,EAAA,MAAM,UAAA,GAAa,GAAG,IAAI,CAAA,OAAA,CAAA;AAG1B,EAAA,IAAI,MAAA,EAAQ;AACV,IAAA,GAAA,CAAI,IAAI,uDAAuD,CAAA;AAC/D,IAAA,GAAA,CAAI,GAAA,CAAI,CAAA,kCAAA,EAAqC,YAAY,CAAA,CAAE,CAAA;AAC3D,IAAA,GAAA,CAAI,GAAA,CAAI,CAAA,qCAAA,EAAwC,OAAO,CAAA,CAAE,CAAA;AACzD,IAAA,GAAA,CAAI,IAAI,gCAAgC,CAAA;AACxC,IAAA,OAAO,EAAE,aAAA,EAAe,qBAAA,EAAuB,YAAA,EAAc,UAAA,EAAW;AAAA,EAC1E;AAEA,EAAA,IAAI,CAAC,WAAU,EAAG;AAChB,IAAA,GAAA,CAAI,MAAM,oCAAoC,CAAA;AAC9C,IAAA,GAAA,CAAI,IAAI,uDAAuD,CAAA;AAC/D,IAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EAChB;AACA,EAAA,GAAA,CAAI,QAAQ,+BAA+B,CAAA;AAG3C,EAAA,cAAA,CAAe,YAAY,CAAA;AAG3B,EAAA,MAAM,aAAA,GAAgB,kBAAkB,OAAO,CAAA;AAE/C,EAAA,OAAO,EAAE,aAAA,EAAe,YAAA,EAAc,UAAA,EAAW;AACnD;AAEO,SAAS,iBAAA,CACd,OAAA,EACA,MAAA,EACA,aAAA,EACA,KACA,MAAA,EACoB;AACpB,EAAA,IAAI,MAAA,EAAQ;AACV,IAAA,GAAA,CAAI,GAAA,CAAI,CAAA,yCAAA,EAA4C,MAAM,CAAA,CAAE,CAAA;AAC5D,IAAA,GAAA,CAAI,GAAA,CAAI,CAAA,qCAAA,EAAwC,MAAM,CAAA,CAAA,CAAG,CAAA;AACzD,IAAA,GAAA,CAAI,IAAI,CAAA,oCAAA,EAAuC,GAAA,GAAM,UAAU,GAAG,CAAA,CAAA,GAAK,EAAE,CAAA,CAAE,CAAA;AAC3E,IAAA,OAAO,MAAA;AAAA,EACT;AAGA,EAAA,GAAA,CAAI,KAAK,2BAA2B,CAAA;AACpC,EAAA,gBAAA,CAAiB,QAAA,CAAS,EAAE,OAAA,EAAS,MAAA,EAAQ,eAAe,CAAA;AAC5D,EAAA,GAAA,CAAI,QAAQ,uBAAuB,CAAA;AAGnC,EAAA,GAAA,CAAI,KAAK,4BAA4B,CAAA;AACrC,EAAA,MAAM,aAAA,GAAgB,SAAA,CAAU,KAAA,EAAO,CAAC,SAAS,CAAA,EAAG;AAAA,IAClD,GAAA,EAAK,MAAA;AAAA,IACL,QAAA,EAAU,MAAA;AAAA,IACV,KAAA,EAAO,CAAC,MAAA,EAAQ,MAAA,EAAQ,MAAM;AAAA,GAC/B,CAAA;AACD,EAAA,IAAI,aAAA,CAAc,WAAW,CAAA,EAAG;AAC9B,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,oBAAA,EAAuB,aAAA,CAAc,MAAM,CAAA,CAAE,CAAA;AAAA,EAC/D;AACA,EAAA,GAAA,CAAI,QAAQ,wBAAwB,CAAA;AAGpC,EAAA,GAAA,CAAI,KAAK,4BAA4B,CAAA;AACrC,EAAA,MAAM,UAAA,GAAa,CAAC,QAAQ,CAAA;AAC5B,EAAA,IAAI,GAAA,EAAK,UAAA,CAAW,IAAA,CAAK,OAAA,EAAS,GAAG,CAAA;AAErC,EAAA,MAAM,YAAA,GAAe,SAAA,CAAU,UAAA,EAAY,UAAA,EAAY;AAAA,IACrD,GAAA,EAAK,MAAA;AAAA,IACL,QAAA,EAAU,MAAA;AAAA,IACV,KAAA,EAAO,CAAC,MAAA,EAAQ,MAAA,EAAQ,MAAM;AAAA,GAC/B,CAAA;AAED,EAAA,IAAI,YAAA,CAAa,WAAW,CAAA,EAAG;AAC7B,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,6BAAA,EAAgC,YAAA,CAAa,MAAM,CAAA,GAAA,EAAM,aAAa,MAAM,CAAA;AAAA,KAC9E;AAAA,EACF;AAGA,EAAA,MAAM,QAAA,GAAW,YAAA,CAAa,MAAA,CAAO,KAAA,CAAM,gCAAgC,CAAA;AAC3E,EAAA,MAAM,SAAA,GAAY,QAAA,GAAW,QAAA,CAAS,CAAC,CAAA,GAAI,MAAA;AAC3C,EAAA,IAAI,SAAA,EAAW;AACb,IAAA,GAAA,CAAI,OAAA,CAAQ,CAAA,aAAA,EAAgB,SAAS,CAAA,CAAE,CAAA;AAAA,EACzC,CAAA,MAAO;AACL,IAAA,GAAA,CAAI,QAAQ,wBAAwB,CAAA;AAAA,EACtC;AAEA,EAAA,OAAO,SAAA;AACT;AAIO,SAAS,eAAeH,QAAAA,EAAwB;AACrD,EAAAA,QAAAA,CACG,OAAA,CAAQ,QAAQ,CAAA,CAChB,WAAA,CAAY,uDAAuD,CAAA,CACnE,MAAA,CAAO,iBAAA,EAAmB,yBAAA,EAA2B,oBAAoB,CAAA,CACzE,MAAA,CAAO,mBAAA,EAAqB,yBAAA,EAA2B,cAAc,CAAA,CACrE,MAAA,CAAO,iBAAA,EAAmB,iDAAiD,CAAA,CAC3E,MAAA,CAAO,uBAAA,EAAyB,qCAAA,EAAuC,YAAY,CAAA,CACnF,MAAA,CAAO,WAAA,EAAa,0CAA0C,CAAA,CAC9D,MAAA;AAAA,IACC,CAAC,IAAA,KAMK;AACJ,MAAA,GAAA,CAAI,KAAK,iBAAiB,CAAA;AAE1B,MAAA,MAAM,MAAA,GAAS,KAAK,MAAA,IAAU,KAAA;AAG9B,MAAA,MAAM,SAAA,GAAYI,OAAAA,CAAQ,OAAA,CAAQ,GAAA,IAAO,QAAQ,CAAA;AACjD,MAAA,IAAIC,UAAAA,CAAW,SAAS,CAAA,EAAG;AACzB,QAAA,GAAA,CAAI,IAAA;AAAA,UACF;AAAA,SACF;AACA,QAAA,GAAA,CAAI,GAAA;AAAA,UACF;AAAA,SACF;AAAA,MACF;AAGA,MAAA,IAAI,IAAA,CAAK,WAAW,YAAA,EAAc;AAChC,QAAA,GAAA,CAAI,KAAA;AAAA,UACF,CAAA,eAAA,EAAkB,KAAK,MAAM,CAAA,wDAAA;AAAA,SAC/B;AACA,QAAA,GAAA,CAAI,GAAA;AAAA,UACF;AAAA,SACF;AACA,QAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,MAChB;AAGA,MAAA,MAAM,UAAU,aAAA,EAAc;AAC9B,MAAA,IAAI,CAAC,OAAA,EAAS;AACZ,QAAA,GAAA,CAAI,MAAM,2CAA2C,CAAA;AACrD,QAAA,GAAA,CAAI,IAAI,0CAA0C,CAAA;AAClD,QAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,MAChB;AACA,MAAA,GAAA,CAAI,OAAA,CAAQ,CAAA,SAAA,EAAY,OAAO,CAAA,CAAE,CAAA;AAEjC,MAAA,MAAM,SAASD,OAAAA,CAAQ,OAAA,CAAQ,GAAA,EAAI,EAAG,KAAK,GAAG,CAAA;AAC9C,MAAA,MAAM,UAAU,IAAA,CAAK,IAAA;AAGrB,MAAA,MAAM,aAAA,GAAgB,gBAAgB,MAAM,CAAA;AAE5C,MAAA,IAAI,aAAA;AACJ,MAAA,IAAI,YAAA;AACJ,MAAA,IAAI,UAAA;AACJ,MAAA,IAAI,aAAA,EAAe,aAAA,IAAiB,aAAA,EAAe,YAAA,EAAc;AAE/D,QAAA,GAAA,CAAI,KAAK,sDAAsD,CAAA;AAC/D,QAAA,YAAA,GAAe,aAAA,CAAc,YAAA;AAC7B,QAAA,UAAA,GAAa,aAAA,CAAc,UAAA;AAE3B,QAAA,IAAI,MAAA,EAAQ;AACV,UAAA,GAAA,CAAI,IAAI,8CAA8C,CAAA;AACtD,UAAA,aAAA,GAAgB,aAAA,CAAc,aAAA;AAAA,QAChC,CAAA,MAAA,IAAW,iBAAA,CAAkB,aAAA,CAAc,aAAa,CAAA,EAAG;AACzD,UAAA,GAAA,CAAI,QAAQ,wBAAwB,CAAA;AACpC,UAAA,aAAA,GAAgB,aAAA,CAAc,aAAA;AAAA,QAChC,CAAA,MAAO;AACL,UAAA,GAAA,CAAI,KAAK,+CAA+C,CAAA;AACxD,UAAA,MAAM,OAAO,OAAA,CAAQ,WAAA,EAAY,CAAE,OAAA,CAAQ,eAAe,GAAG,CAAA;AAC7D,UAAA,aAAA,GAAgB,iBAAA,CAAkB,CAAA,EAAG,IAAI,CAAA,GAAA,CAAK,CAAA;AAC9C,UAAA,gBAAA,CAAiB,MAAA,EAAQ;AAAA,YACvB,GAAG,aAAA;AAAA,YACH;AAAA,WACD,CAAA;AACD,UAAA,GAAA,CAAI,QAAQ,+CAA+C,CAAA;AAAA,QAC7D;AAAA,MACF,CAAA,MAAO;AAEL,QAAA,MAAM,WAAA,GAAc,mBAAA,CAAoB,OAAA,EAAS,MAAA,EAAQ,MAAM,CAAA;AAC/D,QAAA,aAAA,GAAgB,WAAA,CAAY,aAAA;AAC5B,QAAA,YAAA,GAAe,WAAA,CAAY,YAAA;AAC3B,QAAA,UAAA,GAAa,WAAA,CAAY,UAAA;AAGzB,QAAA,IAAI,CAAC,MAAA,EAAQ;AACX,UAAA,gBAAA,CAAiB,MAAA,EAAQ;AAAA,YACvB,aAAA;AAAA,YACA,YAAA;AAAA,YACA,UAAA;AAAA,YACA,YAAA,EAAc;AAAA,WACf,CAAA;AACD,UAAA,GAAA,CAAI,QAAQ,qDAAqD,CAAA;AAAA,QACnE;AAAA,MACF;AAGA,MAAA,IAAI,aAAA,KAAkB,8BAAA,IAAkC,CAAC,aAAA,EAAe;AACtE,QAAA,GAAA,CAAI,KAAA;AAAA,UACF;AAAA,SAGF;AACA,QAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,MAChB;AAEA,MAAA,MAAM,gBAAA,GAAmB,eAAe,YAAA,IAAgB,KAAA;AAGxD,MAAA,IAAI,SAAA;AACJ,MAAA,IAAI;AACF,QAAA,SAAA,GAAY,kBAAkB,OAAA,EAAS,MAAA,EAAQ,aAAA,EAAe,IAAA,CAAK,KAAK,MAAM,CAAA;AAAA,MAChF,SAAS,GAAA,EAAK;AACZ,QAAA,GAAA,CAAI,KAAA,CAAM,kBAAkB,GAAA,YAAe,KAAA,GAAQ,IAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC,CAAA,CAAE,CAAA;AAC9E,QAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,MAChB;AAEA,MAAA,IAAI,MAAA,EAAQ;AACV,QAAA,IAAI,CAAC,gBAAA,EAAkB;AACrB,UAAA,GAAA,CAAI,IAAI,oDAAoD,CAAA;AAAA,QAC9D;AACA,QAAA,GAAA,CAAI,KAAK,yCAAyC,CAAA;AAClD,QAAA;AAAA,MACF;AAGA,MAAA,IAAI,YAAA,GAAe,gBAAA;AACnB,MAAA,IAAI,CAAC,YAAA,EAAc;AACjB,QAAA,IAAI;AACF,UAAA,SAAA,CAAU,cAAc,WAAA,CAAY,EAAE,EAAE,QAAA,CAAS,KAAK,GAAG,MAAM,CAAA;AAC/D,UAAA,GAAA,CAAI,QAAQ,gBAAgB,CAAA;AAC5B,UAAA,YAAA,GAAe,IAAA;AAAA,QACjB,SAAS,GAAA,EAAK;AACZ,UAAA,GAAA,CAAI,IAAA,CAAK,6BAA6B,GAAA,YAAe,KAAA,GAAQ,IAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC,CAAA,CAAE,CAAA;AACxF,UAAA,GAAA,CAAI,IAAI,iDAAiD,CAAA;AAAA,QAC3D;AAAA,MACF;AAGA,MAAA,gBAAA,CAAiB,QAAQ,EAAE,aAAA,EAAe,cAAc,UAAA,EAAY,SAAA,EAAW,cAAc,CAAA;AAG7F,MAAA,IAAI,SAAA,EAAW;AACb,QAAA,MAAM,OAAA,GAAUA,OAAAA,CAAQ,OAAA,CAAQ,GAAA,IAAO,MAAM,CAAA;AAC7C,QAAA,IAAIC,UAAAA,CAAW,OAAO,CAAA,EAAG;AACvB,UAAA,IAAI,UAAA,GAAa,YAAA,CAAa,OAAA,EAAS,MAAM,CAAA;AAC7C,UAAA,IAAI,UAAA,CAAW,QAAA,CAAS,gBAAgB,CAAA,EAAG;AACzC,YAAA,UAAA,GAAa,UAAA,CAAW,OAAA,CAAQ,kBAAA,EAAoB,CAAA,cAAA,EAAiB,SAAS,CAAA,CAAE,CAAA;AAAA,UAClF,CAAA,MAAO;AACL,YAAA,UAAA,IAAc;AAAA,cAAA,EAAmB,SAAS;AAAA,CAAA;AAAA,UAC5C;AACA,UAAAF,aAAAA,CAAc,OAAA,EAAS,UAAA,EAAY,MAAM,CAAA;AACzC,UAAA,GAAA,CAAI,IAAA,CAAK,CAAA,gCAAA,EAAmC,SAAS,CAAA,CAAE,CAAA;AAAA,QACzD;AAAA,MACF;AAAA,IACF;AAAA,GACF;AACJ;AClaA,IAAMG,QAAAA,GAAwC;AAAA,EAC5C,UAAA,EAAY,gBAAA;AAAA,EACZ,IAAA,EAAM;AACR,CAAA;AAEO,SAAS,cAAcN,QAAAA,EAAwB;AACpD,EAAAA,QAAAA,CACG,OAAA,CAAQ,OAAO,CAAA,CACf,WAAA,CAAY,qEAAqE,CAAA,CACjF,MAAA,CAAO,iBAAA,EAAmB,mCAAA,EAAqC,QAAQ,CAAA,CACvE,OAAO,mBAAA,EAAqB,UAAA,EAAY,cAAc,CAAA,CACtD,MAAA,CAAO,uBAAA,EAAyB,oCAAoC,YAAY,CAAA,CAChF,MAAA,CAAO,CAAC,IAAA,KAAwD;AAC/D,IAAA,GAAA,CAAI,KAAK,gBAAgB,CAAA;AAEzB,IAAA,MAAM,MAAA,GAASM,QAAAA,CAAQ,IAAA,CAAK,MAAM,CAAA;AAClC,IAAA,IAAI,CAAC,MAAA,EAAQ;AACX,MAAA,GAAA,CAAI,KAAA,CAAM,CAAA,iBAAA,EAAoB,IAAA,CAAK,MAAM,CAAA,CAAA,CAAG,CAAA;AAC5C,MAAA,GAAA,CAAI,GAAA,CAAI,sBAAsB,MAAA,CAAO,IAAA,CAAKA,QAAO,CAAA,CAAE,IAAA,CAAK,IAAI,CAAC,CAAA,CAAE,CAAA;AAC/D,MAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,IAChB;AAEA,IAAA,MAAM,SAASF,OAAAA,CAAQ,OAAA,CAAQ,GAAA,EAAI,EAAG,KAAK,GAAG,CAAA;AAE9C,IAAA,IAAIC,UAAAA,CAAW,MAAM,CAAA,EAAG;AACtB,MAAA,GAAA,CAAI,KAAA,CAAM,CAAA,0BAAA,EAA6B,MAAM,CAAA,CAAE,CAAA;AAC/C,MAAA,GAAA,CAAI,IAAI,8DAA8D,CAAA;AACtE,MAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,IAChB;AAEA,IAAA,GAAA,CAAI,KAAK,CAAA,SAAA,EAAY,IAAA,CAAK,MAAM,CAAA,UAAA,EAAa,MAAM,CAAA,CAAE,CAAA;AAErD,IAAA,IAAI;AACF,MAAA,MAAA,CAAO,SAAS,EAAE,OAAA,EAAS,IAAA,CAAK,IAAA,EAAM,QAAQ,CAAA;AAC9C,MAAA,GAAA,CAAI,OAAA,CAAQ,CAAA,aAAA,EAAgB,IAAA,CAAK,GAAG,CAAA,CAAA,CAAG,CAAA;AAEvC,MAAA,IAAI,IAAA,CAAK,WAAW,MAAA,EAAQ;AAC1B,QAAA,GAAA,CAAI,IAAI,uDAAuD,CAAA;AAC/D,QAAA,GAAA,CAAI,IAAI,EAAE,CAAA;AACV,QAAA,GAAA,CAAI,IAAI,aAAa,CAAA;AACrB,QAAA,GAAA,CAAI,GAAA,CAAI,CAAA,KAAA,EAAQ,IAAA,CAAK,GAAG,CAAA,CAAE,CAAA;AAC1B,QAAA,GAAA,CAAI,IAAI,eAAe,CAAA;AACvB,QAAA,GAAA,CAAI,IAAI,eAAe,CAAA;AACvB,QAAA,GAAA,CAAI,IAAI,EAAE,CAAA;AACV,QAAA,GAAA,CAAI,IAAI,iCAAiC,CAAA;AAAA,MAC3C,CAAA,MAAO;AACL,QAAA,GAAA,CAAI,IAAI,0DAA0D,CAAA;AAClE,QAAA,GAAA,CAAI,IAAI,EAAE,CAAA;AACV,QAAA,GAAA,CAAI,IAAI,aAAa,CAAA;AACrB,QAAA,GAAA,CAAI,GAAA,CAAI,CAAA,KAAA,EAAQ,IAAA,CAAK,GAAG,CAAA,CAAE,CAAA;AAC1B,QAAA,GAAA,CAAI,IAAI,eAAe,CAAA;AACvB,QAAA,GAAA,CAAI,IAAI,mBAAmB,CAAA;AAC3B,QAAA,GAAA,CAAI,IAAI,EAAE,CAAA;AACV,QAAA,GAAA,CAAI,IAAI,+EAA+E,CAAA;AAAA,MACzF;AAAA,IACF,SAAS,GAAA,EAAK;AACZ,MAAA,GAAA,CAAI,KAAA,CAAM,iBAAiB,GAAA,YAAe,KAAA,GAAQ,IAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC,CAAA,CAAE,CAAA;AAC7E,MAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,IAChB;AAAA,EACF,CAAC,CAAA;AACL;;;AC5DA,IAAME,QAAAA,GAAU,aAAA,CAAc,MAAA,CAAA,IAAA,CAAY,GAAG,CAAA;AAC7C,IAAM,GAAA,GAAMA,SAAQ,oBAAoB,CAAA;AAExC,IAAM,OAAA,GAAU,IAAI,OAAA,EAAQ;AAE5B,OAAA,CACG,IAAA,CAAK,cAAc,CAAA,CACnB,WAAA,CAAY,GAAA,CAAI,WAAW,CAAA,CAC3B,OAAA,CAAQ,GAAA,CAAI,OAAA,EAAS,eAAA,EAAiB,2BAA2B,CAAA;AAEpE,WAAA,CAAY,OAAO,CAAA;AACnB,aAAA,CAAc,OAAO,CAAA;AACrB,cAAA,CAAe,OAAO,CAAA;AACtB,aAAA,CAAc,OAAO,CAAA;AAErB,OAAA,CAAQ,KAAA,CAAM,QAAQ,IAAI,CAAA","file":"index.js","sourcesContent":["import { existsSync } from 'node:fs'\nimport { resolve } from 'node:path'\n\n/** Color helpers for terminal output (no dependencies) */\nconst colors = {\n green: (s: string) => `\\x1b[32m${s}\\x1b[0m`,\n yellow: (s: string) => `\\x1b[33m${s}\\x1b[0m`,\n red: (s: string) => `\\x1b[31m${s}\\x1b[0m`,\n cyan: (s: string) => `\\x1b[36m${s}\\x1b[0m`,\n bold: (s: string) => `\\x1b[1m${s}\\x1b[0m`,\n dim: (s: string) => `\\x1b[2m${s}\\x1b[0m`,\n}\n\nexport const log = {\n info: (msg: string) => console.log(`${colors.cyan('ℹ')} ${msg}`),\n success: (msg: string) => console.log(`${colors.green('✓')} ${msg}`),\n warn: (msg: string) => console.warn(`${colors.yellow('⚠')} ${msg}`),\n error: (msg: string) => console.error(`${colors.red('✗')} ${msg}`),\n bold: (msg: string) => console.log(colors.bold(msg)),\n dim: (msg: string) => console.log(colors.dim(msg)),\n}\n\nconst CONFIG_CANDIDATES = [\n 'offlinekit.config.ts',\n 'offlinekit.config.js',\n 'offlinekit.schema.ts',\n 'offlinekit.schema.js',\n]\n\n/** Finds the OfflineKit config/schema file in the current working directory */\nexport function findSchemaFile(cwd = process.cwd()): string | null {\n for (const candidate of CONFIG_CANDIDATES) {\n const p = resolve(cwd, candidate)\n if (existsSync(p)) return p\n }\n return null\n}\n\n/** Dynamically imports and returns the default export from the schema file */\nexport async function loadSchema(filePath: string): Promise<unknown> {\n const mod = await import(filePath) as { default?: unknown }\n return mod.default ?? mod\n}\n","import type { Command } from 'commander'\nimport { log } from '../utils.js'\n\nexport function registerDev(program: Command): void {\n program\n .command('dev')\n .description('Start LocalKit in local-only mode (no cloud sync)')\n .action(() => {\n process.env['OFFLINEKIT_MODE'] = 'local'\n log.bold('LocalKit Dev Mode')\n log.info('Running in local-only mode (no cloud sync)')\n log.dim('All data is stored locally. Sync is disabled.')\n })\n}\n","/** Main Hono app entry point template */\nexport function workerIndexTemplate(_appName: string): string {\n return `\nimport { Hono } from 'hono'\nimport { cors } from 'hono/cors'\nimport { auth } from './routes/auth.js'\nimport { sync } from './routes/sync.js'\nimport { ws, WsSessions } from './routes/ws.js'\nimport { errors } from './routes/errors.js'\nimport { health } from './routes/health.js'\n\nexport interface Env {\n STORAGE: R2Bucket\n KV: KVNamespace\n JWT_SECRET: string\n WS_SESSIONS: DurableObjectNamespace\n}\n\nexport { WsSessions }\n\nconst app = new Hono<{ Bindings: Env }>()\n\napp.use('/*', cors({\n origin: '*',\n allowMethods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],\n allowHeaders: ['Content-Type', 'Authorization'],\n}))\n\napp.route('/auth', auth)\napp.route('/sync', sync)\napp.route('/ws', ws)\napp.route('/errors', errors)\napp.route('/health', health)\n\nexport default app\n`.trimStart()\n}\n","/** Auth routes: POST /auth/signup, /auth/signin, /auth/signout */\nexport function authTemplate(): string {\n return `\nimport { Hono } from 'hono'\nimport { sign, verify } from 'hono/jwt'\nimport type { Env } from './index.js'\nimport { AUTH_KEY, SESSION_KEY, type StoredUser } from '../storage/kv.js'\n\nexport const auth = new Hono<{ Bindings: Env }>()\n\n/** Constant-time string comparison to prevent timing side-channels */\nfunction timingSafeEqual(a: string, b: string): boolean {\n if (a.length !== b.length) return false\n const encoder = new TextEncoder()\n const bufA = encoder.encode(a)\n const bufB = encoder.encode(b)\n let result = 0\n for (let i = 0; i < bufA.length; i++) result |= bufA[i] ^ bufB[i]\n return result === 0\n}\n\n/** Extract userId from Bearer token — throws on invalid/expired */\nexport async function authMiddleware(c: any, next: () => Promise<void>) {\n const header = c.req.header('Authorization') ?? ''\n const token = header.startsWith('Bearer ') ? header.slice(7) : null\n if (!token) return c.json({ error: 'Unauthorized' }, 401)\n try {\n const payload = await verify(token, c.env.JWT_SECRET, 'HS256') as { sub: string }\n c.set('userId', payload.sub)\n } catch {\n return c.json({ error: 'Invalid token' }, 401)\n }\n return next()\n}\n\nauth.post('/signup', async (c) => {\n const { email, passwordHash } = await c.req.json<{ email: string; passwordHash: string }>()\n if (!email || !passwordHash) return c.json({ error: 'email and passwordHash required' }, 400)\n\n const existing = await c.env.KV.get(AUTH_KEY(email))\n if (existing) return c.json({ error: 'Email already registered' }, 409)\n\n const userId = crypto.randomUUID()\n const user: StoredUser = { userId, email, passwordHash }\n await c.env.KV.put(AUTH_KEY(email), JSON.stringify(user))\n\n const token = await sign({ sub: userId, email, exp: Math.floor(Date.now() / 1000) + 60 * 60 * 24 * 30 }, c.env.JWT_SECRET, 'HS256')\n return c.json({ user: { id: userId, email }, token }, 201)\n})\n\nauth.post('/signin', async (c) => {\n const { email, passwordHash } = await c.req.json<{ email: string; passwordHash: string }>()\n if (!email || !passwordHash) return c.json({ error: 'email and passwordHash required' }, 400)\n\n const raw = await c.env.KV.get(AUTH_KEY(email))\n if (!raw) return c.json({ error: 'Invalid credentials' }, 401)\n\n const user = JSON.parse(raw) as StoredUser\n if (!timingSafeEqual(user.passwordHash, passwordHash)) return c.json({ error: 'Invalid credentials' }, 401)\n\n const token = await sign({ sub: user.userId, email, exp: Math.floor(Date.now() / 1000) + 60 * 60 * 24 * 30 }, c.env.JWT_SECRET, 'HS256')\n return c.json({ user: { id: user.userId, email }, token })\n})\n\nauth.post('/signout', async (c) => {\n const header = c.req.header('Authorization') ?? ''\n const token = header.startsWith('Bearer ') ? header.slice(7) : null\n if (token) await c.env.KV.delete(SESSION_KEY(token))\n return c.json({ ok: true })\n})\n`.trimStart()\n}\n","/** Sync routes: POST /sync/push, GET /sync/pull?since= */\nexport function syncTemplate(): string {\n return `\nimport { Hono } from 'hono'\nimport type { Env } from './index.js'\nimport { authMiddleware } from './auth.js'\nimport { docKey, collectionPrefix } from '../storage/r2.js'\n\ninterface SyncDoc {\n _id: string\n _collection: string\n _updatedAt: number\n _deleted: boolean\n [key: string]: unknown\n}\n\nexport const sync = new Hono<{ Bindings: Env }>()\n\nsync.use('/*', authMiddleware)\n\nsync.post('/push', async (c) => {\n const userId = c.get('userId') as string\n const { changes } = await c.req.json<{ changes: SyncDoc[] }>()\n\n await Promise.all(\n changes.map(async (doc) => {\n const key = docKey(userId, doc._collection, doc._id)\n const existing = await c.env.STORAGE.get(key, 'json') as SyncDoc | null\n\n // LWW — only overwrite if incoming is newer\n if (!existing || doc._updatedAt >= existing._updatedAt) {\n await c.env.STORAGE.put(key, JSON.stringify(doc), {\n customMetadata: { updatedAt: String(doc._updatedAt) },\n })\n }\n }),\n )\n\n return c.json({ ok: true, received: changes.length })\n})\n\nsync.get('/pull', async (c) => {\n const userId = c.get('userId') as string\n const since = parseInt(c.req.query('since') ?? '0', 10)\n\n // Scan all collections for this user — list all objects under {userId}/\n const prefix = \\`\\${userId}/\\`\n const listed = await c.env.STORAGE.list({ prefix })\n\n const changes = await Promise.all(\n listed.objects\n .filter((obj) => {\n const ts = parseInt(obj.customMetadata?.updatedAt ?? '0', 10)\n return ts > since\n })\n .map(async (obj) => {\n const blob = await c.env.STORAGE.get(obj.key, 'json')\n return blob as SyncDoc\n }),\n )\n\n return c.json({ changes: changes.filter(Boolean) })\n})\n`.trimStart()\n}\n","/** WebSocket Durable Object handler for real-time sync */\nexport function wsTemplate(): string {\n return `import { Hono } from 'hono'\nimport { verify } from 'hono/jwt'\nimport type { Env } from './index.js'\nimport { authMiddleware } from './auth.js'\nimport { docKey } from '../storage/r2.js'\n\nexport const ws = new Hono<{ Bindings: Env }>()\n\n// Proxy WS upgrade requests to the user-scoped Durable Object\nws.get('/', authMiddleware, async (c) => {\n const userId = c.get('userId') as string\n const id = c.env.WS_SESSIONS.idFromName(userId)\n return c.env.WS_SESSIONS.get(id).fetch(c.req.raw)\n})\n\n// ---- Durable Object: one instance per userId, owns all WebSocket sessions ----\n\ninterface SyncDoc {\n _id: string\n _collection: string\n _updatedAt: number\n _deleted: boolean\n [key: string]: unknown\n}\n\ninterface WsMsg {\n type: string\n id?: string\n payload?: unknown\n since?: number\n token?: string\n}\n\nexport class WsSessions {\n private readonly sessions = new Map<WebSocket, { userId: string | null }>()\n\n constructor(\n private readonly state: DurableObjectState,\n private readonly env: Env,\n ) {}\n\n async fetch(request: Request): Promise<Response> {\n if (request.headers.get('Upgrade') !== 'websocket') {\n return new Response('Expected WebSocket upgrade', { status: 426 })\n }\n\n const pair = new WebSocketPair()\n const [client, server] = Object.values(pair) as [WebSocket, WebSocket]\n server.accept()\n\n const session = { userId: null as string | null }\n this.sessions.set(server, session)\n\n server.addEventListener('message', async (event) => {\n let msg: WsMsg\n try { msg = JSON.parse(event.data as string) as WsMsg } catch { return }\n try {\n await this.handle(server, session, msg)\n } catch (err) {\n server.send(JSON.stringify({ type: 'error', id: msg.id, payload: { message: String(err) } }))\n }\n })\n\n server.addEventListener('close', () => { this.sessions.delete(server) })\n\n return new Response(null, { status: 101, webSocket: client })\n }\n\n private async handle(ws: WebSocket, session: { userId: string | null }, msg: WsMsg): Promise<void> {\n if (msg.type === 'auth') {\n try {\n const payload = await verify(msg.token ?? '', this.env.JWT_SECRET, 'HS256') as { sub?: string }\n if (!payload.sub) throw new Error('Missing sub')\n session.userId = payload.sub\n ws.send(JSON.stringify({ type: 'auth_ack', id: msg.id }))\n } catch {\n ws.send(JSON.stringify({ type: 'error', id: msg.id, payload: { message: 'Unauthorized' } }))\n ws.close(1008, 'Unauthorized')\n }\n return\n }\n\n if (!session.userId) {\n ws.send(JSON.stringify({ type: 'error', id: msg.id, payload: { message: 'Not authenticated' } }))\n return\n }\n\n if (msg.type === 'push') {\n const { changes } = msg.payload as { changes: SyncDoc[] }\n await Promise.all(changes.map(async (doc) => {\n const key = docKey(session.userId!, doc._collection, doc._id)\n const existing = await this.env.STORAGE.get(key, 'json') as SyncDoc | null\n if (!existing || doc._updatedAt >= existing._updatedAt) {\n await this.env.STORAGE.put(key, JSON.stringify(doc), {\n customMetadata: { updatedAt: String(doc._updatedAt) },\n })\n }\n }))\n ws.send(JSON.stringify({ type: 'push_ack', id: msg.id, payload: { ok: true } }))\n this.broadcast(session.userId, ws, { type: 'remote_changes', changes })\n return\n }\n\n if (msg.type === 'pull') {\n const since = typeof msg.since === 'number' ? msg.since : 0\n const listed = await this.env.STORAGE.list({ prefix: \\`\\${session.userId}/\\` })\n const changes = (await Promise.all(\n listed.objects\n .filter((o) => parseInt(o.customMetadata?.updatedAt ?? '0', 10) > since)\n .map((o) => this.env.STORAGE.get(o.key, 'json') as Promise<SyncDoc>),\n )).filter(Boolean)\n ws.send(JSON.stringify({ type: 'pull_response', id: msg.id, payload: { changes } }))\n return\n }\n\n ws.send(JSON.stringify({ type: 'error', id: msg.id, payload: { message: \\`Unknown type: \\${msg.type}\\` } }))\n }\n\n private broadcast(userId: string, sender: WebSocket, msg: object): void {\n const data = JSON.stringify(msg)\n for (const [ws, s] of this.sessions) {\n if (ws !== sender && s.userId === userId) {\n try { ws.send(data) } catch { /* stale connection */ }\n }\n }\n }\n}\n\n// JWT verification handled by hono/jwt verify() — no hand-rolled crypto needed\n`.trimStart()\n}\n","/** GET /errors — list error blobs for authenticated user */\nexport function errorsTemplate(): string {\n return `\nimport { Hono } from 'hono'\nimport type { Env } from './index.js'\nimport { authMiddleware } from './auth.js'\n\nexport const errors = new Hono<{ Bindings: Env }>()\n\nerrors.use('/*', authMiddleware)\n\nerrors.get('/', async (c) => {\n const userId = c.get('userId') as string\n const prefix = \\`\\${userId}/_errors/\\`\n\n const listed = await c.env.STORAGE.list({ prefix })\n const results = await Promise.all(\n listed.objects.map(async (obj) => {\n const blob = await c.env.STORAGE.get(obj.key)\n if (!blob) return null\n return blob.json()\n }),\n )\n\n return c.json({ errors: results.filter(Boolean) })\n})\n`.trimStart()\n}\n","/** GET /health — liveness check */\nexport function healthTemplate(): string {\n return `\nimport { Hono } from 'hono'\n\nexport const health = new Hono()\n\nhealth.get('/', (c) => {\n return c.json({ status: 'ok', timestamp: Date.now() })\n})\n`.trimStart()\n}\n","/** R2 document key helpers — {userId}/{collection}/{docId}.json */\nexport function r2StorageTemplate(): string {\n return `\nexport const docKey = (userId: string, collection: string, docId: string) =>\n \\`\\${userId}/\\${collection}/\\${docId}.json\\`\n\nexport const collectionPrefix = (userId: string, collection: string) =>\n \\`\\${userId}/\\${collection}/\\`\n`.trimStart()\n}\n","/** KV storage helpers — sessions, auth credentials, metadata */\nexport function kvStorageTemplate(): string {\n return `\n/** Key: auth:{email} Value: { userId, email, passwordHash } */\nexport const AUTH_KEY = (email: string) => \\`auth:\\${email}\\`\n\n/** Key: session:{token} Value: { userId, email, exp } */\nexport const SESSION_KEY = (token: string) => \\`session:\\${token}\\`\n\n/** Key: meta:{userId} Value: arbitrary metadata object */\nexport const META_KEY = (userId: string) => \\`meta:\\${userId}\\`\n\nexport interface StoredUser {\n userId: string\n email: string\n passwordHash: string\n}\n\nexport interface StoredSession {\n userId: string\n email: string\n exp: number\n}\n`.trimStart()\n}\n","/** Generate wrangler.toml for a Cloudflare Worker with R2 + KV bindings */\nexport function wranglerTemplate(appName: string, kvNamespaceId?: string): string {\n const name = appName.toLowerCase().replace(/[^a-z0-9-]/g, '-')\n return `name = \"${name}-worker\"\nmain = \"src/index.ts\"\ncompatibility_date = \"2024-01-01\"\ncompatibility_flags = [\"nodejs_compat\"]\n\n[[r2_buckets]]\nbinding = \"STORAGE\"\nbucket_name = \"${name}-storage\"\n\n[[kv_namespaces]]\nbinding = \"KV\"\nid = \"${kvNamespaceId ?? 'REPLACE_WITH_KV_NAMESPACE_ID'}\"\n\n[[durable_objects.bindings]]\nname = \"WS_SESSIONS\"\nclass_name = \"WsSessions\"\n\n[[migrations]]\ntag = \"v1\"\nnew_sqlite_classes = [\"WsSessions\"]\n\n# Security: Set secrets via Cloudflare dashboard or CLI:\n# wrangler secret put JWT_SECRET\n`\n}\n","import { mkdirSync, writeFileSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { workerIndexTemplate } from './templates/index.js'\nimport { authTemplate } from './templates/auth.js'\nimport { syncTemplate } from './templates/sync.js'\nimport { wsTemplate } from './templates/ws.js'\nimport { errorsTemplate } from './templates/errors.js'\nimport { healthTemplate } from './templates/health.js'\nimport { r2StorageTemplate } from './templates/r2-storage.js'\nimport { kvStorageTemplate } from './templates/kv-storage.js'\nimport { wranglerTemplate } from './templates/wrangler.js'\n\ninterface GeneratorOptions {\n appName: string\n outDir: string\n kvNamespaceId?: string\n}\n\n/**\n * Generates a complete Hono Cloudflare Worker from the app schema.\n * Writes all source files to outDir.\n */\nexport function generateWorker(options: GeneratorOptions): void {\n const { appName, outDir, kvNamespaceId } = options\n\n // Create directory tree\n const dirs = [\n outDir,\n join(outDir, 'src'),\n join(outDir, 'src', 'routes'),\n join(outDir, 'src', 'storage'),\n ]\n for (const dir of dirs) mkdirSync(dir, { recursive: true })\n\n const files: [string, string][] = [\n [join(outDir, 'wrangler.toml'), wranglerTemplate(appName, kvNamespaceId)],\n [join(outDir, 'src', 'index.ts'), workerIndexTemplate(appName)],\n [join(outDir, 'src', 'routes', 'auth.ts'), authTemplate()],\n [join(outDir, 'src', 'routes', 'sync.ts'), syncTemplate()],\n [join(outDir, 'src', 'routes', 'ws.ts'), wsTemplate()],\n [join(outDir, 'src', 'routes', 'errors.ts'), errorsTemplate()],\n [join(outDir, 'src', 'routes', 'health.ts'), healthTemplate()],\n [join(outDir, 'src', 'storage', 'r2.ts'), r2StorageTemplate()],\n [join(outDir, 'src', 'storage', 'kv.ts'), kvStorageTemplate()],\n [join(outDir, 'package.json'), workerPackageJson(appName)],\n [join(outDir, 'tsconfig.json'), workerTsConfig()],\n ]\n\n for (const [path, content] of files) {\n writeFileSync(path, content, 'utf8')\n }\n\n const kvWarning = kvNamespaceId\n ? ''\n : ' - KV namespace id → set your actual KV namespace ID\\n'\n console.warn(\n '\\n⚠ Remember to replace placeholder values in wrangler.toml before deploying:\\n' +\n ' - JWT_SECRET = \"REPLACE_WITH_SECRET\" → set a strong random secret\\n' +\n kvWarning\n )\n}\n\nfunction workerPackageJson(appName: string): string {\n const name = appName.toLowerCase().replace(/[^a-z0-9-]/g, '-')\n return JSON.stringify(\n {\n name: `${name}-worker`,\n version: '1.0.0',\n type: 'module',\n scripts: {\n dev: 'wrangler dev',\n deploy: 'wrangler deploy',\n 'type-check': 'tsc --noEmit',\n },\n dependencies: {\n hono: '^4.6.0',\n },\n devDependencies: {\n '@cloudflare/workers-types': '^4.0.0',\n typescript: '^5.6.0',\n wrangler: '^3.0.0',\n },\n },\n null,\n 2,\n )\n}\n\nfunction workerTsConfig(): string {\n return JSON.stringify(\n {\n compilerOptions: {\n target: 'ES2022',\n module: 'ESNext',\n moduleResolution: 'bundler',\n lib: ['ES2022'],\n types: ['@cloudflare/workers-types'],\n strict: true,\n skipLibCheck: true,\n },\n include: ['src/**/*'],\n },\n null,\n 2,\n )\n}\n","import { generateWorker } from '../generator/index.js'\nimport type { DeployTarget } from './types.js'\n\nexport const cloudflareTarget: DeployTarget = {\n name: 'cloudflare',\n generate({ appName, outDir, kvNamespaceId }: { appName: string; outDir: string; kvNamespaceId?: string }): void {\n generateWorker({ appName, outDir, kvNamespaceId })\n },\n}\n","import { mkdirSync, writeFileSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { authTemplate } from '../generator/templates/auth.js'\nimport { syncTemplate } from '../generator/templates/sync.js'\nimport { wsTemplate } from '../generator/templates/ws.js'\nimport { errorsTemplate } from '../generator/templates/errors.js'\nimport { healthTemplate } from '../generator/templates/health.js'\nimport { r2StorageTemplate } from '../generator/templates/r2-storage.js'\nimport { kvStorageTemplate } from '../generator/templates/kv-storage.js'\nimport type { DeployTarget } from './types.js'\n\nexport const nodeTarget: DeployTarget = {\n name: 'node',\n generate({ appName, outDir }: { appName: string; outDir: string }): void {\n const dirs = [\n outDir,\n join(outDir, 'src'),\n join(outDir, 'src', 'routes'),\n join(outDir, 'src', 'storage'),\n ]\n for (const dir of dirs) mkdirSync(dir, { recursive: true })\n\n const serverEntry = nodeServerEntry(appName)\n\n const files: [string, string][] = [\n [join(outDir, 'src', 'index.ts'), serverEntry],\n [join(outDir, 'src', 'routes', 'auth.ts'), authTemplate()],\n [join(outDir, 'src', 'routes', 'sync.ts'), syncTemplate()],\n [join(outDir, 'src', 'routes', 'ws.ts'), wsTemplate()],\n [join(outDir, 'src', 'routes', 'errors.ts'), errorsTemplate()],\n [join(outDir, 'src', 'routes', 'health.ts'), healthTemplate()],\n [join(outDir, 'src', 'storage', 'r2.ts'), r2StorageTemplate()],\n [join(outDir, 'src', 'storage', 'kv.ts'), kvStorageTemplate()],\n [join(outDir, 'package.json'), nodePackageJson(appName)],\n [join(outDir, 'tsconfig.json'), nodeTsConfig()],\n ]\n\n for (const [path, content] of files) {\n writeFileSync(path, content, 'utf8')\n }\n },\n}\n\nfunction nodeServerEntry(appName: string): string {\n return `import { Hono } from 'hono'\nimport { serve } from '@hono/node-server'\nimport { createNodeWebSocket } from '@hono/node-ws'\nimport { verify } from 'hono/jwt'\nimport { auth } from './routes/auth.js'\nimport { sync } from './routes/sync.js'\nimport { health } from './routes/health.js'\n\nconst app = new Hono()\nconst { injectWebSocket, upgradeWebSocket } = createNodeWebSocket({ app })\n\n// In-memory session store for WebSocket connections (mirrors DO sessions map)\nconst sessions = new Map<WebSocket, { userId: string }>()\n\napp.route('/auth', auth)\napp.route('/sync', sync)\napp.route('/health', health)\n\napp.get('/ws', upgradeWebSocket(() => ({\n onOpen(_event, ws) {\n // session added on auth message\n },\n async onMessage(event, ws) {\n let msg: { type: string; [k: string]: unknown }\n try {\n msg = JSON.parse(event.data.toString())\n } catch {\n ws.send(JSON.stringify({ type: 'error', message: 'Invalid JSON' }))\n return\n }\n\n const session = sessions.get(ws.raw as WebSocket)\n\n if (msg.type === 'auth') {\n try {\n const jwtSecret = process.env.JWT_SECRET\n if (!jwtSecret) throw new Error('JWT_SECRET not configured')\n const payload = await verify(msg.token as string, jwtSecret) as { sub: string }\n if (!payload.sub) throw new Error('Missing sub claim')\n sessions.set(ws.raw as WebSocket, { userId: payload.sub })\n ws.send(JSON.stringify({ type: 'auth', ok: true }))\n } catch {\n ws.send(JSON.stringify({ type: 'error', message: 'Invalid token' }))\n ws.close()\n }\n } else if (!session) {\n ws.send(JSON.stringify({ type: 'error', message: 'Not authenticated' }))\n } else if (msg.type === 'push') {\n ws.send(JSON.stringify({ type: 'push', ok: true }))\n } else if (msg.type === 'pull') {\n ws.send(JSON.stringify({ type: 'pull', changes: [] }))\n }\n },\n onClose(_event, ws) {\n sessions.delete(ws.raw as WebSocket)\n },\n})))\n\nconst port = parseInt(process.env.PORT ?? '3000', 10)\nconsole.log(\\`${appName} server running on http://localhost:\\${port}\\`)\n\nconst server = serve({ fetch: app.fetch, port })\ninjectWebSocket(server)\n`\n}\n\nfunction nodePackageJson(appName: string): string {\n const name = appName.toLowerCase().replace(/[^a-z0-9-]/g, '-')\n return JSON.stringify(\n {\n name: `${name}-server`,\n version: '1.0.0',\n type: 'module',\n scripts: {\n dev: 'tsx watch src/index.ts',\n start: 'node dist/index.js',\n build: 'tsc',\n },\n dependencies: {\n hono: '^4.6.0',\n '@hono/node-server': '^1.13.0',\n '@hono/node-ws': '^1.0.0',\n },\n devDependencies: {\n typescript: '^5.6.0',\n tsx: '^4.0.0',\n '@types/node': '^22.0.0',\n },\n },\n null,\n 2,\n )\n}\n\nfunction nodeTsConfig(): string {\n return JSON.stringify(\n {\n compilerOptions: {\n target: 'ES2022',\n module: 'ESNext',\n moduleResolution: 'bundler',\n lib: ['ES2022'],\n types: ['node'],\n strict: true,\n skipLibCheck: true,\n outDir: 'dist',\n },\n include: ['src/**/*'],\n },\n null,\n 2,\n )\n}\n","import type { Command } from 'commander'\nimport { resolve } from 'node:path'\nimport { cloudflareTarget } from '../targets/cloudflare.js'\nimport { nodeTarget } from '../targets/node.js'\nimport { log } from '../utils.js'\n\nconst targets = { cloudflare: cloudflareTarget, node: nodeTarget }\n\nexport function registerBuild(program: Command): void {\n program\n .command('build')\n .description('Build the LocalKit backend bundle')\n .option('-o, --out <dir>', 'Output directory', '.offlinekit/worker')\n .option('-n, --name <name>', 'App name for the worker', 'localkit-app')\n .option('-t, --target <target>', 'Deploy target: cloudflare or node', 'cloudflare')\n .action(async (opts: { out: string; name: string; target: string }) => {\n log.bold('LocalKit Build')\n\n const target = targets[opts.target as keyof typeof targets]\n if (!target) {\n log.error(`Unknown target: ${opts.target}. Valid targets: ${Object.keys(targets).join(', ')}`)\n process.exit(1)\n }\n\n const outDir = resolve(process.cwd(), opts.out)\n log.info(`Generating ${target.name} backend to: ${outDir}`)\n\n try {\n target.generate({ appName: opts.name, outDir })\n log.success(`Backend generated at ${outDir}`)\n if (opts.target === 'node') {\n log.dim(`Run: cd ${opts.out} && npm install && npm run dev`)\n } else {\n log.dim(`Run: cd ${opts.out} && npm install && wrangler deploy`)\n }\n } catch (err) {\n log.error(`Build failed: ${err instanceof Error ? err.message : String(err)}`)\n process.exit(1)\n }\n })\n}\n","import type { Command } from 'commander'\nimport { execSync, spawnSync } from 'node:child_process'\nimport { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs'\nimport { randomBytes } from 'node:crypto'\nimport { resolve, dirname } from 'node:path'\nimport { cloudflareTarget } from '../targets/cloudflare.js'\nimport { log } from '../utils.js'\n\n// --- Types ---\n\nexport interface DeployState {\n kvNamespaceId: string\n r2BucketName: string\n workerName: string\n workerUrl?: string\n jwtSecretSet: boolean\n}\n\ninterface WranglerResult {\n stdout: string\n stderr: string\n status: number | null\n}\n\n// --- Helpers ---\n\nexport function runWrangler(\n args: string[],\n options?: { cwd?: string; input?: string },\n): WranglerResult {\n const result = spawnSync('wrangler', args, {\n encoding: 'utf8',\n stdio: ['pipe', 'pipe', 'pipe'],\n ...options,\n })\n return {\n stdout: result.stdout ?? '',\n stderr: result.stderr ?? '',\n status: result.status,\n }\n}\n\nfunction checkWrangler(): string | null {\n try {\n const result = execSync('wrangler --version', {\n encoding: 'utf8',\n stdio: ['ignore', 'pipe', 'ignore'],\n })\n return result.trim()\n } catch {\n return null\n }\n}\n\nexport function checkAuth(): boolean {\n const result = runWrangler(['whoami'])\n return result.status === 0\n}\n\nexport function createR2Bucket(name: string): void {\n log.info(`Creating R2 bucket: ${name}`)\n const result = runWrangler(['r2', 'bucket', 'create', name])\n if (result.status !== 0) {\n if (result.stderr.includes('already exists')) {\n log.info(`R2 bucket \"${name}\" already exists, continuing`)\n return\n }\n if (result.stderr.includes('R2') || result.stderr.includes('not allowed') || result.stderr.includes('not enabled')) {\n throw new Error(\n `Failed to create R2 bucket: ${result.stderr}\\n` +\n 'Hint: Enable R2 in your Cloudflare dashboard at https://dash.cloudflare.com → R2 Object Storage before deploying.',\n )\n }\n throw new Error(`Failed to create R2 bucket: ${result.stderr}`)\n }\n log.success(`R2 bucket \"${name}\" created`)\n}\n\nexport function kvNamespaceExists(id: string): boolean {\n const result = runWrangler(['kv', 'namespace', 'list', '--json'])\n if (result.status !== 0) return false\n try {\n const namespaces = JSON.parse(result.stdout) as Array<{ id: string }>\n return namespaces.some((ns) => ns.id === id)\n } catch {\n return false\n }\n}\n\nexport function createKvNamespace(name: string): string {\n log.info(`Creating KV namespace: ${name}`)\n const result = runWrangler(['kv', 'namespace', 'create', name])\n\n if (result.status === 0) {\n // Primary: parse ID from create stdout\n const match = result.stdout.match(/id\\s*=\\s*\"([a-f0-9]+)\"/)\n if (match) {\n log.success(`KV namespace \"${name}\" created with ID: ${match[1]}`)\n return match[1]\n }\n // Try JSON parsing if --json was supported\n try {\n const parsed = JSON.parse(result.stdout)\n if (parsed.id) return parsed.id\n } catch {\n // not JSON, continue\n }\n }\n\n // Fallback: namespace already exists, list and find by title\n if (result.stderr.includes('already exists') || result.status !== 0) {\n log.info(`KV namespace \"${name}\" may already exist, looking up ID...`)\n const listResult = runWrangler(['kv', 'namespace', 'list', '--json'])\n if (listResult.status === 0) {\n try {\n const namespaces = JSON.parse(listResult.stdout) as Array<{\n id: string\n title: string\n }>\n const found = namespaces.find((ns) => ns.title === name)\n if (found) {\n log.success(`Found existing KV namespace \"${name}\" with ID: ${found.id}`)\n return found.id\n }\n } catch {\n log.warn('Failed to parse KV namespace list JSON, falling back to regex')\n }\n // Last resort: regex on raw list output\n const idMatch = listResult.stdout.match(/id\\s*=\\s*\"([a-f0-9]+)\"/)\n if (idMatch) return idMatch[1]\n }\n }\n\n throw new Error(\n `Failed to create or find KV namespace \"${name}\". ` +\n `stdout: ${result.stdout}, stderr: ${result.stderr}`,\n )\n}\n\nexport function setSecret(name: string, value: string, cwd: string): void {\n log.info(`Setting secret: ${name}`)\n const result = runWrangler(['secret', 'put', name], { cwd, input: value })\n if (result.status !== 0) {\n throw new Error(`Failed to set secret ${name}: ${result.stderr}`)\n }\n log.success(`Secret \"${name}\" set`)\n}\n\nexport function readDeployState(outDir: string): DeployState | null {\n const statePath = resolve(outDir, '..', 'deploy-state.json')\n if (!existsSync(statePath)) return null\n try {\n return JSON.parse(readFileSync(statePath, 'utf8')) as DeployState\n } catch {\n return null\n }\n}\n\nexport function writeDeployState(outDir: string, state: DeployState): void {\n const statePath = resolve(outDir, '..', 'deploy-state.json')\n mkdirSync(dirname(statePath), { recursive: true })\n writeFileSync(statePath, JSON.stringify(state, null, 2), 'utf8')\n}\n\n// --- Composable Functions ---\n\nexport function provisionCloudflare(\n appName: string,\n _outDir: string,\n dryRun: boolean,\n): { kvNamespaceId: string; r2BucketName: string; workerName: string } {\n const name = appName.toLowerCase().replace(/[^a-z0-9-]/g, '-')\n const r2BucketName = `${name}-storage`\n const kvTitle = `${name}-kv`\n const workerName = `${name}-worker`\n\n // Check auth\n if (dryRun) {\n log.dim('[dry-run] Would check wrangler auth (wrangler whoami)')\n log.dim(`[dry-run] Would create R2 bucket: ${r2BucketName}`)\n log.dim(`[dry-run] Would create KV namespace: ${kvTitle}`)\n log.dim('[dry-run] Would set JWT_SECRET')\n return { kvNamespaceId: 'DRY_RUN_PLACEHOLDER', r2BucketName, workerName }\n }\n\n if (!checkAuth()) {\n log.error('Not authenticated with Cloudflare.')\n log.dim('Run `wrangler login` to authenticate, then try again.')\n process.exit(1)\n }\n log.success('Authenticated with Cloudflare')\n\n // Create R2 bucket\n createR2Bucket(r2BucketName)\n\n // Create KV namespace\n const kvNamespaceId = createKvNamespace(kvTitle)\n\n return { kvNamespaceId, r2BucketName, workerName }\n}\n\nexport function generateAndDeploy(\n appName: string,\n outDir: string,\n kvNamespaceId: string,\n env: string | undefined,\n dryRun: boolean,\n): string | undefined {\n if (dryRun) {\n log.dim(`[dry-run] Would generate worker code to: ${outDir}`)\n log.dim(`[dry-run] Would run: npm install (in ${outDir})`)\n log.dim(`[dry-run] Would run: wrangler deploy${env ? ` --env ${env}` : ''}`)\n return undefined\n }\n\n // Generate worker code with real KV namespace ID\n log.info('Generating worker code...')\n cloudflareTarget.generate({ appName, outDir, kvNamespaceId })\n log.success('Worker code generated')\n\n // npm install\n log.info('Installing dependencies...')\n const installResult = spawnSync('npm', ['install'], {\n cwd: outDir,\n encoding: 'utf8',\n stdio: ['pipe', 'pipe', 'pipe'],\n })\n if (installResult.status !== 0) {\n throw new Error(`npm install failed: ${installResult.stderr}`)\n }\n log.success('Dependencies installed')\n\n // wrangler deploy\n log.info('Deploying to Cloudflare...')\n const deployArgs = ['deploy']\n if (env) deployArgs.push('--env', env)\n\n const deployResult = spawnSync('wrangler', deployArgs, {\n cwd: outDir,\n encoding: 'utf8',\n stdio: ['pipe', 'pipe', 'pipe'],\n })\n\n if (deployResult.status !== 0) {\n throw new Error(\n `wrangler deploy failed (exit ${deployResult.status}): ${deployResult.stderr}`,\n )\n }\n\n // Parse worker URL\n const urlMatch = deployResult.stdout.match(/https:\\/\\/[^\\s]+\\.workers\\.dev/)\n const workerUrl = urlMatch ? urlMatch[0] : undefined\n if (workerUrl) {\n log.success(`Deployed to: ${workerUrl}`)\n } else {\n log.success('Deployed successfully!')\n }\n\n return workerUrl\n}\n\n// --- Command Registration ---\n\nexport function registerDeploy(program: Command): void {\n program\n .command('deploy')\n .description('Deploy the LocalKit Worker to Cloudflare via Wrangler')\n .option('-d, --dir <dir>', 'Worker output directory', '.offlinekit/worker')\n .option('-n, --name <name>', 'App name for the worker', 'localkit-app')\n .option('-e, --env <env>', 'Wrangler environment (e.g. production, staging)')\n .option('-t, --target <target>', 'Deploy target (default: cloudflare)', 'cloudflare')\n .option('--dry-run', 'Show what would happen without executing')\n .action(\n (opts: {\n dir: string\n name: string\n env?: string\n target: string\n dryRun?: boolean\n }) => {\n log.bold('LocalKit Deploy')\n\n const dryRun = opts.dryRun ?? false\n\n // Check if project has been ejected\n const serverDir = resolve(process.cwd(), 'server')\n if (existsSync(serverDir)) {\n log.info(\n 'Warning: This project has been ejected (./server/ exists).',\n )\n log.dim(\n 'You can deploy the ejected code directly with `cd server && wrangler deploy`.',\n )\n }\n\n // Validate target\n if (opts.target !== 'cloudflare') {\n log.error(\n `Deploy target \"${opts.target}\" is not supported yet. Only \"cloudflare\" is deployable.`,\n )\n log.dim(\n 'For Node.js targets, run `npx mpb-localkit build --target node` then deploy the output manually.',\n )\n process.exit(1)\n }\n\n // Check wrangler\n const version = checkWrangler()\n if (!version) {\n log.error('wrangler is not installed or not in PATH.')\n log.dim('Install it with: npm install -g wrangler')\n process.exit(1)\n }\n log.success(`wrangler ${version}`)\n\n const outDir = resolve(process.cwd(), opts.dir)\n const appName = opts.name\n\n // Read existing deploy state\n const existingState = readDeployState(outDir)\n\n let kvNamespaceId: string\n let r2BucketName: string\n let workerName: string\n if (existingState?.kvNamespaceId && existingState?.r2BucketName) {\n // Subsequent deploy -- validate resources still exist\n log.info('Found existing deploy state, validating resources...')\n r2BucketName = existingState.r2BucketName\n workerName = existingState.workerName\n\n if (dryRun) {\n log.dim('[dry-run] Would validate KV namespace exists')\n kvNamespaceId = existingState.kvNamespaceId\n } else if (kvNamespaceExists(existingState.kvNamespaceId)) {\n log.success('KV namespace validated')\n kvNamespaceId = existingState.kvNamespaceId\n } else {\n log.warn('KV namespace no longer exists, re-creating...')\n const name = appName.toLowerCase().replace(/[^a-z0-9-]/g, '-')\n kvNamespaceId = createKvNamespace(`${name}-kv`)\n writeDeployState(outDir, {\n ...existingState,\n kvNamespaceId,\n })\n log.success('Deploy state updated with new KV namespace ID')\n }\n } else {\n // First deploy -- provision resources\n const provisioned = provisionCloudflare(appName, outDir, dryRun)\n kvNamespaceId = provisioned.kvNamespaceId\n r2BucketName = provisioned.r2BucketName\n workerName = provisioned.workerName\n\n // Save provisioned state (jwtSecretSet: false until secret is actually set)\n if (!dryRun) {\n writeDeployState(outDir, {\n kvNamespaceId,\n r2BucketName,\n workerName,\n jwtSecretSet: false,\n })\n log.success('Deploy state saved to .offlinekit/deploy-state.json')\n }\n }\n\n // Pre-flight: ensure we never deploy with a placeholder KV namespace ID\n if (kvNamespaceId === 'REPLACE_WITH_KV_NAMESPACE_ID' || !kvNamespaceId) {\n log.error(\n 'KV namespace ID is missing or still a placeholder. ' +\n 'Run `mpb-localkit deploy` (not `wrangler deploy` directly) to auto-provision resources, ' +\n 'or create one manually: wrangler kv namespace create KV',\n )\n process.exit(1)\n }\n\n const alreadyHasSecret = existingState?.jwtSecretSet ?? false\n\n // Generate code and deploy (this creates wrangler.toml in outDir)\n let workerUrl: string | undefined\n try {\n workerUrl = generateAndDeploy(appName, outDir, kvNamespaceId, opts.env, dryRun)\n } catch (err) {\n log.error(`Deploy failed: ${err instanceof Error ? err.message : String(err)}`)\n process.exit(1)\n }\n\n if (dryRun) {\n if (!alreadyHasSecret) {\n log.dim('[dry-run] Would set JWT_SECRET (first deploy only)')\n }\n log.bold('Dry run complete. No changes were made.')\n return\n }\n\n // Set JWT_SECRET now that wrangler.toml exists in outDir\n let jwtSecretSet = alreadyHasSecret\n if (!jwtSecretSet) {\n try {\n setSecret('JWT_SECRET', randomBytes(32).toString('hex'), outDir)\n log.success('JWT_SECRET set')\n jwtSecretSet = true\n } catch (err) {\n log.warn(`Could not set JWT_SECRET: ${err instanceof Error ? err.message : String(err)}`)\n log.dim('Set it manually: wrangler secret put JWT_SECRET')\n }\n }\n\n // Persist final state with workerUrl\n writeDeployState(outDir, { kvNamespaceId, r2BucketName, workerName, workerUrl, jwtSecretSet })\n\n // Optionally update .env\n if (workerUrl) {\n const envPath = resolve(process.cwd(), '.env')\n if (existsSync(envPath)) {\n let envContent = readFileSync(envPath, 'utf8')\n if (envContent.includes('VITE_SYNC_URL=')) {\n envContent = envContent.replace(/VITE_SYNC_URL=.*/, `VITE_SYNC_URL=${workerUrl}`)\n } else {\n envContent += `\\nVITE_SYNC_URL=${workerUrl}\\n`\n }\n writeFileSync(envPath, envContent, 'utf8')\n log.info(`Updated .env with VITE_SYNC_URL=${workerUrl}`)\n }\n }\n },\n )\n}\n","import type { Command } from 'commander'\nimport { existsSync } from 'node:fs'\nimport { resolve } from 'node:path'\nimport { cloudflareTarget } from '../targets/cloudflare.js'\nimport { nodeTarget } from '../targets/node.js'\nimport type { DeployTarget } from '../targets/types.js'\nimport { log } from '../utils.js'\n\nconst targets: Record<string, DeployTarget> = {\n cloudflare: cloudflareTarget,\n node: nodeTarget,\n}\n\nexport function registerEject(program: Command): void {\n program\n .command('eject')\n .description('Eject generated Worker code into ./server/ for manual customization')\n .option('-o, --out <dir>', 'Output directory for ejected code', 'server')\n .option('-n, --name <name>', 'App name', 'localkit-app')\n .option('-t, --target <target>', 'Deploy target (cloudflare, node)', 'cloudflare')\n .action((opts: { out: string; name: string; target: string }) => {\n log.bold('LocalKit Eject')\n\n const target = targets[opts.target]\n if (!target) {\n log.error(`Unknown target: \"${opts.target}\"`)\n log.dim(`Available targets: ${Object.keys(targets).join(', ')}`)\n process.exit(1)\n }\n\n const outDir = resolve(process.cwd(), opts.out)\n\n if (existsSync(outDir)) {\n log.error(`Directory already exists: ${outDir}`)\n log.dim('Remove it or choose a different output directory with --out.')\n process.exit(1)\n }\n\n log.info(`Ejecting ${opts.target} code to: ${outDir}`)\n\n try {\n target.generate({ appName: opts.name, outDir })\n log.success(`Ejected to ./${opts.out}/`)\n\n if (opts.target === 'node') {\n log.dim('You can now customize and deploy your Node.js server.')\n log.dim('')\n log.dim('Next steps:')\n log.dim(` cd ${opts.out}`)\n log.dim(' npm install')\n log.dim(' npm run dev')\n log.dim('')\n log.dim('To run in production: npm start')\n } else {\n log.dim('You can now customize and deploy with `wrangler deploy`.')\n log.dim('')\n log.dim('Next steps:')\n log.dim(` cd ${opts.out}`)\n log.dim(' npm install')\n log.dim(' wrangler deploy')\n log.dim('')\n log.dim('Note: Running `npx mpb-localkit deploy` will warn that code has been ejected.')\n }\n } catch (err) {\n log.error(`Eject failed: ${err instanceof Error ? err.message : String(err)}`)\n process.exit(1)\n }\n })\n}\n","#!/usr/bin/env node\nimport { Command } from 'commander'\nimport { createRequire } from 'node:module'\nimport { registerDev } from './commands/dev.js'\nimport { registerBuild } from './commands/build.js'\nimport { registerDeploy } from './commands/deploy.js'\nimport { registerEject } from './commands/eject.js'\n\nconst require = createRequire(import.meta.url)\nconst pkg = require('../../package.json') as { version: string; description: string }\n\nconst program = new Command()\n\nprogram\n .name('mpb-localkit')\n .description(pkg.description)\n .version(pkg.version, '-v, --version', 'Print the current version')\n\nregisterDev(program)\nregisterBuild(program)\nregisterDeploy(program)\nregisterEject(program)\n\nprogram.parse(process.argv)\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/cli/utils.ts","../../src/cli/commands/dev.ts","../../src/cli/generator/templates/index.ts","../../src/cli/generator/templates/auth.ts","../../src/cli/generator/templates/sync.ts","../../src/cli/generator/templates/ws.ts","../../src/cli/generator/templates/errors.ts","../../src/cli/generator/templates/health.ts","../../src/cli/generator/templates/r2-storage.ts","../../src/cli/generator/templates/kv-storage.ts","../../src/cli/generator/templates/wrangler.ts","../../src/cli/generator/index.ts","../../src/cli/targets/cloudflare.ts","../../src/cli/targets/node.ts","../../src/cli/commands/build.ts","../../src/cli/commands/deploy.ts","../../src/cli/commands/eject.ts","../../src/cli/index.ts"],"names":["program","join","mkdirSync","writeFileSync","resolve","existsSync","targets","require"],"mappings":"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","file":"index.js","sourcesContent":["import { existsSync } from 'node:fs'\nimport { resolve } from 'node:path'\n\n/** Color helpers for terminal output (no dependencies) */\nconst colors = {\n green: (s: string) => `\\x1b[32m${s}\\x1b[0m`,\n yellow: (s: string) => `\\x1b[33m${s}\\x1b[0m`,\n red: (s: string) => `\\x1b[31m${s}\\x1b[0m`,\n cyan: (s: string) => `\\x1b[36m${s}\\x1b[0m`,\n bold: (s: string) => `\\x1b[1m${s}\\x1b[0m`,\n dim: (s: string) => `\\x1b[2m${s}\\x1b[0m`,\n}\n\nexport const log = {\n info: (msg: string) => console.log(`${colors.cyan('ℹ')} ${msg}`),\n success: (msg: string) => console.log(`${colors.green('✓')} ${msg}`),\n warn: (msg: string) => console.warn(`${colors.yellow('⚠')} ${msg}`),\n error: (msg: string) => console.error(`${colors.red('✗')} ${msg}`),\n bold: (msg: string) => console.log(colors.bold(msg)),\n dim: (msg: string) => console.log(colors.dim(msg)),\n}\n\nconst CONFIG_CANDIDATES = [\n 'offlinekit.config.ts',\n 'offlinekit.config.js',\n 'offlinekit.schema.ts',\n 'offlinekit.schema.js',\n]\n\n/** Finds the OfflineKit config/schema file in the current working directory */\nexport function findSchemaFile(cwd = process.cwd()): string | null {\n for (const candidate of CONFIG_CANDIDATES) {\n const p = resolve(cwd, candidate)\n if (existsSync(p)) return p\n }\n return null\n}\n\n/** Dynamically imports and returns the default export from the schema file */\nexport async function loadSchema(filePath: string): Promise<unknown> {\n const mod = await import(filePath) as { default?: unknown }\n return mod.default ?? mod\n}\n","import type { Command } from 'commander'\nimport { log } from '../utils.js'\n\nexport function registerDev(program: Command): void {\n program\n .command('dev')\n .description('Start LocalKit in local-only mode (no cloud sync)')\n .action(() => {\n process.env['OFFLINEKIT_MODE'] = 'local'\n log.bold('LocalKit Dev Mode')\n log.info('Running in local-only mode (no cloud sync)')\n log.dim('All data is stored locally. Sync is disabled.')\n })\n}\n","/** Main Hono app entry point template */\nexport function workerIndexTemplate(_appName: string): string {\n return `\nimport { Hono } from 'hono'\nimport { cors } from 'hono/cors'\nimport { auth } from './routes/auth.js'\nimport { sync } from './routes/sync.js'\nimport { ws, WsSessions } from './routes/ws.js'\nimport { errors } from './routes/errors.js'\nimport { health } from './routes/health.js'\n\nexport interface Env {\n STORAGE: R2Bucket\n KV: KVNamespace\n JWT_SECRET: string\n WS_SESSIONS: DurableObjectNamespace\n}\n\nexport { WsSessions }\n\nconst app = new Hono<{ Bindings: Env }>()\n\napp.use('/*', cors({\n origin: '*',\n allowMethods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],\n allowHeaders: ['Content-Type', 'Authorization'],\n}))\n\napp.route('/auth', auth)\napp.route('/sync', sync)\napp.route('/ws', ws)\napp.route('/errors', errors)\napp.route('/health', health)\n\nexport default app\n`.trimStart()\n}\n","/** Auth routes: POST /auth/signup, /auth/signin, /auth/signout, /auth/hash */\nexport function authTemplate(): string {\n return `\nimport { Hono } from 'hono'\nimport { sign, verify } from 'hono/jwt'\nimport type { Env } from './index.js'\nimport { AUTH_KEY, SESSION_KEY, type StoredUser } from '../storage/kv.js'\n\nexport const auth = new Hono<{ Bindings: Env }>()\n\n/** Constant-time string comparison to prevent timing side-channels */\nfunction timingSafeEqual(a: string, b: string): boolean {\n if (a.length !== b.length) return false\n const encoder = new TextEncoder()\n const bufA = encoder.encode(a)\n const bufB = encoder.encode(b)\n let result = 0\n for (let i = 0; i < bufA.length; i++) result |= bufA[i] ^ bufB[i]\n return result === 0\n}\n\n/** Extract userId from Bearer token — throws on invalid/expired */\nexport async function authMiddleware(c: any, next: () => Promise<void>) {\n const header = c.req.header('Authorization') ?? ''\n const token = header.startsWith('Bearer ') ? header.slice(7) : null\n if (!token) return c.json({ error: 'Unauthorized' }, 401)\n try {\n const payload = await verify(token, c.env.JWT_SECRET, 'HS256') as { sub: string }\n c.set('userId', payload.sub)\n } catch {\n return c.json({ error: 'Invalid token' }, 401)\n }\n return next()\n}\n\nauth.post('/signup', async (c) => {\n const { email, passwordHash } = await c.req.json<{ email: string; passwordHash: string }>()\n if (!email || !passwordHash) return c.json({ error: 'email and passwordHash required' }, 400)\n\n const existing = await c.env.KV.get(AUTH_KEY(email))\n if (existing) return c.json({ error: 'Email already registered' }, 409)\n\n const userId = crypto.randomUUID()\n const user: StoredUser = { userId, email, passwordHash }\n await c.env.KV.put(AUTH_KEY(email), JSON.stringify(user))\n\n const token = await sign({ sub: userId, email, exp: Math.floor(Date.now() / 1000) + 60 * 60 * 24 * 30 }, c.env.JWT_SECRET, 'HS256')\n return c.json({ user: { id: userId, email }, token }, 201)\n})\n\nauth.post('/hash', async (c) => {\n const { email } = await c.req.json<{ email: string }>()\n if (!email) return c.json({ error: 'email required' }, 400)\n\n const raw = await c.env.KV.get(AUTH_KEY(email))\n if (!raw) return c.json({ error: 'User not found' }, 404)\n\n const user = JSON.parse(raw) as StoredUser\n return c.json({ passwordHash: user.passwordHash })\n})\n\nauth.post('/signin', async (c) => {\n const { email, passwordHash } = await c.req.json<{ email: string; passwordHash: string }>()\n if (!email || !passwordHash) return c.json({ error: 'email and passwordHash required' }, 400)\n\n const raw = await c.env.KV.get(AUTH_KEY(email))\n if (!raw) return c.json({ error: 'Invalid credentials' }, 401)\n\n const user = JSON.parse(raw) as StoredUser\n if (!timingSafeEqual(user.passwordHash, passwordHash)) return c.json({ error: 'Invalid credentials' }, 401)\n\n const token = await sign({ sub: user.userId, email, exp: Math.floor(Date.now() / 1000) + 60 * 60 * 24 * 30 }, c.env.JWT_SECRET, 'HS256')\n return c.json({ user: { id: user.userId, email }, token })\n})\n\nauth.post('/signout', async (c) => {\n const header = c.req.header('Authorization') ?? ''\n const token = header.startsWith('Bearer ') ? header.slice(7) : null\n if (token) await c.env.KV.delete(SESSION_KEY(token))\n return c.json({ ok: true })\n})\n`.trimStart()\n}\n","/** Sync routes: POST /sync/push, GET /sync/pull?since= */\nexport function syncTemplate(): string {\n return `\nimport { Hono } from 'hono'\nimport type { Env } from './index.js'\nimport { authMiddleware } from './auth.js'\nimport { docKey, collectionPrefix } from '../storage/r2.js'\n\ninterface SyncDoc {\n _id: string\n _collection: string\n _updatedAt: number\n _deleted: boolean\n [key: string]: unknown\n}\n\nexport const sync = new Hono<{ Bindings: Env }>()\n\nsync.use('/*', authMiddleware)\n\nsync.post('/push', async (c) => {\n const userId = c.get('userId') as string\n const { changes } = await c.req.json<{ changes: SyncDoc[] }>()\n\n await Promise.all(\n changes.map(async (doc) => {\n const key = docKey(userId, doc._collection, doc._id)\n const existing = await c.env.STORAGE.get(key, 'json') as SyncDoc | null\n\n // LWW — only overwrite if incoming is newer\n if (!existing || doc._updatedAt >= existing._updatedAt) {\n await c.env.STORAGE.put(key, JSON.stringify(doc), {\n customMetadata: { updatedAt: String(doc._updatedAt) },\n })\n }\n }),\n )\n\n return c.json({ ok: true, received: changes.length })\n})\n\nsync.get('/pull', async (c) => {\n const userId = c.get('userId') as string\n const since = parseInt(c.req.query('since') ?? '0', 10)\n\n // Scan all collections for this user — list all objects under {userId}/\n const prefix = \\`\\${userId}/\\`\n const listed = await c.env.STORAGE.list({ prefix })\n\n const changes = await Promise.all(\n listed.objects\n .filter((obj) => {\n const ts = parseInt(obj.customMetadata?.updatedAt ?? '0', 10)\n return ts > since\n })\n .map(async (obj) => {\n const blob = await c.env.STORAGE.get(obj.key, 'json')\n return blob as SyncDoc\n }),\n )\n\n return c.json({ changes: changes.filter(Boolean) })\n})\n`.trimStart()\n}\n","/** WebSocket Durable Object handler for real-time sync */\nexport function wsTemplate(): string {\n return `import { Hono } from 'hono'\nimport { verify } from 'hono/jwt'\nimport type { Env } from './index.js'\nimport { authMiddleware } from './auth.js'\nimport { docKey } from '../storage/r2.js'\n\nexport const ws = new Hono<{ Bindings: Env }>()\n\n// Proxy WS upgrade requests to the user-scoped Durable Object\nws.get('/', authMiddleware, async (c) => {\n const userId = c.get('userId') as string\n const id = c.env.WS_SESSIONS.idFromName(userId)\n return c.env.WS_SESSIONS.get(id).fetch(c.req.raw)\n})\n\n// ---- Durable Object: one instance per userId, owns all WebSocket sessions ----\n\ninterface SyncDoc {\n _id: string\n _collection: string\n _updatedAt: number\n _deleted: boolean\n [key: string]: unknown\n}\n\ninterface WsMsg {\n type: string\n id?: string\n payload?: unknown\n since?: number\n token?: string\n}\n\nexport class WsSessions {\n private readonly sessions = new Map<WebSocket, { userId: string | null }>()\n\n constructor(\n private readonly state: DurableObjectState,\n private readonly env: Env,\n ) {}\n\n async fetch(request: Request): Promise<Response> {\n if (request.headers.get('Upgrade') !== 'websocket') {\n return new Response('Expected WebSocket upgrade', { status: 426 })\n }\n\n const pair = new WebSocketPair()\n const [client, server] = Object.values(pair) as [WebSocket, WebSocket]\n server.accept()\n\n const session = { userId: null as string | null }\n this.sessions.set(server, session)\n\n server.addEventListener('message', async (event) => {\n let msg: WsMsg\n try { msg = JSON.parse(event.data as string) as WsMsg } catch { return }\n try {\n await this.handle(server, session, msg)\n } catch (err) {\n server.send(JSON.stringify({ type: 'error', id: msg.id, payload: { message: String(err) } }))\n }\n })\n\n server.addEventListener('close', () => { this.sessions.delete(server) })\n\n return new Response(null, { status: 101, webSocket: client })\n }\n\n private async handle(ws: WebSocket, session: { userId: string | null }, msg: WsMsg): Promise<void> {\n if (msg.type === 'auth') {\n try {\n const payload = await verify(msg.token ?? '', this.env.JWT_SECRET, 'HS256') as { sub?: string }\n if (!payload.sub) throw new Error('Missing sub')\n session.userId = payload.sub\n ws.send(JSON.stringify({ type: 'auth_ack', id: msg.id }))\n } catch {\n ws.send(JSON.stringify({ type: 'error', id: msg.id, payload: { message: 'Unauthorized' } }))\n ws.close(1008, 'Unauthorized')\n }\n return\n }\n\n if (!session.userId) {\n ws.send(JSON.stringify({ type: 'error', id: msg.id, payload: { message: 'Not authenticated' } }))\n return\n }\n\n if (msg.type === 'push') {\n const { changes } = msg.payload as { changes: SyncDoc[] }\n await Promise.all(changes.map(async (doc) => {\n const key = docKey(session.userId!, doc._collection, doc._id)\n const existing = await this.env.STORAGE.get(key, 'json') as SyncDoc | null\n if (!existing || doc._updatedAt >= existing._updatedAt) {\n await this.env.STORAGE.put(key, JSON.stringify(doc), {\n customMetadata: { updatedAt: String(doc._updatedAt) },\n })\n }\n }))\n ws.send(JSON.stringify({ type: 'push_ack', id: msg.id, payload: { ok: true } }))\n this.broadcast(session.userId, ws, { type: 'remote_changes', changes })\n return\n }\n\n if (msg.type === 'pull') {\n const since = typeof msg.since === 'number' ? msg.since : 0\n const listed = await this.env.STORAGE.list({ prefix: \\`\\${session.userId}/\\` })\n const changes = (await Promise.all(\n listed.objects\n .filter((o) => parseInt(o.customMetadata?.updatedAt ?? '0', 10) > since)\n .map((o) => this.env.STORAGE.get(o.key, 'json') as Promise<SyncDoc>),\n )).filter(Boolean)\n ws.send(JSON.stringify({ type: 'pull_response', id: msg.id, payload: { changes } }))\n return\n }\n\n ws.send(JSON.stringify({ type: 'error', id: msg.id, payload: { message: \\`Unknown type: \\${msg.type}\\` } }))\n }\n\n private broadcast(userId: string, sender: WebSocket, msg: object): void {\n const data = JSON.stringify(msg)\n for (const [ws, s] of this.sessions) {\n if (ws !== sender && s.userId === userId) {\n try { ws.send(data) } catch { /* stale connection */ }\n }\n }\n }\n}\n\n// JWT verification handled by hono/jwt verify() — no hand-rolled crypto needed\n`.trimStart()\n}\n","/** GET /errors — list error blobs for authenticated user */\nexport function errorsTemplate(): string {\n return `\nimport { Hono } from 'hono'\nimport type { Env } from './index.js'\nimport { authMiddleware } from './auth.js'\n\nexport const errors = new Hono<{ Bindings: Env }>()\n\nerrors.use('/*', authMiddleware)\n\nerrors.get('/', async (c) => {\n const userId = c.get('userId') as string\n const prefix = \\`\\${userId}/_errors/\\`\n\n const listed = await c.env.STORAGE.list({ prefix })\n const results = await Promise.all(\n listed.objects.map(async (obj) => {\n const blob = await c.env.STORAGE.get(obj.key)\n if (!blob) return null\n return blob.json()\n }),\n )\n\n return c.json({ errors: results.filter(Boolean) })\n})\n`.trimStart()\n}\n","/** GET /health — liveness check */\nexport function healthTemplate(): string {\n return `\nimport { Hono } from 'hono'\n\nexport const health = new Hono()\n\nhealth.get('/', (c) => {\n return c.json({ status: 'ok', timestamp: Date.now() })\n})\n`.trimStart()\n}\n","/** R2 document key helpers — {userId}/{collection}/{docId}.json */\nexport function r2StorageTemplate(): string {\n return `\nexport const docKey = (userId: string, collection: string, docId: string) =>\n \\`\\${userId}/\\${collection}/\\${docId}.json\\`\n\nexport const collectionPrefix = (userId: string, collection: string) =>\n \\`\\${userId}/\\${collection}/\\`\n`.trimStart()\n}\n","/** KV storage helpers — sessions, auth credentials, metadata */\nexport function kvStorageTemplate(): string {\n return `\n/** Key: auth:{email} Value: { userId, email, passwordHash } */\nexport const AUTH_KEY = (email: string) => \\`auth:\\${email}\\`\n\n/** Key: session:{token} Value: { userId, email, exp } */\nexport const SESSION_KEY = (token: string) => \\`session:\\${token}\\`\n\n/** Key: meta:{userId} Value: arbitrary metadata object */\nexport const META_KEY = (userId: string) => \\`meta:\\${userId}\\`\n\nexport interface StoredUser {\n userId: string\n email: string\n passwordHash: string\n}\n\nexport interface StoredSession {\n userId: string\n email: string\n exp: number\n}\n`.trimStart()\n}\n","/** Generate wrangler.toml for a Cloudflare Worker with R2 + KV bindings */\nexport function wranglerTemplate(appName: string, kvNamespaceId?: string): string {\n const name = appName.toLowerCase().replace(/[^a-z0-9-]/g, '-')\n return `name = \"${name}-worker\"\nmain = \"src/index.ts\"\ncompatibility_date = \"2024-01-01\"\ncompatibility_flags = [\"nodejs_compat\"]\n\n[[r2_buckets]]\nbinding = \"STORAGE\"\nbucket_name = \"${name}-storage\"\n\n[[kv_namespaces]]\nbinding = \"KV\"\nid = \"${kvNamespaceId ?? 'REPLACE_WITH_KV_NAMESPACE_ID'}\"\n\n[[durable_objects.bindings]]\nname = \"WS_SESSIONS\"\nclass_name = \"WsSessions\"\n\n[[migrations]]\ntag = \"v1\"\nnew_sqlite_classes = [\"WsSessions\"]\n\n# Security: Set secrets via Cloudflare dashboard or CLI:\n# wrangler secret put JWT_SECRET\n`\n}\n","import { mkdirSync, writeFileSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { workerIndexTemplate } from './templates/index.js'\nimport { authTemplate } from './templates/auth.js'\nimport { syncTemplate } from './templates/sync.js'\nimport { wsTemplate } from './templates/ws.js'\nimport { errorsTemplate } from './templates/errors.js'\nimport { healthTemplate } from './templates/health.js'\nimport { r2StorageTemplate } from './templates/r2-storage.js'\nimport { kvStorageTemplate } from './templates/kv-storage.js'\nimport { wranglerTemplate } from './templates/wrangler.js'\n\ninterface GeneratorOptions {\n appName: string\n outDir: string\n kvNamespaceId?: string\n}\n\n/**\n * Generates a complete Hono Cloudflare Worker from the app schema.\n * Writes all source files to outDir.\n */\nexport function generateWorker(options: GeneratorOptions): void {\n const { appName, outDir, kvNamespaceId } = options\n\n // Create directory tree\n const dirs = [\n outDir,\n join(outDir, 'src'),\n join(outDir, 'src', 'routes'),\n join(outDir, 'src', 'storage'),\n ]\n for (const dir of dirs) mkdirSync(dir, { recursive: true })\n\n const files: [string, string][] = [\n [join(outDir, 'wrangler.toml'), wranglerTemplate(appName, kvNamespaceId)],\n [join(outDir, 'src', 'index.ts'), workerIndexTemplate(appName)],\n [join(outDir, 'src', 'routes', 'auth.ts'), authTemplate()],\n [join(outDir, 'src', 'routes', 'sync.ts'), syncTemplate()],\n [join(outDir, 'src', 'routes', 'ws.ts'), wsTemplate()],\n [join(outDir, 'src', 'routes', 'errors.ts'), errorsTemplate()],\n [join(outDir, 'src', 'routes', 'health.ts'), healthTemplate()],\n [join(outDir, 'src', 'storage', 'r2.ts'), r2StorageTemplate()],\n [join(outDir, 'src', 'storage', 'kv.ts'), kvStorageTemplate()],\n [join(outDir, 'package.json'), workerPackageJson(appName)],\n [join(outDir, 'tsconfig.json'), workerTsConfig()],\n ]\n\n for (const [path, content] of files) {\n writeFileSync(path, content, 'utf8')\n }\n\n const kvWarning = kvNamespaceId\n ? ''\n : ' - KV namespace id → set your actual KV namespace ID\\n'\n console.warn(\n '\\n⚠ Remember to replace placeholder values in wrangler.toml before deploying:\\n' +\n ' - JWT_SECRET = \"REPLACE_WITH_SECRET\" → set a strong random secret\\n' +\n kvWarning\n )\n}\n\nfunction workerPackageJson(appName: string): string {\n const name = appName.toLowerCase().replace(/[^a-z0-9-]/g, '-')\n return JSON.stringify(\n {\n name: `${name}-worker`,\n version: '1.0.0',\n type: 'module',\n scripts: {\n dev: 'wrangler dev',\n deploy: 'wrangler deploy',\n 'type-check': 'tsc --noEmit',\n },\n dependencies: {\n hono: '^4.6.0',\n },\n devDependencies: {\n '@cloudflare/workers-types': '^4.0.0',\n typescript: '^5.6.0',\n wrangler: '^3.0.0',\n },\n },\n null,\n 2,\n )\n}\n\nfunction workerTsConfig(): string {\n return JSON.stringify(\n {\n compilerOptions: {\n target: 'ES2022',\n module: 'ESNext',\n moduleResolution: 'bundler',\n lib: ['ES2022'],\n types: ['@cloudflare/workers-types'],\n strict: true,\n skipLibCheck: true,\n },\n include: ['src/**/*'],\n },\n null,\n 2,\n )\n}\n","import { generateWorker } from '../generator/index.js'\nimport type { DeployTarget } from './types.js'\n\nexport const cloudflareTarget: DeployTarget = {\n name: 'cloudflare',\n generate({ appName, outDir, kvNamespaceId }: { appName: string; outDir: string; kvNamespaceId?: string }): void {\n generateWorker({ appName, outDir, kvNamespaceId })\n },\n}\n","import { mkdirSync, writeFileSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { authTemplate } from '../generator/templates/auth.js'\nimport { syncTemplate } from '../generator/templates/sync.js'\nimport { wsTemplate } from '../generator/templates/ws.js'\nimport { errorsTemplate } from '../generator/templates/errors.js'\nimport { healthTemplate } from '../generator/templates/health.js'\nimport { r2StorageTemplate } from '../generator/templates/r2-storage.js'\nimport { kvStorageTemplate } from '../generator/templates/kv-storage.js'\nimport type { DeployTarget } from './types.js'\n\nexport const nodeTarget: DeployTarget = {\n name: 'node',\n generate({ appName, outDir }: { appName: string; outDir: string }): void {\n const dirs = [\n outDir,\n join(outDir, 'src'),\n join(outDir, 'src', 'routes'),\n join(outDir, 'src', 'storage'),\n ]\n for (const dir of dirs) mkdirSync(dir, { recursive: true })\n\n const serverEntry = nodeServerEntry(appName)\n\n const files: [string, string][] = [\n [join(outDir, 'src', 'index.ts'), serverEntry],\n [join(outDir, 'src', 'routes', 'auth.ts'), authTemplate()],\n [join(outDir, 'src', 'routes', 'sync.ts'), syncTemplate()],\n [join(outDir, 'src', 'routes', 'ws.ts'), wsTemplate()],\n [join(outDir, 'src', 'routes', 'errors.ts'), errorsTemplate()],\n [join(outDir, 'src', 'routes', 'health.ts'), healthTemplate()],\n [join(outDir, 'src', 'storage', 'r2.ts'), r2StorageTemplate()],\n [join(outDir, 'src', 'storage', 'kv.ts'), kvStorageTemplate()],\n [join(outDir, 'package.json'), nodePackageJson(appName)],\n [join(outDir, 'tsconfig.json'), nodeTsConfig()],\n ]\n\n for (const [path, content] of files) {\n writeFileSync(path, content, 'utf8')\n }\n },\n}\n\nfunction nodeServerEntry(appName: string): string {\n return `import { Hono } from 'hono'\nimport { serve } from '@hono/node-server'\nimport { createNodeWebSocket } from '@hono/node-ws'\nimport { verify } from 'hono/jwt'\nimport { auth } from './routes/auth.js'\nimport { sync } from './routes/sync.js'\nimport { health } from './routes/health.js'\n\nconst app = new Hono()\nconst { injectWebSocket, upgradeWebSocket } = createNodeWebSocket({ app })\n\n// In-memory session store for WebSocket connections (mirrors DO sessions map)\nconst sessions = new Map<WebSocket, { userId: string }>()\n\napp.route('/auth', auth)\napp.route('/sync', sync)\napp.route('/health', health)\n\napp.get('/ws', upgradeWebSocket(() => ({\n onOpen(_event, ws) {\n // session added on auth message\n },\n async onMessage(event, ws) {\n let msg: { type: string; [k: string]: unknown }\n try {\n msg = JSON.parse(event.data.toString())\n } catch {\n ws.send(JSON.stringify({ type: 'error', message: 'Invalid JSON' }))\n return\n }\n\n const session = sessions.get(ws.raw as WebSocket)\n\n if (msg.type === 'auth') {\n try {\n const jwtSecret = process.env.JWT_SECRET\n if (!jwtSecret) throw new Error('JWT_SECRET not configured')\n const payload = await verify(msg.token as string, jwtSecret) as { sub: string }\n if (!payload.sub) throw new Error('Missing sub claim')\n sessions.set(ws.raw as WebSocket, { userId: payload.sub })\n ws.send(JSON.stringify({ type: 'auth', ok: true }))\n } catch {\n ws.send(JSON.stringify({ type: 'error', message: 'Invalid token' }))\n ws.close()\n }\n } else if (!session) {\n ws.send(JSON.stringify({ type: 'error', message: 'Not authenticated' }))\n } else if (msg.type === 'push') {\n ws.send(JSON.stringify({ type: 'push', ok: true }))\n } else if (msg.type === 'pull') {\n ws.send(JSON.stringify({ type: 'pull', changes: [] }))\n }\n },\n onClose(_event, ws) {\n sessions.delete(ws.raw as WebSocket)\n },\n})))\n\nconst port = parseInt(process.env.PORT ?? '3000', 10)\nconsole.log(\\`${appName} server running on http://localhost:\\${port}\\`)\n\nconst server = serve({ fetch: app.fetch, port })\ninjectWebSocket(server)\n`\n}\n\nfunction nodePackageJson(appName: string): string {\n const name = appName.toLowerCase().replace(/[^a-z0-9-]/g, '-')\n return JSON.stringify(\n {\n name: `${name}-server`,\n version: '1.0.0',\n type: 'module',\n scripts: {\n dev: 'tsx watch src/index.ts',\n start: 'node dist/index.js',\n build: 'tsc',\n },\n dependencies: {\n hono: '^4.6.0',\n '@hono/node-server': '^1.13.0',\n '@hono/node-ws': '^1.0.0',\n },\n devDependencies: {\n typescript: '^5.6.0',\n tsx: '^4.0.0',\n '@types/node': '^22.0.0',\n },\n },\n null,\n 2,\n )\n}\n\nfunction nodeTsConfig(): string {\n return JSON.stringify(\n {\n compilerOptions: {\n target: 'ES2022',\n module: 'ESNext',\n moduleResolution: 'bundler',\n lib: ['ES2022'],\n types: ['node'],\n strict: true,\n skipLibCheck: true,\n outDir: 'dist',\n },\n include: ['src/**/*'],\n },\n null,\n 2,\n )\n}\n","import type { Command } from 'commander'\nimport { resolve } from 'node:path'\nimport { cloudflareTarget } from '../targets/cloudflare.js'\nimport { nodeTarget } from '../targets/node.js'\nimport { log } from '../utils.js'\n\nconst targets = { cloudflare: cloudflareTarget, node: nodeTarget }\n\nexport function registerBuild(program: Command): void {\n program\n .command('build')\n .description('Build the LocalKit backend bundle')\n .option('-o, --out <dir>', 'Output directory', '.offlinekit/worker')\n .option('-n, --name <name>', 'App name for the worker', 'localkit-app')\n .option('-t, --target <target>', 'Deploy target: cloudflare or node', 'cloudflare')\n .action(async (opts: { out: string; name: string; target: string }) => {\n log.bold('LocalKit Build')\n\n const target = targets[opts.target as keyof typeof targets]\n if (!target) {\n log.error(`Unknown target: ${opts.target}. Valid targets: ${Object.keys(targets).join(', ')}`)\n process.exit(1)\n }\n\n const outDir = resolve(process.cwd(), opts.out)\n log.info(`Generating ${target.name} backend to: ${outDir}`)\n\n try {\n target.generate({ appName: opts.name, outDir })\n log.success(`Backend generated at ${outDir}`)\n if (opts.target === 'node') {\n log.dim(`Run: cd ${opts.out} && npm install && npm run dev`)\n } else {\n log.dim(`Run: cd ${opts.out} && npm install && wrangler deploy`)\n }\n } catch (err) {\n log.error(`Build failed: ${err instanceof Error ? err.message : String(err)}`)\n process.exit(1)\n }\n })\n}\n","import type { Command } from 'commander'\nimport { execSync, spawnSync } from 'node:child_process'\nimport { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs'\nimport { randomBytes } from 'node:crypto'\nimport { resolve, dirname } from 'node:path'\nimport { cloudflareTarget } from '../targets/cloudflare.js'\nimport { log } from '../utils.js'\n\n// --- Types ---\n\nexport interface DeployState {\n kvNamespaceId: string\n r2BucketName: string\n workerName: string\n workerUrl?: string\n jwtSecretSet: boolean\n}\n\ninterface WranglerResult {\n stdout: string\n stderr: string\n status: number | null\n}\n\n// --- Helpers ---\n\nexport function runWrangler(\n args: string[],\n options?: { cwd?: string; input?: string },\n): WranglerResult {\n const result = spawnSync('wrangler', args, {\n encoding: 'utf8',\n stdio: ['pipe', 'pipe', 'pipe'],\n ...options,\n })\n return {\n stdout: result.stdout ?? '',\n stderr: result.stderr ?? '',\n status: result.status,\n }\n}\n\nfunction checkWrangler(): string | null {\n try {\n const result = execSync('wrangler --version', {\n encoding: 'utf8',\n stdio: ['ignore', 'pipe', 'ignore'],\n })\n return result.trim()\n } catch {\n return null\n }\n}\n\nexport function checkAuth(): boolean {\n const result = runWrangler(['whoami'])\n return result.status === 0\n}\n\nexport function createR2Bucket(name: string): void {\n log.info(`Creating R2 bucket: ${name}`)\n const result = runWrangler(['r2', 'bucket', 'create', name])\n if (result.status !== 0) {\n if (result.stderr.includes('already exists')) {\n log.info(`R2 bucket \"${name}\" already exists, continuing`)\n return\n }\n if (result.stderr.includes('R2') || result.stderr.includes('not allowed') || result.stderr.includes('not enabled')) {\n throw new Error(\n `Failed to create R2 bucket: ${result.stderr}\\n` +\n 'Hint: Enable R2 in your Cloudflare dashboard at https://dash.cloudflare.com → R2 Object Storage before deploying.',\n )\n }\n throw new Error(`Failed to create R2 bucket: ${result.stderr}`)\n }\n log.success(`R2 bucket \"${name}\" created`)\n}\n\nexport function kvNamespaceExists(id: string): boolean {\n const result = runWrangler(['kv', 'namespace', 'list', '--json'])\n if (result.status !== 0) return false\n try {\n const namespaces = JSON.parse(result.stdout) as Array<{ id: string }>\n return namespaces.some((ns) => ns.id === id)\n } catch {\n return false\n }\n}\n\nexport function createKvNamespace(name: string): string {\n log.info(`Creating KV namespace: ${name}`)\n const result = runWrangler(['kv', 'namespace', 'create', name])\n\n if (result.status === 0) {\n // Primary: parse ID from create stdout\n const match = result.stdout.match(/id\\s*=\\s*\"([a-f0-9]+)\"/)\n if (match) {\n log.success(`KV namespace \"${name}\" created with ID: ${match[1]}`)\n return match[1]\n }\n // Try JSON parsing if --json was supported\n try {\n const parsed = JSON.parse(result.stdout)\n if (parsed.id) return parsed.id\n } catch {\n // not JSON, continue\n }\n }\n\n // Fallback: namespace already exists, list and find by title\n if (result.stderr.includes('already exists') || result.status !== 0) {\n log.info(`KV namespace \"${name}\" may already exist, looking up ID...`)\n const listResult = runWrangler(['kv', 'namespace', 'list', '--json'])\n if (listResult.status === 0) {\n try {\n const namespaces = JSON.parse(listResult.stdout) as Array<{\n id: string\n title: string\n }>\n const found = namespaces.find((ns) => ns.title === name)\n if (found) {\n log.success(`Found existing KV namespace \"${name}\" with ID: ${found.id}`)\n return found.id\n }\n } catch {\n log.warn('Failed to parse KV namespace list JSON, falling back to regex')\n }\n // Last resort: regex on raw list output\n const idMatch = listResult.stdout.match(/id\\s*=\\s*\"([a-f0-9]+)\"/)\n if (idMatch) return idMatch[1]\n }\n }\n\n throw new Error(\n `Failed to create or find KV namespace \"${name}\". ` +\n `stdout: ${result.stdout}, stderr: ${result.stderr}`,\n )\n}\n\nexport function setSecret(name: string, value: string, cwd: string): void {\n log.info(`Setting secret: ${name}`)\n const result = runWrangler(['secret', 'put', name], { cwd, input: value })\n if (result.status !== 0) {\n throw new Error(`Failed to set secret ${name}: ${result.stderr}`)\n }\n log.success(`Secret \"${name}\" set`)\n}\n\nexport function readDeployState(outDir: string): DeployState | null {\n const statePath = resolve(outDir, '..', 'deploy-state.json')\n if (!existsSync(statePath)) return null\n try {\n return JSON.parse(readFileSync(statePath, 'utf8')) as DeployState\n } catch {\n return null\n }\n}\n\nexport function writeDeployState(outDir: string, state: DeployState): void {\n const statePath = resolve(outDir, '..', 'deploy-state.json')\n mkdirSync(dirname(statePath), { recursive: true })\n writeFileSync(statePath, JSON.stringify(state, null, 2), 'utf8')\n}\n\n// --- Composable Functions ---\n\nexport function provisionCloudflare(\n appName: string,\n _outDir: string,\n dryRun: boolean,\n): { kvNamespaceId: string; r2BucketName: string; workerName: string } {\n const name = appName.toLowerCase().replace(/[^a-z0-9-]/g, '-')\n const r2BucketName = `${name}-storage`\n const kvTitle = `${name}-kv`\n const workerName = `${name}-worker`\n\n // Check auth\n if (dryRun) {\n log.dim('[dry-run] Would check wrangler auth (wrangler whoami)')\n log.dim(`[dry-run] Would create R2 bucket: ${r2BucketName}`)\n log.dim(`[dry-run] Would create KV namespace: ${kvTitle}`)\n log.dim('[dry-run] Would set JWT_SECRET')\n return { kvNamespaceId: 'DRY_RUN_PLACEHOLDER', r2BucketName, workerName }\n }\n\n if (!checkAuth()) {\n log.error('Not authenticated with Cloudflare.')\n log.dim('Run `wrangler login` to authenticate, then try again.')\n process.exit(1)\n }\n log.success('Authenticated with Cloudflare')\n\n // Create R2 bucket\n createR2Bucket(r2BucketName)\n\n // Create KV namespace\n const kvNamespaceId = createKvNamespace(kvTitle)\n\n return { kvNamespaceId, r2BucketName, workerName }\n}\n\nexport function generateAndDeploy(\n appName: string,\n outDir: string,\n kvNamespaceId: string,\n env: string | undefined,\n dryRun: boolean,\n): string | undefined {\n if (dryRun) {\n log.dim(`[dry-run] Would generate worker code to: ${outDir}`)\n log.dim(`[dry-run] Would run: npm install (in ${outDir})`)\n log.dim(`[dry-run] Would run: wrangler deploy${env ? ` --env ${env}` : ''}`)\n return undefined\n }\n\n // Generate worker code with real KV namespace ID\n log.info('Generating worker code...')\n cloudflareTarget.generate({ appName, outDir, kvNamespaceId })\n log.success('Worker code generated')\n\n // npm install\n log.info('Installing dependencies...')\n const installResult = spawnSync('npm', ['install'], {\n cwd: outDir,\n encoding: 'utf8',\n stdio: ['pipe', 'pipe', 'pipe'],\n })\n if (installResult.status !== 0) {\n throw new Error(`npm install failed: ${installResult.stderr}`)\n }\n log.success('Dependencies installed')\n\n // wrangler deploy\n log.info('Deploying to Cloudflare...')\n const deployArgs = ['deploy']\n if (env) deployArgs.push('--env', env)\n\n const deployResult = spawnSync('wrangler', deployArgs, {\n cwd: outDir,\n encoding: 'utf8',\n stdio: ['pipe', 'pipe', 'pipe'],\n })\n\n if (deployResult.status !== 0) {\n throw new Error(\n `wrangler deploy failed (exit ${deployResult.status}): ${deployResult.stderr}`,\n )\n }\n\n // Parse worker URL\n const urlMatch = deployResult.stdout.match(/https:\\/\\/[^\\s]+\\.workers\\.dev/)\n const workerUrl = urlMatch ? urlMatch[0] : undefined\n if (workerUrl) {\n log.success(`Deployed to: ${workerUrl}`)\n } else {\n log.success('Deployed successfully!')\n }\n\n return workerUrl\n}\n\n// --- Command Registration ---\n\nexport function registerDeploy(program: Command): void {\n program\n .command('deploy')\n .description('Deploy the LocalKit Worker to Cloudflare via Wrangler')\n .option('-d, --dir <dir>', 'Worker output directory', '.offlinekit/worker')\n .option('-n, --name <name>', 'App name for the worker', 'localkit-app')\n .option('-e, --env <env>', 'Wrangler environment (e.g. production, staging)')\n .option('-t, --target <target>', 'Deploy target (default: cloudflare)', 'cloudflare')\n .option('--dry-run', 'Show what would happen without executing')\n .action(\n (opts: {\n dir: string\n name: string\n env?: string\n target: string\n dryRun?: boolean\n }) => {\n log.bold('LocalKit Deploy')\n\n const dryRun = opts.dryRun ?? false\n\n // Check if project has been ejected\n const serverDir = resolve(process.cwd(), 'server')\n if (existsSync(serverDir)) {\n log.info(\n 'Warning: This project has been ejected (./server/ exists).',\n )\n log.dim(\n 'You can deploy the ejected code directly with `cd server && wrangler deploy`.',\n )\n }\n\n // Validate target\n if (opts.target !== 'cloudflare') {\n log.error(\n `Deploy target \"${opts.target}\" is not supported yet. Only \"cloudflare\" is deployable.`,\n )\n log.dim(\n 'For Node.js targets, run `npx mpb-localkit build --target node` then deploy the output manually.',\n )\n process.exit(1)\n }\n\n // Check wrangler\n const version = checkWrangler()\n if (!version) {\n log.error('wrangler is not installed or not in PATH.')\n log.dim('Install it with: npm install -g wrangler')\n process.exit(1)\n }\n log.success(`wrangler ${version}`)\n\n const outDir = resolve(process.cwd(), opts.dir)\n const appName = opts.name\n\n // Read existing deploy state\n const existingState = readDeployState(outDir)\n\n let kvNamespaceId: string\n let r2BucketName: string\n let workerName: string\n if (existingState?.kvNamespaceId && existingState?.r2BucketName) {\n // Subsequent deploy -- validate resources still exist\n log.info('Found existing deploy state, validating resources...')\n r2BucketName = existingState.r2BucketName\n workerName = existingState.workerName\n\n if (dryRun) {\n log.dim('[dry-run] Would validate KV namespace exists')\n kvNamespaceId = existingState.kvNamespaceId\n } else if (kvNamespaceExists(existingState.kvNamespaceId)) {\n log.success('KV namespace validated')\n kvNamespaceId = existingState.kvNamespaceId\n } else {\n log.warn('KV namespace no longer exists, re-creating...')\n const name = appName.toLowerCase().replace(/[^a-z0-9-]/g, '-')\n kvNamespaceId = createKvNamespace(`${name}-kv`)\n writeDeployState(outDir, {\n ...existingState,\n kvNamespaceId,\n })\n log.success('Deploy state updated with new KV namespace ID')\n }\n } else {\n // First deploy -- provision resources\n const provisioned = provisionCloudflare(appName, outDir, dryRun)\n kvNamespaceId = provisioned.kvNamespaceId\n r2BucketName = provisioned.r2BucketName\n workerName = provisioned.workerName\n\n // Save provisioned state (jwtSecretSet: false until secret is actually set)\n if (!dryRun) {\n writeDeployState(outDir, {\n kvNamespaceId,\n r2BucketName,\n workerName,\n jwtSecretSet: false,\n })\n log.success('Deploy state saved to .offlinekit/deploy-state.json')\n }\n }\n\n // Pre-flight: ensure we never deploy with a placeholder KV namespace ID\n if (kvNamespaceId === 'REPLACE_WITH_KV_NAMESPACE_ID' || !kvNamespaceId) {\n log.error(\n 'KV namespace ID is missing or still a placeholder. ' +\n 'Run `mpb-localkit deploy` (not `wrangler deploy` directly) to auto-provision resources, ' +\n 'or create one manually: wrangler kv namespace create KV',\n )\n process.exit(1)\n }\n\n const alreadyHasSecret = existingState?.jwtSecretSet ?? false\n\n // Generate code and deploy (this creates wrangler.toml in outDir)\n let workerUrl: string | undefined\n try {\n workerUrl = generateAndDeploy(appName, outDir, kvNamespaceId, opts.env, dryRun)\n } catch (err) {\n log.error(`Deploy failed: ${err instanceof Error ? err.message : String(err)}`)\n process.exit(1)\n }\n\n if (dryRun) {\n if (!alreadyHasSecret) {\n log.dim('[dry-run] Would set JWT_SECRET (first deploy only)')\n }\n log.bold('Dry run complete. No changes were made.')\n return\n }\n\n // Set JWT_SECRET now that wrangler.toml exists in outDir\n let jwtSecretSet = alreadyHasSecret\n if (!jwtSecretSet) {\n try {\n setSecret('JWT_SECRET', randomBytes(32).toString('hex'), outDir)\n log.success('JWT_SECRET set')\n jwtSecretSet = true\n } catch (err) {\n log.warn(`Could not set JWT_SECRET: ${err instanceof Error ? err.message : String(err)}`)\n log.dim('Set it manually: wrangler secret put JWT_SECRET')\n }\n }\n\n // Persist final state with workerUrl\n writeDeployState(outDir, { kvNamespaceId, r2BucketName, workerName, workerUrl, jwtSecretSet })\n\n // Optionally update .env\n if (workerUrl) {\n const envPath = resolve(process.cwd(), '.env')\n if (existsSync(envPath)) {\n let envContent = readFileSync(envPath, 'utf8')\n if (envContent.includes('VITE_SYNC_URL=')) {\n envContent = envContent.replace(/VITE_SYNC_URL=.*/, `VITE_SYNC_URL=${workerUrl}`)\n } else {\n envContent += `\\nVITE_SYNC_URL=${workerUrl}\\n`\n }\n writeFileSync(envPath, envContent, 'utf8')\n log.info(`Updated .env with VITE_SYNC_URL=${workerUrl}`)\n }\n }\n },\n )\n}\n","import type { Command } from 'commander'\nimport { existsSync } from 'node:fs'\nimport { resolve } from 'node:path'\nimport { cloudflareTarget } from '../targets/cloudflare.js'\nimport { nodeTarget } from '../targets/node.js'\nimport type { DeployTarget } from '../targets/types.js'\nimport { log } from '../utils.js'\n\nconst targets: Record<string, DeployTarget> = {\n cloudflare: cloudflareTarget,\n node: nodeTarget,\n}\n\nexport function registerEject(program: Command): void {\n program\n .command('eject')\n .description('Eject generated Worker code into ./server/ for manual customization')\n .option('-o, --out <dir>', 'Output directory for ejected code', 'server')\n .option('-n, --name <name>', 'App name', 'localkit-app')\n .option('-t, --target <target>', 'Deploy target (cloudflare, node)', 'cloudflare')\n .action((opts: { out: string; name: string; target: string }) => {\n log.bold('LocalKit Eject')\n\n const target = targets[opts.target]\n if (!target) {\n log.error(`Unknown target: \"${opts.target}\"`)\n log.dim(`Available targets: ${Object.keys(targets).join(', ')}`)\n process.exit(1)\n }\n\n const outDir = resolve(process.cwd(), opts.out)\n\n if (existsSync(outDir)) {\n log.error(`Directory already exists: ${outDir}`)\n log.dim('Remove it or choose a different output directory with --out.')\n process.exit(1)\n }\n\n log.info(`Ejecting ${opts.target} code to: ${outDir}`)\n\n try {\n target.generate({ appName: opts.name, outDir })\n log.success(`Ejected to ./${opts.out}/`)\n\n if (opts.target === 'node') {\n log.dim('You can now customize and deploy your Node.js server.')\n log.dim('')\n log.dim('Next steps:')\n log.dim(` cd ${opts.out}`)\n log.dim(' npm install')\n log.dim(' npm run dev')\n log.dim('')\n log.dim('To run in production: npm start')\n } else {\n log.dim('You can now customize and deploy with `wrangler deploy`.')\n log.dim('')\n log.dim('Next steps:')\n log.dim(` cd ${opts.out}`)\n log.dim(' npm install')\n log.dim(' wrangler deploy')\n log.dim('')\n log.dim('Note: Running `npx mpb-localkit deploy` will warn that code has been ejected.')\n }\n } catch (err) {\n log.error(`Eject failed: ${err instanceof Error ? err.message : String(err)}`)\n process.exit(1)\n }\n })\n}\n","#!/usr/bin/env node\nimport { Command } from 'commander'\nimport { createRequire } from 'node:module'\nimport { registerDev } from './commands/dev.js'\nimport { registerBuild } from './commands/build.js'\nimport { registerDeploy } from './commands/deploy.js'\nimport { registerEject } from './commands/eject.js'\n\nconst require = createRequire(import.meta.url)\nconst pkg = require('../../package.json') as { version: string; description: string }\n\nconst program = new Command()\n\nprogram\n .name('mpb-localkit')\n .description(pkg.description)\n .version(pkg.version, '-v, --version', 'Print the current version')\n\nregisterDev(program)\nregisterBuild(program)\nregisterDeploy(program)\nregisterEject(program)\n\nprogram.parse(process.argv)\n"]}
|
package/dist/core/index.js
CHANGED
|
@@ -960,6 +960,22 @@ async function hashPassword(password, _email) {
|
|
|
960
960
|
const hashHex = await deriveKey(password, salt);
|
|
961
961
|
return `${toHex(salt)}:${hashHex}`;
|
|
962
962
|
}
|
|
963
|
+
async function verifyPassword(password, storedHash) {
|
|
964
|
+
const colonIndex = storedHash.indexOf(":");
|
|
965
|
+
if (colonIndex === -1) return false;
|
|
966
|
+
const saltHex = storedHash.slice(0, colonIndex);
|
|
967
|
+
const hashHex = storedHash.slice(colonIndex + 1);
|
|
968
|
+
const saltBytes = saltHex.match(/.{2}/g);
|
|
969
|
+
if (!saltBytes || saltBytes.length !== SALT_LENGTH) return false;
|
|
970
|
+
const salt = new Uint8Array(saltBytes.map((b) => parseInt(b, 16)));
|
|
971
|
+
const derived = await deriveKey(password, salt);
|
|
972
|
+
if (derived.length !== hashHex.length) return false;
|
|
973
|
+
let result = 0;
|
|
974
|
+
for (let i = 0; i < derived.length; i++) {
|
|
975
|
+
result |= derived.charCodeAt(i) ^ hashHex.charCodeAt(i);
|
|
976
|
+
}
|
|
977
|
+
return result === 0;
|
|
978
|
+
}
|
|
963
979
|
|
|
964
980
|
// src/core/auth/session.ts
|
|
965
981
|
var TOKEN_KEY = "__offlinekit_token";
|
|
@@ -1018,6 +1034,20 @@ var EmailPasswordAuth = class {
|
|
|
1018
1034
|
async signIn(credentials) {
|
|
1019
1035
|
if (!credentials.email) throw new Error("Email is required");
|
|
1020
1036
|
if (!credentials.password) throw new Error("Password is required");
|
|
1037
|
+
const hashRes = await fetch(`${this.config.endpoint}/auth/hash`, {
|
|
1038
|
+
method: "POST",
|
|
1039
|
+
headers: { "Content-Type": "application/json" },
|
|
1040
|
+
body: JSON.stringify({ email: credentials.email })
|
|
1041
|
+
});
|
|
1042
|
+
if (hashRes.ok) {
|
|
1043
|
+
const { passwordHash: passwordHash2 } = await hashRes.json();
|
|
1044
|
+
if (passwordHash2) {
|
|
1045
|
+
const valid = await verifyPassword(credentials.password, passwordHash2);
|
|
1046
|
+
if (!valid) {
|
|
1047
|
+
throw new Error("Invalid credentials");
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
}
|
|
1021
1051
|
const passwordHash = await hashPassword(credentials.password);
|
|
1022
1052
|
const res = await fetch(`${this.config.endpoint}/auth/signin`, {
|
|
1023
1053
|
method: "POST",
|
package/dist/core/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/core/schema/collection.ts","../../src/core/storage/indexeddb.ts","../../src/core/storage/memory.ts","../../src/core/storage/id.ts","../../src/core/storage/encrypted.ts","../../src/core/storage/key-rotation.ts","../../src/core/storage/migrate-encrypted.ts","../../src/core/sync/conflict.ts","../../src/core/sync/transport.ts","../../src/core/sync/ws-transport.ts","../../src/core/sync/auto-transport.ts","../../src/core/sync/engine.ts","../../src/core/sync/triggers.ts","../../src/core/auth/pbkdf2.ts","../../src/core/auth/session.ts","../../src/core/auth/adapter.ts","../../src/core/auth/better-auth-adapter.ts","../../src/core/auth/offline-adapter.ts","../../src/core/errors/tracker.ts","../../src/core/errors/index.ts","../../src/core/storage/query.ts","../../src/core/client/collection.ts","../../src/core/client/events.ts","../../src/core/client/app.ts","../../src/core/query.ts"],"names":["collection","db","uuidv7","isOffline"],"mappings":"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","file":"index.js","sourcesContent":["import { type ZodObject, type ZodRawShape } from 'zod'\nimport type { CollectionDescriptor, CollectionOptions } from './types.js'\n\n/**\n * Wraps a Zod schema to create a typed collection descriptor.\n * TypeScript infers the document type from the schema automatically.\n *\n * @example\n * const brews = collection(z.object({ style: z.string(), og: z.number() }))\n * // brews._inferredType is { style: string; og: number }\n */\nexport function collection<TShape extends ZodRawShape>(\n schema: ZodObject<TShape>,\n options?: CollectionOptions,\n): CollectionDescriptor<TShape> {\n return {\n schema,\n collectionName: '',\n version: options?.version,\n migrate: options?.migrate,\n } as CollectionDescriptor<TShape>\n}\n","import { openDB, IDBPDatabase } from 'idb'\nimport type { Doc } from '../schema/types.js'\nimport type { Filter, Change, StorageAdapter } from './types.js'\n\nconst CHANGES_INDEX = '_updatedAt'\n\nexport class IndexedDBAdapter implements StorageAdapter {\n private dbName: string\n private db: IDBPDatabase | null = null\n private _ensureLock: Promise<void> = Promise.resolve()\n\n constructor(appName: string) {\n this.dbName = `offlinekit-${appName}`\n }\n\n private async getDb(): Promise<IDBPDatabase> {\n if (this.db) return this.db\n this.db = await openDB(this.dbName, 1, {\n upgrade(_db) {\n // Stores are created dynamically per collection on first use\n },\n })\n return this.db\n }\n\n private async ensureStore(collection: string): Promise<IDBPDatabase> {\n // Capture and replace the lock synchronously before any await.\n // This serializes concurrent callers: each waits for its predecessor.\n const prev = this._ensureLock\n let release: () => void\n this._ensureLock = new Promise<void>(r => { release = r })\n\n await prev\n\n try {\n let db = await this.getDb()\n if (db.objectStoreNames.contains(collection)) return db\n\n const version = db.version + 1\n db.close()\n this.db = null\n db = await openDB(this.dbName, version, {\n upgrade(db) {\n if (!db.objectStoreNames.contains(collection)) {\n const store = db.createObjectStore(collection, { keyPath: '_id' })\n store.createIndex(CHANGES_INDEX, '_updatedAt')\n }\n },\n })\n this.db = db\n return db\n } finally {\n release!()\n }\n }\n\n async get(collection: string, id: string): Promise<Doc | null> {\n const db = await this.ensureStore(collection)\n const doc = await db.get(collection, id)\n if (!doc || doc._deleted) return null\n return doc as Doc\n }\n\n async getMany(collection: string, filter?: Filter): Promise<Doc[]> {\n const db = await this.ensureStore(collection)\n const all = await db.getAll(collection) as Doc[]\n return all.filter(doc => {\n if (doc._deleted) return false\n if (!filter) return true\n return Object.entries(filter).every(([k, v]) => Reflect.get(doc as object, k) === v)\n })\n }\n\n async put(collection: string, id: string, doc: Doc): Promise<void> {\n const db = await this.ensureStore(collection)\n await db.put(collection, { ...doc, _id: id, _collection: collection })\n }\n\n async delete(collection: string, id: string): Promise<void> {\n const db = await this.ensureStore(collection)\n const existing = await db.get(collection, id) as Doc | undefined\n if (!existing) return\n await db.put(collection, {\n ...existing,\n _deleted: true,\n _updatedAt: Date.now(),\n })\n }\n\n async getChangesSince(timestamp: number): Promise<Change[]> {\n const db = await this.getDb()\n const results: Change[] = []\n for (const storeName of Array.from(db.objectStoreNames)) {\n if (!db.objectStoreNames.contains(storeName)) continue\n const tx = db.transaction(storeName, 'readonly')\n const store = tx.objectStore(storeName)\n const index = store.index(CHANGES_INDEX)\n const range = IDBKeyRange.lowerBound(timestamp, true)\n const docs = await index.getAll(range) as Doc[]\n for (const doc of docs) {\n results.push({\n collection: storeName,\n id: doc._id,\n doc,\n updatedAt: doc._updatedAt,\n deleted: doc._deleted,\n })\n }\n }\n return results\n }\n}\n","import type { Doc } from '../schema/types.js'\nimport type { Filter, Change, StorageAdapter } from './types.js'\n\nexport class MemoryAdapter implements StorageAdapter {\n private store = new Map<string, Map<string, Doc>>()\n\n private getCollection(collection: string): Map<string, Doc> {\n if (!this.store.has(collection)) {\n this.store.set(collection, new Map())\n }\n return this.store.get(collection)!\n }\n\n async get(collection: string, id: string): Promise<Doc | null> {\n const doc = this.getCollection(collection).get(id)\n if (!doc || doc._deleted) return null\n return { ...doc }\n }\n\n async getRaw(collection: string, id: string): Promise<Doc | null> {\n const doc = this.getCollection(collection).get(id)\n if (!doc) return null\n return { ...doc }\n }\n\n async getMany(collection: string, filter?: Filter): Promise<Doc[]> {\n const col = this.getCollection(collection)\n return Array.from(col.values()).filter(doc => {\n if (doc._deleted) return false\n if (!filter) return true\n return Object.entries(filter).every(([k, v]) => (doc as unknown as Record<string, unknown>)[k] === v)\n }).map(doc => ({ ...doc }))\n }\n\n async put(collection: string, id: string, doc: Doc): Promise<void> {\n this.getCollection(collection).set(id, { ...doc, _id: id, _collection: collection })\n }\n\n async delete(collection: string, id: string): Promise<void> {\n const col = this.getCollection(collection)\n const existing = col.get(id)\n if (!existing) return\n col.set(id, { ...existing, _deleted: true, _updatedAt: Date.now() })\n }\n\n async getChangesSince(timestamp: number): Promise<Change[]> {\n const results: Change[] = []\n for (const [collection, col] of this.store.entries()) {\n for (const doc of col.values()) {\n if (doc._updatedAt > timestamp) {\n results.push({\n collection,\n id: doc._id,\n doc: { ...doc },\n updatedAt: doc._updatedAt,\n deleted: doc._deleted,\n })\n }\n }\n }\n return results\n }\n}\n","import { v7 as uuidv7 } from 'uuid'\n\nexport function generateId(): string {\n return uuidv7()\n}\n","import type { Doc } from '../schema/types.js'\nimport type { Filter, Change, StorageAdapter } from './types.js'\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\n/** A raw CryptoKey or a password+salt pair for PBKDF2 / AES-KW derivation. */\nexport type KeySpec = CryptoKey | { password: string; salt: string }\n\n/** Multi-version keychain configuration for key rotation support. */\nexport interface KeychainConfig {\n keys: Record<number, KeySpec>\n activeVersion: number\n}\n\n/** Key-wrapping options (Mode 3). */\nexport interface WrapConfig {\n /** Base64-encoded wrapped data key from a previous session. */\n wrapped?: string\n /** Called once with the base64-encoded wrapped data key on first use. */\n onKeyWrapped?: (wrappedKey: string) => void\n}\n\n/**\n * Encryption configuration.\n *\n * - Mode 1 `{ key: { password, salt } }` — PBKDF2-SHA256 key derivation\n * - Mode 2 `{ key: CryptoKey }` — raw key used directly\n * - Mode 3 `{ key: { password, salt }, wrap: { ... } }` — AES-KW key wrapping\n * - Keychain mode `{ keychain: { keys, activeVersion } }` — multi-version key rotation\n */\nexport interface EncryptionConfig {\n key?: KeySpec\n keychain?: KeychainConfig\n wrap?: WrapConfig\n /** PBKDF2 iteration count (default: 600 000). */\n iterations?: number\n}\n\n// ─── Internal helpers ─────────────────────────────────────────────────────────\n\nconst METADATA_FIELDS = new Set(['_id', '_collection', '_updatedAt', '_deleted', '_schemaVersion'])\nconst ENCRYPTED_FIELDS = new Set(['_encrypted', '_iv', '_keyVersion'])\n\nexport function toBase64(buf: ArrayBuffer | Uint8Array): string {\n const bytes = buf instanceof Uint8Array ? buf : new Uint8Array(buf)\n let binary = ''\n for (let i = 0; i < bytes.length; i++) binary += String.fromCharCode(bytes[i])\n return btoa(binary)\n}\n\nexport function fromBase64(s: string): Uint8Array<ArrayBuffer> {\n const binary = atob(s)\n const bytes = new Uint8Array(binary.length)\n for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i)\n return bytes as Uint8Array<ArrayBuffer>\n}\n\n/** Cast TextEncoder output to the ArrayBuffer-backed variant that Web Crypto requires. */\nexport function encode(s: string): Uint8Array<ArrayBuffer> {\n return new TextEncoder().encode(s) as unknown as Uint8Array<ArrayBuffer>\n}\n\nasync function deriveAesGcmKey(\n password: string,\n salt: string,\n iterations: number,\n extractable = false\n): Promise<CryptoKey> {\n const keyMaterial = await crypto.subtle.importKey('raw', encode(password), 'PBKDF2', false, [\n 'deriveBits',\n 'deriveKey',\n ])\n return crypto.subtle.deriveKey(\n { name: 'PBKDF2', salt: encode(salt), iterations, hash: 'SHA-256' },\n keyMaterial,\n { name: 'AES-GCM', length: 256 },\n extractable,\n ['encrypt', 'decrypt']\n )\n}\n\nexport async function deriveAesKwKey(password: string, salt: string, iterations: number): Promise<CryptoKey> {\n const keyMaterial = await crypto.subtle.importKey('raw', encode(password), 'PBKDF2', false, [\n 'deriveBits',\n 'deriveKey',\n ])\n return crypto.subtle.deriveKey(\n { name: 'PBKDF2', salt: encode(salt), iterations, hash: 'SHA-256' },\n keyMaterial,\n { name: 'AES-KW', length: 256 },\n false,\n ['wrapKey', 'unwrapKey']\n )\n}\n\nasync function verifySentinel(key: CryptoKey): Promise<void> {\n const sentinel = encode('offlinekit-sentinel')\n const iv = crypto.getRandomValues(new Uint8Array(12))\n const ciphertext = await crypto.subtle.encrypt({ name: 'AES-GCM', iv }, key, sentinel)\n const plaintext = await crypto.subtle\n .decrypt({ name: 'AES-GCM', iv }, key, ciphertext)\n .catch(() => null)\n if (!plaintext || new TextDecoder().decode(plaintext) !== 'offlinekit-sentinel') {\n throw new Error('EncryptedStorageAdapter: key verification failed — wrong password or key')\n }\n}\n\n/** Resolve a single KeySpec to a CryptoKey using Mode 1/2/3 logic. */\nasync function resolveKeySpec(spec: KeySpec, iterations: number, wrap?: WrapConfig): Promise<CryptoKey> {\n if (spec instanceof CryptoKey) {\n // Mode 2 — use the provided key directly\n return spec\n } else if (wrap) {\n // Mode 3 — AES-KW: wrapping key is derived from password + salt\n const { password, salt } = spec\n const wrappingKey = await deriveAesKwKey(password, salt, iterations)\n\n if (wrap.wrapped) {\n // Unwrap stored key blob\n return crypto.subtle.unwrapKey(\n 'raw',\n fromBase64(wrap.wrapped),\n wrappingKey,\n 'AES-KW',\n { name: 'AES-GCM', length: 256 },\n false,\n ['encrypt', 'decrypt']\n )\n } else {\n // Generate a fresh random data key, wrap it for caller storage, then harden\n const extractableKey = await crypto.subtle.generateKey(\n { name: 'AES-GCM', length: 256 },\n true /* must be extractable to wrap */,\n ['encrypt', 'decrypt']\n )\n const wrappedBuf = await crypto.subtle.wrapKey('raw', extractableKey, wrappingKey, 'AES-KW')\n wrap.onKeyWrapped?.(toBase64(wrappedBuf))\n\n // Re-import as non-extractable to harden against XSS\n const rawKeyBuf = await crypto.subtle.exportKey('raw', extractableKey)\n return crypto.subtle.importKey(\n 'raw',\n rawKeyBuf,\n { name: 'AES-GCM', length: 256 },\n false,\n ['encrypt', 'decrypt']\n )\n }\n } else {\n // Mode 1 — PBKDF2: data key is derived directly from password + salt\n const { password, salt } = spec\n return deriveAesGcmKey(password, salt, iterations)\n }\n}\n\n// ─── Factory ──────────────────────────────────────────────────────────────────\n\n/**\n * Wraps any StorageAdapter with transparent AES-GCM 256-bit encryption.\n *\n * @throws If `inner` is already an EncryptedStorageAdapter (double-encryption guard).\n * @throws If key verification fails (wrong password / corrupted wrapped key).\n */\nexport async function encrypted(\n inner: StorageAdapter,\n config: EncryptionConfig\n): Promise<EncryptedStorageAdapter> {\n if (inner instanceof EncryptedStorageAdapter) {\n throw new Error('EncryptedStorageAdapter: double-encryption is not allowed')\n }\n\n if (!config.key && !config.keychain) {\n throw new Error('EncryptedStorageAdapter: either key or keychain must be provided')\n }\n\n const iterations = config.iterations ?? 600_000\n let keychain: Map<number, CryptoKey>\n let activeVersion: number\n\n if (config.keychain) {\n const { keys, activeVersion: av } = config.keychain\n if (!(av in keys)) {\n throw new Error(`EncryptedStorageAdapter: keychain.activeVersion ${av} not found in keychain.keys`)\n }\n activeVersion = av\n keychain = new Map<number, CryptoKey>()\n for (const [ver, spec] of Object.entries(keys)) {\n const version = Number(ver)\n // Wrap config only applies to single-key mode; keychain keys use Mode 1 or Mode 2\n const resolved = await resolveKeySpec(spec, iterations)\n keychain.set(version, resolved)\n }\n } else {\n // Single-key mode: treat as keychain with version 1\n const resolved = await resolveKeySpec(config.key!, iterations, config.wrap)\n activeVersion = 1\n keychain = new Map([[1, resolved]])\n }\n\n await verifySentinel(keychain.get(activeVersion)!)\n return new EncryptedStorageAdapter(inner, keychain, activeVersion)\n}\n\n// ─── Adapter ──────────────────────────────────────────────────────────────────\n\nexport class EncryptedStorageAdapter implements StorageAdapter {\n constructor(\n private readonly inner: StorageAdapter,\n private readonly keychain: Map<number, CryptoKey>,\n private readonly activeVersion: number\n ) {}\n\n private isEncryptedDoc(doc: Doc): boolean {\n return '_encrypted' in doc && '_iv' in doc\n }\n\n private async encryptDoc(doc: Doc): Promise<Doc> {\n const raw = doc as Record<string, unknown>\n\n const metadata: Record<string, unknown> = {}\n for (const field of METADATA_FIELDS) {\n if (field in raw) metadata[field] = raw[field]\n }\n\n const userFields: Record<string, unknown> = {}\n for (const [k, v] of Object.entries(raw)) {\n if (!METADATA_FIELDS.has(k) && !ENCRYPTED_FIELDS.has(k)) {\n userFields[k] = v\n }\n }\n\n const iv = crypto.getRandomValues(new Uint8Array(12))\n const aad = encode(JSON.stringify({ _id: doc._id, _collection: doc._collection }))\n const plaintext = encode(JSON.stringify(userFields))\n\n const ciphertext = await crypto.subtle.encrypt(\n { name: 'AES-GCM', iv, additionalData: aad },\n this.keychain.get(this.activeVersion)!,\n plaintext\n )\n\n return {\n ...metadata,\n _encrypted: toBase64(ciphertext),\n _iv: toBase64(iv),\n _keyVersion: this.activeVersion,\n } as unknown as Doc\n }\n\n private async decryptDoc(doc: Doc): Promise<Doc> {\n if (!this.isEncryptedDoc(doc)) return doc // migration: pass through unencrypted docs\n\n const raw = doc as Record<string, unknown>\n const version = typeof raw._keyVersion === 'number' ? raw._keyVersion : 1\n const key = this.keychain.get(version)\n if (!key) {\n throw new Error(`EncryptedStorageAdapter: no key found for _keyVersion ${version}`)\n }\n\n const aad = encode(JSON.stringify({ _id: doc._id, _collection: doc._collection }))\n const iv = fromBase64(raw._iv as string)\n const ciphertext = fromBase64(raw._encrypted as string)\n\n const plaintext = await crypto.subtle.decrypt(\n { name: 'AES-GCM', iv, additionalData: aad },\n key,\n ciphertext\n )\n\n const userFields = JSON.parse(new TextDecoder().decode(plaintext)) as Record<string, unknown>\n\n const metadata: Record<string, unknown> = {}\n for (const field of METADATA_FIELDS) {\n if (field in raw) metadata[field] = raw[field]\n }\n\n return { ...metadata, ...userFields } as Doc\n }\n\n async get(collection: string, id: string): Promise<Doc | null> {\n const doc = await this.inner.get(collection, id)\n if (!doc) return null\n return this.decryptDoc(doc)\n }\n\n async getRaw(collection: string, id: string): Promise<Doc | null> {\n const fn = this.inner.getRaw?.bind(this.inner) ?? this.inner.get.bind(this.inner)\n const doc = await fn(collection, id)\n if (!doc) return null\n return this.decryptDoc(doc)\n }\n\n async getMany(collection: string, filter?: Filter): Promise<Doc[]> {\n // Fetch all without filter — decrypt first, then apply filter on plaintext\n const docs = await this.inner.getMany(collection)\n const decrypted = await Promise.all(docs.map(doc => this.decryptDoc(doc)))\n if (!filter) return decrypted\n return decrypted.filter(doc =>\n Object.entries(filter).every(([k, v]) => (doc as Record<string, unknown>)[k] === v)\n )\n }\n\n async put(collection: string, id: string, doc: Doc): Promise<void> {\n // Docs arriving from sync pull are already encrypted blobs — pass through unchanged\n if (this.isEncryptedDoc(doc)) {\n return this.inner.put(collection, id, doc)\n }\n const encryptedDoc = await this.encryptDoc(doc)\n return this.inner.put(collection, id, encryptedDoc)\n }\n\n async delete(collection: string, id: string): Promise<void> {\n return this.inner.delete(collection, id)\n }\n\n /** E2E: encrypted blobs travel to the server as-is — no decryption here. */\n async getChangesSince(timestamp: number): Promise<Change[]> {\n return this.inner.getChangesSince(timestamp)\n }\n\n /** Returns raw encrypted storage representation. Do not use in production data flows. */\n async getEncrypted(collection: string, id: string): Promise<Doc | null> {\n return this.inner.get(collection, id)\n }\n}\n","import type { StorageAdapter } from './types.js'\nimport type { EncryptedStorageAdapter } from './encrypted.js'\nimport { toBase64, fromBase64, deriveAesKwKey } from './encrypted.js'\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\nexport interface ReEncryptResult {\n total: number\n reEncrypted: number\n skipped: number\n errors: string[]\n}\n\n// ─── reEncryptAll ─────────────────────────────────────────────────────────────\n\nconst BATCH_SIZE = 100\n\n/**\n * Re-encrypts all documents whose `_keyVersion` differs from `activeVersion`.\n *\n * The adapter must have a keychain containing both the old key(s) and the new\n * active key so it can decrypt with the old key and re-encrypt with the active one.\n *\n * This operation is resumable: documents already at `activeVersion` are skipped,\n * so a second run after an interruption picks up where it left off.\n */\nexport async function reEncryptAll(\n adapter: EncryptedStorageAdapter,\n innerStorage: StorageAdapter,\n activeVersion: number\n): Promise<ReEncryptResult> {\n const result: ReEncryptResult = { total: 0, reEncrypted: 0, skipped: 0, errors: [] }\n\n // Fetch all raw (encrypted) change records from underlying storage\n const changes = await innerStorage.getChangesSince(0)\n result.total = changes.length\n\n // Process in batches to limit memory pressure\n for (let i = 0; i < changes.length; i += BATCH_SIZE) {\n const batch = changes.slice(i, i + BATCH_SIZE)\n\n await Promise.all(\n batch.map(async change => {\n const raw = change.doc as Record<string, unknown>\n const keyVersion = raw._keyVersion as number | undefined\n\n // Skip docs already at the active version (resumability cursor)\n if (keyVersion === activeVersion) {\n result.skipped++\n return\n }\n\n try {\n // Decrypt with old key (adapter picks key by _keyVersion)\n const decrypted = await adapter.get(change.collection, change.id)\n if (!decrypted) {\n result.skipped++\n return\n }\n\n // Re-encrypt with active key (adapter.put always uses activeVersion)\n await adapter.put(change.collection, change.id, decrypted)\n result.reEncrypted++\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n result.errors.push(`${change.collection}/${change.id}: ${msg}`)\n }\n })\n )\n }\n\n return result\n}\n\n// ─── rewrapKey ────────────────────────────────────────────────────────────────\n\n/**\n * Re-wraps a data key under a new password without re-encrypting any documents\n * (Mode 3 — AES-KW).\n *\n * Unwraps the stored wrapped key using a key derived from `oldPassword`, then\n * re-wraps it using a key derived from `newPassword`. The salt is unchanged,\n * so documents are unaffected.\n *\n * @returns New base64-encoded wrapped key to persist in place of the old one.\n */\nexport async function rewrapKey(\n oldPassword: string,\n newPassword: string,\n wrappedKey: string,\n salt: string,\n iterations = 600_000\n): Promise<string> {\n const oldWrappingKey = await deriveAesKwKey(oldPassword, salt, iterations)\n const newWrappingKey = await deriveAesKwKey(newPassword, salt, iterations)\n\n // Unwrap the data key — must be extractable so it can be re-wrapped\n const dataKey = await crypto.subtle.unwrapKey(\n 'raw',\n fromBase64(wrappedKey),\n oldWrappingKey,\n 'AES-KW',\n { name: 'AES-GCM', length: 256 },\n true /* extractable */,\n ['encrypt', 'decrypt']\n )\n\n // Re-wrap with the new wrapping key\n const newWrappedBuf = await crypto.subtle.wrapKey('raw', dataKey, newWrappingKey, 'AES-KW')\n return toBase64(newWrappedBuf)\n}\n","import type { StorageAdapter } from './types.js'\nimport type { EncryptedStorageAdapter } from './encrypted.js'\n\nexport interface MigrationResult {\n total: number\n encrypted: number\n skipped: number\n errors: string[]\n}\n\n/**\n * Migrates all plaintext documents from `storage` into `encryptedStorage`.\n *\n * Idempotent: documents that already have `_encrypted` and `_iv` fields are skipped.\n * Handles mixed state: only plaintext documents are encrypted.\n */\nexport async function migrateToEncrypted(\n storage: StorageAdapter,\n encryptedStorage: EncryptedStorageAdapter\n): Promise<MigrationResult> {\n const changes = await storage.getChangesSince(0)\n\n const result: MigrationResult = {\n total: changes.length,\n encrypted: 0,\n skipped: 0,\n errors: [],\n }\n\n for (const change of changes) {\n const { collection, id, doc } = change\n\n if ('_encrypted' in doc && '_iv' in doc) {\n result.skipped++\n continue\n }\n\n try {\n await encryptedStorage.put(collection, id, doc)\n result.encrypted++\n } catch (err) {\n result.errors.push(\n `${collection}/${id}: ${err instanceof Error ? err.message : String(err)}`\n )\n }\n }\n\n return result\n}\n","import type { Doc } from '../schema/types.js'\n\n/**\n * Last-Write-Wins conflict resolver.\n * Compares _updatedAt timestamps; highest wins.\n * Sufficient for single-user, multi-device scenarios.\n */\nexport function resolveConflict(local: Doc, remote: Doc): Doc {\n return remote._updatedAt >= local._updatedAt ? remote : local\n}\n\n/** Always keeps the local version. */\nexport function localWins(local: Doc, _remote: Doc): Doc {\n return local\n}\n\n/** Always keeps the remote version. */\nexport function remoteWins(_local: Doc, remote: Doc): Doc {\n return remote\n}\n","import type { Doc } from '../schema/types.js'\nimport type { SyncTransport, PushPayload, PullPayload } from './types.js'\n\nexport class HttpTransport implements SyncTransport {\n private token: string | null = null\n\n constructor(private readonly endpoint: string) {}\n\n setToken(token: string | null): void {\n this.token = token\n }\n\n async push(payload: PushPayload): Promise<number> {\n const response = await this.fetchWithRetry(`${this.endpoint}/sync/push`, {\n method: 'POST',\n headers: this.buildHeaders(),\n body: JSON.stringify(payload),\n })\n if (!response.ok) {\n throw new Error(`Push failed: ${response.status} ${response.statusText}`)\n }\n return payload.changes.length\n }\n\n async pull(payload: PullPayload): Promise<Doc[]> {\n const response = await this.fetchWithRetry(`${this.endpoint}/sync/pull?since=${payload.since}`, {\n headers: this.buildHeaders(),\n })\n if (!response.ok) {\n throw new Error(`Pull failed: ${response.status} ${response.statusText}`)\n }\n const { changes } = (await response.json()) as { changes: Doc[] }\n return changes\n }\n\n destroy(): void {}\n\n private async fetchWithRetry(url: string, init: RequestInit, retries = 3): Promise<Response> {\n for (let attempt = 0; attempt <= retries; attempt++) {\n try {\n const res = await fetch(url, init)\n if (res.ok || res.status < 500) return res\n if (attempt === retries) return res\n } catch (err) {\n if (attempt === retries) throw err\n }\n const delay = Math.pow(2, attempt) * 1000 + Math.random() * 500\n await new Promise(r => setTimeout(r, delay))\n }\n throw new Error('fetchWithRetry: unreachable')\n }\n\n private buildHeaders(): Record<string, string> {\n const headers: Record<string, string> = { 'Content-Type': 'application/json' }\n if (this.token) headers['Authorization'] = `Bearer ${this.token}`\n return headers\n }\n}\n","import type { Doc } from '../schema/types.js'\nimport type { PullPayload, PushPayload, SyncTransport } from './types.js'\n\nexport interface WebSocketTransportConfig {\n url: string\n token?: string\n reconnect?: boolean\n maxReconnectAttempts?: number\n requestTimeout?: number\n onRemoteChanges?: (changes: Doc[]) => void\n onConnected?: () => void\n}\n\ninterface PendingRequest {\n resolve: (value: unknown) => void\n reject: (reason: unknown) => void\n}\n\ninterface WsMessage {\n type: string\n id?: string\n payload?: unknown\n changes?: Doc[]\n since?: number\n token?: string\n}\n\nexport class WebSocketTransport implements SyncTransport {\n private ws: WebSocket | null = null\n private readonly pending = new Map<string, PendingRequest>()\n private reconnectAttempt = 0\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null\n private destroyed = false\n private token: string | null\n\n constructor(private readonly config: WebSocketTransportConfig) {\n this.token = config.token ?? null\n if (config.url.startsWith('ws://') && typeof location !== 'undefined' && location.hostname !== 'localhost' && location.hostname !== '127.0.0.1') {\n console.warn('[OfflineKit] WebSocket connection uses insecure ws:// protocol. Use wss:// in production.')\n }\n this.connect()\n }\n\n setToken(token: string | null): void {\n this.token = token\n }\n\n async push(payload: PushPayload): Promise<number> {\n const id = this.generateId()\n await this.send({ type: 'push', id, payload })\n return payload.changes.length\n }\n\n async pull(payload: PullPayload): Promise<Doc[]> {\n const id = this.generateId()\n const result = await this.send({ type: 'pull', id, since: payload.since })\n const { changes } = result as { changes: Doc[] }\n return changes\n }\n\n destroy(): void {\n this.destroyed = true\n if (this.reconnectTimer !== null) {\n clearTimeout(this.reconnectTimer)\n this.reconnectTimer = null\n }\n for (const req of this.pending.values()) {\n req.reject(new Error('Transport destroyed'))\n }\n this.pending.clear()\n if (this.ws) {\n this.ws.close()\n this.ws = null\n }\n }\n\n private connect(): void {\n if (this.destroyed) return\n this.ws = new WebSocket(this.config.url)\n\n this.ws.onopen = () => {\n this.reconnectAttempt = 0\n if (this.token) {\n this.ws!.send(JSON.stringify({ type: 'auth', token: this.token }))\n }\n this.config.onConnected?.()\n }\n\n this.ws.onmessage = (event: MessageEvent<string>) => {\n let msg: WsMessage\n try {\n msg = JSON.parse(event.data) as WsMessage\n } catch {\n return\n }\n\n if (msg.type === 'push_ack' || msg.type === 'pull_response') {\n const pending = this.pending.get(msg.id!)\n if (pending) {\n this.pending.delete(msg.id!)\n pending.resolve(msg.payload)\n }\n } else if (msg.type === 'remote_changes') {\n this.config.onRemoteChanges?.(msg.changes ?? [])\n } else if (msg.type === 'error') {\n const pending = this.pending.get(msg.id!)\n if (pending) {\n this.pending.delete(msg.id!)\n const errPayload = msg.payload as { message?: string } | undefined\n pending.reject(new Error(errPayload?.message ?? 'WebSocket error'))\n }\n }\n }\n\n this.ws.onclose = () => {\n for (const req of this.pending.values()) {\n req.reject(new Error('WebSocket disconnected'))\n }\n this.pending.clear()\n this.scheduleReconnect()\n }\n\n this.ws.onerror = () => {\n // close event fires after error — reconnect handled there\n }\n }\n\n private scheduleReconnect(): void {\n if (this.destroyed || this.config.reconnect === false) return\n const max = this.config.maxReconnectAttempts ?? Infinity\n if (this.reconnectAttempt >= max) return\n const delay = Math.min(1000 * Math.pow(2, this.reconnectAttempt), 30000)\n const jitter = Math.random() * 200\n this.reconnectTimer = setTimeout(() => {\n this.reconnectAttempt++\n this.connect()\n }, delay + jitter)\n }\n\n private send(msg: WsMessage): Promise<unknown> {\n return new Promise((resolve, reject) => {\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {\n reject(new Error('WebSocket not connected'))\n return\n }\n const id = msg.id!\n const timeout = this.config.requestTimeout ?? 30_000\n const timer = setTimeout(() => {\n if (this.pending.has(id)) {\n this.pending.delete(id)\n reject(new Error('WebSocket request timed out'))\n }\n }, timeout)\n this.pending.set(id, {\n resolve: (value) => { clearTimeout(timer); resolve(value) },\n reject: (reason) => { clearTimeout(timer); reject(reason) },\n })\n this.ws.send(JSON.stringify(msg))\n })\n }\n\n private generateId(): string {\n const bytes = new Uint8Array(16) // 128 bits\n crypto.getRandomValues(bytes)\n const hex = Array.from(bytes).map(b => b.toString(16).padStart(2, '0')).join('')\n return `${Date.now()}-${hex}`\n }\n}\n","import type { Doc } from '../schema/types.js'\nimport type { PullPayload, PushPayload, SyncTransport } from './types.js'\nimport { HttpTransport } from './transport.js'\nimport { WebSocketTransport } from './ws-transport.js'\n\nexport interface AutoTransportConfig {\n wsUrl: string\n httpEndpoint: string\n token?: string\n onRemoteChanges?: (changes: Doc[]) => void\n}\n\nexport class AutoTransport implements SyncTransport {\n private readonly ws: WebSocketTransport\n private readonly http: HttpTransport\n private useWs = true\n\n constructor(config: AutoTransportConfig) {\n this.http = new HttpTransport(config.httpEndpoint)\n if (config.token) {\n this.http.setToken(config.token)\n }\n this.ws = new WebSocketTransport({\n url: config.wsUrl,\n token: config.token,\n reconnect: true,\n maxReconnectAttempts: 3,\n onRemoteChanges: config.onRemoteChanges,\n onConnected: () => {\n this.useWs = true\n },\n })\n }\n\n setToken(token: string | null): void {\n this.ws.setToken(token)\n this.http.setToken(token)\n }\n\n async push(payload: PushPayload): Promise<number> {\n if (this.useWs) {\n try {\n return await this.ws.push(payload)\n } catch {\n this.useWs = false\n }\n }\n return this.http.push(payload)\n }\n\n async pull(payload: PullPayload): Promise<Doc[]> {\n if (this.useWs) {\n try {\n return await this.ws.pull(payload)\n } catch {\n this.useWs = false\n }\n }\n return this.http.pull(payload)\n }\n\n destroy(): void {\n this.ws.destroy()\n this.http.destroy()\n }\n}\n","import type { StorageAdapter } from '../storage/types.js'\nimport type { Doc } from '../schema/types.js'\nimport type { SyncConfig, SyncStatus, SyncResult, SyncTransport } from './types.js'\nimport { resolveConflict } from './conflict.js'\nimport { HttpTransport } from './transport.js'\nimport { WebSocketTransport } from './ws-transport.js'\nimport { AutoTransport } from './auto-transport.js'\n\nconst SYNC_META_COLLECTION = '_sync_meta'\n\ninterface SyncEventMap {\n 'sync:start': () => void\n 'sync:complete': (result: SyncResult) => void\n 'sync:error': (error: unknown) => void\n}\ntype SyncEventType = keyof SyncEventMap\n\nexport class SyncEngine {\n private status: SyncStatus = 'idle'\n private lastSyncAt: number = 0\n private lastSyncAtInitialized = false\n /** Typed listener map: values are SyncEventMap[E][] per event key. */\n private readonly listenerMap = new Map<SyncEventType, SyncEventMap[SyncEventType][]>()\n private transport: SyncTransport\n private readonly lastSyncKey: string\n\n constructor(\n private readonly storage: StorageAdapter,\n private readonly config: SyncConfig,\n ) {\n this.lastSyncKey = `last_sync_at_${config.endpoint}`\n this.transport = this.resolveTransport(config)\n }\n\n /**\n * Return the current sync status.\n *\n * @returns The current {@link SyncStatus} (`'idle'`, `'syncing'`, `'error'`, or `'offline'`).\n */\n getStatus(): SyncStatus { return this.status }\n\n /**\n * Return the timestamp of the last successful sync.\n *\n * @returns Epoch timestamp (ms), or `0` if no sync has completed yet.\n */\n getLastSyncAt(): number { return this.lastSyncAt }\n\n /**\n * Set the bearer token used by the transport for authenticated requests.\n *\n * @param token - The bearer token string, or `null` to clear it.\n */\n setToken(token: string | null): void {\n this.transport.setToken?.(token)\n }\n\n /**\n * Register a listener for sync events.\n *\n * @param event - The event type to listen for.\n * @param listener - The callback to invoke when the event fires.\n */\n on<E extends SyncEventType>(event: E, listener: SyncEventMap[E]): void {\n const existing = this.listenerMap.get(event) ?? []\n this.listenerMap.set(event, [...existing, listener])\n }\n\n /**\n * Remove a previously registered sync event listener.\n *\n * @param event - The event type.\n * @param listener - The callback to remove.\n */\n off<E extends SyncEventType>(event: E, listener: SyncEventMap[E]): void {\n const existing = this.listenerMap.get(event) ?? []\n this.listenerMap.set(event, existing.filter(l => l !== listener))\n }\n\n /**\n * Push local changes to the server.\n *\n * @returns The number of documents pushed.\n */\n async push(): Promise<number> {\n const changes = await this.storage.getChangesSince(this.lastSyncAt)\n if (changes.length === 0) return 0\n return this.transport.push({ changes, lastSyncAt: this.lastSyncAt })\n }\n\n /**\n * Pull remote changes from the server. Applies conflict resolution for\n * documents that exist both locally and remotely.\n *\n * @returns An object with `pulled` (total remote docs received) and `conflicts` (local-wins count).\n */\n async pull(): Promise<{ pulled: number; conflicts: number }> {\n const remoteChanges = await this.transport.pull({ since: this.lastSyncAt })\n let conflicts = 0\n\n const validRemote = remoteChanges.filter(doc => {\n if (typeof doc._id !== 'string' || typeof doc._collection !== 'string' ||\n typeof doc._updatedAt !== 'number' || typeof doc._deleted !== 'boolean') {\n console.warn('[OfflineKit] Skipping invalid remote document:', doc._id)\n return false\n }\n return true\n })\n\n for (const remote of validRemote) {\n const local = this.storage.getRaw\n ? await this.storage.getRaw(remote._collection, remote._id)\n : await this.storage.get(remote._collection, remote._id)\n\n let docToStore: Doc = remote\n if (local) {\n const resolver = this.config.conflictResolver ?? resolveConflict\n const resolved = resolver(local, remote)\n if (resolved === local) {\n conflicts++\n continue // local wins — keep it\n }\n docToStore = resolved\n }\n\n if (docToStore._deleted) {\n await this.storage.delete(docToStore._collection, docToStore._id)\n } else {\n await this.storage.put(docToStore._collection, docToStore._id, docToStore)\n }\n }\n\n return { pulled: validRemote.length, conflicts }\n }\n\n /**\n * Run a full push+pull sync cycle. Pushes local changes first, then pulls\n * remote changes. Updates the last-sync timestamp on success.\n *\n * @returns A {@link SyncResult} with pushed, pulled, and conflicts counts.\n */\n async sync(): Promise<SyncResult> {\n if (!this.config.enabled) return { pushed: 0, pulled: 0, conflicts: 0 }\n if (this.status === 'syncing') return { pushed: 0, pulled: 0, conflicts: 0 }\n const isOnline = typeof navigator !== 'undefined' ? navigator.onLine : true\n if (!isOnline) {\n this.setStatus('offline')\n return { pushed: 0, pulled: 0, conflicts: 0 }\n }\n\n // Set status synchronously before any await to prevent concurrent syncs\n this.setStatus('syncing')\n this.emit('sync:start')\n\n try {\n if (!this.lastSyncAtInitialized) {\n this.lastSyncAt = await this.loadLastSyncAt()\n this.lastSyncAtInitialized = true\n }\n\n const pushed = await this.push()\n const { pulled, conflicts } = await this.pull()\n\n this.lastSyncAt = Date.now()\n await this.saveLastSyncAt(this.lastSyncAt)\n this.setStatus('idle')\n\n const result: SyncResult = { pushed, pulled, conflicts }\n this.emit('sync:complete', result)\n return result\n } catch (err) {\n const browserOffline = typeof navigator !== 'undefined' ? !navigator.onLine : false\n const isOffline = browserOffline || (err instanceof TypeError && err.message.includes('fetch'))\n this.setStatus(isOffline ? 'offline' : 'error')\n this.emit('sync:error', err)\n return { pushed: 0, pulled: 0, conflicts: 0, error: err instanceof Error ? err : new Error(String(err)) }\n }\n }\n\n /**\n * Clean up the transport (close WebSocket connections, etc.).\n * Call this when the sync engine is no longer needed.\n */\n destroy(): void {\n this.transport.destroy()\n }\n\n private resolveTransport(config: SyncConfig): SyncTransport {\n const t = config.transport\n if (!t || t === 'http') return new HttpTransport(config.endpoint)\n // Derive WS URL: replace protocol, strip trailing /sync if present, append /ws\n const wsUrl = config.endpoint.replace(/^http/, 'ws').replace(/\\/sync\\/?$/, '') + '/ws'\n if (t === 'websocket') {\n return new WebSocketTransport({ url: wsUrl })\n }\n if (t === 'auto') {\n return new AutoTransport({ wsUrl, httpEndpoint: config.endpoint })\n }\n return t // already a SyncTransport instance\n }\n\n private setStatus(status: SyncStatus): void { this.status = status }\n\n private emit<E extends SyncEventType>(event: E, ...args: Parameters<SyncEventMap[E]>): void {\n const listeners = (this.listenerMap.get(event) ?? []) as Array<SyncEventMap[E]>\n for (const listener of listeners) {\n (listener as (...a: Parameters<SyncEventMap[E]>) => void)(...args)\n }\n }\n\n private async loadLastSyncAt(): Promise<number> {\n try {\n const doc = await this.storage.get(SYNC_META_COLLECTION, this.lastSyncKey)\n const val: unknown = doc !== null ? doc['value'] : undefined\n return typeof val === 'number' ? val : 0\n } catch {\n return 0\n }\n }\n\n private async saveLastSyncAt(ts: number): Promise<void> {\n try {\n await this.storage.put(SYNC_META_COLLECTION, this.lastSyncKey, {\n _id: this.lastSyncKey,\n _collection: SYNC_META_COLLECTION,\n _updatedAt: ts,\n _deleted: false,\n value: ts,\n })\n } catch {\n // storage unavailable — ignore\n }\n }\n}\n","import type { SyncEngine } from './engine.js'\nimport type { SyncConfig } from './types.js'\n\n/** Syncs when the user returns to the tab (visibilitychange → visible) */\nexport function setupFocusTrigger(engine: SyncEngine, config: SyncConfig): () => void {\n const handler = () => {\n if (document.visibilityState === 'visible' && config.enabled) {\n void engine.sync()\n }\n }\n document.addEventListener('visibilitychange', handler)\n return () => document.removeEventListener('visibilitychange', handler)\n}\n\n/** Syncs when the network comes back online */\nexport function setupReconnectTrigger(engine: SyncEngine, config: SyncConfig): () => void {\n const handler = () => {\n if (config.enabled) void engine.sync()\n }\n window.addEventListener('online', handler)\n return () => window.removeEventListener('online', handler)\n}\n\n/** Periodic sync at the configured interval while online */\nexport function setupIntervalTrigger(engine: SyncEngine, config: SyncConfig): () => void {\n const ms = config.interval > 0 ? config.interval : 30_000\n const id = setInterval(() => {\n if (config.enabled && navigator.onLine) void engine.sync()\n }, ms)\n return () => clearInterval(id)\n}\n","const ITERATIONS = 600_000\nconst HASH_ALGO = 'SHA-256'\nconst KEY_LENGTH = 32 // bytes\nconst SALT_LENGTH = 16 // bytes\n\nfunction toHex(bytes: Uint8Array): string {\n return Array.from(bytes)\n .map(b => b.toString(16).padStart(2, '0'))\n .join('')\n}\n\nasync function deriveKey(password: string, salt: Uint8Array): Promise<string> {\n const enc = new TextEncoder()\n const keyMaterial = await crypto.subtle.importKey(\n 'raw',\n enc.encode(password),\n 'PBKDF2',\n false,\n ['deriveBits'],\n )\n const derivedBits = await crypto.subtle.deriveBits(\n {\n name: 'PBKDF2',\n salt: salt as BufferSource,\n iterations: ITERATIONS,\n hash: HASH_ALGO,\n },\n keyMaterial,\n KEY_LENGTH * 8,\n )\n return toHex(new Uint8Array(derivedBits))\n}\n\n/**\n * Hashes a password client-side using PBKDF2 + Web Crypto API.\n * Returns a `salt_hex:hash_hex` string. The server receives only the hash — never the plaintext.\n *\n * A cryptographically random 16-byte salt is generated per call so that the same\n * password always produces a unique output. Use verifyPassword() to check passwords.\n */\nexport async function hashPassword(password: string, _email?: string): Promise<string> {\n if (!password) throw new Error('Password must not be empty')\n const salt = crypto.getRandomValues(new Uint8Array(SALT_LENGTH))\n const hashHex = await deriveKey(password, salt)\n return `${toHex(salt)}:${hashHex}`\n}\n\n/**\n * Verifies a password against a stored hash produced by hashPassword().\n * The storedHash must be in `salt_hex:hash_hex` format.\n * Uses a timing-safe comparison to prevent side-channel leakage.\n */\nexport async function verifyPassword(password: string, storedHash: string): Promise<boolean> {\n const colonIndex = storedHash.indexOf(':')\n if (colonIndex === -1) return false\n const saltHex = storedHash.slice(0, colonIndex)\n const hashHex = storedHash.slice(colonIndex + 1)\n const saltBytes = saltHex.match(/.{2}/g)\n if (!saltBytes || saltBytes.length !== SALT_LENGTH) return false\n const salt = new Uint8Array(saltBytes.map(b => parseInt(b, 16)))\n const derived = await deriveKey(password, salt)\n if (derived.length !== hashHex.length) return false\n let result = 0\n for (let i = 0; i < derived.length; i++) {\n result |= derived.charCodeAt(i) ^ hashHex.charCodeAt(i)\n }\n return result === 0\n}\n","import type { User } from './types.js'\n\nconst TOKEN_KEY = '__offlinekit_token'\nconst USER_KEY = '__offlinekit_user'\n\nexport interface StoredSession {\n user: User\n token: string\n}\n\n/**\n * Persist session to localStorage for offline access.\n *\n * **Security note:** Tokens stored in localStorage are accessible to any JavaScript\n * running on the page. Mitigate XSS risk with Content-Security-Policy headers\n * and input sanitization. Consider HttpOnly cookies for high-security applications.\n */\nexport function saveSession(session: StoredSession): void {\n try {\n localStorage.setItem(TOKEN_KEY, session.token)\n localStorage.setItem(USER_KEY, JSON.stringify(session.user))\n } catch {\n // localStorage unavailable — session is in-memory only\n }\n}\n\nexport function loadSession(): StoredSession | null {\n try {\n const token = localStorage.getItem(TOKEN_KEY)\n const userRaw = localStorage.getItem(USER_KEY)\n if (!token || !userRaw) return null\n const parsed = JSON.parse(userRaw) as Record<string, unknown>\n if (typeof parsed.id !== 'string' || typeof parsed.email !== 'string') return null\n return { token, user: { id: parsed.id, email: parsed.email } }\n } catch {\n return null\n }\n}\n\nexport function clearSession(): void {\n try {\n localStorage.removeItem(TOKEN_KEY)\n localStorage.removeItem(USER_KEY)\n } catch {\n /* localStorage unavailable (SSR or quota exceeded) */\n }\n}\n","import type { AuthAdapter, Credentials, User } from './types.js'\nimport { hashPassword } from './pbkdf2.js'\nimport { clearSession, loadSession, saveSession } from './session.js'\n\nexport interface EmailPasswordAuthConfig {\n endpoint: string\n}\n\ninterface AuthResponse {\n user: User\n token: string\n}\n\n/**\n * Email + password auth adapter.\n * - Hashes password client-side (PBKDF2) before sending\n * - Stores JWT + user in localStorage for offline access\n * - Exposes getToken() for the sync engine to attach to requests\n */\nexport class EmailPasswordAuth implements AuthAdapter {\n private session = loadSession()\n\n constructor(private readonly config: EmailPasswordAuthConfig) {}\n\n async signUp(credentials: Credentials): Promise<User> {\n if (!credentials.email) throw new Error('Email is required')\n if (!credentials.password) throw new Error('Password is required')\n const passwordHash = await hashPassword(credentials.password)\n const res = await fetch(`${this.config.endpoint}/auth/signup`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ email: credentials.email, passwordHash }),\n })\n\n if (!res.ok) {\n const body = (await res.json().catch(() => ({}))) as { error?: string }\n throw new Error(body.error ?? `Sign-up failed: ${res.status}`)\n }\n\n const data = (await res.json()) as AuthResponse\n this.session = { user: data.user, token: data.token }\n saveSession(this.session)\n return data.user\n }\n\n async signIn(credentials: Credentials): Promise<User> {\n if (!credentials.email) throw new Error('Email is required')\n if (!credentials.password) throw new Error('Password is required')\n const passwordHash = await hashPassword(credentials.password)\n const res = await fetch(`${this.config.endpoint}/auth/signin`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ email: credentials.email, passwordHash }),\n })\n\n if (!res.ok) {\n const body = (await res.json().catch(() => ({}))) as { error?: string }\n throw new Error(body.error ?? `Sign-in failed: ${res.status}`)\n }\n\n const data = (await res.json()) as AuthResponse\n this.session = { user: data.user, token: data.token }\n saveSession(this.session)\n return data.user\n }\n\n async signOut(): Promise<void> {\n const token = this.session?.token\n this.session = null\n clearSession()\n\n if (token) {\n await fetch(`${this.config.endpoint}/auth/signout`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` },\n }).catch(() => {\n // Fire-and-forget — local session is already cleared\n })\n }\n }\n\n currentUser(): User | null {\n return this.session?.user ?? null\n }\n\n getToken(): string | null {\n return this.session?.token ?? null\n }\n}\n","import type { Credentials, SocialAuthAdapter, SocialProvider, User } from './types.js'\nimport { clearSession, loadSession, saveSession } from './session.js'\n\n/**\n * Better Auth response envelope — all client methods return { data, error }.\n * @see https://www.better-auth.com/docs/basic-usage\n */\nexport interface BetterAuthResponse<T> {\n data: T | null\n error: { message: string; status?: number } | null\n}\n\n/** Core user fields returned by Better Auth */\nexport interface BetterAuthUser {\n id: string\n email: string\n name: string\n image?: string | null\n emailVerified?: boolean\n createdAt?: Date\n updatedAt?: Date\n [key: string]: unknown\n}\n\n/**\n * Minimal interface matching Better Auth's createAuthClient() return type.\n * Requires the bearer plugin on the server for token-based auth.\n *\n * @see https://www.better-auth.com/docs/plugins/bearer\n */\nexport interface BetterAuthClient {\n signUp: {\n email: (opts: {\n email: string\n password: string\n name: string\n }) => Promise<BetterAuthResponse<{ user: BetterAuthUser; token: string | null }>>\n }\n signIn: {\n email: (opts: {\n email: string\n password: string\n }) => Promise<BetterAuthResponse<{ user: BetterAuthUser; token: string }>>\n social: (opts: {\n provider: string\n }) => Promise<BetterAuthResponse<{\n url?: string\n redirect?: boolean\n user?: BetterAuthUser\n token?: string\n }>>\n }\n signOut: () => Promise<BetterAuthResponse<null>>\n getSession: () => Promise<BetterAuthResponse<{\n session: { id: string; token: string; userId: string; expiresAt: Date }\n user: BetterAuthUser\n }>>\n}\n\nexport interface BetterAuthAdapterConfig {\n client: BetterAuthClient\n trustedOrigins?: string[]\n}\n\nfunction unwrap<T>(result: BetterAuthResponse<T>, context: string): T {\n if (result.error) {\n throw new Error(result.error.message ?? `Better Auth ${context} failed`)\n }\n if (!result.data) {\n throw new Error(`Better Auth ${context}: no data returned`)\n }\n return result.data\n}\n\nfunction toUser(baUser: BetterAuthUser): User {\n return { id: baUser.id, email: baUser.email }\n}\n\nexport class BetterAuthAdapter implements SocialAuthAdapter {\n private session = loadSession()\n\n constructor(private readonly config: BetterAuthAdapterConfig) {}\n\n /**\n * Revalidate the stored session against the server.\n * Call on app startup to verify a cached bearer token is still valid.\n * On network failure the cached session is kept for offline use.\n */\n async revalidateSession(): Promise<User | null> {\n if (!this.session?.token) return null\n try {\n const result = await this.config.client.getSession()\n if (result.error || !result.data) {\n this.session = null\n clearSession()\n return null\n }\n const user = toUser(result.data.user)\n const token = result.data.session.token\n this.session = { user, token }\n saveSession(this.session)\n return user\n } catch {\n // Network error — keep cached session for offline use\n return this.session?.user ?? null\n }\n }\n\n async signUp(credentials: Credentials): Promise<User> {\n const name = credentials.name ?? credentials.email.split('@')[0]\n const result = await this.config.client.signUp.email({\n email: credentials.email,\n password: credentials.password,\n name,\n })\n const data = unwrap(result, 'signUp')\n const user = toUser(data.user)\n const token = data.token\n if (token) {\n this.session = { user, token }\n saveSession(this.session)\n }\n return user\n }\n\n async signIn(credentials: Credentials): Promise<User> {\n const result = await this.config.client.signIn.email({\n email: credentials.email,\n password: credentials.password,\n })\n const data = unwrap(result, 'signIn')\n const user = toUser(data.user)\n this.session = { user, token: data.token }\n saveSession(this.session)\n return user\n }\n\n async signInWithSocial(provider: SocialProvider): Promise<User> {\n const result = await this.config.client.signIn.social({ provider })\n const data = unwrap(result, 'signInWithSocial')\n\n // If idToken was provided, user data is returned directly (no redirect)\n if (data.user && data.token) {\n const user = toUser(data.user)\n this.session = { user, token: data.token }\n saveSession(this.session)\n return user\n }\n\n // Standard OAuth: triggers browser redirect, page navigates away.\n // Session is picked up via revalidateSession() after the OAuth callback.\n if (data.url && typeof window !== 'undefined') {\n const url = new URL(data.url)\n const trusted = this.config.trustedOrigins ?? [window.location.origin]\n if (!trusted.includes(url.origin)) {\n throw new Error(`Untrusted redirect URL origin: ${url.origin}`)\n }\n window.location.href = data.url\n }\n throw new Error(\n 'Social sign-in initiated OAuth redirect. ' +\n 'Call revalidateSession() after the callback to load the session.',\n )\n }\n\n async signOut(): Promise<void> {\n this.session = null\n clearSession()\n try {\n await this.config.client.signOut()\n } catch {\n // Server unreachable — local session already cleared\n }\n }\n\n currentUser(): User | null {\n return this.session?.user ?? null\n }\n\n getToken(): string | null {\n return this.session?.token ?? null\n }\n}\n","import type { AuthAdapter, Credentials, OfflineSession, User } from './types.js'\n\nconst OFFLINE_SESSION_KEY = '__offlinekit_offline_session'\n\nfunction saveOfflineSession(session: OfflineSession): void {\n try {\n localStorage.setItem(OFFLINE_SESSION_KEY, JSON.stringify(session))\n } catch { /* localStorage unavailable (SSR or quota exceeded) */ }\n}\n\nfunction loadOfflineSession(): OfflineSession | null {\n try {\n const raw = localStorage.getItem(OFFLINE_SESSION_KEY)\n if (!raw) return null\n const parsed = JSON.parse(raw) as Record<string, unknown>\n if (typeof parsed.token !== 'string' || typeof parsed.expiresAt !== 'number' ||\n !parsed.user || typeof (parsed.user as Record<string, unknown>).id !== 'string') return null\n return parsed as unknown as OfflineSession\n } catch {\n return null\n }\n}\n\nfunction clearOfflineSession(): void {\n try {\n localStorage.removeItem(OFFLINE_SESSION_KEY)\n } catch { /* localStorage unavailable (SSR or quota exceeded) */ }\n}\n\nfunction isOffline(): boolean {\n return typeof navigator !== 'undefined' && !navigator.onLine\n}\n\nexport class OfflineSessionAdapter implements AuthAdapter {\n constructor(\n private readonly inner: AuthAdapter,\n private readonly cacheDuration = 7 * 24 * 60 * 60 * 1000,\n ) {}\n\n async signUp(credentials: Credentials): Promise<User> {\n const user = await this.inner.signUp(credentials)\n const token = this.inner.getToken() ?? ''\n saveOfflineSession({ user, token, expiresAt: Date.now() + this.cacheDuration, provider: 'email' })\n return user\n }\n\n async signIn(credentials: Credentials): Promise<User> {\n try {\n const user = await this.inner.signIn(credentials)\n const token = this.inner.getToken() ?? ''\n saveOfflineSession({ user, token, expiresAt: Date.now() + this.cacheDuration, provider: 'email' })\n return user\n } catch (err) {\n if (isOffline()) {\n const cached = loadOfflineSession()\n if (cached && cached.expiresAt > Date.now()) {\n return cached.user\n }\n }\n throw err\n }\n }\n\n async signOut(): Promise<void> {\n clearOfflineSession()\n await this.inner.signOut()\n }\n\n currentUser(): User | null {\n const inner = this.inner.currentUser()\n if (inner) return inner\n const cached = loadOfflineSession()\n if (cached && cached.expiresAt > Date.now()) return cached.user\n return null\n }\n\n getToken(): string | null {\n const inner = this.inner.getToken()\n if (inner) return inner\n const cached = loadOfflineSession()\n if (cached && cached.expiresAt > Date.now()) return cached.token\n return null\n }\n}\n","import { generateId } from '../storage/id.js'\nimport type { StorageAdapter } from '../storage/types.js'\nimport type { ErrorConfig, ErrorContext, ErrorEntry, ErrorSnapshot, ErrorType } from './types.js'\n\nconst ERRORS_COLLECTION = '_errors'\n\n/**\n * Low-level error tracker that persists errors to a StorageAdapter.\n * Supports snapshot capture, webhook delivery with retry, and automatic pruning.\n */\nexport class ErrorTracker {\n constructor(\n private readonly storage: StorageAdapter,\n private readonly config: ErrorConfig,\n ) {}\n\n /**\n * Retrieve all stored error entries.\n *\n * @returns An array of all persisted {@link ErrorEntry} records.\n */\n async getAll(): Promise<ErrorEntry[]> {\n const docs = await this.storage.getMany(ERRORS_COLLECTION)\n return docs as unknown as ErrorEntry[]\n }\n\n /**\n * Clear all stored error entries (soft-deletes them from storage).\n */\n async clear(): Promise<void> {\n const all = await this.storage.getMany(ERRORS_COLLECTION)\n for (const entry of all) {\n await this.storage.delete(ERRORS_COLLECTION, entry._id)\n }\n }\n\n /**\n * Capture an error and persist it to storage. Triggers the `onError` callback\n * and webhook (if configured), then prunes old entries if over the limit.\n *\n * @param error - The Error instance to capture.\n * @param type - The error category (e.g. `'unhandled_exception'`, `'sync_error'`).\n * @param context - Optional additional context merged with auto-detected fields.\n */\n async capture(\n error: Error,\n type: ErrorType,\n context?: Partial<ErrorContext>,\n ): Promise<void> {\n if (!this.config.enabled) return\n\n const now = Date.now()\n const entry: ErrorEntry = {\n _id: generateId(),\n _collection: ERRORS_COLLECTION,\n _updatedAt: now,\n _deleted: false,\n timestamp: now,\n type,\n message: error.message,\n stack: error.stack,\n context: {\n online: typeof navigator !== 'undefined' ? navigator.onLine : true,\n userAgent: typeof navigator !== 'undefined' ? navigator.userAgent : 'unknown',\n ...context,\n },\n ...(this.config.snapshot ? { snapshot: await this.captureSnapshot() } : {}),\n }\n\n await this.storage.put(ERRORS_COLLECTION, entry._id, entry)\n this.config.onError?.(entry)\n if (this.config.webhookUrl) {\n this.sendWebhook(this.config.webhookUrl, entry)\n }\n await this.pruneIfNeeded()\n }\n\n private sendWebhook(url: string, entry: ErrorEntry): void {\n const send = async (attempt: number): Promise<void> => {\n try {\n const res = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'User-Agent': 'localkit-error-tracker',\n },\n body: JSON.stringify(entry),\n })\n if (res.ok) return\n if (res.status === 429) {\n this.reportWebhookFailure(url)\n return\n }\n if (attempt < 3) {\n const jitter = Math.random() * 500\n const delay = Math.pow(2, attempt) * 1000 + jitter\n await new Promise(r => setTimeout(r, delay))\n return send(attempt + 1)\n }\n this.reportWebhookFailure(url)\n } catch {\n if (attempt < 3) {\n const jitter = Math.random() * 500\n const delay = Math.pow(2, attempt) * 1000 + jitter\n await new Promise(r => setTimeout(r, delay))\n return send(attempt + 1)\n }\n this.reportWebhookFailure(url)\n }\n }\n send(0)\n }\n\n private reportWebhookFailure(url: string): void {\n if (this.config.onError) {\n const now = Date.now()\n this.config.onError({\n _id: '',\n _collection: '_errors',\n _updatedAt: now,\n _deleted: false,\n type: 'runtime',\n message: `Webhook delivery failed after retries: ${url}`,\n timestamp: now,\n context: { online: typeof navigator !== 'undefined' ? navigator.onLine : true },\n })\n }\n }\n\n private async captureSnapshot(): Promise<ErrorSnapshot> {\n const snapshot: ErrorSnapshot = {}\n\n try {\n let total = 0\n for (let i = 0; i < localStorage.length; i++) {\n const k = localStorage.key(i) ?? ''\n total += k.length + (localStorage.getItem(k)?.length ?? 0)\n }\n snapshot.localStorageSize = total\n } catch {\n // localStorage unavailable\n }\n\n return snapshot\n }\n\n private async pruneIfNeeded(): Promise<void> {\n const all = await this.storage.getMany(ERRORS_COLLECTION)\n if (all.length <= this.config.maxLocalErrors) return\n\n // Sort by timestamp ascending, delete oldest\n const sorted = [...all].sort((a, b) => (a._updatedAt ?? 0) - (b._updatedAt ?? 0))\n const toDelete = sorted.slice(0, all.length - this.config.maxLocalErrors)\n for (const entry of toDelete) {\n await this.storage.delete(ERRORS_COLLECTION, entry._id)\n }\n }\n}\n","// Error tracking — capture, store, sync\nexport type { ErrorEntry, ErrorContext, ErrorSnapshot, ErrorType, ErrorConfig } from './types.js'\nexport { ErrorTracker } from './tracker.js'\nexport { setupGlobalHandler, wrapSyncErrors } from './handlers.js'\n\nimport type { StorageAdapter } from '../storage/types.js'\nimport type { ErrorConfig, ErrorContext, ErrorEntry, ErrorType } from './types.js'\nimport { ErrorTracker } from './tracker.js'\n\nconst DEFAULT_CONFIG: ErrorConfig = {\n enabled: true,\n snapshot: true,\n maxLocalErrors: 100,\n}\n\n/** High-level API for error tracking wired into createApp. */\nexport class ErrorManager {\n private readonly tracker: ErrorTracker\n\n constructor(storage: StorageAdapter, config: Partial<ErrorConfig> = {}) {\n this.tracker = new ErrorTracker(storage, { ...DEFAULT_CONFIG, ...config })\n }\n\n /**\n * Capture an error and persist it to storage. Triggers the `onError` callback\n * and webhook (if configured), then prunes old entries if over the limit.\n *\n * @param error - The Error instance to capture.\n * @param type - The error category (defaults to `'unhandled_exception'`).\n * @param context - Optional additional context (online status, user agent, etc.).\n */\n async capture(\n error: Error,\n type: ErrorType = 'unhandled_exception',\n context?: Partial<ErrorContext>,\n ): Promise<void> {\n return this.tracker.capture(error, type, context)\n }\n\n /**\n * Retrieve all stored error entries.\n *\n * @returns An array of all persisted {@link ErrorEntry} records.\n */\n async getAll(): Promise<ErrorEntry[]> {\n return this.tracker.getAll()\n }\n\n /**\n * Clear all stored error entries (soft-deletes them from storage).\n */\n async clear(): Promise<void> {\n return this.tracker.clear()\n }\n\n /**\n * Expose the underlying tracker for handler wiring (e.g. global error handlers).\n *\n * @returns The {@link ErrorTracker} instance.\n */\n getTracker(): ErrorTracker {\n return this.tracker\n }\n}\n","export interface QueryOptions<T> {\n where?: WhereClause<T>\n sort?: Partial<Record<keyof T, 'asc' | 'desc'>>\n limit?: number\n offset?: number\n}\n\nexport type WhereClause<T> = {\n [K in keyof T]?: T[K] | { $gt?: T[K]; $lt?: T[K]; $gte?: T[K]; $lte?: T[K]; $in?: T[K][] }\n}\n\ntype FieldCondition<V> = { $gt?: V; $lt?: V; $gte?: V; $lte?: V; $in?: V[] }\n\nfunction isCondition<V>(value: unknown): value is FieldCondition<V> {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return false\n const keys = Object.keys(value)\n return keys.some(k => k === '$gt' || k === '$lt' || k === '$gte' || k === '$lte' || k === '$in')\n}\n\nexport function matchesWhere<T>(doc: T, where: WhereClause<T>): boolean {\n for (const key of Object.keys(where) as Array<keyof T>) {\n const condition = where[key]\n const docValue = doc[key]\n\n if (isCondition<T[typeof key]>(condition)) {\n if (condition.$gt != null && !(docValue > condition.$gt)) return false\n if (condition.$lt != null && !(docValue < condition.$lt)) return false\n if (condition.$gte != null && !(docValue >= condition.$gte)) return false\n if (condition.$lte != null && !(docValue <= condition.$lte)) return false\n if (condition.$in !== undefined && !condition.$in.includes(docValue)) return false\n } else {\n if (docValue !== condition) return false\n }\n }\n return true\n}\n\nexport function applySort<T>(docs: T[], sort: Partial<Record<keyof T, 'asc' | 'desc'>>): T[] {\n const entries = Object.entries(sort) as Array<[keyof T, 'asc' | 'desc']>\n if (entries.length === 0) return docs\n\n return [...docs].sort((a, b) => {\n for (const [field, direction] of entries) {\n const av = a[field]\n const bv = b[field]\n if (av === bv) continue\n const cmp = av < bv ? -1 : 1\n return direction === 'asc' ? cmp : -cmp\n }\n return 0\n })\n}\n\nexport function applyQuery<T>(docs: T[], options: QueryOptions<T>): T[] {\n let result = docs\n\n if (options.where) {\n const where = options.where\n result = result.filter(doc => matchesWhere(doc, where))\n }\n\n if (options.sort) {\n result = applySort(result, options.sort)\n }\n\n const offset = options.offset ?? 0\n if (offset > 0) {\n result = result.slice(offset)\n }\n\n if (options.limit !== undefined) {\n result = result.slice(0, options.limit)\n }\n\n return result\n}\n","import type { ZodObject, ZodRawShape } from 'zod'\nimport type { Doc, WithMeta } from '../schema/types.js'\nimport { generateId } from '../storage/id.js'\nimport type { StorageAdapter } from '../storage/types.js'\nimport type { QueryOptions } from '../storage/query.js'\nimport { applyQuery } from '../storage/query.js'\n\n/**\n * A collection that supports reactive subscriptions.\n * Compatible with React's `useSyncExternalStore` via `subscribe` + `getSnapshot`.\n */\nexport interface ObservableCollection<T> extends Collection<T> {\n /**\n * Subscribe to collection changes. The listener is called whenever the\n * in-memory snapshot is refreshed (after any mutation).\n * Compatible with `useSyncExternalStore`.\n *\n * @param listener - Callback invoked on every snapshot change.\n * @returns An unsubscribe function.\n */\n subscribe(listener: () => void): () => void\n\n /**\n * Get the current in-memory snapshot of all documents.\n *\n * @returns A read-only array of all non-deleted documents.\n */\n getSnapshot(): ReadonlyArray<WithMeta<T>>\n}\n\nexport interface Collection<T> {\n /** The name of this collection. */\n readonly name: string\n\n /**\n * Create a new document, auto-generating `_id` and metadata fields\n * (`_collection`, `_updatedAt`, `_deleted`).\n *\n * @param data - The user-defined fields for the document.\n * @returns The created document with all metadata fields populated.\n *\n * @example\n * ```ts\n * const todo = await todos.create({ title: 'Buy milk', done: false })\n * console.log(todo._id) // auto-generated\n * ```\n */\n create(data: T): Promise<WithMeta<T>>\n\n /**\n * Query documents with optional where, sort, limit, and offset filters.\n *\n * @param options - Optional query options (where, sort, limit, offset).\n * @returns An array of matching documents.\n *\n * @example\n * ```ts\n * const active = await todos.findMany({\n * where: { done: { $eq: false } },\n * sort: { field: 'title', direction: 'asc' },\n * limit: 10,\n * })\n * ```\n */\n findMany(options?: QueryOptions<T>): Promise<WithMeta<T>[]>\n\n /**\n * Find a single document by ID. Returns `null` if not found.\n *\n * @param id - The document ID.\n * @returns The document, or `null` if not found or deleted.\n */\n findOne(id: string): Promise<WithMeta<T> | null>\n\n /**\n * Partially update a document. Validates the merged result against the schema.\n *\n * @param id - The document ID.\n * @param data - Partial fields to merge into the existing document.\n * @returns The updated document.\n * @throws If the document is not found or deleted.\n */\n update(id: string, data: Partial<T>): Promise<WithMeta<T>>\n\n /**\n * Soft-delete a document (sets `_deleted: true`).\n *\n * @param id - The document ID.\n */\n delete(id: string): Promise<void>\n\n /**\n * Count documents matching an optional query.\n *\n * @param options - Optional query options (where, sort, limit, offset).\n * @returns The number of matching documents.\n */\n count(options?: QueryOptions<T>): Promise<number>\n\n /**\n * Check if a non-deleted document with the given ID exists.\n *\n * @param id - The document ID.\n * @returns `true` if the document exists and is not deleted.\n */\n exists(id: string): Promise<boolean>\n}\n\ntype UserType<TShape extends ZodRawShape> = ZodObject<TShape>['_output']\n\nexport class CollectionImpl<TShape extends ZodRawShape>\n implements Collection<UserType<TShape>>\n{\n private readonly schema: ZodObject<TShape>\n private readonly collectionName: string\n private readonly storage: StorageAdapter\n private readonly version: number | undefined\n private readonly migrate: ((doc: Record<string, unknown>) => Record<string, unknown>) | undefined\n\n constructor(\n schema: ZodObject<TShape>,\n collectionName: string,\n storage: StorageAdapter,\n version?: number,\n migrate?: (doc: Record<string, unknown>) => Record<string, unknown>,\n ) {\n this.schema = schema\n this.collectionName = collectionName\n this.storage = storage\n this.version = version\n this.migrate = migrate\n }\n\n get name(): string {\n return this.collectionName\n }\n\n private async applyMigration(doc: Doc): Promise<WithMeta<UserType<TShape>>> {\n if (this.version === undefined || doc._schemaVersion === this.version) {\n return doc as WithMeta<UserType<TShape>>\n }\n if (this.migrate) {\n const migrated = this.migrate(doc as Record<string, unknown>)\n const updated: Doc = { ...(migrated as Doc), _schemaVersion: this.version }\n await this.storage.put(this.collectionName, updated._id, updated)\n return updated as WithMeta<UserType<TShape>>\n }\n return doc as WithMeta<UserType<TShape>>\n }\n\n async create(data: UserType<TShape>): Promise<WithMeta<UserType<TShape>>> {\n const validated = this.schema.parse(data) as UserType<TShape>\n const id = generateId()\n const doc: WithMeta<UserType<TShape>> = {\n ...validated,\n _id: id,\n _collection: this.collectionName,\n _updatedAt: Date.now(),\n _deleted: false,\n ...(this.version !== undefined ? { _schemaVersion: this.version } : {}),\n }\n await this.storage.put(this.collectionName, id, doc as Doc)\n return doc\n }\n\n async findMany(\n options?: QueryOptions<UserType<TShape>>,\n ): Promise<WithMeta<UserType<TShape>>[]> {\n const docs = await this.storage.getMany(this.collectionName)\n const typed = await Promise.all(\n docs\n .filter(doc => !doc._deleted)\n .map(doc => this.applyMigration(doc)),\n )\n if (!options) return typed\n return applyQuery(typed, options as QueryOptions<WithMeta<UserType<TShape>>>)\n }\n\n async findOne(id: string): Promise<WithMeta<UserType<TShape>> | null> {\n const doc = await this.storage.get(this.collectionName, id)\n if (!doc || doc._deleted) return null\n return this.applyMigration(doc)\n }\n\n async update(\n id: string,\n data: Partial<UserType<TShape>>,\n ): Promise<WithMeta<UserType<TShape>>> {\n const existing = await this.storage.get(this.collectionName, id)\n if (!existing || existing._deleted) {\n throw new Error(`Document not found: ${id}`)\n }\n const merged = {\n ...(existing as WithMeta<UserType<TShape>>),\n ...data,\n }\n // Extract user fields (non-meta) for schema validation\n const userFields: Record<string, unknown> = {}\n for (const [k, v] of Object.entries(merged as Record<string, unknown>)) {\n if (!k.startsWith('_')) userFields[k] = v\n }\n this.schema.parse(userFields)\n const updated: WithMeta<UserType<TShape>> = {\n ...merged,\n _updatedAt: Date.now(),\n }\n await this.storage.put(this.collectionName, id, updated as Doc)\n return updated\n }\n\n async delete(id: string): Promise<void> {\n const existing = await this.storage.get(this.collectionName, id)\n if (!existing) return\n const deleted: Doc = {\n ...existing,\n _deleted: true,\n _updatedAt: Date.now(),\n }\n await this.storage.put(this.collectionName, id, deleted)\n }\n\n async count(options?: QueryOptions<UserType<TShape>>): Promise<number> {\n const docs = await this.findMany(options)\n return docs.length\n }\n\n async exists(id: string): Promise<boolean> {\n const doc = await this.storage.get(this.collectionName, id)\n return doc !== null && !doc._deleted\n }\n}\n\n/**\n * Extends CollectionImpl with useSyncExternalStore-compatible subscribe/getSnapshot.\n * Maintains an in-memory snapshot refreshed after every mutation.\n */\nexport class ObservableCollectionImpl<TShape extends ZodRawShape>\n extends CollectionImpl<TShape>\n implements ObservableCollection<UserType<TShape>>\n{\n private snapshot: ReadonlyArray<WithMeta<UserType<TShape>>> = []\n private subscribers = new Set<() => void>()\n\n private notify(): void {\n for (const sub of this.subscribers) sub()\n }\n\n private async refreshSnapshot(): Promise<void> {\n const data = await this.findMany()\n this.snapshot = data\n this.notify()\n }\n\n subscribe(listener: () => void): () => void {\n this.subscribers.add(listener)\n this.refreshSnapshot().catch(err => console.error('[LocalKit] subscribe refreshSnapshot failed:', err))\n return () => {\n this.subscribers.delete(listener)\n }\n }\n\n getSnapshot(): ReadonlyArray<WithMeta<UserType<TShape>>> {\n return this.snapshot\n }\n\n override async create(\n data: UserType<TShape>,\n ): Promise<WithMeta<UserType<TShape>>> {\n const doc = await super.create(data)\n await this.refreshSnapshot()\n return doc\n }\n\n override async update(\n id: string,\n data: Partial<UserType<TShape>>,\n ): Promise<WithMeta<UserType<TShape>>> {\n const doc = await super.update(id, data)\n await this.refreshSnapshot()\n return doc\n }\n\n override async delete(id: string): Promise<void> {\n await super.delete(id)\n await this.refreshSnapshot()\n }\n}\n","import type { AuthAdapter, Credentials, User } from '../auth/types.js'\nimport type { SyncStatus } from '../sync/types.js'\n\nexport interface AuthState {\n user: User | null\n token: string | null\n isLoading: boolean\n}\n\nexport interface SyncState {\n status: SyncStatus\n lastSyncAt: number | null\n}\n\n/** Observable auth wrapper — delegates to AuthAdapter and notifies React subscribers on state changes. */\nexport class AuthStore implements AuthAdapter {\n private state: AuthState\n private listeners = new Set<() => void>()\n\n constructor(private readonly adapter: AuthAdapter) {\n this.state = {\n user: adapter.currentUser(),\n token: adapter.getToken(),\n isLoading: false,\n }\n }\n\n subscribe(listener: () => void): () => void {\n this.listeners.add(listener)\n return () => {\n this.listeners.delete(listener)\n }\n }\n\n getSnapshot(): AuthState {\n return this.state\n }\n\n private notify(): void {\n for (const l of this.listeners) l()\n }\n\n async signUp(credentials: Credentials): Promise<User> {\n this.state = { ...this.state, isLoading: true }\n this.notify()\n try {\n const user = await this.adapter.signUp(credentials)\n this.state = { user, token: this.adapter.getToken(), isLoading: false }\n this.notify()\n return user\n } catch (err) {\n this.state = { ...this.state, isLoading: false }\n this.notify()\n throw err\n }\n }\n\n async signIn(credentials: Credentials): Promise<User> {\n this.state = { ...this.state, isLoading: true }\n this.notify()\n try {\n const user = await this.adapter.signIn(credentials)\n this.state = { user, token: this.adapter.getToken(), isLoading: false }\n this.notify()\n return user\n } catch (err) {\n this.state = { ...this.state, isLoading: false }\n this.notify()\n throw err\n }\n }\n\n async signOut(): Promise<void> {\n await this.adapter.signOut()\n this.state = { user: null, token: null, isLoading: false }\n this.notify()\n }\n\n currentUser(): User | null {\n return this.state.user\n }\n\n getToken(): string | null {\n return this.state.token\n }\n\n /**\n * Revalidate a cached session against the server.\n * Delegates to the inner adapter's `revalidateSession` if it supports it.\n *\n * @returns The revalidated user, or `null` if the session is invalid or the adapter does not support revalidation.\n */\n async revalidateSession(): Promise<User | null> {\n if (!this.adapter.revalidateSession) return null\n const user = await this.adapter.revalidateSession()\n this.state = {\n user,\n token: this.adapter.getToken(),\n isLoading: false,\n }\n this.notify()\n return user\n }\n}\n\n/** Observable sync state — updated by the sync engine and read by useSync. */\nexport class SyncStore {\n private state: SyncState = { status: 'idle', lastSyncAt: null }\n private listeners = new Set<() => void>()\n\n subscribe(listener: () => void): () => void {\n this.listeners.add(listener)\n return () => {\n this.listeners.delete(listener)\n }\n }\n\n getSnapshot(): SyncState {\n return this.state\n }\n\n setStatus(status: SyncStatus, lastSyncAt?: number): void {\n this.state = {\n status,\n lastSyncAt: lastSyncAt !== undefined ? lastSyncAt : this.state.lastSyncAt,\n }\n for (const l of this.listeners) l()\n }\n}\n","import type { ZodRawShape } from 'zod'\nimport type { AuthAdapter } from '../auth/types.js'\nimport { EmailPasswordAuth } from '../auth/adapter.js'\nimport { BetterAuthAdapter, type BetterAuthClient } from '../auth/better-auth-adapter.js'\nimport { loadSession } from '../auth/session.js'\nimport { ErrorManager } from '../errors/index.js'\nimport type { CollectionDescriptor } from '../schema/types.js'\nimport { IndexedDBAdapter } from '../storage/indexeddb.js'\nimport { MemoryAdapter } from '../storage/memory.js'\nimport type { StorageAdapter } from '../storage/types.js'\nimport type { SyncConfig } from '../sync/types.js'\nimport { SyncEngine } from '../sync/engine.js'\nimport { ObservableCollectionImpl, type ObservableCollection } from './collection.js'\nimport { AuthStore, SyncStore } from './events.js'\nimport type { AuthConfig, ErrorTrackingConfig, SyncAPI } from './types.js'\n\ntype ObservableInferredCollections<\n C extends Record<string, CollectionDescriptor<ZodRawShape>>,\n> = {\n [K in keyof C]: ObservableCollection<C[K]['_inferredType']>\n}\n\nexport type App<C extends Record<string, CollectionDescriptor<ZodRawShape>>> =\n ObservableInferredCollections<C> & {\n auth: AuthStore\n errors: ErrorManager\n syncStore: SyncStore\n sync?: SyncAPI\n }\n\nexport interface CreateAppConfig<\n C extends Record<string, CollectionDescriptor<ZodRawShape>>,\n> {\n collections: C\n storage?: StorageAdapter\n sync?: Partial<SyncConfig>\n errorTracking?: ErrorTrackingConfig\n auth?: AuthConfig\n}\n\nfunction createDeferredBetterAuthClient(baseURL: string): BetterAuthClient {\n let clientPromise: Promise<BetterAuthClient> | null = null\n\n function getClient(): Promise<BetterAuthClient> {\n if (!clientPromise) {\n clientPromise = (async () => {\n try {\n const mod = await import('better-auth/client')\n return (mod as { createAuthClient: (opts: Record<string, unknown>) => BetterAuthClient }).createAuthClient({\n baseURL,\n fetchOptions: {\n auth: {\n type: 'Bearer',\n token: (): string => {\n try { return loadSession()?.token ?? '' } catch { return '' }\n },\n },\n },\n })\n } catch {\n throw new Error(\n 'better-auth is not installed. Run: npm install better-auth\\n' +\n 'The server must enable the bearer plugin: import { bearer } from \"better-auth/plugins\"',\n )\n }\n })()\n }\n return clientPromise\n }\n\n return {\n signUp: {\n email: async (opts) => (await getClient()).signUp.email(opts),\n },\n signIn: {\n email: async (opts) => (await getClient()).signIn.email(opts),\n social: async (opts) => (await getClient()).signIn.social(opts),\n },\n signOut: async () => (await getClient()).signOut(),\n getSession: async () => (await getClient()).getSession(),\n }\n}\n\nfunction resolveAuth(config?: AuthConfig): AuthAdapter {\n if (!config) {\n return {\n signUp: async () => { throw new Error('Auth not configured. Implement AuthAdapter.') },\n signIn: async () => { throw new Error('Auth not configured. Implement AuthAdapter.') },\n signOut: async () => { throw new Error('Auth not configured. Implement AuthAdapter.') },\n currentUser: () => null,\n getToken: () => null,\n }\n }\n if ('type' in config) {\n if (config.type === 'email-password') {\n return new EmailPasswordAuth({ endpoint: config.endpoint })\n }\n if (config.type === 'better-auth') {\n return new BetterAuthAdapter({ client: createDeferredBetterAuthClient(config.baseURL) })\n }\n }\n // Verify custom AuthAdapter has required methods\n const adapter = config as AuthAdapter\n if (typeof adapter.signUp !== 'function' || typeof adapter.signIn !== 'function' ||\n typeof adapter.signOut !== 'function' || typeof adapter.currentUser !== 'function' ||\n typeof adapter.getToken !== 'function') {\n throw new Error('Invalid auth config: must implement AuthAdapter interface (signUp, signIn, signOut, currentUser, getToken)')\n }\n return adapter\n}\n\nexport function createApp<\n C extends Record<string, CollectionDescriptor<ZodRawShape>>,\n>(config: CreateAppConfig<C>): App<C> {\n // IndexedDBAdapter constructor is SSR-safe (just sets dbName, DB opens lazily).\n // Fall back to MemoryAdapter in environments without indexedDB (Node tests, SSR\n // without browser globals). IndexedDB operations only run on the client.\n const storage: StorageAdapter = config.storage ??\n (typeof indexedDB !== 'undefined' ? new IndexedDBAdapter('localkit') : new MemoryAdapter())\n\n const RESERVED_KEYS = ['auth', 'errors', 'syncStore', 'sync'] as const\n for (const name of Object.keys(config.collections)) {\n if ((RESERVED_KEYS as readonly string[]).includes(name)) {\n throw new Error(`Collection name \"${name}\" conflicts with reserved key`)\n }\n }\n\n const collections: Record<string, ObservableCollection<unknown>> = {}\n for (const [name, descriptor] of Object.entries(config.collections)) {\n collections[name] = new ObservableCollectionImpl(descriptor.schema, name, storage, descriptor.version, descriptor.migrate)\n }\n\n const errors = new ErrorManager(storage, config.errorTracking)\n const authStore = new AuthStore(resolveAuth(config.auth))\n const syncStore = new SyncStore()\n\n let syncAPI: SyncAPI | undefined\n\n if (config.sync?.endpoint) {\n const syncConfig: SyncConfig = {\n endpoint: config.sync.endpoint,\n interval: config.sync.interval ?? 30_000,\n enabled: config.sync.enabled ?? true,\n conflictResolver: config.sync.conflictResolver,\n transport: config.sync.transport,\n }\n\n const engine = new SyncEngine(storage, syncConfig)\n\n // Wire auth token into transport so authenticated syncs work offline\n engine.setToken(authStore.getToken())\n const unsubAuth = authStore.subscribe(() => engine.setToken(authStore.getToken()))\n\n // Wire engine events to syncStore for React subscribers\n engine.on('sync:start', () => syncStore.setStatus('syncing'))\n engine.on('sync:complete', () => syncStore.setStatus('idle', engine.getLastSyncAt()))\n engine.on('sync:error', () => syncStore.setStatus(engine.getStatus()))\n\n let intervalId: ReturnType<typeof setInterval> | null = null\n const onOnline = () => { void engine.sync() }\n\n syncAPI = {\n push: () => engine.push(),\n pull: () => engine.pull(),\n start() {\n if (!syncConfig.enabled) return\n intervalId = setInterval(() => { void engine.sync() }, syncConfig.interval)\n if (typeof window !== 'undefined') {\n window.addEventListener('online', onOnline)\n }\n },\n stop() {\n if (intervalId !== null) {\n clearInterval(intervalId)\n intervalId = null\n }\n if (typeof window !== 'undefined') {\n window.removeEventListener('online', onOnline)\n }\n unsubAuth()\n },\n get status() {\n return engine.getStatus()\n },\n }\n }\n\n return {\n ...collections,\n auth: authStore,\n errors,\n syncStore,\n ...(syncAPI !== undefined ? { sync: syncAPI } : {}),\n } as App<C>\n}\n","import type { QueryOptions } from './storage/query.js'\nimport type { WithMeta } from './schema/types.js'\nimport type { Collection } from './client/collection.js'\n\n/** Minimal QueryClient interface — avoids a hard dep on @tanstack/query-core */\ninterface MinimalQueryClient {\n invalidateQueries(opts: { queryKey: readonly unknown[] }): Promise<void>\n}\n\nexport const localkitKeys = {\n all: ['offlinekit'] as const,\n collection: (name: string) => ['offlinekit', name] as const,\n collectionQuery: (name: string, opts: unknown) =>\n ['offlinekit', name, JSON.stringify(opts)] as const,\n}\n\nexport function collectionQueryOptions<T>(\n collection: Collection<T>,\n queryOptions?: QueryOptions<T>,\n): {\n queryKey: readonly unknown[]\n queryFn: () => Promise<WithMeta<T>[]>\n} {\n const queryKey = queryOptions\n ? localkitKeys.collectionQuery(collection.name, queryOptions)\n : localkitKeys.collection(collection.name)\n\n return {\n queryKey,\n queryFn: () => collection.findMany(queryOptions),\n }\n}\n\nexport function subscribeToCollection<T>(\n collection: Collection<T>,\n queryClient: MinimalQueryClient,\n): () => void {\n const queryKey = localkitKeys.collection(collection.name)\n\n if (!('subscribe' in collection)) {\n return () => {}\n }\n\n const obs = collection as Collection<T> & {\n subscribe(listener: () => void): () => void\n }\n\n return obs.subscribe(() => {\n void queryClient.invalidateQueries({ queryKey })\n })\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/core/schema/collection.ts","../../src/core/storage/indexeddb.ts","../../src/core/storage/memory.ts","../../src/core/storage/id.ts","../../src/core/storage/encrypted.ts","../../src/core/storage/key-rotation.ts","../../src/core/storage/migrate-encrypted.ts","../../src/core/sync/conflict.ts","../../src/core/sync/transport.ts","../../src/core/sync/ws-transport.ts","../../src/core/sync/auto-transport.ts","../../src/core/sync/engine.ts","../../src/core/sync/triggers.ts","../../src/core/auth/pbkdf2.ts","../../src/core/auth/session.ts","../../src/core/auth/adapter.ts","../../src/core/auth/better-auth-adapter.ts","../../src/core/auth/offline-adapter.ts","../../src/core/errors/tracker.ts","../../src/core/errors/index.ts","../../src/core/storage/query.ts","../../src/core/client/collection.ts","../../src/core/client/events.ts","../../src/core/client/app.ts","../../src/core/query.ts"],"names":["collection","db","uuidv7","isOffline","passwordHash"],"mappings":"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","file":"index.js","sourcesContent":["import { type ZodObject, type ZodRawShape } from 'zod'\nimport type { CollectionDescriptor, CollectionOptions } from './types.js'\n\n/**\n * Wraps a Zod schema to create a typed collection descriptor.\n * TypeScript infers the document type from the schema automatically.\n *\n * @example\n * const brews = collection(z.object({ style: z.string(), og: z.number() }))\n * // brews._inferredType is { style: string; og: number }\n */\nexport function collection<TShape extends ZodRawShape>(\n schema: ZodObject<TShape>,\n options?: CollectionOptions,\n): CollectionDescriptor<TShape> {\n return {\n schema,\n collectionName: '',\n version: options?.version,\n migrate: options?.migrate,\n } as CollectionDescriptor<TShape>\n}\n","import { openDB, IDBPDatabase } from 'idb'\nimport type { Doc } from '../schema/types.js'\nimport type { Filter, Change, StorageAdapter } from './types.js'\n\nconst CHANGES_INDEX = '_updatedAt'\n\nexport class IndexedDBAdapter implements StorageAdapter {\n private dbName: string\n private db: IDBPDatabase | null = null\n private _ensureLock: Promise<void> = Promise.resolve()\n\n constructor(appName: string) {\n this.dbName = `offlinekit-${appName}`\n }\n\n private async getDb(): Promise<IDBPDatabase> {\n if (this.db) return this.db\n this.db = await openDB(this.dbName, 1, {\n upgrade(_db) {\n // Stores are created dynamically per collection on first use\n },\n })\n return this.db\n }\n\n private async ensureStore(collection: string): Promise<IDBPDatabase> {\n // Capture and replace the lock synchronously before any await.\n // This serializes concurrent callers: each waits for its predecessor.\n const prev = this._ensureLock\n let release: () => void\n this._ensureLock = new Promise<void>(r => { release = r })\n\n await prev\n\n try {\n let db = await this.getDb()\n if (db.objectStoreNames.contains(collection)) return db\n\n const version = db.version + 1\n db.close()\n this.db = null\n db = await openDB(this.dbName, version, {\n upgrade(db) {\n if (!db.objectStoreNames.contains(collection)) {\n const store = db.createObjectStore(collection, { keyPath: '_id' })\n store.createIndex(CHANGES_INDEX, '_updatedAt')\n }\n },\n })\n this.db = db\n return db\n } finally {\n release!()\n }\n }\n\n async get(collection: string, id: string): Promise<Doc | null> {\n const db = await this.ensureStore(collection)\n const doc = await db.get(collection, id)\n if (!doc || doc._deleted) return null\n return doc as Doc\n }\n\n async getMany(collection: string, filter?: Filter): Promise<Doc[]> {\n const db = await this.ensureStore(collection)\n const all = await db.getAll(collection) as Doc[]\n return all.filter(doc => {\n if (doc._deleted) return false\n if (!filter) return true\n return Object.entries(filter).every(([k, v]) => Reflect.get(doc as object, k) === v)\n })\n }\n\n async put(collection: string, id: string, doc: Doc): Promise<void> {\n const db = await this.ensureStore(collection)\n await db.put(collection, { ...doc, _id: id, _collection: collection })\n }\n\n async delete(collection: string, id: string): Promise<void> {\n const db = await this.ensureStore(collection)\n const existing = await db.get(collection, id) as Doc | undefined\n if (!existing) return\n await db.put(collection, {\n ...existing,\n _deleted: true,\n _updatedAt: Date.now(),\n })\n }\n\n async getChangesSince(timestamp: number): Promise<Change[]> {\n const db = await this.getDb()\n const results: Change[] = []\n for (const storeName of Array.from(db.objectStoreNames)) {\n if (!db.objectStoreNames.contains(storeName)) continue\n const tx = db.transaction(storeName, 'readonly')\n const store = tx.objectStore(storeName)\n const index = store.index(CHANGES_INDEX)\n const range = IDBKeyRange.lowerBound(timestamp, true)\n const docs = await index.getAll(range) as Doc[]\n for (const doc of docs) {\n results.push({\n collection: storeName,\n id: doc._id,\n doc,\n updatedAt: doc._updatedAt,\n deleted: doc._deleted,\n })\n }\n }\n return results\n }\n}\n","import type { Doc } from '../schema/types.js'\nimport type { Filter, Change, StorageAdapter } from './types.js'\n\nexport class MemoryAdapter implements StorageAdapter {\n private store = new Map<string, Map<string, Doc>>()\n\n private getCollection(collection: string): Map<string, Doc> {\n if (!this.store.has(collection)) {\n this.store.set(collection, new Map())\n }\n return this.store.get(collection)!\n }\n\n async get(collection: string, id: string): Promise<Doc | null> {\n const doc = this.getCollection(collection).get(id)\n if (!doc || doc._deleted) return null\n return { ...doc }\n }\n\n async getRaw(collection: string, id: string): Promise<Doc | null> {\n const doc = this.getCollection(collection).get(id)\n if (!doc) return null\n return { ...doc }\n }\n\n async getMany(collection: string, filter?: Filter): Promise<Doc[]> {\n const col = this.getCollection(collection)\n return Array.from(col.values()).filter(doc => {\n if (doc._deleted) return false\n if (!filter) return true\n return Object.entries(filter).every(([k, v]) => (doc as unknown as Record<string, unknown>)[k] === v)\n }).map(doc => ({ ...doc }))\n }\n\n async put(collection: string, id: string, doc: Doc): Promise<void> {\n this.getCollection(collection).set(id, { ...doc, _id: id, _collection: collection })\n }\n\n async delete(collection: string, id: string): Promise<void> {\n const col = this.getCollection(collection)\n const existing = col.get(id)\n if (!existing) return\n col.set(id, { ...existing, _deleted: true, _updatedAt: Date.now() })\n }\n\n async getChangesSince(timestamp: number): Promise<Change[]> {\n const results: Change[] = []\n for (const [collection, col] of this.store.entries()) {\n for (const doc of col.values()) {\n if (doc._updatedAt > timestamp) {\n results.push({\n collection,\n id: doc._id,\n doc: { ...doc },\n updatedAt: doc._updatedAt,\n deleted: doc._deleted,\n })\n }\n }\n }\n return results\n }\n}\n","import { v7 as uuidv7 } from 'uuid'\n\nexport function generateId(): string {\n return uuidv7()\n}\n","import type { Doc } from '../schema/types.js'\nimport type { Filter, Change, StorageAdapter } from './types.js'\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\n/** A raw CryptoKey or a password+salt pair for PBKDF2 / AES-KW derivation. */\nexport type KeySpec = CryptoKey | { password: string; salt: string }\n\n/** Multi-version keychain configuration for key rotation support. */\nexport interface KeychainConfig {\n keys: Record<number, KeySpec>\n activeVersion: number\n}\n\n/** Key-wrapping options (Mode 3). */\nexport interface WrapConfig {\n /** Base64-encoded wrapped data key from a previous session. */\n wrapped?: string\n /** Called once with the base64-encoded wrapped data key on first use. */\n onKeyWrapped?: (wrappedKey: string) => void\n}\n\n/**\n * Encryption configuration.\n *\n * - Mode 1 `{ key: { password, salt } }` — PBKDF2-SHA256 key derivation\n * - Mode 2 `{ key: CryptoKey }` — raw key used directly\n * - Mode 3 `{ key: { password, salt }, wrap: { ... } }` — AES-KW key wrapping\n * - Keychain mode `{ keychain: { keys, activeVersion } }` — multi-version key rotation\n */\nexport interface EncryptionConfig {\n key?: KeySpec\n keychain?: KeychainConfig\n wrap?: WrapConfig\n /** PBKDF2 iteration count (default: 600 000). */\n iterations?: number\n}\n\n// ─── Internal helpers ─────────────────────────────────────────────────────────\n\nconst METADATA_FIELDS = new Set(['_id', '_collection', '_updatedAt', '_deleted', '_schemaVersion'])\nconst ENCRYPTED_FIELDS = new Set(['_encrypted', '_iv', '_keyVersion'])\n\nexport function toBase64(buf: ArrayBuffer | Uint8Array): string {\n const bytes = buf instanceof Uint8Array ? buf : new Uint8Array(buf)\n let binary = ''\n for (let i = 0; i < bytes.length; i++) binary += String.fromCharCode(bytes[i])\n return btoa(binary)\n}\n\nexport function fromBase64(s: string): Uint8Array<ArrayBuffer> {\n const binary = atob(s)\n const bytes = new Uint8Array(binary.length)\n for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i)\n return bytes as Uint8Array<ArrayBuffer>\n}\n\n/** Cast TextEncoder output to the ArrayBuffer-backed variant that Web Crypto requires. */\nexport function encode(s: string): Uint8Array<ArrayBuffer> {\n return new TextEncoder().encode(s) as unknown as Uint8Array<ArrayBuffer>\n}\n\nasync function deriveAesGcmKey(\n password: string,\n salt: string,\n iterations: number,\n extractable = false\n): Promise<CryptoKey> {\n const keyMaterial = await crypto.subtle.importKey('raw', encode(password), 'PBKDF2', false, [\n 'deriveBits',\n 'deriveKey',\n ])\n return crypto.subtle.deriveKey(\n { name: 'PBKDF2', salt: encode(salt), iterations, hash: 'SHA-256' },\n keyMaterial,\n { name: 'AES-GCM', length: 256 },\n extractable,\n ['encrypt', 'decrypt']\n )\n}\n\nexport async function deriveAesKwKey(password: string, salt: string, iterations: number): Promise<CryptoKey> {\n const keyMaterial = await crypto.subtle.importKey('raw', encode(password), 'PBKDF2', false, [\n 'deriveBits',\n 'deriveKey',\n ])\n return crypto.subtle.deriveKey(\n { name: 'PBKDF2', salt: encode(salt), iterations, hash: 'SHA-256' },\n keyMaterial,\n { name: 'AES-KW', length: 256 },\n false,\n ['wrapKey', 'unwrapKey']\n )\n}\n\nasync function verifySentinel(key: CryptoKey): Promise<void> {\n const sentinel = encode('offlinekit-sentinel')\n const iv = crypto.getRandomValues(new Uint8Array(12))\n const ciphertext = await crypto.subtle.encrypt({ name: 'AES-GCM', iv }, key, sentinel)\n const plaintext = await crypto.subtle\n .decrypt({ name: 'AES-GCM', iv }, key, ciphertext)\n .catch(() => null)\n if (!plaintext || new TextDecoder().decode(plaintext) !== 'offlinekit-sentinel') {\n throw new Error('EncryptedStorageAdapter: key verification failed — wrong password or key')\n }\n}\n\n/** Resolve a single KeySpec to a CryptoKey using Mode 1/2/3 logic. */\nasync function resolveKeySpec(spec: KeySpec, iterations: number, wrap?: WrapConfig): Promise<CryptoKey> {\n if (spec instanceof CryptoKey) {\n // Mode 2 — use the provided key directly\n return spec\n } else if (wrap) {\n // Mode 3 — AES-KW: wrapping key is derived from password + salt\n const { password, salt } = spec\n const wrappingKey = await deriveAesKwKey(password, salt, iterations)\n\n if (wrap.wrapped) {\n // Unwrap stored key blob\n return crypto.subtle.unwrapKey(\n 'raw',\n fromBase64(wrap.wrapped),\n wrappingKey,\n 'AES-KW',\n { name: 'AES-GCM', length: 256 },\n false,\n ['encrypt', 'decrypt']\n )\n } else {\n // Generate a fresh random data key, wrap it for caller storage, then harden\n const extractableKey = await crypto.subtle.generateKey(\n { name: 'AES-GCM', length: 256 },\n true /* must be extractable to wrap */,\n ['encrypt', 'decrypt']\n )\n const wrappedBuf = await crypto.subtle.wrapKey('raw', extractableKey, wrappingKey, 'AES-KW')\n wrap.onKeyWrapped?.(toBase64(wrappedBuf))\n\n // Re-import as non-extractable to harden against XSS\n const rawKeyBuf = await crypto.subtle.exportKey('raw', extractableKey)\n return crypto.subtle.importKey(\n 'raw',\n rawKeyBuf,\n { name: 'AES-GCM', length: 256 },\n false,\n ['encrypt', 'decrypt']\n )\n }\n } else {\n // Mode 1 — PBKDF2: data key is derived directly from password + salt\n const { password, salt } = spec\n return deriveAesGcmKey(password, salt, iterations)\n }\n}\n\n// ─── Factory ──────────────────────────────────────────────────────────────────\n\n/**\n * Wraps any StorageAdapter with transparent AES-GCM 256-bit encryption.\n *\n * @throws If `inner` is already an EncryptedStorageAdapter (double-encryption guard).\n * @throws If key verification fails (wrong password / corrupted wrapped key).\n */\nexport async function encrypted(\n inner: StorageAdapter,\n config: EncryptionConfig\n): Promise<EncryptedStorageAdapter> {\n if (inner instanceof EncryptedStorageAdapter) {\n throw new Error('EncryptedStorageAdapter: double-encryption is not allowed')\n }\n\n if (!config.key && !config.keychain) {\n throw new Error('EncryptedStorageAdapter: either key or keychain must be provided')\n }\n\n const iterations = config.iterations ?? 600_000\n let keychain: Map<number, CryptoKey>\n let activeVersion: number\n\n if (config.keychain) {\n const { keys, activeVersion: av } = config.keychain\n if (!(av in keys)) {\n throw new Error(`EncryptedStorageAdapter: keychain.activeVersion ${av} not found in keychain.keys`)\n }\n activeVersion = av\n keychain = new Map<number, CryptoKey>()\n for (const [ver, spec] of Object.entries(keys)) {\n const version = Number(ver)\n // Wrap config only applies to single-key mode; keychain keys use Mode 1 or Mode 2\n const resolved = await resolveKeySpec(spec, iterations)\n keychain.set(version, resolved)\n }\n } else {\n // Single-key mode: treat as keychain with version 1\n const resolved = await resolveKeySpec(config.key!, iterations, config.wrap)\n activeVersion = 1\n keychain = new Map([[1, resolved]])\n }\n\n await verifySentinel(keychain.get(activeVersion)!)\n return new EncryptedStorageAdapter(inner, keychain, activeVersion)\n}\n\n// ─── Adapter ──────────────────────────────────────────────────────────────────\n\nexport class EncryptedStorageAdapter implements StorageAdapter {\n constructor(\n private readonly inner: StorageAdapter,\n private readonly keychain: Map<number, CryptoKey>,\n private readonly activeVersion: number\n ) {}\n\n private isEncryptedDoc(doc: Doc): boolean {\n return '_encrypted' in doc && '_iv' in doc\n }\n\n private async encryptDoc(doc: Doc): Promise<Doc> {\n const raw = doc as Record<string, unknown>\n\n const metadata: Record<string, unknown> = {}\n for (const field of METADATA_FIELDS) {\n if (field in raw) metadata[field] = raw[field]\n }\n\n const userFields: Record<string, unknown> = {}\n for (const [k, v] of Object.entries(raw)) {\n if (!METADATA_FIELDS.has(k) && !ENCRYPTED_FIELDS.has(k)) {\n userFields[k] = v\n }\n }\n\n const iv = crypto.getRandomValues(new Uint8Array(12))\n const aad = encode(JSON.stringify({ _id: doc._id, _collection: doc._collection }))\n const plaintext = encode(JSON.stringify(userFields))\n\n const ciphertext = await crypto.subtle.encrypt(\n { name: 'AES-GCM', iv, additionalData: aad },\n this.keychain.get(this.activeVersion)!,\n plaintext\n )\n\n return {\n ...metadata,\n _encrypted: toBase64(ciphertext),\n _iv: toBase64(iv),\n _keyVersion: this.activeVersion,\n } as unknown as Doc\n }\n\n private async decryptDoc(doc: Doc): Promise<Doc> {\n if (!this.isEncryptedDoc(doc)) return doc // migration: pass through unencrypted docs\n\n const raw = doc as Record<string, unknown>\n const version = typeof raw._keyVersion === 'number' ? raw._keyVersion : 1\n const key = this.keychain.get(version)\n if (!key) {\n throw new Error(`EncryptedStorageAdapter: no key found for _keyVersion ${version}`)\n }\n\n const aad = encode(JSON.stringify({ _id: doc._id, _collection: doc._collection }))\n const iv = fromBase64(raw._iv as string)\n const ciphertext = fromBase64(raw._encrypted as string)\n\n const plaintext = await crypto.subtle.decrypt(\n { name: 'AES-GCM', iv, additionalData: aad },\n key,\n ciphertext\n )\n\n const userFields = JSON.parse(new TextDecoder().decode(plaintext)) as Record<string, unknown>\n\n const metadata: Record<string, unknown> = {}\n for (const field of METADATA_FIELDS) {\n if (field in raw) metadata[field] = raw[field]\n }\n\n return { ...metadata, ...userFields } as Doc\n }\n\n async get(collection: string, id: string): Promise<Doc | null> {\n const doc = await this.inner.get(collection, id)\n if (!doc) return null\n return this.decryptDoc(doc)\n }\n\n async getRaw(collection: string, id: string): Promise<Doc | null> {\n const fn = this.inner.getRaw?.bind(this.inner) ?? this.inner.get.bind(this.inner)\n const doc = await fn(collection, id)\n if (!doc) return null\n return this.decryptDoc(doc)\n }\n\n async getMany(collection: string, filter?: Filter): Promise<Doc[]> {\n // Fetch all without filter — decrypt first, then apply filter on plaintext\n const docs = await this.inner.getMany(collection)\n const decrypted = await Promise.all(docs.map(doc => this.decryptDoc(doc)))\n if (!filter) return decrypted\n return decrypted.filter(doc =>\n Object.entries(filter).every(([k, v]) => (doc as Record<string, unknown>)[k] === v)\n )\n }\n\n async put(collection: string, id: string, doc: Doc): Promise<void> {\n // Docs arriving from sync pull are already encrypted blobs — pass through unchanged\n if (this.isEncryptedDoc(doc)) {\n return this.inner.put(collection, id, doc)\n }\n const encryptedDoc = await this.encryptDoc(doc)\n return this.inner.put(collection, id, encryptedDoc)\n }\n\n async delete(collection: string, id: string): Promise<void> {\n return this.inner.delete(collection, id)\n }\n\n /** E2E: encrypted blobs travel to the server as-is — no decryption here. */\n async getChangesSince(timestamp: number): Promise<Change[]> {\n return this.inner.getChangesSince(timestamp)\n }\n\n /** Returns raw encrypted storage representation. Do not use in production data flows. */\n async getEncrypted(collection: string, id: string): Promise<Doc | null> {\n return this.inner.get(collection, id)\n }\n}\n","import type { StorageAdapter } from './types.js'\nimport type { EncryptedStorageAdapter } from './encrypted.js'\nimport { toBase64, fromBase64, deriveAesKwKey } from './encrypted.js'\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\nexport interface ReEncryptResult {\n total: number\n reEncrypted: number\n skipped: number\n errors: string[]\n}\n\n// ─── reEncryptAll ─────────────────────────────────────────────────────────────\n\nconst BATCH_SIZE = 100\n\n/**\n * Re-encrypts all documents whose `_keyVersion` differs from `activeVersion`.\n *\n * The adapter must have a keychain containing both the old key(s) and the new\n * active key so it can decrypt with the old key and re-encrypt with the active one.\n *\n * This operation is resumable: documents already at `activeVersion` are skipped,\n * so a second run after an interruption picks up where it left off.\n */\nexport async function reEncryptAll(\n adapter: EncryptedStorageAdapter,\n innerStorage: StorageAdapter,\n activeVersion: number\n): Promise<ReEncryptResult> {\n const result: ReEncryptResult = { total: 0, reEncrypted: 0, skipped: 0, errors: [] }\n\n // Fetch all raw (encrypted) change records from underlying storage\n const changes = await innerStorage.getChangesSince(0)\n result.total = changes.length\n\n // Process in batches to limit memory pressure\n for (let i = 0; i < changes.length; i += BATCH_SIZE) {\n const batch = changes.slice(i, i + BATCH_SIZE)\n\n await Promise.all(\n batch.map(async change => {\n const raw = change.doc as Record<string, unknown>\n const keyVersion = raw._keyVersion as number | undefined\n\n // Skip docs already at the active version (resumability cursor)\n if (keyVersion === activeVersion) {\n result.skipped++\n return\n }\n\n try {\n // Decrypt with old key (adapter picks key by _keyVersion)\n const decrypted = await adapter.get(change.collection, change.id)\n if (!decrypted) {\n result.skipped++\n return\n }\n\n // Re-encrypt with active key (adapter.put always uses activeVersion)\n await adapter.put(change.collection, change.id, decrypted)\n result.reEncrypted++\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n result.errors.push(`${change.collection}/${change.id}: ${msg}`)\n }\n })\n )\n }\n\n return result\n}\n\n// ─── rewrapKey ────────────────────────────────────────────────────────────────\n\n/**\n * Re-wraps a data key under a new password without re-encrypting any documents\n * (Mode 3 — AES-KW).\n *\n * Unwraps the stored wrapped key using a key derived from `oldPassword`, then\n * re-wraps it using a key derived from `newPassword`. The salt is unchanged,\n * so documents are unaffected.\n *\n * @returns New base64-encoded wrapped key to persist in place of the old one.\n */\nexport async function rewrapKey(\n oldPassword: string,\n newPassword: string,\n wrappedKey: string,\n salt: string,\n iterations = 600_000\n): Promise<string> {\n const oldWrappingKey = await deriveAesKwKey(oldPassword, salt, iterations)\n const newWrappingKey = await deriveAesKwKey(newPassword, salt, iterations)\n\n // Unwrap the data key — must be extractable so it can be re-wrapped\n const dataKey = await crypto.subtle.unwrapKey(\n 'raw',\n fromBase64(wrappedKey),\n oldWrappingKey,\n 'AES-KW',\n { name: 'AES-GCM', length: 256 },\n true /* extractable */,\n ['encrypt', 'decrypt']\n )\n\n // Re-wrap with the new wrapping key\n const newWrappedBuf = await crypto.subtle.wrapKey('raw', dataKey, newWrappingKey, 'AES-KW')\n return toBase64(newWrappedBuf)\n}\n","import type { StorageAdapter } from './types.js'\nimport type { EncryptedStorageAdapter } from './encrypted.js'\n\nexport interface MigrationResult {\n total: number\n encrypted: number\n skipped: number\n errors: string[]\n}\n\n/**\n * Migrates all plaintext documents from `storage` into `encryptedStorage`.\n *\n * Idempotent: documents that already have `_encrypted` and `_iv` fields are skipped.\n * Handles mixed state: only plaintext documents are encrypted.\n */\nexport async function migrateToEncrypted(\n storage: StorageAdapter,\n encryptedStorage: EncryptedStorageAdapter\n): Promise<MigrationResult> {\n const changes = await storage.getChangesSince(0)\n\n const result: MigrationResult = {\n total: changes.length,\n encrypted: 0,\n skipped: 0,\n errors: [],\n }\n\n for (const change of changes) {\n const { collection, id, doc } = change\n\n if ('_encrypted' in doc && '_iv' in doc) {\n result.skipped++\n continue\n }\n\n try {\n await encryptedStorage.put(collection, id, doc)\n result.encrypted++\n } catch (err) {\n result.errors.push(\n `${collection}/${id}: ${err instanceof Error ? err.message : String(err)}`\n )\n }\n }\n\n return result\n}\n","import type { Doc } from '../schema/types.js'\n\n/**\n * Last-Write-Wins conflict resolver.\n * Compares _updatedAt timestamps; highest wins.\n * Sufficient for single-user, multi-device scenarios.\n */\nexport function resolveConflict(local: Doc, remote: Doc): Doc {\n return remote._updatedAt >= local._updatedAt ? remote : local\n}\n\n/** Always keeps the local version. */\nexport function localWins(local: Doc, _remote: Doc): Doc {\n return local\n}\n\n/** Always keeps the remote version. */\nexport function remoteWins(_local: Doc, remote: Doc): Doc {\n return remote\n}\n","import type { Doc } from '../schema/types.js'\nimport type { SyncTransport, PushPayload, PullPayload } from './types.js'\n\nexport class HttpTransport implements SyncTransport {\n private token: string | null = null\n\n constructor(private readonly endpoint: string) {}\n\n setToken(token: string | null): void {\n this.token = token\n }\n\n async push(payload: PushPayload): Promise<number> {\n const response = await this.fetchWithRetry(`${this.endpoint}/sync/push`, {\n method: 'POST',\n headers: this.buildHeaders(),\n body: JSON.stringify(payload),\n })\n if (!response.ok) {\n throw new Error(`Push failed: ${response.status} ${response.statusText}`)\n }\n return payload.changes.length\n }\n\n async pull(payload: PullPayload): Promise<Doc[]> {\n const response = await this.fetchWithRetry(`${this.endpoint}/sync/pull?since=${payload.since}`, {\n headers: this.buildHeaders(),\n })\n if (!response.ok) {\n throw new Error(`Pull failed: ${response.status} ${response.statusText}`)\n }\n const { changes } = (await response.json()) as { changes: Doc[] }\n return changes\n }\n\n destroy(): void {}\n\n private async fetchWithRetry(url: string, init: RequestInit, retries = 3): Promise<Response> {\n for (let attempt = 0; attempt <= retries; attempt++) {\n try {\n const res = await fetch(url, init)\n if (res.ok || res.status < 500) return res\n if (attempt === retries) return res\n } catch (err) {\n if (attempt === retries) throw err\n }\n const delay = Math.pow(2, attempt) * 1000 + Math.random() * 500\n await new Promise(r => setTimeout(r, delay))\n }\n throw new Error('fetchWithRetry: unreachable')\n }\n\n private buildHeaders(): Record<string, string> {\n const headers: Record<string, string> = { 'Content-Type': 'application/json' }\n if (this.token) headers['Authorization'] = `Bearer ${this.token}`\n return headers\n }\n}\n","import type { Doc } from '../schema/types.js'\nimport type { PullPayload, PushPayload, SyncTransport } from './types.js'\n\nexport interface WebSocketTransportConfig {\n url: string\n token?: string\n reconnect?: boolean\n maxReconnectAttempts?: number\n requestTimeout?: number\n onRemoteChanges?: (changes: Doc[]) => void\n onConnected?: () => void\n}\n\ninterface PendingRequest {\n resolve: (value: unknown) => void\n reject: (reason: unknown) => void\n}\n\ninterface WsMessage {\n type: string\n id?: string\n payload?: unknown\n changes?: Doc[]\n since?: number\n token?: string\n}\n\nexport class WebSocketTransport implements SyncTransport {\n private ws: WebSocket | null = null\n private readonly pending = new Map<string, PendingRequest>()\n private reconnectAttempt = 0\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null\n private destroyed = false\n private token: string | null\n\n constructor(private readonly config: WebSocketTransportConfig) {\n this.token = config.token ?? null\n if (config.url.startsWith('ws://') && typeof location !== 'undefined' && location.hostname !== 'localhost' && location.hostname !== '127.0.0.1') {\n console.warn('[OfflineKit] WebSocket connection uses insecure ws:// protocol. Use wss:// in production.')\n }\n this.connect()\n }\n\n setToken(token: string | null): void {\n this.token = token\n }\n\n async push(payload: PushPayload): Promise<number> {\n const id = this.generateId()\n await this.send({ type: 'push', id, payload })\n return payload.changes.length\n }\n\n async pull(payload: PullPayload): Promise<Doc[]> {\n const id = this.generateId()\n const result = await this.send({ type: 'pull', id, since: payload.since })\n const { changes } = result as { changes: Doc[] }\n return changes\n }\n\n destroy(): void {\n this.destroyed = true\n if (this.reconnectTimer !== null) {\n clearTimeout(this.reconnectTimer)\n this.reconnectTimer = null\n }\n for (const req of this.pending.values()) {\n req.reject(new Error('Transport destroyed'))\n }\n this.pending.clear()\n if (this.ws) {\n this.ws.close()\n this.ws = null\n }\n }\n\n private connect(): void {\n if (this.destroyed) return\n this.ws = new WebSocket(this.config.url)\n\n this.ws.onopen = () => {\n this.reconnectAttempt = 0\n if (this.token) {\n this.ws!.send(JSON.stringify({ type: 'auth', token: this.token }))\n }\n this.config.onConnected?.()\n }\n\n this.ws.onmessage = (event: MessageEvent<string>) => {\n let msg: WsMessage\n try {\n msg = JSON.parse(event.data) as WsMessage\n } catch {\n return\n }\n\n if (msg.type === 'push_ack' || msg.type === 'pull_response') {\n const pending = this.pending.get(msg.id!)\n if (pending) {\n this.pending.delete(msg.id!)\n pending.resolve(msg.payload)\n }\n } else if (msg.type === 'remote_changes') {\n this.config.onRemoteChanges?.(msg.changes ?? [])\n } else if (msg.type === 'error') {\n const pending = this.pending.get(msg.id!)\n if (pending) {\n this.pending.delete(msg.id!)\n const errPayload = msg.payload as { message?: string } | undefined\n pending.reject(new Error(errPayload?.message ?? 'WebSocket error'))\n }\n }\n }\n\n this.ws.onclose = () => {\n for (const req of this.pending.values()) {\n req.reject(new Error('WebSocket disconnected'))\n }\n this.pending.clear()\n this.scheduleReconnect()\n }\n\n this.ws.onerror = () => {\n // close event fires after error — reconnect handled there\n }\n }\n\n private scheduleReconnect(): void {\n if (this.destroyed || this.config.reconnect === false) return\n const max = this.config.maxReconnectAttempts ?? Infinity\n if (this.reconnectAttempt >= max) return\n const delay = Math.min(1000 * Math.pow(2, this.reconnectAttempt), 30000)\n const jitter = Math.random() * 200\n this.reconnectTimer = setTimeout(() => {\n this.reconnectAttempt++\n this.connect()\n }, delay + jitter)\n }\n\n private send(msg: WsMessage): Promise<unknown> {\n return new Promise((resolve, reject) => {\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {\n reject(new Error('WebSocket not connected'))\n return\n }\n const id = msg.id!\n const timeout = this.config.requestTimeout ?? 30_000\n const timer = setTimeout(() => {\n if (this.pending.has(id)) {\n this.pending.delete(id)\n reject(new Error('WebSocket request timed out'))\n }\n }, timeout)\n this.pending.set(id, {\n resolve: (value) => { clearTimeout(timer); resolve(value) },\n reject: (reason) => { clearTimeout(timer); reject(reason) },\n })\n this.ws.send(JSON.stringify(msg))\n })\n }\n\n private generateId(): string {\n const bytes = new Uint8Array(16) // 128 bits\n crypto.getRandomValues(bytes)\n const hex = Array.from(bytes).map(b => b.toString(16).padStart(2, '0')).join('')\n return `${Date.now()}-${hex}`\n }\n}\n","import type { Doc } from '../schema/types.js'\nimport type { PullPayload, PushPayload, SyncTransport } from './types.js'\nimport { HttpTransport } from './transport.js'\nimport { WebSocketTransport } from './ws-transport.js'\n\nexport interface AutoTransportConfig {\n wsUrl: string\n httpEndpoint: string\n token?: string\n onRemoteChanges?: (changes: Doc[]) => void\n}\n\nexport class AutoTransport implements SyncTransport {\n private readonly ws: WebSocketTransport\n private readonly http: HttpTransport\n private useWs = true\n\n constructor(config: AutoTransportConfig) {\n this.http = new HttpTransport(config.httpEndpoint)\n if (config.token) {\n this.http.setToken(config.token)\n }\n this.ws = new WebSocketTransport({\n url: config.wsUrl,\n token: config.token,\n reconnect: true,\n maxReconnectAttempts: 3,\n onRemoteChanges: config.onRemoteChanges,\n onConnected: () => {\n this.useWs = true\n },\n })\n }\n\n setToken(token: string | null): void {\n this.ws.setToken(token)\n this.http.setToken(token)\n }\n\n async push(payload: PushPayload): Promise<number> {\n if (this.useWs) {\n try {\n return await this.ws.push(payload)\n } catch {\n this.useWs = false\n }\n }\n return this.http.push(payload)\n }\n\n async pull(payload: PullPayload): Promise<Doc[]> {\n if (this.useWs) {\n try {\n return await this.ws.pull(payload)\n } catch {\n this.useWs = false\n }\n }\n return this.http.pull(payload)\n }\n\n destroy(): void {\n this.ws.destroy()\n this.http.destroy()\n }\n}\n","import type { StorageAdapter } from '../storage/types.js'\nimport type { Doc } from '../schema/types.js'\nimport type { SyncConfig, SyncStatus, SyncResult, SyncTransport } from './types.js'\nimport { resolveConflict } from './conflict.js'\nimport { HttpTransport } from './transport.js'\nimport { WebSocketTransport } from './ws-transport.js'\nimport { AutoTransport } from './auto-transport.js'\n\nconst SYNC_META_COLLECTION = '_sync_meta'\n\ninterface SyncEventMap {\n 'sync:start': () => void\n 'sync:complete': (result: SyncResult) => void\n 'sync:error': (error: unknown) => void\n}\ntype SyncEventType = keyof SyncEventMap\n\nexport class SyncEngine {\n private status: SyncStatus = 'idle'\n private lastSyncAt: number = 0\n private lastSyncAtInitialized = false\n /** Typed listener map: values are SyncEventMap[E][] per event key. */\n private readonly listenerMap = new Map<SyncEventType, SyncEventMap[SyncEventType][]>()\n private transport: SyncTransport\n private readonly lastSyncKey: string\n\n constructor(\n private readonly storage: StorageAdapter,\n private readonly config: SyncConfig,\n ) {\n this.lastSyncKey = `last_sync_at_${config.endpoint}`\n this.transport = this.resolveTransport(config)\n }\n\n /**\n * Return the current sync status.\n *\n * @returns The current {@link SyncStatus} (`'idle'`, `'syncing'`, `'error'`, or `'offline'`).\n */\n getStatus(): SyncStatus { return this.status }\n\n /**\n * Return the timestamp of the last successful sync.\n *\n * @returns Epoch timestamp (ms), or `0` if no sync has completed yet.\n */\n getLastSyncAt(): number { return this.lastSyncAt }\n\n /**\n * Set the bearer token used by the transport for authenticated requests.\n *\n * @param token - The bearer token string, or `null` to clear it.\n */\n setToken(token: string | null): void {\n this.transport.setToken?.(token)\n }\n\n /**\n * Register a listener for sync events.\n *\n * @param event - The event type to listen for.\n * @param listener - The callback to invoke when the event fires.\n */\n on<E extends SyncEventType>(event: E, listener: SyncEventMap[E]): void {\n const existing = this.listenerMap.get(event) ?? []\n this.listenerMap.set(event, [...existing, listener])\n }\n\n /**\n * Remove a previously registered sync event listener.\n *\n * @param event - The event type.\n * @param listener - The callback to remove.\n */\n off<E extends SyncEventType>(event: E, listener: SyncEventMap[E]): void {\n const existing = this.listenerMap.get(event) ?? []\n this.listenerMap.set(event, existing.filter(l => l !== listener))\n }\n\n /**\n * Push local changes to the server.\n *\n * @returns The number of documents pushed.\n */\n async push(): Promise<number> {\n const changes = await this.storage.getChangesSince(this.lastSyncAt)\n if (changes.length === 0) return 0\n return this.transport.push({ changes, lastSyncAt: this.lastSyncAt })\n }\n\n /**\n * Pull remote changes from the server. Applies conflict resolution for\n * documents that exist both locally and remotely.\n *\n * @returns An object with `pulled` (total remote docs received) and `conflicts` (local-wins count).\n */\n async pull(): Promise<{ pulled: number; conflicts: number }> {\n const remoteChanges = await this.transport.pull({ since: this.lastSyncAt })\n let conflicts = 0\n\n const validRemote = remoteChanges.filter(doc => {\n if (typeof doc._id !== 'string' || typeof doc._collection !== 'string' ||\n typeof doc._updatedAt !== 'number' || typeof doc._deleted !== 'boolean') {\n console.warn('[OfflineKit] Skipping invalid remote document:', doc._id)\n return false\n }\n return true\n })\n\n for (const remote of validRemote) {\n const local = this.storage.getRaw\n ? await this.storage.getRaw(remote._collection, remote._id)\n : await this.storage.get(remote._collection, remote._id)\n\n let docToStore: Doc = remote\n if (local) {\n const resolver = this.config.conflictResolver ?? resolveConflict\n const resolved = resolver(local, remote)\n if (resolved === local) {\n conflicts++\n continue // local wins — keep it\n }\n docToStore = resolved\n }\n\n if (docToStore._deleted) {\n await this.storage.delete(docToStore._collection, docToStore._id)\n } else {\n await this.storage.put(docToStore._collection, docToStore._id, docToStore)\n }\n }\n\n return { pulled: validRemote.length, conflicts }\n }\n\n /**\n * Run a full push+pull sync cycle. Pushes local changes first, then pulls\n * remote changes. Updates the last-sync timestamp on success.\n *\n * @returns A {@link SyncResult} with pushed, pulled, and conflicts counts.\n */\n async sync(): Promise<SyncResult> {\n if (!this.config.enabled) return { pushed: 0, pulled: 0, conflicts: 0 }\n if (this.status === 'syncing') return { pushed: 0, pulled: 0, conflicts: 0 }\n const isOnline = typeof navigator !== 'undefined' ? navigator.onLine : true\n if (!isOnline) {\n this.setStatus('offline')\n return { pushed: 0, pulled: 0, conflicts: 0 }\n }\n\n // Set status synchronously before any await to prevent concurrent syncs\n this.setStatus('syncing')\n this.emit('sync:start')\n\n try {\n if (!this.lastSyncAtInitialized) {\n this.lastSyncAt = await this.loadLastSyncAt()\n this.lastSyncAtInitialized = true\n }\n\n const pushed = await this.push()\n const { pulled, conflicts } = await this.pull()\n\n this.lastSyncAt = Date.now()\n await this.saveLastSyncAt(this.lastSyncAt)\n this.setStatus('idle')\n\n const result: SyncResult = { pushed, pulled, conflicts }\n this.emit('sync:complete', result)\n return result\n } catch (err) {\n const browserOffline = typeof navigator !== 'undefined' ? !navigator.onLine : false\n const isOffline = browserOffline || (err instanceof TypeError && err.message.includes('fetch'))\n this.setStatus(isOffline ? 'offline' : 'error')\n this.emit('sync:error', err)\n return { pushed: 0, pulled: 0, conflicts: 0, error: err instanceof Error ? err : new Error(String(err)) }\n }\n }\n\n /**\n * Clean up the transport (close WebSocket connections, etc.).\n * Call this when the sync engine is no longer needed.\n */\n destroy(): void {\n this.transport.destroy()\n }\n\n private resolveTransport(config: SyncConfig): SyncTransport {\n const t = config.transport\n if (!t || t === 'http') return new HttpTransport(config.endpoint)\n // Derive WS URL: replace protocol, strip trailing /sync if present, append /ws\n const wsUrl = config.endpoint.replace(/^http/, 'ws').replace(/\\/sync\\/?$/, '') + '/ws'\n if (t === 'websocket') {\n return new WebSocketTransport({ url: wsUrl })\n }\n if (t === 'auto') {\n return new AutoTransport({ wsUrl, httpEndpoint: config.endpoint })\n }\n return t // already a SyncTransport instance\n }\n\n private setStatus(status: SyncStatus): void { this.status = status }\n\n private emit<E extends SyncEventType>(event: E, ...args: Parameters<SyncEventMap[E]>): void {\n const listeners = (this.listenerMap.get(event) ?? []) as Array<SyncEventMap[E]>\n for (const listener of listeners) {\n (listener as (...a: Parameters<SyncEventMap[E]>) => void)(...args)\n }\n }\n\n private async loadLastSyncAt(): Promise<number> {\n try {\n const doc = await this.storage.get(SYNC_META_COLLECTION, this.lastSyncKey)\n const val: unknown = doc !== null ? doc['value'] : undefined\n return typeof val === 'number' ? val : 0\n } catch {\n return 0\n }\n }\n\n private async saveLastSyncAt(ts: number): Promise<void> {\n try {\n await this.storage.put(SYNC_META_COLLECTION, this.lastSyncKey, {\n _id: this.lastSyncKey,\n _collection: SYNC_META_COLLECTION,\n _updatedAt: ts,\n _deleted: false,\n value: ts,\n })\n } catch {\n // storage unavailable — ignore\n }\n }\n}\n","import type { SyncEngine } from './engine.js'\nimport type { SyncConfig } from './types.js'\n\n/** Syncs when the user returns to the tab (visibilitychange → visible) */\nexport function setupFocusTrigger(engine: SyncEngine, config: SyncConfig): () => void {\n const handler = () => {\n if (document.visibilityState === 'visible' && config.enabled) {\n void engine.sync()\n }\n }\n document.addEventListener('visibilitychange', handler)\n return () => document.removeEventListener('visibilitychange', handler)\n}\n\n/** Syncs when the network comes back online */\nexport function setupReconnectTrigger(engine: SyncEngine, config: SyncConfig): () => void {\n const handler = () => {\n if (config.enabled) void engine.sync()\n }\n window.addEventListener('online', handler)\n return () => window.removeEventListener('online', handler)\n}\n\n/** Periodic sync at the configured interval while online */\nexport function setupIntervalTrigger(engine: SyncEngine, config: SyncConfig): () => void {\n const ms = config.interval > 0 ? config.interval : 30_000\n const id = setInterval(() => {\n if (config.enabled && navigator.onLine) void engine.sync()\n }, ms)\n return () => clearInterval(id)\n}\n","const ITERATIONS = 600_000\nconst HASH_ALGO = 'SHA-256'\nconst KEY_LENGTH = 32 // bytes\nconst SALT_LENGTH = 16 // bytes\n\nfunction toHex(bytes: Uint8Array): string {\n return Array.from(bytes)\n .map(b => b.toString(16).padStart(2, '0'))\n .join('')\n}\n\nasync function deriveKey(password: string, salt: Uint8Array): Promise<string> {\n const enc = new TextEncoder()\n const keyMaterial = await crypto.subtle.importKey(\n 'raw',\n enc.encode(password),\n 'PBKDF2',\n false,\n ['deriveBits'],\n )\n const derivedBits = await crypto.subtle.deriveBits(\n {\n name: 'PBKDF2',\n salt: salt as BufferSource,\n iterations: ITERATIONS,\n hash: HASH_ALGO,\n },\n keyMaterial,\n KEY_LENGTH * 8,\n )\n return toHex(new Uint8Array(derivedBits))\n}\n\n/**\n * Hashes a password client-side using PBKDF2 + Web Crypto API.\n * Returns a `salt_hex:hash_hex` string. The server receives only the hash — never the plaintext.\n *\n * A cryptographically random 16-byte salt is generated per call so that the same\n * password always produces a unique output. Use verifyPassword() to check passwords.\n */\nexport async function hashPassword(password: string, _email?: string): Promise<string> {\n if (!password) throw new Error('Password must not be empty')\n const salt = crypto.getRandomValues(new Uint8Array(SALT_LENGTH))\n const hashHex = await deriveKey(password, salt)\n return `${toHex(salt)}:${hashHex}`\n}\n\n/**\n * Verifies a password against a stored hash produced by hashPassword().\n * The storedHash must be in `salt_hex:hash_hex` format.\n * Uses a timing-safe comparison to prevent side-channel leakage.\n */\nexport async function verifyPassword(password: string, storedHash: string): Promise<boolean> {\n const colonIndex = storedHash.indexOf(':')\n if (colonIndex === -1) return false\n const saltHex = storedHash.slice(0, colonIndex)\n const hashHex = storedHash.slice(colonIndex + 1)\n const saltBytes = saltHex.match(/.{2}/g)\n if (!saltBytes || saltBytes.length !== SALT_LENGTH) return false\n const salt = new Uint8Array(saltBytes.map(b => parseInt(b, 16)))\n const derived = await deriveKey(password, salt)\n if (derived.length !== hashHex.length) return false\n let result = 0\n for (let i = 0; i < derived.length; i++) {\n result |= derived.charCodeAt(i) ^ hashHex.charCodeAt(i)\n }\n return result === 0\n}\n","import type { User } from './types.js'\n\nconst TOKEN_KEY = '__offlinekit_token'\nconst USER_KEY = '__offlinekit_user'\n\nexport interface StoredSession {\n user: User\n token: string\n}\n\n/**\n * Persist session to localStorage for offline access.\n *\n * **Security note:** Tokens stored in localStorage are accessible to any JavaScript\n * running on the page. Mitigate XSS risk with Content-Security-Policy headers\n * and input sanitization. Consider HttpOnly cookies for high-security applications.\n */\nexport function saveSession(session: StoredSession): void {\n try {\n localStorage.setItem(TOKEN_KEY, session.token)\n localStorage.setItem(USER_KEY, JSON.stringify(session.user))\n } catch {\n // localStorage unavailable — session is in-memory only\n }\n}\n\nexport function loadSession(): StoredSession | null {\n try {\n const token = localStorage.getItem(TOKEN_KEY)\n const userRaw = localStorage.getItem(USER_KEY)\n if (!token || !userRaw) return null\n const parsed = JSON.parse(userRaw) as Record<string, unknown>\n if (typeof parsed.id !== 'string' || typeof parsed.email !== 'string') return null\n return { token, user: { id: parsed.id, email: parsed.email } }\n } catch {\n return null\n }\n}\n\nexport function clearSession(): void {\n try {\n localStorage.removeItem(TOKEN_KEY)\n localStorage.removeItem(USER_KEY)\n } catch {\n /* localStorage unavailable (SSR or quota exceeded) */\n }\n}\n","import type { AuthAdapter, Credentials, User } from './types.js'\nimport { hashPassword, verifyPassword } from './pbkdf2.js'\nimport { clearSession, loadSession, saveSession } from './session.js'\n\nexport interface EmailPasswordAuthConfig {\n endpoint: string\n}\n\ninterface AuthResponse {\n user: User\n token: string\n}\n\n/**\n * Email + password auth adapter.\n * - Hashes password client-side (PBKDF2) before sending\n * - Stores JWT + user in localStorage for offline access\n * - Exposes getToken() for the sync engine to attach to requests\n */\nexport class EmailPasswordAuth implements AuthAdapter {\n private session = loadSession()\n\n constructor(private readonly config: EmailPasswordAuthConfig) {}\n\n async signUp(credentials: Credentials): Promise<User> {\n if (!credentials.email) throw new Error('Email is required')\n if (!credentials.password) throw new Error('Password is required')\n const passwordHash = await hashPassword(credentials.password)\n const res = await fetch(`${this.config.endpoint}/auth/signup`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ email: credentials.email, passwordHash }),\n })\n\n if (!res.ok) {\n const body = (await res.json().catch(() => ({}))) as { error?: string }\n throw new Error(body.error ?? `Sign-up failed: ${res.status}`)\n }\n\n const data = (await res.json()) as AuthResponse\n this.session = { user: data.user, token: data.token }\n saveSession(this.session)\n return data.user\n }\n\n async signIn(credentials: Credentials): Promise<User> {\n if (!credentials.email) throw new Error('Email is required')\n if (!credentials.password) throw new Error('Password is required')\n\n const hashRes = await fetch(`${this.config.endpoint}/auth/hash`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ email: credentials.email }),\n })\n\n if (hashRes.ok) {\n const { passwordHash } = (await hashRes.json()) as { passwordHash?: string }\n if (passwordHash) {\n const valid = await verifyPassword(credentials.password, passwordHash)\n if (!valid) {\n throw new Error('Invalid credentials')\n }\n }\n }\n\n const passwordHash = await hashPassword(credentials.password)\n const res = await fetch(`${this.config.endpoint}/auth/signin`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ email: credentials.email, passwordHash }),\n })\n\n if (!res.ok) {\n const body = (await res.json().catch(() => ({}))) as { error?: string }\n throw new Error(body.error ?? `Sign-in failed: ${res.status}`)\n }\n\n const data = (await res.json()) as AuthResponse\n this.session = { user: data.user, token: data.token }\n saveSession(this.session)\n return data.user\n }\n\n async signOut(): Promise<void> {\n const token = this.session?.token\n this.session = null\n clearSession()\n\n if (token) {\n await fetch(`${this.config.endpoint}/auth/signout`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` },\n }).catch(() => {\n // Fire-and-forget — local session is already cleared\n })\n }\n }\n\n currentUser(): User | null {\n return this.session?.user ?? null\n }\n\n getToken(): string | null {\n return this.session?.token ?? null\n }\n}\n","import type { Credentials, SocialAuthAdapter, SocialProvider, User } from './types.js'\nimport { clearSession, loadSession, saveSession } from './session.js'\n\n/**\n * Better Auth response envelope — all client methods return { data, error }.\n * @see https://www.better-auth.com/docs/basic-usage\n */\nexport interface BetterAuthResponse<T> {\n data: T | null\n error: { message: string; status?: number } | null\n}\n\n/** Core user fields returned by Better Auth */\nexport interface BetterAuthUser {\n id: string\n email: string\n name: string\n image?: string | null\n emailVerified?: boolean\n createdAt?: Date\n updatedAt?: Date\n [key: string]: unknown\n}\n\n/**\n * Minimal interface matching Better Auth's createAuthClient() return type.\n * Requires the bearer plugin on the server for token-based auth.\n *\n * @see https://www.better-auth.com/docs/plugins/bearer\n */\nexport interface BetterAuthClient {\n signUp: {\n email: (opts: {\n email: string\n password: string\n name: string\n }) => Promise<BetterAuthResponse<{ user: BetterAuthUser; token: string | null }>>\n }\n signIn: {\n email: (opts: {\n email: string\n password: string\n }) => Promise<BetterAuthResponse<{ user: BetterAuthUser; token: string }>>\n social: (opts: {\n provider: string\n }) => Promise<BetterAuthResponse<{\n url?: string\n redirect?: boolean\n user?: BetterAuthUser\n token?: string\n }>>\n }\n signOut: () => Promise<BetterAuthResponse<null>>\n getSession: () => Promise<BetterAuthResponse<{\n session: { id: string; token: string; userId: string; expiresAt: Date }\n user: BetterAuthUser\n }>>\n}\n\nexport interface BetterAuthAdapterConfig {\n client: BetterAuthClient\n trustedOrigins?: string[]\n}\n\nfunction unwrap<T>(result: BetterAuthResponse<T>, context: string): T {\n if (result.error) {\n throw new Error(result.error.message ?? `Better Auth ${context} failed`)\n }\n if (!result.data) {\n throw new Error(`Better Auth ${context}: no data returned`)\n }\n return result.data\n}\n\nfunction toUser(baUser: BetterAuthUser): User {\n return { id: baUser.id, email: baUser.email }\n}\n\nexport class BetterAuthAdapter implements SocialAuthAdapter {\n private session = loadSession()\n\n constructor(private readonly config: BetterAuthAdapterConfig) {}\n\n /**\n * Revalidate the stored session against the server.\n * Call on app startup to verify a cached bearer token is still valid.\n * On network failure the cached session is kept for offline use.\n */\n async revalidateSession(): Promise<User | null> {\n if (!this.session?.token) return null\n try {\n const result = await this.config.client.getSession()\n if (result.error || !result.data) {\n this.session = null\n clearSession()\n return null\n }\n const user = toUser(result.data.user)\n const token = result.data.session.token\n this.session = { user, token }\n saveSession(this.session)\n return user\n } catch {\n // Network error — keep cached session for offline use\n return this.session?.user ?? null\n }\n }\n\n async signUp(credentials: Credentials): Promise<User> {\n const name = credentials.name ?? credentials.email.split('@')[0]\n const result = await this.config.client.signUp.email({\n email: credentials.email,\n password: credentials.password,\n name,\n })\n const data = unwrap(result, 'signUp')\n const user = toUser(data.user)\n const token = data.token\n if (token) {\n this.session = { user, token }\n saveSession(this.session)\n }\n return user\n }\n\n async signIn(credentials: Credentials): Promise<User> {\n const result = await this.config.client.signIn.email({\n email: credentials.email,\n password: credentials.password,\n })\n const data = unwrap(result, 'signIn')\n const user = toUser(data.user)\n this.session = { user, token: data.token }\n saveSession(this.session)\n return user\n }\n\n async signInWithSocial(provider: SocialProvider): Promise<User> {\n const result = await this.config.client.signIn.social({ provider })\n const data = unwrap(result, 'signInWithSocial')\n\n // If idToken was provided, user data is returned directly (no redirect)\n if (data.user && data.token) {\n const user = toUser(data.user)\n this.session = { user, token: data.token }\n saveSession(this.session)\n return user\n }\n\n // Standard OAuth: triggers browser redirect, page navigates away.\n // Session is picked up via revalidateSession() after the OAuth callback.\n if (data.url && typeof window !== 'undefined') {\n const url = new URL(data.url)\n const trusted = this.config.trustedOrigins ?? [window.location.origin]\n if (!trusted.includes(url.origin)) {\n throw new Error(`Untrusted redirect URL origin: ${url.origin}`)\n }\n window.location.href = data.url\n }\n throw new Error(\n 'Social sign-in initiated OAuth redirect. ' +\n 'Call revalidateSession() after the callback to load the session.',\n )\n }\n\n async signOut(): Promise<void> {\n this.session = null\n clearSession()\n try {\n await this.config.client.signOut()\n } catch {\n // Server unreachable — local session already cleared\n }\n }\n\n currentUser(): User | null {\n return this.session?.user ?? null\n }\n\n getToken(): string | null {\n return this.session?.token ?? null\n }\n}\n","import type { AuthAdapter, Credentials, OfflineSession, User } from './types.js'\n\nconst OFFLINE_SESSION_KEY = '__offlinekit_offline_session'\n\nfunction saveOfflineSession(session: OfflineSession): void {\n try {\n localStorage.setItem(OFFLINE_SESSION_KEY, JSON.stringify(session))\n } catch { /* localStorage unavailable (SSR or quota exceeded) */ }\n}\n\nfunction loadOfflineSession(): OfflineSession | null {\n try {\n const raw = localStorage.getItem(OFFLINE_SESSION_KEY)\n if (!raw) return null\n const parsed = JSON.parse(raw) as Record<string, unknown>\n if (typeof parsed.token !== 'string' || typeof parsed.expiresAt !== 'number' ||\n !parsed.user || typeof (parsed.user as Record<string, unknown>).id !== 'string') return null\n return parsed as unknown as OfflineSession\n } catch {\n return null\n }\n}\n\nfunction clearOfflineSession(): void {\n try {\n localStorage.removeItem(OFFLINE_SESSION_KEY)\n } catch { /* localStorage unavailable (SSR or quota exceeded) */ }\n}\n\nfunction isOffline(): boolean {\n return typeof navigator !== 'undefined' && !navigator.onLine\n}\n\nexport class OfflineSessionAdapter implements AuthAdapter {\n constructor(\n private readonly inner: AuthAdapter,\n private readonly cacheDuration = 7 * 24 * 60 * 60 * 1000,\n ) {}\n\n async signUp(credentials: Credentials): Promise<User> {\n const user = await this.inner.signUp(credentials)\n const token = this.inner.getToken() ?? ''\n saveOfflineSession({ user, token, expiresAt: Date.now() + this.cacheDuration, provider: 'email' })\n return user\n }\n\n async signIn(credentials: Credentials): Promise<User> {\n try {\n const user = await this.inner.signIn(credentials)\n const token = this.inner.getToken() ?? ''\n saveOfflineSession({ user, token, expiresAt: Date.now() + this.cacheDuration, provider: 'email' })\n return user\n } catch (err) {\n if (isOffline()) {\n const cached = loadOfflineSession()\n if (cached && cached.expiresAt > Date.now()) {\n return cached.user\n }\n }\n throw err\n }\n }\n\n async signOut(): Promise<void> {\n clearOfflineSession()\n await this.inner.signOut()\n }\n\n currentUser(): User | null {\n const inner = this.inner.currentUser()\n if (inner) return inner\n const cached = loadOfflineSession()\n if (cached && cached.expiresAt > Date.now()) return cached.user\n return null\n }\n\n getToken(): string | null {\n const inner = this.inner.getToken()\n if (inner) return inner\n const cached = loadOfflineSession()\n if (cached && cached.expiresAt > Date.now()) return cached.token\n return null\n }\n}\n","import { generateId } from '../storage/id.js'\nimport type { StorageAdapter } from '../storage/types.js'\nimport type { ErrorConfig, ErrorContext, ErrorEntry, ErrorSnapshot, ErrorType } from './types.js'\n\nconst ERRORS_COLLECTION = '_errors'\n\n/**\n * Low-level error tracker that persists errors to a StorageAdapter.\n * Supports snapshot capture, webhook delivery with retry, and automatic pruning.\n */\nexport class ErrorTracker {\n constructor(\n private readonly storage: StorageAdapter,\n private readonly config: ErrorConfig,\n ) {}\n\n /**\n * Retrieve all stored error entries.\n *\n * @returns An array of all persisted {@link ErrorEntry} records.\n */\n async getAll(): Promise<ErrorEntry[]> {\n const docs = await this.storage.getMany(ERRORS_COLLECTION)\n return docs as unknown as ErrorEntry[]\n }\n\n /**\n * Clear all stored error entries (soft-deletes them from storage).\n */\n async clear(): Promise<void> {\n const all = await this.storage.getMany(ERRORS_COLLECTION)\n for (const entry of all) {\n await this.storage.delete(ERRORS_COLLECTION, entry._id)\n }\n }\n\n /**\n * Capture an error and persist it to storage. Triggers the `onError` callback\n * and webhook (if configured), then prunes old entries if over the limit.\n *\n * @param error - The Error instance to capture.\n * @param type - The error category (e.g. `'unhandled_exception'`, `'sync_error'`).\n * @param context - Optional additional context merged with auto-detected fields.\n */\n async capture(\n error: Error,\n type: ErrorType,\n context?: Partial<ErrorContext>,\n ): Promise<void> {\n if (!this.config.enabled) return\n\n const now = Date.now()\n const entry: ErrorEntry = {\n _id: generateId(),\n _collection: ERRORS_COLLECTION,\n _updatedAt: now,\n _deleted: false,\n timestamp: now,\n type,\n message: error.message,\n stack: error.stack,\n context: {\n online: typeof navigator !== 'undefined' ? navigator.onLine : true,\n userAgent: typeof navigator !== 'undefined' ? navigator.userAgent : 'unknown',\n ...context,\n },\n ...(this.config.snapshot ? { snapshot: await this.captureSnapshot() } : {}),\n }\n\n await this.storage.put(ERRORS_COLLECTION, entry._id, entry)\n this.config.onError?.(entry)\n if (this.config.webhookUrl) {\n this.sendWebhook(this.config.webhookUrl, entry)\n }\n await this.pruneIfNeeded()\n }\n\n private sendWebhook(url: string, entry: ErrorEntry): void {\n const send = async (attempt: number): Promise<void> => {\n try {\n const res = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'User-Agent': 'localkit-error-tracker',\n },\n body: JSON.stringify(entry),\n })\n if (res.ok) return\n if (res.status === 429) {\n this.reportWebhookFailure(url)\n return\n }\n if (attempt < 3) {\n const jitter = Math.random() * 500\n const delay = Math.pow(2, attempt) * 1000 + jitter\n await new Promise(r => setTimeout(r, delay))\n return send(attempt + 1)\n }\n this.reportWebhookFailure(url)\n } catch {\n if (attempt < 3) {\n const jitter = Math.random() * 500\n const delay = Math.pow(2, attempt) * 1000 + jitter\n await new Promise(r => setTimeout(r, delay))\n return send(attempt + 1)\n }\n this.reportWebhookFailure(url)\n }\n }\n send(0)\n }\n\n private reportWebhookFailure(url: string): void {\n if (this.config.onError) {\n const now = Date.now()\n this.config.onError({\n _id: '',\n _collection: '_errors',\n _updatedAt: now,\n _deleted: false,\n type: 'runtime',\n message: `Webhook delivery failed after retries: ${url}`,\n timestamp: now,\n context: { online: typeof navigator !== 'undefined' ? navigator.onLine : true },\n })\n }\n }\n\n private async captureSnapshot(): Promise<ErrorSnapshot> {\n const snapshot: ErrorSnapshot = {}\n\n try {\n let total = 0\n for (let i = 0; i < localStorage.length; i++) {\n const k = localStorage.key(i) ?? ''\n total += k.length + (localStorage.getItem(k)?.length ?? 0)\n }\n snapshot.localStorageSize = total\n } catch {\n // localStorage unavailable\n }\n\n return snapshot\n }\n\n private async pruneIfNeeded(): Promise<void> {\n const all = await this.storage.getMany(ERRORS_COLLECTION)\n if (all.length <= this.config.maxLocalErrors) return\n\n // Sort by timestamp ascending, delete oldest\n const sorted = [...all].sort((a, b) => (a._updatedAt ?? 0) - (b._updatedAt ?? 0))\n const toDelete = sorted.slice(0, all.length - this.config.maxLocalErrors)\n for (const entry of toDelete) {\n await this.storage.delete(ERRORS_COLLECTION, entry._id)\n }\n }\n}\n","// Error tracking — capture, store, sync\nexport type { ErrorEntry, ErrorContext, ErrorSnapshot, ErrorType, ErrorConfig } from './types.js'\nexport { ErrorTracker } from './tracker.js'\nexport { setupGlobalHandler, wrapSyncErrors } from './handlers.js'\n\nimport type { StorageAdapter } from '../storage/types.js'\nimport type { ErrorConfig, ErrorContext, ErrorEntry, ErrorType } from './types.js'\nimport { ErrorTracker } from './tracker.js'\n\nconst DEFAULT_CONFIG: ErrorConfig = {\n enabled: true,\n snapshot: true,\n maxLocalErrors: 100,\n}\n\n/** High-level API for error tracking wired into createApp. */\nexport class ErrorManager {\n private readonly tracker: ErrorTracker\n\n constructor(storage: StorageAdapter, config: Partial<ErrorConfig> = {}) {\n this.tracker = new ErrorTracker(storage, { ...DEFAULT_CONFIG, ...config })\n }\n\n /**\n * Capture an error and persist it to storage. Triggers the `onError` callback\n * and webhook (if configured), then prunes old entries if over the limit.\n *\n * @param error - The Error instance to capture.\n * @param type - The error category (defaults to `'unhandled_exception'`).\n * @param context - Optional additional context (online status, user agent, etc.).\n */\n async capture(\n error: Error,\n type: ErrorType = 'unhandled_exception',\n context?: Partial<ErrorContext>,\n ): Promise<void> {\n return this.tracker.capture(error, type, context)\n }\n\n /**\n * Retrieve all stored error entries.\n *\n * @returns An array of all persisted {@link ErrorEntry} records.\n */\n async getAll(): Promise<ErrorEntry[]> {\n return this.tracker.getAll()\n }\n\n /**\n * Clear all stored error entries (soft-deletes them from storage).\n */\n async clear(): Promise<void> {\n return this.tracker.clear()\n }\n\n /**\n * Expose the underlying tracker for handler wiring (e.g. global error handlers).\n *\n * @returns The {@link ErrorTracker} instance.\n */\n getTracker(): ErrorTracker {\n return this.tracker\n }\n}\n","export interface QueryOptions<T> {\n where?: WhereClause<T>\n sort?: Partial<Record<keyof T, 'asc' | 'desc'>>\n limit?: number\n offset?: number\n}\n\nexport type WhereClause<T> = {\n [K in keyof T]?: T[K] | { $gt?: T[K]; $lt?: T[K]; $gte?: T[K]; $lte?: T[K]; $in?: T[K][] }\n}\n\ntype FieldCondition<V> = { $gt?: V; $lt?: V; $gte?: V; $lte?: V; $in?: V[] }\n\nfunction isCondition<V>(value: unknown): value is FieldCondition<V> {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return false\n const keys = Object.keys(value)\n return keys.some(k => k === '$gt' || k === '$lt' || k === '$gte' || k === '$lte' || k === '$in')\n}\n\nexport function matchesWhere<T>(doc: T, where: WhereClause<T>): boolean {\n for (const key of Object.keys(where) as Array<keyof T>) {\n const condition = where[key]\n const docValue = doc[key]\n\n if (isCondition<T[typeof key]>(condition)) {\n if (condition.$gt != null && !(docValue > condition.$gt)) return false\n if (condition.$lt != null && !(docValue < condition.$lt)) return false\n if (condition.$gte != null && !(docValue >= condition.$gte)) return false\n if (condition.$lte != null && !(docValue <= condition.$lte)) return false\n if (condition.$in !== undefined && !condition.$in.includes(docValue)) return false\n } else {\n if (docValue !== condition) return false\n }\n }\n return true\n}\n\nexport function applySort<T>(docs: T[], sort: Partial<Record<keyof T, 'asc' | 'desc'>>): T[] {\n const entries = Object.entries(sort) as Array<[keyof T, 'asc' | 'desc']>\n if (entries.length === 0) return docs\n\n return [...docs].sort((a, b) => {\n for (const [field, direction] of entries) {\n const av = a[field]\n const bv = b[field]\n if (av === bv) continue\n const cmp = av < bv ? -1 : 1\n return direction === 'asc' ? cmp : -cmp\n }\n return 0\n })\n}\n\nexport function applyQuery<T>(docs: T[], options: QueryOptions<T>): T[] {\n let result = docs\n\n if (options.where) {\n const where = options.where\n result = result.filter(doc => matchesWhere(doc, where))\n }\n\n if (options.sort) {\n result = applySort(result, options.sort)\n }\n\n const offset = options.offset ?? 0\n if (offset > 0) {\n result = result.slice(offset)\n }\n\n if (options.limit !== undefined) {\n result = result.slice(0, options.limit)\n }\n\n return result\n}\n","import type { ZodObject, ZodRawShape } from 'zod'\nimport type { Doc, WithMeta } from '../schema/types.js'\nimport { generateId } from '../storage/id.js'\nimport type { StorageAdapter } from '../storage/types.js'\nimport type { QueryOptions } from '../storage/query.js'\nimport { applyQuery } from '../storage/query.js'\n\n/**\n * A collection that supports reactive subscriptions.\n * Compatible with React's `useSyncExternalStore` via `subscribe` + `getSnapshot`.\n */\nexport interface ObservableCollection<T> extends Collection<T> {\n /**\n * Subscribe to collection changes. The listener is called whenever the\n * in-memory snapshot is refreshed (after any mutation).\n * Compatible with `useSyncExternalStore`.\n *\n * @param listener - Callback invoked on every snapshot change.\n * @returns An unsubscribe function.\n */\n subscribe(listener: () => void): () => void\n\n /**\n * Get the current in-memory snapshot of all documents.\n *\n * @returns A read-only array of all non-deleted documents.\n */\n getSnapshot(): ReadonlyArray<WithMeta<T>>\n}\n\nexport interface Collection<T> {\n /** The name of this collection. */\n readonly name: string\n\n /**\n * Create a new document, auto-generating `_id` and metadata fields\n * (`_collection`, `_updatedAt`, `_deleted`).\n *\n * @param data - The user-defined fields for the document.\n * @returns The created document with all metadata fields populated.\n *\n * @example\n * ```ts\n * const todo = await todos.create({ title: 'Buy milk', done: false })\n * console.log(todo._id) // auto-generated\n * ```\n */\n create(data: T): Promise<WithMeta<T>>\n\n /**\n * Query documents with optional where, sort, limit, and offset filters.\n *\n * @param options - Optional query options (where, sort, limit, offset).\n * @returns An array of matching documents.\n *\n * @example\n * ```ts\n * const active = await todos.findMany({\n * where: { done: { $eq: false } },\n * sort: { field: 'title', direction: 'asc' },\n * limit: 10,\n * })\n * ```\n */\n findMany(options?: QueryOptions<T>): Promise<WithMeta<T>[]>\n\n /**\n * Find a single document by ID. Returns `null` if not found.\n *\n * @param id - The document ID.\n * @returns The document, or `null` if not found or deleted.\n */\n findOne(id: string): Promise<WithMeta<T> | null>\n\n /**\n * Partially update a document. Validates the merged result against the schema.\n *\n * @param id - The document ID.\n * @param data - Partial fields to merge into the existing document.\n * @returns The updated document.\n * @throws If the document is not found or deleted.\n */\n update(id: string, data: Partial<T>): Promise<WithMeta<T>>\n\n /**\n * Soft-delete a document (sets `_deleted: true`).\n *\n * @param id - The document ID.\n */\n delete(id: string): Promise<void>\n\n /**\n * Count documents matching an optional query.\n *\n * @param options - Optional query options (where, sort, limit, offset).\n * @returns The number of matching documents.\n */\n count(options?: QueryOptions<T>): Promise<number>\n\n /**\n * Check if a non-deleted document with the given ID exists.\n *\n * @param id - The document ID.\n * @returns `true` if the document exists and is not deleted.\n */\n exists(id: string): Promise<boolean>\n}\n\ntype UserType<TShape extends ZodRawShape> = ZodObject<TShape>['_output']\n\nexport class CollectionImpl<TShape extends ZodRawShape>\n implements Collection<UserType<TShape>>\n{\n private readonly schema: ZodObject<TShape>\n private readonly collectionName: string\n private readonly storage: StorageAdapter\n private readonly version: number | undefined\n private readonly migrate: ((doc: Record<string, unknown>) => Record<string, unknown>) | undefined\n\n constructor(\n schema: ZodObject<TShape>,\n collectionName: string,\n storage: StorageAdapter,\n version?: number,\n migrate?: (doc: Record<string, unknown>) => Record<string, unknown>,\n ) {\n this.schema = schema\n this.collectionName = collectionName\n this.storage = storage\n this.version = version\n this.migrate = migrate\n }\n\n get name(): string {\n return this.collectionName\n }\n\n private async applyMigration(doc: Doc): Promise<WithMeta<UserType<TShape>>> {\n if (this.version === undefined || doc._schemaVersion === this.version) {\n return doc as WithMeta<UserType<TShape>>\n }\n if (this.migrate) {\n const migrated = this.migrate(doc as Record<string, unknown>)\n const updated: Doc = { ...(migrated as Doc), _schemaVersion: this.version }\n await this.storage.put(this.collectionName, updated._id, updated)\n return updated as WithMeta<UserType<TShape>>\n }\n return doc as WithMeta<UserType<TShape>>\n }\n\n async create(data: UserType<TShape>): Promise<WithMeta<UserType<TShape>>> {\n const validated = this.schema.parse(data) as UserType<TShape>\n const id = generateId()\n const doc: WithMeta<UserType<TShape>> = {\n ...validated,\n _id: id,\n _collection: this.collectionName,\n _updatedAt: Date.now(),\n _deleted: false,\n ...(this.version !== undefined ? { _schemaVersion: this.version } : {}),\n }\n await this.storage.put(this.collectionName, id, doc as Doc)\n return doc\n }\n\n async findMany(\n options?: QueryOptions<UserType<TShape>>,\n ): Promise<WithMeta<UserType<TShape>>[]> {\n const docs = await this.storage.getMany(this.collectionName)\n const typed = await Promise.all(\n docs\n .filter(doc => !doc._deleted)\n .map(doc => this.applyMigration(doc)),\n )\n if (!options) return typed\n return applyQuery(typed, options as QueryOptions<WithMeta<UserType<TShape>>>)\n }\n\n async findOne(id: string): Promise<WithMeta<UserType<TShape>> | null> {\n const doc = await this.storage.get(this.collectionName, id)\n if (!doc || doc._deleted) return null\n return this.applyMigration(doc)\n }\n\n async update(\n id: string,\n data: Partial<UserType<TShape>>,\n ): Promise<WithMeta<UserType<TShape>>> {\n const existing = await this.storage.get(this.collectionName, id)\n if (!existing || existing._deleted) {\n throw new Error(`Document not found: ${id}`)\n }\n const merged = {\n ...(existing as WithMeta<UserType<TShape>>),\n ...data,\n }\n // Extract user fields (non-meta) for schema validation\n const userFields: Record<string, unknown> = {}\n for (const [k, v] of Object.entries(merged as Record<string, unknown>)) {\n if (!k.startsWith('_')) userFields[k] = v\n }\n this.schema.parse(userFields)\n const updated: WithMeta<UserType<TShape>> = {\n ...merged,\n _updatedAt: Date.now(),\n }\n await this.storage.put(this.collectionName, id, updated as Doc)\n return updated\n }\n\n async delete(id: string): Promise<void> {\n const existing = await this.storage.get(this.collectionName, id)\n if (!existing) return\n const deleted: Doc = {\n ...existing,\n _deleted: true,\n _updatedAt: Date.now(),\n }\n await this.storage.put(this.collectionName, id, deleted)\n }\n\n async count(options?: QueryOptions<UserType<TShape>>): Promise<number> {\n const docs = await this.findMany(options)\n return docs.length\n }\n\n async exists(id: string): Promise<boolean> {\n const doc = await this.storage.get(this.collectionName, id)\n return doc !== null && !doc._deleted\n }\n}\n\n/**\n * Extends CollectionImpl with useSyncExternalStore-compatible subscribe/getSnapshot.\n * Maintains an in-memory snapshot refreshed after every mutation.\n */\nexport class ObservableCollectionImpl<TShape extends ZodRawShape>\n extends CollectionImpl<TShape>\n implements ObservableCollection<UserType<TShape>>\n{\n private snapshot: ReadonlyArray<WithMeta<UserType<TShape>>> = []\n private subscribers = new Set<() => void>()\n\n private notify(): void {\n for (const sub of this.subscribers) sub()\n }\n\n private async refreshSnapshot(): Promise<void> {\n const data = await this.findMany()\n this.snapshot = data\n this.notify()\n }\n\n subscribe(listener: () => void): () => void {\n this.subscribers.add(listener)\n this.refreshSnapshot().catch(err => console.error('[LocalKit] subscribe refreshSnapshot failed:', err))\n return () => {\n this.subscribers.delete(listener)\n }\n }\n\n getSnapshot(): ReadonlyArray<WithMeta<UserType<TShape>>> {\n return this.snapshot\n }\n\n override async create(\n data: UserType<TShape>,\n ): Promise<WithMeta<UserType<TShape>>> {\n const doc = await super.create(data)\n await this.refreshSnapshot()\n return doc\n }\n\n override async update(\n id: string,\n data: Partial<UserType<TShape>>,\n ): Promise<WithMeta<UserType<TShape>>> {\n const doc = await super.update(id, data)\n await this.refreshSnapshot()\n return doc\n }\n\n override async delete(id: string): Promise<void> {\n await super.delete(id)\n await this.refreshSnapshot()\n }\n}\n","import type { AuthAdapter, Credentials, User } from '../auth/types.js'\nimport type { SyncStatus } from '../sync/types.js'\n\nexport interface AuthState {\n user: User | null\n token: string | null\n isLoading: boolean\n}\n\nexport interface SyncState {\n status: SyncStatus\n lastSyncAt: number | null\n}\n\n/** Observable auth wrapper — delegates to AuthAdapter and notifies React subscribers on state changes. */\nexport class AuthStore implements AuthAdapter {\n private state: AuthState\n private listeners = new Set<() => void>()\n\n constructor(private readonly adapter: AuthAdapter) {\n this.state = {\n user: adapter.currentUser(),\n token: adapter.getToken(),\n isLoading: false,\n }\n }\n\n subscribe(listener: () => void): () => void {\n this.listeners.add(listener)\n return () => {\n this.listeners.delete(listener)\n }\n }\n\n getSnapshot(): AuthState {\n return this.state\n }\n\n private notify(): void {\n for (const l of this.listeners) l()\n }\n\n async signUp(credentials: Credentials): Promise<User> {\n this.state = { ...this.state, isLoading: true }\n this.notify()\n try {\n const user = await this.adapter.signUp(credentials)\n this.state = { user, token: this.adapter.getToken(), isLoading: false }\n this.notify()\n return user\n } catch (err) {\n this.state = { ...this.state, isLoading: false }\n this.notify()\n throw err\n }\n }\n\n async signIn(credentials: Credentials): Promise<User> {\n this.state = { ...this.state, isLoading: true }\n this.notify()\n try {\n const user = await this.adapter.signIn(credentials)\n this.state = { user, token: this.adapter.getToken(), isLoading: false }\n this.notify()\n return user\n } catch (err) {\n this.state = { ...this.state, isLoading: false }\n this.notify()\n throw err\n }\n }\n\n async signOut(): Promise<void> {\n await this.adapter.signOut()\n this.state = { user: null, token: null, isLoading: false }\n this.notify()\n }\n\n currentUser(): User | null {\n return this.state.user\n }\n\n getToken(): string | null {\n return this.state.token\n }\n\n /**\n * Revalidate a cached session against the server.\n * Delegates to the inner adapter's `revalidateSession` if it supports it.\n *\n * @returns The revalidated user, or `null` if the session is invalid or the adapter does not support revalidation.\n */\n async revalidateSession(): Promise<User | null> {\n if (!this.adapter.revalidateSession) return null\n const user = await this.adapter.revalidateSession()\n this.state = {\n user,\n token: this.adapter.getToken(),\n isLoading: false,\n }\n this.notify()\n return user\n }\n}\n\n/** Observable sync state — updated by the sync engine and read by useSync. */\nexport class SyncStore {\n private state: SyncState = { status: 'idle', lastSyncAt: null }\n private listeners = new Set<() => void>()\n\n subscribe(listener: () => void): () => void {\n this.listeners.add(listener)\n return () => {\n this.listeners.delete(listener)\n }\n }\n\n getSnapshot(): SyncState {\n return this.state\n }\n\n setStatus(status: SyncStatus, lastSyncAt?: number): void {\n this.state = {\n status,\n lastSyncAt: lastSyncAt !== undefined ? lastSyncAt : this.state.lastSyncAt,\n }\n for (const l of this.listeners) l()\n }\n}\n","import type { ZodRawShape } from 'zod'\nimport type { AuthAdapter } from '../auth/types.js'\nimport { EmailPasswordAuth } from '../auth/adapter.js'\nimport { BetterAuthAdapter, type BetterAuthClient } from '../auth/better-auth-adapter.js'\nimport { loadSession } from '../auth/session.js'\nimport { ErrorManager } from '../errors/index.js'\nimport type { CollectionDescriptor } from '../schema/types.js'\nimport { IndexedDBAdapter } from '../storage/indexeddb.js'\nimport { MemoryAdapter } from '../storage/memory.js'\nimport type { StorageAdapter } from '../storage/types.js'\nimport type { SyncConfig } from '../sync/types.js'\nimport { SyncEngine } from '../sync/engine.js'\nimport { ObservableCollectionImpl, type ObservableCollection } from './collection.js'\nimport { AuthStore, SyncStore } from './events.js'\nimport type { AuthConfig, ErrorTrackingConfig, SyncAPI } from './types.js'\n\ntype ObservableInferredCollections<\n C extends Record<string, CollectionDescriptor<ZodRawShape>>,\n> = {\n [K in keyof C]: ObservableCollection<C[K]['_inferredType']>\n}\n\nexport type App<C extends Record<string, CollectionDescriptor<ZodRawShape>>> =\n ObservableInferredCollections<C> & {\n auth: AuthStore\n errors: ErrorManager\n syncStore: SyncStore\n sync?: SyncAPI\n }\n\nexport interface CreateAppConfig<\n C extends Record<string, CollectionDescriptor<ZodRawShape>>,\n> {\n collections: C\n storage?: StorageAdapter\n sync?: Partial<SyncConfig>\n errorTracking?: ErrorTrackingConfig\n auth?: AuthConfig\n}\n\nfunction createDeferredBetterAuthClient(baseURL: string): BetterAuthClient {\n let clientPromise: Promise<BetterAuthClient> | null = null\n\n function getClient(): Promise<BetterAuthClient> {\n if (!clientPromise) {\n clientPromise = (async () => {\n try {\n const mod = await import('better-auth/client')\n return (mod as { createAuthClient: (opts: Record<string, unknown>) => BetterAuthClient }).createAuthClient({\n baseURL,\n fetchOptions: {\n auth: {\n type: 'Bearer',\n token: (): string => {\n try { return loadSession()?.token ?? '' } catch { return '' }\n },\n },\n },\n })\n } catch {\n throw new Error(\n 'better-auth is not installed. Run: npm install better-auth\\n' +\n 'The server must enable the bearer plugin: import { bearer } from \"better-auth/plugins\"',\n )\n }\n })()\n }\n return clientPromise\n }\n\n return {\n signUp: {\n email: async (opts) => (await getClient()).signUp.email(opts),\n },\n signIn: {\n email: async (opts) => (await getClient()).signIn.email(opts),\n social: async (opts) => (await getClient()).signIn.social(opts),\n },\n signOut: async () => (await getClient()).signOut(),\n getSession: async () => (await getClient()).getSession(),\n }\n}\n\nfunction resolveAuth(config?: AuthConfig): AuthAdapter {\n if (!config) {\n return {\n signUp: async () => { throw new Error('Auth not configured. Implement AuthAdapter.') },\n signIn: async () => { throw new Error('Auth not configured. Implement AuthAdapter.') },\n signOut: async () => { throw new Error('Auth not configured. Implement AuthAdapter.') },\n currentUser: () => null,\n getToken: () => null,\n }\n }\n if ('type' in config) {\n if (config.type === 'email-password') {\n return new EmailPasswordAuth({ endpoint: config.endpoint })\n }\n if (config.type === 'better-auth') {\n return new BetterAuthAdapter({ client: createDeferredBetterAuthClient(config.baseURL) })\n }\n }\n // Verify custom AuthAdapter has required methods\n const adapter = config as AuthAdapter\n if (typeof adapter.signUp !== 'function' || typeof adapter.signIn !== 'function' ||\n typeof adapter.signOut !== 'function' || typeof adapter.currentUser !== 'function' ||\n typeof adapter.getToken !== 'function') {\n throw new Error('Invalid auth config: must implement AuthAdapter interface (signUp, signIn, signOut, currentUser, getToken)')\n }\n return adapter\n}\n\nexport function createApp<\n C extends Record<string, CollectionDescriptor<ZodRawShape>>,\n>(config: CreateAppConfig<C>): App<C> {\n // IndexedDBAdapter constructor is SSR-safe (just sets dbName, DB opens lazily).\n // Fall back to MemoryAdapter in environments without indexedDB (Node tests, SSR\n // without browser globals). IndexedDB operations only run on the client.\n const storage: StorageAdapter = config.storage ??\n (typeof indexedDB !== 'undefined' ? new IndexedDBAdapter('localkit') : new MemoryAdapter())\n\n const RESERVED_KEYS = ['auth', 'errors', 'syncStore', 'sync'] as const\n for (const name of Object.keys(config.collections)) {\n if ((RESERVED_KEYS as readonly string[]).includes(name)) {\n throw new Error(`Collection name \"${name}\" conflicts with reserved key`)\n }\n }\n\n const collections: Record<string, ObservableCollection<unknown>> = {}\n for (const [name, descriptor] of Object.entries(config.collections)) {\n collections[name] = new ObservableCollectionImpl(descriptor.schema, name, storage, descriptor.version, descriptor.migrate)\n }\n\n const errors = new ErrorManager(storage, config.errorTracking)\n const authStore = new AuthStore(resolveAuth(config.auth))\n const syncStore = new SyncStore()\n\n let syncAPI: SyncAPI | undefined\n\n if (config.sync?.endpoint) {\n const syncConfig: SyncConfig = {\n endpoint: config.sync.endpoint,\n interval: config.sync.interval ?? 30_000,\n enabled: config.sync.enabled ?? true,\n conflictResolver: config.sync.conflictResolver,\n transport: config.sync.transport,\n }\n\n const engine = new SyncEngine(storage, syncConfig)\n\n // Wire auth token into transport so authenticated syncs work offline\n engine.setToken(authStore.getToken())\n const unsubAuth = authStore.subscribe(() => engine.setToken(authStore.getToken()))\n\n // Wire engine events to syncStore for React subscribers\n engine.on('sync:start', () => syncStore.setStatus('syncing'))\n engine.on('sync:complete', () => syncStore.setStatus('idle', engine.getLastSyncAt()))\n engine.on('sync:error', () => syncStore.setStatus(engine.getStatus()))\n\n let intervalId: ReturnType<typeof setInterval> | null = null\n const onOnline = () => { void engine.sync() }\n\n syncAPI = {\n push: () => engine.push(),\n pull: () => engine.pull(),\n start() {\n if (!syncConfig.enabled) return\n intervalId = setInterval(() => { void engine.sync() }, syncConfig.interval)\n if (typeof window !== 'undefined') {\n window.addEventListener('online', onOnline)\n }\n },\n stop() {\n if (intervalId !== null) {\n clearInterval(intervalId)\n intervalId = null\n }\n if (typeof window !== 'undefined') {\n window.removeEventListener('online', onOnline)\n }\n unsubAuth()\n },\n get status() {\n return engine.getStatus()\n },\n }\n }\n\n return {\n ...collections,\n auth: authStore,\n errors,\n syncStore,\n ...(syncAPI !== undefined ? { sync: syncAPI } : {}),\n } as App<C>\n}\n","import type { QueryOptions } from './storage/query.js'\nimport type { WithMeta } from './schema/types.js'\nimport type { Collection } from './client/collection.js'\n\n/** Minimal QueryClient interface — avoids a hard dep on @tanstack/query-core */\ninterface MinimalQueryClient {\n invalidateQueries(opts: { queryKey: readonly unknown[] }): Promise<void>\n}\n\nexport const localkitKeys = {\n all: ['offlinekit'] as const,\n collection: (name: string) => ['offlinekit', name] as const,\n collectionQuery: (name: string, opts: unknown) =>\n ['offlinekit', name, JSON.stringify(opts)] as const,\n}\n\nexport function collectionQueryOptions<T>(\n collection: Collection<T>,\n queryOptions?: QueryOptions<T>,\n): {\n queryKey: readonly unknown[]\n queryFn: () => Promise<WithMeta<T>[]>\n} {\n const queryKey = queryOptions\n ? localkitKeys.collectionQuery(collection.name, queryOptions)\n : localkitKeys.collection(collection.name)\n\n return {\n queryKey,\n queryFn: () => collection.findMany(queryOptions),\n }\n}\n\nexport function subscribeToCollection<T>(\n collection: Collection<T>,\n queryClient: MinimalQueryClient,\n): () => void {\n const queryKey = localkitKeys.collection(collection.name)\n\n if (!('subscribe' in collection)) {\n return () => {}\n }\n\n const obs = collection as Collection<T> & {\n subscribe(listener: () => void): () => void\n }\n\n return obs.subscribe(() => {\n void queryClient.invalidateQueries({ queryKey })\n })\n}\n"]}
|