@sveltebase/sync 1.3.0 → 1.4.1

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.
@@ -8,3 +8,4 @@ export function defineSync(config) {
8
8
  },
9
9
  };
10
10
  }
11
+ export { createBulkPublisher, createPublisher, INTERNAL_AUTH_HEADER, } from "./handler.js";
@@ -0,0 +1,10 @@
1
+ import type { RequestHandler } from "@sveltejs/kit";
2
+ export type SyncProxyOptions = {
3
+ binding?: string;
4
+ fallbackUrl?: string;
5
+ };
6
+ export declare function syncProxy(options?: SyncProxyOptions): {
7
+ GET: RequestHandler;
8
+ POST: RequestHandler;
9
+ };
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sveltekit/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAeF,wBAAgB,SAAS,CAAC,OAAO,CAAC,EAAE,gBAAgB,GAAG;IACrD,GAAG,EAAE,cAAc,CAAC;IACpB,IAAI,EAAE,cAAc,CAAC;CACtB,CA6BA"}
@@ -0,0 +1,29 @@
1
+ function buildFallbackRequest(request, fallbackUrl) {
2
+ const sourceUrl = new URL(request.url);
3
+ const targetUrl = new URL(fallbackUrl);
4
+ targetUrl.search = sourceUrl.search;
5
+ return new Request(targetUrl, {
6
+ method: request.method,
7
+ headers: request.headers,
8
+ body: request.body,
9
+ redirect: request.redirect,
10
+ });
11
+ }
12
+ export function syncProxy(options) {
13
+ const bindingName = options?.binding ?? "SYNC_WORKER";
14
+ const handler = async (event) => {
15
+ const platform = event.platform;
16
+ const serviceBinding = platform?.env?.[bindingName];
17
+ if (serviceBinding?.fetch) {
18
+ return serviceBinding.fetch(event.request);
19
+ }
20
+ if (options?.fallbackUrl) {
21
+ return fetch(buildFallbackRequest(event.request, options.fallbackUrl));
22
+ }
23
+ return new Response(`Missing sync Worker binding ${bindingName}. Configure a service binding or pass fallbackUrl to syncProxy().`, { status: 500 });
24
+ };
25
+ return {
26
+ GET: handler,
27
+ POST: handler,
28
+ };
29
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sveltebase/sync",
3
- "version": "1.3.0",
3
+ "version": "1.4.1",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -22,16 +22,16 @@
22
22
  "default": "./dist/client/index.js"
23
23
  },
24
24
  "./server": {
25
- "types": "./dist/server/engine.d.ts",
26
- "default": "./dist/server/engine.js"
25
+ "types": "./dist/server/index.d.ts",
26
+ "default": "./dist/server/index.js"
27
27
  },
