@wener/utils 1.1.5 → 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.
- package/README.md +5 -1
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/server.js +1 -1
- package/dist/cjs/server.js.map +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/server.js +1 -1
- package/dist/esm/server.js.map +1 -1
- package/dist/system/index.js +1 -1
- package/dist/system/index.js.map +1 -1
- package/dist/system/server.js +1 -1
- package/dist/system/server.js.map +1 -1
- package/lib/arrays/MaybeArray.js.map +1 -1
- package/lib/asyncs/createLazyPromise.js +55 -0
- package/lib/asyncs/createLazyPromise.js.map +1 -0
- package/lib/asyncs/timeout.js +1 -1
- package/lib/asyncs/timeout.js.map +1 -1
- package/lib/browsers/copy.js +2 -3
- package/lib/browsers/copy.js.map +1 -1
- package/lib/browsers/loaders.js +6 -11
- package/lib/browsers/loaders.js.map +1 -1
- package/lib/crypto/{hex.js → base.js} +1 -1
- package/lib/crypto/base.js.map +1 -0
- package/lib/crypto/hashing.js +4 -4
- package/lib/crypto/hashing.js.map +1 -1
- package/lib/crypto/randomUUID.js +3 -5
- package/lib/crypto/randomUUID.js.map +1 -1
- package/lib/i18n/createTranslate.js +37 -0
- package/lib/i18n/createTranslate.js.map +1 -0
- package/lib/index.js +12 -7
- package/lib/index.js.map +1 -1
- package/lib/io/ArrayBuffers.js +164 -0
- package/lib/io/ArrayBuffers.js.map +1 -0
- package/lib/io/isBuffer.js +1 -1
- package/lib/io/isBuffer.js.map +1 -1
- package/lib/io/isTransferable.js +23 -0
- package/lib/io/isTransferable.js.map +1 -0
- package/lib/isomorphics/structuredClone.js +70 -0
- package/lib/isomorphics/structuredClone.js.map +1 -0
- package/lib/langs/classOf.js +6 -0
- package/lib/langs/classOf.js.map +1 -0
- package/lib/{validations/dequal.js → langs/deepEqual.js} +7 -7
- package/lib/langs/deepEqual.js.map +1 -0
- package/lib/{validations/shallow.js → langs/shallowEqual.js} +3 -3
- package/lib/langs/shallowEqual.js.map +1 -0
- package/lib/logging/createNoopLogger.js.map +1 -1
- package/lib/modules/isModule.js.map +1 -1
- package/lib/modules/parseModuleId.js +7 -5
- package/lib/modules/parseModuleId.js.map +1 -1
- package/lib/objects/parseObjectPath.js.map +1 -1
- package/lib/objects/set.js.map +1 -1
- package/lib/server/polyfillBrowser.js +12 -0
- package/lib/server/polyfillBrowser.js.map +1 -0
- package/lib/server/polyfillCrypto.js +10 -0
- package/lib/server/polyfillCrypto.js.map +1 -0
- package/lib/server/polyfillFetch.js +31 -0
- package/lib/server/polyfillFetch.js.map +1 -0
- package/lib/server/polyfillJsDom.js +49 -0
- package/lib/server/polyfillJsDom.js.map +1 -0
- package/lib/server.js +4 -1
- package/lib/server.js.map +1 -1
- package/lib/{formats → strings}/formatBytes.js +1 -1
- package/lib/{formats → strings}/formatBytes.js.map +1 -1
- package/lib/strings/renderTemplate.js +4 -2
- package/lib/strings/renderTemplate.js.map +1 -1
- package/lib/validations/isUUID.js +6 -0
- package/lib/validations/isUUID.js.map +1 -0
- package/package.json +14 -2
- package/src/arrays/MaybeArray.ts +1 -1
- package/src/asyncs/createLazyPromise.test.ts +39 -0
- package/src/asyncs/createLazyPromise.ts +63 -0
- package/src/asyncs/generatorOfStream.ts +1 -0
- package/src/asyncs/timeout.ts +1 -1
- package/src/browsers/copy.ts +6 -5
- package/src/browsers/loaders.ts +6 -11
- package/src/crypto/{hex.ts → base.ts} +3 -0
- package/src/crypto/hashing.test.ts +12 -8
- package/src/crypto/hashing.ts +4 -4
- package/src/crypto/randomUUID.ts +6 -4
- package/src/i18n/createTranslate.test.ts +155 -0
- package/src/i18n/createTranslate.ts +52 -0
- package/src/index.ts +22 -9
- package/src/io/AbstractEncoding.ts +21 -0
- package/src/io/ArrayBuffer.test-d.ts +4 -0
- package/src/io/ArrayBuffers.base64.test.ts +61 -0
- package/src/io/ArrayBuffers.test.ts +23 -0
- package/src/io/ArrayBuffers.ts +272 -0
- package/src/io/Buffer.ts +16 -0
- package/src/io/isBuffer.test.ts +9 -0
- package/src/io/isBuffer.ts +3 -8
- package/src/io/isTransferable.test.ts +10 -0
- package/src/io/isTransferable.ts +50 -0
- package/src/isomorphics/structuredClone.test.ts +14 -0
- package/src/isomorphics/structuredClone.ts +88 -0
- package/src/langs/classOf.ts +3 -0
- package/src/{validations/dequal.test.ts → langs/deepEqual.test.ts} +2 -2
- package/src/{validations/dequal.ts → langs/deepEqual.ts} +6 -5
- package/src/langs/langs.test.ts +23 -0
- package/src/{validations/shallow.ts → langs/shallowEqual.ts} +2 -2
- package/src/logging/Logger.ts +6 -0
- package/src/logging/createNoopLogger.ts +1 -1
- package/src/logging/logger.test.ts +3 -3
- package/src/modules/isModule.ts +3 -0
- package/src/modules/parseModuleId.test.ts +7 -2
- package/src/modules/parseModuleId.ts +15 -9
- package/src/objects/get.test-d.ts +51 -0
- package/src/objects/get.test.ts +2 -55
- package/src/objects/parseObjectPath.ts +4 -3
- package/src/objects/set.test.ts +32 -31
- package/src/objects/set.ts +2 -2
- package/src/server/polyfillBrowser.test.ts +15 -0
- package/src/server/polyfillBrowser.ts +17 -0
- package/src/server/polyfillCrypto.ts +7 -0
- package/src/server/polyfillFetch.ts +28 -0
- package/src/server/polyfillJsDom.ts +85 -0
- package/src/server.ts +4 -1
- package/src/{formats → strings}/formatBytes.ts +1 -1
- package/src/strings/renderTemplate.test.ts +1 -0
- package/src/strings/renderTemplate.ts +12 -6
- package/src/typedoc.ts +2 -0
- package/src/validations/isUUID.ts +3 -0
- package/tsconfig.json +2 -1
- package/lib/asyncs/LazyPromise.js +0 -27
- package/lib/asyncs/LazyPromise.js.map +0 -1
- package/lib/crypto/hex.js.map +0 -1
- package/lib/server/polyfill.js +0 -8
- package/lib/server/polyfill.js.map +0 -1
- package/lib/shim/urljoin.js +0 -51
- package/lib/shim/urljoin.js.map +0 -1
- package/lib/validations/dequal.js.map +0 -1
- package/lib/validations/shallow.js.map +0 -1
- package/src/asyncs/LazyPromise.ts +0 -29
- package/src/server/polyfill.ts +0 -5
- package/src/shim/urljoin.test.ts +0 -6
- package/src/shim/urljoin.ts +0 -75
- package/src/types.d.ts +0 -7
package/src/io/isBuffer.ts
CHANGED
|
@@ -1,13 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* check {@
|
|
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
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import test from 'ava';
|
|
2
|
+
import { Buffer } from 'node:buffer';
|
|
3
|
+
import { isTransferable } from './isTransferable';
|
|
4
|
+
|
|
5
|
+
test('isTransferable', (t) => {
|
|
6
|
+
t.false(isTransferable(0));
|
|
7
|
+
t.false(isTransferable(Buffer.from('')));
|
|
8
|
+
t.true(new ArrayBuffer(0) instanceof ArrayBuffer);
|
|
9
|
+
t.true(isTransferable(new ArrayBuffer(0)));
|
|
10
|
+
});
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* transferable object pass between workers, can work with structuredClone
|
|
3
|
+
*
|
|
4
|
+
* - Chrome 87, FF 103, Safari X, NodeJS X
|
|
5
|
+
*
|
|
6
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Glossary/Transferable_objects | Transferable objects}
|
|
7
|
+
*/
|
|
8
|
+
export function isTransferable(v: any): v is TransferableObject {
|
|
9
|
+
_ctors ||= ctors();
|
|
10
|
+
return _ctors.some((ctor) => v instanceof ctor);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
let _ctors: any[];
|
|
14
|
+
|
|
15
|
+
function ctors() {
|
|
16
|
+
const o: any = globalThis.window || globalThis || global;
|
|
17
|
+
return [
|
|
18
|
+
o.ArrayBuffer,
|
|
19
|
+
o.MessagePort,
|
|
20
|
+
o.ReadableStream,
|
|
21
|
+
o.WritableStream,
|
|
22
|
+
o.TransformStream,
|
|
23
|
+
o.AudioData,
|
|
24
|
+
o.ImageBitmap,
|
|
25
|
+
o.VideoFrame,
|
|
26
|
+
o.OffscreenCanvas,
|
|
27
|
+
o.RTCDataChannel,
|
|
28
|
+
].filter(Boolean);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export type TransferableObject =
|
|
32
|
+
| Transferable
|
|
33
|
+
| ArrayBuffer
|
|
34
|
+
| MessagePort
|
|
35
|
+
| ReadableStream
|
|
36
|
+
| WritableStream
|
|
37
|
+
| TransformStream
|
|
38
|
+
| AudioData
|
|
39
|
+
| ImageBitmap
|
|
40
|
+
| VideoFrame
|
|
41
|
+
| OffscreenCanvas
|
|
42
|
+
| RTCDataChannel;
|
|
43
|
+
|
|
44
|
+
declare global {
|
|
45
|
+
interface OffscreenCanvas {}
|
|
46
|
+
|
|
47
|
+
interface VideoFrame {}
|
|
48
|
+
|
|
49
|
+
interface AudioData {}
|
|
50
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import test from 'ava';
|
|
2
|
+
import { classOf } from '../langs/classOf';
|
|
3
|
+
import { _clone } from './structuredClone';
|
|
4
|
+
|
|
5
|
+
test('structuredClone', (t) => {
|
|
6
|
+
for (const [k, v] of [
|
|
7
|
+
['', ''],
|
|
8
|
+
[Number(1), 1],
|
|
9
|
+
]) {
|
|
10
|
+
const c = _clone(k);
|
|
11
|
+
t.deepEqual(c, v);
|
|
12
|
+
t.is(classOf(c), classOf(v));
|
|
13
|
+
}
|
|
14
|
+
});
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/* eslint no-proto:0 */
|
|
2
|
+
import { classOf } from '../langs/classOf';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Clone an object using structured cloning algorithm
|
|
6
|
+
*
|
|
7
|
+
* - Chrome 98, Safari 15.4
|
|
8
|
+
*
|
|
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}
|
|
11
|
+
*/
|
|
12
|
+
export const structuredClone: <T>(value: T, options?: StructuredSerializeOptions) => T =
|
|
13
|
+
globalThis.structuredClone || _clone;
|
|
14
|
+
|
|
15
|
+
function set(obj: any, key: any, val: any) {
|
|
16
|
+
if (typeof val.value === 'object') val.value = _clone(val.value);
|
|
17
|
+
if (!val.enumerable || val.get || val.set || !val.configurable || !val.writable || key === '__proto__') {
|
|
18
|
+
Object.defineProperty(obj, key, val);
|
|
19
|
+
} else obj[key] = val.value;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @see {@link https://github.com/lukeed/klona/blob/master/src/full.js klona}
|
|
24
|
+
*/
|
|
25
|
+
export function _clone(x: any): any {
|
|
26
|
+
// too complex
|
|
27
|
+
// https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/web.structured-clone.js
|
|
28
|
+
|
|
29
|
+
if (typeof x !== 'object') return x;
|
|
30
|
+
|
|
31
|
+
let i = 0;
|
|
32
|
+
let k;
|
|
33
|
+
let list;
|
|
34
|
+
let tmp: any;
|
|
35
|
+
const str = classOf(x);
|
|
36
|
+
switch (str) {
|
|
37
|
+
case 'Array':
|
|
38
|
+
tmp = Array(x.length);
|
|
39
|
+
break;
|
|
40
|
+
case 'Object':
|
|
41
|
+
tmp = Object.create(x.__proto__ || null);
|
|
42
|
+
break;
|
|
43
|
+
case 'Set':
|
|
44
|
+
tmp = new Set();
|
|
45
|
+
x.forEach(function (val: any) {
|
|
46
|
+
tmp.add(_clone(val));
|
|
47
|
+
});
|
|
48
|
+
break;
|
|
49
|
+
case 'Map':
|
|
50
|
+
tmp = new Map();
|
|
51
|
+
x.forEach(function (val: any, key: any) {
|
|
52
|
+
tmp.set(_clone(key), _clone(val));
|
|
53
|
+
});
|
|
54
|
+
break;
|
|
55
|
+
case 'Date':
|
|
56
|
+
tmp = new Date(+x);
|
|
57
|
+
break;
|
|
58
|
+
case 'RegExp':
|
|
59
|
+
tmp = new RegExp(x.source, x.flags);
|
|
60
|
+
break;
|
|
61
|
+
case 'DataView':
|
|
62
|
+
tmp = new x.constructor(_clone(x.buffer));
|
|
63
|
+
break;
|
|
64
|
+
case 'ArrayBuffer':
|
|
65
|
+
tmp = x.slice(0);
|
|
66
|
+
break;
|
|
67
|
+
default:
|
|
68
|
+
// typed arrays
|
|
69
|
+
if (str.endsWith('Array')) {
|
|
70
|
+
// ArrayBuffer.isView(x)
|
|
71
|
+
// ~> `new` bcuz `Buffer.slice` => ref
|
|
72
|
+
tmp = new x.constructor(x);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (tmp) {
|
|
77
|
+
for (list = Object.getOwnPropertySymbols(x); i < list.length; i++) {
|
|
78
|
+
set(tmp, list[i], Object.getOwnPropertyDescriptor(x, list[i]));
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
for (i = 0, list = Object.getOwnPropertyNames(x); i < list.length; i++) {
|
|
82
|
+
if (Object.hasOwnProperty.call(tmp, (k = list[i])) && tmp[k] === x[k]) continue;
|
|
83
|
+
set(tmp, k, Object.getOwnPropertyDescriptor(x, k));
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return tmp || x;
|
|
88
|
+
}
|
|
@@ -3,7 +3,7 @@ const hasElementType = typeof Element !== 'undefined';
|
|
|
3
3
|
|
|
4
4
|
function find(iter: any, tar: any, key?: any) {
|
|
5
5
|
for (key of iter.keys()) {
|
|
6
|
-
if (
|
|
6
|
+
if (deepEqual(key, tar)) return key;
|
|
7
7
|
}
|
|
8
8
|
}
|
|
9
9
|
|
|
@@ -12,7 +12,7 @@ function find(iter: any, tar: any, key?: any) {
|
|
|
12
12
|
* @see {@link https://github.com/lukeed/dequal/blob/master/src/lite.js dequal/src/lite.js}
|
|
13
13
|
* @see {@link https://github.com/FormidableLabs/react-fast-compare/blob/master/index.js react-fast-compare/index.js}
|
|
14
14
|
*/
|
|
15
|
-
export function
|
|
15
|
+
export function deepEqual(foo: any, bar: any) {
|
|
16
16
|
let ctor, len, tmp;
|
|
17
17
|
if (foo === bar) return true;
|
|
18
18
|
|
|
@@ -22,7 +22,7 @@ export function dequal(foo: any, bar: any) {
|
|
|
22
22
|
|
|
23
23
|
if (ctor === Array) {
|
|
24
24
|
if ((len = foo.length) === bar.length) {
|
|
25
|
-
while (len-- &&
|
|
25
|
+
while (len-- && deepEqual(foo[len], bar[len]));
|
|
26
26
|
}
|
|
27
27
|
return len === -1;
|
|
28
28
|
}
|
|
@@ -52,7 +52,7 @@ export function dequal(foo: any, bar: any) {
|
|
|
52
52
|
tmp = find(bar, tmp);
|
|
53
53
|
if (!tmp) return false;
|
|
54
54
|
}
|
|
55
|
-
if (!
|
|
55
|
+
if (!deepEqual(len[1], bar.get(tmp))) {
|
|
56
56
|
return false;
|
|
57
57
|
}
|
|
58
58
|
}
|
|
@@ -95,11 +95,12 @@ export function dequal(foo: any, bar: any) {
|
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
if (has.call(foo, ctor) && ++len && !has.call(bar, ctor)) return false;
|
|
98
|
-
if (!(ctor in bar) || !
|
|
98
|
+
if (!(ctor in bar) || !deepEqual(foo[ctor], bar[ctor])) return false;
|
|
99
99
|
}
|
|
100
100
|
return Object.keys(bar).length === len;
|
|
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,23 @@
|
|
|
1
|
+
import test from 'ava';
|
|
2
|
+
import { classOf } from './classOf';
|
|
3
|
+
|
|
4
|
+
test('classOf', (t) => {
|
|
5
|
+
for (const [k, v] of [
|
|
6
|
+
[0, 'Number'],
|
|
7
|
+
['', 'String'],
|
|
8
|
+
[true, 'Boolean'],
|
|
9
|
+
[null, 'Null'],
|
|
10
|
+
[undefined, 'Undefined'],
|
|
11
|
+
[{}, 'Object'],
|
|
12
|
+
[[], 'Array'],
|
|
13
|
+
[new ArrayBuffer(0), 'ArrayBuffer'],
|
|
14
|
+
[new Map(), 'Map'],
|
|
15
|
+
[new Set(), 'Set'],
|
|
16
|
+
[new Date(), 'Date'],
|
|
17
|
+
[new RegExp(''), 'RegExp'],
|
|
18
|
+
[new DataView(new ArrayBuffer(0)), 'DataView'],
|
|
19
|
+
[new Int8Array(0), 'Int8Array'],
|
|
20
|
+
]) {
|
|
21
|
+
t.is(classOf(k), v as any);
|
|
22
|
+
}
|
|
23
|
+
});
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* @see {@link https://github.com/pmndrs/zustand/blob/main/src/shallow.ts zustand/src/shallow.ts}
|
|
5
5
|
*/
|
|
6
|
-
export function
|
|
6
|
+
export function shallowEqual<T, U>(objA: T, objB: U) {
|
|
7
7
|
if (Object.is(objA, objB)) {
|
|
8
8
|
return true;
|
|
9
9
|
}
|
|
@@ -16,7 +16,7 @@ export function shallow<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]
|
|
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;
|
package/src/logging/Logger.ts
CHANGED
|
@@ -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
|
|
|
@@ -4,9 +4,9 @@ import { createWriteLogger } from './createWriteLogger';
|
|
|
4
4
|
|
|
5
5
|
test('logger', (t) => {
|
|
6
6
|
{
|
|
7
|
-
|
|
7
|
+
const logs: any[] = [];
|
|
8
8
|
const base = createWriteLogger((o) => logs.push(o));
|
|
9
|
-
|
|
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
|
-
|
|
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);
|
package/src/modules/isModule.ts
CHANGED
|
@@ -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
|
|
18
|
+
org: string;
|
|
17
19
|
}
|
|
18
20
|
);
|
|
19
21
|
|
|
20
22
|
/**
|
|
21
23
|
* Parse NPM module id
|
|
22
24
|
*
|
|
23
|
-
*
|
|
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
|
-
|
|
35
|
+
const scoped = Boolean(org);
|
|
32
36
|
const v = /^\d+\.\d+\.\d+/.test(version) ? version : undefined;
|
|
33
|
-
|
|
34
|
-
const o = {
|
|
37
|
+
const range = version || 'latest';
|
|
38
|
+
const o: ParsedModuleId = {
|
|
35
39
|
id: `${name}@${range}`,
|
|
36
40
|
name,
|
|
37
|
-
range
|
|
41
|
+
range,
|
|
38
42
|
scoped,
|
|
39
43
|
pkg,
|
|
40
|
-
|
|
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
|
|
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"]', ''));
|
package/src/objects/get.test.ts
CHANGED
|
@@ -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
|
-
|
|
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,
|
|
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})`);
|
|
@@ -5,9 +5,10 @@ export type ObjectPathLike = ObjectKey | ObjectPath;
|
|
|
5
5
|
/**
|
|
6
6
|
* Parse object path
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
8
|
+
* @example
|
|
9
|
+
* parseObjectPath('a.b.c') // => ['a', 'b', 'c']
|
|
10
|
+
* parseObjectPath('a[0].b') // => ['a', 0, 'b']
|
|
11
|
+
* parseObjectPath('a[0][1]') // => ['a', 0, 1]
|
|
11
12
|
*
|
|
12
13
|
*/
|
|
13
14
|
export function parseObjectPath(s: ObjectPathLike): ObjectPath {
|