mpb-localkit 1.3.4 → 1.3.7

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/README.md CHANGED
@@ -108,7 +108,7 @@ Passwords are hashed client-side (PBKDF2) before transmission. Sessions are JWTs
108
108
 
109
109
  ## Sync
110
110
 
111
- Sync happens automatically when configured with an `endpoint`. MPB LocalKit uses a Last-Write-Wins (LWW) protocol — the document with the highest `_updatedAt` timestamp wins conflicts.
111
+ Sync happens automatically when configured with an `endpoint`. LocalKit uses a Last-Write-Wins (LWW) protocol — the document with the highest `_updatedAt` timestamp wins conflicts.
112
112
 
113
113
  ```ts
114
114
  // Manual sync
@@ -226,7 +226,7 @@ Done! Your project is ready.
226
226
 
227
227
  ## Transport Configuration
228
228
 
229
- MPB LocalKit supports three sync transports, configurable at `createApp` time:
229
+ LocalKit supports three sync transports, configurable at `createApp` time:
230
230
 
231
231
  ### HTTP Transport (default)
232
232
 
@@ -271,11 +271,11 @@ const app = createApp({
271
271
  })
272
272
  ```
273
273
 
274
- With `auto`, MPB LocalKit upgrades to WebSocket when the server supports it and degrades gracefully on restricted networks.
274
+ With `auto`, LocalKit upgrades to WebSocket when the server supports it and degrades gracefully on restricted networks.
275
275
 
276
276
  ## WebSocket Sync
277
277
 
278
- When using `transport: 'websocket'` or `transport: 'auto'`, MPB LocalKit maintains a persistent WebSocket connection to your sync Worker. The Worker sends change events as they occur — no polling delay.
278
+ When using `transport: 'websocket'` or `transport: 'auto'`, LocalKit maintains a persistent WebSocket connection to your sync Worker. The Worker sends change events as they occur — no polling delay.
279
279
 
