@omujs/omu 0.9.32 → 0.9.40

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 (58) hide show
  1. package/CHANGELOG.md +70 -0
  2. package/dist/dts/api/asset/extension.d.ts +3 -3
  3. package/dist/dts/api/asset/index.d.ts +1 -1
  4. package/dist/dts/api/dashboard/extension.d.ts +13 -3
  5. package/dist/dts/api/dashboard/handler.d.ts +2 -1
  6. package/dist/dts/api/dashboard/index.d.ts +1 -1
  7. package/dist/dts/api/http/extension.d.ts +2 -135
  8. package/dist/dts/api/http/http.d.ts +36 -0
  9. package/dist/dts/api/http/websocket.d.ts +123 -0
  10. package/dist/dts/api/permission/extension.d.ts +1 -0
  11. package/dist/dts/index.d.ts +1 -3
  12. package/dist/dts/version.d.ts +2 -1
  13. package/dist/esm/api/asset/extension.js +43 -18
  14. package/dist/esm/api/asset/index.js +42 -17
  15. package/dist/esm/api/dashboard/extension.js +17 -13
  16. package/dist/esm/api/dashboard/index.js +17 -13
  17. package/dist/esm/api/endpoint/extension.js +3 -3
  18. package/dist/esm/api/extension.js +3 -3
  19. package/dist/esm/api/http/extension.js +262 -277
  20. package/dist/esm/api/http/http.js +442 -0
  21. package/dist/esm/api/http/index.js +262 -165
  22. package/dist/esm/api/http/websocket.js +220 -0
  23. package/dist/esm/api/i18n/extension.js +3 -3
  24. package/dist/esm/api/i18n/index.js +3 -3
  25. package/dist/esm/api/index.js +3 -3
  26. package/dist/esm/api/logger/extension.js +3 -3
  27. package/dist/esm/api/logger/index.js +3 -3
  28. package/dist/esm/api/permission/extension.js +6 -3
  29. package/dist/esm/api/plugin/extension.js +3 -3
  30. package/dist/esm/api/plugin/index.js +3 -3
  31. package/dist/esm/api/registry/extension.js +3 -3
  32. package/dist/esm/api/registry/index.js +3 -3
  33. package/dist/esm/api/server/extension.js +3 -3
  34. package/dist/esm/api/server/index.js +3 -3
  35. package/dist/esm/api/session/extension.js +3 -3
  36. package/dist/esm/api/session/index.js +3 -3
  37. package/dist/esm/api/signal/extension.js +3 -3
  38. package/dist/esm/api/table/extension.js +3 -3
  39. package/dist/esm/api/table/index.js +3 -3
  40. package/dist/esm/index.js +319 -189
  41. package/dist/esm/network/index.js +3 -3
  42. package/dist/esm/network/network.js +3 -3
  43. package/dist/esm/omu.js +318 -186
  44. package/dist/esm/version.js +5 -3
  45. package/package.json +1 -1
  46. package/src/api/asset/extension.ts +46 -12
  47. package/src/api/asset/index.ts +1 -2
  48. package/src/api/dashboard/extension.ts +29 -13
  49. package/src/api/dashboard/handler.ts +2 -1
  50. package/src/api/dashboard/index.ts +2 -0
  51. package/src/api/extension.ts +1 -1
  52. package/src/api/http/extension.ts +13 -364
  53. package/src/api/http/http.ts +79 -0
  54. package/src/api/http/websocket.ts +283 -0
  55. package/src/api/permission/extension.ts +4 -0
  56. package/src/index.ts +3 -5
  57. package/src/version.ts +2 -1
  58. package/tsconfig.tsbuildinfo +1 -1
@@ -1,10 +1,11 @@
1
- /* eslint-disable @typescript-eslint/no-explicit-any */
2
- import { textDecoder, textEncoder } from '../../const';
1
+
2
+ import { textEncoder } from '../../const';
3
3
  import { Identifier } from '../../identifier';
4
4
  import { PacketType } from '../../network/packet';
5
5
  import { Omu } from '../../omu';
6
- import { ByteReader, ByteWriter, JsonType } from '../../serialize';
7
6
  import { Extension, ExtensionType } from '../extension';
7
+ import { DataChunk, HttpRequest, OmuResponse, RequestHandle } from './http';
8
+ import { OmuWS, WebSocketClose, WebSocketError, WebSocketOpen, WSData, WSDataMeta, WSHandleState, WSMsgType } from './websocket';
8
9
 
