insite-subscriptions-server 1.0.216 → 1.0.227
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/bun.lockb +0 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +7 -0
- package/package.json +30 -32
- package/lib/CollectionMapPublication.js +0 -163
- package/lib/CollectionMapSubscriptionHandle.js +0 -60
- package/lib/Publication.js +0 -42
- package/lib/SubscriptionHandle.js +0 -44
- package/lib/index.js +0 -3
- package/lib/ws/SubscriptionHandler.js +0 -70
- package/lib/ws/Subscriptions.js +0 -15
- package/lib/ws/index.js +0 -1
package/bun.lockb
ADDED
|
Binary file
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import g from"sift";var l=new Map,f=class{constructor(e,s){this.name=e,Object.assign(this,s),l.set(e,this)}type="object";subscriptions=new Set;fetch(){}fetchSubscription(e){return this.fetch(...e.args)}subscribe(e){this.subscriptions.add(e),this.onSubscribe?.(e)}changed(e){for(let s of this.subscriptions)s.changed(e)}unsubscribe(e){this.onUnsubscribe?.(e),this.subscriptions.delete(e)}};function h(r,e,s=!0,i=!0){if(e)if(s){let n={};for(let t in e){let o=e[t];n[t]=typeof o=="object"?Array.isArray(r[t])?r[t].map(a=>h(a,o,!0,!1)):h(r[t],o,!0,!1):r[t]}return i&&e._id===0&&delete n._id,n}else{let n={...r};for(let t in e){let o=e[t];typeof o=="object"?n[t]=Array.isArray(r[t])?r[t].map(a=>h(a,o,!1,!1)):h(r[t],o,!1,!1):delete n[t]}return n}return r}var b=class extends f{constructor(e,s,i,n){super(e,{collection:s,queryProps:i,transform:n})}type="map";skipSymbol=Symbol("skip");skip(e){e[this.skipSymbol]=!0}makeQueryProps(e){let{query:s=null,projection:i=null,sort:n=null,triggers:t}=(typeof this.queryProps=="function"?this.queryProps(...e):this.queryProps)||{},o=null,a=null;if(i){for(let u in i)if(o=!!i[u],u!=="_id")break;o&&(a=new Set([...Object.keys(s),...Object.keys(i),...t??[]]),a.delete("_id"),i._id!==0&&(i._id=1))}return{query:s,projection:i,isProjectionInclusive:o,fields:a,sort:n,args:e}}async fetchSubscription(e,s){if(e.query){if(s){let{_id:t}=s.documentKey;if(s.operationType==="insert"||s.operationType!="delete"&&e.match(s.fullDocument)){let o=h(s.fullDocument,e.projection,e.isProjectionInclusive);return this.transform?.(o,e.args),e.ids.has(t)?["u",o,s.updateDescription&&Object.keys(s.updateDescription.updatedFields)]:(e.ids.add(t),["c",o])}return e.ids.delete(t),["d",t]}let i=this.collection.find(e.query);e.projection&&i.project(e.projection),e.sort&&i.sort(e.sort);let n=await i.toArray();if(e.ids)if(e.ids.clear(),this.transform)for(let t of n)e.ids.add(t._id),this.transform(t,e.args);else for(let t of n)e.ids.add(t._id);else if(this.transform)for(let t of n)this.transform(t,e.args);return["i",n,e.sort]}return null}async fetch(...e){return[await this.fetchSubscription(this.makeQueryProps(e),null)]}changed(e){return Promise.all(this.subscriptions.map(s=>s.changed(e)))}onSubscribe(e){Object.assign(e,this.makeQueryProps(e.args)),e.query&&(e.match=g(e.query),this.collection.changeListeners.add(e.collectionChangeListener))}flushInitial(){return Promise.all(this.subscriptions.map(async e=>{e.handler([await this.fetchSubscription(e)]),e.updates=[]}))}onUnsubscribe(e){e.query&&this.collection.changeListeners.delete(e.collectionChangeListener)}};var c=class{constructor(e,s,i,n,t){this.publication=l.get(e),this.publication&&(this.args=s,this.handler=i,t||(this.publication.subscribe(this),n&&this.changed(null)))}async changed(e){this.handler(await this.publication.fetchSubscription(this,e),e)}cancel(){this.publication?.unsubscribe(this)}renew(){return this.publication?.unsubscribe(this),this.publication?.subscribe(this),this.changed(null)}};var d=class extends c{constructor(e,s,i,n){super(e,s,i,n,!0),this.publication&&(this.publication.subscribe(this),this.skipSymbol=this.publication.skipSymbol,n&&this.changed(null))}ids=new Set;async changed(e){this.handler([await this.publication.fetchSubscription(this,e)])}updates=[];flushTimeout=null;handleUpdatedFieldsSome=e=>this.fields.has(e);flushUpdates=()=>{this.updates.length&&(this.handler(this.updates),this.updates=[])};collectionChangeListener=async e=>{!e[this.skipSymbol]&&(this.ids.has(e.documentKey._id)?e.operationType!=="update"||!this.fields||Object.keys(e.updateDescription.updatedFields).some(this.handleUpdatedFieldsSome):this.match(e.fullDocument))&&(clearTimeout(this.flushTimeout),this.updates.push(await this.publication.fetchSubscription(this,e)),this.flushTimeout=setTimeout(this.flushUpdates,1))}};var p=class extends Map{subscribe=this.set;renew(){return Promise.all(this.mapValues(e=>e.renew()))}cancel(e){this.get(e)?.cancel(),this.delete(e)}};var S={object:c,map:d},m=class r{constructor(e,s={}){let{users:i}=s;i&&i.on("user-permissions-change",r.handleUserPermissionsChange),e.on("client-connect",r.handleClientConnect),e.on("client-session",r.handleClientSession),e.on("client-message:s-s",r.handleClientSubscribe),e.on("client-message:s-u",r.handleClientUnsubscribe),e.on("client-close",r.handleClientClose)}static handleUserPermissionsChange(e){if(e.webSockets)for(let s of e.webSockets)s.subscriptions.renew()}static handleClientConnect(e){e.subscriptions=new p}static handleClientSession(e){e.subscriptions.renew()}static handleClientSubscribe(e,s,i,n,t,o){let a=S[s];if(a&&l.get(i)?.type===s){let u=y=>e.sendMessage("s-c",n,y);e.subscriptions.subscribe(n,new a(i,[e,...t],u,o))}}static handleClientUnsubscribe(e,s){e.subscriptions.cancel(s)}static handleClientClose(e){for(let s of e.subscriptions.values())s.cancel()}};export{b as CollectionMapPublication,f as Publication,c as SubscriptionHandle,m as SubscriptionHandler,l as publications};
|
|
2
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/CollectionMapPublication.js", "../src/Publication.js", "../src/SubscriptionHandle.js", "../src/CollectionMapSubscriptionHandle.js", "../src/ws/Subscriptions.js", "../src/ws/SubscriptionHandler.js"],
|
|
4
|
+
"sourcesContent": ["import sift from \"sift\";\nimport { Publication } from \"./Publication\";\n\n\nfunction projectDocument(document, projection, isInclusive = true, isTop = true) {\n\tif (projection)\n\t\tif (isInclusive) {\n\t\t\tconst projected = {};\n\t\t\tfor (const key in projection) {\n\t\t\t\tconst subprojection = projection[key];\n\t\t\t\tprojected[key] =\n\t\t\t\t\ttypeof subprojection == \"object\" ?\n\t\t\t\t\t\tArray.isArray(document[key]) ?\n\t\t\t\t\t\t\tdocument[key].map(item => projectDocument(item, subprojection, true, false)) :\n\t\t\t\t\t\t\tprojectDocument(document[key], subprojection, true, false) :\n\t\t\t\t\t\tdocument[key];\n\t\t\t}\n\t\t\tif (isTop && projection._id === 0)\n\t\t\t\tdelete projected._id;\n\t\t\t\n\t\t\treturn projected;\n\t\t} else {\n\t\t\tconst projected = { ...document };\n\t\t\tfor (const key in projection) {\n\t\t\t\tconst subprojection = projection[key];\n\t\t\t\tif (typeof subprojection == \"object\")\n\t\t\t\t\tprojected[key] =\n\t\t\t\t\t\tArray.isArray(document[key]) ?\n\t\t\t\t\t\t\tdocument[key].map(item => projectDocument(item, subprojection, false, false)) :\n\t\t\t\t\t\t\tprojectDocument(document[key], subprojection, false, false);\n\t\t\t\t else\n\t\t\t\t\tdelete projected[key];\n\t\t\t}\n\t\t\t\n\t\t\treturn projected;\n\t\t}\n\t\n\treturn document;\n}\n\n\nexport class CollectionMapPublication extends Publication {\n\tconstructor(name, collection, queryProps, transform) {\n\t\tsuper(name, { collection, queryProps, transform });\n\t\t\n\t}\n\t\n\ttype = \"map\";\n\t\n\tskipSymbol = Symbol(\"skip\");\n\t\n\tskip(next) {\n\t\tnext[this.skipSymbol] = true;\n\t\t\n\t}\n\t\n\tmakeQueryProps(args) {\n\t\tconst { query = null, projection = null, sort = null, triggers } = (typeof this.queryProps == \"function\" ? this.queryProps(...args) : this.queryProps) || {};\n\t\t\n\t\tlet isProjectionInclusive = null;\n\t\tlet fields = null;\n\t\tif (projection) {\n\t\t\tfor (const key in projection) {\n\t\t\t\tisProjectionInclusive = !!projection[key];\n\t\t\t\tif (key !== \"_id\")\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (isProjectionInclusive) {\n\t\t\t\tfields = new Set([ ...Object.keys(query), ...Object.keys(projection), ...triggers ?? [] ]);\n\t\t\t\tfields.delete(\"_id\");\n\t\t\t\tif (projection._id !== 0)\n\t\t\t\t\tprojection._id = 1;\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn { query, projection, isProjectionInclusive, fields, sort, args };\n\t}\n\t\n\tasync fetchSubscription(subscription, next) {\n\t\tif (subscription.query) {\n\t\t\tif (next) {\n\t\t\t\tconst { _id } = next.documentKey;\n\t\t\t\t\n\t\t\t\tif (next.operationType === \"insert\" || (next.operationType != \"delete\" && subscription.match(next.fullDocument))) {\n\t\t\t\t\tconst doc = projectDocument(next.fullDocument, subscription.projection, subscription.isProjectionInclusive);\n\t\t\t\t\tthis.transform?.(doc, subscription.args);\n\t\t\t\t\tif (subscription.ids.has(_id))\n\t\t\t\t\t\treturn [ \"u\"/* update */, doc, next.updateDescription && Object.keys(next.updateDescription.updatedFields) ];\n\t\t\t\t\t\n\t\t\t\t\tsubscription.ids.add(_id);\n\t\t\t\t\t\n\t\t\t\t\treturn [ \"c\"/* create */, doc ];\n\t\t\t\t\t\n\t\t\t\t}\n\t\t\t\tsubscription.ids.delete(_id);\n\t\t\t\t\n\t\t\t\treturn [ \"d\"/* delete */, _id ];\n\t\t\t\t\n\t\t\t}\n\t\t\tconst cursor = this.collection.find(subscription.query);\n\t\t\t\n\t\t\tif (subscription.projection)\n\t\t\t\tcursor.project(subscription.projection);\n\t\t\t\n\t\t\tif (subscription.sort)\n\t\t\t\tcursor.sort(subscription.sort);\n\t\t\t\n\t\t\tconst array = await cursor.toArray();\n\t\t\t\n\t\t\tif (subscription.ids) {\n\t\t\t\tsubscription.ids.clear();\n\t\t\t\tif (this.transform)\n\t\t\t\t\tfor (const item of array) {\n\t\t\t\t\t\tsubscription.ids.add(item._id);\n\t\t\t\t\t\tthis.transform(item, subscription.args);\n\t\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\tfor (const item of array)\n\t\t\t\t\t\tsubscription.ids.add(item._id);\n\t\t\t} else if (this.transform)\n\t\t\t\tfor (const item of array)\n\t\t\t\t\tthis.transform(item, subscription.args);\n\t\t\t\n\t\t\treturn [ \"i\"/* initial */, array, subscription.sort ];\n\t\t\t\n\t\t}\n\t\t\n\t\treturn null;\n\t}\n\t\n\tasync fetch(...args) {\n\t\treturn [ await this.fetchSubscription(this.makeQueryProps(args), null) ];\n\t}\n\t\n\tchanged(changed) {\n\t\treturn Promise.all(this.subscriptions.map(subscription => subscription.changed(changed)));\n\t}\n\t\n\tonSubscribe(subscription) {\n\t\tObject.assign(subscription, this.makeQueryProps(subscription.args));\n\t\t\n\t\tif (subscription.query) {\n\t\t\tsubscription.match = sift(subscription.query);\n\t\t\tthis.collection.changeListeners.add(subscription.collectionChangeListener);\n\t\t}\n\t\t\n\t}\n\t\n\tflushInitial() {\n\t\treturn Promise.all(this.subscriptions.map(async subscription => {\n\t\t\tsubscription.handler([ await this.fetchSubscription(subscription) ]);\n\t\t\tsubscription.updates = [];\n\t\t\t\n\t\t}));\n\t}\n\t\n\tonUnsubscribe(subscription) {\n\t\tif (subscription.query)\n\t\t\tthis.collection.changeListeners.delete(subscription.collectionChangeListener);\n\t\t\n\t}\n\t\n}\n", "export const publications = new Map();\n\n\nexport class Publication {\n\tconstructor(name, props) {\n\t\tthis.name = name;\n\t\tObject.assign(this, props);\n\t\t\n\t\tpublications.set(name, this);\n\t\t\n\t}\n\t\n\ttype = \"object\";\n\t\n\tsubscriptions = new Set();\n\t\n\t// eslint-disable-next-line @typescript-eslint/no-empty-function\n\tfetch() {}\n\t\n\tfetchSubscription(subscription) {\n\t\treturn this.fetch(...subscription.args);\n\t}\n\t\n\tsubscribe(subscription) {\n\t\tthis.subscriptions.add(subscription);\n\t\tthis.onSubscribe?.(subscription);\n\t\t\n\t}\n\t\n\tchanged(changed) {\n\t\tfor (const subscription of this.subscriptions)\n\t\t\tsubscription.changed(changed);\n\t\t\n\t}\n\t\n\tunsubscribe(subscription) {\n\t\tthis.onUnsubscribe?.(subscription);\n\t\tthis.subscriptions.delete(subscription);\n\t\t\n\t}\n\t\n}\n", "import { publications } from \"./Publication\";\n\n\nexport class SubscriptionHandle {\n\tconstructor(publicationName, args, handler, immediately, prevent) {\n\t\tthis.publication = publications.get(publicationName);\n\t\t\n\t\tif (this.publication) {\n\t\t\tthis.args = args;\n\t\t\tthis.handler = handler;\n\t\t\t\n\t\t\tif (!prevent) {\n\t\t\t\tthis.publication.subscribe(this);\n\t\t\t\t\n\t\t\t\tif (immediately)\n\t\t\t\t\tthis.changed(null);\n\t\t\t}\n\t\t\t\n\t\t} else if (process.env.NODE_ENV === \"development\")\n\t\t\tconsole.error(\"Unknown publication\", publicationName);\n\t\t\n\t}\n\t\n\tasync changed(changed) {\n\t\tthis.handler(await this.publication.fetchSubscription(this, changed), changed);\n\t\t\n\t}\n\t\n\tcancel() {\n\t\t\n\t\tthis.publication?.unsubscribe(this);\n\t\t\n\t}\n\t\n\trenew() {\n\t\t\n\t\tthis.publication?.unsubscribe(this);\n\t\t\n\t\tthis.publication?.subscribe(this);\n\t\t\n\t\treturn this.changed(null);\n\t}\n\t\n}\n", "import { SubscriptionHandle } from \"./SubscriptionHandle\";\n\n\nexport class CollectionMapSubscriptionHandle extends SubscriptionHandle {\n\tconstructor(publicationName, args, handler, immediately) {\n\t\tsuper(publicationName, args, handler, immediately, true);\n\t\t\n\t\tif (this.publication) {\n\t\t\tthis.publication.subscribe(this);\n\t\t\t\n\t\t\tthis.skipSymbol = this.publication.skipSymbol;\n\t\t\t\n\t\t\tif (immediately)\n\t\t\t\tthis.changed(null);\n\t\t}\n\t\t\n\t}\n\t\n\tids = new Set();\n\t\n\tasync changed(next) {\n\t\tthis.handler([ await this.publication.fetchSubscription(this, next) ]);\n\t\t\n\t}\n\t\n\tupdates = [];\n\tflushTimeout = null;\n\t\n\thandleUpdatedFieldsSome = field => this.fields.has(field);\n\t\n\tflushUpdates = () => {\n\t\t\n\t\tif (this.updates.length) {\n\t\t\tthis.handler(this.updates);\n\t\t\tthis.updates = [];\n\t\t}\n\t\t\n\t};\n\t\n\tcollectionChangeListener = async next => {\n\t\t\n\t\tif (\n\t\t\t!next[this.skipSymbol] &&\n\t\t\t(this.ids.has(next.documentKey._id) ? (\n\t\t\t\tnext.operationType !== \"update\" ||\n\t\t\t\t!this.fields ||\n\t\t\t\tObject.keys(next.updateDescription.updatedFields).some(this.handleUpdatedFieldsSome)\n\t\t\t) : this.match(next.fullDocument))\n\t\t) {\n\t\t\tclearTimeout(this.flushTimeout);\n\t\t\t\n\t\t\tthis.updates.push(await this.publication.fetchSubscription(this, next));\n\t\t\t\n\t\t\tthis.flushTimeout = setTimeout(this.flushUpdates, 1);\n\t\t}\n\t\t\n\t};\n\t\n\t\n}\n", "export class Subscriptions extends Map {\n\t\n\tsubscribe = this.set;\n\t\n\trenew() {\n\t\treturn Promise.all(this.mapValues(subscription => subscription.renew()));\n\t}\n\t\n\tcancel(key) {\n\t\tthis.get(key)?.cancel();\n\t\tthis.delete(key);\n\t\t\n\t}\n\t\n}\n", "import { CollectionMapSubscriptionHandle } from \"../CollectionMapSubscriptionHandle\";\nimport { publications } from \"../Publication\";\nimport { SubscriptionHandle } from \"../SubscriptionHandle\";\nimport { Subscriptions } from \"./Subscriptions\";\n\n\nconst handlesByType = {\n\tobject: SubscriptionHandle,\n\tmap: CollectionMapSubscriptionHandle\n};\n\n\nexport class SubscriptionHandler {\n\tconstructor(wss, options = {}) {\n\t\t\n\t\tconst {\n\t\t\tusers\n\t\t} = options;\n\t\t\n\t\tif (users)\n\t\t\tusers.on(\"user-permissions-change\", SubscriptionHandler.handleUserPermissionsChange);\n\t\t\n\t\twss.on(\"client-connect\", SubscriptionHandler.handleClientConnect);\n\t\twss.on(\"client-session\", SubscriptionHandler.handleClientSession);\n\t\twss.on(\"client-message:s-s\"/* subscription subscribe */, SubscriptionHandler.handleClientSubscribe);\n\t\twss.on(\"client-message:s-u\"/* subscription unsubscribe */, SubscriptionHandler.handleClientUnsubscribe);\n\t\twss.on(\"client-close\", SubscriptionHandler.handleClientClose);\n\t\t\n\t}\n\t\n\t\n\tstatic handleUserPermissionsChange(user) {\n\t\tif (user.webSockets)\n\t\t\tfor (const ws of user.webSockets)\n\t\t\t\tws.subscriptions.renew();\n\t\t\n\t}\n\t\n\tstatic handleClientConnect(ws) {\n\t\tws.subscriptions = new Subscriptions();\n\t\t\n\t}\n\t\n\tstatic handleClientSession(ws) {\n\t\tws.subscriptions.renew();\n\t\t\n\t}\n\t\n\tstatic handleClientSubscribe(ws, subscriptionType, publicationName, i, args, immediately) {\n\t\tconst Handle = handlesByType[subscriptionType];\n\t\t\n\t\tif (Handle && publications.get(publicationName)?.type === subscriptionType) {\n\t\t\tconst handler = data => ws.sendMessage(\"s-c\"/* subscription changed */, i, data);\n\t\t\tws.subscriptions.subscribe(i, new Handle(publicationName, [ ws, ...args ], handler, immediately));\n\t\t}\n\t\t\n\t}\n\t\n\tstatic handleClientUnsubscribe(ws, i) {\n\t\tws.subscriptions.cancel(i);\n\t\t\n\t}\n\t\n\tstatic handleClientClose(ws) {\n\t\tfor (const subscription of ws.subscriptions.values())\n\t\t\tsubscription.cancel();\n\t\t\n\t}\n\t\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["sift", "publications", "Publication", "name", "props", "subscription", "changed", "projectDocument", "document", "projection", "isInclusive", "isTop", "projected", "key", "subprojection", "item", "CollectionMapPublication", "Publication", "name", "collection", "queryProps", "transform", "next", "args", "query", "sort", "triggers", "isProjectionInclusive", "fields", "subscription", "_id", "doc", "cursor", "array", "changed", "sift", "SubscriptionHandle", "publicationName", "args", "handler", "immediately", "prevent", "publications", "changed", "CollectionMapSubscriptionHandle", "SubscriptionHandle", "publicationName", "args", "handler", "immediately", "next", "field", "Subscriptions", "subscription", "key", "handlesByType", "SubscriptionHandle", "CollectionMapSubscriptionHandle", "SubscriptionHandler", "_SubscriptionHandler", "wss", "options", "users", "user", "ws", "Subscriptions", "subscriptionType", "publicationName", "i", "args", "immediately", "Handle", "publications", "handler", "data", "subscription"]
|
|
7
|
+
}
|
package/package.json
CHANGED
|
@@ -1,34 +1,32 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
"@nesvet/eslint-config": "^1"
|
|
33
|
-
}
|
|
2
|
+
"name": "insite-subscriptions-server",
|
|
3
|
+
"version": "1.0.227",
|
|
4
|
+
"description": "inSite subscriptions server side",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"packageManager": "bun@1.1.8",
|
|
9
|
+
"scripts": {
|
|
10
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
11
|
+
"build": "bun .conveyer.js"
|
|
12
|
+
},
|
|
13
|
+
"repository": {
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "git+https://github.com/nesvet/insite-subscriptions-server.git"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"insite",
|
|
19
|
+
"subscriptions",
|
|
20
|
+
"server"
|
|
21
|
+
],
|
|
22
|
+
"author": "Eugene Nesvetaev <dev@nesvet.dev> (https://nesvet.dev/)",
|
|
23
|
+
"license": "MIT",
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"insite-ws": "^1",
|
|
26
|
+
"sift": "^16"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@nesvet/conveyer": "^2",
|
|
30
|
+
"@nesvet/eslint-config": "^1"
|
|
31
|
+
}
|
|
34
32
|
}
|
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
import sift from "sift";
|
|
2
|
-
import { Publication } from "./Publication";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
function projectDocument(document, projection, isInclusive = true, isTop = true) {
|
|
6
|
-
if (projection)
|
|
7
|
-
if (isInclusive) {
|
|
8
|
-
const projected = {};
|
|
9
|
-
for (const key in projection) {
|
|
10
|
-
const subprojection = projection[key];
|
|
11
|
-
projected[key] =
|
|
12
|
-
typeof subprojection == "object" ?
|
|
13
|
-
Array.isArray(document[key]) ?
|
|
14
|
-
document[key].map(item => projectDocument(item, subprojection, true, false)) :
|
|
15
|
-
projectDocument(document[key], subprojection, true, false) :
|
|
16
|
-
document[key];
|
|
17
|
-
}
|
|
18
|
-
if (isTop && projection._id === 0)
|
|
19
|
-
delete projected._id;
|
|
20
|
-
|
|
21
|
-
return projected;
|
|
22
|
-
} else {
|
|
23
|
-
const projected = { ...document };
|
|
24
|
-
for (const key in projection) {
|
|
25
|
-
const subprojection = projection[key];
|
|
26
|
-
if (typeof subprojection == "object")
|
|
27
|
-
projected[key] =
|
|
28
|
-
Array.isArray(document[key]) ?
|
|
29
|
-
document[key].map(item => projectDocument(item, subprojection, false, false)) :
|
|
30
|
-
projectDocument(document[key], subprojection, false, false);
|
|
31
|
-
else
|
|
32
|
-
delete projected[key];
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
return projected;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
return document;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
export class CollectionMapPublication extends Publication {
|
|
43
|
-
constructor(name, collection, queryProps, transform) {
|
|
44
|
-
super(name, { collection, queryProps, transform });
|
|
45
|
-
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
type = "map";
|
|
49
|
-
|
|
50
|
-
skipSymbol = Symbol("skip");
|
|
51
|
-
|
|
52
|
-
skip(next) {
|
|
53
|
-
next[this.skipSymbol] = true;
|
|
54
|
-
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
makeQueryProps(args) {
|
|
58
|
-
const { query = null, projection = null, sort = null, triggers } = (typeof this.queryProps == "function" ? this.queryProps(...args) : this.queryProps) || {};
|
|
59
|
-
|
|
60
|
-
let isProjectionInclusive = null;
|
|
61
|
-
let fields = null;
|
|
62
|
-
if (projection) {
|
|
63
|
-
for (const key in projection) {
|
|
64
|
-
isProjectionInclusive = !!projection[key];
|
|
65
|
-
if (key !== "_id")
|
|
66
|
-
break;
|
|
67
|
-
}
|
|
68
|
-
if (isProjectionInclusive) {
|
|
69
|
-
fields = new Set([ ...Object.keys(query), ...Object.keys(projection), ...triggers ?? [] ]);
|
|
70
|
-
fields.delete("_id");
|
|
71
|
-
if (projection._id !== 0)
|
|
72
|
-
projection._id = 1;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
return { query, projection, isProjectionInclusive, fields, sort, args };
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
async fetchSubscription(subscription, next) {
|
|
80
|
-
if (subscription.query) {
|
|
81
|
-
if (next) {
|
|
82
|
-
const { _id } = next.documentKey;
|
|
83
|
-
|
|
84
|
-
if (next.operationType === "insert" || (next.operationType != "delete" && subscription.match(next.fullDocument))) {
|
|
85
|
-
const doc = projectDocument(next.fullDocument, subscription.projection, subscription.isProjectionInclusive);
|
|
86
|
-
this.transform?.(doc, subscription.args);
|
|
87
|
-
if (subscription.ids.has(_id))
|
|
88
|
-
return [ "u"/* update */, doc, next.updateDescription && Object.keys(next.updateDescription.updatedFields) ];
|
|
89
|
-
|
|
90
|
-
subscription.ids.add(_id);
|
|
91
|
-
|
|
92
|
-
return [ "c"/* create */, doc ];
|
|
93
|
-
|
|
94
|
-
}
|
|
95
|
-
subscription.ids.delete(_id);
|
|
96
|
-
|
|
97
|
-
return [ "d"/* delete */, _id ];
|
|
98
|
-
|
|
99
|
-
}
|
|
100
|
-
const cursor = this.collection.find(subscription.query);
|
|
101
|
-
|
|
102
|
-
if (subscription.projection)
|
|
103
|
-
cursor.project(subscription.projection);
|
|
104
|
-
|
|
105
|
-
if (subscription.sort)
|
|
106
|
-
cursor.sort(subscription.sort);
|
|
107
|
-
|
|
108
|
-
const array = await cursor.toArray();
|
|
109
|
-
|
|
110
|
-
if (subscription.ids) {
|
|
111
|
-
subscription.ids.clear();
|
|
112
|
-
if (this.transform)
|
|
113
|
-
for (const item of array) {
|
|
114
|
-
subscription.ids.add(item._id);
|
|
115
|
-
this.transform(item, subscription.args);
|
|
116
|
-
}
|
|
117
|
-
else
|
|
118
|
-
for (const item of array)
|
|
119
|
-
subscription.ids.add(item._id);
|
|
120
|
-
} else if (this.transform)
|
|
121
|
-
for (const item of array)
|
|
122
|
-
this.transform(item, subscription.args);
|
|
123
|
-
|
|
124
|
-
return [ "i"/* initial */, array, subscription.sort ];
|
|
125
|
-
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
return null;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
async fetch(...args) {
|
|
132
|
-
return [ await this.fetchSubscription(this.makeQueryProps(args), null) ];
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
changed(changed) {
|
|
136
|
-
return Promise.all(this.subscriptions.map(subscription => subscription.changed(changed)));
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
onSubscribe(subscription) {
|
|
140
|
-
Object.assign(subscription, this.makeQueryProps(subscription.args));
|
|
141
|
-
|
|
142
|
-
if (subscription.query) {
|
|
143
|
-
subscription.match = sift(subscription.query);
|
|
144
|
-
this.collection.changeListeners.add(subscription.collectionChangeListener);
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
flushInitial() {
|
|
150
|
-
return Promise.all(this.subscriptions.map(async subscription => {
|
|
151
|
-
subscription.handler([ await this.fetchSubscription(subscription) ]);
|
|
152
|
-
subscription.updates = [];
|
|
153
|
-
|
|
154
|
-
}));
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
onUnsubscribe(subscription) {
|
|
158
|
-
if (subscription.query)
|
|
159
|
-
this.collection.changeListeners.delete(subscription.collectionChangeListener);
|
|
160
|
-
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
}
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import { SubscriptionHandle } from "./SubscriptionHandle";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
export class CollectionMapSubscriptionHandle extends SubscriptionHandle {
|
|
5
|
-
constructor(publicationName, args, handler, immediately) {
|
|
6
|
-
super(publicationName, args, handler, immediately, true);
|
|
7
|
-
|
|
8
|
-
if (this.publication) {
|
|
9
|
-
this.publication.subscribe(this);
|
|
10
|
-
|
|
11
|
-
this.skipSymbol = this.publication.skipSymbol;
|
|
12
|
-
|
|
13
|
-
if (immediately)
|
|
14
|
-
this.changed(null);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
ids = new Set();
|
|
20
|
-
|
|
21
|
-
async changed(next) {
|
|
22
|
-
this.handler([ await this.publication.fetchSubscription(this, next) ]);
|
|
23
|
-
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
updates = [];
|
|
27
|
-
flushTimeout = null;
|
|
28
|
-
|
|
29
|
-
handleUpdatedFieldsSome = field => this.fields.has(field);
|
|
30
|
-
|
|
31
|
-
flushUpdates = () => {
|
|
32
|
-
|
|
33
|
-
if (this.updates.length) {
|
|
34
|
-
this.handler(this.updates);
|
|
35
|
-
this.updates = [];
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
collectionChangeListener = async next => {
|
|
41
|
-
|
|
42
|
-
if (
|
|
43
|
-
!next[this.skipSymbol] &&
|
|
44
|
-
(this.ids.has(next.documentKey._id) ? (
|
|
45
|
-
next.operationType !== "update" ||
|
|
46
|
-
!this.fields ||
|
|
47
|
-
Object.keys(next.updateDescription.updatedFields).some(this.handleUpdatedFieldsSome)
|
|
48
|
-
) : this.match(next.fullDocument))
|
|
49
|
-
) {
|
|
50
|
-
clearTimeout(this.flushTimeout);
|
|
51
|
-
|
|
52
|
-
this.updates.push(await this.publication.fetchSubscription(this, next));
|
|
53
|
-
|
|
54
|
-
this.flushTimeout = setTimeout(this.flushUpdates, 1);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
}
|
package/lib/Publication.js
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
export const publications = new Map();
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
export class Publication {
|
|
5
|
-
constructor(name, props) {
|
|
6
|
-
this.name = name;
|
|
7
|
-
Object.assign(this, props);
|
|
8
|
-
|
|
9
|
-
publications.set(name, this);
|
|
10
|
-
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
type = "object";
|
|
14
|
-
|
|
15
|
-
subscriptions = new Set();
|
|
16
|
-
|
|
17
|
-
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
18
|
-
fetch() {}
|
|
19
|
-
|
|
20
|
-
fetchSubscription(subscription) {
|
|
21
|
-
return this.fetch(...subscription.args);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
subscribe(subscription) {
|
|
25
|
-
this.subscriptions.add(subscription);
|
|
26
|
-
this.onSubscribe?.(subscription);
|
|
27
|
-
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
changed(changed) {
|
|
31
|
-
for (const subscription of this.subscriptions)
|
|
32
|
-
subscription.changed(changed);
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
unsubscribe(subscription) {
|
|
37
|
-
this.onUnsubscribe?.(subscription);
|
|
38
|
-
this.subscriptions.delete(subscription);
|
|
39
|
-
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
}
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import { publications } from "./Publication";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
export class SubscriptionHandle {
|
|
5
|
-
constructor(publicationName, args, handler, immediately, prevent) {
|
|
6
|
-
this.publication = publications.get(publicationName);
|
|
7
|
-
|
|
8
|
-
if (this.publication) {
|
|
9
|
-
this.args = args;
|
|
10
|
-
this.handler = handler;
|
|
11
|
-
|
|
12
|
-
if (!prevent) {
|
|
13
|
-
this.publication.subscribe(this);
|
|
14
|
-
|
|
15
|
-
if (immediately)
|
|
16
|
-
this.changed(null);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
} else if (process.env.NODE_ENV === "development")
|
|
20
|
-
console.error("Unknown publication", publicationName);
|
|
21
|
-
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
async changed(changed) {
|
|
25
|
-
this.handler(await this.publication.fetchSubscription(this, changed), changed);
|
|
26
|
-
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
cancel() {
|
|
30
|
-
|
|
31
|
-
this.publication?.unsubscribe(this);
|
|
32
|
-
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
renew() {
|
|
36
|
-
|
|
37
|
-
this.publication?.unsubscribe(this);
|
|
38
|
-
|
|
39
|
-
this.publication?.subscribe(this);
|
|
40
|
-
|
|
41
|
-
return this.changed(null);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
}
|
package/lib/index.js
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import { CollectionMapSubscriptionHandle } from "../CollectionMapSubscriptionHandle";
|
|
2
|
-
import { publications } from "../Publication";
|
|
3
|
-
import { SubscriptionHandle } from "../SubscriptionHandle";
|
|
4
|
-
import { Subscriptions } from "./Subscriptions";
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const handlesByType = {
|
|
8
|
-
object: SubscriptionHandle,
|
|
9
|
-
map: CollectionMapSubscriptionHandle
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
export class SubscriptionHandler {
|
|
14
|
-
constructor(wss, options = {}) {
|
|
15
|
-
|
|
16
|
-
const {
|
|
17
|
-
users
|
|
18
|
-
} = options;
|
|
19
|
-
|
|
20
|
-
if (users)
|
|
21
|
-
users.on("user-permissions-change", SubscriptionHandler.handleUserPermissionsChange);
|
|
22
|
-
|
|
23
|
-
wss.on("client-connect", SubscriptionHandler.handleClientConnect);
|
|
24
|
-
wss.on("client-session", SubscriptionHandler.handleClientSession);
|
|
25
|
-
wss.on("client-message:s-s"/* subscription subscribe */, SubscriptionHandler.handleClientSubscribe);
|
|
26
|
-
wss.on("client-message:s-u"/* subscription unsubscribe */, SubscriptionHandler.handleClientUnsubscribe);
|
|
27
|
-
wss.on("client-close", SubscriptionHandler.handleClientClose);
|
|
28
|
-
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
static handleUserPermissionsChange(user) {
|
|
33
|
-
if (user.webSockets)
|
|
34
|
-
for (const ws of user.webSockets)
|
|
35
|
-
ws.subscriptions.renew();
|
|
36
|
-
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
static handleClientConnect(ws) {
|
|
40
|
-
ws.subscriptions = new Subscriptions();
|
|
41
|
-
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
static handleClientSession(ws) {
|
|
45
|
-
ws.subscriptions.renew();
|
|
46
|
-
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
static handleClientSubscribe(ws, subscriptionType, publicationName, i, args, immediately) {
|
|
50
|
-
const Handle = handlesByType[subscriptionType];
|
|
51
|
-
|
|
52
|
-
if (Handle && publications.get(publicationName)?.type === subscriptionType) {
|
|
53
|
-
const handler = data => ws.sendMessage("s-c"/* subscription changed */, i, data);
|
|
54
|
-
ws.subscriptions.subscribe(i, new Handle(publicationName, [ ws, ...args ], handler, immediately));
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
static handleClientUnsubscribe(ws, i) {
|
|
60
|
-
ws.subscriptions.cancel(i);
|
|
61
|
-
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
static handleClientClose(ws) {
|
|
65
|
-
for (const subscription of ws.subscriptions.values())
|
|
66
|
-
subscription.cancel();
|
|
67
|
-
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
}
|
package/lib/ws/Subscriptions.js
DELETED
package/lib/ws/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./SubscriptionHandler";
|