@manifest-editor/server-vault 2.1.1-next.0.96fdf30 → 2.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/dist/index.cjs CHANGED
@@ -1,4 +1,5 @@
1
- //#region rolldown:runtime
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ //#region \0rolldown/runtime.js
2
3
  var __create = Object.create;
3
4
  var __defProp = Object.defineProperty;
4
5
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -15,31 +16,28 @@ var __copyProps = (to, from, except, desc) => {
15
16
  }
16
17
  return to;
17
18
  };
18
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
19
20
  value: mod,
20
21
  enumerable: true
21
22
  }) : target, mod));
22
-
23
23
  //#endregion
24
- let __iiif_helpers_vault = require("@iiif/helpers/vault");
24
+ let _iiif_helpers_vault = require("@iiif/helpers/vault");
25
25
  let ws = require("ws");
26
- ws = __toESM(ws);
26
+ ws = __toESM(ws, 1);
27
27
  let uuid = require("uuid");
28
28
  let timers = require("timers");
29
29
  let http = require("http");
30
-
31
- //#region \0@oxc-project+runtime@0.97.0/helpers/typeof.js
30
+ //#region \0@oxc-project+runtime@0.143.0/helpers/esm/typeof.js
32
31
  function _typeof(o) {
33
32
  "@babel/helpers - typeof";
34
- return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o$1) {
35
- return typeof o$1;
36
- } : function(o$1) {
37
- return o$1 && "function" == typeof Symbol && o$1.constructor === Symbol && o$1 !== Symbol.prototype ? "symbol" : typeof o$1;
33
+ return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o) {
34
+ return typeof o;
35
+ } : function(o) {
36
+ return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
38
37
  }, _typeof(o);
39
38
  }
40
-
41
39
  //#endregion
42
- //#region \0@oxc-project+runtime@0.97.0/helpers/toPrimitive.js
40
+ //#region \0@oxc-project+runtime@0.143.0/helpers/esm/toPrimitive.js
43
41
  function toPrimitive(t, r) {
44
42
  if ("object" != _typeof(t) || !t) return t;
45
43
  var e = t[Symbol.toPrimitive];
@@ -50,16 +48,14 @@ function toPrimitive(t, r) {
50
48
  }
51
49
  return ("string" === r ? String : Number)(t);
52
50
  }
53
-
54
51
  //#endregion
55
- //#region \0@oxc-project+runtime@0.97.0/helpers/toPropertyKey.js
52
+ //#region \0@oxc-project+runtime@0.143.0/helpers/esm/toPropertyKey.js
56
53
  function toPropertyKey(t) {
57
54
  var i = toPrimitive(t, "string");
58
55
  return "symbol" == _typeof(i) ? i : i + "";
59
56
  }
60
-
61
57
  //#endregion
62
- //#region \0@oxc-project+runtime@0.97.0/helpers/defineProperty.js
58
+ //#region \0@oxc-project+runtime@0.143.0/helpers/esm/defineProperty.js
63
59
  function _defineProperty(e, r, t) {
64
60
  return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
65
61
  value: t,
@@ -68,7 +64,6 @@ function _defineProperty(e, r, t) {
68
64
  writable: !0
69
65
  }) : e[r] = t, e;
70
66
  }
71
-
72
67
  //#endregion
73
68
  //#region src/server-vault.ts
74
69
  const GenesisId = "@genesis";
@@ -141,7 +136,7 @@ var ServerVault = class {
141
136
  ...message
142
137
  });
143
138
  });
144
- this.vault = new __iiif_helpers_vault.Vault();
139
+ this.vault = new _iiif_helpers_vault.Vault();
145
140
  this.ws = new ws.WebSocketServer({ noServer: true });
146
141
  this.ws.on("connection", this.setupWebSocket);
147
142
  this.pingInterval = (0, timers.setInterval)(() => {
@@ -167,7 +162,6 @@ var ServerVault = class {
167
162
  });
168
163
  }
169
164
  };
170
-
171
165
  //#endregion
172
166
  //#region src/server.ts
