@openlv/signaling 0.1.0 → 0.1.1

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.
@@ -1,4 +1,10 @@
1
1
  import type { SignalingProtocol } from "../protocol.js";
2
+ type NtfyAttachment = {
3
+ url: string;
4
+ name: string;
5
+ size: number;
6
+ type: string;
7
+ };
2
8
  export type NtfyMessage = {
3
9
  id: string;
4
10
  time: number;
@@ -6,6 +12,7 @@ export type NtfyMessage = {
6
12
  event: string;
7
13
  topic: string;
8
14
  message: string;
15
+ attachment?: NtfyAttachment;
9
16
  };
10
17
  /**
11
18
  * Ntfy Signaling Layer
@@ -24,3 +31,4 @@ export type NtfyMessage = {
24
31
  * https://openlv.sh/api/signaling/ntfy
25
32
  */
26
33
  export declare const ntfy: SignalingProtocol;
34
+ export {};
@@ -62,7 +62,16 @@ export const ntfy = ({ topic, url }) => {
62
62
  resolve();
63
63
  }
64
64
  else if (data.event === "message" && typeof data.message === "string") {
65
- events.emit("message", data.message);
65
+ ((async () => {
66
+ if (data.attachment) {
67
+ const response = await fetch(data.attachment.url);
68
+ const text = await response.text();
69
+ events.emit("message", text);
70
+ }
71
+ else {
72
+ events.emit("message", data.message);
73
+ }
74
+ })());
66
75
  }
67
76
  });
