@syncular/server-cloudflare 0.0.1-100

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/src/worker.ts ADDED
@@ -0,0 +1,73 @@
1
+ /**
2
+ * @syncular/server-cloudflare - Worker handler (polling only)
3
+ *
4
+ * Creates a stateless Cloudflare Worker that serves sync routes via Hono.
5
+ * No WebSocket support — use the Durable Object adapter for realtime.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * import { createSyncWorker } from '@syncular/server-cloudflare/worker';
10
+ * import { createD1Db } from '@syncular/dialect-d1';
11
+ * import { createSqliteServerDialect } from '@syncular/server-dialect-sqlite';
12
+ * import { ensureSyncSchema } from '@syncular/server';
13
+ * import { createSyncServer } from '@syncular/server-hono';
14
+ *
15
+ * type Env = { DB: D1Database };
16
+ *
17
+ * export default createSyncWorker<Env>((app, env) => {
18
+ * const db = createD1Db(env.DB);
19
+ * const dialect = createSqliteServerDialect();
20
+ * const { syncRoutes, consoleRoutes } = createSyncServer({
21
+ * db, dialect,
22
+ * handlers: [tasksHandler],
23
+ * authenticate: async (c) => ({ actorId: c.req.header('x-user-id')! }),
24
+ * });
25
+ * app.route('/sync', syncRoutes);
26
+ * if (consoleRoutes) app.route('/console', consoleRoutes);
27
+ * });
28
+ * ```
29
+ */
30
+
31
+ import { Hono } from 'hono';
32
+
33
+ type SyncWorkerSetup<B extends object> = (
34
+ app: Hono<{ Bindings: B }>,
35
+ env: B
36
+ ) => void | Promise<void>;
37
+
38
+ /**
39
+ * Create a Cloudflare Worker export that lazily initializes a Hono app.
40
+ *
41
+ * The `setup` callback is called once per isolate on the first request.
42
+ * It receives a fresh Hono app and the Worker env bindings.
43
+ */
44
+ export function createSyncWorker<
45
+ Bindings extends object = Record<string, unknown>,
46
+ >(setup: SyncWorkerSetup<Bindings>): ExportedHandler<Bindings> {
47
+ type E = { Bindings: Bindings };
48
+ let app: Hono<E> | null = null;
49
+ let initPromise: Promise<void> | null = null;
50
+
51
+ async function getApp(env: Bindings): Promise<Hono<E>> {
52
+ if (app) return app;
53
+ if (!initPromise) {
54
+ const honoApp = new Hono<E>();
55
+ initPromise = Promise.resolve(setup(honoApp, env)).then(() => {
56
+ app = honoApp;
57
+ });
58
+ }
59
+ await initPromise;
60
+ return app!;
61
+ }
62
+
63
+ return {
64
+ async fetch(
65
+ request: Request,
66
+ env: Bindings,
67
+ ctx: ExecutionContext
68
+ ): Promise<Response> {
69
+ const honoApp = await getApp(env);
70
+ return honoApp.fetch(request, env, ctx);
71
+ },
72
+ };
73
+ }