@dxos/util 0.4.7-main.33db07e โ†’ 0.4.7-main.340e96b

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/util",
3
- "version": "0.4.7-main.33db07e",
3
+ "version": "0.4.7-main.340e96b",
4
4
  "description": "Temporary bucket for misc functions, which should graduate into separate packages.",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -16,13 +16,13 @@
16
16
  "src"
17
17
  ],
18
18
  "dependencies": {
19
- "@dxos/debug": "0.4.7-main.33db07e",
20
- "@dxos/invariant": "0.4.7-main.33db07e",
21
- "@dxos/keys": "0.4.7-main.33db07e",
22
- "@dxos/node-std": "0.4.7-main.33db07e"
19
+ "@dxos/debug": "0.4.7-main.340e96b",
20
+ "@dxos/invariant": "0.4.7-main.340e96b",
21
+ "@dxos/keys": "0.4.7-main.340e96b",
22
+ "@dxos/node-std": "0.4.7-main.340e96b"
23
23
  },
24
24
  "devDependencies": {
25
- "@dxos/crypto": "0.4.7-main.33db07e"
25
+ "@dxos/crypto": "0.4.7-main.340e96b"
26
26
  },
27
27
  "publishConfig": {
28
28
  "access": "public"
@@ -0,0 +1,33 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import { describe, test, expect } from 'vitest';
6
+
7
+ import { CircularBuffer } from './circular-buffer';
8
+
9
+ describe('CircularBuffer', () => {
10
+ test('single element', () => {
11
+ const buffer = new CircularBuffer<number>(1);
12
+ for (let i = 0; i < 3; i++) {
13
+ buffer.push(i);
14
+ expect([...buffer]).toStrictEqual([i]);
15
+ expect(buffer.getLast()).toStrictEqual(i);
16
+ }
17
+ });
18
+
19
+ test('full cycle', () => {
20
+ const maxSize = 10;
21
+ const regularArray: number[] = [];
22
+ const buffer = new CircularBuffer<number>(maxSize);
23
+ for (let i = 0; i < maxSize * 2 + 2; i++) {
24
+ expect([...buffer]).toStrictEqual(regularArray);
25
+ buffer.push(i);
26
+ regularArray.push(i);
27
+ if (regularArray.length > maxSize) {
28
+ regularArray.splice(0, 1);
29
+ }
30
+ expect(buffer.getLast()).toStrictEqual(i);
31
+ }
32
+ });
33
+ });
@@ -0,0 +1,54 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import { invariant } from '@dxos/invariant';
6
+
7
+ export class CircularBuffer<T> {
8
+ private readonly _buffer: T[];
9
+ private _nextIndex = 0;
10
+ private _elementCount = 0;
11
+
12
+ constructor(size: number) {
13
+ invariant(size >= 1);
14
+ this._buffer = new Array(size);
15
+ }
16
+
17
+ public push(element: T) {
18
+ this._buffer[this._nextIndex] = element;
19
+ this._nextIndex = (this._nextIndex + 1) % this._buffer.length;
20
+ this._elementCount = Math.min(this._buffer.length, this._elementCount + 1);
21
+ }
22
+
23
+ public getLast(): T | undefined {
24
+ if (this._elementCount === 0) {
25
+ return undefined;
26
+ }
27
+ if (this._nextIndex === 0) {
28
+ return this._buffer[this._buffer.length - 1];
29
+ }
30
+ return this._buffer[this._nextIndex - 1];
31
+ }
32
+
33
+ [Symbol.iterator](): IterableIterator<T> {
34
+ return this.values();
35
+ }
36
+
37
+ public *values(): IterableIterator<T> {
38
+ if (this._elementCount === 0) {
39
+ return;
40
+ }
41
+ if (this._elementCount < this._buffer.length) {
42
+ for (let i = 0; i < this._elementCount; i++) {
43
+ yield this._buffer[i];
44
+ }
45
+ return;
46
+ }
47
+ for (let i = this._nextIndex; i < this._buffer.length; i++) {
48
+ yield this._buffer[i];
49
+ }
50
+ for (let i = 0; i < this._nextIndex; i++) {
51
+ yield this._buffer[i];
52
+ }
53
+ }
54
+ }
package/src/index.ts CHANGED
@@ -8,6 +8,7 @@ export * from './bitfield';
8
8
  export * from './callback';
9
9
  export * from './complex';
10
10
  export * from './defer-function';
11
+ export * from './to-fallback';
11
12
  export * from './entry';
12
13
  export * from './human-hash';
13
14
  export * from './interval';
@@ -30,3 +31,4 @@ export * from './for-each-async';
30
31
  export * from './weak';
31
32
  export * from './map-values';
32
33
  export * from './defer';
34
+ export * from './circular-buffer';
@@ -37,7 +37,7 @@ export const getPrototypeSpecificInstanceId = (instance: any): number => {
37
37
  };
38
38
 
39
39
  export const getDebugName = (instance: any): string => {
40
- if (instance === null) {
40
+ if (instance == null) {
41
41
  return 'null';
42
42
  }
43
43
 
@@ -0,0 +1,195 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ import { type PublicKey } from '@dxos/keys';
6
+
7
+ export const idEmoji = [
8
+ // When changing this set, please check the result in a console or e.g. RunKit (https://runkit.com/thure/642214441dd6ae000855a8de)
9
+ // Emoji sometimes use a combination of code points, and some code points aren't visible on their own, so by adding or deleting you may unintentionally create non-visible items.
10
+ // This set was chosen from the characters in Unicode Emoji v15.0 based on the following criteria:
11
+ // โ€“ not people or isolated anthropomorphic faces
12
+ // โ€“ not flags
13
+ // โ€“ more concrete than abstract
14
+ // โ€“ less culturally specific
15
+ // โ€“ less easily confused with another emoji in the set
16
+ // โ€“ requires less special knowledge to identify
17
+ // โ€“ less likely to evoke negative feelings (no meat, no drugs, no weapons, etc)
18
+ // โ€“ less common as a signifier in UX
19
+ // NOTE that this is intentionally an array of strings because of the way emoji graphemes work.
20
+ '๐Ÿ‘น',
21
+ '๐Ÿ‘ป',
22
+ '๐Ÿ‘ฝ',
23
+ '๐Ÿค–',
24
+ '๐ŸŽƒ',
25
+ '๐Ÿฆพ',
26
+ '๐Ÿฆฟ',
27
+ '๐Ÿฆท',
28
+ '๐Ÿ‘ฃ',
29
+ '๐Ÿ‘๏ธ',
30
+ '๐Ÿงถ',
31
+ '๐Ÿ‘‘',
32
+ '๐Ÿ’',
33
+ '๐Ÿฆ†',
34
+ '๐Ÿฆ‰',
35
+ '๐Ÿด',
36
+ '๐Ÿฆ„',
37
+ '๐Ÿ',
38
+ '๐Ÿฆ‹',
39
+ '๐Ÿž',
40
+ '๐Ÿชฒ',
41
+ '๐Ÿข',
42
+ '๐ŸฆŽ',
43
+ '๐Ÿฆ•',
44
+ '๐Ÿฆ‘',
45
+ '๐Ÿฆ€',
46
+ '๐Ÿ ',
47
+ '๐Ÿฌ',
48
+ '๐Ÿ‹',
49
+ '๐Ÿฆญ',
50
+ '๐Ÿ…',
51
+ '๐Ÿ†',
52
+ '๐Ÿฆ“',
53
+ '๐Ÿฆ',
54
+ '๐Ÿฆง',
55
+ '๐Ÿ˜',
56
+ '๐Ÿซ',
57
+ '๐Ÿฆ’',
58
+ '๐Ÿฆ˜',
59
+ '๐Ÿฆฌ',
60
+ '๐Ÿ–',
61
+ '๐Ÿ',
62
+ '๐ŸฆŒ',
63
+ '๐Ÿ•',
64
+ '๐Ÿˆ',
65
+ '๐Ÿ“',
66
+ '๐Ÿฆš',
67
+ '๐Ÿฆœ',
68
+ '๐Ÿฆข',
69
+ '๐Ÿฆฉ',
70
+ '๐Ÿฆฆ',
71
+ '๐Ÿ',
72
+ '๐Ÿฟ๏ธ',
73
+ '๐ŸŒต',
74
+ '๐ŸŒฒ',
75
+ '๐ŸŒณ',
76
+ '๐Ÿชต',
77
+ '๐ŸŒฑ',
78
+ '๐Ÿ',
79
+ '๐Ÿชบ',
80
+ '๐Ÿ„',
81
+ '๐Ÿš',
82
+ '๐Ÿชธ',
83
+ '๐Ÿชจ',
84
+ '๐ŸŒพ',
85
+ '๐ŸŒท',
86
+ '๐ŸŒป',
87
+ 'โ˜€๏ธ',
88
+ '๐ŸŒ™',
89
+ '๐Ÿช',
90
+ 'โญ๏ธ',
91
+ 'โšก๏ธ',
92
+ 'โ˜„๏ธ',
93
+ '๐Ÿ”ฅ',
94
+ '๐ŸŒˆ',
95
+ 'โ˜๏ธ',
96
+ '๐Ÿ’ง',
97
+ 'โ›ฑ๏ธ',
98
+ '๐ŸŒŠ',
99
+ '๐ŸŽ',
100
+ '๐Ÿ‹',
101
+ '๐Ÿ‰',
102
+ '๐Ÿ‡',
103
+ '๐Ÿซ',
104
+ '๐Ÿˆ',
105
+ '๐Ÿ’',
106
+ '๐Ÿ‘',
107
+ '๐Ÿฅญ',
108
+ '๐Ÿ',
109
+ '๐Ÿฅฅ',
110
+ '๐Ÿฅ',
111
+ '๐Ÿฅ‘',
112
+ '๐ŸŒถ๏ธ',
113
+ '๐ŸŒฝ',
114
+ '๐Ÿฅ•',
115
+ '๐Ÿฌ',
116
+ '๐Ÿฅœ',
117
+ '๐Ÿซ–',
118
+ 'โ˜•๏ธ',
119
+ '๐Ÿต',
120
+ '๐ŸงŠ',
121
+ '๐Ÿง‚',
122
+ '๐Ÿ”๏ธ',
123
+ 'โš“๏ธ',
124
+ '๐Ÿ›Ÿ',
125
+ '๐Ÿ๏ธ',
126
+ '๐Ÿ›ถ',
127
+ '๐Ÿš€',
128
+ '๐Ÿ›ฐ๏ธ',
129
+ 'โ›ฒ๏ธ',
130
+ '๐Ÿฐ',
131
+ '๐Ÿšฒ',
132
+ 'โ›บ๏ธ',
133
+ '๐ŸŽ™๏ธ',
134
+ '๐Ÿงฒ',
135
+ 'โš™๏ธ',
136
+ '๐Ÿ”ฉ',
137
+ '๐Ÿ”ฎ',
138
+ '๐Ÿ”ญ',
139
+ '๐Ÿ”ฌ',
140
+ '๐Ÿงฌ',
141
+ '๐ŸŒก๏ธ',
142
+ '๐Ÿงบ',
143
+ '๐Ÿ›Ž๏ธ',
144
+ '๐Ÿ”‘',
145
+ '๐Ÿช‘',
146
+ '๐Ÿงธ',
147
+ '๐ŸŽˆ',
148
+ '๐ŸŽ€',
149
+ '๐ŸŽŠ',
150
+ 'โ™ป๏ธ',
151
+ '๐ŸŽต',
152
+ ];
153
+
154
+ export const idHue = [
155
+ 'red' as const,
156
+ // 'orange' as const, /* More shades in these palettes are considered โ€œuglyโ€ */
157
+ 'amber' as const, // Amber arcs between red-orange and yellow as it gets lighter, so improves aesthetics.
158
+ // 'yellow' as const, /* More shades in these palettes are considered โ€œuglyโ€ */
159
+ 'lime' as const,
160
+ 'green' as const,
161
+ 'emerald' as const,
162
+ 'teal' as const,
163
+ 'cyan' as const,
164
+ // 'sky' as const, /* Omitted since it is quite similar to the primary accent palette */
165
+ // 'blue' as const, /* Omitted since it is quite similar to the primary accent palette */
166
+ // 'indigo' as const, /* Omitted since it is quite similar to the primary accent palette */
167
+ 'violet' as const,
168
+ 'purple' as const,
169
+ 'fuchsia' as const,
170
+ 'pink' as const,
171
+ 'rose' as const,
172
+ ];
173
+
174
+ export const keyToEmoji = (key: PublicKey) => hexToEmoji(key.toHex());
175
+
176
+ export const hexToEmoji = (hex: string) => toEmoji(parseInt(hex, 16));
177
+
178
+ export const toEmoji = (hash: number) => idEmoji[hash % idEmoji.length];
179
+
180
+ export const keyToHue = (key: PublicKey) => hexToHue(key.toHex());
181
+
182
+ export const hexToHue = (hex: string) => toHue(parseInt(hex, 16));
183
+
184
+ export const toHue = (hash: number) => idHue[hash % idHue.length];
185
+
186
+ export type FallbackValue = {
187
+ emoji: string;
188
+ hue: (typeof idHue)[number];
189
+ };
190
+
191
+ export const keyToFallback = (key: PublicKey) => hexToFallback(key.toHex());
192
+
193
+ export const hexToFallback = (hex: string) => toFallback(parseInt(hex, 16));
194
+
195
+ export const toFallback = (hash: number): FallbackValue => ({ emoji: toEmoji(hash), hue: toHue(hash) });