prostgles-client 4.0.174 → 4.0.176

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.
Files changed (42) hide show
  1. package/.eslintignore +1 -0
  2. package/.prettierignore +2 -0
  3. package/.prettierrc +4 -0
  4. package/.vscode/settings.json +10 -1
  5. package/dist/Auth.d.ts +2 -2
  6. package/dist/Auth.d.ts.map +1 -1
  7. package/dist/Auth.js +28 -18
  8. package/dist/SyncedTable/SyncedTable.d.ts +12 -12
  9. package/dist/SyncedTable/SyncedTable.d.ts.map +1 -1
  10. package/dist/SyncedTable/SyncedTable.js +92 -78
  11. package/dist/SyncedTable/getMultiSyncSubscription.d.ts.map +1 -1
  12. package/dist/SyncedTable/getMultiSyncSubscription.js +11 -9
  13. package/dist/index.js +1 -1
  14. package/dist/index.no-sync.js +1 -1
  15. package/dist/prostgles.d.ts +24 -0
  16. package/dist/prostgles.d.ts.map +1 -1
  17. package/package.json +3 -2
  18. package/tsconfig.json +1 -3
  19. package/dist/typeTests.d.ts +0 -2
  20. package/dist/typeTests.d.ts.map +0 -1
  21. package/dist/typeTests.js +0 -37
  22. package/lib/Auth.ts +0 -155
  23. package/lib/FunctionQueuer.ts +0 -71
  24. package/lib/SyncedTable/SyncedTable.ts +0 -1078
  25. package/lib/SyncedTable/getMultiSyncSubscription.ts +0 -67
  26. package/lib/SyncedTable/getSingleSyncSubscription.ts +0 -0
  27. package/lib/getDbHandler.ts +0 -152
  28. package/lib/getMethods.ts +0 -30
  29. package/lib/getSqlHandler.ts +0 -174
  30. package/lib/getSubscriptionHandler.ts +0 -211
  31. package/lib/getSyncHandler.ts +0 -201
  32. package/lib/md5.ts +0 -183
  33. package/lib/prostgles-full-cdn.ts +0 -5
  34. package/lib/prostgles-full.ts +0 -8
  35. package/lib/prostgles.ts +0 -351
  36. package/lib/react-hooks.ts +0 -356
  37. package/lib/typeTests.ts +0 -64
  38. package/lib/useProstglesClient.ts +0 -92
  39. package/tests/package-lock.json +0 -71
  40. package/tests/package.json +0 -17
  41. package/tests/test.ts +0 -10
  42. package/tests/tsconfig.json +0 -27
