@wener/utils 1.1.6 → 1.1.7

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 (128) hide show
  1. package/README.md +3 -1
  2. package/dist/cjs/index.js +1 -1
  3. package/dist/cjs/index.js.map +1 -1
  4. package/dist/cjs/server.js +1 -1
  5. package/dist/cjs/server.js.map +1 -1
  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 +2 -2
  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/hashing.js +4 -4
  26. package/lib/crypto/hashing.js.map +1 -1
  27. package/lib/crypto/randomUUID.js.map +1 -1
  28. package/lib/i18n/createTranslate.js.map +1 -1
  29. package/lib/index.js +2 -2
  30. package/lib/io/ArrayBuffers.js +164 -0
  31. package/lib/io/ArrayBuffers.js.map +1 -0
  32. package/lib/io/isBuffer.js +1 -1
  33. package/lib/io/isBuffer.js.map +1 -1
  34. package/lib/io/isTransferable.js.map +1 -1
  35. package/lib/isomorphics/structuredClone.js.map +1 -1
  36. package/lib/langs/deepEqual.js.map +1 -1
  37. package/lib/langs/shallowEqual.js.map +1 -1
  38. package/lib/logging/createNoopLogger.js.map +1 -1
  39. package/lib/modules/isModule.js.map +1 -1
  40. package/lib/modules/parseModuleId.js +7 -5
  41. package/lib/modules/parseModuleId.js.map +1 -1
  42. package/lib/objects/parseObjectPath.js.map +1 -1
  43. package/lib/objects/set.js.map +1 -1
  44. package/lib/server/polyfillBrowser.js.map +1 -1
  45. package/lib/server/polyfillFetch.js.map +1 -1
  46. package/lib/server/polyfillJsDom.js +1 -1
  47. package/lib/server/polyfillJsDom.js.map +1 -1
  48. package/lib/strings/formatBytes.js +1 -1
  49. package/lib/strings/formatBytes.js.map +1 -1
  50. package/lib/strings/renderTemplate.js +1 -1
  51. package/lib/strings/renderTemplate.js.map +1 -1
  52. package/package.json +10 -2
  53. package/src/arrays/MaybeArray.ts +1 -1
  54. package/src/asyncs/createLazyPromise.test.ts +4 -4
  55. package/src/asyncs/createLazyPromise.ts +2 -2
  56. package/src/asyncs/generatorOfStream.ts +1 -0
  57. package/src/asyncs/timeout.ts +1 -1
  58. package/src/browsers/copy.ts +6 -5
  59. package/src/browsers/loaders.ts +6 -11
  60. package/src/crypto/{hex.ts → base.ts} +3 -0
  61. package/src/crypto/hashing.test.ts +1 -1
  62. package/src/crypto/hashing.ts +4 -4
  63. package/src/crypto/randomUUID.ts +3 -0
  64. package/src/i18n/createTranslate.test.ts +18 -18
  65. package/src/i18n/createTranslate.ts +1 -1
  66. package/src/index.ts +3 -2
  67. package/src/io/AbstractEncoding.ts +21 -0
  68. package/src/io/ArrayBuffer.test-d.ts +4 -0
  69. package/src/io/ArrayBuffers.base64.test.ts +61 -0
  70. package/src/io/ArrayBuffers.test.ts +23 -0
  71. package/src/io/ArrayBuffers.ts +272 -0
  72. package/src/io/Buffer.ts +16 -0
  73. package/src/io/isBuffer.test.ts +2 -0
  74. package/src/io/isBuffer.ts +3 -8
  75. package/src/io/isTransferable.ts +1 -1
  76. package/src/isomorphics/structuredClone.test.ts +1 -1
  77. package/src/isomorphics/structuredClone.ts +9 -6
  78. package/src/langs/deepEqual.ts +1 -0
  79. package/src/langs/shallowEqual.ts +1 -1
  80. package/src/logging/Logger.ts +6 -0
  81. package/src/logging/createNoopLogger.ts +1 -1
  82. package/src/logging/logger.test.ts +3 -3
  83. package/src/modules/isModule.ts +3 -0
  84. package/src/modules/parseModuleId.test.ts +7 -2
  85. package/src/modules/parseModuleId.ts +15 -9
  86. package/src/objects/get.test-d.ts +51 -0
  87. package/src/objects/get.test.ts +2 -55
  88. package/src/objects/parseObjectPath.ts +4 -3
  89. package/src/objects/set.test.ts +32 -31
  90. package/src/objects/set.ts +2 -2
  91. package/src/server/polyfillBrowser.ts +8 -0
  92. package/src/server/polyfillFetch.ts +0 -1
  93. package/src/server/polyfillJsDom.ts +3 -2
  94. package/src/strings/formatBytes.ts +1 -1
  95. package/src/strings/renderTemplate.test.ts +1 -0
  96. package/src/strings/renderTemplate.ts +8 -5
  97. package/src/typedoc.ts +2 -0
  98. package/tsconfig.json +2 -1
  99. package/dist/cjs/_commonjsHelpers-dfec268f.js +0 -2
  100. package/dist/cjs/_commonjsHelpers-dfec268f.js.map +0 -1
  101. package/dist/cjs/api-7db97ae3.js +0 -1085
  102. package/dist/cjs/api-7db97ae3.js.map +0 -1
  103. package/dist/cjs/index-a6d1d653.js +0 -14
  104. package/dist/cjs/index-a6d1d653.js.map +0 -1
  105. package/dist/cjs/multipart-parser-141ed517.js +0 -3
  106. package/dist/cjs/multipart-parser-141ed517.js.map +0 -1
  107. package/dist/esm/_commonjsHelpers-28e086c5.js +0 -2
  108. package/dist/esm/_commonjsHelpers-28e086c5.js.map +0 -1
  109. package/dist/esm/api-3f555472.js +0 -1085
  110. package/dist/esm/api-3f555472.js.map +0 -1
  111. package/dist/esm/index-b50fef91.js +0 -14
  112. package/dist/esm/index-b50fef91.js.map +0 -1
  113. package/dist/esm/multipart-parser-5c1d6ee9.js +0 -3
  114. package/dist/esm/multipart-parser-5c1d6ee9.js.map +0 -1
  115. package/dist/system/_commonjsHelpers-07f370a7.js +0 -2
  116. package/dist/system/_commonjsHelpers-07f370a7.js.map +0 -1
  117. package/dist/system/api-dc50ebac.js +0 -1085
  118. package/dist/system/api-dc50ebac.js.map +0 -1
  119. package/dist/system/index-8f1807ba.js +0 -14
  120. package/dist/system/index-8f1807ba.js.map +0 -1
  121. package/dist/system/multipart-parser-53518ee9.js +0 -3
  122. package/dist/system/multipart-parser-53518ee9.js.map +0 -1
  123. package/lib/crypto/hex.js.map +0 -1
  124. package/lib/shim/urljoin.js +0 -51
  125. package/lib/shim/urljoin.js.map +0 -1
  126. package/src/shim/urljoin.test.ts +0 -6
  127. package/src/shim/urljoin.ts +0 -75
  128. package/src/types.d.ts +0 -7
