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.
- package/.eslintignore +1 -0
- package/.prettierignore +2 -0
- package/.prettierrc +4 -0
- package/.vscode/settings.json +10 -1
- package/dist/Auth.d.ts +2 -2
- package/dist/Auth.d.ts.map +1 -1
- package/dist/Auth.js +28 -18
- package/dist/SyncedTable/SyncedTable.d.ts +12 -12
- package/dist/SyncedTable/SyncedTable.d.ts.map +1 -1
- package/dist/SyncedTable/SyncedTable.js +92 -78
- package/dist/SyncedTable/getMultiSyncSubscription.d.ts.map +1 -1
- package/dist/SyncedTable/getMultiSyncSubscription.js +11 -9
- package/dist/index.js +1 -1
- package/dist/index.no-sync.js +1 -1
- package/dist/prostgles.d.ts +24 -0
- package/dist/prostgles.d.ts.map +1 -1
- package/package.json +3 -2
- package/tsconfig.json +1 -3
- package/dist/typeTests.d.ts +0 -2
- package/dist/typeTests.d.ts.map +0 -1
- package/dist/typeTests.js +0 -37
- package/lib/Auth.ts +0 -155
- package/lib/FunctionQueuer.ts +0 -71
- package/lib/SyncedTable/SyncedTable.ts +0 -1078
- package/lib/SyncedTable/getMultiSyncSubscription.ts +0 -67
- package/lib/SyncedTable/getSingleSyncSubscription.ts +0 -0
- package/lib/getDbHandler.ts +0 -152
- package/lib/getMethods.ts +0 -30
- package/lib/getSqlHandler.ts +0 -174
- package/lib/getSubscriptionHandler.ts +0 -211
- package/lib/getSyncHandler.ts +0 -201
- package/lib/md5.ts +0 -183
- package/lib/prostgles-full-cdn.ts +0 -5
- package/lib/prostgles-full.ts +0 -8
- package/lib/prostgles.ts +0 -351
- package/lib/react-hooks.ts +0 -356
- package/lib/typeTests.ts +0 -64
- package/lib/useProstglesClient.ts +0 -92
- package/tests/package-lock.json +0 -71
- package/tests/package.json +0 -17
- package/tests/test.ts +0 -10
- 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
|
package/lib/getDbHandler.ts
DELETED
|
@@ -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
|
-
}
|
package/lib/getSqlHandler.ts
DELETED
|
@@ -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
|
-
}
|