syncora 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +5 -0
- package/LICENSE +15 -0
- package/README.md +149 -0
- package/dist/chunk-VZXBPBHO.js +116 -0
- package/dist/chunk-VZXBPBHO.js.map +1 -0
- package/dist/client-OmEeE-w1.d.cts +136 -0
- package/dist/client-OmEeE-w1.d.ts +136 -0
- package/dist/index.cjs +591 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +82 -0
- package/dist/index.d.ts +82 -0
- package/dist/index.js +457 -0
- package/dist/index.js.map +1 -0
- package/dist/react.cjs +105 -0
- package/dist/react.cjs.map +1 -0
- package/dist/react.d.cts +19 -0
- package/dist/react.d.ts +19 -0
- package/dist/react.js +73 -0
- package/dist/react.js.map +1 -0
- package/package.json +87 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/server.ts","../src/store.ts","../src/client.ts"],"sourcesContent":["import { randomBytes } from \"node:crypto\";\nimport { WebSocketServer, type WebSocket } from \"ws\";\nimport type { Server as HttpServer } from \"node:http\";\nimport { matches } from \"./filter.js\";\nimport { MemoryStore, type SyncStore } from \"./store.js\";\nimport type {\n ChangeEvent,\n ClientMessage,\n Filter,\n ServerMessage,\n SyncDocument,\n} from \"./types.js\";\n\nexport interface SyncServerOptions {\n store?: SyncStore;\n server?: HttpServer;\n port?: number;\n host?: string;\n path?: string;\n authorize?: (handshake: { headers: Record<string, string | string[] | undefined>; url?: string }) => boolean | Promise<boolean>;\n permit?: (clientId: string, message: ClientMessage) => boolean | Promise<boolean>;\n}\n\ninterface ClientSession {\n id: string;\n socket: WebSocket;\n subscriptions: Map<string, { collection: string; filter?: Filter }>;\n}\n\nexport class SyncServer {\n readonly store: SyncStore;\n private wss: WebSocketServer;\n private clients = new Map<string, ClientSession>();\n private unwatch: () => void;\n private serverVersion = 0;\n\n constructor(options: SyncServerOptions = {}) {\n this.store = options.store ?? new MemoryStore();\n const wssConfig: ConstructorParameters<typeof WebSocketServer>[0] = options.server\n ? { server: options.server, path: options.path }\n : { host: options.host ?? \"127.0.0.1\", port: options.port ?? 0, path: options.path };\n this.wss = new WebSocketServer(wssConfig);\n this.wss.on(\"connection\", (socket, req) => this.handleConnection(socket, req, options.authorize, options.permit));\n this.unwatch = this.store.watch((event) => this.fanoutEvent(event));\n }\n\n address(): { host: string; port: number } | null {\n const a = this.wss.address();\n if (typeof a === \"string\" || a === null) return null;\n return { host: a.address, port: a.port };\n }\n\n async close(): Promise<void> {\n this.unwatch();\n for (const session of this.clients.values()) {\n try { session.socket.close(); } catch { /* ignore */ }\n }\n this.clients.clear();\n return new Promise((resolve) => this.wss.close(() => resolve()));\n }\n\n attachChangeStream(emitter: { on: (event: \"change\", handler: (event: ChangeEvent) => void) => unknown }): () => void {\n const handler = (event: ChangeEvent) => this.fanoutEvent(event);\n emitter.on(\"change\", handler);\n return () => {\n const off = (emitter as unknown as { off?: (event: string, handler: unknown) => unknown }).off;\n if (typeof off === \"function\") off.call(emitter, \"change\", handler);\n };\n }\n\n private async handleConnection(\n socket: WebSocket,\n req: { headers: Record<string, string | string[] | undefined>; url?: string },\n authorize?: SyncServerOptions[\"authorize\"],\n permit?: SyncServerOptions[\"permit\"],\n ): Promise<void> {\n if (authorize) {\n try {\n const ok = await authorize({ headers: req.headers, url: req.url });\n if (!ok) {\n socket.close(4401, \"unauthorized\");\n return;\n }\n } catch {\n socket.close(4401, \"unauthorized\");\n return;\n }\n }\n const session: ClientSession = {\n id: `c_${randomBytes(8).toString(\"hex\")}`,\n socket,\n subscriptions: new Map(),\n };\n this.clients.set(session.id, session);\n\n socket.on(\"close\", () => this.clients.delete(session.id));\n socket.on(\"error\", () => { /* socket lifecycle handled by ws */ });\n socket.on(\"message\", (data) => {\n this.handleMessage(session, data.toString(), permit).catch(() => {\n send(socket, { type: \"error\", message: \"internal error\" });\n });\n });\n\n send(socket, { type: \"hello\", clientId: session.id, serverVersion: this.serverVersion });\n }\n\n private async handleMessage(\n session: ClientSession,\n raw: string,\n permit?: SyncServerOptions[\"permit\"],\n ): Promise<void> {\n let message: ClientMessage;\n try { message = JSON.parse(raw) as ClientMessage; } catch {\n send(session.socket, { type: \"error\", message: \"invalid JSON\" });\n return;\n }\n if (permit) {\n try {\n const allowed = await permit(session.id, message);\n if (!allowed) {\n send(session.socket, { type: \"error\", message: \"forbidden\" });\n return;\n }\n } catch {\n send(session.socket, { type: \"error\", message: \"permission check failed\" });\n return;\n }\n }\n switch (message.type) {\n case \"subscribe\":\n return this.handleSubscribe(session, message);\n case \"unsubscribe\":\n session.subscriptions.delete(message.subscriptionId);\n return;\n case \"mutation\":\n return this.handleMutation(session, message);\n default:\n send(session.socket, { type: \"error\", message: \"unknown message type\" });\n }\n }\n\n private handleSubscribe(session: ClientSession, message: Extract<ClientMessage, { type: \"subscribe\" }>): void {\n session.subscriptions.set(message.subscriptionId, { collection: message.collection, filter: message.filter });\n const snapshot = this.store.snapshot(message.collection, message.filter);\n send(session.socket, {\n type: \"event\",\n subscriptionId: message.subscriptionId,\n event: { type: \"snapshot\", collection: message.collection, documents: snapshot.documents, version: snapshot.version },\n });\n }\n\n private handleMutation(session: ClientSession, message: Extract<ClientMessage, { type: \"mutation\" }>): void {\n try {\n if (message.op === \"insert\") {\n if (!message.document) throw new Error(\"document required\");\n this.store.insert(message.collection, message.document);\n } else if (message.op === \"update\") {\n if (!message.documentId || !message.patch) throw new Error(\"documentId and patch required\");\n const result = this.store.update(message.collection, message.documentId, message.patch);\n if (!result) throw new Error(\"not found\");\n } else if (message.op === \"delete\") {\n if (!message.documentId) throw new Error(\"documentId required\");\n const ok = this.store.delete(message.collection, message.documentId);\n if (!ok) throw new Error(\"not found\");\n }\n send(session.socket, { type: \"ack\", mutationId: message.mutationId, ok: true });\n } catch (err) {\n send(session.socket, {\n type: \"ack\",\n mutationId: message.mutationId,\n ok: false,\n error: err instanceof Error ? err.message : String(err),\n });\n }\n }\n\n private fanoutEvent(event: ChangeEvent): void {\n this.serverVersion = Math.max(this.serverVersion, event.version);\n for (const session of this.clients.values()) {\n for (const [subscriptionId, sub] of session.subscriptions) {\n if (sub.collection !== event.collection) continue;\n if (!eventMatchesFilter(event, sub.filter)) continue;\n send(session.socket, { type: \"event\", subscriptionId, event });\n }\n }\n }\n}\n\nfunction eventMatchesFilter(event: ChangeEvent, filter: Filter | undefined): boolean {\n if (!filter) return true;\n if (event.type === \"snapshot\") return true;\n if (event.type === \"delete\") return true;\n if (event.type === \"insert\") return matches(event.document, filter);\n if (event.type === \"update\") return matches(event.patch as SyncDocument, filter);\n return true;\n}\n\nfunction send(socket: WebSocket, message: ServerMessage): void {\n if (socket.readyState !== 1) return;\n try {\n socket.send(JSON.stringify(message));\n } catch {\n /* socket may have closed mid-send */\n }\n}\n","import { randomBytes } from \"node:crypto\";\nimport { matches } from \"./filter.js\";\nimport type { ChangeEvent, Filter, StoreSnapshot, SyncDocument } from \"./types.js\";\n\nexport interface SyncStore {\n insert<T extends SyncDocument>(collection: string, document: Omit<T, \"_id\"> & { _id?: string }): T;\n update<T extends SyncDocument>(collection: string, id: string, patch: Partial<T>): T | undefined;\n delete(collection: string, id: string): boolean;\n find<T extends SyncDocument>(collection: string, filter?: Filter): T[];\n findOne<T extends SyncDocument>(collection: string, id: string): T | undefined;\n snapshot<T extends SyncDocument>(collection: string, filter?: Filter): StoreSnapshot<T>;\n watch(handler: (event: ChangeEvent) => void): () => void;\n version(collection: string): number;\n reset(): void;\n}\n\nexport class MemoryStore implements SyncStore {\n private collections = new Map<string, Map<string, SyncDocument>>();\n private versions = new Map<string, number>();\n private watchers = new Set<(e: ChangeEvent) => void>();\n\n insert<T extends SyncDocument>(collection: string, doc: Omit<T, \"_id\"> & { _id?: string }): T {\n const id = doc._id ?? `doc_${randomBytes(8).toString(\"hex\")}`;\n const map = this.ensureCollection(collection);\n const document = { ...doc, _id: id } as unknown as T;\n map.set(id, document);\n const version = this.bumpVersion(collection);\n this.emit({ type: \"insert\", collection, document, version });\n return document;\n }\n\n update<T extends SyncDocument>(collection: string, id: string, patch: Partial<T>): T | undefined {\n const map = this.collections.get(collection);\n if (!map) return undefined;\n const existing = map.get(id);\n if (!existing) return undefined;\n const updated = { ...existing, ...patch, _id: id } as T;\n map.set(id, updated);\n const version = this.bumpVersion(collection);\n this.emit({ type: \"update\", collection, documentId: id, patch, version });\n return updated;\n }\n\n delete(collection: string, id: string): boolean {\n const map = this.collections.get(collection);\n if (!map) return false;\n if (!map.delete(id)) return false;\n const version = this.bumpVersion(collection);\n this.emit({ type: \"delete\", collection, documentId: id, version });\n return true;\n }\n\n find<T extends SyncDocument>(collection: string, filter?: Filter): T[] {\n const map = this.collections.get(collection);\n if (!map) return [];\n const out: T[] = [];\n for (const doc of map.values()) {\n if (matches(doc, filter)) out.push(doc as T);\n }\n return out;\n }\n\n findOne<T extends SyncDocument>(collection: string, id: string): T | undefined {\n return this.collections.get(collection)?.get(id) as T | undefined;\n }\n\n snapshot<T extends SyncDocument>(collection: string, filter?: Filter): StoreSnapshot<T> {\n return { documents: this.find<T>(collection, filter), version: this.version(collection) };\n }\n\n watch(handler: (event: ChangeEvent) => void): () => void {\n this.watchers.add(handler);\n return () => this.watchers.delete(handler);\n }\n\n version(collection: string): number {\n return this.versions.get(collection) ?? 0;\n }\n\n reset(): void {\n this.collections.clear();\n this.versions.clear();\n }\n\n private ensureCollection(collection: string): Map<string, SyncDocument> {\n let map = this.collections.get(collection);\n if (!map) {\n map = new Map();\n this.collections.set(collection, map);\n }\n return map;\n }\n\n private bumpVersion(collection: string): number {\n const next = this.version(collection) + 1;\n this.versions.set(collection, next);\n return next;\n }\n\n private emit(event: ChangeEvent): void {\n for (const w of this.watchers) {\n try { w(event); } catch { /* swallow individual subscriber errors */ }\n }\n }\n}\n","import { applyEventToDocuments } from \"./apply.js\";\nimport type {\n ChangeEvent,\n ClientMessage,\n Filter,\n ServerMessage,\n SyncDocument,\n} from \"./types.js\";\n\ntype WSLike = {\n send(data: string): void;\n close(): void;\n addEventListener(event: \"open\", cb: () => void): void;\n addEventListener(event: \"close\", cb: () => void): void;\n addEventListener(event: \"error\", cb: (event: unknown) => void): void;\n addEventListener(event: \"message\", cb: (event: { data: unknown }) => void): void;\n readyState?: number;\n};\n\ntype WSConstructor = new (url: string) => WSLike;\n\nexport interface SyncoraClientOptions {\n url: string;\n WebSocket?: WSConstructor;\n reconnectDelayMs?: number;\n maxReconnectDelayMs?: number;\n onConnect?: (clientId: string) => void;\n onDisconnect?: () => void;\n onError?: (error: unknown) => void;\n}\n\nexport interface Subscription<T extends SyncDocument = SyncDocument> {\n id: string;\n collection: string;\n filter?: Filter;\n data: T[];\n version: number;\n unsubscribe(): void;\n onChange(listener: (state: { data: T[]; version: number }) => void): () => void;\n}\n\ntype Listener<T extends SyncDocument> = (state: { data: T[]; version: number }) => void;\n\n/** Stored subscriptions are document-shaped only; `subscribe<T>` bridges at the API boundary. */\ninterface InternalSubscription {\n id: string;\n collection: string;\n filter?: Filter;\n data: SyncDocument[];\n version: number;\n listeners: Set<(state: { data: SyncDocument[]; version: number }) => void>;\n}\n\ntype PendingMutation = { resolve: () => void; reject: (err: Error) => void };\n\nexport class SyncoraClient {\n private url: string;\n private WS: WSConstructor;\n private socket?: WSLike;\n private subscriptions = new Map<string, InternalSubscription>();\n private pendingMutations = new Map<string, PendingMutation>();\n private reconnectDelay: number;\n private maxReconnectDelay: number;\n private currentDelay: number;\n private intentionalClose = false;\n private clientId?: string;\n private outbox: ClientMessage[] = [];\n private connectedListeners = new Set<(clientId: string) => void>();\n private disconnectedListeners = new Set<() => void>();\n private onError?: (error: unknown) => void;\n\n constructor(options: SyncoraClientOptions) {\n this.url = options.url;\n this.WS = options.WebSocket ?? (globalThis as { WebSocket?: WSConstructor }).WebSocket as WSConstructor;\n if (!this.WS) throw new Error(\"No WebSocket implementation. Pass options.WebSocket explicitly.\");\n this.reconnectDelay = options.reconnectDelayMs ?? 500;\n this.maxReconnectDelay = options.maxReconnectDelayMs ?? 15_000;\n this.currentDelay = this.reconnectDelay;\n this.onError = options.onError;\n if (options.onConnect) this.connectedListeners.add(options.onConnect);\n if (options.onDisconnect) this.disconnectedListeners.add(options.onDisconnect);\n this.connect();\n }\n\n isConnected(): boolean {\n return this.socket?.readyState === 1;\n }\n\n close(): void {\n this.intentionalClose = true;\n this.socket?.close();\n }\n\n onConnect(handler: (clientId: string) => void): () => void {\n this.connectedListeners.add(handler);\n return () => this.connectedListeners.delete(handler);\n }\n\n onDisconnect(handler: () => void): () => void {\n this.disconnectedListeners.add(handler);\n return () => this.disconnectedListeners.delete(handler);\n }\n\n subscribe<T extends SyncDocument = SyncDocument>(collection: string, options: { filter?: Filter } = {}): Subscription<T> {\n const id = `sub_${cryptoRandom()}`;\n const sub: InternalSubscription = {\n id,\n collection,\n filter: options.filter,\n data: [],\n version: 0,\n listeners: new Set(),\n };\n this.subscriptions.set(id, sub);\n this.send({ type: \"subscribe\", subscriptionId: id, collection, filter: options.filter });\n const api: Subscription<T> = {\n id,\n collection,\n filter: options.filter,\n get data() { return sub.data as T[]; },\n get version() { return sub.version; },\n unsubscribe: () => {\n this.subscriptions.delete(id);\n this.send({ type: \"unsubscribe\", subscriptionId: id });\n },\n onChange: (listener: Listener<T>) => {\n const bridge = (state: { data: SyncDocument[]; version: number }) => {\n listener({ data: state.data as T[], version: state.version });\n };\n sub.listeners.add(bridge);\n bridge({ data: sub.data, version: sub.version });\n return () => sub.listeners.delete(bridge);\n },\n };\n return api;\n }\n\n async mutate(\n collection: string,\n op: \"insert\" | \"update\" | \"delete\",\n payload: { document?: SyncDocument; documentId?: string; patch?: Partial<SyncDocument> } = {},\n ): Promise<void> {\n const mutationId = `mut_${cryptoRandom()}`;\n const message: ClientMessage = {\n type: \"mutation\",\n mutationId,\n collection,\n op,\n ...payload,\n };\n return new Promise<void>((resolve, reject) => {\n this.pendingMutations.set(mutationId, { resolve, reject });\n this.send(message);\n });\n }\n\n private connect(): void {\n this.intentionalClose = false;\n let socket: WSLike;\n try {\n socket = new this.WS(this.url);\n } catch (err) {\n this.onError?.(err);\n this.scheduleReconnect();\n return;\n }\n this.socket = socket;\n socket.addEventListener(\"open\", () => {\n this.currentDelay = this.reconnectDelay;\n for (const msg of this.outbox) {\n try { socket.send(JSON.stringify(msg)); } catch { /* drop */ }\n }\n this.outbox = [];\n for (const sub of this.subscriptions.values()) {\n try {\n socket.send(JSON.stringify({ type: \"subscribe\", subscriptionId: sub.id, collection: sub.collection, filter: sub.filter } satisfies ClientMessage));\n } catch { /* drop */ }\n }\n });\n socket.addEventListener(\"message\", (event) => {\n let parsed: ServerMessage;\n try {\n parsed = JSON.parse(typeof event.data === \"string\" ? event.data : String(event.data)) as ServerMessage;\n } catch {\n return;\n }\n this.handleMessage(parsed);\n });\n socket.addEventListener(\"error\", (err) => this.onError?.(err));\n socket.addEventListener(\"close\", () => {\n for (const listener of this.disconnectedListeners) listener();\n if (!this.intentionalClose) this.scheduleReconnect();\n });\n }\n\n private scheduleReconnect(): void {\n const delay = this.currentDelay;\n this.currentDelay = Math.min(this.maxReconnectDelay, this.currentDelay * 2);\n setTimeout(() => this.connect(), delay);\n }\n\n private handleMessage(message: ServerMessage): void {\n switch (message.type) {\n case \"hello\":\n this.clientId = message.clientId;\n for (const listener of this.connectedListeners) listener(message.clientId);\n break;\n case \"event\": {\n const sub = this.subscriptions.get(message.subscriptionId);\n if (!sub) return;\n applyEventToSubscription(sub, message.event);\n for (const l of sub.listeners) l({ data: sub.data, version: sub.version });\n break;\n }\n case \"ack\": {\n const pending = this.pendingMutations.get(message.mutationId);\n if (!pending) return;\n this.pendingMutations.delete(message.mutationId);\n if (message.ok) pending.resolve();\n else pending.reject(new Error(message.error ?? \"mutation rejected\"));\n break;\n }\n case \"error\":\n this.onError?.(new Error(message.message));\n break;\n }\n }\n\n private send(message: ClientMessage): void {\n if (this.socket && this.socket.readyState === 1) {\n try {\n this.socket.send(JSON.stringify(message));\n return;\n } catch { /* fall through to outbox */ }\n }\n this.outbox.push(message);\n }\n}\n\nfunction applyEventToSubscription(sub: InternalSubscription, event: ChangeEvent): void {\n const { data, version } = applyEventToDocuments<SyncDocument>(sub.data, sub.version, event, sub.filter);\n sub.data = data;\n sub.version = version;\n}\n\nfunction cryptoRandom(): string {\n const bytes = new Uint8Array(8);\n if (typeof globalThis.crypto !== \"undefined\" && typeof globalThis.crypto.getRandomValues === \"function\") {\n globalThis.crypto.getRandomValues(bytes);\n } else {\n for (let i = 0; i < 8; i++) bytes[i] = Math.floor(Math.random() * 256);\n }\n return Array.from(bytes, (b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n}\n"],"mappings":"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","names":["randomBytes","randomBytes"]}
|
package/dist/react.cjs
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/react.ts
|
|
21
|
+
var react_exports = {};
|
|
22
|
+
__export(react_exports, {
|
|
23
|
+
createSyncoraHooks: () => createSyncoraHooks
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(react_exports);
|
|
26
|
+
var import_react = require("react");
|
|
27
|
+
|
|
28
|
+
// src/apply.ts
|
|
29
|
+
function applyOptimisticInsert(documents, document) {
|
|
30
|
+
return [...documents.filter((d) => d._id !== document._id), document];
|
|
31
|
+
}
|
|
32
|
+
function applyOptimisticUpdate(documents, id, patch) {
|
|
33
|
+
return documents.map((d) => d._id === id ? { ...d, ...patch, _id: id } : d);
|
|
34
|
+
}
|
|
35
|
+
function applyOptimisticDelete(documents, id) {
|
|
36
|
+
return documents.filter((d) => d._id !== id);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// src/react.ts
|
|
40
|
+
function createSyncoraHooks(client) {
|
|
41
|
+
function useSyncora(collection, options = {}) {
|
|
42
|
+
const subscriptionRef = (0, import_react.useRef)(null);
|
|
43
|
+
const [, force] = (0, import_react.useState)(0);
|
|
44
|
+
(0, import_react.useEffect)(() => {
|
|
45
|
+
const sub = client.subscribe(collection, { filter: options.filter });
|
|
46
|
+
subscriptionRef.current = sub;
|
|
47
|
+
const off = sub.onChange(() => force((n) => n + 1));
|
|
48
|
+
return () => {
|
|
49
|
+
off();
|
|
50
|
+
sub.unsubscribe();
|
|
51
|
+
subscriptionRef.current = null;
|
|
52
|
+
};
|
|
53
|
+
}, [collection, JSON.stringify(options.filter)]);
|
|
54
|
+
const isConnected = (0, import_react.useSyncExternalStore)(
|
|
55
|
+
(notify) => {
|
|
56
|
+
const onC = client.onConnect(() => notify());
|
|
57
|
+
const onD = client.onDisconnect(() => notify());
|
|
58
|
+
return () => {
|
|
59
|
+
onC();
|
|
60
|
+
onD();
|
|
61
|
+
};
|
|
62
|
+
},
|
|
63
|
+
() => client.isConnected(),
|
|
64
|
+
() => false
|
|
65
|
+
);
|
|
66
|
+
const data = subscriptionRef.current?.data ?? [];
|
|
67
|
+
const version = subscriptionRef.current?.version ?? 0;
|
|
68
|
+
const actions = (0, import_react.useMemo)(() => {
|
|
69
|
+
const insert = async (document) => {
|
|
70
|
+
if (options.optimistic && subscriptionRef.current) {
|
|
71
|
+
subscriptionRef.current.data = applyOptimisticInsert(subscriptionRef.current.data, document);
|
|
72
|
+
force((n) => n + 1);
|
|
73
|
+
}
|
|
74
|
+
await client.mutate(collection, "insert", { document });
|
|
75
|
+
};
|
|
76
|
+
const update = async (id, patch) => {
|
|
77
|
+
if (options.optimistic && subscriptionRef.current) {
|
|
78
|
+
subscriptionRef.current.data = applyOptimisticUpdate(subscriptionRef.current.data, id, patch);
|
|
79
|
+
force((n) => n + 1);
|
|
80
|
+
}
|
|
81
|
+
await client.mutate(collection, "update", { documentId: id, patch });
|
|
82
|
+
};
|
|
83
|
+
const remove = async (id) => {
|
|
84
|
+
if (options.optimistic && subscriptionRef.current) {
|
|
85
|
+
subscriptionRef.current.data = applyOptimisticDelete(subscriptionRef.current.data, id);
|
|
86
|
+
force((n) => n + 1);
|
|
87
|
+
}
|
|
88
|
+
await client.mutate(collection, "delete", { documentId: id });
|
|
89
|
+
};
|
|
90
|
+
return { insert, update, remove };
|
|
91
|
+
}, [collection, options.optimistic]);
|
|
92
|
+
return {
|
|
93
|
+
data,
|
|
94
|
+
version,
|
|
95
|
+
isConnected,
|
|
96
|
+
...actions
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
return { useSyncora };
|
|
100
|
+
}
|
|
101
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
102
|
+
0 && (module.exports = {
|
|
103
|
+
createSyncoraHooks
|
|
104
|
+
});
|
|
105
|
+
//# sourceMappingURL=react.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/react.ts","../src/apply.ts"],"sourcesContent":["import { useEffect, useMemo, useRef, useState, useSyncExternalStore } from \"react\";\nimport {\n applyOptimisticDelete,\n applyOptimisticInsert,\n applyOptimisticUpdate,\n} from \"./apply.js\";\nimport type { SyncoraClient, Subscription } from \"./client.js\";\nimport type { Filter, SyncDocument } from \"./types.js\";\n\nexport interface UseSyncoraResult<T extends SyncDocument> {\n data: T[];\n version: number;\n isConnected: boolean;\n insert(document: T): Promise<void>;\n update(id: string, patch: Partial<T>): Promise<void>;\n remove(id: string): Promise<void>;\n}\n\nexport interface UseSyncoraOptions {\n filter?: Filter;\n optimistic?: boolean;\n}\n\nexport function createSyncoraHooks(client: SyncoraClient) {\n function useSyncora<T extends SyncDocument = SyncDocument>(\n collection: string,\n options: UseSyncoraOptions = {},\n ): UseSyncoraResult<T> {\n const subscriptionRef = useRef<Subscription<T> | null>(null);\n const [, force] = useState(0);\n\n useEffect(() => {\n const sub = client.subscribe<T>(collection, { filter: options.filter });\n subscriptionRef.current = sub;\n const off = sub.onChange(() => force((n) => n + 1));\n return () => {\n off();\n sub.unsubscribe();\n subscriptionRef.current = null;\n };\n }, [collection, JSON.stringify(options.filter)]);\n\n const isConnected = useSyncExternalStore(\n (notify) => {\n const onC = client.onConnect(() => notify());\n const onD = client.onDisconnect(() => notify());\n return () => { onC(); onD(); };\n },\n () => client.isConnected(),\n () => false,\n );\n\n const data = subscriptionRef.current?.data ?? [];\n const version = subscriptionRef.current?.version ?? 0;\n\n const actions = useMemo(() => {\n const insert = async (document: T) => {\n if (options.optimistic && subscriptionRef.current) {\n subscriptionRef.current.data = applyOptimisticInsert(subscriptionRef.current.data, document);\n force((n) => n + 1);\n }\n await client.mutate(collection, \"insert\", { document });\n };\n const update = async (id: string, patch: Partial<T>) => {\n if (options.optimistic && subscriptionRef.current) {\n subscriptionRef.current.data = applyOptimisticUpdate(subscriptionRef.current.data, id, patch);\n force((n) => n + 1);\n }\n await client.mutate(collection, \"update\", { documentId: id, patch: patch as Partial<SyncDocument> });\n };\n const remove = async (id: string) => {\n if (options.optimistic && subscriptionRef.current) {\n subscriptionRef.current.data = applyOptimisticDelete(subscriptionRef.current.data, id);\n force((n) => n + 1);\n }\n await client.mutate(collection, \"delete\", { documentId: id });\n };\n return { insert, update, remove };\n }, [collection, options.optimistic]);\n\n return {\n data,\n version,\n isConnected,\n ...actions,\n };\n }\n\n return { useSyncora };\n}\n","import { matches } from \"./filter.js\";\nimport type { ChangeEvent, Filter, SyncDocument } from \"./types.js\";\n\nexport function applyEventToDocuments<T extends SyncDocument>(\n documents: T[],\n version: number,\n event: ChangeEvent,\n filter?: Filter,\n): { data: T[]; version: number } {\n if (event.type === \"snapshot\") {\n const next = (event.documents as T[]).filter((d) => matches(d, filter));\n return { data: next, version: event.version };\n }\n if (event.type === \"insert\") {\n if (!matches(event.document, filter)) return { data: documents, version: event.version };\n const next = [...documents.filter((d) => d._id !== event.document._id), event.document as T];\n return { data: next, version: event.version };\n }\n if (event.type === \"update\") {\n const next = documents.map((d) =>\n d._id === event.documentId ? ({ ...d, ...event.patch, _id: d._id } as T) : d,\n );\n if (filter) {\n const filtered = next.filter((d) => matches(d, filter));\n return { data: filtered, version: event.version };\n }\n return { data: next, version: event.version };\n }\n if (event.type === \"delete\") {\n return { data: documents.filter((d) => d._id !== event.documentId), version: event.version };\n }\n return { data: documents, version };\n}\n\nexport function applyOptimisticInsert<T extends SyncDocument>(documents: T[], document: T): T[] {\n return [...documents.filter((d) => d._id !== document._id), document];\n}\n\nexport function applyOptimisticUpdate<T extends SyncDocument>(\n documents: T[],\n id: string,\n patch: Partial<T>,\n): T[] {\n return documents.map((d) => (d._id === id ? ({ ...d, ...patch, _id: id } as T) : d));\n}\n\nexport function applyOptimisticDelete<T extends SyncDocument>(documents: T[], id: string): T[] {\n return documents.filter((d) => d._id !== id);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAA2E;;;ACkCpE,SAAS,sBAA8C,WAAgB,UAAkB;AAC9F,SAAO,CAAC,GAAG,UAAU,OAAO,CAAC,MAAM,EAAE,QAAQ,SAAS,GAAG,GAAG,QAAQ;AACtE;AAEO,SAAS,sBACd,WACA,IACA,OACK;AACL,SAAO,UAAU,IAAI,CAAC,MAAO,EAAE,QAAQ,KAAM,EAAE,GAAG,GAAG,GAAG,OAAO,KAAK,GAAG,IAAU,CAAE;AACrF;AAEO,SAAS,sBAA8C,WAAgB,IAAiB;AAC7F,SAAO,UAAU,OAAO,CAAC,MAAM,EAAE,QAAQ,EAAE;AAC7C;;;ADzBO,SAAS,mBAAmB,QAAuB;AACxD,WAAS,WACP,YACA,UAA6B,CAAC,GACT;AACrB,UAAM,sBAAkB,qBAA+B,IAAI;AAC3D,UAAM,CAAC,EAAE,KAAK,QAAI,uBAAS,CAAC;AAE5B,gCAAU,MAAM;AACd,YAAM,MAAM,OAAO,UAAa,YAAY,EAAE,QAAQ,QAAQ,OAAO,CAAC;AACtE,sBAAgB,UAAU;AAC1B,YAAM,MAAM,IAAI,SAAS,MAAM,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC;AAClD,aAAO,MAAM;AACX,YAAI;AACJ,YAAI,YAAY;AAChB,wBAAgB,UAAU;AAAA,MAC5B;AAAA,IACF,GAAG,CAAC,YAAY,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAE/C,UAAM,kBAAc;AAAA,MAClB,CAAC,WAAW;AACV,cAAM,MAAM,OAAO,UAAU,MAAM,OAAO,CAAC;AAC3C,cAAM,MAAM,OAAO,aAAa,MAAM,OAAO,CAAC;AAC9C,eAAO,MAAM;AAAE,cAAI;AAAG,cAAI;AAAA,QAAG;AAAA,MAC/B;AAAA,MACA,MAAM,OAAO,YAAY;AAAA,MACzB,MAAM;AAAA,IACR;AAEA,UAAM,OAAO,gBAAgB,SAAS,QAAQ,CAAC;AAC/C,UAAM,UAAU,gBAAgB,SAAS,WAAW;AAEpD,UAAM,cAAU,sBAAQ,MAAM;AAC5B,YAAM,SAAS,OAAO,aAAgB;AACpC,YAAI,QAAQ,cAAc,gBAAgB,SAAS;AACjD,0BAAgB,QAAQ,OAAO,sBAAsB,gBAAgB,QAAQ,MAAM,QAAQ;AAC3F,gBAAM,CAAC,MAAM,IAAI,CAAC;AAAA,QACpB;AACA,cAAM,OAAO,OAAO,YAAY,UAAU,EAAE,SAAS,CAAC;AAAA,MACxD;AACA,YAAM,SAAS,OAAO,IAAY,UAAsB;AACtD,YAAI,QAAQ,cAAc,gBAAgB,SAAS;AACjD,0BAAgB,QAAQ,OAAO,sBAAsB,gBAAgB,QAAQ,MAAM,IAAI,KAAK;AAC5F,gBAAM,CAAC,MAAM,IAAI,CAAC;AAAA,QACpB;AACA,cAAM,OAAO,OAAO,YAAY,UAAU,EAAE,YAAY,IAAI,MAAsC,CAAC;AAAA,MACrG;AACA,YAAM,SAAS,OAAO,OAAe;AACnC,YAAI,QAAQ,cAAc,gBAAgB,SAAS;AACjD,0BAAgB,QAAQ,OAAO,sBAAsB,gBAAgB,QAAQ,MAAM,EAAE;AACrF,gBAAM,CAAC,MAAM,IAAI,CAAC;AAAA,QACpB;AACA,cAAM,OAAO,OAAO,YAAY,UAAU,EAAE,YAAY,GAAG,CAAC;AAAA,MAC9D;AACA,aAAO,EAAE,QAAQ,QAAQ,OAAO;AAAA,IAClC,GAAG,CAAC,YAAY,QAAQ,UAAU,CAAC;AAEnC,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA,GAAG;AAAA,IACL;AAAA,EACF;AAEA,SAAO,EAAE,WAAW;AACtB;","names":[]}
|
package/dist/react.d.cts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { F as Filter, d as SyncDocument, e as SyncoraClient } from './client-OmEeE-w1.cjs';
|
|
2
|
+
|
|
3
|
+
interface UseSyncoraResult<T extends SyncDocument> {
|
|
4
|
+
data: T[];
|
|
5
|
+
version: number;
|
|
6
|
+
isConnected: boolean;
|
|
7
|
+
insert(document: T): Promise<void>;
|
|
8
|
+
update(id: string, patch: Partial<T>): Promise<void>;
|
|
9
|
+
remove(id: string): Promise<void>;
|
|
10
|
+
}
|
|
11
|
+
interface UseSyncoraOptions {
|
|
12
|
+
filter?: Filter;
|
|
13
|
+
optimistic?: boolean;
|
|
14
|
+
}
|
|
15
|
+
declare function createSyncoraHooks(client: SyncoraClient): {
|
|
16
|
+
useSyncora: <T extends SyncDocument = SyncDocument>(collection: string, options?: UseSyncoraOptions) => UseSyncoraResult<T>;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export { type UseSyncoraOptions, type UseSyncoraResult, createSyncoraHooks };
|
package/dist/react.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { F as Filter, d as SyncDocument, e as SyncoraClient } from './client-OmEeE-w1.js';
|
|
2
|
+
|
|
3
|
+
interface UseSyncoraResult<T extends SyncDocument> {
|
|
4
|
+
data: T[];
|
|
5
|
+
version: number;
|
|
6
|
+
isConnected: boolean;
|
|
7
|
+
insert(document: T): Promise<void>;
|
|
8
|
+
update(id: string, patch: Partial<T>): Promise<void>;
|
|
9
|
+
remove(id: string): Promise<void>;
|
|
10
|
+
}
|
|
11
|
+
interface UseSyncoraOptions {
|
|
12
|
+
filter?: Filter;
|
|
13
|
+
optimistic?: boolean;
|
|
14
|
+
}
|
|
15
|
+
declare function createSyncoraHooks(client: SyncoraClient): {
|
|
16
|
+
useSyncora: <T extends SyncDocument = SyncDocument>(collection: string, options?: UseSyncoraOptions) => UseSyncoraResult<T>;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export { type UseSyncoraOptions, type UseSyncoraResult, createSyncoraHooks };
|
package/dist/react.js
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import {
|
|
2
|
+
applyOptimisticDelete,
|
|
3
|
+
applyOptimisticInsert,
|
|
4
|
+
applyOptimisticUpdate
|
|
5
|
+
} from "./chunk-VZXBPBHO.js";
|
|
6
|
+
|
|
7
|
+
// src/react.ts
|
|
8
|
+
import { useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
|
|
9
|
+
function createSyncoraHooks(client) {
|
|
10
|
+
function useSyncora(collection, options = {}) {
|
|
11
|
+
const subscriptionRef = useRef(null);
|
|
12
|
+
const [, force] = useState(0);
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
const sub = client.subscribe(collection, { filter: options.filter });
|
|
15
|
+
subscriptionRef.current = sub;
|
|
16
|
+
const off = sub.onChange(() => force((n) => n + 1));
|
|
17
|
+
return () => {
|
|
18
|
+
off();
|
|
19
|
+
sub.unsubscribe();
|
|
20
|
+
subscriptionRef.current = null;
|
|
21
|
+
};
|
|
22
|
+
}, [collection, JSON.stringify(options.filter)]);
|
|
23
|
+
const isConnected = useSyncExternalStore(
|
|
24
|
+
(notify) => {
|
|
25
|
+
const onC = client.onConnect(() => notify());
|
|
26
|
+
const onD = client.onDisconnect(() => notify());
|
|
27
|
+
return () => {
|
|
28
|
+
onC();
|
|
29
|
+
onD();
|
|
30
|
+
};
|
|
31
|
+
},
|
|
32
|
+
() => client.isConnected(),
|
|
33
|
+
() => false
|
|
34
|
+
);
|
|
35
|
+
const data = subscriptionRef.current?.data ?? [];
|
|
36
|
+
const version = subscriptionRef.current?.version ?? 0;
|
|
37
|
+
const actions = useMemo(() => {
|
|
38
|
+
const insert = async (document) => {
|
|
39
|
+
if (options.optimistic && subscriptionRef.current) {
|
|
40
|
+
subscriptionRef.current.data = applyOptimisticInsert(subscriptionRef.current.data, document);
|
|
41
|
+
force((n) => n + 1);
|
|
42
|
+
}
|
|
43
|
+
await client.mutate(collection, "insert", { document });
|
|
44
|
+
};
|
|
45
|
+
const update = async (id, patch) => {
|
|
46
|
+
if (options.optimistic && subscriptionRef.current) {
|
|
47
|
+
subscriptionRef.current.data = applyOptimisticUpdate(subscriptionRef.current.data, id, patch);
|
|
48
|
+
force((n) => n + 1);
|
|
49
|
+
}
|
|
50
|
+
await client.mutate(collection, "update", { documentId: id, patch });
|
|
51
|
+
};
|
|
52
|
+
const remove = async (id) => {
|
|
53
|
+
if (options.optimistic && subscriptionRef.current) {
|
|
54
|
+
subscriptionRef.current.data = applyOptimisticDelete(subscriptionRef.current.data, id);
|
|
55
|
+
force((n) => n + 1);
|
|
56
|
+
}
|
|
57
|
+
await client.mutate(collection, "delete", { documentId: id });
|
|
58
|
+
};
|
|
59
|
+
return { insert, update, remove };
|
|
60
|
+
}, [collection, options.optimistic]);
|
|
61
|
+
return {
|
|
62
|
+
data,
|
|
63
|
+
version,
|
|
64
|
+
isConnected,
|
|
65
|
+
...actions
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
return { useSyncora };
|
|
69
|
+
}
|
|
70
|
+
export {
|
|
71
|
+
createSyncoraHooks
|
|
72
|
+
};
|
|
73
|
+
//# sourceMappingURL=react.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/react.ts"],"sourcesContent":["import { useEffect, useMemo, useRef, useState, useSyncExternalStore } from \"react\";\nimport {\n applyOptimisticDelete,\n applyOptimisticInsert,\n applyOptimisticUpdate,\n} from \"./apply.js\";\nimport type { SyncoraClient, Subscription } from \"./client.js\";\nimport type { Filter, SyncDocument } from \"./types.js\";\n\nexport interface UseSyncoraResult<T extends SyncDocument> {\n data: T[];\n version: number;\n isConnected: boolean;\n insert(document: T): Promise<void>;\n update(id: string, patch: Partial<T>): Promise<void>;\n remove(id: string): Promise<void>;\n}\n\nexport interface UseSyncoraOptions {\n filter?: Filter;\n optimistic?: boolean;\n}\n\nexport function createSyncoraHooks(client: SyncoraClient) {\n function useSyncora<T extends SyncDocument = SyncDocument>(\n collection: string,\n options: UseSyncoraOptions = {},\n ): UseSyncoraResult<T> {\n const subscriptionRef = useRef<Subscription<T> | null>(null);\n const [, force] = useState(0);\n\n useEffect(() => {\n const sub = client.subscribe<T>(collection, { filter: options.filter });\n subscriptionRef.current = sub;\n const off = sub.onChange(() => force((n) => n + 1));\n return () => {\n off();\n sub.unsubscribe();\n subscriptionRef.current = null;\n };\n }, [collection, JSON.stringify(options.filter)]);\n\n const isConnected = useSyncExternalStore(\n (notify) => {\n const onC = client.onConnect(() => notify());\n const onD = client.onDisconnect(() => notify());\n return () => { onC(); onD(); };\n },\n () => client.isConnected(),\n () => false,\n );\n\n const data = subscriptionRef.current?.data ?? [];\n const version = subscriptionRef.current?.version ?? 0;\n\n const actions = useMemo(() => {\n const insert = async (document: T) => {\n if (options.optimistic && subscriptionRef.current) {\n subscriptionRef.current.data = applyOptimisticInsert(subscriptionRef.current.data, document);\n force((n) => n + 1);\n }\n await client.mutate(collection, \"insert\", { document });\n };\n const update = async (id: string, patch: Partial<T>) => {\n if (options.optimistic && subscriptionRef.current) {\n subscriptionRef.current.data = applyOptimisticUpdate(subscriptionRef.current.data, id, patch);\n force((n) => n + 1);\n }\n await client.mutate(collection, \"update\", { documentId: id, patch: patch as Partial<SyncDocument> });\n };\n const remove = async (id: string) => {\n if (options.optimistic && subscriptionRef.current) {\n subscriptionRef.current.data = applyOptimisticDelete(subscriptionRef.current.data, id);\n force((n) => n + 1);\n }\n await client.mutate(collection, \"delete\", { documentId: id });\n };\n return { insert, update, remove };\n }, [collection, options.optimistic]);\n\n return {\n data,\n version,\n isConnected,\n ...actions,\n };\n }\n\n return { useSyncora };\n}\n"],"mappings":";;;;;;;AAAA,SAAS,WAAW,SAAS,QAAQ,UAAU,4BAA4B;AAuBpE,SAAS,mBAAmB,QAAuB;AACxD,WAAS,WACP,YACA,UAA6B,CAAC,GACT;AACrB,UAAM,kBAAkB,OAA+B,IAAI;AAC3D,UAAM,CAAC,EAAE,KAAK,IAAI,SAAS,CAAC;AAE5B,cAAU,MAAM;AACd,YAAM,MAAM,OAAO,UAAa,YAAY,EAAE,QAAQ,QAAQ,OAAO,CAAC;AACtE,sBAAgB,UAAU;AAC1B,YAAM,MAAM,IAAI,SAAS,MAAM,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC;AAClD,aAAO,MAAM;AACX,YAAI;AACJ,YAAI,YAAY;AAChB,wBAAgB,UAAU;AAAA,MAC5B;AAAA,IACF,GAAG,CAAC,YAAY,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAE/C,UAAM,cAAc;AAAA,MAClB,CAAC,WAAW;AACV,cAAM,MAAM,OAAO,UAAU,MAAM,OAAO,CAAC;AAC3C,cAAM,MAAM,OAAO,aAAa,MAAM,OAAO,CAAC;AAC9C,eAAO,MAAM;AAAE,cAAI;AAAG,cAAI;AAAA,QAAG;AAAA,MAC/B;AAAA,MACA,MAAM,OAAO,YAAY;AAAA,MACzB,MAAM;AAAA,IACR;AAEA,UAAM,OAAO,gBAAgB,SAAS,QAAQ,CAAC;AAC/C,UAAM,UAAU,gBAAgB,SAAS,WAAW;AAEpD,UAAM,UAAU,QAAQ,MAAM;AAC5B,YAAM,SAAS,OAAO,aAAgB;AACpC,YAAI,QAAQ,cAAc,gBAAgB,SAAS;AACjD,0BAAgB,QAAQ,OAAO,sBAAsB,gBAAgB,QAAQ,MAAM,QAAQ;AAC3F,gBAAM,CAAC,MAAM,IAAI,CAAC;AAAA,QACpB;AACA,cAAM,OAAO,OAAO,YAAY,UAAU,EAAE,SAAS,CAAC;AAAA,MACxD;AACA,YAAM,SAAS,OAAO,IAAY,UAAsB;AACtD,YAAI,QAAQ,cAAc,gBAAgB,SAAS;AACjD,0BAAgB,QAAQ,OAAO,sBAAsB,gBAAgB,QAAQ,MAAM,IAAI,KAAK;AAC5F,gBAAM,CAAC,MAAM,IAAI,CAAC;AAAA,QACpB;AACA,cAAM,OAAO,OAAO,YAAY,UAAU,EAAE,YAAY,IAAI,MAAsC,CAAC;AAAA,MACrG;AACA,YAAM,SAAS,OAAO,OAAe;AACnC,YAAI,QAAQ,cAAc,gBAAgB,SAAS;AACjD,0BAAgB,QAAQ,OAAO,sBAAsB,gBAAgB,QAAQ,MAAM,EAAE;AACrF,gBAAM,CAAC,MAAM,IAAI,CAAC;AAAA,QACpB;AACA,cAAM,OAAO,OAAO,YAAY,UAAU,EAAE,YAAY,GAAG,CAAC;AAAA,MAC9D;AACA,aAAO,EAAE,QAAQ,QAAQ,OAAO;AAAA,IAClC,GAAG,CAAC,YAAY,QAAQ,UAAU,CAAC;AAEnC,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA,GAAG;AAAA,IACL;AAAA,EACF;AAEA,SAAO,EAAE,WAAW;AACtB;","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "syncora",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Realtime MERN sync engine. Subscribe to MongoDB collections from React with optimistic updates, automatic websocket transport, and a pluggable backing store.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./dist/index.cjs",
|
|
8
|
+
"module": "./dist/index.js",
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"import": "./dist/index.js",
|
|
14
|
+
"require": "./dist/index.cjs"
|
|
15
|
+
},
|
|
16
|
+
"./react": {
|
|
17
|
+
"types": "./dist/react.d.ts",
|
|
18
|
+
"import": "./dist/react.js",
|
|
19
|
+
"require": "./dist/react.cjs"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"dist",
|
|
24
|
+
"README.md",
|
|
25
|
+
"LICENSE",
|
|
26
|
+
"CHANGELOG.md"
|
|
27
|
+
],
|
|
28
|
+
"scripts": {
|
|
29
|
+
"build": "tsup",
|
|
30
|
+
"test": "vitest run",
|
|
31
|
+
"typecheck": "tsc --noEmit",
|
|
32
|
+
"prepublishOnly": "npm run build"
|
|
33
|
+
},
|
|
34
|
+
"keywords": [
|
|
35
|
+
"mern",
|
|
36
|
+
"mern-packages",
|
|
37
|
+
"merndev",
|
|
38
|
+
"mongodb",
|
|
39
|
+
"nodejs",
|
|
40
|
+
"npm-pm",
|
|
41
|
+
"observability",
|
|
42
|
+
"optimistic",
|
|
43
|
+
"react",
|
|
44
|
+
"realtime",
|
|
45
|
+
"subscription",
|
|
46
|
+
"sync",
|
|
47
|
+
"syncora",
|
|
48
|
+
"typescript",
|
|
49
|
+
"websocket"
|
|
50
|
+
],
|
|
51
|
+
"dependencies": {
|
|
52
|
+
"ws": "^8.16.0"
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"@types/node": "^20.11.0",
|
|
56
|
+
"@types/react": "^18.2.0",
|
|
57
|
+
"@types/ws": "^8.5.10",
|
|
58
|
+
"react": "^18.2.0",
|
|
59
|
+
"tsup": "^8.0.0",
|
|
60
|
+
"typescript": "^5.4.0",
|
|
61
|
+
"vitest": "^1.4.0"
|
|
62
|
+
},
|
|
63
|
+
"peerDependencies": {
|
|
64
|
+
"react": ">=18"
|
|
65
|
+
},
|
|
66
|
+
"peerDependenciesMeta": {
|
|
67
|
+
"react": {
|
|
68
|
+
"optional": true
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
"engines": {
|
|
72
|
+
"node": ">=18"
|
|
73
|
+
},
|
|
74
|
+
"author": "Aftab Ahmad Khan (https://github.com/aftab-ahmad-khan-dev)",
|
|
75
|
+
"repository": {
|
|
76
|
+
"type": "git",
|
|
77
|
+
"url": "git+https://github.com/NPM-Packages-Modules/mern.git",
|
|
78
|
+
"directory": "syncora"
|
|
79
|
+
},
|
|
80
|
+
"bugs": {
|
|
81
|
+
"url": "https://github.com/NPM-Packages-Modules/mern/issues"
|
|
82
|
+
},
|
|
83
|
+
"homepage": "https://github.com/NPM-Packages-Modules/mern/tree/main/syncora",
|
|
84
|
+
"publishConfig": {
|
|
85
|
+
"access": "public"
|
|
86
|
+
}
|
|
87
|
+
}
|