@helioslx/core 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.
Files changed (53) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/CONTRIBUTING.md +83 -0
  3. package/LICENSE +256 -0
  4. package/README.md +159 -0
  5. package/SECURITY.md +67 -0
  6. package/dist/contracts-C4kpAdZq.d.ts +265 -0
  7. package/dist/contracts-C4kpAdZq.d.ts.map +1 -0
  8. package/dist/http.d.ts +643 -0
  9. package/dist/http.d.ts.map +1 -0
  10. package/dist/http.js +670 -0
  11. package/dist/http.js.map +1 -0
  12. package/dist/index.d.ts +40 -0
  13. package/dist/index.d.ts.map +1 -0
  14. package/dist/index.js +270 -0
  15. package/dist/index.js.map +1 -0
  16. package/dist/node.d.ts +114 -0
  17. package/dist/node.d.ts.map +1 -0
  18. package/dist/node.js +334 -0
  19. package/dist/node.js.map +1 -0
  20. package/dist/redis.d.ts +46 -0
  21. package/dist/redis.d.ts.map +1 -0
  22. package/dist/redis.js +174 -0
  23. package/dist/redis.js.map +1 -0
  24. package/dist/source-DB1oq2GT.js +884 -0
  25. package/dist/source-DB1oq2GT.js.map +1 -0
  26. package/dist/source-D_XNWXS9.d.ts +76 -0
  27. package/dist/source-D_XNWXS9.d.ts.map +1 -0
  28. package/dist/testing.d.ts +38 -0
  29. package/dist/testing.d.ts.map +1 -0
  30. package/dist/testing.js +98 -0
  31. package/dist/testing.js.map +1 -0
  32. package/dist/validation-BdsVeyAE.js +151 -0
  33. package/dist/validation-BdsVeyAE.js.map +1 -0
  34. package/examples/embedded-elysia-http.ts +30 -0
  35. package/examples/full-frame-fade.ts +25 -0
  36. package/examples/graceful-shutdown.ts +19 -0
  37. package/examples/quickstart.ts +30 -0
  38. package/examples/redis.ts +30 -0
  39. package/examples/sparse-channels.ts +23 -0
  40. package/examples/viewer-subscription.ts +38 -0
  41. package/examples/viewer-tui.ts +201 -0
  42. package/package.json +108 -0
  43. package/src/contracts.ts +302 -0
  44. package/src/http.ts +1101 -0
  45. package/src/index.ts +61 -0
  46. package/src/memory-store.ts +45 -0
  47. package/src/node.ts +578 -0
  48. package/src/output-engine.ts +778 -0
  49. package/src/redis.ts +258 -0
  50. package/src/source.ts +502 -0
  51. package/src/testing.ts +139 -0
  52. package/src/validation.ts +328 -0
  53. package/src/viewer.ts +368 -0
