cojson 0.8.11 → 0.8.16

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 (158) hide show
  1. package/CHANGELOG.md +94 -82
  2. package/dist/native/PeerKnownStates.js +1 -1
  3. package/dist/native/PeerKnownStates.js.map +1 -1
  4. package/dist/native/PeerState.js +4 -1
  5. package/dist/native/PeerState.js.map +1 -1
  6. package/dist/native/PriorityBasedMessageQueue.js +1 -10
  7. package/dist/native/PriorityBasedMessageQueue.js.map +1 -1
  8. package/dist/native/base64url.js.map +1 -1
  9. package/dist/native/base64url.test.js +1 -1
  10. package/dist/native/base64url.test.js.map +1 -1
  11. package/dist/native/coValue.js.map +1 -1
  12. package/dist/native/coValueCore.js +141 -149
  13. package/dist/native/coValueCore.js.map +1 -1
  14. package/dist/native/coValueState.js.map +1 -1
  15. package/dist/native/coValues/account.js +6 -6
  16. package/dist/native/coValues/account.js.map +1 -1
  17. package/dist/native/coValues/coList.js +2 -3
  18. package/dist/native/coValues/coList.js.map +1 -1
  19. package/dist/native/coValues/coMap.js +1 -1
  20. package/dist/native/coValues/coMap.js.map +1 -1
  21. package/dist/native/coValues/coStream.js +3 -5
  22. package/dist/native/coValues/coStream.js.map +1 -1
  23. package/dist/native/coValues/group.js +11 -11
  24. package/dist/native/coValues/group.js.map +1 -1
  25. package/dist/native/coreToCoValue.js +2 -2
  26. package/dist/native/coreToCoValue.js.map +1 -1
  27. package/dist/native/crypto/PureJSCrypto.js +4 -4
  28. package/dist/native/crypto/PureJSCrypto.js.map +1 -1
  29. package/dist/native/crypto/crypto.js.map +1 -1
  30. package/dist/native/exports.js +12 -12
  31. package/dist/native/exports.js.map +1 -1
  32. package/dist/native/ids.js.map +1 -1
  33. package/dist/native/jsonStringify.js.map +1 -1
  34. package/dist/native/localNode.js +6 -8
  35. package/dist/native/localNode.js.map +1 -1
  36. package/dist/native/permissions.js +4 -7
  37. package/dist/native/permissions.js.map +1 -1
  38. package/dist/native/priority.js.map +1 -1
  39. package/dist/native/storage/FileSystem.js.map +1 -1
  40. package/dist/native/storage/chunksAndKnownStates.js +2 -4
  41. package/dist/native/storage/chunksAndKnownStates.js.map +1 -1
  42. package/dist/native/storage/index.js +7 -16
  43. package/dist/native/storage/index.js.map +1 -1
  44. package/dist/native/streamUtils.js.map +1 -1
  45. package/dist/native/sync.js +6 -8
  46. package/dist/native/sync.js.map +1 -1
  47. package/dist/native/typeUtils/accountOrAgentIDfromSessionID.js.map +1 -1
  48. package/dist/native/typeUtils/expectGroup.js.map +1 -1
  49. package/dist/native/typeUtils/isAccountID.js.map +1 -1
  50. package/dist/native/typeUtils/isCoValue.js +1 -1
  51. package/dist/native/typeUtils/isCoValue.js.map +1 -1
  52. package/dist/web/PeerKnownStates.js +1 -1
  53. package/dist/web/PeerKnownStates.js.map +1 -1
  54. package/dist/web/PeerState.js +4 -1
  55. package/dist/web/PeerState.js.map +1 -1
  56. package/dist/web/PriorityBasedMessageQueue.js +1 -10
  57. package/dist/web/PriorityBasedMessageQueue.js.map +1 -1
  58. package/dist/web/base64url.js.map +1 -1
  59. package/dist/web/base64url.test.js +1 -1
  60. package/dist/web/base64url.test.js.map +1 -1
  61. package/dist/web/coValue.js.map +1 -1
  62. package/dist/web/coValueCore.js +141 -149
  63. package/dist/web/coValueCore.js.map +1 -1
  64. package/dist/web/coValueState.js.map +1 -1
  65. package/dist/web/coValues/account.js +6 -6
  66. package/dist/web/coValues/account.js.map +1 -1
  67. package/dist/web/coValues/coList.js +2 -3
  68. package/dist/web/coValues/coList.js.map +1 -1
  69. package/dist/web/coValues/coMap.js +1 -1
  70. package/dist/web/coValues/coMap.js.map +1 -1
  71. package/dist/web/coValues/coStream.js +3 -5
  72. package/dist/web/coValues/coStream.js.map +1 -1
  73. package/dist/web/coValues/group.js +11 -11
  74. package/dist/web/coValues/group.js.map +1 -1
  75. package/dist/web/coreToCoValue.js +2 -2
  76. package/dist/web/coreToCoValue.js.map +1 -1
  77. package/dist/web/crypto/PureJSCrypto.js +4 -4
  78. package/dist/web/crypto/PureJSCrypto.js.map +1 -1
  79. package/dist/web/crypto/WasmCrypto.js +5 -5
  80. package/dist/web/crypto/WasmCrypto.js.map +1 -1
  81. package/dist/web/crypto/crypto.js.map +1 -1
  82. package/dist/web/exports.js +12 -12
  83. package/dist/web/exports.js.map +1 -1
  84. package/dist/web/ids.js.map +1 -1
  85. package/dist/web/jsonStringify.js.map +1 -1
  86. package/dist/web/localNode.js +6 -8
  87. package/dist/web/localNode.js.map +1 -1
  88. package/dist/web/permissions.js +4 -7
  89. package/dist/web/permissions.js.map +1 -1
  90. package/dist/web/priority.js.map +1 -1
  91. package/dist/web/storage/FileSystem.js.map +1 -1
  92. package/dist/web/storage/chunksAndKnownStates.js +2 -4
  93. package/dist/web/storage/chunksAndKnownStates.js.map +1 -1
  94. package/dist/web/storage/index.js +7 -16
  95. package/dist/web/storage/index.js.map +1 -1
  96. package/dist/web/streamUtils.js.map +1 -1
  97. package/dist/web/sync.js +6 -8
  98. package/dist/web/sync.js.map +1 -1
  99. package/dist/web/typeUtils/accountOrAgentIDfromSessionID.js.map +1 -1
  100. package/dist/web/typeUtils/expectGroup.js.map +1 -1
  101. package/dist/web/typeUtils/isAccountID.js.map +1 -1
  102. package/dist/web/typeUtils/isCoValue.js +1 -1
  103. package/dist/web/typeUtils/isCoValue.js.map +1 -1
  104. package/package.json +4 -14
  105. package/src/PeerKnownStates.ts +91 -89
  106. package/src/PeerState.ts +72 -69
  107. package/src/PriorityBasedMessageQueue.ts +42 -49
  108. package/src/base64url.test.ts +24 -24
  109. package/src/base64url.ts +44 -45
  110. package/src/coValue.ts +45 -45
  111. package/src/coValueCore.ts +746 -785
  112. package/src/coValueState.ts +82 -72
  113. package/src/coValues/account.ts +143 -150
  114. package/src/coValues/coList.ts +520 -522
  115. package/src/coValues/coMap.ts +283 -285
  116. package/src/coValues/coStream.ts +320 -324
  117. package/src/coValues/group.ts +306 -305
  118. package/src/coreToCoValue.ts +28 -31
  119. package/src/crypto/PureJSCrypto.ts +188 -194
  120. package/src/crypto/WasmCrypto.ts +236 -254
  121. package/src/crypto/crypto.ts +302 -309
  122. package/src/exports.ts +116 -116
  123. package/src/ids.ts +9 -9
  124. package/src/jsonStringify.ts +46 -46
  125. package/src/jsonValue.ts +24 -10
  126. package/src/localNode.ts +635 -660
  127. package/src/media.ts +3 -3
  128. package/src/permissions.ts +272 -278
  129. package/src/priority.ts +21 -19
  130. package/src/storage/FileSystem.ts +91 -99
  131. package/src/storage/chunksAndKnownStates.ts +110 -115
  132. package/src/storage/index.ts +466 -497
  133. package/src/streamUtils.ts +60 -60
  134. package/src/sync.ts +593 -615
  135. package/src/tests/PeerKnownStates.test.ts +38 -34
  136. package/src/tests/PeerState.test.ts +101 -64
  137. package/src/tests/PriorityBasedMessageQueue.test.ts +91 -91
  138. package/src/tests/account.test.ts +59 -59
  139. package/src/tests/coList.test.ts +65 -65
  140. package/src/tests/coMap.test.ts +137 -137
  141. package/src/tests/coStream.test.ts +254 -257
  142. package/src/tests/coValueCore.test.ts +153 -156
  143. package/src/tests/crypto.test.ts +136 -144
  144. package/src/tests/cryptoImpl.test.ts +205 -197
  145. package/src/tests/group.test.ts +24 -24
  146. package/src/tests/permissions.test.ts +1306 -1371
  147. package/src/tests/priority.test.ts +65 -82
  148. package/src/tests/sync.test.ts +1300 -1291
  149. package/src/tests/testUtils.ts +52 -53
  150. package/src/typeUtils/accountOrAgentIDfromSessionID.ts +4 -4
  151. package/src/typeUtils/expectGroup.ts +9 -9
  152. package/src/typeUtils/isAccountID.ts +1 -1
  153. package/src/typeUtils/isCoValue.ts +9 -9
  154. package/tsconfig.json +4 -6
  155. package/tsconfig.native.json +9 -11
  156. package/tsconfig.web.json +4 -10
  157. package/.eslintrc.cjs +0 -25
  158. package/.prettierrc.js +0 -9
