@openlv/signaling 0.1.2 → 0.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/gundb/index.d.ts +3 -0
- package/dist/gundb/index.js +3 -0
- package/dist/gundb/index.js.map +1 -1
- package/dist/handshake.d.ts +20 -0
- package/dist/handshake.js +38 -0
- package/dist/handshake.js.map +1 -0
- package/dist/handshake.test.js +32 -30
- package/dist/handshake.test.js.map +1 -1
- package/dist/index.d.ts +16 -20
- package/dist/index.js +87 -186
- package/dist/index.js.map +1 -1
- package/dist/index.test.js +17 -13
- package/dist/index.test.js.map +1 -1
- package/dist/messages.d.ts +1 -1
- package/dist/messages.js +13 -13
- package/dist/messages.js.map +1 -1
- package/dist/messages.test.js +1 -1
- package/dist/messages.test.js.map +1 -1
- package/dist/mqtt/index.js +5 -1
- package/dist/mqtt/index.js.map +1 -1
- package/dist/ntfy/url.js +1 -1
- package/dist/ntfy/url.js.map +1 -1
- package/dist/ntfy/url.test.js +4 -4
- package/dist/ntfy/url.test.js.map +1 -1
- package/dist/protocol.d.ts +2 -2
- package/dist/protocol.js.map +1 -1
- package/dist/utils/log.d.ts +1 -1
- package/package.json +2 -7
- package/dist/dynamic.d.ts +0 -6
- package/dist/dynamic.js +0 -23
- package/dist/dynamic.js.map +0 -1
package/dist/messages.js
CHANGED
|
@@ -20,7 +20,7 @@ export const validatePeerInfo = (info) => {
|
|
|
20
20
|
return `info.name must be 1-${MAX_TEXT_LENGTH} characters`;
|
|
21
21
|
}
|
|
22
22
|
if (info.icon !== undefined && !isBoundedString(info.icon, MAX_ICON_LENGTH)) {
|
|
23
|
-
return `info.icon must be 1-${MAX_ICON_LENGTH} characters
|
|
23
|
+
return `info.icon must be 1-${MAX_ICON_LENGTH} characters -- use a smaller image or an image URL`;
|
|
24
24
|
}
|
|
25
25
|
return undefined;
|
|
26
26
|
};
|
|
@@ -38,7 +38,7 @@ const parsePeerInfo = (raw) => {
|
|
|
38
38
|
return {
|
|
39
39
|
identity: info["identity"],
|
|
40
40
|
name: info["name"],
|
|
41
|
-
...(info["icon"]
|
|
41
|
+
...(info["icon"] !== undefined && { icon: info["icon"] }),
|
|
42
42
|
};
|
|
43
43
|
};
|
|
44
44
|
export const parseCapabilities = (raw) => {
|
|
@@ -49,7 +49,7 @@ export const parseCapabilities = (raw) => {
|
|
|
49
49
|
if (!Array.isArray(transports)
|
|
50
50
|
|| transports.length === 0
|
|
51
51
|
|| transports.length > MAX_TRANSPORTS
|
|
52
|
-
||
|
|
52
|
+
|| transports.some(transportId => !isBoundedString(transportId, MAX_TRANSPORT_ID_LENGTH))) {
|
|
53
53
|
return undefined;
|
|
54
54
|
}
|
|
55
55
|
if (payload["info"] === undefined)
|
|
@@ -74,34 +74,34 @@ export const parseSignalMessage = (raw) => {
|
|
|
74
74
|
}
|
|
75
75
|
if (typeof parsed !== "object" || parsed === null)
|
|
76
76
|
return undefined;
|
|
77
|
-
const
|
|
78
|
-
switch (
|
|
77
|
+
const message = parsed;
|
|
78
|
+
switch (message["type"]) {
|
|
79
79
|
case "flash": {
|
|
80
|
-
return typeof
|
|
81
|
-
?
|
|
80
|
+
return typeof message["payload"] === "object" && message["payload"] !== null
|
|
81
|
+
? message
|
|
82
82
|
: undefined;
|
|
83
83
|
}
|
|
84
84
|
case "pubkey": {
|
|
85
|
-
const payload =
|
|
85
|
+
const payload = message["payload"];
|
|
86
86
|
return typeof payload === "object"
|
|
87
87
|
&& payload !== null
|
|
88
88
|
&& typeof payload["publicKey"] === "string"
|
|
89
|
-
?
|
|
89
|
+
? message
|
|
90
90
|
: undefined;
|
|
91
91
|
}
|
|
92
92
|
case "capabilities": {
|
|
93
|
-
const capabilities = parseCapabilities(
|
|
93
|
+
const capabilities = parseCapabilities(message["payload"]);
|
|
94
94
|
if (!capabilities)
|
|
95
95
|
return undefined;
|
|
96
96
|
return {
|
|
97
97
|
type: "capabilities",
|
|
98
98
|
payload: capabilities,
|
|
99
|
-
timestamp:
|
|
99
|
+
timestamp: message["timestamp"],
|
|
100
100
|
};
|
|
101
101
|
}
|
|
102
102
|
case "data": {
|
|
103
|
-
return typeof
|
|
104
|
-
?
|
|
103
|
+
return typeof message["payload"] === "object" && message["payload"] !== null
|
|
104
|
+
? message
|
|
105
105
|
: undefined;
|
|
106
106
|
}
|
|
107
107
|
default: {
|
package/dist/messages.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messages.js","sourceRoot":"","sources":["../src/messages.ts"],"names":[],"mappings":"AAsDA,MAAM,cAAc,GAAG,CAAC,CAAC;AACzB,MAAM,uBAAuB,GAAG,EAAE,CAAC;AACnC,MAAM,eAAe,GAAG,GAAG,CAAC;AAE5B,2EAA2E;AAC3E,2EAA2E;AAC3E,qCAAqC;AACrC,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,CAAC;AAEpC,MAAM,eAAe,GAAG,CAAC,KAAc,EAAE,SAAiB,EAAmB,EAAE,CAC7E,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,CAAC,MAAM,IAAI,SAAS,CAAC;AAE7E;;;;;GAKG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,IAAc,EAAsB,EAAE;IACrE,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,QAAQ,EAAE,eAAe,CAAC,EAAE,CAAC;QACrD,OAAO,2BAA2B,eAAe,aAAa,CAAC;IACjE,CAAC;IAED,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,EAAE,eAAe,CAAC,EAAE,CAAC;QACjD,OAAO,uBAAuB,eAAe,aAAa,CAAC;IAC7D,CAAC;IAED,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,EAAE,eAAe,CAAC,EAAE,CAAC;QAC5E,OAAO,uBAAuB,eAAe,
|
|
1
|
+
{"version":3,"file":"messages.js","sourceRoot":"","sources":["../src/messages.ts"],"names":[],"mappings":"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","sourcesContent":["export type SignalMessageBase<T extends string, P> = {\n type: T;\n payload: P;\n timestamp: number;\n};\n\n/**\n * Flash message\n * Sent to initiate handshake by non-host\n */\nexport type SignalMessageFlash = SignalMessageBase<\"flash\", object>;\n\nexport type SignalMessagePubkey = SignalMessageBase<\n \"pubkey\",\n {\n publicKey: string;\n }\n>;\n\n/** Optional self-description shown in the other peer's UI. */\nexport type PeerInfo = {\n /** Reverse-DNS application identifier, e.g. \"com.example.wallet\". */\n identity: string;\n name: string;\n /**\n * A data URI or an image URL. Only size is enforced on the wire -- anyone\n * rendering or fetching it is responsible for sanity-checking it first.\n */\n icon?: string;\n};\n\nexport type PeerCapabilities = {\n /** Supported transport identifiers, in preference order. */\n transports: string[];\n info?: PeerInfo;\n};\n\n/**\n * Completes the handshake: acknowledges the previous step, negotiates the\n * transport, and shares peer metadata in a single packet.\n */\nexport type SignalMessageCapabilities = SignalMessageBase<\n \"capabilities\",\n PeerCapabilities\n>;\n\nexport type SignalMessageData = SignalMessageBase<\"data\", object>;\n\nexport type SignalMessage\n = | SignalMessageFlash\n | SignalMessagePubkey\n | SignalMessageCapabilities\n | SignalMessageData;\n\nconst MAX_TRANSPORTS = 8;\nconst MAX_TRANSPORT_ID_LENGTH = 32;\nconst MAX_TEXT_LENGTH = 128;\n\n// Relay message limits (ntfy in particular) leave little room after base64\n// and encryption overhead; oversized icons would silently fail to deliver,\n// so they are rejected here instead.\nexport const MAX_ICON_LENGTH = 8192;\n\nconst isBoundedString = (value: unknown, maxLength: number): value is string =>\n typeof value === \"string\" && value.length > 0 && value.length <= maxLength;\n\n/**\n * Check outgoing peer info against the wire limits enforced by receivers.\n * Returns a human-readable problem, or undefined when the info is sendable.\n * Senders must use this: a receiver silently drops an oversized packet, which\n * would otherwise surface only as a generic handshake timeout.\n */\nexport const validatePeerInfo = (info: PeerInfo): string | undefined => {\n if (!isBoundedString(info.identity, MAX_TEXT_LENGTH)) {\n return `info.identity must be 1-${MAX_TEXT_LENGTH} characters`;\n }\n\n if (!isBoundedString(info.name, MAX_TEXT_LENGTH)) {\n return `info.name must be 1-${MAX_TEXT_LENGTH} characters`;\n }\n\n if (info.icon !== undefined && !isBoundedString(info.icon, MAX_ICON_LENGTH)) {\n return `info.icon must be 1-${MAX_ICON_LENGTH} characters -- use a smaller image or an image URL`;\n }\n\n return undefined;\n};\n\nconst parsePeerInfo = (raw: unknown): PeerInfo | undefined => {\n if (typeof raw !== \"object\" || raw === null) return undefined;\n\n const info = raw as Record<string, unknown>;\n\n if (!isBoundedString(info[\"identity\"], MAX_TEXT_LENGTH)) return undefined;\n\n if (!isBoundedString(info[\"name\"], MAX_TEXT_LENGTH)) return undefined;\n\n if (info[\"icon\"] !== undefined && !isBoundedString(info[\"icon\"], MAX_ICON_LENGTH)) {\n return undefined;\n }\n\n return {\n identity: info[\"identity\"],\n name: info[\"name\"],\n ...(info[\"icon\"] !== undefined && { icon: info[\"icon\"] }),\n };\n};\n\nexport const parseCapabilities = (raw: unknown): PeerCapabilities | undefined => {\n if (typeof raw !== \"object\" || raw === null) return undefined;\n\n const payload = raw as Record<string, unknown>;\n const transports = payload[\"transports\"];\n\n if (\n !Array.isArray(transports)\n || transports.length === 0\n || transports.length > MAX_TRANSPORTS\n || transports.some(transportId => !isBoundedString(transportId, MAX_TRANSPORT_ID_LENGTH))\n ) {\n return undefined;\n }\n\n if (payload[\"info\"] === undefined) return { transports };\n\n const info = parsePeerInfo(payload[\"info\"]);\n\n if (!info) return undefined;\n\n return { transports, info };\n};\n\n/**\n * Parse and shape-check a decrypted signaling payload. The relay topic is\n * public, so decrypted JSON is still untrusted input: anything that does not\n * match one of the four message shapes is dropped (returns undefined).\n */\nexport const parseSignalMessage = (raw: string): SignalMessage | undefined => {\n let parsed: unknown;\n\n try {\n parsed = JSON.parse(raw);\n }\n catch {\n return undefined;\n }\n\n if (typeof parsed !== \"object\" || parsed === null) return undefined;\n\n const message = parsed as Record<string, unknown>;\n\n switch (message[\"type\"]) {\n case \"flash\": {\n return typeof message[\"payload\"] === \"object\" && message[\"payload\"] !== null\n ? (message as SignalMessageFlash)\n : undefined;\n }\n case \"pubkey\": {\n const payload = message[\"payload\"] as Record<string, unknown> | null;\n\n return typeof payload === \"object\"\n && payload !== null\n && typeof payload[\"publicKey\"] === \"string\"\n ? (message as SignalMessagePubkey)\n : undefined;\n }\n case \"capabilities\": {\n const capabilities = parseCapabilities(message[\"payload\"]);\n\n if (!capabilities) return undefined;\n\n return {\n type: \"capabilities\",\n payload: capabilities,\n timestamp: message[\"timestamp\"] as number,\n };\n }\n case \"data\": {\n return typeof message[\"payload\"] === \"object\" && message[\"payload\"] !== null\n ? (message as SignalMessageData)\n : undefined;\n }\n default: {\n return undefined;\n }\n }\n};\n"]}
|
package/dist/messages.test.js
CHANGED
|
@@ -24,7 +24,7 @@ describe("parseSignalMessage", () => {
|
|
|
24
24
|
timestamp: 1750000000000,
|
|
25
25
|
});
|
|
26
26
|
});
|
|
27
|
-
it("accepts an icon that is a URL
|
|
27
|
+
it("accepts an icon that is a URL -- content vetting is the renderer's job", () => {
|
|
28
28
|
const message = parseSignalMessage(frame("capabilities", {
|
|
29
29
|
transports: ["wrtc"],
|
|
30
30
|
info: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messages.test.js","sourceRoot":"","sources":["../src/messages.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAE9C,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEtF,MAAM,KAAK,GAAG,CAAC,IAAY,EAAE,OAAgB,EAAE,EAAE,CAC/C,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,aAAiB,EAAE,CAAC,CAAC;AAElE,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;IAClC,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;QAChD,MAAM,OAAO,GAAG,kBAAkB,CAChC,KAAK,CAAC,cAAc,EAAE;YACpB,UAAU,EAAE,CAAC,MAAM,EAAE,IAAI,CAAC;YAC1B,IAAI,EAAE;gBACJ,QAAQ,EAAE,oBAAoB;gBAC9B,IAAI,EAAE,gBAAgB;gBACtB,IAAI,EAAE,4BAA4B;aACnC;SACF,CAAC,CACH,CAAC;QAEF,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC;YACtB,IAAI,EAAE,cAAc;YACpB,OAAO,EAAE;gBACP,UAAU,EAAE,CAAC,MAAM,EAAE,IAAI,CAAC;gBAC1B,IAAI,EAAE;oBACJ,QAAQ,EAAE,oBAAoB;oBAC9B,IAAI,EAAE,gBAAgB;oBACtB,IAAI,EAAE,4BAA4B;iBACnC;aACF;YACD,SAAS,EAAE,aAAiB;SAC7B,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"messages.test.js","sourceRoot":"","sources":["../src/messages.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, expect, it } from \"vitest\";\n\nimport { MAX_ICON_LENGTH, parseSignalMessage, validatePeerInfo } from \"./messages.js\";\n\nconst frame = (type: string, payload: unknown) =>\n JSON.stringify({ type, payload, timestamp: 1_750_000_000_000 });\n\ndescribe(\"parseSignalMessage\", () => {\n it(\"parses a capabilities packet with info\", () => {\n const message = parseSignalMessage(\n frame(\"capabilities\", {\n transports: [\"wrtc\", \"ws\"],\n info: {\n identity: \"com.example.wallet\",\n name: \"Example Wallet\",\n icon: \"data:image/png;base64,aaaa\",\n },\n }),\n );\n\n expect(message).toEqual({\n type: \"capabilities\",\n payload: {\n transports: [\"wrtc\", \"ws\"],\n info: {\n identity: \"com.example.wallet\",\n name: \"Example Wallet\",\n icon: \"data:image/png;base64,aaaa\",\n },\n },\n timestamp: 1_750_000_000_000,\n });\n });\n\n it(\"accepts an icon that is a URL -- content vetting is the renderer's job\", () => {\n const message = parseSignalMessage(\n frame(\"capabilities\", {\n transports: [\"wrtc\"],\n info: {\n identity: \"com.example.wallet\",\n name: \"Example Wallet\",\n icon: \"https://example.com/icon.png\",\n },\n }),\n );\n\n expect(message?.payload).toMatchObject({\n info: { icon: \"https://example.com/icon.png\" },\n });\n });\n\n it(\"parses a capabilities packet without info\", () => {\n expect(\n parseSignalMessage(frame(\"capabilities\", { transports: [\"wrtc\"] })),\n ).toMatchObject({ payload: { transports: [\"wrtc\"] } });\n });\n\n it(\"drops unknown extra fields from capabilities payloads\", () => {\n const message = parseSignalMessage(\n frame(\"capabilities\", { transports: [\"wrtc\"], extra: \"field\" }),\n );\n\n expect(message?.payload).toEqual({ transports: [\"wrtc\"] });\n });\n\n it(\"rejects capabilities without transports\", () => {\n expect(parseSignalMessage(frame(\"capabilities\", {}))).toBeUndefined();\n expect(parseSignalMessage(frame(\"capabilities\", { transports: [] }))).toBeUndefined();\n expect(\n parseSignalMessage(frame(\"capabilities\", { transports: [42] })),\n ).toBeUndefined();\n });\n\n it(\"rejects capabilities with malformed info\", () => {\n expect(\n parseSignalMessage(\n frame(\"capabilities\", { transports: [\"wrtc\"], info: { name: \"No identity\" } }),\n ),\n ).toBeUndefined();\n expect(\n parseSignalMessage(\n frame(\"capabilities\", {\n transports: [\"wrtc\"],\n info: {\n identity: \"com.example.wallet\",\n name: \"Example Wallet\",\n icon: \"x\".repeat(10_000),\n },\n }),\n ),\n ).toBeUndefined();\n });\n\n it(\"rejects retired and unknown packet types\", () => {\n expect(parseSignalMessage(frame(\"ack\", undefined))).toBeUndefined();\n expect(parseSignalMessage(frame(\"nonsense\", {}))).toBeUndefined();\n expect(parseSignalMessage(\"not json\")).toBeUndefined();\n });\n\n it(\"validates outgoing peer info with descriptive reasons\", () => {\n expect(validatePeerInfo({ identity: \"com.example.wallet\", name: \"Example Wallet\" }))\n .toBeUndefined();\n expect(validatePeerInfo({\n identity: \"com.example.wallet\",\n name: \"Example Wallet\",\n icon: \"data:image/png;base64,aaaa\",\n })).toBeUndefined();\n expect(validatePeerInfo({ identity: \"\", name: \"Example Wallet\" }))\n .toMatch(/identity/);\n expect(validatePeerInfo({ identity: \"com.example.wallet\", name: \"x\".repeat(200) }))\n .toMatch(/name/);\n expect(validatePeerInfo({\n identity: \"com.example.wallet\",\n name: \"Example Wallet\",\n icon: \"x\".repeat(MAX_ICON_LENGTH + 1),\n })).toMatch(/icon/);\n });\n\n it(\"still parses flash, pubkey, and data\", () => {\n expect(parseSignalMessage(frame(\"flash\", {}))).toMatchObject({ type: \"flash\" });\n expect(\n parseSignalMessage(frame(\"pubkey\", { publicKey: \"abc\" })),\n ).toMatchObject({ type: \"pubkey\" });\n expect(\n parseSignalMessage(frame(\"data\", { anything: true })),\n ).toMatchObject({ type: \"data\" });\n });\n});\n"]}
|
package/dist/mqtt/index.js
CHANGED
|
@@ -21,7 +21,11 @@ export const mqtt = ({ url, topic }) => {
|
|
|
21
21
|
});
|
|
22
22
|
connection.on("error", (error) => {
|
|
23
23
|
log("MQTT: Error connecting to URL", error);
|
|
24
|
-
|
|
24
|
+
// The client reports transport failures as a DOM Event, which
|
|
25
|
+
// stringifies to "[object Event]" and reaches the user's screen.
|
|
26
|
+
reject(error instanceof Error
|
|
27
|
+
? error
|
|
28
|
+
: new Error(`MQTT: could not connect to ${endpoint}`));
|
|
25
29
|
});
|
|
26
30
|
connection.on("close", () => {
|
|
27
31
|
reject(new Error("MQTT: Closed connection to URL"));
|
package/dist/mqtt/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/mqtt/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAmB,MAAM,gBAAgB,CAAC;AAE7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAEnD,OAAO,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AAEtC;;;;GAIG;AACH,MAAM,CAAC,MAAM,IAAI,GAAsB,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE;IACxD,+DAA+D;IAC/D,MAAM,QAAQ,GAAG,GAAG,IAAI,oCAAoC,CAAC;IAC7D,IAAI,UAAkC,CAAC;IAEvC,OAAO,oBAAoB,CAAC;QAC1B,IAAI,EAAE,MAAM;QACZ,KAAK;YACH,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gBACrC,UAAU,GAAG,UAAU,CAAC,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC;gBAE3C,UAAU,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE;oBAC5B,OAAO,EAAE,CAAC;gBACZ,CAAC,CAAC,CAAC;gBACH,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;oBAC/B,GAAG,CAAC,+BAA+B,EAAE,KAAK,CAAC,CAAC;oBAC5C,MAAM,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/mqtt/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAmB,MAAM,gBAAgB,CAAC;AAE7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAEnD,OAAO,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AAEtC;;;;GAIG;AACH,MAAM,CAAC,MAAM,IAAI,GAAsB,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE;IACxD,+DAA+D;IAC/D,MAAM,QAAQ,GAAG,GAAG,IAAI,oCAAoC,CAAC;IAC7D,IAAI,UAAkC,CAAC;IAEvC,OAAO,oBAAoB,CAAC;QAC1B,IAAI,EAAE,MAAM;QACZ,KAAK;YACH,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gBACrC,UAAU,GAAG,UAAU,CAAC,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC;gBAE3C,UAAU,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE;oBAC5B,OAAO,EAAE,CAAC;gBACZ,CAAC,CAAC,CAAC;gBACH,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;oBAC/B,GAAG,CAAC,+BAA+B,EAAE,KAAK,CAAC,CAAC;oBAC5C,8DAA8D;oBAC9D,iEAAiE;oBACjE,MAAM,CACJ,KAAK,YAAY,KAAK;wBACpB,CAAC,CAAC,KAAK;wBACP,CAAC,CAAC,IAAI,KAAK,CAAC,8BAA8B,QAAQ,EAAE,CAAC,CACxD,CAAC;gBACJ,CAAC,CAAC,CAAC;gBAEH,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;oBAC1B,MAAM,CAAC,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC,CAAC;gBACtD,CAAC,CAAC,CAAC;gBAEH,UAAU,CAAC,OAAO,EAAE,CAAC;YACvB,CAAC,CAAC,CAAC;QACL,CAAC;QACD,QAAQ;YACN,UAAU,EAAE,KAAK,EAAE,CAAC;YACpB,UAAU,GAAG,SAAS,CAAC;QACzB,CAAC;QACD,KAAK,CAAC,OAAO,CAAC,OAAO;YACnB,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;YACvD,CAAC;YAED,UAAU,EAAE,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;QACzD,CAAC;QACD,KAAK,CAAC,SAAS,CAAC,OAAO;YACrB,IAAI,CAAC,UAAU;gBAAE,MAAM,IAAI,uBAAuB,EAAE,CAAC;YAErD,GAAG,CAAC,4BAA4B,EAAE,KAAK,CAAC,CAAC;YAEzC,UAAU,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,aAAa,EAAE,OAAO,EAAE,EAAE;gBAClD,GAAG,CAAC,iCAAiC,EAAE,KAAK,CAAC,CAAC;gBAE9C,IAAI,aAAa,KAAK,KAAK;oBAAE,OAAO;gBAEpC,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;gBAElD,OAAO,CAAC,OAAO,CAAC,CAAC;YACnB,CAAC,CAAC,CAAC;YAEH,MAAM,UAAU,EAAE,SAAS,CAAC,KAAK,CAAC,CAAC;QACrC,CAAC;KACF,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC","sourcesContent":["import { SignalNoConnectionError } from \"@openlv/core/errors\";\nimport { createMqtt, type MqttClient } from \"websocket-mqtt\";\n\nimport { createSignalingLayer } from \"../index.js\";\nimport type { SignalingProtocol } from \"../protocol.js\";\nimport { log } from \"../utils/log.js\";\n\n/**\n * MQTT Signaling Layer\n *\n * https://openlv.sh/api/signaling/mqtt\n */\nexport const mqtt: SignalingProtocol = ({ url, topic }) => {\n // `url` may be an empty string when the session URI omits `s`.\n const endpoint = url || \"wss://test.mosquitto.org:8081/mqtt\";\n let connection: MqttClient | undefined;\n\n return createSignalingLayer({\n type: \"mqtt\",\n setup() {\n return new Promise((resolve, reject) => {\n connection = createMqtt({ url: endpoint });\n\n connection.on(\"connect\", () => {\n resolve();\n });\n connection.on(\"error\", (error) => {\n log(\"MQTT: Error connecting to URL\", error);\n // The client reports transport failures as a DOM Event, which\n // stringifies to \"[object Event]\" and reaches the user's screen.\n reject(\n error instanceof Error\n ? error\n : new Error(`MQTT: could not connect to ${endpoint}`),\n );\n });\n\n connection.on(\"close\", () => {\n reject(new Error(\"MQTT: Closed connection to URL\"));\n });\n\n connection.connect();\n });\n },\n teardown() {\n connection?.close();\n connection = undefined;\n },\n async publish(payload) {\n if (!connection) {\n throw new Error(\"MQTT: No connection to publish to\");\n }\n\n connection?.publish(topic, payload, { retain: false });\n },\n async subscribe(handler) {\n if (!connection) throw new SignalNoConnectionError();\n\n log(\"MQTT: Subscribing to topic\", topic);\n\n connection.on(\"message\", (receivedTopic, message) => {\n log(\"MQTT: Received message on topic\", topic);\n\n if (receivedTopic !== topic) return;\n\n const decoded = new TextDecoder().decode(message);\n\n handler(decoded);\n });\n\n await connection?.subscribe(topic);\n },\n });\n};\n\nObject.defineProperty(mqtt, \"__name\", { value: \"mqtt\" });\n"]}
|
package/dist/ntfy/url.js
CHANGED
|
@@ -2,7 +2,7 @@ export const NTFY_URL_REGEX = /^(?<protocol>https?|ntfys?):\/\/(?:(?:(?<user>[^:
|
|
|
2
2
|
/*
|
|
3
3
|
* URL format supports the ?auth= parameter
|
|
4
4
|
* example: https://ntfy.sh/?auth=mytoken
|
|
5
|
-
* example:
|
|
5
|
+
* example: https://authtoken123@myserver.example.com/
|
|
6
6
|
*
|
|
7
7
|
* The same goes for apprise ntfy urls
|
|
8
8
|
* example: ntfy://{token}@{host}/
|
package/dist/ntfy/url.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"url.js","sourceRoot":"","sources":["../../src/ntfy/url.ts"],"names":[],"mappings":"AAYA,MAAM,CAAC,MAAM,cAAc,GACvB,oHAAoH,CAAC;AAEzH;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,GAAW,EAAW,EAAE;IACnD,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;IAExC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,qBAAqB,GAAG,EAAE,CAAC,CAAC;IAC9C,CAAC;IAED,MAAM,EACJ,QAAQ,EAAE,YAAY,EACtB,IAAI,EACJ,QAAQ,EACR,IAAI,EACJ,UAAU,GACX,GAAG,KAAK,CAAC,MAAM,IAAI,EAAE,CAAC;IAEvB,qBAAqB;IACrB,IAAI,QAA0B,CAAC;IAE/B,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;QAC5C,QAAQ,GAAG,MAAM,CAAC;IACpB,CAAC;SACI,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;QACnD,QAAQ,GAAG,OAAO,CAAC;IACrB,CAAC;SACI,CAAC;QACJ,MAAM,IAAI,KAAK,CAAC,qBAAqB,GAAG,EAAE,CAAC,CAAC;IAC9C,CAAC;IAED,MAAM,WAAW,GAAG,IAAI;QACtB,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE;QACpB,CAAC,CAAC,CAAC,QAAQ;YACP,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE;YACrB,CAAC,CAAC,SAAS,CAAC,CAAC;IAEnB,OAAO;QACL,IAAI;QACJ,QAAQ;QACR,WAAW;QACX,UAAU,EAAE,UAAU,IAAI,SAAS;KACpC,CAAC;AACJ,CAAC,CAAC","sourcesContent":["export type NtfyUrl = {\n host: string;\n protocol: \"http\" | \"https\";\n credentials?:\n | {\n user: string;\n password: string;\n }\n | { token: string; };\n parameters?: string;\n};\n\nexport const NTFY_URL_REGEX\n = /^(?<protocol>https?|ntfys?):\\/\\/(?:(?:(?<user>[^:@]+):)?(?<password>[^@]+)?@)?(?<host>[^/?]+)\\/?(?<parameters>.*)$/;\n\n/*\n * URL format supports the ?auth= parameter\n * example: https://ntfy.sh/?auth=mytoken\n * example:
|
|
1
|
+
{"version":3,"file":"url.js","sourceRoot":"","sources":["../../src/ntfy/url.ts"],"names":[],"mappings":"AAYA,MAAM,CAAC,MAAM,cAAc,GACvB,oHAAoH,CAAC;AAEzH;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,GAAW,EAAW,EAAE;IACnD,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;IAExC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,qBAAqB,GAAG,EAAE,CAAC,CAAC;IAC9C,CAAC;IAED,MAAM,EACJ,QAAQ,EAAE,YAAY,EACtB,IAAI,EACJ,QAAQ,EACR,IAAI,EACJ,UAAU,GACX,GAAG,KAAK,CAAC,MAAM,IAAI,EAAE,CAAC;IAEvB,qBAAqB;IACrB,IAAI,QAA0B,CAAC;IAE/B,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;QAC5C,QAAQ,GAAG,MAAM,CAAC;IACpB,CAAC;SACI,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;QACnD,QAAQ,GAAG,OAAO,CAAC;IACrB,CAAC;SACI,CAAC;QACJ,MAAM,IAAI,KAAK,CAAC,qBAAqB,GAAG,EAAE,CAAC,CAAC;IAC9C,CAAC;IAED,MAAM,WAAW,GAAG,IAAI;QACtB,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE;QACpB,CAAC,CAAC,CAAC,QAAQ;YACP,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE;YACrB,CAAC,CAAC,SAAS,CAAC,CAAC;IAEnB,OAAO;QACL,IAAI;QACJ,QAAQ;QACR,WAAW;QACX,UAAU,EAAE,UAAU,IAAI,SAAS;KACpC,CAAC;AACJ,CAAC,CAAC","sourcesContent":["export type NtfyUrl = {\n host: string;\n protocol: \"http\" | \"https\";\n credentials?:\n | {\n user: string;\n password: string;\n }\n | { token: string; };\n parameters?: string;\n};\n\nexport const NTFY_URL_REGEX\n = /^(?<protocol>https?|ntfys?):\\/\\/(?:(?:(?<user>[^:@]+):)?(?<password>[^@]+)?@)?(?<host>[^/?]+)\\/?(?<parameters>.*)$/;\n\n/*\n * URL format supports the ?auth= parameter\n * example: https://ntfy.sh/?auth=mytoken\n * example: https://authtoken123@myserver.example.com/\n *\n * The same goes for apprise ntfy urls\n * example: ntfy://{token}@{host}/\n * example: ntfy://{user}:{password}@{host}/\n * https variant: ntfys://{user}:{password}@{host}/\n */\nexport const parseNtfyUrl = (url: string): NtfyUrl => {\n const match = url.match(NTFY_URL_REGEX);\n\n if (!match) {\n throw new Error(`Invalid NTFY URL: ${url}`);\n }\n\n const {\n protocol: protocolType,\n user,\n password,\n host,\n parameters,\n } = match.groups || {};\n\n // Determine protocol\n let protocol: \"http\" | \"https\";\n\n if ([\"http\", \"ntfy\"].includes(protocolType)) {\n protocol = \"http\";\n }\n else if ([\"https\", \"ntfys\"].includes(protocolType)) {\n protocol = \"https\";\n }\n else {\n throw new Error(`Invalid NTFY URL: ${url}`);\n }\n\n const credentials = user\n ? { user, password }\n : (password\n ? { token: password }\n : undefined);\n\n return {\n host,\n protocol,\n credentials,\n parameters: parameters || undefined,\n };\n};\n"]}
|
package/dist/ntfy/url.test.js
CHANGED
|
@@ -10,10 +10,10 @@ const testCases = [
|
|
|
10
10
|
},
|
|
11
11
|
},
|
|
12
12
|
{
|
|
13
|
-
url: "
|
|
13
|
+
url: "https://ntfy.sh/?auth=mytoken2",
|
|
14
14
|
expected: {
|
|
15
15
|
host: "ntfy.sh",
|
|
16
|
-
protocol: "
|
|
16
|
+
protocol: "https",
|
|
17
17
|
parameters: "?auth=mytoken2",
|
|
18
18
|
},
|
|
19
19
|
},
|
|
@@ -44,11 +44,11 @@ const testCases = [
|
|
|
44
44
|
},
|
|
45
45
|
];
|
|
46
46
|
describe("should parse NTFY URL", () => {
|
|
47
|
-
|
|
47
|
+
for (const testCase of testCases) {
|
|
48
48
|
it(`should parse NTFY URL ${testCase.url}`, () => {
|
|
49
49
|
const result = parseNtfyUrl(testCase.url);
|
|
50
50
|
expect(result).toEqual(testCase.expected);
|
|
51
51
|
});
|
|
52
|
-
}
|
|
52
|
+
}
|
|
53
53
|
});
|
|
54
54
|
//# sourceMappingURL=url.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"url.test.js","sourceRoot":"","sources":["../../src/ntfy/url.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAE9C,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAExC,MAAM,SAAS,GAAG;IAChB;QACE,GAAG,EAAE,gCAAgC;QACrC,QAAQ,EAAE;YACR,IAAI,EAAE,SAAS;YACf,QAAQ,EAAE,OAAO;YACjB,UAAU,EAAE,gBAAgB;SAC7B;KACF;IACD;QACE,GAAG,EAAE
|
|
1
|
+
{"version":3,"file":"url.test.js","sourceRoot":"","sources":["../../src/ntfy/url.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAE9C,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAExC,MAAM,SAAS,GAAG;IAChB;QACE,GAAG,EAAE,gCAAgC;QACrC,QAAQ,EAAE;YACR,IAAI,EAAE,SAAS;YACf,QAAQ,EAAE,OAAO;YACjB,UAAU,EAAE,gBAAgB;SAC7B;KACF;IACD;QACE,GAAG,EAAE,gCAAgC;QACrC,QAAQ,EAAE;YACR,IAAI,EAAE,SAAS;YACf,QAAQ,EAAE,OAAO;YACjB,UAAU,EAAE,gBAAgB;SAC7B;KACF;IACD;QACE,GAAG,EAAE,4BAA4B;QACjC,QAAQ,EAAE;YACR,IAAI,EAAE,aAAa;YACnB,QAAQ,EAAE,MAAM;YAChB,WAAW,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE;SAClC;KACF;IACD;QACE,GAAG,EAAE,oCAAoC;QACzC,QAAQ,EAAE;YACR,IAAI,EAAE,SAAS;YACf,QAAQ,EAAE,OAAO;YACjB,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE;SACxD;KACF;IACD;QACE,GAAG,EAAE,sCAAsC;QAC3C,QAAQ,EAAE;YACR,IAAI,EAAE,SAAS;YACf,QAAQ,EAAE,MAAM;YAChB,WAAW,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE;YACjC,UAAU,EAAE,eAAe;SAC5B;KACF;CACF,CAAC;AAEF,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;IACrC,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,EAAE,CAAC,yBAAyB,QAAQ,CAAC,GAAG,EAAE,EAAE,GAAG,EAAE;YAC/C,MAAM,MAAM,GAAG,YAAY,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;YAE1C,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAC5C,CAAC,CAAC,CAAC;IACL,CAAC;AACH,CAAC,CAAC,CAAC","sourcesContent":["import { describe, expect, it } from \"vitest\";\n\nimport { parseNtfyUrl } from \"./url.js\";\n\nconst testCases = [\n {\n url: \"https://ntfy.sh/?auth=mytoken1\",\n expected: {\n host: \"ntfy.sh\",\n protocol: \"https\",\n parameters: \"?auth=mytoken1\",\n },\n },\n {\n url: \"https://ntfy.sh/?auth=mytoken2\",\n expected: {\n host: \"ntfy.sh\",\n protocol: \"https\",\n parameters: \"?auth=mytoken2\",\n },\n },\n {\n url: \"ntfy://mytoken@example.com\",\n expected: {\n host: \"example.com\",\n protocol: \"http\",\n credentials: { token: \"mytoken\" },\n },\n },\n {\n url: \"ntfys://myuser:mypassword@ntfy.sh/\",\n expected: {\n host: \"ntfy.sh\",\n protocol: \"https\",\n credentials: { user: \"myuser\", password: \"mypassword\" },\n },\n },\n {\n url: \"ntfy://mytoken@ntfy.sh/?auth=mytoken\",\n expected: {\n host: \"ntfy.sh\",\n protocol: \"http\",\n credentials: { token: \"mytoken\" },\n parameters: \"?auth=mytoken\",\n },\n },\n];\n\ndescribe(\"should parse NTFY URL\", () => {\n for (const testCase of testCases) {\n it(`should parse NTFY URL ${testCase.url}`, () => {\n const result = parseNtfyUrl(testCase.url);\n\n expect(result).toEqual(testCase.expected);\n });\n }\n});\n"]}
|
package/dist/protocol.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { MaybePromise } from "viem";
|
|
2
|
-
import type {
|
|
2
|
+
import type { SignalingLayerFunction } from "./index.js";
|
|
3
3
|
export type SignalingChannel = {
|
|
4
4
|
type: string;
|
|
5
5
|
setup: () => MaybePromise<void>;
|
|
@@ -11,4 +11,4 @@ export type SignalingProtocolOptions = {
|
|
|
11
11
|
topic: string;
|
|
12
12
|
url: string;
|
|
13
13
|
};
|
|
14
|
-
export type SignalingProtocol = (properties: SignalingProtocolOptions) => MaybePromise<
|
|
14
|
+
export type SignalingProtocol = (properties: SignalingProtocolOptions) => MaybePromise<SignalingLayerFunction>;
|
package/dist/protocol.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"","sourcesContent":["import type { MaybePromise } from \"viem\";\n\nimport type {
|
|
1
|
+
{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"","sourcesContent":["import type { MaybePromise } from \"viem\";\n\nimport type { SignalingLayerFunction } from \"./index.js\";\n\nexport type SignalingChannel = {\n type: string;\n setup: () => MaybePromise<void>;\n teardown: () => MaybePromise<void>;\n publish: (payload: string) => MaybePromise<void>;\n subscribe: (handler: (payload: string) => void) => MaybePromise<void>;\n};\n\nexport type SignalingProtocolOptions = {\n topic: string;\n url: string;\n};\n\nexport type SignalingProtocol = (\n properties: SignalingProtocolOptions,\n) => MaybePromise<SignalingLayerFunction>;\n"]}
|
package/dist/utils/log.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const log: (...
|
|
1
|
+
export declare const log: (...arguments_: Parameters<typeof console.log>) => void;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openlv/signaling",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"keywords": [
|
|
5
5
|
"open-lavatory"
|
|
6
6
|
],
|
|
@@ -40,11 +40,6 @@
|
|
|
40
40
|
"types": "./dist/gundb/index.d.ts",
|
|
41
41
|
"import": "./dist/gundb/index.js",
|
|
42
42
|
"default": "./dist/gundb/index.js"
|
|
43
|
-
},
|
|
44
|
-
"./dynamic": {
|
|
45
|
-
"types": "./dist/dynamic.d.ts",
|
|
46
|
-
"import": "./dist/dynamic.js",
|
|
47
|
-
"default": "./dist/dynamic.js"
|
|
48
43
|
}
|
|
49
44
|
},
|
|
50
45
|
"main": "./dist/index.js",
|
|
@@ -59,7 +54,7 @@
|
|
|
59
54
|
"gun": "^0.2020.1241",
|
|
60
55
|
"websocket-mqtt": "0.0.7",
|
|
61
56
|
"ts-pattern": "^5",
|
|
62
|
-
"@openlv/core": "0.
|
|
57
|
+
"@openlv/core": "0.2.0"
|
|
63
58
|
},
|
|
64
59
|
"devDependencies": {
|
|
65
60
|
"typescript": "^5",
|
package/dist/dynamic.d.ts
DELETED
package/dist/dynamic.js
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { match } from "ts-pattern";
|
|
2
|
-
/**
|
|
3
|
-
* Imports the signaling layer based on the protocol at runtime
|
|
4
|
-
*
|
|
5
|
-
* TODO: Make this a built-in feature of session/provider
|
|
6
|
-
*/
|
|
7
|
-
export const dynamicSignalingLayer = async (protocol) => match(protocol)
|
|
8
|
-
.with("mqtt", async () => {
|
|
9
|
-
const mod = await import("./mqtt/index.js");
|
|
10
|
-
return mod.mqtt;
|
|
11
|
-
})
|
|
12
|
-
.with("ntfy", async () => {
|
|
13
|
-
const mod = await import("./ntfy/index.js");
|
|
14
|
-
return mod.ntfy;
|
|
15
|
-
})
|
|
16
|
-
.with("gun", async () => {
|
|
17
|
-
const mod = await import("./gundb/index.js");
|
|
18
|
-
return mod.gundb;
|
|
19
|
-
})
|
|
20
|
-
.otherwise(() => {
|
|
21
|
-
throw new Error(`Unknown signaling protocol: ${protocol}`);
|
|
22
|
-
});
|
|
23
|
-
//# sourceMappingURL=dynamic.js.map
|
package/dist/dynamic.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"dynamic.js","sourceRoot":"","sources":["../src/dynamic.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC;;;;GAIG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,KAAK,EAAE,QAAgB,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC;KAC7E,IAAI,CAAC,MAAM,EAAE,KAAK,IAAI,EAAE;IACvB,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,iBAAiB,CAAC,CAAC;IAE5C,OAAO,GAAG,CAAC,IAAI,CAAC;AAClB,CAAC,CAAC;KACD,IAAI,CAAC,MAAM,EAAE,KAAK,IAAI,EAAE;IACvB,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,iBAAiB,CAAC,CAAC;IAE5C,OAAO,GAAG,CAAC,IAAI,CAAC;AAClB,CAAC,CAAC;KACD,IAAI,CAAC,KAAK,EAAE,KAAK,IAAI,EAAE;IACtB,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC;IAE7C,OAAO,GAAG,CAAC,KAAK,CAAC;AACnB,CAAC,CAAC;KACD,SAAS,CAAC,GAAG,EAAE;IACd,MAAM,IAAI,KAAK,CAAC,+BAA+B,QAAQ,EAAE,CAAC,CAAC;AAC7D,CAAC,CAAC,CAAC","sourcesContent":["import { match } from \"ts-pattern\";\n\n/**\n * Imports the signaling layer based on the protocol at runtime\n *\n * TODO: Make this a built-in feature of session/provider\n */\nexport const dynamicSignalingLayer = async (protocol: string) => match(protocol)\n .with(\"mqtt\", async () => {\n const mod = await import(\"./mqtt/index.js\");\n\n return mod.mqtt;\n })\n .with(\"ntfy\", async () => {\n const mod = await import(\"./ntfy/index.js\");\n\n return mod.ntfy;\n })\n .with(\"gun\", async () => {\n const mod = await import(\"./gundb/index.js\");\n\n return mod.gundb;\n })\n .otherwise(() => {\n throw new Error(`Unknown signaling protocol: ${protocol}`);\n });\n"]}
|