28
- "./server/dev-engine": {
29
- "types": "./dist/server/dev-engine.d.ts",
30
- "default": "./dist/server/dev-engine.js"
28
+ "./sveltekit": {
29
+ "types": "./dist/sveltekit/index.d.ts",
30
+ "default": "./dist/sveltekit/index.js"
31
31
  },
32
- "./vite": {
33
- "types": "./dist/vite.d.ts",
34
- "default": "./dist/vite.js"
32
+ "./cloudflare": {
33
+ "types": "./dist/cloudflare/index.d.ts",
34
+ "default": "./dist/cloudflare/index.js"
35
35
  }
36
36
  },
37
37
  "dependencies": {
package/dist/global.d.ts DELETED
@@ -1,25 +0,0 @@
1
- namespace App {
2
- interface Platform {
3
- env: {
4
- SYNC_ENGINE: any;
5
- [key: string]: any;
6
- };
7
- context: any;
8
- caches: any;
9
- }
10
- }
11
-
12
- interface Env {
13
- SYNC_ENGINE: any;
14
- [key: string]: any;
15
- }
16
-
17
- declare module "$app/environment" {
18
- export const dev: boolean;
19
- export const browser: boolean;
20
- export const building: boolean;
21
- }
22
-
23
- declare module "$app/server" {
24
- export function getRequestEvent(): any;
25
- }
@@ -1,16 +0,0 @@
1
- import type { SyncHandler } from "./index.js";
2
- import type { SyncUpgradeOptions } from "./handler.js";
3
- import type { IncomingMessage } from "node:http";
4
- export declare function setHandlers(handlers: SyncHandler[]): void;
5
- export declare function addClient(ws: {
6
- send: (data: string) => void;
7
- close: (code?: number, reason?: string) => void;
8
- on: (event: string, listener: (...args: any[]) => void) => void;
9
- }, req: IncomingMessage, options?: SyncUpgradeOptions): Promise<boolean>;
10
- export declare function broadcastExternalChange(channel: string, action: "create" | "update" | "delete", key: string | undefined, data: any): Promise<void>;
11
- export declare function broadcastExternalBatchChange(channel: string, changes: Array<{
12
- action: "create" | "update" | "delete";
13
- key?: string;
14
- data?: any;
15
- }>): Promise<void>;
16
- //# sourceMappingURL=dev-engine.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"dev-engine.d.ts","sourceRoot":"","sources":["../../src/server/dev-engine.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACvD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAUjD,wBAAgB,WAAW,CAAC,QAAQ,EAAE,WAAW,EAAE,QASlD;AAcD,wBAAsB,SAAS,CAC7B,EAAE,EAAE;IACF,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7B,KAAK,EAAE,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,EAAE,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,KAAK,IAAI,CAAC;CACjE,EACD,GAAG,EAAE,eAAe,EACpB,OAAO,CAAC,EAAE,kBAAkB,GAC3B,OAAO,CAAC,OAAO,CAAC,CAwHlB;AAyBD,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,EACtC,GAAG,EAAE,MAAM,GAAG,SAAS,EACvB,IAAI,EAAE,GAAG,iBAIV;AAED,wBAAsB,4BAA4B,CAChD,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,KAAK,CAAC;IACb,MAAM,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;IACvC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,GAAG,CAAC;CACZ,CAAC,iBAIH"}
@@ -1,160 +0,0 @@
1
- import { SyncBroker } from "./broker.js";
2
- const GLOBAL_KEY = "__sync_dev_broker__";
3
- let devBroker = null;
4
- export function setHandlers(handlers) {
5
- const g = globalThis;
6
- if (!g[GLOBAL_KEY]) {
7
- const broker = new SyncBroker(handlers);
8
- g[GLOBAL_KEY] = { broker };
9
- }
10
- else {
11
- g[GLOBAL_KEY].broker.setHandlers(handlers);
12
- }
13
- devBroker = g[GLOBAL_KEY].broker;
14
- }
15
- function getDevBroker() {
16
- if (devBroker)
17
- return devBroker;
18
- const g = globalThis;
19
- if (g[GLOBAL_KEY]) {
20
- devBroker = g[GLOBAL_KEY].broker;
21
- return devBroker;
22
- }
23
- throw new Error("Sync dev broker not initialized. Call setHandlers first.");
24
- }
25
- export async function addClient(ws, req, options) {
26
- const broker = getDevBroker();
27
- const subscribedChannels = new Set();
28
- let auth = null;
29
- let identity = null;
30
- // Convert Node IncomingMessage headers to web-standard Headers
31
- const headers = new Headers();
32
- for (const [key, value] of Object.entries(req.headers)) {
33
- if (value === undefined)
34
- continue;
35
- if (Array.isArray(value)) {
36
- for (const v of value) {
37
- headers.append(key, v);
38
- }
39
- }
40
- else {
41
- headers.set(key, value);
42
- }
43
- }
44
- const urlObj = new URL(req.url ?? "", `http://${req.headers.host || "localhost"}`);
45
- const initConnection = async () => {
46
- const request = new Request(urlObj.toString(), { headers });
47
- if (options?.auth) {
48
- auth = (await options.auth(request, undefined)) ?? null;
49
- if (!auth && options.allowUnauthenticated === false) {
50
- ws.close(1008, "Unauthorized");
51
- return false;
52
- }
53
- if (auth) {
54
- const identityValue = options.identity
55
- ? options.identity(auth)
56
- : (auth?.user?.id ?? auth?.userId);
57
- identity = identityValue == null ? null : String(identityValue);
58
- }
59
- }
60
- // Legacy fallback for existing demos/apps that pass identity in URL/header.
61
- const userId = urlObj.searchParams.get("userId") || headers.get("x-user-id");
62
- if (userId && !auth) {
63
- auth = { userId };
64
- identity = userId;
65
- }
66
- return true;
67
- };
68
- const conn = {
69
- send(data) {
70
- ws.send(data);
71
- },
72
- close(code, reason) {
73
- ws.close(code, reason);
74
- },
75
- getAuth() {
76
- return auth;
77
- },
78
- setAuth(newAuth) {
79
- auth = newAuth;
80
- },
81
- getIdentity() {
82
- return identity;
83
- },
84
- setIdentity(newIdentity) {
85
- identity = newIdentity;
86
- },
87
- getSubscribedChannels() {
88
- return subscribedChannels;
89
- },
90
- headers,
91
- url: urlObj.toString(),
92
- };
93
- try {
94
- const ok = await initConnection();
95
- if (!ok)
96
- return false;
97
- broker.registerConnection(conn);
98
- console.log("dev-engine: addClient registered connection");
99
- }
100
- catch (err) {
101
- console.error("dev-engine: Error initializing connection:", err);
102
- try {
103
- ws.close(1011, "Internal server error");
104
- }
105
- catch { }
106
- return false;
107
- }
108
- ws.on("message", async (data) => {
109
- const messageString = String(data);
110
- console.log("dev-engine: WebSocket message received:", messageString.slice(0, 100));
111
- const request = new Request(conn.url, {
112
- headers: conn.headers,
113
- });
114
- try {
115
- console.log("dev-engine: getting platform proxy...");
116
- const platform = await getPlatform();
117
- console.log("dev-engine: platform proxy obtained, handling message...");
118
- await broker.handleMessage(conn, messageString, platform, request);
119
- console.log("dev-engine: message handled successfully");
120
- }
121
- catch (err) {
122
- console.error("dev-engine: Error handling message:", err);
123
- }
124
- });
125
- ws.on("close", () => {
126
- console.log("dev-engine: WebSocket connection closed");
127
- broker.removeConnection(conn);
128
- });
129
- ws.on("error", (err) => {
130
- console.error("dev-engine: WebSocket connection error:", err);
131
- broker.removeConnection(conn);
132
- });
133
- return true;
134
- }
135
- const GLOBAL_PLATFORM_KEY = "__sync_dev_platform__";
136
- async function getPlatform() {
137
- const g = globalThis;
138
- if (!g[GLOBAL_PLATFORM_KEY]) {
139
- try {
140
- console.log("dev-engine: calling getPlatformProxy()...");
141
- const startTime = Date.now();
142
- const { getPlatformProxy } = await import("wrangler");
143
- const platform = await getPlatformProxy();
144
- g[GLOBAL_PLATFORM_KEY] = { platform };
145
- console.log(`dev-engine: getPlatformProxy() succeeded in ${Date.now() - startTime}ms`);
146
- }
147
- catch (err) {
148
- console.error("dev-engine: Failed to load wrangler platform proxy:", err);
149
- }
150
- }
151
- return g[GLOBAL_PLATFORM_KEY]?.platform;
152
- }
153
- export async function broadcastExternalChange(channel, action, key, data) {
154
- const broker = getDevBroker();
155
- await broker.handleExternalChange(channel, action, key, data);
156
- }
157
- export async function broadcastExternalBatchChange(channel, changes) {
158
- const broker = getDevBroker();
159
- await broker.handleExternalBatchChange(channel, changes);
160
- }
package/dist/vite.d.ts DELETED
@@ -1,10 +0,0 @@
1
- import type { Plugin } from "vite";
2
- import type { SyncUpgradeOptions } from "./server/handler.js";
3
- export type SyncDevPluginOptions = {
4
- handlersPath?: string;
5
- auth?: SyncUpgradeOptions["auth"];
6
- identity?: SyncUpgradeOptions["identity"];
7
- allowUnauthenticated?: SyncUpgradeOptions["allowUnauthenticated"];
8
- };
9
- export declare function syncDevPlugin(options?: SyncDevPluginOptions): Plugin;
10
- //# sourceMappingURL=vite.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"vite.d.ts","sourceRoot":"","sources":["../src/vite.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AACnC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAa9D,MAAM,MAAM,oBAAoB,GAAG;IACjC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAClC,QAAQ,CAAC,EAAE,kBAAkB,CAAC,UAAU,CAAC,CAAC;IAC1C,oBAAoB,CAAC,EAAE,kBAAkB,CAAC,sBAAsB,CAAC,CAAC;CACnE,CAAC;AAEF,wBAAgB,aAAa,CAAC,OAAO,CAAC,EAAE,oBAAoB,GAAG,MAAM,CAwFpE"}
package/dist/vite.js DELETED
@@ -1,62 +0,0 @@
1
- const SYNC_PATH = "/api/sync";
2
- export function syncDevPlugin(options) {
3
- const handlersPath = options?.handlersPath ?? "/src/lib/server/sync-handlers.ts";
4
- return {
5
- name: "sync-dev-websocket",
6
- apply: "serve",
7
- async configureServer(server) {
8
- // Dynamic import — ws is a transitive dependency of Vite itself.
9
- // @ts-expect-error -- ws has no bundled type declarations
10
- const { WebSocketServer } = (await import("ws"));
11
- const wss = new WebSocketServer({ noServer: true });
12
- server.httpServer?.on("upgrade", (request, socket, head) => {
13
- const url = new URL(request.url ?? "", `http://${request.headers.host}`);
14
- if (url.pathname !== SYNC_PATH) {
15
- return;
16
- }
17
- wss.handleUpgrade(request, socket, head, (client) => {
18
- console.log("sync-dev-plugin: WebSocket upgrade handler starting (buffering messages)...");
19
- // Buffer messages while async ssrLoadModule runs to avoid race conditions
20
- const messageQueue = [];
21
- const onMessage = (data) => {
22
- messageQueue.push(data);
23
- };
24
- client.on("message", onMessage);
25
- (async () => {
26
- try {
27
- // Load the handlers module dynamically from the user-configured path
28
- const handlersModule = await server.ssrLoadModule(handlersPath);
29
- const devEngine = await server.ssrLoadModule("@sveltebase/sync/server/dev-engine");
30
- // Register handlers dynamically before connecting client
31
- devEngine.setHandlers(handlersModule.handlers);
32
- // Remove temporary buffering listener
33
- client.off("message", onMessage);
34
- // Register client in the dev engine
35
- const connected = await devEngine.addClient(client, request, {
36
- auth: options?.auth,
37
- identity: options?.identity,
38
- allowUnauthenticated: options?.allowUnauthenticated,
39
- });
40
- if (!connected) {
41
- return;
42
- }
43
- console.log("sync-dev-plugin: WebSocket upgrade handler completed, replaying buffered messages:", messageQueue.length);
44
- // Replay any buffered messages
45
- for (const msg of messageQueue) {
46
- client.emit("message", msg);
47
- }
48
- }
49
- catch (err) {
50
- console.error("sync-dev-plugin: Error in WebSocket upgrade handler:", err);
51
- try {
52
- client.off("message", onMessage);
53
- client.close(1011, "Internal server error");
54
- }
55
- catch { }
56
- }
57
- })();
58
- });
59
- });
60
- },
61
- };
62
- }