@wener/utils 1.1.6 → 1.1.8

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 (160) hide show
  1. package/README.md +3 -1
  2. package/dist/cjs/index.cjs +2 -0
  3. package/dist/cjs/index.cjs.map +1 -0
  4. package/dist/cjs/server.cjs +2 -0
  5. package/dist/cjs/server.cjs.map +1 -0
  6. package/dist/esm/index.js +1 -1
  7. package/dist/esm/index.js.map +1 -1
  8. package/dist/esm/server.js +1 -1
  9. package/dist/esm/server.js.map +1 -1
  10. package/dist/system/index.js +1 -1
  11. package/dist/system/index.js.map +1 -1
  12. package/dist/system/server.js +1 -1
  13. package/dist/system/server.js.map +1 -1
  14. package/lib/arrays/MaybeArray.js.map +1 -1
  15. package/lib/asyncs/createLazyPromise.js +12 -3
  16. package/lib/asyncs/createLazyPromise.js.map +1 -1
  17. package/lib/asyncs/timeout.js +1 -1
  18. package/lib/asyncs/timeout.js.map +1 -1
  19. package/lib/browsers/copy.js +2 -3
  20. package/lib/browsers/copy.js.map +1 -1
  21. package/lib/browsers/loaders.js +6 -11
  22. package/lib/browsers/loaders.js.map +1 -1
  23. package/lib/crypto/{hex.js → base.js} +1 -1
  24. package/lib/crypto/base.js.map +1 -0
  25. package/lib/crypto/getRandomValues.js +37 -0
  26. package/lib/crypto/getRandomValues.js.map +1 -0
  27. package/lib/crypto/hashing.js +4 -4
  28. package/lib/crypto/hashing.js.map +1 -1
  29. package/lib/crypto/randomUUID.js.map +1 -1
  30. package/lib/crypto/ulid.js +139 -0
  31. package/lib/crypto/ulid.js.map +1 -0
  32. package/lib/i18n/createTranslate.js +17 -1
  33. package/lib/i18n/createTranslate.js.map +1 -1
  34. package/lib/index.js +10 -5
  35. package/lib/index.js.map +1 -1
  36. package/lib/io/ArrayBuffers.js +170 -0
  37. package/lib/io/ArrayBuffers.js.map +1 -0
  38. package/lib/io/Buffer.js +21 -0
  39. package/lib/io/Buffer.js.map +1 -0
  40. package/lib/io/isBuffer.js +1 -1
  41. package/lib/io/isBuffer.js.map +1 -1
  42. package/lib/io/isTransferable.js.map +1 -1
  43. package/lib/isomorphics/structuredClone.js.map +1 -1
  44. package/lib/langs/deepEqual.js.map +1 -1
  45. package/lib/langs/shallowClone.js +15 -0
  46. package/lib/langs/shallowClone.js.map +1 -0
  47. package/lib/langs/shallowEqual.js.map +1 -1
  48. package/lib/logging/createChildLogger.js.map +1 -1
  49. package/lib/logging/createNoopLogger.js.map +1 -1
  50. package/lib/logging/createWriteLogger.js.map +1 -1
  51. package/lib/modules/isModule.js.map +1 -1
  52. package/lib/modules/parseModuleId.js +7 -5
  53. package/lib/modules/parseModuleId.js.map +1 -1
  54. package/lib/objects/get.js.map +1 -1
  55. package/lib/objects/parseObjectPath.js.map +1 -1
  56. package/lib/objects/set.js.map +1 -1
  57. package/lib/server/polyfillBrowser.js.map +1 -1
  58. package/lib/server/polyfillFetch.js.map +1 -1
  59. package/lib/server/polyfillJsDom.js +1 -1
  60. package/lib/server/polyfillJsDom.js.map +1 -1
  61. package/lib/strings/formatBytes.js +1 -1
  62. package/lib/strings/formatBytes.js.map +1 -1
  63. package/lib/strings/renderTemplate.js +1 -1
  64. package/lib/strings/renderTemplate.js.map +1 -1
  65. package/lib/validations/isEmptyObject.js +3 -4
  66. package/lib/validations/isEmptyObject.js.map +1 -1
  67. package/lib/validations/isPlainObject.js +11 -0
  68. package/lib/validations/isPlainObject.js.map +1 -0
  69. package/package.json +14 -6
  70. package/src/arrays/MaybeArray.ts +1 -1
  71. package/src/asyncs/createLazyPromise.test.ts +19 -4
  72. package/src/asyncs/createLazyPromise.ts +19 -4
  73. package/src/asyncs/generatorOfStream.ts +1 -0
  74. package/src/asyncs/timeout.ts +1 -1
  75. package/src/browsers/copy.ts +6 -5
  76. package/src/browsers/loaders.ts +6 -11
  77. package/src/crypto/{hex.ts → base.ts} +3 -0
  78. package/src/crypto/getRandomValues.ts +40 -0
  79. package/src/crypto/hashing.test.ts +1 -1
  80. package/src/crypto/hashing.ts +4 -4
  81. package/src/crypto/randomUUID.ts +3 -0
  82. package/src/crypto/ulid.test.ts +22 -0
  83. package/src/crypto/ulid.ts +182 -0
  84. package/src/i18n/createTranslate.test.ts +33 -18
  85. package/src/i18n/createTranslate.ts +20 -4
  86. package/src/index.ts +14 -7
  87. package/src/io/AbstractEncoding.ts +21 -0
  88. package/src/io/ArrayBuffer.test-d.ts +4 -0
  89. package/src/io/ArrayBuffers.base64.test.ts +61 -0
  90. package/src/io/ArrayBuffers.test.ts +23 -0
  91. package/src/io/ArrayBuffers.ts +288 -0
  92. package/src/io/Buffer.test.ts +23 -0
  93. package/src/io/Buffer.ts +30 -0
  94. package/src/io/isBuffer.test.ts +2 -0
  95. package/src/io/isBuffer.ts +3 -8
  96. package/src/io/isTransferable.ts +1 -1
  97. package/src/isomorphics/structuredClone.test.ts +1 -1
  98. package/src/isomorphics/structuredClone.ts +9 -6
  99. package/src/langs/deepEqual.ts +1 -0
  100. package/src/langs/shallowClone.ts +13 -0
  101. package/src/langs/shallowEqual.ts +1 -1
  102. package/src/logging/Logger.ts +6 -0
  103. package/src/logging/createChildLogger.ts +1 -1
  104. package/src/logging/createNoopLogger.ts +2 -2
  105. package/src/logging/createWriteLogger.ts +1 -1
  106. package/src/logging/logger.test.ts +3 -3
  107. package/src/modules/isModule.ts +3 -0
  108. package/src/modules/parseModuleId.test.ts +7 -2
  109. package/src/modules/parseModuleId.ts +15 -9
  110. package/src/objects/get.test-d.ts +51 -0
  111. package/src/objects/get.test.ts +2 -55
  112. package/src/objects/get.ts +2 -1
  113. package/src/objects/parseObjectPath.ts +4 -3
  114. package/src/objects/set.test.ts +32 -31
  115. package/src/objects/set.ts +4 -3
  116. package/src/server/polyfillBrowser.ts +8 -0
  117. package/src/server/polyfillFetch.ts +0 -1
  118. package/src/server/polyfillJsDom.ts +3 -2
  119. package/src/strings/formatBytes.ts +1 -1
  120. package/src/strings/renderTemplate.test.ts +1 -0
  121. package/src/strings/renderTemplate.ts +8 -5
  122. package/src/typedoc.ts +2 -0
  123. package/src/validations/isEmptyObject.ts +3 -4
  124. package/src/validations/isFunction.ts +3 -0
  125. package/src/validations/isPlainObject.ts +10 -0
  126. package/tsconfig.json +2 -1
  127. package/dist/cjs/_commonjsHelpers-dfec268f.js +0 -2
  128. package/dist/cjs/_commonjsHelpers-dfec268f.js.map +0 -1
  129. package/dist/cjs/api-7db97ae3.js +0 -1085
  130. package/dist/cjs/api-7db97ae3.js.map +0 -1
  131. package/dist/cjs/index-a6d1d653.js +0 -14
  132. package/dist/cjs/index-a6d1d653.js.map +0 -1
  133. package/dist/cjs/index.js +0 -2
  134. package/dist/cjs/index.js.map +0 -1
  135. package/dist/cjs/multipart-parser-141ed517.js +0 -3
  136. package/dist/cjs/multipart-parser-141ed517.js.map +0 -1
  137. package/dist/cjs/server.js +0 -2
  138. package/dist/cjs/server.js.map +0 -1
  139. package/dist/esm/_commonjsHelpers-28e086c5.js +0 -2
  140. package/dist/esm/_commonjsHelpers-28e086c5.js.map +0 -1
  141. package/dist/esm/api-3f555472.js +0 -1085
  142. package/dist/esm/api-3f555472.js.map +0 -1
  143. package/dist/esm/index-b50fef91.js +0 -14
  144. package/dist/esm/index-b50fef91.js.map +0 -1
  145. package/dist/esm/multipart-parser-5c1d6ee9.js +0 -3
  146. package/dist/esm/multipart-parser-5c1d6ee9.js.map +0 -1
  147. package/dist/system/_commonjsHelpers-07f370a7.js +0 -2
  148. package/dist/system/_commonjsHelpers-07f370a7.js.map +0 -1
  149. package/dist/system/api-dc50ebac.js +0 -1085
  150. package/dist/system/api-dc50ebac.js.map +0 -1
  151. package/dist/system/index-8f1807ba.js +0 -14
  152. package/dist/system/index-8f1807ba.js.map +0 -1
  153. package/dist/system/multipart-parser-53518ee9.js +0 -3
  154. package/dist/system/multipart-parser-53518ee9.js.map +0 -1
  155. package/lib/crypto/hex.js.map +0 -1
  156. package/lib/shim/urljoin.js +0 -51
  157. package/lib/shim/urljoin.js.map +0 -1
  158. package/src/shim/urljoin.test.ts +0 -6
  159. package/src/shim/urljoin.ts +0 -75
  160. package/src/types.d.ts +0 -7