@@ -0,0 +1,272 @@
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
+ // eslint-disable-next-line @typescript-eslint/no-redeclare
70
+ export const ArrayBuffers = {
71
+ _allowedBuffer: true,
72
+ isArrayBuffer: (v: any): v is ArrayBuffer => {
73
+ return v instanceof ArrayBuffer;
74
+ },
75
+ slice: (o: TypedArray, start?: number, end?: number) => {
76
+ // NodeJS Buffer slice is not the same as UInt8Array slice
77
+ // https://nodejs.org/api/buffer.html#bufslicestart-end
78
+ if (isBuffer(o)) {
79
+ return Uint8Array.prototype.slice.call(o, start, end);
80
+ }
81
+ return o.slice(start, end);
82
+ },
83
+ asView: <C extends ArrayBufferViewConstructor<unknown>, I extends InstanceType<C>>(
84
+ TypedArray: C,
85
+ v: BufferSource,
86
+ byteOffset?: number,
87
+ byteLength?: number,
88
+ ): I => {
89
+ if (v instanceof TypedArray && (byteOffset ?? 0) === 0 && byteLength === undefined) {
90
+ return v as I;
91
+ }
92
+ if (ArrayBuffer.isView(v) || isBuffer(v)) {
93
+ if (ArrayBuffers._allowedBuffer && typeof Buffer !== 'undefined' && (TypedArray as any) === Buffer) {
94
+ // new Buffer() is deprecated
95
+ return Buffer.from(v.buffer, byteOffset, byteLength) as I;
96
+ }
97
+ return new TypedArray(v.buffer, v.byteOffset + (byteOffset ?? 0), byteLength ?? v.byteLength) as I;
98
+ }
99
+ return new TypedArray(v, byteOffset, byteLength) as I;
100
+ },
101
+ toString: (buf: BufferSource | string, encoding: ToStringEncoding = 'utf8') => {
102
+ // 'ascii' 'utf16le' | 'ucs2' | 'ucs-2' | 'base64' | 'base64url' | 'latin1' | 'binary' | 'hex'
103
+ if (typeof buf === 'string') {
104
+ return buf;
105
+ }
106
+ if (typeof Buffer !== 'undefined' && ArrayBuffers._allowedBuffer) {
107
+ return Buffer.from(ArrayBuffers.asView(Uint8Array, buf)).toString(encoding);
108
+ }
109
+ // reference
110
+ // https://github.com/feross/buffer/blob/master/index.js
111
+ switch (encoding) {
112
+ case 'hex': {
113
+ const view: Uint8Array = ArrayBuffers.asView(Uint8Array, buf);
114
+ return [...view].map((b) => hexLookupTable[b]).join('');
115
+ }
116
+ case 'base64': {
117
+ const view: Uint8Array = ArrayBuffers.asView(Uint8Array, buf);
118
+ return btoa(String.fromCharCode(...view));
119
+ }
120
+ case 'utf8':
121
+ // falls through
122
+ case 'utf-8':
123
+ return new TextDecoder().decode(buf as any);
124
+ case 'ascii': {
125
+ const view: Uint8Array = ArrayBuffers.asView(Uint8Array, buf);
126
+ return String.fromCharCode(...view.map((v) => v & 0x7f));
127
+ }
128
+ case 'latin1':
129
+ // falls through
130
+ case 'binary': {
131
+ const view: Uint8Array = ArrayBuffers.asView(Uint8Array, buf);
132
+ return String.fromCharCode(...view);
133
+ }
134
+ case 'ucs2':
135
+ // falls through
136
+ case 'ucs-2':
137
+ // case 'utf-16le':
138
+ // falls through
139
+ case 'utf16le': {
140
+ const view: Uint8Array = ArrayBuffers.asView(Uint8Array, buf);
141
+ let res = '';
142
+ // If length is odd, the last 8 bits must be ignored (same as node.js)
143
+ for (let i = 0; i < view.length - 1; i += 2) {
144
+ res += String.fromCharCode(view[i] + view[i + 1] * 256);
145
+ }
146
+ return res;
147
+ }
148
+ default:
149
+ throw new Error(`[ArrayBuffers.toString] Unknown encoding: ${encoding}`);
150
+ }
151
+ },
152
+ toJSON: (v: BufferSource | string, reviver?: (this: any, key: string, value: any) => any) => {
153
+ return JSON.parse(ArrayBuffers.toString(v), reviver);
154
+ },
155
+ alloc: (size: number, fill?: string | number, encoding?: ToStringEncoding) => {
156
+ if (fill !== undefined) {
157
+ if (typeof fill === 'number') {
158
+ return new Uint8Array(size).fill(fill);
159
+ }
160
+ // as cast
161
+ // https://stackoverflow.com/questions/73994091
162
+ return ArrayBuffers.asView(Uint8Array, ArrayBuffers.from(fill, encoding)).slice(0, size);
163
+ }
164
+ return new ArrayBuffer(size);
165
+ },
166
+ from: (
167
+ v: string | BufferSource | ArrayLike<number> | Iterable<number>,
168
+ encoding: ToStringEncoding = 'utf8',
169
+ ): BufferSource => {
170
+ if (!v) {
171
+ return new ArrayBuffer(0);
172
+ }
173
+ if (typeof v === 'string') {
174
+ if (typeof Buffer !== 'undefined' && ArrayBuffers._allowedBuffer) {
175
+ return Buffer.from(v, encoding);
176
+ }
177
+
178
+ switch (encoding) {
179
+ case 'utf-8':
180
+ // falls through
181
+ case 'utf8':
182
+ return new TextEncoder().encode(v).buffer;
183
+ case 'base64':
184
+ // replaceAll
185
+ return Uint8Array.from(atob(v.replace(/[^0-9a-zA-Z=+/_ \r\n]/g, '')), (c) => c.charCodeAt(0));
186
+ default:
187
+ throw new Error(`[ArrayBuffers.from] Unknown encoding: ${encoding}`);
188
+ }
189
+ }
190
+ if (v instanceof ArrayBuffer) {
191
+ return v;
192
+ }
193
+ // lost length
194
+ if (ArrayBuffer.isView(v) || isBuffer(v)) {
195
+ if (v.byteOffset !== 0) {
196
+ // return v.buffer.slice(v.byteOffset, v.byteOffset + v.byteLength)
197
+ throw new Error('ArrayBuffers.from do not support view with offset');
198
+ }
199
+ return v.buffer;
200
+ }
201
+ if (Array.isArray(v)) {
202
+ return new Uint8Array(v);
203
+ }
204
+ const type = classOf(v);
205
+ throw new TypeError(`ArrayBuffers.from unsupported type ${type}`);
206
+ },
207
+ isEncoding: (encoding?: string) => {
208
+ switch (String(encoding).toLowerCase()) {
209
+ case 'hex':
210
+ case 'utf8':
211
+ case 'utf-8':
212
+ case 'ascii':
213
+ case 'latin1':
214
+ case 'binary':
215
+ case 'base64':
216
+ case 'ucs2':
217
+ case 'ucs-2':
218
+ case 'utf16le':
219
+ // case 'utf-16le':
220
+ return true;
221
+ default:
222
+ return false;
223
+ }
224
+ },
225
+ concat: (buffers: Array<BufferSource>, result?: ArrayBuffer, offset = 0) => {
226
+ // https://stackoverflow.com/questions/10786128/appending-arraybuffers
227
+
228
+ const length = buffers.reduce((a, b) => a + b.byteLength, 0);
229
+ const r = result ? new Uint8Array(result) : new Uint8Array(length);
230
+ for (const buffer of buffers) {
231
+ if (!buffer || !buffer.byteLength) continue;
232
+ let n: Uint8Array;
233
+ if (buffer instanceof ArrayBuffer) {
234
+ n = new Uint8Array(buffer);
235
+ } else if (ArrayBuffer.isView(buffer)) {
236
+ n = new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength);
237
+ } else {
238
+ throw new Error(`ArrayBuffers.concat unsupported type ${classOf(buffer)}`);
239
+ }
240
+ r.set(n, offset);
241
+ offset += buffer.byteLength;
242
+ }
243
+ return r.buffer;
244
+ },
245
+ };
246
+
247
+ export type TypedArray =
248
+ | Uint8Array
249
+ | Uint8ClampedArray
250
+ | Uint16Array
251
+ | Uint32Array
252
+ | Int8Array
253
+ | Int16Array
254
+ | Int32Array
255
+ | BigUint64Array
256
+ | BigInt64Array
257
+ | Float32Array
258
+ | Float64Array;
259
+
260
+ type ArrayBufferViewConstructor<T> = new (buffer: ArrayBufferLike, byteOffset?: number, byteLength?: number) => T;
261
+
262
+ const hexLookupTable = (function () {
263
+ const alphabet = '0123456789abcdef';
264
+ const table = new Array(256);
265
+ for (let i = 0; i < 16; ++i) {
266
+ const i16 = i * 16;
267
+ for (let j = 0; j < 16; ++j) {
268
+ table[i16 + j] = alphabet[i] + alphabet[j];
269
+ }
270
+ }
271
+ return table;
272
+ })();
@@ -0,0 +1,16 @@
1
+ import { ArrayBuffers } from './ArrayBuffers';
2
+
3
+ export class Buffer extends Uint8Array {
4
+ // constructor(buffer: ArrayBufferLike, byteOffset?: number, length?: number) {
5
+ // super(buffer, byteOffset, length);
6
+ // }
7
+
8
+ static from(array: string | BufferSource | ArrayLike<number> | Iterable<number>, arg2?: any): Buffer {
9
+ // todo mapfn
10
+ return new Buffer(ArrayBuffers.from(array, arg2) as ArrayBuffer);
11
+ }
12
+
13
+ toString(encoding?: string): string {
14
+ return ArrayBuffers.toString(this, encoding as any);
15
+ }
16
+ }
@@ -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
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
  }
