@zaflun/lumio-protocol 0.2.4 → 0.9.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/CHANGELOG.md +129 -1
- package/README.md +1 -1
- package/dist/chunk-746VSR4E.js +51 -0
- package/dist/index.d.ts +1409 -12
- package/dist/index.js +729 -9
- package/dist/origin.d.ts +24 -0
- package/dist/origin.js +14 -0
- package/package.json +6 -2
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,134 @@ All notable changes to `@zaflun/lumio-protocol` are documented here.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## 0.9.0
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **Typed event payloads** — `LUMIO_EVENT_PAYLOAD_SCHEMAS` holds one zod
|
|
13
|
+
schema per `LUMIO_EVENT_TYPES` entry for the `data` of an `event.platform`
|
|
14
|
+
notification (the backend's event `raw`; a `ChatMessageInput` for the chat
|
|
15
|
+
types). `LumioEventPayloadMap` / `LumioEventPayload<K>` are the inferred
|
|
16
|
+
types, `ChatMessagePayload` and `ModerationLogPayload` the shared ones.
|
|
17
|
+
`lumioEventPayloadSchema(type)` and `parseLumioEventPayload(type, data)`
|
|
18
|
+
validate a payload. The map is checked with `satisfies` against
|
|
19
|
+
`LumioEventType`, so a new event type without a schema fails typecheck. The
|
|
20
|
+
shapes follow the golden fixtures the backend exports to `fixtures/events/`.
|
|
21
|
+
Object schemas are loose: fields the backend adds later are kept, typed
|
|
22
|
+
`unknown`. The wire format is unchanged.
|
|
23
|
+
|
|
24
|
+
### Changed
|
|
25
|
+
|
|
26
|
+
- **`twitch:gift_sub` is now `twitch:gift`** in `LUMIO_EVENT_TYPES`. The
|
|
27
|
+
backend has always emitted gifted subs as `twitch:gift`, so no event ever
|
|
28
|
+
matched `twitch:gift_sub`. Replace the type in `useLumioEvent()` calls and
|
|
29
|
+
`event()` triggers. Breaking.
|
|
30
|
+
|
|
31
|
+
## 0.8.0
|
|
32
|
+
|
|
33
|
+
### Added
|
|
34
|
+
|
|
35
|
+
- **`SERVER_FUNCTION_ERRORS`** — the JSON-RPC error codes a host answers a
|
|
36
|
+
failed `server.query` / `server.mutation` with (`INVALID_REQUEST`,
|
|
37
|
+
`UNAVAILABLE`, `DENIED`, `UNKNOWN_FUNCTION`, `INVALID_PARAMS`, `FAILED`),
|
|
38
|
+
and the `ServerFunctionErrorCode` type. `ServerQueryParams` /
|
|
39
|
+
`ServerMutationParams` document their results: `server.query` resolves with
|
|
40
|
+
the rows, `server.mutation` with the written row or `null`. Additive.
|
|
41
|
+
- **`server.realtime`** — `HOST_METHODS.SERVER_REALTIME` (`"server.realtime"`)
|
|
42
|
+
is the host → worker notification that carries a message a handler of the
|
|
43
|
+
install pushed with `ctx.realtime.push(topic, payload)`, with
|
|
44
|
+
`ServerRealtimeParams` (`{ topic; payload }`). `REALTIME_LIMITS` holds the
|
|
45
|
+
push rules (`TOPIC_PATTERN`, `MAX_PAYLOAD_BYTES` 16 KiB,
|
|
46
|
+
`MAX_PUSHES_PER_INVOCATION` 32, `MAX_PUSHES_PER_MINUTE` 300 and
|
|
47
|
+
`MAX_BYTES_PER_MINUTE` 1 MiB per install). Additive.
|
|
48
|
+
|
|
49
|
+
### Removed
|
|
50
|
+
|
|
51
|
+
- **`interactive` target** — `LifecycleInitParams["target"]` and the
|
|
52
|
+
`extensionConfigSchema` `target` enum accept only `editor` and `layer`. No
|
|
53
|
+
host ever rendered an `interactive` surface; viewers interact through chat
|
|
54
|
+
commands and channel point rewards (`twitch:reward`, `kick:reward`) that a
|
|
55
|
+
bot-module handler turns into `ctx.realtime.push`, received with
|
|
56
|
+
`server.realtime`.
|
|
57
|
+
|
|
58
|
+
**Breaking for consumers** that pass or `switch` over `"interactive"`. Drop
|
|
59
|
+
that arm; an init message carrying `target: "interactive"` now fails
|
|
60
|
+
validation.
|
|
61
|
+
|
|
62
|
+
## 0.7.0
|
|
63
|
+
|
|
64
|
+
### Added
|
|
65
|
+
|
|
66
|
+
- **`action.execute`** — `WORKER_METHODS.ACTION_EXECUTE` (`"action.execute"`)
|
|
67
|
+
is the worker → host request `useLumioAction()` sends, with
|
|
68
|
+
`ActionExecuteParams` (`{ action: LumioActionType; params }`) and
|
|
69
|
+
`ActionExecuteResult` (`{ data }`). `ACTION_EXECUTE_ERRORS` lists the
|
|
70
|
+
JSON-RPC error codes a host answers a failed action with (`INVALID_REQUEST`,
|
|
71
|
+
`UNAVAILABLE`, `DENIED`, `UNKNOWN_ACTION`, `INVALID_PARAMS`, `FAILED`).
|
|
72
|
+
Additive.
|
|
73
|
+
- **Twitch reward lifecycle event types** — `twitch:reward_status`,
|
|
74
|
+
`twitch:reward_add`, `twitch:reward_update` and `twitch:reward_remove` are in
|
|
75
|
+
`LUMIO_EVENT_TYPES`, `LumioEventType` and the `lumioEventTypeSchema` Zod enum.
|
|
76
|
+
`twitch:reward_status` is a redemption's status change (`fulfilled` /
|
|
77
|
+
`canceled`) with the same shape as `twitch:reward`. `twitch:reward_add` /
|
|
78
|
+
`_update` / `_remove` fire when the streamer creates, changes or deletes a
|
|
79
|
+
channel-point reward on Twitch and carry the Twitch custom-reward object; they
|
|
80
|
+
are delivered live only (`broadcast_only`) and never appear in the event
|
|
81
|
+
history. Additive.
|
|
82
|
+
|
|
83
|
+
## 0.6.0
|
|
84
|
+
|
|
85
|
+
### Added
|
|
86
|
+
|
|
87
|
+
- **Per-extension runtime origins** — new entry point
|
|
88
|
+
`@zaflun/lumio-protocol/origin` (also re-exported from the package root) with
|
|
89
|
+
`extensionRuntimeLabel(extensionId)` (canonical lowercase UUID → 32 lowercase
|
|
90
|
+
hex, otherwise `null`), `extensionRuntimeOrigin(extensionId, template)`
|
|
91
|
+
(`https://{label}.runtime.ext.lumio.vision` → the extension's origin, `null` for an
|
|
92
|
+
invalid id or template), `extensionRuntimeOriginLabel(origin, template)` and
|
|
93
|
+
`isValidExtensionRuntimeOriginTemplate(template)`. The `/origin` entry has no
|
|
94
|
+
runtime dependencies. Additive.
|
|
95
|
+
|
|
96
|
+
## 0.5.0
|
|
97
|
+
|
|
98
|
+
### Added
|
|
99
|
+
|
|
100
|
+
- **Kick event types** — `kick:resub`, `kick:kicks`, `kick:reward`,
|
|
101
|
+
`kick:reward_status` and `kick:stream_update` are in `LUMIO_EVENT_TYPES`,
|
|
102
|
+
`LumioEventType` and the `lumioEventTypeSchema` Zod enum. The Lumio webhook
|
|
103
|
+
receiver emits them for Kick subscription renewals, KICKs gifts, channel-point
|
|
104
|
+
redemptions (first delivery of a redemption `id` → `kick:reward`, every later
|
|
105
|
+
status change → `kick:reward_status`) and livestream metadata changes. Every
|
|
106
|
+
Kick event carries canonical top-level fields (`user_id`, `user_login`,
|
|
107
|
+
`user_name`, `avatarUrl`, `is_anonymous`) next to the original Kick payload.
|
|
108
|
+
`LUMIO_EVENT_TYPES` now holds 58 event types.
|
|
109
|
+
|
|
110
|
+
Additive: existing event strings are unchanged. Consumers that exhaustively
|
|
111
|
+
`switch` over `LumioEventType` need arms for the five new Kick types.
|
|
112
|
+
|
|
113
|
+
## 0.4.0
|
|
114
|
+
|
|
115
|
+
### Added
|
|
116
|
+
|
|
117
|
+
- **YouTube stream lifecycle** — `youtube:stream_online` and
|
|
118
|
+
`youtube:stream_offline`, emitted by the poll-driven YouTube worker on the
|
|
119
|
+
channel-status online/offline edge (once per real transition).
|
|
120
|
+
|
|
121
|
+
## 0.3.0
|
|
122
|
+
|
|
123
|
+
### Removed
|
|
124
|
+
|
|
125
|
+
- **Trovo event types** — `trovo:subscribe`, `trovo:spell` and `trovo:chat` are
|
|
126
|
+
gone from `LUMIO_EVENT_TYPES`, `LumioEventType` and the `lumioEventTypeSchema`
|
|
127
|
+
Zod enum. The Trovo platform has been shut down by its operator, so these
|
|
128
|
+
events can no longer be emitted. `LUMIO_EVENT_TYPES` now holds 72 event types
|
|
129
|
+
across Twitch, YouTube, Kick, Spotify, StreamElements, and per-platform +
|
|
130
|
+
cross-platform chat.
|
|
131
|
+
|
|
132
|
+
**Breaking for consumers** that reference a Trovo event type by name or
|
|
133
|
+
exhaustively `switch` over `LumioEventType`. Drop the Trovo arms; validation of
|
|
134
|
+
a Trovo event string now fails closed via `lumioEventTypeSchema`.
|
|
135
|
+
|
|
8
136
|
## 0.2.4
|
|
9
137
|
|
|
10
138
|
Wire-format types for the Lumio Extension Platform — the contract for
|
|
@@ -15,7 +143,7 @@ the validated schemas.
|
|
|
15
143
|
### Exports
|
|
16
144
|
|
|
17
145
|
- **Events** (`src/events.ts`)
|
|
18
|
-
- `LUMIO_EVENT_TYPES` —
|
|
146
|
+
- `LUMIO_EVENT_TYPES` — 75 platform event types across Twitch, YouTube, Kick,
|
|
19
147
|
Trovo, Spotify, StreamElements, and per-platform + cross-platform chat, with
|
|
20
148
|
`LumioEventType` and the `lumioEventTypeSchema` Zod enum.
|
|
21
149
|
- `ACTION_TYPES` — 21 action types (Chat, OBS, Spotify, Events, Overlay), with
|
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@ npm install @zaflun/lumio-protocol
|
|
|
10
10
|
|
|
11
11
|
## What's included
|
|
12
12
|
|
|
13
|
-
- **54 Event Types** — Twitch, YouTube, Kick,
|
|
13
|
+
- **54 Event Types** — Twitch, YouTube, Kick, Spotify, StreamElements, Chat
|
|
14
14
|
- **21 Action Types** — Chat, OBS, Spotify, Events, Overlay
|
|
15
15
|
- **Message Schemas** — JSON-RPC 2.0 wire format (Zod validated)
|
|
16
16
|
- **30 Component Types** — `LumioComponentNode` for serialized UI trees
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// src/origin.ts
|
|
2
|
+
var EXTENSION_RUNTIME_LABEL_PLACEHOLDER = "{label}";
|
|
3
|
+
var UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
|
|
4
|
+
var LABEL_PATTERN = /^[0-9a-f]{32}$/;
|
|
5
|
+
var DNS_LABEL_PATTERN = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/;
|
|
6
|
+
var TEMPLATE_PATTERN = /^(https:\/\/|http:\/\/)\{label\}(\.[a-z0-9.-]+(?::[0-9]{1,5})?)$/;
|
|
7
|
+
function parseTemplate(template) {
|
|
8
|
+
const match = TEMPLATE_PATTERN.exec(template);
|
|
9
|
+
if (!match) return null;
|
|
10
|
+
const prefix = match[1];
|
|
11
|
+
const suffix = match[2];
|
|
12
|
+
const host = suffix.slice(1).replace(/:[0-9]+$/, "");
|
|
13
|
+
if (prefix === "http://" && host !== "localhost") return null;
|
|
14
|
+
if (!host.split(".").every((label) => DNS_LABEL_PATTERN.test(label))) return null;
|
|
15
|
+
const sample = `${prefix}${"0".repeat(32)}${suffix}`;
|
|
16
|
+
try {
|
|
17
|
+
if (new URL(sample).origin !== sample) return null;
|
|
18
|
+
} catch {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
return { prefix, suffix };
|
|
22
|
+
}
|
|
23
|
+
function extensionRuntimeLabel(extensionId) {
|
|
24
|
+
if (typeof extensionId !== "string" || !UUID_PATTERN.test(extensionId)) return null;
|
|
25
|
+
return extensionId.replaceAll("-", "");
|
|
26
|
+
}
|
|
27
|
+
function extensionRuntimeOrigin(extensionId, template) {
|
|
28
|
+
const label = extensionRuntimeLabel(extensionId);
|
|
29
|
+
if (!label) return null;
|
|
30
|
+
const parsed = parseTemplate(template);
|
|
31
|
+
if (!parsed) return null;
|
|
32
|
+
return `${parsed.prefix}${label}${parsed.suffix}`;
|
|
33
|
+
}
|
|
34
|
+
function extensionRuntimeOriginLabel(origin, template) {
|
|
35
|
+
const parsed = parseTemplate(template);
|
|
36
|
+
if (!parsed) return null;
|
|
37
|
+
if (!origin.startsWith(parsed.prefix) || !origin.endsWith(parsed.suffix)) return null;
|
|
38
|
+
const label = origin.slice(parsed.prefix.length, origin.length - parsed.suffix.length);
|
|
39
|
+
return LABEL_PATTERN.test(label) ? label : null;
|
|
40
|
+
}
|
|
41
|
+
function isValidExtensionRuntimeOriginTemplate(template) {
|
|
42
|
+
return parseTemplate(template) !== null;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export {
|
|
46
|
+
EXTENSION_RUNTIME_LABEL_PLACEHOLDER,
|
|
47
|
+
extensionRuntimeLabel,
|
|
48
|
+
extensionRuntimeOrigin,
|
|
49
|
+
extensionRuntimeOriginLabel,
|
|
50
|
+
isValidExtensionRuntimeOriginTemplate
|
|
51
|
+
};
|