173
167
  var MultiVaultServer = class {
@@ -203,9 +197,9 @@ var MultiVaultServer = class {
203
197
  }
204
198
  if (vault) {
205
199
  const theVault = vault;
206
- theVault.ws.handleUpgrade(request, socket, head, (ws$1) => {
200
+ theVault.ws.handleUpgrade(request, socket, head, (ws) => {
207
201
  console.log("new client", vaultId);
208
- theVault.ws.emit("connection", ws$1, request);
202
+ theVault.ws.emit("connection", ws, request);
209
203
  theVault.ws.on("close", () => {
210
204
  if (theVault.ws.clients.size === 0) {
211
205
  console.log("destroying vault", vaultId);
@@ -227,7 +221,8 @@ var MultiVaultServer = class {
227
221
  this.server.listen(port, hostname, backlog, listeningListener);
228
222
  }
229
223
  };
230
-
231
224
  //#endregion
232
225
  exports.MultiVaultServer = MultiVaultServer;
233
- exports.ServerVault = ServerVault;
226
+ exports.ServerVault = ServerVault;
227
+
228
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","names":["WebSocket","v4","Vault","WebSocketServer","setInterval","createServer"],"sources":["../src/server-vault.ts","../src/server.ts"],"sourcesContent":["// Server vault.\nimport { AllActions, IIIFStore, Vault } from \"@iiif/helpers/vault\";\nimport { BatchAction } from \"@iiif/helpers/vault/actions\";\nimport { Collection, Manifest } from \"@iiif/presentation-3\";\nimport WebSocket, { RawData, WebSocketServer } from \"ws\";\nimport { v4 } from \"uuid\";\nimport { clearInterval, setInterval } from \"timers\";\n\ntype RemoteAction = {\n _id: string;\n _type: \"vault-action\";\n _lastActionId: string;\n action: AllActions | BatchAction;\n};\n\nconst GenesisId = \"@genesis\";\n\ntype ClientInitAction = {\n _id: string;\n _type: \"init-response\";\n _lastActionId: string;\n data: IIIFStore;\n};\n\ntype ClientInitRequestAction = {\n _type: \"init-request\";\n};\n\ntype RemoteActionConfirmation = {\n _id: string;\n _type: \"vault-action-confirmation\";\n _lastActionId: string;\n action: string;\n};\n\ntype RemoteActionRejection = {\n _id: string;\n _type: \"vault-action-rejection\";\n _lastActionId: string;\n action: string;\n};\n\ntype InitialiseWithResourceAction = {\n _id: string;\n _type: \"initialise-with-resource\";\n _lastActionId: string;\n resource: Collection | Manifest;\n};\n\ntype EmptyVaultResponse = {\n _id: string;\n _type: \"empty-vault-response\";\n _lastActionId: string;\n};\n\nexport type ClientAction = RemoteAction | ClientInitRequestAction | InitialiseWithResourceAction;\n\nexport type ServerAction =\n | RemoteAction\n | RemoteActionConfirmation\n | RemoteActionRejection\n | ClientInitAction\n | EmptyVaultResponse;\n\n// Extend ws module interface WebSocket.WebSocket with custom typescript property\ndeclare module \"ws\" {\n interface WebSocket {\n isAlive: boolean;\n }\n}\n\nexport interface ServerVaultOptions {\n pingTimeout?: number;\n onClose?: () => void;\n}\n\nexport class ServerVault {\n vault: Vault;\n ws: WebSocketServer;\n lastActionId: string = GenesisId;\n pingInterval: NodeJS.Timeout;\n\n private _handleMessage = new Map();\n private _handleOpen = new Map();\n private _handleClose = new Map();\n\n constructor(options: ServerVaultOptions = {}) {\n this.vault = new Vault();\n this.ws = new WebSocketServer({ noServer: true });\n\n this.ws.on(\"connection\", this.setupWebSocket);\n\n this.pingInterval = setInterval(() => {\n this.ws.clients.forEach((socket) => {\n if ((socket as any).isAlive === false) {\n return socket.terminate();\n }\n\n (socket as any).isAlive = false;\n socket.ping();\n });\n }, options.pingTimeout || 30000);\n\n this.ws.on(\"close\", () => {\n clearInterval(this.pingInterval);\n\n if (options.onClose) {\n options.onClose();\n }\n });\n\n this.ws.on(\"error\", (err) => {\n // @todo error handling.\n });\n }\n\n async close() {\n clearTimeout(this.pingInterval);\n\n return new Promise<void>((resolve, error) => {\n this.ws.close((err) => {\n if (err) {\n error(err);\n }\n resolve();\n });\n });\n }\n\n setupWebSocket = (socket: WebSocket.WebSocket) => {\n socket.isAlive = true;\n socket.on(\"pong\", () => {\n socket.isAlive = true;\n });\n socket.on(\"open\", this.handleOpen(socket));\n socket.on(\"message\", this.handleMessage(socket));\n socket.on(\"close\", this.handleClose(socket));\n // Send the initial state to the client.\n socket.send(this.createMessage(\"init-response\", { data: this.vault.getState() }));\n };\n\n handleMessage = (socket: WebSocket) => {\n if (this._handleMessage.has(socket)) {\n return this._handleMessage.get(socket);\n }\n const handler = (data: RawData, isBinary: boolean) => {\n const parsed: ClientAction = JSON.parse(data.toString());\n\n if (parsed._type === \"init-request\") {\n socket.send(this.createMessage(\"init-response\", { data: this.vault.getState() }));\n }\n\n if (parsed._type === \"vault-action\") {\n try {\n this.vault.dispatch(parsed.action);\n } catch (e) {\n // @todo error handling.\n socket.send(\n this.createMessage(\"vault-action-rejection\", {\n action: parsed._id,\n })\n );\n return;\n }\n\n this.lastActionId = parsed._id;\n this.rebroadcast(socket, data, parsed, isBinary);\n }\n };\n\n this._handleMessage.set(socket, handler);\n\n return handler;\n };\n\n send = (data: RawData) => {\n this.ws.clients.forEach(function each(client) {\n if (client.readyState === WebSocket.OPEN) {\n client.send(data, { binary: true });\n }\n });\n };\n\n rebroadcast = (source: WebSocket, data: RawData, action: RemoteAction, isBinary = true) => {\n this.ws.clients.forEach((client) => {\n if (client !== source && client.readyState === WebSocket.OPEN) {\n client.send(data, { binary: isBinary });\n } else {\n client.send(\n this.createMessage(\"vault-action-confirmation\", {\n action: action._id,\n })\n );\n }\n });\n };\n\n handleOpen = (socket: WebSocket) => {\n if (this._handleOpen.has(socket)) {\n return this._handleOpen.get(socket);\n }\n const handler = () => {\n // Handle open.\n };\n\n this._handleOpen.set(socket, handler);\n\n return handler;\n };\n\n handleClose = (socket: WebSocket) => {\n if (this._handleClose.has(socket)) {\n return this._handleClose.get(socket);\n }\n const handler = () => {\n // Close handler.\n };\n\n this._handleClose.set(socket, handler);\n\n return handler;\n };\n\n createMessage = (type: string, message: any) => {\n return JSON.stringify({\n _id: v4(),\n _type: type,\n _lastActionId: this.lastActionId,\n ...message,\n });\n };\n}\n","import { createServer, IncomingMessage, Server } from \"http\";\nimport { Socket } from \"net\";\nimport { ServerVault } from \"./server-vault\";\n\nexport class MultiVaultServer {\n server: Server;\n vaults: Map<string, ServerVault> = new Map();\n constructor(server?: Server) {\n this.server = server || createServer();\n this.server.on(\"upgrade\", this.handleUpgrade);\n this.server.on(\"request\", this.handleRequest);\n }\n\n listen(port: number, hostname?: string, backlog?: number, listeningListener?: () => void) {\n this.server.listen(port, hostname, backlog, listeningListener);\n }\n\n handleRequest = (request: IncomingMessage, response: any) => {\n if (request.url === \"/vault\") {\n // Need to respond with a JSON body with a list of available vaults.\n const vaults = Array.from(this.vaults.keys());\n const json = JSON.stringify({ vaults });\n\n response.writeHead(200, {\n \"Content-Length\": Buffer.byteLength(json),\n \"Content-Type\": \"application/json\",\n });\n response.write(json);\n response.end();\n return;\n }\n\n // If the pathname is not recognised, destroy the socket and send 404.\n response.writeHead(404);\n response.end();\n };\n\n handleUpgrade = (request: IncomingMessage, socket: Socket, head: Buffer) => {\n console.log(\"ws.url\", request.url);\n const pathname = request.url;\n\n // @todo some logic for handling the pathname. For now, just let any incoming be an ID.\n if (pathname && (pathname as string).startsWith(\"/vault\")) {\n // Get the vault ID from the URL.\n const vaultId = (pathname as string).replace(\"/vault/\", \"\");\n\n let vault = this.vaults.get(vaultId);\n\n // If no vault exists for this ID, create one.\n if (!vault) {\n const newVault = new ServerVault();\n console.log(\"new vault\", vaultId);\n this.vaults.set(vaultId, newVault);\n vault = newVault;\n }\n\n if (vault) {\n const theVault = vault;\n // If it exists, add the socket to the vault.\n theVault.ws.handleUpgrade(request, socket, head, (ws) => {\n console.log(\"new client\", vaultId);\n theVault.ws.emit(\"connection\", ws, request);\n theVault.ws.on(\"close\", () => {\n if (theVault.ws.clients.size === 0) {\n console.log(\"destroying vault\", vaultId);\n this.vaults.delete(vaultId);\n }\n });\n });\n } else {\n socket.destroy();\n }\n return;\n }\n\n // If the pathname is not recognised, destroy the socket and send 404.\n socket.write(\"HTTP/1.1 404 Not Found\\r\\n\\r\\n\");\n socket.destroy();\n };\n}\n"],"mappings":"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"}
package/dist/index.d.cts CHANGED
@@ -4,7 +4,6 @@ import { Collection, Manifest } from "@iiif/presentation-3";
4
4
  import WebSocket, { RawData, WebSocketServer } from "ws";
5
5
  import { IncomingMessage, Server } from "http";
6
6
  import { Socket } from "net";
7
-
8
7
  //#region src/server-vault.d.ts
9
8
  type RemoteAction = {
10
9
  _id: string;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","names":[],"sources":["../src/server-vault.ts","../src/server.ts"],"sourcesContent":[],"mappings":";;;;;;;;KAQK,YAAA;;;;EAAA,MAAA,EAIK,UAJO,GAIM,WAAb;AAAwB,CAAA;AASjB,KAJZ,gBAAA,GAOA;EAIA,GAAA,EAAA,MAAA;EAOA,KAAA,EAAA,eAAA;EAOA,aAAA,EAAA,MAAA;EAOA,IAAA,EA5BG,SA4BH;AAML,CAAA;KA/BK,uBAAA,GA+BsB;EAAe,KAAA,EAAA,cAAA;CAA0B;KA3B/D,wBAAA,GA2B2F;EAEpF,GAAA,EAAA,MAAA;EACR,KAAA,EAAA,2BAAA;EACA,aAAA,EAAA,MAAA;EACA,MAAA,EAAA,MAAA;CACA;KA1BC,qBAAA,GA2BD;EAAkB,GAAA,EAAA,MAAA;EAAC,KAAA,EAAA,wBAAA;EAAA,aAAA,EAAA,MAAA;QAAA,EAAA,MAAA;CAAA;KApBlB,4BAAA,GAoBkB;EASN,GAAA,EAAA,MAAA;EAKJ,KAAA,EAAA,0BAAW;EACf,aAAA,EAAA,MAAA;EACH,QAAA,EAhCM,UAgCN,GAhCmB,QAgCnB;CAEU;KA/BX,kBAAA,GAqCkB;EA8BV,GAAA,EAAA,MAAA;EAae,KAAA,EAAU,sBAAA;EAYX,aAAA,EAAA,MAAA;CAkCX;AAQS,KAhIb,YAAA,GAAe,YAgIF,GAhIiB,uBAgIjB,GAhI2C,4BAgI3C;AAAiB,KA9H9B,YAAA,GACR,YA6HsC,GA5HtC,wBA4HsC,GA3HtC,qBA2HsC,GA1HtC,gBA0HsC,GAzHtC,kBAyHsC;eAAiB,IAAA,CAAA;EAcnC,UAAA,SAAA,CAAA;IAaC,OAAA,EAAA,OAAA;EAAS;;UA3IjB,kBAAA;;ECnEJ,OAAA,CAAA,EAAA,GAAA,GAAA,IAAgB;;AAEP,cDsET,WAAA,CCtES;EAAZ,KAAA,EDuED,KCvEC;EACa,EAAA,EDuEjB,eCvEiB;EAUK,YAAA,EAAA,MAAA;EAoBA,YAAA,ED2CZ,MAAA,CAAO,OC3CK;EAAyB,QAAA,cAAA;EAAc,QAAA,WAAA;EAAM,QAAA,YAAA;wBDiDlD;WA8BV;2BAae,SAAA,CAAU;0BAYX;eAkCX;wBAQS,iBAAiB,iBAAiB;uBAcnC;wBAaC;;;;;cC9MZ,gBAAA;UACH;UACA,YAAY;uBACC;;EDClB,aAAA,EAAY,CAAA,OAAA,ECSW,eDLL,EAAA,QAAW,EAAA,GAAA,EAAA,GAAA,IAAA;EAK7B,aAAA,EAAA,CAAA,OAAgB,ECoBO,eDhBX,EAAA,MAAA,ECgBoC,MDhBpC,EAAA,IAAA,ECgBkD,MDhBlD,EAAA,GAAA,IAAA;AAAA"}
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../src/server-vault.ts","../src/server.ts"],"mappings":";;;;;;;KAQK;EACH;EACA;EACA;EACA,QAAQ,aAAa;;KAKlB;EACH;EACA;EACA;EACA,MAAM;;KAGH;EACH;;KAGG;EACH;EACA;EACA;EACA;;KAGG;EACH;EACA;EACA;EACA;;KAGG;EACH;EACA;EACA;EACA,UAAU,aAAa;;KAGpB;EACH;EACA;EACA;;KAGU,eAAe,eAAe,0BAA0B;KAExD,eACR,eACA,2BACA,wBACA,mBACA;;YAIQ;IACR;;;UAIa;EACf;EACA;;cAGW;EACX,OAAO;EACP,IAAI;EACJ;EACA,cAAc,OAAO;UAEb;UACA;UACA;EAER,YAAY,UAAS;EA8Bf,SAAK;EAaX,iBAAc,QAAY,UAAU;EAYpC,gBAAa,QAAY;EAkCzB,OAAI,MAAU;EAQd,cAAW,QAAY,WAAS,MAAQ,SAAO,QAAU,cAAY;EAcrE,aAAU,QAAY;EAatB,cAAW,QAAY;EAavB,gBAAa,cAAgB;;;;cC3NlB;EACX,QAAQ;EACR,QAAQ,YAAY;EACpB,YAAY,SAAS;EAMrB,OAAO,cAAc,mBAAmB,kBAAkB;EAI1D,gBAAa,SAAa,iBAAe;EAoBzC,gBAAa,SAAa,iBAAe,QAAU,QAAM,MAAQ"}
package/dist/index.d.mts CHANGED
@@ -4,7 +4,6 @@ import { IncomingMessage, Server } from "http";
4
4
  import { BatchAction } from "@iiif/helpers/vault/actions";
5
5
  import { Collection, Manifest } from "@iiif/presentation-3";
6
6
  import { Socket } from "net";
7
-
8
7
  //#region src/server-vault.d.ts
9
8
  type RemoteAction = {
10
9
  _id: string;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/server-vault.ts","../src/server.ts"],"sourcesContent":[],"mappings":";;;;;;;;KAQK,YAAA;;;;EAAA,MAAA,EAIK,UAJO,GAIM,WAAb;AAAwB,CAAA;AASjB,KAJZ,gBAAA,GAOA;EAIA,GAAA,EAAA,MAAA;EAOA,KAAA,EAAA,eAAA;EAOA,aAAA,EAAA,MAAA;EAOA,IAAA,EA5BG,SA4BH;AAML,CAAA;KA/BK,uBAAA,GA+BsB;EAAe,KAAA,EAAA,cAAA;CAA0B;KA3B/D,wBAAA,GA2B2F;EAEpF,GAAA,EAAA,MAAA;EACR,KAAA,EAAA,2BAAA;EACA,aAAA,EAAA,MAAA;EACA,MAAA,EAAA,MAAA;CACA;KA1BC,qBAAA,GA2BD;EAAkB,GAAA,EAAA,MAAA;EAAC,KAAA,EAAA,wBAAA;EAAA,aAAA,EAAA,MAAA;QAAA,EAAA,MAAA;CAAA;KApBlB,4BAAA,GAoBkB;EASN,GAAA,EAAA,MAAA;EAKJ,KAAA,EAAA,0BAAW;EACf,aAAA,EAAA,MAAA;EACH,QAAA,EAhCM,UAgCN,GAhCmB,QAgCnB;CAEU;KA/BX,kBAAA,GAqCkB;EA8BV,GAAA,EAAA,MAAA;EAae,KAAA,EAAU,sBAAA;EAYX,aAAA,EAAA,MAAA;CAkCX;AAQS,KAhIb,YAAA,GAAe,YAgIF,GAhIiB,uBAgIjB,GAhI2C,4BAgI3C;AAAiB,KA9H9B,YAAA,GACR,YA6HsC,GA5HtC,wBA4HsC,GA3HtC,qBA2HsC,GA1HtC,gBA0HsC,GAzHtC,kBAyHsC;eAAiB,IAAA,CAAA;EAcnC,UAAA,SAAA,CAAA;IAaC,OAAA,EAAA,OAAA;EAAS;;UA3IjB,kBAAA;;ECnEJ,OAAA,CAAA,EAAA,GAAA,GAAA,IAAgB;;AAEP,cDsET,WAAA,CCtES;EAAZ,KAAA,EDuED,KCvEC;EACa,EAAA,EDuEjB,eCvEiB;EAUK,YAAA,EAAA,MAAA;EAoBA,YAAA,ED2CZ,MAAA,CAAO,OC3CK;EAAyB,QAAA,cAAA;EAAc,QAAA,WAAA;EAAM,QAAA,YAAA;wBDiDlD;WA8BV;2BAae,SAAA,CAAU;0BAYX;eAkCX;wBAQS,iBAAiB,iBAAiB;uBAcnC;wBAaC;;;;;cC9MZ,gBAAA;UACH;UACA,YAAY;uBACC;;EDClB,aAAA,EAAY,CAAA,OAAA,ECSW,eDLL,EAAA,QAAW,EAAA,GAAA,EAAA,GAAA,IAAA;EAK7B,aAAA,EAAA,CAAA,OAAgB,ECoBO,eDhBX,EAAA,MAAA,ECgBoC,MDhBpC,EAAA,IAAA,ECgBkD,MDhBlD,EAAA,GAAA,IAAA;AAAA"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/server-vault.ts","../src/server.ts"],"mappings":";;;;;;;KAQK;EACH;EACA;EACA;EACA,QAAQ,aAAa;;KAKlB;EACH;EACA;EACA;EACA,MAAM;;KAGH;EACH;;KAGG;EACH;EACA;EACA;EACA;;KAGG;EACH;EACA;EACA;EACA;;KAGG;EACH;EACA;EACA;EACA,UAAU,aAAa;;KAGpB;EACH;EACA;EACA;;KAGU,eAAe,eAAe,0BAA0B;KAExD,eACR,eACA,2BACA,wBACA,mBACA;;YAIQ;IACR;;;UAIa;EACf;EACA;;cAGW;EACX,OAAO;EACP,IAAI;EACJ;EACA,cAAc,OAAO;UAEb;UACA;UACA;EAER,YAAY,UAAS;EA8Bf,SAAK;EAaX,iBAAc,QAAY,UAAU;EAYpC,gBAAa,QAAY;EAkCzB,OAAI,MAAU;EAQd,cAAW,QAAY,WAAS,MAAQ,SAAO,QAAU,cAAY;EAcrE,aAAU,QAAY;EAatB,cAAW,QAAY;EAavB,gBAAa,cAAgB;;;;cC3NlB;EACX,QAAQ;EACR,QAAQ,YAAY;EACpB,YAAY,SAAS;EAMrB,OAAO,cAAc,mBAAmB,kBAAkB;EAI1D,gBAAa,SAAa,iBAAe;EAoBzC,gBAAa,SAAa,iBAAe,QAAU,QAAM,MAAQ"}
package/dist/index.mjs CHANGED
@@ -3,19 +3,17 @@ import WebSocket, { WebSocketServer } from "ws";
3
3
  import { v4 } from "uuid";
4
4
  import { clearInterval, setInterval } from "timers";
5
5
  import { createServer } from "http";
6
-
7
- //#region \0@oxc-project+runtime@0.97.0/helpers/typeof.js
6
+ //#region \0@oxc-project+runtime@0.143.0/helpers/esm/typeof.js
8
7
  function _typeof(o) {
9
8
  "@babel/helpers - typeof";
10
- return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o$1) {
11
- return typeof o$1;
12
- } : function(o$1) {
13
- return o$1 && "function" == typeof Symbol && o$1.constructor === Symbol && o$1 !== Symbol.prototype ? "symbol" : typeof o$1;
9
+ return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o) {
10
+ return typeof o;
11
+ } : function(o) {
12
+ return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
14
13
  }, _typeof(o);
15
14
  }
16
-
17
15
  //#endregion
18
- //#region \0@oxc-project+runtime@0.97.0/helpers/toPrimitive.js
16
+ //#region \0@oxc-project+runtime@0.143.0/helpers/esm/toPrimitive.js
19
17
  function toPrimitive(t, r) {
20
18
  if ("object" != _typeof(t) || !t) return t;
21
19
  var e = t[Symbol.toPrimitive];
@@ -26,16 +24,14 @@ function toPrimitive(t, r) {
26
24
  }
27
25
  return ("string" === r ? String : Number)(t);
28
26
  }
29
-
30
27
  //#endregion
31
- //#region \0@oxc-project+runtime@0.97.0/helpers/toPropertyKey.js
28
+ //#region \0@oxc-project+runtime@0.143.0/helpers/esm/toPropertyKey.js
32
29
  function toPropertyKey(t) {
33
30
  var i = toPrimitive(t, "string");
34
31
  return "symbol" == _typeof(i) ? i : i + "";
35
32
  }
36
-
37
33
  //#endregion
38
- //#region \0@oxc-project+runtime@0.97.0/helpers/defineProperty.js
34
+ //#region \0@oxc-project+runtime@0.143.0/helpers/esm/defineProperty.js
39
35
  function _defineProperty(e, r, t) {
40
36
  return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
41
37
  value: t,
@@ -44,7 +40,6 @@ function _defineProperty(e, r, t) {
44
40
  writable: !0
45
41
  }) : e[r] = t, e;
46
42
  }
47
-
48
43
  //#endregion
49
44
  //#region src/server-vault.ts
50
45
  const GenesisId = "@genesis";
@@ -143,7 +138,6 @@ var ServerVault = class {
143
138
  });
144
139
  }
145
140
  };
146
-
147
141
  //#endregion
148
142
  //#region src/server.ts
149
143
  var MultiVaultServer = class {
@@ -203,7 +197,7 @@ var MultiVaultServer = class {
203
197
  this.server.listen(port, hostname, backlog, listeningListener);
204
198
  }
205
199
  };
206
-
207
200
  //#endregion
208
201
  export { MultiVaultServer, ServerVault };
202
+
209
203
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["parsed: ClientAction"],"sources":["../src/server-vault.ts","../src/server.ts"],"sourcesContent":["// Server vault.\nimport { AllActions, IIIFStore, Vault } from \"@iiif/helpers/vault\";\nimport { BatchAction } from \"@iiif/helpers/vault/actions\";\nimport { Collection, Manifest } from \"@iiif/presentation-3\";\nimport WebSocket, { RawData, WebSocketServer } from \"ws\";\nimport { v4 } from \"uuid\";\nimport { clearInterval, setInterval } from \"timers\";\n\ntype RemoteAction = {\n _id: string;\n _type: \"vault-action\";\n _lastActionId: string;\n action: AllActions | BatchAction;\n};\n\nconst GenesisId = \"@genesis\";\n\ntype ClientInitAction = {\n _id: string;\n _type: \"init-response\";\n _lastActionId: string;\n data: IIIFStore;\n};\n\ntype ClientInitRequestAction = {\n _type: \"init-request\";\n};\n\ntype RemoteActionConfirmation = {\n _id: string;\n _type: \"vault-action-confirmation\";\n _lastActionId: string;\n action: string;\n};\n\ntype RemoteActionRejection = {\n _id: string;\n _type: \"vault-action-rejection\";\n _lastActionId: string;\n action: string;\n};\n\ntype InitialiseWithResourceAction = {\n _id: string;\n _type: \"initialise-with-resource\";\n _lastActionId: string;\n resource: Collection | Manifest;\n};\n\ntype EmptyVaultResponse = {\n _id: string;\n _type: \"empty-vault-response\";\n _lastActionId: string;\n};\n\nexport type ClientAction = RemoteAction | ClientInitRequestAction | InitialiseWithResourceAction;\n\nexport type ServerAction =\n | RemoteAction\n | RemoteActionConfirmation\n | RemoteActionRejection\n | ClientInitAction\n | EmptyVaultResponse;\n\n// Extend ws module interface WebSocket.WebSocket with custom typescript property\ndeclare module \"ws\" {\n interface WebSocket {\n isAlive: boolean;\n }\n}\n\nexport interface ServerVaultOptions {\n pingTimeout?: number;\n onClose?: () => void;\n}\n\nexport class ServerVault {\n vault: Vault;\n ws: WebSocketServer;\n lastActionId: string = GenesisId;\n pingInterval: NodeJS.Timeout;\n\n private _handleMessage = new Map();\n private _handleOpen = new Map();\n private _handleClose = new Map();\n\n constructor(options: ServerVaultOptions = {}) {\n this.vault = new Vault();\n this.ws = new WebSocketServer({ noServer: true });\n\n this.ws.on(\"connection\", this.setupWebSocket);\n\n this.pingInterval = setInterval(() => {\n this.ws.clients.forEach((socket) => {\n if ((socket as any).isAlive === false) {\n return socket.terminate();\n }\n\n (socket as any).isAlive = false;\n socket.ping();\n });\n }, options.pingTimeout || 30000);\n\n this.ws.on(\"close\", () => {\n clearInterval(this.pingInterval);\n\n if (options.onClose) {\n options.onClose();\n }\n });\n\n this.ws.on(\"error\", (err) => {\n // @todo error handling.\n });\n }\n\n async close() {\n clearTimeout(this.pingInterval);\n\n return new Promise<void>((resolve, error) => {\n this.ws.close((err) => {\n if (err) {\n error(err);\n }\n resolve();\n });\n });\n }\n\n setupWebSocket = (socket: WebSocket.WebSocket) => {\n socket.isAlive = true;\n socket.on(\"pong\", () => {\n socket.isAlive = true;\n });\n socket.on(\"open\", this.handleOpen(socket));\n socket.on(\"message\", this.handleMessage(socket));\n socket.on(\"close\", this.handleClose(socket));\n // Send the initial state to the client.\n socket.send(this.createMessage(\"init-response\", { data: this.vault.getState() }));\n };\n\n handleMessage = (socket: WebSocket) => {\n if (this._handleMessage.has(socket)) {\n return this._handleMessage.get(socket);\n }\n const handler = (data: RawData, isBinary: boolean) => {\n const parsed: ClientAction = JSON.parse(data.toString());\n\n if (parsed._type === \"init-request\") {\n socket.send(this.createMessage(\"init-response\", { data: this.vault.getState() }));\n }\n\n if (parsed._type === \"vault-action\") {\n try {\n this.vault.dispatch(parsed.action);\n } catch (e) {\n // @todo error handling.\n socket.send(\n this.createMessage(\"vault-action-rejection\", {\n action: parsed._id,\n })\n );\n return;\n }\n\n this.lastActionId = parsed._id;\n this.rebroadcast(socket, data, parsed, isBinary);\n }\n };\n\n this._handleMessage.set(socket, handler);\n\n return handler;\n };\n\n send = (data: RawData) => {\n this.ws.clients.forEach(function each(client) {\n if (client.readyState === WebSocket.OPEN) {\n client.send(data, { binary: true });\n }\n });\n };\n\n rebroadcast = (source: WebSocket, data: RawData, action: RemoteAction, isBinary = true) => {\n this.ws.clients.forEach((client) => {\n if (client !== source && client.readyState === WebSocket.OPEN) {\n client.send(data, { binary: isBinary });\n } else {\n client.send(\n this.createMessage(\"vault-action-confirmation\", {\n action: action._id,\n })\n );\n }\n });\n };\n\n handleOpen = (socket: WebSocket) => {\n if (this._handleOpen.has(socket)) {\n return this._handleOpen.get(socket);\n }\n const handler = () => {\n // Handle open.\n };\n\n this._handleOpen.set(socket, handler);\n\n return handler;\n };\n\n handleClose = (socket: WebSocket) => {\n if (this._handleClose.has(socket)) {\n return this._handleClose.get(socket);\n }\n const handler = () => {\n // Close handler.\n };\n\n this._handleClose.set(socket, handler);\n\n return handler;\n };\n\n createMessage = (type: string, message: any) => {\n return JSON.stringify({\n _id: v4(),\n _type: type,\n _lastActionId: this.lastActionId,\n ...message,\n });\n };\n}\n","import { createServer, IncomingMessage, Server } from \"http\";\nimport { Socket } from \"net\";\nimport { ServerVault } from \"./server-vault\";\n\nexport class MultiVaultServer {\n server: Server;\n vaults: Map<string, ServerVault> = new Map();\n constructor(server?: Server) {\n this.server = server || createServer();\n this.server.on(\"upgrade\", this.handleUpgrade);\n this.server.on(\"request\", this.handleRequest);\n }\n\n listen(port: number, hostname?: string, backlog?: number, listeningListener?: () => void) {\n this.server.listen(port, hostname, backlog, listeningListener);\n }\n\n handleRequest = (request: IncomingMessage, response: any) => {\n if (request.url === \"/vault\") {\n // Need to respond with a JSON body with a list of available vaults.\n const vaults = Array.from(this.vaults.keys());\n const json = JSON.stringify({ vaults });\n\n response.writeHead(200, {\n \"Content-Length\": Buffer.byteLength(json),\n \"Content-Type\": \"application/json\",\n });\n response.write(json);\n response.end();\n return;\n }\n\n // If the pathname is not recognised, destroy the socket and send 404.\n response.writeHead(404);\n response.end();\n };\n\n handleUpgrade = (request: IncomingMessage, socket: Socket, head: Buffer) => {\n console.log(\"ws.url\", request.url);\n const pathname = request.url;\n\n // @todo some logic for handling the pathname. For now, just let any incoming be an ID.\n if (pathname && (pathname as string).startsWith(\"/vault\")) {\n // Get the vault ID from the URL.\n const vaultId = (pathname as string).replace(\"/vault/\", \"\");\n\n let vault = this.vaults.get(vaultId);\n\n // If no vault exists for this ID, create one.\n if (!vault) {\n const newVault = new ServerVault();\n console.log(\"new vault\", vaultId);\n this.vaults.set(vaultId, newVault);\n vault = newVault;\n }\n\n if (vault) {\n const theVault = vault;\n // If it exists, add the socket to the vault.\n theVault.ws.handleUpgrade(request, socket, head, (ws) => {\n console.log(\"new client\", vaultId);\n theVault.ws.emit(\"connection\", ws, request);\n theVault.ws.on(\"close\", () => {\n if (theVault.ws.clients.size === 0) {\n console.log(\"destroying vault\", vaultId);\n this.vaults.delete(vaultId);\n }\n });\n });\n } else {\n socket.destroy();\n }\n return;\n }\n\n // If the pathname is not recognised, destroy the socket and send 404.\n socket.write(\"HTTP/1.1 404 Not Found\\r\\n\\r\\n\");\n socket.destroy();\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/server-vault.ts","../src/server.ts"],"sourcesContent":["// Server vault.\nimport { AllActions, IIIFStore, Vault } from \"@iiif/helpers/vault\";\nimport { BatchAction } from \"@iiif/helpers/vault/actions\";\nimport { Collection, Manifest } from \"@iiif/presentation-3\";\nimport WebSocket, { RawData, WebSocketServer } from \"ws\";\nimport { v4 } from \"uuid\";\nimport { clearInterval, setInterval } from \"timers\";\n\ntype RemoteAction = {\n _id: string;\n _type: \"vault-action\";\n _lastActionId: string;\n action: AllActions | BatchAction;\n};\n\nconst GenesisId = \"@genesis\";\n\ntype ClientInitAction = {\n _id: string;\n _type: \"init-response\";\n _lastActionId: string;\n data: IIIFStore;\n};\n\ntype ClientInitRequestAction = {\n _type: \"init-request\";\n};\n\ntype RemoteActionConfirmation = {\n _id: string;\n _type: \"vault-action-confirmation\";\n _lastActionId: string;\n action: string;\n};\n\ntype RemoteActionRejection = {\n _id: string;\n _type: \"vault-action-rejection\";\n _lastActionId: string;\n action: string;\n};\n\ntype InitialiseWithResourceAction = {\n _id: string;\n _type: \"initialise-with-resource\";\n _lastActionId: string;\n resource: Collection | Manifest;\n};\n\ntype EmptyVaultResponse = {\n _id: string;\n _type: \"empty-vault-response\";\n _lastActionId: string;\n};\n\nexport type ClientAction = RemoteAction | ClientInitRequestAction | InitialiseWithResourceAction;\n\nexport type ServerAction =\n | RemoteAction\n | RemoteActionConfirmation\n | RemoteActionRejection\n | ClientInitAction\n | EmptyVaultResponse;\n\n// Extend ws module interface WebSocket.WebSocket with custom typescript property\ndeclare module \"ws\" {\n interface WebSocket {\n isAlive: boolean;\n }\n}\n\nexport interface ServerVaultOptions {\n pingTimeout?: number;\n onClose?: () => void;\n}\n\nexport class ServerVault {\n vault: Vault;\n ws: WebSocketServer;\n lastActionId: string = GenesisId;\n pingInterval: NodeJS.Timeout;\n\n private _handleMessage = new Map();\n private _handleOpen = new Map();\n private _handleClose = new Map();\n\n constructor(options: ServerVaultOptions = {}) {\n this.vault = new Vault();\n this.ws = new WebSocketServer({ noServer: true });\n\n this.ws.on(\"connection\", this.setupWebSocket);\n\n this.pingInterval = setInterval(() => {\n this.ws.clients.forEach((socket) => {\n if ((socket as any).isAlive === false) {\n return socket.terminate();\n }\n\n (socket as any).isAlive = false;\n socket.ping();\n });\n }, options.pingTimeout || 30000);\n\n this.ws.on(\"close\", () => {\n clearInterval(this.pingInterval);\n\n if (options.onClose) {\n options.onClose();\n }\n });\n\n this.ws.on(\"error\", (err) => {\n // @todo error handling.\n });\n }\n\n async close() {\n clearTimeout(this.pingInterval);\n\n return new Promise<void>((resolve, error) => {\n this.ws.close((err) => {\n if (err) {\n error(err);\n }\n resolve();\n });\n });\n }\n\n setupWebSocket = (socket: WebSocket.WebSocket) => {\n socket.isAlive = true;\n socket.on(\"pong\", () => {\n socket.isAlive = true;\n });\n socket.on(\"open\", this.handleOpen(socket));\n socket.on(\"message\", this.handleMessage(socket));\n socket.on(\"close\", this.handleClose(socket));\n // Send the initial state to the client.\n socket.send(this.createMessage(\"init-response\", { data: this.vault.getState() }));\n };\n\n handleMessage = (socket: WebSocket) => {\n if (this._handleMessage.has(socket)) {\n return this._handleMessage.get(socket);\n }\n const handler = (data: RawData, isBinary: boolean) => {\n const parsed: ClientAction = JSON.parse(data.toString());\n\n if (parsed._type === \"init-request\") {\n socket.send(this.createMessage(\"init-response\", { data: this.vault.getState() }));\n }\n\n if (parsed._type === \"vault-action\") {\n try {\n this.vault.dispatch(parsed.action);\n } catch (e) {\n // @todo error handling.\n socket.send(\n this.createMessage(\"vault-action-rejection\", {\n action: parsed._id,\n })\n );\n return;\n }\n\n this.lastActionId = parsed._id;\n this.rebroadcast(socket, data, parsed, isBinary);\n }\n };\n\n this._handleMessage.set(socket, handler);\n\n return handler;\n };\n\n send = (data: RawData) => {\n this.ws.clients.forEach(function each(client) {\n if (client.readyState === WebSocket.OPEN) {\n client.send(data, { binary: true });\n }\n });\n };\n\n rebroadcast = (source: WebSocket, data: RawData, action: RemoteAction, isBinary = true) => {\n this.ws.clients.forEach((client) => {\n if (client !== source && client.readyState === WebSocket.OPEN) {\n client.send(data, { binary: isBinary });\n } else {\n client.send(\n this.createMessage(\"vault-action-confirmation\", {\n action: action._id,\n })\n );\n }\n });\n };\n\n handleOpen = (socket: WebSocket) => {\n if (this._handleOpen.has(socket)) {\n return this._handleOpen.get(socket);\n }\n const handler = () => {\n // Handle open.\n };\n\n this._handleOpen.set(socket, handler);\n\n return handler;\n };\n\n handleClose = (socket: WebSocket) => {\n if (this._handleClose.has(socket)) {\n return this._handleClose.get(socket);\n }\n const handler = () => {\n // Close handler.\n };\n\n this._handleClose.set(socket, handler);\n\n return handler;\n };\n\n createMessage = (type: string, message: any) => {\n return JSON.stringify({\n _id: v4(),\n _type: type,\n _lastActionId: this.lastActionId,\n ...message,\n });\n };\n}\n","import { createServer, IncomingMessage, Server } from \"http\";\nimport { Socket } from \"net\";\nimport { ServerVault } from \"./server-vault\";\n\nexport class MultiVaultServer {\n server: Server;\n vaults: Map<string, ServerVault> = new Map();\n constructor(server?: Server) {\n this.server = server || createServer();\n this.server.on(\"upgrade\", this.handleUpgrade);\n this.server.on(\"request\", this.handleRequest);\n }\n\n listen(port: number, hostname?: string, backlog?: number, listeningListener?: () => void) {\n this.server.listen(port, hostname, backlog, listeningListener);\n }\n\n handleRequest = (request: IncomingMessage, response: any) => {\n if (request.url === \"/vault\") {\n // Need to respond with a JSON body with a list of available vaults.\n const vaults = Array.from(this.vaults.keys());\n const json = JSON.stringify({ vaults });\n\n response.writeHead(200, {\n \"Content-Length\": Buffer.byteLength(json),\n \"Content-Type\": \"application/json\",\n });\n response.write(json);\n response.end();\n return;\n }\n\n // If the pathname is not recognised, destroy the socket and send 404.\n response.writeHead(404);\n response.end();\n };\n\n handleUpgrade = (request: IncomingMessage, socket: Socket, head: Buffer) => {\n console.log(\"ws.url\", request.url);\n const pathname = request.url;\n\n // @todo some logic for handling the pathname. For now, just let any incoming be an ID.\n if (pathname && (pathname as string).startsWith(\"/vault\")) {\n // Get the vault ID from the URL.\n const vaultId = (pathname as string).replace(\"/vault/\", \"\");\n\n let vault = this.vaults.get(vaultId);\n\n // If no vault exists for this ID, create one.\n if (!vault) {\n const newVault = new ServerVault();\n console.log(\"new vault\", vaultId);\n this.vaults.set(vaultId, newVault);\n vault = newVault;\n }\n\n if (vault) {\n const theVault = vault;\n // If it exists, add the socket to the vault.\n theVault.ws.handleUpgrade(request, socket, head, (ws) => {\n console.log(\"new client\", vaultId);\n theVault.ws.emit(\"connection\", ws, request);\n theVault.ws.on(\"close\", () => {\n if (theVault.ws.clients.size === 0) {\n console.log(\"destroying vault\", vaultId);\n this.vaults.delete(vaultId);\n }\n });\n });\n } else {\n socket.destroy();\n }\n return;\n }\n\n // If the pathname is not recognised, destroy the socket and send 404.\n socket.write(\"HTTP/1.1 404 Not Found\\r\\n\\r\\n\");\n socket.destroy();\n };\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@manifest-editor/server-vault",
3
- "version": "2.1.1-next.0.96fdf30",
3
+ "version": "2.2.0",
4
4
  "type": "module",
5
5
  "bugs": "https://github.com/digirati-co-uk/iiif-manifest-editor/issues",
6
6
  "repository": {
@@ -43,20 +43,19 @@
43
43
  "prepack": "tsdown src/index.ts"
44
44
  },
45
45
  "dependencies": {
46
- "@iiif/helpers": "1.5.7",
46
+ "@iiif/helpers": "1.6.1",
47
47
  "@iiif/presentation-3": "^2.2.3",
48
48
  "uuid": "^9.0.1",
49
49
  "ws": "^8.16.0"
50
50
  },
51
51
  "devDependencies": {
52
- "@repo/eslint-config": "workspace:*",
53
- "@types/node": "^20.11.24",
52
+ "@types/node": "22.20.1",
54
53
  "@types/uuid": "^9.0.8",
55
54
  "@types/ws": "8.5.10",
56
- "tsdown": "0.16.4"
55
+ "tsdown": "0.22.14"
57
56
  },
58
57
  "publishConfig": {
59
58
  "access": "public"
60
59
  },
61
- "gitHead": "96fdf3010c854efc620205ad43a3e361fea56691"
60
+ "gitHead": "9ee7ce32bf7728205e22d852fb80061b86067471"
62
61
  }