@@ -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,7 +1,7 @@
1
1
  import { 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,
@@ -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
  }
@@ -0,0 +1,51 @@
1
+ import { expectType } from 'tsd';
2
+ import { get } from './get';
3
+
4
+ interface TestClass {
5
+ normal: string;
6
+ nested: {
7
+ a: number;
8
+ b: {
9
+ c: boolean;
10
+ };
11
+ };
12
+ arr: number[];
13
+ nestedArr: {
14
+ sum: number;
15
+ other: null;
16
+ }[];
17
+ deep: {
18
+ arr: string[];
19
+ };
20
+ deeplvl1: {
21
+ deeplvl2: {
22
+ deeplvl3: {
23
+ deeplvl4: {
24
+ value: RegExp;
25
+ };
26
+ }[];
27
+ };
28
+ }[];
29
+ }
30
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
31
+ const obj = {} as TestClass;
32
+
33
+ expectType<number>(get(obj, 'nested.a', null));
34
+ expectType<string>(get(obj, 'normal', null));
35
+ expectType<number>(get(obj, 'nested.a'));
36
+ expectType<boolean>(get(obj, 'nested.b.c'));
37
+ expectType<number[]>(get(obj, 'arr'));
38
+ expectType<number>(get(obj, 'arr[13]'));
39
+ expectType<number>(get(obj, 'arr.13'));
40
+ expectType<null>(get(obj, 'nestedArr[3].other'));
41
+ expectType<string[]>(get(obj, 'deep.deep'));
42
+ expectType<string>(get(obj, 'deep.arr[333]'));
43
+ expectType<number>(get(obj, 'deep.arr[333].length'));
44
+ expectType<boolean>(get(obj, 'nested["b"]["c"]'));
45
+ expectType<never>(get(obj, ''));
46
+ expectType<number>(get(obj, '', 3));
47
+ expectType<never>(get(obj, 'nested.asdfasdf'));
48
+ expectType<RegExp>(get(obj, 'deeplvl1[1].deeplvl2.deeplvl3[88].deeplvl4.value'));
49
+ expectType<never>(get(obj, 'deeplvl1[1].deeplvl2.deeplvl1[88].deeplvl4.value'));
50
+ expectType<TestClass>(get(obj, 'deeplvl1[1].deeplvl2.deeplvl1[88].deeplvl4.value', obj));
51
+ expectType<string>(get(obj, 'nested["dd"]', ''));
@@ -1,62 +1,9 @@
1
1
  import test from 'ava';