9
10
  export const HTTP_EXTENSION_TYPE: ExtensionType<HttpExtension> = new ExtensionType(
10
11
  'http',
@@ -13,42 +14,10 @@ export const HTTP_EXTENSION_TYPE: ExtensionType<HttpExtension> = new ExtensionTy
13
14
 
14
15
  export const HTTP_REQUEST_PERMISSION_ID: Identifier = HTTP_EXTENSION_TYPE.join('request');
15
16
 
16
- type RequestHandle = {
17
- id: string;
18
- };
19
-
20
- type HttpRequest = RequestHandle & {
21
- header: Record<string, string>;
22
- method: string;
23
- redirect: RequestRedirect;
24
- url: string;
25
- };
26
-
27
17
  const REQUEST_CREATE = PacketType.createJson<HttpRequest>(HTTP_EXTENSION_TYPE, {
28
18
  name: 'request_create',
29
19
  });
30
20
 
31
- class DataChunk<T extends JsonType> {
32
- constructor(
33
- public readonly meta: T,
34
- public readonly body: Uint8Array,
35
- ) { }
36
-
37
- public static serialize<T extends JsonType>(data: DataChunk<T>): Uint8Array {
38
- const writer = new ByteWriter();
39
- writer.writeJSON(data.meta);
40
- writer.writeUint8Array(data.body);
41
- return writer.finish();
42
- }
43
-
44
- public static deserialize<T extends JsonType>(data: Uint8Array): DataChunk<T> {
45
- const reader = ByteReader.fromUint8Array(data);
46
- const meta = reader.readJSON<T>();
47
- const body = reader.readUint8Array();
48
- return new DataChunk(meta, body);
49
- }
50
- }
51
-
52
21
  const REQUEST_SEND = PacketType.createSerialized<DataChunk<RequestHandle>>(HTTP_EXTENSION_TYPE, {
53
22
  name: 'request_send',
54
23
  serializer: DataChunk,
@@ -95,64 +64,6 @@ type HandleStateCreated = {
95
64
 
96
65
  type HandleState = HandleStateCreated | HandleStateReceiving;
97
66
 
98
- type WSData = string | ArrayBufferLike | Blob | ArrayBufferView;
99
-
100
- export const WSMsgType = {
101
- CONTINUATION: 0x0,
102
- TEXT: 0x1,
103
- BINARY: 0x2,
104
- PING: 0x9,
105
- PONG: 0xA,
106
- CLOSE: 0x8,
107
- } as const;
108
-
109
- export const WSCloseCode = {
110
- OK: 1000,
111
- GOING_AWAY: 1001,
112
- PROTOCOL_ERROR: 1002,
113
- UNSUPPORTED_DATA: 1003,
114
- ABNORMAL_CLOSURE: 1006,
115
- INVALID_TEXT: 1007,
116
- POLICY_VIOLATION: 1008,
117
- MESSAGE_TOO_BIG: 1009,
118
- MANDATORY_EXTENSION: 1010,
119
- INTERNAL_ERROR: 1011,
120
- SERVICE_RESTART: 1012,
121
- TRY_AGAIN_LATER: 1013,
122
- BAD_GATEWAY: 1014,
123
- } as const;
124
-
125
- type WebSocketOpen = RequestHandle & {
126
- url: string;
127
- protocol?: string | null;
128
- };
129
- type WebSocketClose = RequestHandle & {
130
- code?: number;
131
- reason?: string | null;
132
- };
133
-
134
- type WebSocketHandle = {
135
- ws: OmuWS;
136
- open: (response: WebSocketOpen) => void;
137
- dispatch: (data: DataChunk<WSDataMeta>) => void;
138
- close: (response: WebSocketClose) => void;
139
- error: (response: WebSocketError) => void;
140
- };
141
-
142
- type WSDataMeta = {
143
- id: string;
144
- type:
145
- | typeof WSMsgType.TEXT
146
- | typeof WSMsgType.BINARY
147
- | typeof WSMsgType.PING
148
- | typeof WSMsgType.PONG;
149
- };
150
-
151
- type WSHandleState = {
152
- type: 'created' | 'receiving';
153
- handle: WebSocketHandle;
154
- };
155
-
156
67
  const WEBSOCKET_CREATE = PacketType.createJson<HttpRequest>(HTTP_EXTENSION_TYPE, {
157
68
  name: 'ws_create',
158
69
  });
@@ -170,11 +81,6 @@ const WEBSOCKET_CLOSE = PacketType.createJson<WebSocketClose>(HTTP_EXTENSION_TYP
170
81
  name: 'ws_close',
171
82
  });
172
83
 
173
- type WebSocketError = RequestHandle & {
174
- type: 'ConnectionRefused';
175
- reason?: string | null;
176
- };
177
-
178
84
  const WEBSOCKET_ERROR = PacketType.createJson<WebSocketError>(HTTP_EXTENSION_TYPE, {
179
85
  name: 'ws_error',
180
86
  });
@@ -451,20 +357,23 @@ export class HttpExtension implements Extension {
451
357
  }): Promise<OmuWS> {
452
358
  const request = new Request(input, options);
453
359
  const id = this.generateId();
454
- const handle = OmuWS.create(
455
- this.omu,
456
- id,
457
- (data) => {
360
+ const handle = OmuWS.create({
361
+ addQueue: (data) => {
458
362
  this.wsSendQueue.push({
459
363
  id: id.key(),
460
364
  data,
461
365
  });
462
366
  this.wsSendWaitResolve();
463
367
  },
464
- () => {
368
+ dispose: (options: { code?: number; reason?: string }) => {
369
+ this.omu.send(WEBSOCKET_CLOSE, {
370
+ id: id.key(),
371
+ code: options.code,
372
+ reason: options.reason,
373
+ });
465
374
  delete this.wsHandles[id.key()];
466
375
  },
467
- );
376
+ });
468
377
  this.wsHandles[id.key()] = {
469
378
  type: 'created',
470
379
  handle,
@@ -480,266 +389,6 @@ export class HttpExtension implements Extension {
480
389
  }
481
390
  }
482
391
 
483
- class OmuResponse implements Response {
484
- constructor(
485
- public readonly headers: Headers,
486
- public readonly ok: boolean,
487
- public readonly redirected: boolean,
488
- public readonly status: number,
489
- public readonly statusText: string,
490
- public readonly type: ResponseType,
491
- public readonly url: string,
492
- public readonly body: ReadableStream<Uint8Array<ArrayBuffer>> | null,
493
- public readonly bodyUsed: boolean,
494
- ) {}
495
-
496
- clone(): OmuResponse {
497
- return new OmuResponse(
498
- this.headers,
499
- this.ok,
500
- this.redirected,
501
- this.status,
502
- this.statusText,
503
- this.type,
504
- this.url,
505
- this.body,
506
- this.bodyUsed,
507
- );
508
- }
509
- async arrayBuffer(): Promise<ArrayBuffer> {
510
- return await new Response(this.body).arrayBuffer();
511
- }
512
- blob(): Promise<Blob> {
513
- return new Response(this.body).blob();
514
- }
515
- bytes(): Promise<Uint8Array<ArrayBuffer>> {
516
- return new Response(this.body).arrayBuffer().then((buf) => new Uint8Array(buf));
517
- }
518
- formData(): Promise<FormData> {
519
- return new Response(this.body).formData();
520
- }
521
- json(): Promise<any> {
522
- return new Response(this.body).json();
523
- }
524
- text(): Promise<string> {
525
- return new Response(this.body).text();
526
- }
527
- }
528
-
529
- type EventListenerMap<T> = {
530
- [K in keyof T]: ((event: T[K]) => unknown)[]
531
- };
532
-
533
- export type WSMsg = {
534
- type: 'open';
535
- data: WebSocketOpen;
536
- } | {
537
- type: 'error';
538
- data: WebSocketError;
539
- } | {
540
- type: 'text';
541
- data: string;
542
- } | {
543
- type: 'binary';
544
- data: Uint8Array;
545
- } | {
546
- type: 'close';
547
- data: WebSocketClose;
548
- };
549
-
550
- export class OmuWS {
551
- constructor(
552
- protected readonly omu: Omu,
553
- protected readonly id: Identifier,
554
- protected readonly addQueue: (data: WSData) => void,
555
- protected readonly dispose: () => void,
556
- protected readonly receiveQueue: WSMsg[] = [],
557
- private receiveResolve: (() => void) | undefined = undefined,
558
- private status: 'connecting' | 'open' | 'closed' = 'connecting',
559
- ) { }
560
-
561
- public static create(omu: Omu, id: Identifier, addQueue: (data: WSData) => void, dispose: () => void): WebSocketHandle {
562
- const ws = new OmuWS(omu, id, addQueue, dispose);
563
- return {
564
- ws,
565
- open: (response) => {
566
- ws.receiveQueue.push({
567
- type: 'open',
568
- data: response,
569
- });
570
- ws.receiveResolve?.();
571
- },
572
- dispatch: (data: DataChunk<WSDataMeta>): void => {
573
- if (data.meta.type === WSMsgType.BINARY) {
574
- ws.receiveQueue.push({
575
- type: 'binary',
576
- data: data.body,
577
- });
578
- } else {
579
- ws.receiveQueue.push({
580
- type: 'text',
581
- data: textDecoder.decode(data.body),
582
- });
583
- }
584
- ws.receiveResolve?.();
585
- },
586
- close: (response) => {
587
- ws.receiveQueue.push({
588
- type: 'close',
589
- data: response,
590
- });
591
- ws.receiveResolve?.();
592
- },
593
- error: (response) => {
594
- ws.receiveQueue.push({
595
- type: 'error',
596
- data: response,
597
- });
598
- ws.receiveResolve?.();
599
- },
600
- };
601
- }
602
-
603
- public send(data: WSData): void {
604
- this.addQueue(data);
605
- }
606
-
607
- public close(code?: number, reason?: string): void {
608
- this.omu.send(WEBSOCKET_CLOSE, {
609
- id: this.id.key(),
610
- code,
611
- reason,
612
- });
613
- this.dispose();
614
- }
615
-
616
- public async receive(): Promise<WSMsg> {
617
- if (this.receiveResolve) {
618
- throw new Error('Already receiving from another async call');
619
- }
620
- while (this.status !== 'closed') {
621
- const data = this.receiveQueue.shift();
622
- if (!data) {
623
- await new Promise<void>((resolve) => this.receiveResolve = resolve);
624
- continue;
625
- }
626
- if (data.type === 'close') {
627
- this.status = 'closed';
628
- }
629
- if (data.type === 'open') {
630
- this.status = 'open';
631
- }
632
- this.receiveResolve = undefined;
633
- return data;
634
- }
635
- throw new Error('Receiving on already closed socket');
636
- }
637
-
638
- protocol: string = '';
639
- url: string = '';
640
- }
641
-
642
- export class OmuWebSocket implements WebSocket {
643
- public CONNECTING = 0 as const;
644
- public OPEN = 1 as const;
645
- public CLOSING = 2 as const;
646
- public CLOSED = 3 as const;
647
-
648
- binaryType: BinaryType = 'blob';
649
- bufferedAmount: number = 0;
650
- extensions: string = '';
651
- onclose: ((this: WebSocket, ev: CloseEvent) => any) | null = null;
652
- onerror: ((this: WebSocket, ev: Event) => any) | null = null;
653
- onmessage: ((this: WebSocket, ev: MessageEvent) => any) | null = null;
654
- onopen: ((this: WebSocket, ev: Event) => any) | null = null;
655
- protocol: string = '';
656
- readyState: 0 | 2 | 1 | 3 = 0;
657
- url: string = '';
658
-
659
- constructor(
660
- protected readonly ws: OmuWS,
661
- private readonly eventListeners: EventListenerMap<WebSocketEventMap> = {
662
- close: [],
663
- error: [],
664
- message: [],
665
- open: [],
666
- },
667
- ) {
668
- this.receiveLoop();
669
- }
670
-
671
- private async receiveLoop() {
672
- while (this.readyState === WebSocket.CLOSED) {
673
- const { data, type } = await this.ws.receive();
674
- switch (type) {
675
- case 'close':
676
- this.dispatchEvent(new CloseEvent('close', {
677
- code: data.code,
678
- reason: data.reason ?? undefined,
679
- }));
680
- break;
681
- case 'open':
682
- this.url = data.url;
683
- this.protocol = data.protocol ?? '';
684
- this.dispatchEvent(new Event('open', {}));
685
- break;
686
- case 'error':
687
- this.dispatchEvent(new ErrorEvent('error', {
688
- error: data.type,
689
- message: data.reason ?? undefined,
690
- }));
691
- break;
692
- case 'text':
693
- case 'binary':
694
- this.dispatchEvent(new MessageEvent('message', {
695
- data,
696
- }));
697
- break;
698
- }
699
- }
700
- }
701
-
702
- dispatchEvent(event: Event): boolean {
703
- const listeners = this.eventListeners[event.type];
704
- for (const listener of listeners) {
705
- listener(event);
706
- }
707
- if (event.type === 'open') {
708
- this.onopen?.(event as MessageEvent);
709
- }
710
- if (event.type === 'error') {
711
- this.onerror?.(event);
712
- }
713
- if (event.type === 'message') {
714
- this.onmessage?.(event as MessageEvent);
715
- }
716
- if (event.type === 'close') {
717
- this.onclose?.(event as CloseEvent);
718
- }
719
- return true;
720
- }
721
-
722
- send(data: string | ArrayBufferLike | Blob | ArrayBufferView): void {
723
- this.ws.send(data);
724
- }
725
-
726
- close(code?: number, reason?: string): void {
727
- this.ws.close(code, reason);
728
- }
729
-
730
- addEventListener<K extends keyof WebSocketEventMap>(type: K, listener: (this: WebSocket, ev: WebSocketEventMap[K]) => any): void {
731
- this.eventListeners[type].push(listener);
732
- }
733
-
734
- removeEventListener<K extends keyof WebSocketEventMap>(type: K, listener: (this: WebSocket, ev: WebSocketEventMap[K]) => any): void {
735
- const listeners = this.eventListeners[type];
736
- const index = listeners.indexOf(listener);
737
- if (index !== -1) {
738
- listeners.splice(index, 1);
739
- }
740
- }
741
- }
742
-
743
392
  async function toUint8Array(data: string | ArrayBufferLike | Blob | ArrayBufferView): Promise<Uint8Array<ArrayBufferLike>> {
744
393
  if (typeof data === 'string') {
745
394
  return textEncoder.encode(data);
@@ -0,0 +1,79 @@
1
+ import { ByteReader, ByteWriter, JsonType } from '../../serialize';
2
+
3
+ export type RequestHandle = {
4
+ id: string;
5
+ };
6
+
7
+ export type HttpRequest = RequestHandle & {
8
+ header: Record<string, string>;
9
+ method: string;
10
+ redirect: RequestRedirect;
11
+ url: string;
12
+ };
13
+
14
+ export class DataChunk<T extends JsonType> {
15
+ constructor(
16
+ public readonly meta: T,
17
+ public readonly body: Uint8Array,
18
+ ) { }
19
+
20
+ public static serialize<T extends JsonType>(data: DataChunk<T>): Uint8Array {
21
+ const writer = new ByteWriter();
22
+ writer.writeJSON(data.meta);
23
+ writer.writeUint8Array(data.body);
24
+ return writer.finish();
25
+ }
26
+
27
+ public static deserialize<T extends JsonType>(data: Uint8Array): DataChunk<T> {
28
+ const reader = ByteReader.fromUint8Array(data);
29
+ const meta = reader.readJSON<T>();
30
+ const body = reader.readUint8Array();
31
+ return new DataChunk(meta, body);
32
+ }
33
+ }
34
+
35
+ export class OmuResponse implements Response {
36
+ constructor(
37
+ public readonly headers: Headers,
38
+ public readonly ok: boolean,
39
+ public readonly redirected: boolean,
40
+ public readonly status: number,
41
+ public readonly statusText: string,
42
+ public readonly type: ResponseType,
43
+ public readonly url: string,
44
+ public readonly body: ReadableStream<Uint8Array<ArrayBuffer>> | null,
45
+ public readonly bodyUsed: boolean,
46
+ ) {}
47
+
48
+ clone(): OmuResponse {
49
+ return new OmuResponse(
50
+ this.headers,
51
+ this.ok,
52
+ this.redirected,
53
+ this.status,
54
+ this.statusText,
55
+ this.type,
56
+ this.url,
57
+ this.body,
58
+ this.bodyUsed,
59
+ );
60
+ }
61
+ async arrayBuffer(): Promise<ArrayBuffer> {
62
+ return await new Response(this.body).arrayBuffer();
63
+ }
64
+ blob(): Promise<Blob> {
65
+ return new Response(this.body).blob();
66
+ }
67
+ bytes(): Promise<Uint8Array<ArrayBuffer>> {
68
+ return new Response(this.body).arrayBuffer().then((buf) => new Uint8Array(buf));
69
+ }
70
+ formData(): Promise<FormData> {
71
+ return new Response(this.body).formData();
72
+ }
73
+ json(): Promise<any> {
74
+ return new Response(this.body).json();
75
+ }
76
+ text(): Promise<string> {
77
+ return new Response(this.body).text();
78
+ }
79
+ }