280
280
  ```ts
281
281
  import { createApp, collection, z } from 'mpb-localkit'
@@ -307,7 +307,7 @@ The WebSocket connection is managed automatically:
307
307
 
308
308
  ## Better Auth Integration
309
309
 
310
- MPB LocalKit integrates with [Better Auth](https://better-auth.com) for full-featured server-side authentication.
310
+ LocalKit integrates with [Better Auth](https://better-auth.com) for full-featured server-side authentication.
311
311
 
312
312
  ### Setup
313
313
 
package/dist/cli/index.js CHANGED
@@ -41,9 +41,9 @@ async function loadSchema(filePath) {
41
41
 
42
42
  // src/cli/commands/dev.ts
43
43
  function registerDev(program2) {
44
- program2.command("dev").description("Start OfflineKit in local-only mode (no cloud sync)").action(() => {
44
+ program2.command("dev").description("Start LocalKit in local-only mode (no cloud sync)").action(() => {
45
45
  process.env["OFFLINEKIT_MODE"] = "local";
46
- log.bold("OfflineKit Dev Mode");
46
+ log.bold("LocalKit Dev Mode");
47
47
  log.info("Running in local-only mode (no cloud sync)");
48
48
  log.dim("All data is stored locally. Sync is disabled.");
49
49
  });
@@ -693,8 +693,8 @@ function nodeTsConfig() {
693
693
  // src/cli/commands/build.ts
694
694
  var targets = { cloudflare: cloudflareTarget, node: nodeTarget };
695
695
  function registerBuild(program2) {
696
- program2.command("build").description("Build the OfflineKit backend bundle").option("-o, --out <dir>", "Output directory", ".offlinekit/worker").option("-n, --name <name>", "App name for the worker", "offlinekit-app").option("-t, --target <target>", "Deploy target: cloudflare or node", "cloudflare").action(async (opts) => {
697
- log.bold("OfflineKit Build");
696
+ program2.command("build").description("Build the LocalKit backend bundle").option("-o, --out <dir>", "Output directory", ".offlinekit/worker").option("-n, --name <name>", "App name for the worker", "localkit-app").option("-t, --target <target>", "Deploy target: cloudflare or node", "cloudflare").action(async (opts) => {
697
+ log.bold("LocalKit Build");
698
698
  const target = targets[opts.target];
699
699
  if (!target) {
700
700
  log.error(`Unknown target: ${opts.target}. Valid targets: ${Object.keys(targets).join(", ")}`);
@@ -738,8 +738,8 @@ function checkWrangler() {
738
738
  }
739
739
  }
740
740
  function registerDeploy(program2) {
741
- program2.command("deploy").description("Deploy the OfflineKit Worker to Cloudflare via Wrangler").option("-d, --dir <dir>", "Worker output directory", ".offlinekit/worker").option("-e, --env <env>", "Wrangler environment (e.g. production, staging)").option("-t, --target <target>", "Deploy target (default: cloudflare)", "cloudflare").option("--dry-run", "Print the wrangler command without running it").action((opts) => {
742
- log.bold("OfflineKit Deploy");
741
+ program2.command("deploy").description("Deploy the LocalKit Worker to Cloudflare via Wrangler").option("-d, --dir <dir>", "Worker output directory", ".offlinekit/worker").option("-e, --env <env>", "Wrangler environment (e.g. production, staging)").option("-t, --target <target>", "Deploy target (default: cloudflare)", "cloudflare").option("--dry-run", "Print the wrangler command without running it").action((opts) => {
742
+ log.bold("LocalKit Deploy");
743
743
  const serverDir = resolve(process.cwd(), "server");
744
744
  if (existsSync(serverDir)) {
745
745
  log.info("Warning: This project has been ejected (./server/ exists).");
@@ -747,7 +747,7 @@ function registerDeploy(program2) {
747
747
  }
748
748
  if (opts.target !== "cloudflare") {
749
749
  log.error(`Deploy target "${opts.target}" is not supported yet. Only "cloudflare" is deployable.`);
750
- log.dim("For Node.js targets, run `offlinekit build --target node` then deploy the output manually.");
750
+ log.dim("For Node.js targets, run `npx mpb-localkit build --target node` then deploy the output manually.");
751
751
  process.exit(1);
752
752
  }
753
753
  const version = checkWrangler();
@@ -760,13 +760,13 @@ function registerDeploy(program2) {
760
760
  const outDir = resolve(process.cwd(), opts.dir);
761
761
  if (!existsSync(outDir)) {
762
762
  log.error(`Worker directory not found: ${outDir}`);
763
- log.dim("Run `offlinekit build` first to generate the worker.");
763
+ log.dim("Run `npx mpb-localkit build` first to generate the worker.");
764
764
  process.exit(1);
765
765
  }
766
766
  const tomlPath = resolve(outDir, "wrangler.toml");
767
767
  if (!existsSync(tomlPath)) {
768
768
  log.error(`wrangler.toml not found in ${outDir}`);
769
- log.dim("Run `offlinekit build` to regenerate the worker.");
769
+ log.dim("Run `npx mpb-localkit build` to regenerate the worker.");
770
770
  process.exit(1);
771
771
  }
772
772
  const args = ["deploy"];
@@ -795,8 +795,8 @@ var targets2 = {
795
795
  node: nodeTarget
796
796
  };
797
797
  function registerEject(program2) {
798
- program2.command("eject").description("Eject generated Worker code into ./server/ for manual customization").option("-o, --out <dir>", "Output directory for ejected code", "server").option("-n, --name <name>", "App name", "offlinekit-app").option("-t, --target <target>", "Deploy target (cloudflare, node)", "cloudflare").action((opts) => {
799
- log.bold("OfflineKit Eject");
798
+ program2.command("eject").description("Eject generated Worker code into ./server/ for manual customization").option("-o, --out <dir>", "Output directory for ejected code", "server").option("-n, --name <name>", "App name", "localkit-app").option("-t, --target <target>", "Deploy target (cloudflare, node)", "cloudflare").action((opts) => {
799
+ log.bold("LocalKit Eject");
800
800
  const target = targets2[opts.target];
801
801
  if (!target) {
802
802
  log.error(`Unknown target: "${opts.target}"`);
@@ -830,7 +830,7 @@ function registerEject(program2) {
830
830
  log.dim(" npm install");
831
831
  log.dim(" wrangler deploy");
832
832
  log.dim("");
833
- log.dim("Note: Running `offlinekit deploy` will warn that code has been ejected.");
833
+ log.dim("Note: Running `npx mpb-localkit deploy` will warn that code has been ejected.");
834
834
  }
835
835
  } catch (err) {
836
836
  log.error(`Eject failed: ${err instanceof Error ? err.message : String(err)}`);
@@ -843,7 +843,7 @@ function registerEject(program2) {
843
843
  var require2 = createRequire(import.meta.url);
844
844
  var pkg = require2("../../package.json");
845
845
  var program = new Command();
846
- program.name("offlinekit").description(pkg.description).version(pkg.version, "-v, --version", "Print the current version");
846
+ program.name("mpb-localkit").description(pkg.description).version(pkg.version, "-v, --version", "Print the current version");
847
847
  registerDev(program);
848
848
  registerBuild(program);
849
849
  registerDeploy(program);
@@ -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":"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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 OfflineKit in local-only mode (no cloud sync)')\n .action(() => {\n process.env['OFFLINEKIT_MODE'] = 'local'\n log.bold('OfflineKit 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) 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)\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)\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) 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): 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 = \"REPLACE_WITH_KV_NAMESPACE_ID\"\n\n[[durable_objects.bindings]]\nname = \"WS_SESSIONS\"\nclass_name = \"WsSessions\"\n\n[[migrations]]\ntag = \"v1\"\nnew_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}\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 } = 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)],\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 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 ' - KV namespace id → set your actual KV namespace ID\\n'\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 }: { appName: string; outDir: string }): void {\n generateWorker({ appName, outDir })\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 { findSchemaFile, loadSchema, 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 OfflineKit backend bundle')\n .option('-o, --out <dir>', 'Output directory', '.offlinekit/worker')\n .option('-n, --name <name>', 'App name for the worker', 'offlinekit-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('OfflineKit 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 schemaFile = findSchemaFile()\n if (!schemaFile) {\n log.error('No schema file found. Create offlinekit.config.ts in your project root.')\n process.exit(1)\n }\n\n log.info(`Found schema: ${schemaFile}`)\n\n try {\n await loadSchema(schemaFile)\n log.success('Schema loaded successfully')\n } catch (err) {\n log.error(`Schema load failed: ${err instanceof Error ? err.message : String(err)}`)\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 } from 'node:fs'\nimport { resolve } from 'node:path'\nimport { log } from '../utils.js'\n\nfunction checkWrangler(): string | null {\n try {\n const result = execSync('wrangler --version', { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] })\n return result.trim()\n } catch {\n return null\n }\n}\n\nexport function registerDeploy(program: Command): void {\n program\n .command('deploy')\n .description('Deploy the OfflineKit Worker to Cloudflare via Wrangler')\n .option('-d, --dir <dir>', 'Worker output directory', '.offlinekit/worker')\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', 'Print the wrangler command without running it')\n .action((opts: { dir: string; env?: string; target: string; dryRun?: boolean }) => {\n log.bold('OfflineKit Deploy')\n\n // 0. Check if project has been ejected\n const serverDir = resolve(process.cwd(), 'server')\n if (existsSync(serverDir)) {\n log.info('Warning: This project has been ejected (./server/ exists).')\n log.dim('You can deploy the ejected code directly with `cd server && wrangler deploy`.')\n }\n\n // 0b. Validate target\n if (opts.target !== 'cloudflare') {\n log.error(`Deploy target \"${opts.target}\" is not supported yet. Only \"cloudflare\" is deployable.`)\n log.dim('For Node.js targets, run `offlinekit build --target node` then deploy the output manually.')\n process.exit(1)\n }\n\n // 1. 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 // 2. Check output directory exists\n const outDir = resolve(process.cwd(), opts.dir)\n if (!existsSync(outDir)) {\n log.error(`Worker directory not found: ${outDir}`)\n log.dim('Run `offlinekit build` first to generate the worker.')\n process.exit(1)\n }\n\n // 3. Check wrangler.toml is present\n const tomlPath = resolve(outDir, 'wrangler.toml')\n if (!existsSync(tomlPath)) {\n log.error(`wrangler.toml not found in ${outDir}`)\n log.dim('Run `offlinekit build` to regenerate the worker.')\n process.exit(1)\n }\n\n // 4. Build wrangler deploy command\n const args = ['deploy']\n if (opts.env) args.push('--env', opts.env)\n\n log.info(`Deploying from: ${outDir}`)\n if (opts.env) log.info(`Environment: ${opts.env}`)\n\n if (opts.dryRun) {\n log.dim(`[dry-run] wrangler ${args.join(' ')}`)\n log.dim(`[dry-run] cwd: ${outDir}`)\n return\n }\n\n // 5. Run wrangler deploy\n const result = spawnSync('wrangler', args, {\n cwd: outDir,\n stdio: 'inherit',\n encoding: 'utf8',\n })\n\n if (result.status !== 0) {\n log.error(`wrangler deploy failed (exit ${result.status ?? 'unknown'})`)\n process.exit(result.status ?? 1)\n }\n\n log.success('Deployed successfully!')\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', 'offlinekit-app')\n .option('-t, --target <target>', 'Deploy target (cloudflare, node)', 'cloudflare')\n .action((opts: { out: string; name: string; target: string }) => {\n log.bold('OfflineKit 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 `offlinekit 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('offlinekit')\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 */\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) 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)\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)\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) 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): 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 = \"REPLACE_WITH_KV_NAMESPACE_ID\"\n\n[[durable_objects.bindings]]\nname = \"WS_SESSIONS\"\nclass_name = \"WsSessions\"\n\n[[migrations]]\ntag = \"v1\"\nnew_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}\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 } = 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)],\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 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 ' - KV namespace id → set your actual KV namespace ID\\n'\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 }: { appName: string; outDir: string }): void {\n generateWorker({ appName, outDir })\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 { findSchemaFile, loadSchema, 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 schemaFile = findSchemaFile()\n if (!schemaFile) {\n log.error('No schema file found. Create offlinekit.config.ts in your project root.')\n process.exit(1)\n }\n\n log.info(`Found schema: ${schemaFile}`)\n\n try {\n await loadSchema(schemaFile)\n log.success('Schema loaded successfully')\n } catch (err) {\n log.error(`Schema load failed: ${err instanceof Error ? err.message : String(err)}`)\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 } from 'node:fs'\nimport { resolve } from 'node:path'\nimport { log } from '../utils.js'\n\nfunction checkWrangler(): string | null {\n try {\n const result = execSync('wrangler --version', { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] })\n return result.trim()\n } catch {\n return null\n }\n}\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('-e, --env <env>', 'Wrangler environment (e.g. production, staging)')\n .option('-t, --target <target>', 'Deploy target (default: cloudflare)', 'cloudflare')\n .option('--dry-run', 'Print the wrangler command without running it')\n .action((opts: { dir: string; env?: string; target: string; dryRun?: boolean }) => {\n log.bold('LocalKit Deploy')\n\n // 0. Check if project has been ejected\n const serverDir = resolve(process.cwd(), 'server')\n if (existsSync(serverDir)) {\n log.info('Warning: This project has been ejected (./server/ exists).')\n log.dim('You can deploy the ejected code directly with `cd server && wrangler deploy`.')\n }\n\n // 0b. Validate target\n if (opts.target !== 'cloudflare') {\n log.error(`Deploy target \"${opts.target}\" is not supported yet. Only \"cloudflare\" is deployable.`)\n log.dim('For Node.js targets, run `npx mpb-localkit build --target node` then deploy the output manually.')\n process.exit(1)\n }\n\n // 1. 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 // 2. Check output directory exists\n const outDir = resolve(process.cwd(), opts.dir)\n if (!existsSync(outDir)) {\n log.error(`Worker directory not found: ${outDir}`)\n log.dim('Run `npx mpb-localkit build` first to generate the worker.')\n process.exit(1)\n }\n\n // 3. Check wrangler.toml is present\n const tomlPath = resolve(outDir, 'wrangler.toml')\n if (!existsSync(tomlPath)) {\n log.error(`wrangler.toml not found in ${outDir}`)\n log.dim('Run `npx mpb-localkit build` to regenerate the worker.')\n process.exit(1)\n }\n\n // 4. Build wrangler deploy command\n const args = ['deploy']\n if (opts.env) args.push('--env', opts.env)\n\n log.info(`Deploying from: ${outDir}`)\n if (opts.env) log.info(`Environment: ${opts.env}`)\n\n if (opts.dryRun) {\n log.dim(`[dry-run] wrangler ${args.join(' ')}`)\n log.dim(`[dry-run] cwd: ${outDir}`)\n return\n }\n\n // 5. Run wrangler deploy\n const result = spawnSync('wrangler', args, {\n cwd: outDir,\n stdio: 'inherit',\n encoding: 'utf8',\n })\n\n if (result.status !== 0) {\n log.error(`wrangler deploy failed (exit ${result.status ?? 'unknown'})`)\n process.exit(result.status ?? 1)\n }\n\n log.success('Deployed successfully!')\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"]}
@@ -5,7 +5,7 @@ export { C as Collection, l as OfflineSession, Q as QueryOptions, m as SyncResul
5
5
  import { E as ErrorConfig, a as ErrorEntry, b as ErrorType, c as ErrorContext, S as SyncAPI, d as ErrorTrackingConfig, A as AuthConfig } from '../types-BlqxG_-6.js';
6
6
  export { e as AppConfig, f as ErrorSnapshot } from '../types-BlqxG_-6.js';
7
7
  import { A as AuthStore, S as SyncStore } from '../events-hGI5qde5.js';
8
- export { c as collectionQueryOptions, l as localkitKeys, s as subscribeToCollection } from '../query-BgIfgMSp.js';
8
+ export { c as collectionQueryOptions, l as localkitKeys, s as subscribeToCollection } from '../query-D2jbktTG.js';
9
9
 
10
10
  /**
11
11
  * Wraps a Zod schema to create a typed collection descriptor.
@@ -1203,7 +1203,7 @@ var ErrorTracker = class {
1203
1203
  method: "POST",
1204
1204
  headers: {
1205
1205
  "Content-Type": "application/json",
1206
- "User-Agent": "mpb-localkit-error-tracker"
1206
+ "User-Agent": "localkit-error-tracker"
1207
1207
  },
1208
1208
  body: JSON.stringify(entry)
1209
1209
  });
@@ -1480,7 +1480,7 @@ var ObservableCollectionImpl = class extends CollectionImpl {
1480
1480
  }
1481
1481
  subscribe(listener) {
1482
1482
  this.subscribers.add(listener);
1483
- this.refreshSnapshot().catch((err) => console.error("[MPB LocalKit] subscribe refreshSnapshot failed:", err));
1483
+ this.refreshSnapshot().catch((err) => console.error("[LocalKit] subscribe refreshSnapshot failed:", err));
1484
1484
  return () => {
1485
1485
  this.subscribers.delete(listener);
1486
1486
  };
@@ -1752,9 +1752,9 @@ function createApp(config) {
1752
1752
 
1753
1753
  // src/core/query.ts
1754
1754
  var localkitKeys = {
1755
- all: ["localkit"],
1756
- collection: (name) => ["localkit", name],
1757
- collectionQuery: (name, opts) => ["localkit", name, JSON.stringify(opts)]
1755
+ all: ["offlinekit"],
1756
+ collection: (name) => ["offlinekit", name],
1757
+ collectionQuery: (name, opts) => ["offlinekit", name, JSON.stringify(opts)]
1758
1758
  };
1759
1759
  function collectionQueryOptions(collection2, queryOptions) {
1760
1760
  const queryKey = queryOptions ? localkitKeys.collectionQuery(collection2.name, queryOptions) : localkitKeys.collection(collection2.name);