@@ -1,67 +0,0 @@
1
- import type { AnyObject } from "prostgles-types";
2
- import type { $UpdateOpts, MultiChangeListener, MultiSyncHandles, SubscriptionMulti, SyncedTable } from "./SyncedTable";
3
-
4
- type Args = {
5
- onChange: MultiChangeListener<AnyObject>;
6
- handlesOnData: boolean;
7
- }
8
- export function getMultiSyncSubscription(this: SyncedTable, { onChange, handlesOnData }: Args){
9
-
10
- const handles: MultiSyncHandles<AnyObject> = {
11
- $unsync: () => {
12
- return this.unsubscribe(onChange)
13
- },
14
- getItems: () => { return this.getItems(); },
15
- $upsert: (newData) => {
16
- if (!(newData as any)) {
17
- throw "No data provided for upsert";
18
- }
19
-
20
- const prepareOne = (d: AnyObject) => {
21
- return ({
22
- idObj: this.getIdObj(d),
23
- delta: d
24
- });
25
- }
26
-
27
- if (Array.isArray(newData)) {
28
- this.upsert(newData.map(d => prepareOne(d)));
29
- } else {
30
- this.upsert([prepareOne(newData)]);
31
- }
32
- }
33
- };
34
-
35
- const sub: SubscriptionMulti<AnyObject> = {
36
- _onChange: onChange,
37
- handlesOnData,
38
- handles,
39
- notify: (_allItems, _allDeltas) => {
40
- let allItems = [..._allItems];
41
- const allDeltas = [..._allDeltas];
42
- if (handlesOnData) {
43
- allItems = allItems.map((item, i) => {
44
-
45
- const getItem = (d: AnyObject, idObj: Partial<AnyObject>) => ({
46
- ...d,
47
- ...this.makeSingleSyncHandles(idObj, onChange),
48
- $get: () => getItem(this.getItem(idObj).data!, idObj),
49
- $find: (idObject: Partial<AnyObject>) => getItem(this.getItem(idObject).data!, idObject),
50
- $update: (newData: AnyObject, opts: $UpdateOpts): Promise<boolean> => {
51
- return this.upsert([{ idObj, delta: newData, opts }]).then(r => true);
52
- },
53
- $delete: async (): Promise<boolean> => {
54
- return this.delete(idObj);
55
- },
56
- $cloneMultiSync: (onChange: MultiChangeListener) => this.sync(onChange, handlesOnData)
57
- })
58
- const idObj = this.getIdObj(item) as Partial<AnyObject>;
59
- return getItem(item, idObj);
60
- });
61
- }
62
- return onChange(allItems, allDeltas)
63
- }
64
- };
65
-
66
- return { sub, handles }
67
- }
File without changes
@@ -1,152 +0,0 @@
1
- import { type AnyObject, CHANNELS, type ClientSchema, getKeys, isObject, omitKeys, type TableSchemaForClient } from "prostgles-types";
2
- import { type InitOptions, type TableHandlerClient, type AnyFunction, type DBHandlerClient, useSync, useSubscribe, useFetch } from "./prostgles";
3
- import type { Sync, SyncedTable, SyncOne, SyncOptions } from "./SyncedTable/SyncedTable";
4
- import type { getSyncHandler } from "./getSyncHandler";
5
- import type { getSubscriptionHandler } from "./getSubscriptionHandler";
6
-
7
-
8
- type Args = {
9
- schema: TableSchemaForClient;
10
- onDebug: InitOptions["onDebug"];
11
- socket: InitOptions["socket"];
12
- joinTables: ClientSchema["joinTables"];
13
- syncedTable: typeof SyncedTable | undefined;
14
- syncHandler: ReturnType<typeof getSyncHandler>;
15
- subscriptionHandler: ReturnType<typeof getSubscriptionHandler>;
16
- }
17
-
18
- const preffix = CHANNELS._preffix;
19
-
20
- export const getDBO = ({ schema, onDebug, syncedTable, syncHandler, subscriptionHandler, socket, joinTables }: Args) => {
21
-
22
- const dbo: Partial<DBHandlerClient> = JSON.parse(JSON.stringify(schema));
23
-
24
- /* Building DBO object */
25
- const checkSubscriptionArgs = (basicFilter: AnyObject | undefined, options: AnyObject | undefined, onChange: AnyFunction, onError?: AnyFunction) => {
26
- if (basicFilter !== undefined && !isObject(basicFilter) || options !== undefined && !isObject(options) || !(typeof onChange === "function") || onError !== undefined && typeof onError !== "function") {
27
- throw "Expecting: ( basicFilter<object>, options<object>, onChange<function> , onError?<function>) but got something else";
28
- }
29
- }
30
- const sub_commands = ["subscribe", "subscribeOne"] as const;
31
- getKeys(dbo).forEach(tableName => {
32
- const all_commands = Object.keys(dbo[tableName]!);
33
-
34
- const dboTable = dbo[tableName] as TableHandlerClient;
35
- all_commands
36
- .sort((a, b) => <never>sub_commands.includes(a as any) - <never>sub_commands.includes(b as any))
37
- .forEach(command => {
38
-
39
- if (command === "sync") {
40
- dboTable._syncInfo = { ...dboTable[command] };
41
- if (syncedTable) {
42
- dboTable.getSync = async (filter, params = {}) => {
43
- await onDebug?.({ type: "table", command: "getSync", tableName, data: { filter, params } });
44
- return syncedTable.create({
45
- name: tableName,
46
- onDebug: onDebug as any,
47
- filter,
48
- db: dbo,
49
- ...params
50
- });
51
- }
52
- const upsertSyncTable = async (basicFilter = {}, options: SyncOptions = {}, onError) => {
53
- const syncName = `${tableName}.${JSON.stringify(basicFilter)}.${JSON.stringify(omitKeys(options, ["handlesOnData"]))}`
54
- if (!syncHandler.syncedTables[syncName]) {
55
- syncHandler.syncedTables[syncName] = await syncedTable.create({
56
- ...options,
57
- onDebug: onDebug as any,
58
- name: tableName,
59
- filter: basicFilter,
60
- db: dbo,
61
- onError
62
- });
63
- }
64
- return syncHandler.syncedTables[syncName]
65
- }
66
- const sync: Sync<AnyObject> = async (basicFilter, options = { handlesOnData: true, select: "*" }, onChange, onError) => {
67
- await onDebug?.({ type: "table", command: "sync", tableName, data: { basicFilter, options } });
68
- checkSubscriptionArgs(basicFilter, options, onChange, onError);
69
- const s = await upsertSyncTable(basicFilter, options, onError);
70
- return await s.sync(onChange, options.handlesOnData);
71
- }
72
- const syncOne: SyncOne<AnyObject> = async (basicFilter, options = { handlesOnData: true }, onChange, onError) => {
73
- await onDebug?.({ type: "table", command: "syncOne", tableName, data: { basicFilter, options } });
74
- checkSubscriptionArgs(basicFilter, options, onChange, onError);
75
- const s = await upsertSyncTable(basicFilter, options, onError);
76
- return await s.syncOne(basicFilter, onChange, options.handlesOnData);
77
- }
78
- dboTable.sync = sync;
79
- dboTable.syncOne = syncOne;
80
- // eslint-disable-next-line react-hooks/rules-of-hooks
81
- dboTable.useSync = (basicFilter, options) => useSync(sync, basicFilter, options) as any;
82
- // eslint-disable-next-line react-hooks/rules-of-hooks
83
- dboTable.useSyncOne = (basicFilter, options) => useSync(syncOne, basicFilter, options) as any;
84
- }
85
-
86
- dboTable._sync = async function (param1, param2, syncHandles) {
87
- await onDebug?.({ type: "table", command: "_sync", tableName, data: { param1, param2, syncHandles } });
88
- return syncHandler.addSync({ tableName, command, param1, param2 }, syncHandles);
89
- }
90
- } else if (sub_commands.includes(command as any)) {
91
- const subFunc = async function (param1 = {}, param2 = {}, onChange, onError) {
92
- await onDebug?.({ type: "table", command: command as typeof sub_commands[number], tableName, data: { param1, param2, onChange, onError } });
93
- checkSubscriptionArgs(param1, param2, onChange, onError);
94
- return subscriptionHandler.addSub(dbo, { tableName, command, param1, param2 }, onChange, onError);
95
- };
96
- dboTable[command] = subFunc;
97
- const SUBONE = "subscribeOne";
98
-
99
- /**
100
- * React hooks
101
- */
102
- const handlerName = command === "subscribe" ? "useSubscribe" : command === "subscribeOne"? "useSubscribeOne" : undefined;
103
- if(handlerName){
104
- // eslint-disable-next-line react-hooks/rules-of-hooks
105
- dboTable[handlerName] = (filter, options) => useSubscribe(subFunc, command === SUBONE, filter, options)
106
- }
107
-
108
- if (command === SUBONE || !sub_commands.includes(SUBONE)) {
109
- dboTable[SUBONE] = async function (param1, param2, onChange, onError) {
110
- await onDebug?.({ type: "table", command: "getSync", tableName, data: { param1, param2, onChange, onError } });
111
- checkSubscriptionArgs(param1, param2, onChange, onError);
112
-
113
- const onChangeOne = (rows) => { onChange(rows[0]) };
114
- return subscriptionHandler.addSub(dbo, { tableName, command, param1, param2 }, onChangeOne, onError);
115
- };
116
- }
117
- } else {
118
- const method = async function (param1, param2, param3) {
119
- await onDebug?.({ type: "table", command: command as any, tableName, data: { param1, param2, param3 } });
120
- return new Promise((resolve, reject) => {
121
- socket.emit(preffix,
122
- { tableName, command, param1, param2, param3 },
123
-
124
- /* Get col definition and re-cast data types?! */
125
- (err, res) => {
126
- if (err) reject(err);
127
- else resolve(res);
128
- }
129
- );
130
- })
131
- }
132
- dboTable[command] = method;
133
-
134
- const methodName = command === "findOne" ? "useFindOne" : command === "find" ? "useFind" : command === "count" ? "useCount" : command === "size" ? "useSize" : undefined;
135
- if(methodName){
136
- // eslint-disable-next-line react-hooks/rules-of-hooks
137
- dboTable[methodName] = (param1, param2, param3?) => useFetch(method, [param1, param2, param3]);
138
- }
139
- if (["find", "findOne"].includes(command)) {
140
- dboTable.getJoinedTables = function () {
141
- return joinTables
142
- .filter(tb => Array.isArray(tb) && tb.includes(tableName))
143
- .flat()
144
- .filter(t => t !== tableName);
145
- }
146
- }
147
- }
148
- })
149
- });
150
-
151
- return { dbo };
152
- }
package/lib/getMethods.ts DELETED
@@ -1,30 +0,0 @@
1
- import type { ClientSchema, MethodHandler } from "prostgles-types";
2
- import { CHANNELS } from "prostgles-types";
3
- import type { InitOptions } from "./prostgles";
4
-
5
- export const getMethods = ({ onDebug, methods, socket }: Pick<InitOptions, "onDebug" | "socket"> & Pick<ClientSchema, "methods">) => {
6
-
7
- let methodsObj: MethodHandler = {};
8
- const _methods: typeof methods = JSON.parse(JSON.stringify(methods));
9
- _methods.map(method => {
10
- /** New method def */
11
- const isBasic = typeof method === "string";
12
- const methodName = isBasic ? method : method.name;
13
- const onRun = async function (...params) {
14
- await onDebug?.({ type: "method", command: methodName, data: { params } });
15
- return new Promise((resolve, reject) => {
16
- socket.emit(CHANNELS.METHOD, { method: methodName, params }, (err, res) => {
17
- if (err) reject(err);
18
- else resolve(res);
19
- });
20
- })
21
- }
22
- methodsObj[methodName] = isBasic ? onRun : {
23
- ...method,
24
- run: onRun
25
- };
26
- });
27
- methodsObj = Object.freeze(methodsObj);
28
-
29
- return { methodsObj };
30
- }
@@ -1,174 +0,0 @@
1
- import { CHANNELS, type SQLHandler, type DBEventHandles, type DBNoticeConfig, type DBNotifConfig, type SocketSQLStreamClient, type SocketSQLStreamServer } from "prostgles-types";
2
- import type { InitOptions } from "./prostgles";
3
-
4
- export const getSqlHandler = ({ socket }: Pick<InitOptions, "socket">) => {
5
-
6
- let noticeSubs: {
7
- listeners: ((notice: any) => void)[];
8
- config: DBNoticeConfig;
9
- } | undefined;
10
- const notifSubs: {
11
- [key: string]: {
12
- config: DBNotifConfig
13
- listeners: ((notif: any) => void)[]
14
- }
15
- } = {};
16
- const removeNotifListener = (listener: any, conf: DBNotifConfig, socket: any) => {
17
- const channelSubs = notifSubs[conf.notifChannel]
18
- if (channelSubs) {
19
- channelSubs.listeners = channelSubs.listeners.filter(nl => nl !== listener);
20
- if (!channelSubs.listeners.length && channelSubs.config.socketUnsubChannel && socket) {
21
- socket.emit(channelSubs.config.socketUnsubChannel, {});
22
- delete notifSubs[conf.notifChannel];
23
- }
24
- }
25
- };
26
- const addNotifListener = (listener: any, conf: DBNotifConfig, socket: any) => {
27
- const channelSubs = notifSubs[conf.notifChannel]
28
- if (!channelSubs) {
29
- notifSubs[conf.notifChannel] = {
30
- config: conf,
31
- listeners: [listener]
32
- };
33
- socket.removeAllListeners(conf.socketChannel);
34
- socket.on(conf.socketChannel, (notif: any) => {
35
- if (notifSubs[conf.notifChannel]?.listeners.length) {
36
- notifSubs[conf.notifChannel]!.listeners.map(l => {
37
- l(notif);
38
- })
39
- } else {
40
- socket.emit(notifSubs[conf.notifChannel]?.config.socketUnsubChannel, {});
41
- }
42
- });
43
-
44
- } else {
45
- notifSubs[conf.notifChannel]?.listeners.push(listener);
46
- }
47
- };
48
-
49
-
50
- const removeNoticeListener = (listener: any, socket: any) => {
51
- if (noticeSubs) {
52
- noticeSubs.listeners = noticeSubs.listeners.filter(nl => nl !== listener);
53
- if (!noticeSubs.listeners.length && noticeSubs.config.socketUnsubChannel && socket) {
54
- socket.emit(noticeSubs.config.socketUnsubChannel, {});
55
- }
56
- }
57
- }
58
- const addNoticeListener = (listener: any, conf: DBNoticeConfig, socket: any) => {
59
- noticeSubs ??= {
60
- config: conf,
61
- listeners: []
62
- };
63
-
64
- if (!noticeSubs.listeners.length) {
65
- socket.removeAllListeners(conf.socketChannel);
66
- socket.on(conf.socketChannel, (notice: any) => {
67
- if (noticeSubs && noticeSubs.listeners.length) {
68
- noticeSubs.listeners.map(l => {
69
- l(notice);
70
- })
71
- } else {
72
- socket.emit(conf.socketUnsubChannel, {});
73
- }
74
- });
75
- }
76
- noticeSubs.listeners.push(listener);
77
- }
78
-
79
- const sql: SQLHandler = function (query, params, options) {
80
- return new Promise((resolve, reject) => {
81
- socket.emit(CHANNELS.SQL, { query, params, options }, (err, res) => {
82
- if (err) {
83
- return reject(err);
84
- }
85
- if(options?.returnType === "stream"){
86
- const { channel, unsubChannel } = res as SocketSQLStreamServer;
87
- const start: SocketSQLStreamClient["start"] = (listener) => new Promise<Awaited<ReturnType<SocketSQLStreamClient["start"]>>>((resolveStart, rejectStart) => {
88
- socket.on(channel, listener)
89
- socket.emit(channel, {}, (pid: number, err) => {
90
- if(err){
91
- rejectStart(err);
92
- socket.removeAllListeners(channel);
93
- } else {
94
- resolveStart({
95
- pid,
96
- run: (query, params) => {
97
- return new Promise((resolveRun, rejectRun) => {
98
- socket.emit(channel, { query, params }, (data, _err) => {
99
- if(_err){
100
- rejectRun(_err);
101
- } else {
102
- resolveRun(data);
103
- }
104
- });
105
- });
106
- },
107
- stop: (terminate?: boolean) => {
108
- return new Promise((resolveStop, rejectStop) => {
109
- socket.emit(unsubChannel, { terminate }, (data, _err) => {
110
- if(_err){
111
- rejectStop(_err);
112
- } else {
113
- resolveStop(data);
114
- }
115
- });
116
- });
117
- }
118
- });
119
- }
120
- });
121
- });
122
- const streamHandlers = {
123
- channel,
124
- unsubChannel,
125
- start,
126
- } satisfies SocketSQLStreamClient;
127
-
128
- return resolve(streamHandlers as any);
129
- } else if (options &&
130
- (options.returnType === "noticeSubscription") &&
131
- res &&
132
- Object.keys(res).sort().join() === ["socketChannel", "socketUnsubChannel"].sort().join() &&
133
- !Object.values(res).find(v => typeof v !== "string")
134
- ) {
135
- const sockInfo: DBNoticeConfig = res;
136
- const addListener = (listener: (arg: any) => void) => {
137
- addNoticeListener(listener, sockInfo, socket);
138
- return {
139
- ...sockInfo,
140
- removeListener: () => removeNoticeListener(listener, socket)
141
- }
142
- };
143
- const handle: DBEventHandles = {
144
- ...sockInfo,
145
- addListener
146
- };
147
- // @ts-ignore
148
- resolve(handle);
149
- } else if (
150
- (!options || !options.returnType || options.returnType !== "statement") &&
151
- res &&
152
- Object.keys(res).sort().join() === ["socketChannel", "socketUnsubChannel", "notifChannel"].sort().join() &&
153
- !Object.values(res).find(v => typeof v !== "string")
154
- ) {
155
- const sockInfo: DBNotifConfig = res;
156
- const addListener = (listener: (arg: any) => void) => {
157
- addNotifListener(listener, sockInfo, socket)
158
- return {
159
- ...res,
160
- removeListener: () => removeNotifListener(listener, sockInfo, socket)
161
- }
162
- }
163
- const handle: DBEventHandles = { ...res, addListener };
164
- resolve(handle as any);
165
-
166
- } else {
167
- resolve(res);
168
- }
169
- });
170
- });
171
- }
172
-
173
- return { sql };
174
- }
@@ -1,211 +0,0 @@
1
- import { CHANNELS, type AnyObject, type DeleteParams, type SubscriptionChannels, type SubscriptionHandler, type UpdateParams } from "prostgles-types";
2
- import { debug, isEqual, type AnyFunction, type CoreParams, type InitOptions } from "./prostgles";
3
- import { FunctionQueuer } from "./FunctionQueuer";
4
-
5
- type Subscription = CoreParams & {
6
- lastData: any;
7
- onCall: AnyFunction,
8
- handlers: AnyFunction[];
9
- errorHandlers: (AnyFunction | undefined)[];
10
- unsubChannel: string;
11
- reAttach: () => Promise<void>;
12
- };
13
-
14
- type Subscriptions = {
15
- [key: string]: Subscription
16
- };
17
-
18
- const preffix = CHANNELS._preffix;
19
-
20
- export const getSubscriptionHandler = (initOpts: Pick<InitOptions, "socket" | "onDebug">) => {
21
- const { socket, onDebug, } = initOpts;
22
-
23
- const subscriptions: Subscriptions = {};
24
-
25
- const removeServerSub = (unsubChannel: string) => {
26
- return new Promise((resolve, reject) => {
27
- socket.emit(unsubChannel, {}, (err: any, _res: any) => {
28
- if (err) {
29
- console.error(err);
30
- reject(err);
31
- } else {
32
- resolve(_res);
33
- }
34
- });
35
- });
36
- }
37
-
38
- function _unsubscribe(channelName: string, unsubChannel: string, handler: AnyFunction): Promise<true> {
39
- debug("_unsubscribe", { channelName, handler });
40
-
41
- return new Promise((resolve, reject) => {
42
- const sub = subscriptions[channelName];
43
- if (sub) {
44
- sub.handlers = sub.handlers.filter(h => h !== handler);
45
- if (!sub.handlers.length) {
46
- onDebug?.({ type: "table", command: "unsubscribe", tableName: sub.tableName });
47
- removeServerSub(unsubChannel);
48
- socket.removeListener(channelName, sub.onCall);
49
- delete subscriptions[channelName];
50
-
51
- /* Not waiting for server confirmation to speed things up */
52
- resolve(true)
53
- } else {
54
- onDebug?.({ type: "table", command: "unsubscribe", tableName: sub.tableName, unsubChannel });
55
- resolve(true)
56
- }
57
- } else {
58
- resolve(true)
59
- }
60
- });
61
- }
62
-
63
-
64
- /**
65
- * Obtaines subscribe channel from server
66
- */
67
- function addServerSub({ tableName, command, param1, param2 }: CoreParams): Promise<SubscriptionChannels> {
68
- return new Promise((resolve, reject) => {
69
- socket.emit(preffix, { tableName, command, param1, param2 }, (err?: any, res?: SubscriptionChannels) => {
70
- if (err) {
71
- console.error(err);
72
- reject(err);
73
- } else if (res) {
74
- resolve(res);
75
- }
76
- });
77
- });
78
- }
79
-
80
-
81
- /**
82
- * Can be used concurrently
83
- */
84
- const addSubQueuer = new FunctionQueuer(_addSub, ([_, { tableName }]) => tableName);
85
- const addSub = async (dbo: any, params: CoreParams, onChange: AnyFunction, _onError?: AnyFunction): Promise<SubscriptionHandler> => {
86
- return addSubQueuer.run([dbo, params, onChange, _onError]);
87
- }
88
-
89
- /**
90
- * Do NOT use concurrently
91
- */
92
- async function _addSub(dbo: any, { tableName, command, param1, param2 }: CoreParams, onChange: AnyFunction, _onError?: AnyFunction): Promise<SubscriptionHandler> {
93
-
94
- const makeHandler = (channelName: string, unsubChannel: string) => {
95
-
96
- const unsubscribe = function () {
97
- return _unsubscribe(channelName, unsubChannel, onChange);
98
- }
99
-
100
- let subHandlers: any = { unsubscribe, filter: { ...param1 } }
101
-
102
- /* Some dbo sorting was done to make sure this will work */
103
- if (dbo[tableName].update) {
104
- subHandlers = {
105
- ...subHandlers,
106
- update: function (newData: AnyObject, updateParams: UpdateParams) {
107
- return dbo[tableName].update(param1, newData, updateParams);
108
- }
109
- }
110
- }
111
- if (dbo[tableName].delete) {
112
- subHandlers = {
113
- ...subHandlers,
114
- delete: function (deleteParams: DeleteParams) {
115
- return dbo[tableName].delete(param1, deleteParams);
116
- }
117
- }
118
- }
119
- return Object.freeze(subHandlers);
120
- }
121
-
122
- const existing = Object.entries(subscriptions).find(([ch, s]) => {
123
- return (
124
- s.tableName === tableName &&
125
- s.command === command &&
126
- isEqual(s.param1 || {}, param1 || {}) &&
127
- isEqual(s.param2 || {}, param2 || {})
128
- );
129
- });
130
-
131
- if (existing) {
132
- const existingCh = existing[0];
133
- existing[1].handlers.push(onChange);
134
- existing[1].errorHandlers.push(_onError);
135
- setTimeout(() => {
136
- if (subscriptions[existingCh]?.lastData) {
137
- onChange(subscriptions[existingCh]?.lastData)
138
- }
139
- }, 10)
140
- return makeHandler(existingCh, existing[1].unsubChannel);
141
- }
142
-
143
- const { channelName, channelNameReady, channelNameUnsubscribe } = await addServerSub({ tableName, command, param1, param2 })
144
-
145
- const onCall = function (data: any) {
146
- /* TO DO: confirm receiving data or server will unsubscribe */
147
- // if(cb) cb(true);
148
- const sub = subscriptions[channelName];
149
- if (sub) {
150
- if (data.data) {
151
- sub.lastData = data.data;
152
- sub.handlers.forEach(h => {
153
- h(data.data);
154
- });
155
- } else if (data.err) {
156
- sub.errorHandlers.forEach(h => {
157
- h?.(data.err);
158
- });
159
- } else {
160
- console.error("INTERNAL ERROR: Unexpected data format from subscription: ", data)
161
- }
162
- } else {
163
- console.warn("Orphaned subscription: ", channelName)
164
- }
165
- }
166
- const onError = _onError || function (err: any) { console.error(`Uncaught error within running subscription \n ${channelName}`, err) }
167
-
168
- socket.on(channelName, onCall);
169
- subscriptions[channelName] = {
170
- lastData: undefined,
171
- tableName,
172
- command,
173
- param1,
174
- param2,
175
- onCall,
176
- unsubChannel: channelNameUnsubscribe,
177
- handlers: [onChange],
178
- errorHandlers: [onError],
179
- reAttach: async () => {
180
- await removeServerSub(channelNameUnsubscribe).catch(console.error);
181
- await addServerSub({ tableName, command, param1, param2 });
182
- socket.emit(channelNameReady, { now: Date.now() });
183
- }
184
- }
185
- socket.emit(channelNameReady, { now: Date.now() });
186
- return makeHandler(channelName, channelNameUnsubscribe);
187
- }
188
-
189
- /**
190
- * Reconnect all subscriptions
191
- * Used when connection is lost and re-established or schema changes
192
- */
193
- const reAttachAll = async () => {
194
- for await (const s of Object.values(subscriptions)) {
195
- try {
196
- await s.reAttach();
197
- } catch (err) {
198
- console.error("There was an issue reconnecting old subscriptions", err, s)
199
- Object.values(s.errorHandlers).forEach(h => h?.(err));
200
- }
201
- }
202
- }
203
-
204
- return {
205
- addSub,
206
- subscriptions,
207
- addServerSub,
208
- _unsubscribe,
209
- reAttachAll,
210
- }
211
- }