2
- import { expectType } from 'tsd';
3
2
  import { get } from './get';
4
3
  import { parseObjectPath } from './parseObjectPath';
5
4
 
6
- test('get typed', (t) => {
7
- interface TestClass {
8
- normal: string;
9
- nested: {
10
- a: number;
11
- b: {
12
- c: boolean;
13
- };
14
- };
15
- arr: number[];
16
- nestedArr: {
17
- sum: number;
18
- other: null;
19
- }[];
20
- deep: {
21
- arr: string[];
22
- };
23
- deeplvl1: {
24
- deeplvl2: {
25
- deeplvl3: {
26
- deeplvl4: {
27
- value: RegExp;
28
- };
29
- }[];
30
- };
31
- }[];
32
- }
33
-
34
- const obj = {} as TestClass;
35
-
36
- expectType<number>(get(obj, 'nested.a', null));
37
- expectType<string>(get(obj, 'normal', null));
38
- expectType<number>(get(obj, 'nested.a'));
39
- expectType<boolean>(get(obj, 'nested.b.c'));
40
- expectType<number[]>(get(obj, 'arr'));
41
- expectType<number>(get(obj, 'arr[13]'));
42
- expectType<number>(get(obj, 'arr.13'));
43
- expectType<null>(get(obj, 'nestedArr[3].other'));
44
- expectType<string[]>(get(obj, 'deep.deep'));
45
- expectType<string>(get(obj, 'deep.arr[333]'));
46
- expectType<number>(get(obj, 'deep.arr[333].length'));
47
- expectType<boolean>(get(obj, 'nested["b"]["c"]'));
48
- expectType<never>(get(obj, ''));
49
- expectType<number>(get(obj, '', 3));
50
- expectType<never>(get(obj, 'nested.asdfasdf'));
51
- expectType<RegExp>(get(obj, 'deeplvl1[1].deeplvl2.deeplvl3[88].deeplvl4.value'));
52
- expectType<never>(get(obj, 'deeplvl1[1].deeplvl2.deeplvl1[88].deeplvl4.value'));
53
- expectType<TestClass>(get(obj, 'deeplvl1[1].deeplvl2.deeplvl1[88].deeplvl4.value', obj));
54
- expectType<string>(get(obj, 'nested["dd"]', ''));
55
- t.pass();
56
- });
57
-
58
5
  test('get', (t) => {
59
- let obj = {
6
+ const obj = {
60
7
  undef: undefined,
61
8
  zero: 0,
62
9
  one: 1,
@@ -76,7 +23,7 @@ test('get', (t) => {
76
23
 
77
24
  function check(path: string, value: any, def?: any) {
78
25
  const out = get(obj, path, def);
79
- t.is(out, value, 'get(obj, "' + path + '") should be ' + value + ', got ' + out);
26
+ t.is(out, value, `get(obj, "${path}") should be ${value}, got ${out}`);
80
27
  if (path) {
81
28
  const arr = parseObjectPath(path);
82
29
  t.is(get(obj, arr, def), value, `get(obj,${JSON.stringify(arr)}, ${def})`);