@@ -0,0 +1,265 @@
1
+ //#region src/contracts.d.ts
2
+ declare const SLOT_COUNT = 512;
3
+ declare const MIN_UNIVERSE = 1;
4
+ declare const MAX_UNIVERSE = 63999;
5
+ declare const MIN_PRIORITY = 0;
6
+ declare const MAX_PRIORITY = 200;
7
+ declare const DEFAULT_PRIORITY = 100;
8
+ declare const DEFAULT_ACTIVE_FPS = 44;
9
+ declare const DEFAULT_IDLE_FPS = 2;
10
+ interface OutputAddress {
11
+ readonly universe: number;
12
+ readonly priority?: number;
13
+ }
14
+ interface OutputOptions extends OutputAddress {
15
+ readonly cid?: string;
16
+ readonly idleFps?: number;
17
+ readonly sourceName?: string;
18
+ }
19
+ /** One-based DMX channel → value map used by setChannels / fadeChannels. */
20
+ type ChannelValues = Readonly<Record<number, number>>;
21
+ interface ChannelWrite {
22
+ /** One-based DMX slot number. */
23
+ readonly channel: number;
24
+ readonly value: number;
25
+ /** Linear transition duration in milliseconds. Defaults to 0 (snap). */
26
+ readonly durationMs?: number;
27
+ }
28
+ interface TransitionWrite {
29
+ readonly channel: number;
30
+ readonly value: number;
31
+ readonly durationMs: number;
32
+ }
33
+ interface FadeChannelsOptions {
34
+ readonly durationMs: number;
35
+ readonly signal?: AbortSignal;
36
+ }
37
+ interface WriteFrameOptions {
38
+ readonly durationMs?: number;
39
+ readonly signal?: AbortSignal;
40
+ }
41
+ interface ClearUniverseOptions {
42
+ readonly signal?: AbortSignal;
43
+ }
44
+ interface UniverseOptions {
45
+ readonly priority?: number;
46
+ readonly cid?: string;
47
+ readonly idleFps?: number;
48
+ readonly sourceName?: string;
49
+ }
50
+ type FrameMode = "active" | "idle";
51
+ interface OutputSnapshot {
52
+ readonly activeTransitions: number;
53
+ readonly cid: string;
54
+ readonly current: readonly number[];
55
+ readonly dirty: boolean;
56
+ readonly frameMode: FrameMode;
57
+ readonly idleFps: number;
58
+ readonly lastError: string | null;
59
+ readonly lastSent: readonly number[];
60
+ readonly lastSentAt: number | null;
61
+ readonly nextDueAt: number;
62
+ readonly priority: number;
63
+ readonly sequence: number;
64
+ readonly sourceName: string | null;
65
+ readonly target: readonly number[];
66
+ readonly universe: number;
67
+ readonly updatedAt: number;
68
+ }
69
+ interface OutputRecord {
70
+ readonly cid: string;
71
+ readonly idleFps: number;
72
+ readonly priority: number;
73
+ readonly sourceName: string | null;
74
+ readonly target: readonly number[];
75
+ readonly universe: number;
76
+ readonly updatedAt: number;
77
+ }
78
+ interface OutputStore {
79
+ get(address: Required<OutputAddress>): Promise<OutputRecord | null>;
80
+ list(): Promise<readonly OutputRecord[]>;
81
+ remove(address: Required<OutputAddress>): Promise<void>;
82
+ save(record: OutputRecord): Promise<void>;
83
+ close?(): Promise<void>;
84
+ }
85
+ interface OutputPacket {
86
+ readonly cid: string;
87
+ readonly data: Uint8Array;
88
+ readonly priority: number;
89
+ readonly sequence: number;
90
+ readonly sourceName: string | null;
91
+ readonly universe: number;
92
+ }
93
+ interface OutputTransport {
94
+ send(packet: OutputPacket, signal: AbortSignal): Promise<void>;
95
+ closeOutput?(address: Required<OutputAddress>): Promise<void>;
96
+ close(): Promise<void>;
97
+ }
98
+ interface Clock {
99
+ /** Monotonic milliseconds used for scheduling. */
100
+ now(): number;
101
+ /** Wall-clock Unix milliseconds used for public and persisted metadata. */
102
+ wallNow?(): number;
103
+ sleep(delayMs: number, signal: AbortSignal): Promise<void>;
104
+ }
105
+ interface Logger {
106
+ debug?(message: string, context?: Readonly<Record<string, unknown>>): void;
107
+ info?(message: string, context?: Readonly<Record<string, unknown>>): void;
108
+ warn?(message: string, context?: Readonly<Record<string, unknown>>): void;
109
+ error?(message: string, context?: Readonly<Record<string, unknown>>): void;
110
+ }
111
+ interface TransportTelemetry {
112
+ readonly sendAttempts: number;
113
+ readonly sendFailures: number;
114
+ readonly sendRetries: number;
115
+ readonly sendSuccesses: number;
116
+ readonly sendTimeouts: number;
117
+ }
118
+ interface EngineTelemetry {
119
+ readonly closed: boolean;
120
+ readonly lastLoopCompletedAt: number | null;
121
+ readonly lastLoopDurationMs: number | null;
122
+ readonly lastLoopStartedAt: number | null;
123
+ readonly loopIterations: number;
124
+ readonly outputCount: number;
125
+ readonly outputs: readonly OutputSnapshot[];
126
+ readonly running: boolean;
127
+ readonly transport: TransportTelemetry;
128
+ }
129
+ type SacnLifecycleHook = () => void | Promise<void>;
130
+ interface SacnSourceOptions {
131
+ readonly transport: OutputTransport;
132
+ readonly store?: OutputStore;
133
+ readonly clock?: Clock;
134
+ readonly logger?: Logger;
135
+ readonly activeFps?: number;
136
+ readonly idleFps?: number;
137
+ readonly sendTimeoutMs?: number;
138
+ /** Maximum time spent awaiting transport shutdown. Defaults to 2 seconds. */
139
+ readonly shutdownTimeoutMs?: number;
140
+ /** Maximum number of active universe/priority outputs. Defaults to 1024. */
141
+ readonly maxOutputs?: number;
142
+ /** Close the injected transport with the source. Defaults to false. */
143
+ readonly ownsTransport?: boolean;
144
+ /** Defaults to true for the default memory store, false for an injected store. */
145
+ readonly ownsStore?: boolean;
146
+ readonly createId?: () => string;
147
+ readonly onStart?: SacnLifecycleHook;
148
+ readonly onStop?: SacnLifecycleHook;
149
+ readonly onClose?: SacnLifecycleHook;
150
+ }
151
+ type SacnSourceEvent = {
152
+ readonly type: "started";
153
+ } | {
154
+ readonly type: "stopped";
155
+ } | {
156
+ readonly type: "output-updated";
157
+ readonly output: OutputSnapshot;
158
+ } | {
159
+ readonly type: "output-cleared";
160
+ readonly address: Required<OutputAddress>;
161
+ } | {
162
+ readonly type: "closed";
163
+ };
164
+ interface UniverseContract {
165
+ readonly universe: number;
166
+ readonly priority: number;
167
+ setChannels(values: ChannelValues, options?: {
168
+ readonly signal?: AbortSignal;
169
+ }): Promise<OutputSnapshot>;
170
+ fadeChannels(values: ChannelValues, options: FadeChannelsOptions): Promise<OutputSnapshot>;
171
+ transition(writes: readonly TransitionWrite[], options?: {
172
+ readonly signal?: AbortSignal;
173
+ }): Promise<OutputSnapshot>;
174
+ write(values: readonly number[] | Uint8Array, options?: WriteFrameOptions): Promise<OutputSnapshot>;
175
+ get(): Promise<OutputSnapshot | null>;
176
+ clear(options?: ClearUniverseOptions): Promise<boolean>;
177
+ }
178
+ interface SacnSourceContract {
179
+ universe(universe: number, options?: UniverseOptions): UniverseContract;
180
+ start(): Promise<void>;
181
+ stop(): Promise<void>;
182
+ listUniverses(): Promise<readonly OutputSnapshot[]>;
183
+ getTelemetry(): EngineTelemetry;
184
+ subscribe(listener: (event: SacnSourceEvent) => void): () => void;
185
+ close(): Promise<void>;
186
+ }
187
+ interface ReceiverPacket {
188
+ readonly cid: string;
189
+ readonly priority: number;
190
+ readonly sequence: number;
191
+ readonly sourceAddress: string | null;
192
+ readonly sourceName: string | null;
193
+ readonly universe: number;
194
+ readonly values: Uint8Array;
195
+ }
196
+ type ReceiverPacketListener = (packet: ReceiverPacket) => void;
197
+ /** Runtime-neutral source of normalized sACN packets. */
198
+ interface Receiver {
199
+ addUniverse(universe: number): Promise<void> | void;
200
+ removeUniverse(universe: number): Promise<void> | void;
201
+ subscribe(listener: ReceiverPacketListener): () => void;
202
+ close(): Promise<void>;
203
+ }
204
+ interface ViewerSourceMetadata {
205
+ readonly cid: string;
206
+ readonly priority: number;
207
+ readonly sequence: number;
208
+ readonly sourceAddress: string | null;
209
+ readonly sourceName: string | null;
210
+ }
211
+ interface ViewerPacket {
212
+ readonly receivedAt: number;
213
+ readonly source: ViewerSourceMetadata;
214
+ readonly universe: number;
215
+ /** Exactly 512 normalized values. */
216
+ readonly values: readonly number[];
217
+ }
218
+ interface ViewerRecord {
219
+ readonly selectedUniverses: readonly number[];
220
+ readonly updatedAt: number;
221
+ }
222
+ interface ViewerStore {
223
+ load(): Promise<ViewerRecord | null>;
224
+ save(record: ViewerRecord): Promise<void>;
225
+ close?(): Promise<void>;
226
+ }
227
+ interface ViewerTelemetry {
228
+ readonly droppedUpdates: number;
229
+ readonly packetsReceived: number;
230
+ readonly selectedUniverses: readonly number[];
231
+ readonly streamCount: number;
232
+ }
233
+ interface ViewerPacketStream extends AsyncIterable<ViewerPacket> {
234
+ close(): void;
235
+ }
236
+ interface ViewerServiceContract {
237
+ start(): Promise<void>;
238
+ getSelectedUniverses(): readonly number[];
239
+ setSelectedUniverses(universes: readonly number[]): Promise<readonly number[]>;
240
+ addUniverse(universe: number): Promise<readonly number[]>;
241
+ removeUniverse(universe: number): Promise<readonly number[]>;
242
+ subscribe(listener: (packet: ViewerPacket) => void): () => void;
243
+ packets(capacity?: number): ViewerPacketStream;
244
+ getTelemetry(): ViewerTelemetry;
245
+ close(): Promise<void>;
246
+ }
247
+ interface ViewerServiceOptions {
248
+ readonly receiver: Receiver;
249
+ readonly store?: ViewerStore;
250
+ readonly clock?: Pick<Clock, "now">;
251
+ readonly logger?: Logger;
252
+ /** Close the injected receiver with this service. Defaults to false. */
253
+ readonly ownsReceiver?: boolean;
254
+ /** Defaults to true for the default memory store, false for an injected store. */
255
+ readonly ownsStore?: boolean;
256
+ /** Default queue capacity for streams. Defaults to 32. */
257
+ readonly streamCapacity?: number;
258
+ /** Maximum number of selected universes. Defaults to 256. */
259
+ readonly maxUniverses?: number;
260
+ /** Maximum combined callback and stream subscribers. Defaults to 256. */
261
+ readonly maxListeners?: number;
262
+ }
263
+ //#endregion
264
+ export { SacnSourceOptions as A, ViewerSourceMetadata as B, Receiver as C, SacnLifecycleHook as D, SLOT_COUNT as E, ViewerPacket as F, ViewerTelemetry as H, ViewerPacketStream as I, ViewerRecord as L, TransportTelemetry as M, UniverseContract as N, SacnSourceContract as O, UniverseOptions as P, ViewerServiceContract as R, OutputTransport as S, ReceiverPacketListener as T, WriteFrameOptions as U, ViewerStore as V, OutputOptions as _, DEFAULT_ACTIVE_FPS as a, OutputSnapshot as b, EngineTelemetry as c, Logger as d, MAX_PRIORITY as f, OutputAddress as g, MIN_UNIVERSE as h, Clock as i, TransitionWrite as j, SacnSourceEvent as k, FadeChannelsOptions as l, MIN_PRIORITY as m, ChannelWrite as n, DEFAULT_IDLE_FPS as o, MAX_UNIVERSE as p, ClearUniverseOptions as r, DEFAULT_PRIORITY as s, ChannelValues as t, FrameMode as u, OutputPacket as v, ReceiverPacket as w, OutputStore as x, OutputRecord as y, ViewerServiceOptions as z };
265
+ //# sourceMappingURL=contracts-C4kpAdZq.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contracts-C4kpAdZq.d.ts","names":[],"sources":["../src/contracts.ts"],"mappings":";cAAa;cACA;cACA;cACA;cACA;cACA;cACA;cACA;UAEI;WACP;WACA;;UAGO,sBAAsB;WAC7B;WACA;WACA;;;KAIE,gBAAgB,SAAS;UAEpB;;WAEP;WACA;;WAEA;;UAGO;WACP;WACA;WACA;;UAGO;WACP;WACA,SAAS;;UAGF;WACP;WACA,SAAS;;UAGF;WACP,SAAS;;UAGF;WACP;WACA;WACA;WACA;;KAGE;UAEK;WACP;WACA;WACA;WACA;WACA,WAAW;WACX;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;;UAGO;WACP;WACA;WACA;WACA;WACA;WACA;WACA;;UAGO;EAChB,IAAI,SAAS,SAAS,iBAAiB,QAAQ;EAC/C,QAAQ,iBAAiB;EACzB,OAAO,SAAS,SAAS,iBAAiB;EAC1C,KAAK,QAAQ,eAAe;EAC5B,UAAU;;UAGM;WACP;WACA,MAAM;WACN;WACA;WACA;WACA;;UAGO;EAChB,KAAK,QAAQ,cAAc,QAAQ,cAAc;EACjD,aAAa,SAAS,SAAS,iBAAiB;EAChD,SAAS;;UAGO;;EAEhB;;EAEA;EACA,MAAM,iBAAiB,QAAQ,cAAc;;UAG7B;EAChB,OAAO,iBAAiB,UAAU,SAAS;EAC3C,MAAM,iBAAiB,UAAU,SAAS;EAC1C,MAAM,iBAAiB,UAAU,SAAS;EAC1C,OAAO,iBAAiB,UAAU,SAAS;;UAG3B;WACP;WACA;WACA;WACA;WACA;;UAGO;WACP;WACA;WACA;WACA;WACA;WACA;WACA,kBAAkB;WAClB;WACA,WAAW;;KAGT,iCAAiC;UAE5B;WACP,WAAW;WACX,QAAQ;WACR,QAAQ;WACR,SAAS;WACT;WACA;WACA;;WAEA;;WAEA;;WAEA;;WAEA;WACA;WACA,UAAU;WACV,SAAS;WACT,UAAU;;KAGR;WACE;;WACA;;WACA;WAAiC,QAAQ;;WAE3C;WACA,SAAS,SAAS;;WAEhB;;UAEG;WACP;WACA;EACT,YACC,QAAQ,eACR;aAAqB,SAAS;MAC5B,QAAQ;EACX,aACC,QAAQ,eACR,SAAS,sBACP,QAAQ;EACX,WACC,iBAAiB,mBACjB;aAAqB,SAAS;MAC5B,QAAQ;EACX,MACC,4BAA4B,YAC5B,UAAU,oBACR,QAAQ;EACX,OAAO,QAAQ;EACf,MAAM,UAAU,uBAAuB;;UAGvB;EAChB,SAAS,kBAAkB,UAAU,kBAAkB;EACvD,SAAS;EACT,QAAQ;EACR,iBAAiB,iBAAiB;EAClC,gBAAgB;EAChB,UAAU,WAAW,OAAO;EAC5B,SAAS;;UAGO;WACP;WACA;WACA;WACA;WACA;WACA;WACA,QAAQ;;KAGN,0BAA0B,QAAQ;;UAG7B;EAChB,YAAY,mBAAmB;EAC/B,eAAe,mBAAmB;EAClC,UAAU,UAAU;EACpB,SAAS;;UAGO;WACP;WACA;WACA;WACA;WACA;;UAGO;WACP;WACA,QAAQ;WACR;;WAEA;;UAGO;WACP;WACA;;UAGO;EAChB,QAAQ,QAAQ;EAChB,KAAK,QAAQ,eAAe;EAC5B,UAAU;;UAGM;WACP;WACA;WACA;WACA;;UAGO,2BAA2B,cAAc;EACzD;;UAGgB;EAChB,SAAS;EACT;EACA,qBACC,+BACE;EACH,YAAY,mBAAmB;EAC/B,eAAe,mBAAmB;EAClC,UAAU,WAAW,QAAQ;EAC7B,QAAQ,oBAAoB;EAC5B,gBAAgB;EAChB,SAAS;;UAGO;WACP,UAAU;WACV,QAAQ;WACR,QAAQ,KAAK;WACb,SAAS;;WAET;;WAEA;;WAEA;;WAEA;;WAEA"}