@@ -0,0 +1,288 @@
1
+ import { classOf } from '../langs/classOf';
2
+ import { isBuffer } from './isBuffer';
3
+
4
+ /**
5
+ * Various utils to work with {@link ArrayBuffer}
6
+ */
7
+ export interface ArrayBuffers {
8
+ /**
9
+ * isArrayBuffer check if the given value is an {@link ArrayBuffer}
10
+ */
11
+ isArrayBuffer(v: any): v is ArrayBuffer;
12
+
13
+ /**
14
+ * slice the given view with the given offset and length, will handle the {@link Buffer} as well
15
+ *
16
+ * @see {@link https://nodejs.org/api/buffer.html#bufslicestart-end Buffer.slice}
17
+ */
18
+ slice<T extends ArrayBufferView>(o: T, start?: number, end?: number): T;
19
+
20
+ /**
21
+ * asView convert the given value to given {@link TypedArray} view
22
+ *
23
+ * TypedArray can be {@link Buffer}, will avoid copy
24
+ */
25
+ asView<C extends ArrayBufferViewConstructor<unknown>>(
26
+ TypedArray: C,
27
+ v: BufferSource,
28
+ byteOffset?: number,
29
+ byteLength?: number,
30
+ ): InstanceType<C>;
31
+
32
+ /**
33
+ * toString convert the given {@link BufferSource} to string
34
+ */
35
+ toString(v: BufferSource | string, encoding?: ToStringEncoding): string;
36
+
37
+ /**
38
+ * Returns true if encoding is the name of a supported character encoding, or false otherwise.
39
+ */
40
+ isEncoding(v?: string): v is ToStringEncoding;
41
+
42
+ toJSON<T = any>(v: BufferSource | string, reviver?: (this: any, key: string, value: any) => any): T;
43
+
44
+ /**
45
+ * from convert the given value to {@link ArrayBuffer}
46
+ */
47
+ from(v: string | BufferSource, encoding?: ToStringEncoding): ArrayBuffer;
48
+
49
+ /**
50
+ * concat the given {@link BufferSource} to a new {@link ArrayBuffer}
51
+ */
52
+ concat(buffers: Array<BufferSource>, result?: ArrayBuffer, offset?: number): ArrayBuffer;
53
+ }
54
+
55
+ type ToStringEncoding =
56
+ | 'ascii'
57
+ | 'utf16le'
58
+ // | 'utf-16le'
59
+ | 'ucs2'
60
+ | 'ucs-2'
61
+ | 'base64'
62
+ | 'base64url'
63
+ | 'latin1'
64
+ | 'binary'
65
+ | 'utf8'
66
+ | 'utf-8'
67
+ | 'hex';
68
+
69
+ export class ArrayBuffers {
70
+ static #_allowedNativeBuffer: boolean = true;
71
+
72
+ static #isNativeBufferValid() {
73
+ return this.#_allowedNativeBuffer && !(globalThis.Buffer as any)?.isPollyfill?.();
74
+ }
75
+
76
+ static setAllowedNativeBuffer(v: boolean) {
77
+ this.#_allowedNativeBuffer = v;
78
+ }
79
+
80
+ static isArrayBuffer = (v: any): v is ArrayBuffer => {
81
+ return v instanceof ArrayBuffer;
82
+ };
83
+
84
+ static slice = (o: TypedArray, start?: number, end?: number) => {
85
+ // NodeJS Buffer slice is not the same as UInt8Array slice
86
+ // https://nodejs.org/api/buffer.html#bufslicestart-end
87
+ if (isBuffer(o)) {
88
+ return Uint8Array.prototype.slice.call(o, start, end);
89
+ }
90
+ return o.slice(start, end);
91
+ };
92
+
93
+ static asView = <C extends ArrayBufferViewConstructor<unknown>, I extends InstanceType<C>>(
94
+ TypedArray: C,
95
+ v: BufferSource,
96
+ byteOffset?: number,
97
+ byteLength?: number,
98
+ ): I => {
99
+ if (v instanceof TypedArray && (byteOffset ?? 0) === 0 && byteLength === undefined) {
100
+ return v as I;
101
+ }
102
+ if (ArrayBuffer.isView(v) || isBuffer(v)) {
103
+ if (ArrayBuffers.#isNativeBufferValid() && (TypedArray as any) === Buffer) {
104
+ // new Buffer() is deprecated
105
+ return Buffer.from(v.buffer, byteOffset, byteLength) as I;
106
+ }
107
+ return new TypedArray(v.buffer, v.byteOffset + (byteOffset ?? 0), byteLength ?? v.byteLength) as I;
108
+ }
109
+ return new TypedArray(v, byteOffset, byteLength) as I;
110
+ };
111
+
112
+ static toString = (buf: BufferSource | string, encoding: ToStringEncoding = 'utf8') => {
113
+ // 'ascii' 'utf16le' | 'ucs2' | 'ucs-2' | 'base64' | 'base64url' | 'latin1' | 'binary' | 'hex'
114
+ if (typeof buf === 'string') {
115
+ return buf;
116
+ }
117
+ if (ArrayBuffers.#isNativeBufferValid()) {
118
+ return Buffer.from(ArrayBuffers.asView(Uint8Array, buf)).toString(encoding);
119
+ }
120
+ // reference
121
+ // https://github.com/feross/buffer/blob/master/index.js
122
+ switch (encoding) {
123
+ case 'hex': {
124
+ const view: Uint8Array = ArrayBuffers.asView(Uint8Array, buf);
125
+ return [...view].map((b) => hexLookupTable[b]).join('');
126
+ }
127
+ case 'base64': {
128
+ const view: Uint8Array = ArrayBuffers.asView(Uint8Array, buf);
129
+ return btoa(String.fromCharCode(...view));
130
+ }
131
+ case 'utf8':
132
+ // falls through
133
+ case 'utf-8':
134
+ return new TextDecoder().decode(buf as any);
135
+ case 'ascii': {
136
+ const view: Uint8Array = ArrayBuffers.asView(Uint8Array, buf);
137
+ return String.fromCharCode(...view.map((v) => v & 0x7f));
138
+ }
139
+ case 'latin1':
140
+ // falls through
141
+ case 'binary': {
142
+ const view: Uint8Array = ArrayBuffers.asView(Uint8Array, buf);
143
+ return String.fromCharCode(...view);
144
+ }
145
+ case 'ucs2':
146
+ // falls through
147
+ case 'ucs-2':
148
+ // case 'utf-16le':
149
+ // falls through
150
+ case 'utf16le': {
151
+ const view: Uint8Array = ArrayBuffers.asView(Uint8Array, buf);
152
+ let res = '';
153
+ // If length is odd, the last 8 bits must be ignored (same as node.js)
154
+ for (let i = 0; i < view.length - 1; i += 2) {
155
+ res += String.fromCharCode(view[i] + view[i + 1] * 256);
156
+ }
157
+ return res;
158
+ }
159
+ default:
160
+ throw new Error(`[ArrayBuffers.toString] Unknown encoding: ${encoding}`);
161
+ }
162
+ };
163
+
164
+ static toJSON = (v: BufferSource | string, reviver?: (this: any, key: string, value: any) => any) => {
165
+ return JSON.parse(ArrayBuffers.toString(v), reviver);
166
+ };
167
+
168
+ static alloc = (size: number, fill?: string | number, encoding?: ToStringEncoding) => {
169
+ if (fill !== undefined) {
170
+ if (typeof fill === 'number') {
171
+ return new Uint8Array(size).fill(fill);
172
+ }
173
+ // as cast
174
+ // https://stackoverflow.com/questions/73994091
175
+ return ArrayBuffers.asView(Uint8Array, ArrayBuffers.from(fill, encoding)).slice(0, size);
176
+ }
177
+ return new ArrayBuffer(size);
178
+ };
179
+
180
+ static from = (
181
+ v: string | BufferSource | ArrayLike<number> | Iterable<number>,
182
+ encoding: ToStringEncoding = 'utf8',
183
+ ): BufferSource => {
184
+ if (!v) {
185
+ return new ArrayBuffer(0);
186
+ }
187
+ if (typeof v === 'string') {
188
+ if (ArrayBuffers.#isNativeBufferValid()) {
189
+ return Buffer.from(v, encoding);
190
+ }
191
+
192
+ switch (encoding) {
193
+ case 'utf-8':
194
+ // falls through
195
+ case 'utf8':
196
+ return new TextEncoder().encode(v).buffer;
197
+ case 'base64':
198
+ // replaceAll
199
+ return Uint8Array.from(atob(v.replace(/[^0-9a-zA-Z=+/_ \r\n]/g, '')), (c) => c.charCodeAt(0));
200
+ default:
201
+ throw new Error(`[ArrayBuffers.from] Unknown encoding: ${encoding}`);
202
+ }
203
+ }
204
+ if (v instanceof ArrayBuffer) {
205
+ return v;
206
+ }
207
+ // lost length
208
+ if (ArrayBuffer.isView(v) || isBuffer(v)) {
209
+ if (v.byteOffset !== 0) {
210
+ // return v.buffer.slice(v.byteOffset, v.byteOffset + v.byteLength)
211
+ throw new Error('ArrayBuffers.from do not support view with offset');
212
+ }
213
+ return v.buffer;
214
+ }
215
+ if (Array.isArray(v)) {
216
+ return new Uint8Array(v);
217
+ }
218
+ const type = classOf(v);
219
+ throw new TypeError(`ArrayBuffers.from unsupported type ${type}`);
220
+ };
221
+
222
+ static isEncoding = (encoding?: string) => {
223
+ switch (String(encoding).toLowerCase()) {
224
+ case 'hex':
225
+ case 'utf8':
226
+ case 'utf-8':
227
+ case 'ascii':
228
+ case 'latin1':
229
+ case 'binary':
230
+ case 'base64':
231
+ case 'ucs2':
232
+ case 'ucs-2':
233
+ case 'utf16le':
234
+ // case 'utf-16le':
235
+ return true;
236
+ default:
237
+ return false;
238
+ }
239
+ };
240
+
241
+ static concat = (buffers: Array<BufferSource>, result?: ArrayBuffer, offset = 0) => {
242
+ // https://stackoverflow.com/questions/10786128/appending-arraybuffers
243
+
244
+ const length = buffers.reduce((a, b) => a + b.byteLength, 0);
245
+ const r = result ? new Uint8Array(result) : new Uint8Array(length);
246
+ for (const buffer of buffers) {
247
+ if (!buffer || !buffer.byteLength) continue;
248
+ let n: Uint8Array;
249
+ if (buffer instanceof ArrayBuffer) {
250
+ n = new Uint8Array(buffer);
251
+ } else if (ArrayBuffer.isView(buffer)) {
252
+ n = new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength);
253
+ } else {
254
+ throw new Error(`ArrayBuffers.concat unsupported type ${classOf(buffer)}`);
255
+ }
256
+ r.set(n, offset);
257
+ offset += buffer.byteLength;
258
+ }
259
+ return r.buffer;
260
+ };
261
+ }
262
+
263
+ export type TypedArray =
264
+ | Uint8Array
265
+ | Uint8ClampedArray
266
+ | Uint16Array
267
+ | Uint32Array
268
+ | Int8Array
269
+ | Int16Array
270
+ | Int32Array
271
+ | BigUint64Array
272
+ | BigInt64Array
273
+ | Float32Array
274
+ | Float64Array;
275
+
276
+ type ArrayBufferViewConstructor<T> = new (buffer: ArrayBufferLike, byteOffset?: number, byteLength?: number) => T;
277
+
278
+ const hexLookupTable = (function () {
279
+ const alphabet = '0123456789abcdef';
280
+ const table = new Array(256);
281
+ for (let i = 0; i < 16; ++i) {
282
+ const i16 = i * 16;
283
+ for (let j = 0; j < 16; ++j) {
284
+ table[i16 + j] = alphabet[i] + alphabet[j];
285
+ }
286
+ }
287
+ return table;
288
+ })();
@@ -0,0 +1,23 @@
1
+ import test from 'ava';
2
+ import { Buffer } from './Buffer';
3
+ import { isBuffer } from './isBuffer';
4
+
5
+ test('basic', (t) => {
6
+ {
7
+ const buf = new Buffer(0);
8
+ t.true(Buffer.isBuffer(buf));
9
+ t.true(isBuffer(buf));
10
+ }
11
+ // const b = new Buffer(10)
12
+ // t.is(b.length,10)
13
+ // t.is(b.byteLength,10)
14
+ // t.is(b.byteOffset,0)
15
+ // t.is(b.buffer.byteLength,10)
16
+ // t.is(b.buffer.byteOffset,0)
17
+ // t.is(b.buffer.length,1)
18
+ // t.is(b.buffer[0].byteLength,10)
19
+ // t.is(b.buffer[0].byteOffset,0)
20
+ // t.is(b.buffer[0].length,10)
21
+ // t.is(b.buffer[0][0],0)
22
+ // t.is(b.buffer[0][9],0)
23
+ });
@@ -0,0 +1,30 @@
1
+ import { ArrayBuffers } from './ArrayBuffers';
2
+ import { isBuffer } from './isBuffer';
3
+
4
+ /**
5
+ * Buffer is a polyfill version of NodeJS Buffer
6
+ */
7
+ export class Buffer extends Uint8Array {
8
+ // constructor(buffer: ArrayBufferLike, byteOffset?: number, length?: number) {
9
+ // super(buffer, byteOffset, length);
10
+ // }
11
+
12
+ static get isPolyfill() {
13
+ return true;
14
+ }
15
+
16
+ static isBuffer(v: any): v is Buffer {
17
+ return v instanceof Buffer || isBuffer(v);
18
+ }
19
+
20
+ static from(array: string | BufferSource | ArrayLike<number> | Iterable<number>, arg2?: any): Buffer {
21
+ // todo mapfn
22
+ return new Buffer(ArrayBuffers.from(array, arg2) as ArrayBuffer);
23
+ }
24
+
25
+ static isEncoding = ArrayBuffers.isEncoding;
26
+
27
+ toString(encoding?: string): string {
28
+ return ArrayBuffers.toString(this, encoding as any);
29
+ }
30
+ }
@@ -1,7 +1,9 @@
1
1
  import test from 'ava';