68
77
  });
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ntfy/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { EventEmitter } from \"eventemitter3\";\nimport { match } from \"ts-pattern\";\n\nimport { createSignalingLayer } from \"../index.js\";\nimport type { SignalingProtocol } from \"../protocol.js\";\nimport { log } from \"../utils/log.js\";\nimport { parseNtfyUrl } from \"./url.js\";\n\nexport type NtfyMessage = {\n // eslint-disable-next-line no-restricted-syntax\n id: string;\n time: number;\n expires: number;\n event: string;\n topic: string;\n message: string;\n};\n\n/**\n * Ntfy Signaling Layer\n *\n * Uses HTTP Post for publishing\n * Uses WebSocket for subscribing\n *\n * URL format supports the ?auth= parameter\n * example: https://ntfy.sh/mytopic?auth=mytoken\n *\n * The same goes for apprise ntfy urls\n * example: ntfy://{token}@{hostname}/{topic}\n * example: ntfy://{user}:{password}@{hostname}/{topic}\n * https variant: ntfys://{user}:{password}@{hostname}/{topic}\n *\n * https://openlv.sh/api/signaling/ntfy\n */\nexport const ntfy: SignalingProtocol = ({ topic, url }) => {\n let connection: WebSocket | undefined;\n const connectionInfo = parseNtfyUrl(url || \"https://ntfy.sh\");\n const wsProtocol = match(connectionInfo.protocol)\n .with(\"https\", () => \"wss\")\n .with(\"http\", () => \"ws\")\n .exhaustive();\n const events = new EventEmitter<{ message: string; }>();\n\n return createSignalingLayer({\n type: \"ntfy\",\n async setup() {\n log(\"NTFY: Setting up\");\n\n const wsUrl\n = wsProtocol\n + \"://\"\n + connectionInfo.host\n + \"/\"\n + topic\n + \"/ws\"\n + (connectionInfo.parameters || \"\");\n\n log(\"NTFY: Connecting to WebSocket\", wsUrl);\n connection = new WebSocket(wsUrl);\n\n // Resolves once the server confirms the subscription (\"open\" event);\n // rejects on socket error/close so setup cannot hang forever.\n await new Promise<void>((resolve, reject) => {\n connection!.addEventListener(\"error\", () => {\n reject(new Error(`NTFY: WebSocket error connecting to ${connectionInfo.host}`));\n });\n\n connection!.addEventListener(\"close\", () => {\n reject(new Error(\"NTFY: WebSocket closed before subscription was confirmed\"));\n });\n\n connection!.addEventListener(\"message\", (event) => {\n let data: NtfyMessage;\n\n try {\n data = JSON.parse(event.data) as NtfyMessage;\n }\n catch {\n log(\"NTFY: Dropping non-JSON frame\");\n\n return;\n }\n\n if (data.event === \"open\") {\n resolve();\n }\n else if (data.event === \"message\" && typeof data.message === \"string\") {\n events.emit(\"message\", data.message);\n }\n });\n });\n },\n teardown() {\n connection?.close();\n },\n async publish(body) {\n const headers = { \"Content-Type\": \"application/json\" } as HeadersInit;\n\n const response = await fetch(\n `${connectionInfo.protocol}://${connectionInfo.host}/${topic}`,\n { method: \"POST\", body, headers },\n );\n\n if (!response.ok) {\n throw new Error(`NTFY: publish failed with status ${response.status}`);\n }\n },\n subscribe: (handler) => {\n events.on(\"message\", handler);\n },\n });\n};\n\nObject.defineProperty(ntfy, \"__name\", { value: \"ntfy\" });\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ntfy/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { EventEmitter } from \"eventemitter3\";\nimport { match } from \"ts-pattern\";\n\nimport { createSignalingLayer } from \"../index.js\";\nimport type { SignalingProtocol } from \"../protocol.js\";\nimport { log } from \"../utils/log.js\";\nimport { parseNtfyUrl } from \"./url.js\";\n\ntype NtfyAttachment = {\n url: string;\n name: string;\n size: number;\n type: string;\n};\n\nexport type NtfyMessage = {\n // eslint-disable-next-line no-restricted-syntax\n id: string;\n time: number;\n expires: number;\n event: string;\n topic: string;\n message: string;\n attachment?: NtfyAttachment;\n};\n\n/**\n * Ntfy Signaling Layer\n *\n * Uses HTTP Post for publishing\n * Uses WebSocket for subscribing\n *\n * URL format supports the ?auth= parameter\n * example: https://ntfy.sh/mytopic?auth=mytoken\n *\n * The same goes for apprise ntfy urls\n * example: ntfy://{token}@{hostname}/{topic}\n * example: ntfy://{user}:{password}@{hostname}/{topic}\n * https variant: ntfys://{user}:{password}@{hostname}/{topic}\n *\n * https://openlv.sh/api/signaling/ntfy\n */\nexport const ntfy: SignalingProtocol = ({ topic, url }) => {\n let connection: WebSocket | undefined;\n const connectionInfo = parseNtfyUrl(url || \"https://ntfy.sh\");\n const wsProtocol = match(connectionInfo.protocol)\n .with(\"https\", () => \"wss\")\n .with(\"http\", () => \"ws\")\n .exhaustive();\n const events = new EventEmitter<{ message: string; }>();\n\n return createSignalingLayer({\n type: \"ntfy\",\n async setup() {\n log(\"NTFY: Setting up\");\n\n const wsUrl\n = wsProtocol\n + \"://\"\n + connectionInfo.host\n + \"/\"\n + topic\n + \"/ws\"\n + (connectionInfo.parameters || \"\");\n\n log(\"NTFY: Connecting to WebSocket\", wsUrl);\n connection = new WebSocket(wsUrl);\n\n // Resolves once the server confirms the subscription (\"open\" event);\n // rejects on socket error/close so setup cannot hang forever.\n await new Promise<void>((resolve, reject) => {\n connection!.addEventListener(\"error\", () => {\n reject(new Error(`NTFY: WebSocket error connecting to ${connectionInfo.host}`));\n });\n\n connection!.addEventListener(\"close\", () => {\n reject(new Error(\"NTFY: WebSocket closed before subscription was confirmed\"));\n });\n\n connection!.addEventListener(\"message\", (event) => {\n let data: NtfyMessage;\n\n try {\n data = JSON.parse(event.data) as NtfyMessage;\n }\n catch {\n log(\"NTFY: Dropping non-JSON frame\");\n\n return;\n }\n\n if (data.event === \"open\") {\n resolve();\n }\n else if (data.event === \"message\" && typeof data.message === \"string\") {\n ((async () => {\n if (data.attachment) {\n const response = await fetch(data.attachment.url);\n const text = await response.text();\n\n events.emit(\"message\", text);\n }\n else {\n events.emit(\"message\", data.message);\n }\n })());\n }\n });\n });\n },\n teardown() {\n connection?.close();\n },\n async publish(body) {\n const headers = { \"Content-Type\": \"application/json\" } as HeadersInit;\n\n const response = await fetch(\n `${connectionInfo.protocol}://${connectionInfo.host}/${topic}`,\n { method: \"POST\", body, headers },\n );\n\n if (!response.ok) {\n throw new Error(`NTFY: publish failed with status ${response.status}`);\n }\n },\n subscribe: (handler) => {\n events.on(\"message\", handler);\n },\n });\n};\n\nObject.defineProperty(ntfy, \"__name\", { value: \"ntfy\" });\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openlv/signaling",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "keywords": [
5
5
  "open-lavatory"
6
6
  ],