prostgles-client
Version:
Reactive client for Postgres
177 lines (176 loc) • 6.94 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.getSyncHandler = void 0;
const prostgles_types_1 = require("prostgles-types");
const FunctionQueuer_1 = require("./FunctionQueuer");
const prostgles_1 = require("./prostgles");
const preffix = prostgles_types_1.CHANNELS._preffix;
const getSyncHandler = ({ socket }) => {
let syncedTables = {};
let syncs = {};
const destroySyncs = async () => {
(0, prostgles_1.debug)("destroySyncs", { syncedTables });
syncs = {};
Object.values(syncedTables).forEach((s) => {
s.destroy();
});
syncedTables = {};
};
function _unsync(channelName, triggers) {
(0, prostgles_1.debug)("_unsync", { channelName, triggers });
return new Promise((resolve, reject) => {
if (syncs[channelName]) {
syncs[channelName].triggers = syncs[channelName].triggers.filter((tr) => tr.onPullRequest !== triggers.onPullRequest &&
tr.onSyncRequest !== triggers.onSyncRequest &&
tr.onUpdates !== triggers.onUpdates);
if (!syncs[channelName].triggers.length) {
socket.emit(channelName + "unsync", {}, (err, res) => {
if (err)
reject(err);
else
resolve(res);
});
socket.removeListener(channelName, syncs[channelName].onCall);
delete syncs[channelName];
}
}
});
}
function addServerSync({ tableName, command, param1, param2 }, onSyncRequest) {
return new Promise((resolve, reject) => {
socket.emit(preffix, { tableName, command, param1, param2 }, (err, res) => {
if (err) {
console.error(err);
reject(err);
}
else if (res) {
const { id_fields, synced_field, channelName } = res;
socket.emit(channelName, { onSyncRequest: onSyncRequest({}) }, (response) => {
console.log(response);
});
resolve({ id_fields, synced_field, channelName });
}
});
});
}
const addSyncQueuer = new FunctionQueuer_1.FunctionQueuer(_addSync, ([{ tableName }]) => tableName);
async function addSync(params, triggers) {
return addSyncQueuer.run([params, triggers]);
}
async function _addSync({ tableName, command, param1, param2 }, triggers) {
const { onSyncRequest } = triggers;
function makeHandler(channelName) {
const unsync = function () {
_unsync(channelName, triggers);
};
const syncData = function (data, deleted, cb) {
socket.emit(channelName, {
onSyncRequest: {
...onSyncRequest({}),
...{ data },
...{ deleted },
},
}, !cb ? null : ((response) => {
cb(response);
}));
};
return Object.freeze({ unsync, syncData });
}
const existingChannel = Object.keys(syncs).find((ch) => {
const s = syncs[ch];
return (s &&
s.tableName === tableName &&
s.command === command &&
(0, prostgles_types_1.isEqual)(s.param1, param1) &&
(0, prostgles_types_1.isEqual)(s.param2, param2));
});
if (existingChannel) {
syncs[existingChannel].triggers.push(triggers);
return makeHandler(existingChannel);
}
else {
const sync_info = await addServerSync({ tableName, command, param1, param2 }, onSyncRequest);
const { channelName } = sync_info;
const onCall = function (data, cb) {
/*
Client will:
1. Send last_synced on(onSyncRequest)
2. Send data >= server_synced on(onPullRequest)
3. Send data on CRUD emit(data.data)
4. Upsert data.data on(data.data)
*/
if (!data)
return;
if (!syncs[channelName])
return;
syncs[channelName].triggers.map(({ onUpdates, onSyncRequest, onPullRequest }) => {
if (data.data) {
Promise.resolve(onUpdates(data))
.then(() => {
cb({ ok: true });
})
.catch((err) => {
cb({ err });
});
}
else if (data.onSyncRequest) {
Promise.resolve(onSyncRequest(data.onSyncRequest))
.then((res) => cb({ onSyncRequest: res }))
.catch((err) => {
cb({ err });
});
}
else if (data.onPullRequest) {
Promise.resolve(onPullRequest(data.onPullRequest))
.then((result) => {
cb(result);
})
.catch((err) => {
cb({ err });
});
}
else {
console.log("unexpected response");
}
});
};
syncs[channelName] = {
tableName,
command,
param1,
param2,
triggers: [triggers],
syncInfo: sync_info,
onCall,
};
socket.on(channelName, onCall);
return makeHandler(channelName);
}
}
const reAttachAll = async () => {
let reAttached = 0;
Object.entries(syncs).forEach(async ([ch, s]) => {
const firstTrigger = s.triggers[0];
if (firstTrigger) {
try {
await addServerSync(s, firstTrigger.onSyncRequest);
socket.on(ch, s.onCall);
reAttached++;
}
catch (err) {
console.error("There was an issue reconnecting olf subscriptions", err);
}
}
});
if (reAttached) {
console.log("reAttached", reAttached, " syncs", syncs);
}
};
return {
destroySyncs,
syncedTables,
addSync,
reAttachAll,
};
};
exports.getSyncHandler = getSyncHandler;