@@ -1,108 +1,110 @@
1
1
  import { RawCoID, SessionID } from "./ids.js";
2
- import { CoValueKnownState, emptyKnownState, combinedKnownStates } from "./sync.js";
2
+ import {
3
+ CoValueKnownState,
4
+ combinedKnownStates,
5
+ emptyKnownState,
6
+ } from "./sync.js";
3
7
 
4
- type PeerKnownStateActions = {
5
- type: "SET_AS_EMPTY";
6
- id: RawCoID;
7
- } | {
8
- type: "UPDATE_HEADER";
9
- id: RawCoID;
10
- header: boolean;
11
- } |
12
- {
13
- type: "UPDATE_SESSION_COUNTER";
14
- id: RawCoID;
15
- sessionId: SessionID;
16
- value: number;
17
- } |
18
- {
19
- type: "SET";
20
- id: RawCoID;
21
- value: CoValueKnownState;
22
- } |
23
- {
24
- type: "COMBINE_WITH";
25
- id: RawCoID;
26
- value: CoValueKnownState;
27
- };
8
+ type PeerKnownStateActions =
9
+ | {
10
+ type: "SET_AS_EMPTY";
11
+ id: RawCoID;
12
+ }
13
+ | {
14
+ type: "UPDATE_HEADER";
15
+ id: RawCoID;
16
+ header: boolean;
17
+ }
18
+ | {
19
+ type: "UPDATE_SESSION_COUNTER";
20
+ id: RawCoID;
21
+ sessionId: SessionID;
22
+ value: number;
23
+ }
24
+ | {
25
+ type: "SET";
26
+ id: RawCoID;
27
+ value: CoValueKnownState;
28
+ }
29
+ | {
30
+ type: "COMBINE_WITH";
31
+ id: RawCoID;
32
+ value: CoValueKnownState;
33
+ };
28
34
 