2
2
  import { Buffer } from 'node:buffer';
3
+ import { classOf } from '../langs/classOf';
3
4
  import { isBuffer } from './isBuffer';
4
5
 
5
6
  test('isBuffer', (t) => {
6
7
  t.true(isBuffer(Buffer.from('')));
8
+ t.is(classOf(Buffer), 'Function');
7
9
  });
@@ -1,13 +1,8 @@
1
1
  /**
2
- * check {@code obj} is Buffer
2
+ * check {@link obj} is Buffer
3
3
  *
4
- * {@link https://github.com/feross/is-buffer feross/is-buffer}
4
+ * @see {@link https://github.com/feross/is-buffer feross/is-buffer}
5
5
  */
6
6
  export function isBuffer(obj: any): obj is Buffer {
7
- return (
8
- obj != null &&
9
- obj.constructor != null &&
10
- typeof obj.constructor.isBuffer === 'function' &&
11
- obj.constructor.isBuffer(obj)
12
- );
7
+ return obj?.constructor?.isBuffer?.(obj);
13
8
  }
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * - Chrome 87, FF 103, Safari X, NodeJS X
5
5
  *
6
- * {@link https://developer.mozilla.org/en-US/docs/Glossary/Transferable_objects | Transferable objects}
6
+ * @see {@link https://developer.mozilla.org/en-US/docs/Glossary/Transferable_objects | Transferable objects}
7
7
  */
8
8
  export function isTransferable(v: any): v is TransferableObject {
9
9
  _ctors ||= ctors();
@@ -7,7 +7,7 @@ test('structuredClone', (t) => {
7
7
  ['', ''],
8
8
  [Number(1), 1],
9
9
  ]) {
10
- let c = _clone(k);
10
+ const c = _clone(k);
11
11
  t.deepEqual(c, v);
12
12
  t.is(classOf(c), classOf(v));
13
13
  }
@@ -1,11 +1,14 @@
1
+ /* eslint no-proto:0 */
2
+ import { classOf } from '../langs/classOf';
3
+
1
4
  /**
2
- * Chrome 98, Safari 15.4
5
+ * Clone an object using structured cloning algorithm
6
+ *
7
+ * - Chrome 98, Safari 15.4, NodeJS 17
3
8
  *
4
- * {@link https://developer.mozilla.org/en-US/docs/Web/API/structuredClone structuredClone}
5
- * {@link https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/web.structured-clone.js core-js}
9
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/structuredClone structuredClone}
10
+ * @see {@link https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/web.structured-clone.js core-js}
6
11
  */
7
- import { classOf } from '../langs/classOf';
8
-
9
12
  export const structuredClone: <T>(value: T, options?: StructuredSerializeOptions) => T =
10
13
  globalThis.structuredClone || _clone;
11
14
 
@@ -17,7 +20,7 @@ function set(obj: any, key: any, val: any) {
17
20
  }
18
21
 
19
22
  /**
20
- * {@link https://github.com/lukeed/klona/blob/master/src/full.js klona}
23
+ * @see {@link https://github.com/lukeed/klona/blob/master/src/full.js klona}
21
24
  */
22
25
  export function _clone(x: any): any {
23
26
  // too complex
@@ -101,5 +101,6 @@ export function deepEqual(foo: any, bar: any) {
101
101
  }
102
102
  }
103
103
 
104
+ // eslint-disable-next-line no-self-compare
104
105
  return foo !== foo && bar !== bar;
105
106
  }
@@ -0,0 +1,13 @@
1
+ export function shallowClone<T>(obj: T): T {
2
+ if (!obj) {
3
+ return obj;
4
+ }
5
+ if (Array.isArray(obj)) {
6
+ return obj.slice() as T;
7
+ }
8
+ if (typeof obj === 'object') {
9
+ return Object.assign({}, obj);
10
+ }
11
+ // skip Map, Set, WeakMap, WeakSet, Date, RegExp, etc.
12
+ return obj;
13
+ }
@@ -16,7 +16,7 @@ export function shallowEqual<T, U>(objA: T, objB: U) {
16
16
  }
17
17
  for (let i = 0; i < keysA.length; i++) {
18
18
  if (
19
- !Object.prototype.hasOwnProperty.call(objB, keysA[i] as string) ||
19
+ !Object.prototype.hasOwnProperty.call(objB, keysA[i]) ||
20
20
  !Object.is(objA[keysA[i] as keyof T], objB[keysA[i] as keyof U])
21
21
  ) {
22
22
  return false;
@@ -1,3 +1,6 @@
1
+ /**
2
+ * Logger interface satisfies the `console`, `pino` logger interface.
3
+ */
1
4
  export interface Logger {
2
5
  trace(...data: any[]): void;
3
6
 
@@ -9,6 +12,9 @@ export interface Logger {
9
12
 
10
13
  error(...data: any[]): void;
11
14
 
15
+ /**
16
+ * create child logger with given context
17
+ */
12
18
  child?: (o: object) => Logger;
13
19
  }
14
20
 
@@ -1,4 +1,4 @@
1
- import { Logger, LoggerWithChild } from './Logger';
1
+ import type { Logger, LoggerWithChild } from './Logger';
2
2
  import { createWriteLogger } from './createWriteLogger';
3
3
 
4
4
  export function createChildLogger(l: Logger, ctx: object): LoggerWithChild {
@@ -1,7 +1,7 @@
1
- import { LoggerWithChild } from './Logger';
1
+ import type { LoggerWithChild } from './Logger';
2
2
 
3
3
  export function createNoopLogger(): LoggerWithChild {
4
- const noop = (..._: any[]) => void 0;
4
+ const noop = (..._: any[]) => undefined;
5
5
  return {
6
6
  trace: noop,
7
7
  debug: noop,
@@ -1,4 +1,4 @@
1
- import { LoggerWithChild, LogLevel } from './Logger';
1
+ import type { LoggerWithChild, LogLevel } from './Logger';
2
2
 
3
3
  export function createWriteLogger(
4
4
  write: (o: { level: LogLevel; values: any[] } & Record<string | symbol, any>) => void,
@@ -4,9 +4,9 @@ import { createWriteLogger } from './createWriteLogger';
4
4
 
5
5
  test('logger', (t) => {
6
6
  {
7
- let logs: any[] = [];
7
+ const logs: any[] = [];
8
8
  const base = createWriteLogger((o) => logs.push(o));
9
- let l = createChildLogger(base, { c: 'test' });
9
+ const l = createChildLogger(base, { c: 'test' });
10
10
  l.info('hello');
11
11
  t.deepEqual(logs.shift(), { level: 'info', values: ['hello'], c: 'test' });
12
12
  l.child({ m: 1 }).trace('trace');
@@ -15,7 +15,7 @@ test('logger', (t) => {
15
15
  createChildLogger(console, { c: 'test' }).info('hello');
16
16
  {
17
17
  let pass = 0;
18
- let l = createWriteLogger(
18
+ const l = createWriteLogger(
19
19
  (o) => {
20
20
  pass++;
21
21
  t.log(`${o.level}: [${[o.m, o.c].filter(Boolean).join('.') || 'default'}]`, ...o.values);
@@ -1,3 +1,6 @@
1
+ /**
2
+ * Check is ESM Module
3
+ */
1
4
  export function isModule(o: any): o is Module {
2
5
  return o && o[Symbol.toStringTag] === 'Module';
3
6
  }
@@ -10,6 +10,7 @@ test('parseModuleId', (t) => {
10
10
  scoped: true,
11
11
  org: 'wener',
12
12
  pkg: 'reaction',
13
+ versioned: false,
13
14
  },
14
15
  reaction: {
15
16
  id: `reaction@latest`,
@@ -17,6 +18,7 @@ test('parseModuleId', (t) => {
17
18
  range: 'latest',
18
19
  pkg: 'reaction',
19
20
  scoped: false,
21
+ versioned: false,
20
22
  },
21
23
  'reaction@1': {
22
24
  id: `reaction@1`,
@@ -24,6 +26,7 @@ test('parseModuleId', (t) => {
24
26
  range: '1',
25
27
  pkg: 'reaction',
26
28
  scoped: false,
29
+ versioned: true,
27
30
  },
28
31
  'reaction@1.1.1': {
29
32
  id: `reaction@1.1.1`,
@@ -32,6 +35,7 @@ test('parseModuleId', (t) => {
32
35
  range: '1.1.1',
33
36
  pkg: 'reaction',
34
37
  scoped: false,
38
+ versioned: true,
35
39
  },
36
40
  'reaction@1.1.1-alpha': {
37
41
  id: `reaction@1.1.1-alpha`,
@@ -39,7 +43,7 @@ test('parseModuleId', (t) => {
39
43
  version: '1.1.1-alpha',
40
44
  range: '1.1.1-alpha',
41
45
  pkg: 'reaction',
42
-
46
+ versioned: true,
43
47
  scoped: false,
44
48
  },
45
49
  'reaction@1.1.1/index.js': {
@@ -49,7 +53,7 @@ test('parseModuleId', (t) => {
49
53
  range: '1.1.1',
50
54
  scoped: false,
51
55
  pkg: 'reaction',
52
-
56
+ versioned: true,
53
57
  path: '/index.js',
54
58
  },
55
59
  'reaction@1.1.1/': {
@@ -60,6 +64,7 @@ test('parseModuleId', (t) => {
60
64
  scoped: false,
61
65
  pkg: 'reaction',
62
66
  path: '/',
67
+ versioned: true,
63
68
  },
64
69
  };
65
70
  for (const [k, v] of Object.entries(tests)) {
@@ -9,18 +9,22 @@ export type ParsedModuleId = {
9
9
  range: string; // version, tag, range
10
10
  pkg: string;
11
11
  path?: string;
12
+ org?: string;
13
+ versioned: boolean; // is module id contain a version specifier
12
14
  } & (
13
15
  | { scoped: false }
14
16
  | {
15
17
  scoped: true;
16
- org?: string;
18
+ org: string;
17
19
  }
18
20
  );
19
21
 
20
22
  /**
21
23
  * Parse NPM module id
22
24
  *
23
- * parseModuleId('@wener/reaction@latest/index.js') // => { id: '@wener/reaction@latest', name: '@wener/reaction', version: 'latest', range: 'latest', pkg: 'reaction', path: '/index.js', scoped: true, org: 'wener' }
25
+ * @example
26
+ * parseModuleId('@wener/reaction@latest/index.js')
27
+ * // { id: '@wener/reaction@latest', name: '@wener/reaction', version: 'latest', range: 'latest', pkg: 'reaction', path: '/index.js', scoped: true, org: 'wener' }
24
28
  */
25
29
  export function parseModuleId(s: string): ParsedModuleId | undefined {
26
30
  const groups = s.match(regModuleId)?.groups;
@@ -28,24 +32,26 @@ export function parseModuleId(s: string): ParsedModuleId | undefined {
28
32
  return undefined;
29
33
  }
30
34
  const { n: name, v: version, p: path, org, pkg } = groups;
31
- let scoped = Boolean(org);
35
+ const scoped = Boolean(org);
32
36
  const v = /^\d+\.\d+\.\d+/.test(version) ? version : undefined;
33
- let range = version || 'latest';
34
- const o = {
37
+ const range = version || 'latest';
38
+ const o: ParsedModuleId = {
35
39
  id: `${name}@${range}`,
36
40
  name,
37
- range: range,
41
+ range,
38
42
  scoped,
39
43
  pkg,
40
- } as ParsedModuleId;
44
+ org,
45
+ versioned: Boolean(version),
46
+ };
41
47
  if (v) {
42
48
  o.version = v;
43
49
  }
44
50
  if (path) {
45
51
  o.path = path;
46
52
  }
47
- if (o.scoped) {
48
- o.org = org;
53
+ if (!o.scoped) {
54
+ delete o.org;
49
55
  }
50
56
  return o;
51
57
  }