29
35
  export class PeerKnownStates {
30
- private coValues = new Map<RawCoID, CoValueKnownState>();
36
+ private coValues = new Map<RawCoID, CoValueKnownState>();
31
37
 
32
- private updateHeader(id: RawCoID, header: boolean) {
33
- const knownState = this.coValues.get(id) ?? emptyKnownState(id);
34
- knownState.header = header;
35
- this.coValues.set(id, knownState);
36
- }
38
+ private updateHeader(id: RawCoID, header: boolean) {
39
+ const knownState = this.coValues.get(id) ?? emptyKnownState(id);
40
+ knownState.header = header;
41
+ this.coValues.set(id, knownState);
42
+ }
37
43
 
38
- private combineWith(id: RawCoID, value: CoValueKnownState) {
39
- const knownState = this.coValues.get(id) ?? emptyKnownState(id);
40
- this.coValues.set(id, combinedKnownStates(knownState, value));
41
- }
44
+ private combineWith(id: RawCoID, value: CoValueKnownState) {
45
+ const knownState = this.coValues.get(id) ?? emptyKnownState(id);
46
+ this.coValues.set(id, combinedKnownStates(knownState, value));
47
+ }
42
48
 
43
- private updateSessionCounter(
44
- id: RawCoID,
45
- sessionId: SessionID,
46
- value: number
47
- ) {
48
- const knownState = this.coValues.get(id) ?? emptyKnownState(id);
49
- const currentValue = knownState.sessions[sessionId] || 0;
50
- knownState.sessions[sessionId] = Math.max(currentValue, value);
49
+ private updateSessionCounter(
50
+ id: RawCoID,
51
+ sessionId: SessionID,
52
+ value: number,
53
+ ) {
54
+ const knownState = this.coValues.get(id) ?? emptyKnownState(id);
55
+ const currentValue = knownState.sessions[sessionId] || 0;
56
+ knownState.sessions[sessionId] = Math.max(currentValue, value);
51
57
 
52
- this.coValues.set(id, knownState);
53
- }
58
+ this.coValues.set(id, knownState);
59
+ }
54
60
 
55
- get(id: RawCoID) {
56
- return this.coValues.get(id);
57
- }
58
-
59
- has(id: RawCoID) {
60
- return this.coValues.has(id);
61
- }
61
+ get(id: RawCoID) {
62
+ return this.coValues.get(id);
63
+ }
62
64
 
63
- dispatch(action: PeerKnownStateActions) {
64
- switch (action.type) {
65
- case "UPDATE_HEADER":
66
- this.updateHeader(action.id, action.header);
67
- break;
68
- case "UPDATE_SESSION_COUNTER":
69
- this.updateSessionCounter(
70
- action.id,
71
- action.sessionId,
72
- action.value
73
- );
74
- break;
75
- case "SET":
76
- this.coValues.set(action.id, action.value);
77
- break;
78
- case "COMBINE_WITH":
79
- this.combineWith(action.id, action.value);
80
- break;
81
- case "SET_AS_EMPTY":
82
- this.coValues.set(action.id, emptyKnownState(action.id));
83
- break;
84
- }
65
+ has(id: RawCoID) {
66
+ return this.coValues.has(id);
67
+ }
85
68
 
86
- this.triggerUpdate(action.id);
69
+ dispatch(action: PeerKnownStateActions) {
70
+ switch (action.type) {
71
+ case "UPDATE_HEADER":
72
+ this.updateHeader(action.id, action.header);
73
+ break;
74
+ case "UPDATE_SESSION_COUNTER":
75
+ this.updateSessionCounter(action.id, action.sessionId, action.value);
76
+ break;
77
+ case "SET":
78
+ this.coValues.set(action.id, action.value);
79
+ break;
80
+ case "COMBINE_WITH":
81
+ this.combineWith(action.id, action.value);
82
+ break;
83
+ case "SET_AS_EMPTY":
84
+ this.coValues.set(action.id, emptyKnownState(action.id));
85
+ break;
87
86
  }
88
87
 
89
- listeners = new Set<(id: RawCoID, knownState: CoValueKnownState) => void>();
88
+ this.triggerUpdate(action.id);
89
+ }
90
90
 
91
- triggerUpdate(id: RawCoID) {
92
- this.trigger(id, this.coValues.get(id) ?? emptyKnownState(id));
93
- }
91
+ listeners = new Set<(id: RawCoID, knownState: CoValueKnownState) => void>();
92
+
93
+ triggerUpdate(id: RawCoID) {
94
+ this.trigger(id, this.coValues.get(id) ?? emptyKnownState(id));
95
+ }
94
96
 
95
- private trigger(id: RawCoID, knownState: CoValueKnownState) {
96
- for (const listener of this.listeners) {
97
- listener(id, knownState);
98
- }
97
+ private trigger(id: RawCoID, knownState: CoValueKnownState) {
98
+ for (const listener of this.listeners) {
99
+ listener(id, knownState);
99
100
  }
101
+ }
100
102
 
101
- subscribe(listener: (id: RawCoID, knownState: CoValueKnownState) => void) {
102
- this.listeners.add(listener);
103
+ subscribe(listener: (id: RawCoID, knownState: CoValueKnownState) => void) {
104
+ this.listeners.add(listener);
103
105
 
104
- return () => {
105
- this.listeners.delete(listener);
106
- };
107
- }
106
+ return () => {
107
+ this.listeners.delete(listener);
108
+ };
109
+ }
108
110
  }
package/src/PeerState.ts CHANGED
@@ -1,87 +1,90 @@
1
- import { RawCoID } from "./ids.js";
2
1
  import { PeerKnownStates } from "./PeerKnownStates.js";
3
- import { CO_VALUE_PRIORITY } from "./priority.js";
4
2
  import {
5
- PriorityBasedMessageQueue,
6
- QueueEntry,
3
+ PriorityBasedMessageQueue,
4
+ QueueEntry,
7
5
  } from "./PriorityBasedMessageQueue.js";
6
+ import { RawCoID } from "./ids.js";
7
+ import { CO_VALUE_PRIORITY } from "./priority.js";
8
8
  import { Peer, SyncMessage } from "./sync.js";
9
9
 
10
10
  export class PeerState {
11
- constructor(private peer: Peer) {}
12
-
13
- readonly optimisticKnownStates = new PeerKnownStates();
14
- readonly toldKnownState: Set<RawCoID> = new Set();
15
-
16
- get id() {
17
- return this.peer.id;
11
+ constructor(private peer: Peer) {}
12
+
13
+ readonly optimisticKnownStates = new PeerKnownStates();
14
+ readonly toldKnownState: Set<RawCoID> = new Set();
15
+
16
+ get id() {
17
+ return this.peer.id;
18
+ }
19
+
20
+ get role() {
21
+ return this.peer.role;
22
+ }
23
+
24
+ get priority() {
25
+ return this.peer.priority;
26
+ }
27
+
28
+ get crashOnClose() {
29
+ return this.peer.crashOnClose;
30
+ }
31
+
32
+ isServerOrStoragePeer() {
33
+ return this.peer.role === "server" || this.peer.role === "storage";
34
+ }
35
+
36
+ /**
37
+ * We set as default priority HIGH to handle all the messages without a
38
+ * priority property as HIGH priority.
39
+ *
40
+ * This way we consider all the non-content messsages as HIGH priority.
41
+ */
42
+ private queue = new PriorityBasedMessageQueue(CO_VALUE_PRIORITY.HIGH);
43
+ private processing = false;
44
+ public closed = false;
45
+
46
+ async processQueue() {
47
+ if (this.processing) {
48
+ return;
18
49
  }
19
50
 
20
- get role() {
21
- return this.peer.role;
51
+ this.processing = true;
52
+
53
+ let entry: QueueEntry | undefined;
54
+ while ((entry = this.queue.pull())) {
55
+ // Awaiting the push to send one message at a time
56
+ // This way when the peer is "under pressure" we can enqueue all
57
+ // the coming messages and organize them by priority
58
+ await this.peer.outgoing
59
+ .push(entry.msg)
60
+ .then(entry.resolve)
61
+ .catch(entry.reject);
22
62
  }
23
63
 
24
- get priority() {
25
- return this.peer.priority;
26
- }
64
+ this.processing = false;
65
+ }
27
66
 
28
- get crashOnClose() {
29
- return this.peer.crashOnClose;
30
- }
31
-
32
- /**
33
- * We set as default priority HIGH to handle all the messages without a
34
- * priority property as HIGH priority.
35
- *
36
- * This way we consider all the non-content messsages as HIGH priority.
37
- */
38
- private queue = new PriorityBasedMessageQueue(CO_VALUE_PRIORITY.HIGH);
39
- private processing = false;
40
- public closed = false;
41
-
42
- async processQueue() {
43
- if (this.processing) {
44
- return;
45
- }
46
-
47
- this.processing = true;
48
-
49
-
50
- let entry: QueueEntry | undefined;
51
- while ((entry = this.queue.pull())) {
52
- // Awaiting the push to send one message at a time
53
- // This way when the peer is "under pressure" we can enqueue all
54
- // the coming messages and organize them by priority
55
- await this.peer.outgoing
56
- .push(entry.msg)
57
- .then(entry.resolve)
58
- .catch(entry.reject);
59
- }
60
-
61
- this.processing = false;
62
- }
67
+ pushOutgoingMessage(msg: SyncMessage) {
68
+ const promise = this.queue.push(msg);
63
69
 
64
- pushOutgoingMessage(msg: SyncMessage) {
65
- const promise = this.queue.push(msg);
70
+ void this.processQueue();
66
71
 
67
- void this.processQueue();
72
+ return promise;
73
+ }
68
74
 
69
- return promise;
75
+ get incoming() {
76
+ if (this.closed) {
77
+ return (async function* () {
78
+ yield "Disconnected" as const;
79
+ })();
70
80
  }
71
81
 
72
- get incoming() {
73
- if (this.closed) {
74
- return (async function* () {
75
- yield "Disconnected" as const;
76
- })();
77
- }
82
+ return this.peer.incoming;
83
+ }
78
84
 
79
- return this.peer.incoming;
80
- }
81
-
82
- gracefulShutdown() {
83
- console.debug("Gracefully closing", this.id);
84
- this.peer.outgoing.close();
85
- this.closed = true;
86
- }
85
+ gracefulShutdown() {
86
+ console.debug("Gracefully closing", this.id);
87
+ this.peer.outgoing.close();
88
+ this.closed = true;
89
+ }
87
90
  }
@@ -2,76 +2,69 @@ import { CoValuePriority } from "./priority.js";
2
2
  import { SyncMessage } from "./sync.js";
3
3
 
4
4
  function promiseWithResolvers<R>() {
5
- let resolve = (_: R) => {};
6
- let reject = (_: unknown) => {};
5
+ let resolve = (_: R) => {};
6
+ let reject = (_: unknown) => {};
7
7
 
8
- const promise = new Promise<R>((_resolve, _reject) => {
9
- resolve = _resolve;
10
- reject = _reject;
11
- });
8
+ const promise = new Promise<R>((_resolve, _reject) => {
9
+ resolve = _resolve;
10
+ reject = _reject;
11
+ });
12
12
 
13
- return {
14
- promise,
15
- resolve,
16
- reject,
17
- };
13
+ return {
14
+ promise,
15
+ resolve,
16
+ reject,
17
+ };
18
18
  }
19
19
 
20
20
  export type QueueEntry = {
21
- msg: SyncMessage;
22
- promise: Promise<void>;
23
- resolve: () => void;
24
- reject: (_: unknown) => void;
21
+ msg: SyncMessage;
22
+ promise: Promise<void>;
23
+ resolve: () => void;
24
+ reject: (_: unknown) => void;
25
25
  };
26
26
 
27
27
  /**
28
28
  * Since we have a fixed range of priority values (0-7) we can create a fixed array of queues.
29
29
  */
30
- type Tuple<T, N extends number, A extends unknown[] = []> = A extends { length: N } ? A : Tuple<T, N, [...A, T]>;
30
+ type Tuple<T, N extends number, A extends unknown[] = []> = A extends {
31
+ length: N;
32
+ }
33
+ ? A
34
+ : Tuple<T, N, [...A, T]>;
31
35
  type QueueTuple = Tuple<QueueEntry[], 8>;
32
36
 
33
37
  export class PriorityBasedMessageQueue {
34
- private queues: QueueTuple = [
35
- [],
36
- [],
37
- [],
38
- [],
39
- [],
40
- [],
41
- [],
42
- [],
43
- ];
44
-
45
- private getQueue(priority: CoValuePriority) {
46
- return this.queues[priority];
47
- }
38
+ private queues: QueueTuple = [[], [], [], [], [], [], [], []];
48
39
 
49
- constructor(
50
- private defaultPriority: CoValuePriority,
51
- ) {}
40
+ private getQueue(priority: CoValuePriority) {
41
+ return this.queues[priority];
42
+ }
52
43
 
53
- public push(msg: SyncMessage) {
54
- const { promise, resolve, reject } = promiseWithResolvers<void>();
55
- const entry: QueueEntry = { msg, promise, resolve, reject };
44
+ constructor(private defaultPriority: CoValuePriority) {}
56
45
 
57
- if ("priority" in msg) {
58
- const queue = this.getQueue(msg.priority);
46
+ public push(msg: SyncMessage) {
47
+ const { promise, resolve, reject } = promiseWithResolvers<void>();
48
+ const entry: QueueEntry = { msg, promise, resolve, reject };
59
49
 
60
- queue?.push(entry);
61
- } else {
62
- this.getQueue(this.defaultPriority).push(entry);
63
- }
50
+ if ("priority" in msg) {
51
+ const queue = this.getQueue(msg.priority);
64
52
 
65
- return promise;
53
+ queue?.push(entry);
54
+ } else {
55
+ this.getQueue(this.defaultPriority).push(entry);
66
56
  }
67
57
 
68
- public pull() {
69
- const activeQueue = this.queues.find((queue) => queue.length > 0);
58
+ return promise;
59
+ }
70
60
 
71
- if (!activeQueue) {
72
- return undefined;
73
- }
61
+ public pull() {
62
+ const activeQueue = this.queues.find((queue) => queue.length > 0);
74
63
 
75
- return activeQueue.shift();
64
+ if (!activeQueue) {
65
+ return undefined;
76
66
  }
67
+
68
+ return activeQueue.shift();
69
+ }
77
70
  }
@@ -1,33 +1,33 @@
1
+ import { expect, test } from "vitest";
1
2
  import { base64URLtoBytes, bytesToBase64url } from "./base64url.js";
2
- import { test, expect } from "vitest";
3
3
 
4
4
  const txt = new TextEncoder();
5
5
 
6
6
  test("Test our Base64 URL encoding and decoding", () => {
7
- // tests from the RFC
7
+ // tests from the RFC
8
8
 
9
- expect(base64URLtoBytes("")).toEqual(new Uint8Array([]));
10
- expect(bytesToBase64url(new Uint8Array([]))).toEqual("");
9
+ expect(base64URLtoBytes("")).toEqual(new Uint8Array([]));
10
+ expect(bytesToBase64url(new Uint8Array([]))).toEqual("");
11
11
 
12
- expect(bytesToBase64url(txt.encode("f"))).toEqual("Zg==");
13
- expect(bytesToBase64url(txt.encode("fo"))).toEqual("Zm8=");
14
- expect(bytesToBase64url(txt.encode("foo"))).toEqual("Zm9v");
15
- expect(bytesToBase64url(txt.encode("foob"))).toEqual("Zm9vYg==");
16
- expect(bytesToBase64url(txt.encode("fooba"))).toEqual("Zm9vYmE=");
17
- expect(bytesToBase64url(txt.encode("foobar"))).toEqual("Zm9vYmFy");
18
- // reverse
19
- expect(base64URLtoBytes("Zg==")).toEqual(txt.encode("f"));
20
- expect(base64URLtoBytes("Zm8=")).toEqual(txt.encode("fo"));
21
- expect(base64URLtoBytes("Zm9v")).toEqual(txt.encode("foo"));
22
- expect(base64URLtoBytes("Zm9vYg==")).toEqual(txt.encode("foob"));
23
- expect(base64URLtoBytes("Zm9vYmE=")).toEqual(txt.encode("fooba"));
24
- expect(base64URLtoBytes("Zm9vYmFy")).toEqual(txt.encode("foobar"));
12
+ expect(bytesToBase64url(txt.encode("f"))).toEqual("Zg==");
13
+ expect(bytesToBase64url(txt.encode("fo"))).toEqual("Zm8=");
14
+ expect(bytesToBase64url(txt.encode("foo"))).toEqual("Zm9v");
15
+ expect(bytesToBase64url(txt.encode("foob"))).toEqual("Zm9vYg==");
16
+ expect(bytesToBase64url(txt.encode("fooba"))).toEqual("Zm9vYmE=");
17
+ expect(bytesToBase64url(txt.encode("foobar"))).toEqual("Zm9vYmFy");
18
+ // reverse
19
+ expect(base64URLtoBytes("Zg==")).toEqual(txt.encode("f"));
20
+ expect(base64URLtoBytes("Zm8=")).toEqual(txt.encode("fo"));
21
+ expect(base64URLtoBytes("Zm9v")).toEqual(txt.encode("foo"));
22
+ expect(base64URLtoBytes("Zm9vYg==")).toEqual(txt.encode("foob"));
23
+ expect(base64URLtoBytes("Zm9vYmE=")).toEqual(txt.encode("fooba"));
24
+ expect(base64URLtoBytes("Zm9vYmFy")).toEqual(txt.encode("foobar"));
25
25
 
26
- expect(
27
- base64URLtoBytes("V2hhdCBkb2VzIDIgKyAyLjEgZXF1YWw_PyB-IDQ="),
28
- ).toEqual(txt.encode("What does 2 + 2.1 equal?? ~ 4"));
29
- // reverse
30
- expect(
31
- bytesToBase64url(txt.encode("What does 2 + 2.1 equal?? ~ 4")),
32
- ).toEqual("V2hhdCBkb2VzIDIgKyAyLjEgZXF1YWw_PyB-IDQ=");
26
+ expect(base64URLtoBytes("V2hhdCBkb2VzIDIgKyAyLjEgZXF1YWw_PyB-IDQ=")).toEqual(
27
+ txt.encode("What does 2 + 2.1 equal?? ~ 4"),
28
+ );
29
+ // reverse
30
+ expect(bytesToBase64url(txt.encode("What does 2 + 2.1 equal?? ~ 4"))).toEqual(
31
+ "V2hhdCBkb2VzIDIgKyAyLjEgZXF1YWw_PyB-IDQ=",
32
+ );
33
33
  });
package/src/base64url.ts CHANGED
@@ -2,67 +2,66 @@ const encoder = new TextEncoder();
2
2
  const decoder = new TextDecoder();
3
3
 
4
4
  export function base64URLtoBytes(base64: string) {
5
- base64 = base64.replace(/=/g, "");
6
- const n = base64.length;
7
- const rem = n % 4;
8
- const k = rem && rem - 1; // how many bytes the last base64 chunk encodes
9
- const m = (n >> 2) * 3 + k; // total encoded bytes
5
+ base64 = base64.replace(/=/g, "");
6
+ const n = base64.length;
7
+ const rem = n % 4;
8
+ const k = rem && rem - 1; // how many bytes the last base64 chunk encodes
9
+ const m = (n >> 2) * 3 + k; // total encoded bytes
10
10
 
11
- const encoded = new Uint8Array(n + 3);
12
- encoder.encodeInto(base64 + "===", encoded);
11
+ const encoded = new Uint8Array(n + 3);
12
+ encoder.encodeInto(base64 + "===", encoded);
13
13
 
14
- for (let i = 0, j = 0; i < n; i += 4, j += 3) {
15
- const x =
16
- (lookup[encoded[i]!]! << 18) +
17
- (lookup[encoded[i + 1]!]! << 12) +
18
- (lookup[encoded[i + 2]!]! << 6) +
19
- lookup[encoded[i + 3]!]!;
20
- encoded[j] = x >> 16;
21
- encoded[j + 1] = (x >> 8) & 0xff;
22
- encoded[j + 2] = x & 0xff;
23
- }
24
- return new Uint8Array(encoded.buffer, 0, m);
14
+ for (let i = 0, j = 0; i < n; i += 4, j += 3) {
15
+ const x =
16
+ (lookup[encoded[i]!]! << 18) +
17
+ (lookup[encoded[i + 1]!]! << 12) +
18
+ (lookup[encoded[i + 2]!]! << 6) +
19
+ lookup[encoded[i + 3]!]!;
20
+ encoded[j] = x >> 16;
21
+ encoded[j + 1] = (x >> 8) & 0xff;
22
+ encoded[j + 2] = x & 0xff;
23
+ }
24
+ return new Uint8Array(encoded.buffer, 0, m);
25
25
  }
26
26
 
27
27
  export function bytesToBase64url(bytes: Uint8Array) {
28
- // const before = performance.now();
29
- const m = bytes.length;
30
- const k = m % 3;
31
- const n = Math.floor(m / 3) * 4 + (k && k + 1);
32
- const N = Math.ceil(m / 3) * 4;
33
- const encoded = new Uint8Array(N);
28
+ // const before = performance.now();
29
+ const m = bytes.length;
30
+ const k = m % 3;
31
+ const n = Math.floor(m / 3) * 4 + (k && k + 1);
32
+ const N = Math.ceil(m / 3) * 4;
33
+ const encoded = new Uint8Array(N);
34
34
 
35
- for (let i = 0, j = 0; j < m; i += 4, j += 3) {
36
- const y =
37
- (bytes[j]! << 16) + (bytes[j + 1]! << 8) + (bytes[j + 2]! | 0);
38
- encoded[i] = encodeLookup[y >> 18]!;
39
- encoded[i + 1] = encodeLookup[(y >> 12) & 0x3f]!;
40
- encoded[i + 2] = encodeLookup[(y >> 6) & 0x3f]!;
41
- encoded[i + 3] = encodeLookup[y & 0x3f]!;
42
- }
35
+ for (let i = 0, j = 0; j < m; i += 4, j += 3) {
36
+ const y = (bytes[j]! << 16) + (bytes[j + 1]! << 8) + (bytes[j + 2]! | 0);
37
+ encoded[i] = encodeLookup[y >> 18]!;
38
+ encoded[i + 1] = encodeLookup[(y >> 12) & 0x3f]!;
39
+ encoded[i + 2] = encodeLookup[(y >> 6) & 0x3f]!;
40
+ encoded[i + 3] = encodeLookup[y & 0x3f]!;
41
+ }
43
42
 
44
- let base64 = decoder.decode(new Uint8Array(encoded.buffer, 0, n));
45
- if (k === 1) base64 += "==";
46
- if (k === 2) base64 += "=";
47
- // const after = performance.now();
48
- // console.log(
49
- // "bytesToBase64url bandwidth in MB/s for length",
50
- // (1000 * bytes.length / (after - before)) / (1024 * 1024),
51
- // bytes.length
52
- // );
53
- return base64;
43
+ let base64 = decoder.decode(new Uint8Array(encoded.buffer, 0, n));
44
+ if (k === 1) base64 += "==";
45
+ if (k === 2) base64 += "=";
46
+ // const after = performance.now();
47
+ // console.log(
48
+ // "bytesToBase64url bandwidth in MB/s for length",
49
+ // (1000 * bytes.length / (after - before)) / (1024 * 1024),
50
+ // bytes.length
51
+ // );
52
+ return base64;
54
53
  }
55
54
 
56
55
  const alphabet =
57
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
56
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
58
57
 
59
58
  const lookup = new Uint8Array(128);
60
59
  for (const [i, a] of Array.from(alphabet).entries()) {
61
- lookup[a.charCodeAt(0)] = i;
60
+ lookup[a.charCodeAt(0)] = i;
62
61
  }
63
62
  lookup["=".charCodeAt(0)] = 0;
64
63
 
65
64
  const encodeLookup = new Uint8Array(64);
66
65
  for (const [i, a] of Array.from(alphabet).entries()) {
67
- encodeLookup[i] = a.charCodeAt(0);
66
+ encodeLookup[i] = a.charCodeAt(0);
68
67
  }