@wener/utils 1.1.5 → 1.1.6

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 (106) hide show
  1. package/README.md +3 -1
  2. package/dist/cjs/_commonjsHelpers-dfec268f.js +2 -0
  3. package/dist/cjs/_commonjsHelpers-dfec268f.js.map +1 -0
  4. package/dist/cjs/api-7db97ae3.js +1085 -0
  5. package/dist/cjs/api-7db97ae3.js.map +1 -0
  6. package/dist/cjs/index-a6d1d653.js +14 -0
  7. package/dist/cjs/index-a6d1d653.js.map +1 -0
  8. package/dist/cjs/index.js +1 -1
  9. package/dist/cjs/index.js.map +1 -1
  10. package/dist/cjs/multipart-parser-141ed517.js +3 -0
  11. package/dist/cjs/multipart-parser-141ed517.js.map +1 -0
  12. package/dist/cjs/server.js +1 -1
  13. package/dist/cjs/server.js.map +1 -1
  14. package/dist/esm/_commonjsHelpers-28e086c5.js +2 -0
  15. package/dist/esm/_commonjsHelpers-28e086c5.js.map +1 -0
  16. package/dist/esm/api-3f555472.js +1085 -0
  17. package/dist/esm/api-3f555472.js.map +1 -0
  18. package/dist/esm/index-b50fef91.js +14 -0
  19. package/dist/esm/index-b50fef91.js.map +1 -0
  20. package/dist/esm/index.js +1 -1
  21. package/dist/esm/index.js.map +1 -1
  22. package/dist/esm/multipart-parser-5c1d6ee9.js +3 -0
  23. package/dist/esm/multipart-parser-5c1d6ee9.js.map +1 -0
  24. package/dist/esm/server.js +1 -1
  25. package/dist/esm/server.js.map +1 -1
  26. package/dist/system/_commonjsHelpers-07f370a7.js +2 -0
  27. package/dist/system/_commonjsHelpers-07f370a7.js.map +1 -0
  28. package/dist/system/api-dc50ebac.js +1085 -0
  29. package/dist/system/api-dc50ebac.js.map +1 -0
  30. package/dist/system/index-8f1807ba.js +14 -0
  31. package/dist/system/index-8f1807ba.js.map +1 -0
  32. package/dist/system/index.js +1 -1
  33. package/dist/system/index.js.map +1 -1
  34. package/dist/system/multipart-parser-53518ee9.js +3 -0
  35. package/dist/system/multipart-parser-53518ee9.js.map +1 -0
  36. package/dist/system/server.js +1 -1
  37. package/dist/system/server.js.map +1 -1
  38. package/lib/asyncs/createLazyPromise.js +55 -0
  39. package/lib/asyncs/createLazyPromise.js.map +1 -0
  40. package/lib/crypto/randomUUID.js +3 -5
  41. package/lib/crypto/randomUUID.js.map +1 -1
  42. package/lib/i18n/createTranslate.js +37 -0
  43. package/lib/i18n/createTranslate.js.map +1 -0
  44. package/lib/index.js +11 -6
  45. package/lib/index.js.map +1 -1
  46. package/lib/io/isTransferable.js +23 -0
  47. package/lib/io/isTransferable.js.map +1 -0
  48. package/lib/isomorphics/structuredClone.js +70 -0
  49. package/lib/isomorphics/structuredClone.js.map +1 -0
  50. package/lib/langs/classOf.js +6 -0
  51. package/lib/langs/classOf.js.map +1 -0
  52. package/lib/{validations/dequal.js → langs/deepEqual.js} +7 -7
  53. package/lib/langs/deepEqual.js.map +1 -0
  54. package/lib/{validations/shallow.js → langs/shallowEqual.js} +3 -3
  55. package/lib/langs/shallowEqual.js.map +1 -0
  56. package/lib/server/polyfillBrowser.js +12 -0
  57. package/lib/server/polyfillBrowser.js.map +1 -0
  58. package/lib/server/polyfillCrypto.js +10 -0
  59. package/lib/server/polyfillCrypto.js.map +1 -0
  60. package/lib/server/polyfillFetch.js +31 -0
  61. package/lib/server/polyfillFetch.js.map +1 -0
  62. package/lib/server/polyfillJsDom.js +49 -0
  63. package/lib/server/polyfillJsDom.js.map +1 -0
  64. package/lib/server.js +4 -1
  65. package/lib/server.js.map +1 -1
  66. package/lib/{formats → strings}/formatBytes.js +0 -0
  67. package/lib/{formats → strings}/formatBytes.js.map +1 -1
  68. package/lib/strings/renderTemplate.js +3 -1
  69. package/lib/strings/renderTemplate.js.map +1 -1
  70. package/lib/validations/isUUID.js +6 -0
  71. package/lib/validations/isUUID.js.map +1 -0
  72. package/package.json +5 -1
  73. package/src/asyncs/createLazyPromise.test.ts +39 -0
  74. package/src/asyncs/createLazyPromise.ts +63 -0
  75. package/src/crypto/hashing.test.ts +11 -7
  76. package/src/crypto/randomUUID.ts +3 -4
  77. package/src/i18n/createTranslate.test.ts +155 -0
  78. package/src/i18n/createTranslate.ts +52 -0
  79. package/src/index.ts +20 -8
  80. package/src/io/isBuffer.test.ts +7 -0
  81. package/src/io/isTransferable.test.ts +10 -0
  82. package/src/io/isTransferable.ts +50 -0
  83. package/src/isomorphics/structuredClone.test.ts +14 -0
  84. package/src/isomorphics/structuredClone.ts +85 -0
  85. package/src/langs/classOf.ts +3 -0
  86. package/src/{validations/dequal.test.ts → langs/deepEqual.test.ts} +2 -2
  87. package/src/{validations/dequal.ts → langs/deepEqual.ts} +5 -5
  88. package/src/langs/langs.test.ts +23 -0
  89. package/src/{validations/shallow.ts → langs/shallowEqual.ts} +1 -1
  90. package/src/server/polyfillBrowser.test.ts +15 -0
  91. package/src/server/polyfillBrowser.ts +9 -0
  92. package/src/server/polyfillCrypto.ts +7 -0
  93. package/src/server/polyfillFetch.ts +29 -0
  94. package/src/server/polyfillJsDom.ts +84 -0
  95. package/src/server.ts +4 -1
  96. package/src/{formats → strings}/formatBytes.ts +0 -0
  97. package/src/strings/renderTemplate.ts +4 -1
  98. package/src/validations/isUUID.ts +3 -0
  99. package/lib/asyncs/LazyPromise.js +0 -27
  100. package/lib/asyncs/LazyPromise.js.map +0 -1
  101. package/lib/server/polyfill.js +0 -8
  102. package/lib/server/polyfill.js.map +0 -1
  103. package/lib/validations/dequal.js.map +0 -1
  104. package/lib/validations/shallow.js.map +0 -1
  105. package/src/asyncs/LazyPromise.ts +0 -29
  106. package/src/server/polyfill.ts +0 -5
@@ -0,0 +1,155 @@
1
+ import test from 'ava';
2
+ import { createTranslate } from './createTranslate';
3
+
4
+ test('exports', (t) => {
5
+ let out = createTranslate();
6
+ t.is(typeof out, 'object', 'returns an object');
7
+ t.is(typeof out.t, 'function', '~> has "t" function');
8
+ t.is(typeof out.dict, 'function', '~> has "set" function');
9
+ t.is(typeof out.locale, 'function', '~> has "locale" function');
10
+ });
11
+
12
+ test('usage', (t) => {
13
+ let ctx = createTranslate({
14
+ en: { hello: 'Hello, {{name}}!' },
15
+ es: { hello: 'Hola {{name}}!' },
16
+ pt: { foo: 'foo {{name}}~!' },
17
+ });
18
+
19
+ t.deepEqual(ctx.dict('en'), { hello: 'Hello, {{name}}!' });
20
+
21
+ t.is(ctx.dict('foobar'), undefined);
22
+
23
+ let foo = ctx.t('hello');
24
+ t.is(foo, '', '~> "" w/o locale');
25
+
26
+ t.is(ctx.locale('en'), 'en', '>>> ctx.locale()');
27
+
28
+ t.is(ctx.locale(), 'en');
29
+
30
+ let bar = ctx.t('hello');
31
+ t.not(bar, '', '(en) found "hello" key');
32
+ t.is(bar, 'Hello, !', '~> interpolations empty if missing param');
33
+
34
+ let baz = ctx.t('hello', { name: 'world' });
35
+ t.is(baz, 'Hello, world!', '~> interpolations successful');
36
+
37
+ let bat = ctx.t('hello', { name: 'world' }, 'es');
38
+ t.not(bat, '', '(es) found "hello" key');
39
+ t.is(bat, 'Hola world!', '~> success');
40
+
41
+ t.is(ctx.t('hello', { name: 'world' }, 'pt'), '', '(pt) did NOT find "hello" key');
42
+
43
+ t.is(ctx.dict('pt', { hello: 'Oí {{name}}!' }), undefined, '>>> ctx.dict()');
44
+
45
+ let quz = ctx.t('hello', { name: 'world' }, 'pt');
46
+ t.not(quz, '', '(pt) found "hello" key');
47
+ t.is(quz, 'Oí world!', '~> success');
48
+
49
+ let qut = ctx.t('foo', { name: 'bar' }, 'pt');
50
+ t.not(qut, '', '(pt) found "foo" key');
51
+ t.is(qut, 'foo bar~!', '~> success');
52
+
53
+ t.is(ctx.locale('es'), 'es', '>>> ctx.locale()');
54
+
55
+ t.is(ctx.locale(), 'es');
56
+ t.is(ctx.locale(''), 'es');
57
+ t.is(ctx.locale(false as any), 'es');
58
+ t.is(ctx.locale(null as any), 'es');
59
+ t.is(ctx.locale(0 as any), 'es');
60
+
61
+ let qux = ctx.t('hello', { name: 'default' });
62
+ t.not(qux, '', '(es) found "hello" key');
63
+ t.is(qux, 'Hola default!', '~> success');
64
+
65
+ t.is(ctx.t('hello', { name: 'world' }, 'de'), '', '(de) did NOT find "hello" key');
66
+
67
+ t.is(ctx.dict('de', { hello: 'Hallo {{name}}!' }), undefined, '>>> ctx.dict(de)');
68
+
69
+ let qar = ctx.t('hello', { name: 'world' }, 'de');
70
+ t.not(qar, '', '(de) found "hello" key');
71
+ t.is(qar, 'Hallo world!', '~> success');
72
+ });
73
+
74
+ test('functional', (t) => {
75
+ let ctx = createTranslate({
76
+ en: {
77
+ hello(value: any) {
78
+ return `hello ${value || 'stranger'}~!`;
79
+ },
80
+ },
81
+ });
82
+
83
+ ctx.locale('en');
84
+
85
+ let foo = ctx.t('hello');
86
+ t.is(foo, 'hello stranger~!', '~> called function w/o param');
87
+
88
+ let bar = ctx.t('hello', 'world' as any);
89
+ t.is(bar, 'hello world~!', '~> called function w/ param (string)');
90
+
91
+ let baz = ctx.t('hello', [1, 2, 3]);
92
+ t.is(baz, 'hello 1,2,3~!', '~> called function w/ param (array)');
93
+ });
94
+
95
+ test('nested', (t) => {
96
+ let ctx = createTranslate({
97
+ en: {
98
+ fruits: {
99
+ apple: 'apple',
100
+ orange: 'orange',
101
+ grape: 'grape',
102
+ },
103
+ },
104
+ es: {
105
+ fruits: {
106
+ apple: 'manzana',
107
+ orange: 'naranja',
108
+ grape: 'uva',
109
+ },
110
+ },
111
+ });
112
+
113
+ ctx.locale('en');
114
+ t.is(ctx.t('fruits.apple'), 'apple', '(en) fruits.apple');
115
+ t.is(ctx.t('fruits.orange'), 'orange', '(en) fruits.orange');
116
+ t.is(ctx.t(['fruits', 'grape']), 'grape', '(en) ["fruits","grape"]');
117
+ t.is(ctx.t('fruits.404'), '', '(en) fruits.404 ~> ""');
118
+ t.is(ctx.t('error.404'), '', '(en) error.404 ~> ""');
119
+
120
+ ctx.locale('es');
121
+ t.is(ctx.t('fruits.apple'), 'manzana', '(es) fruits.apple');
122
+ t.is(ctx.t('fruits.orange'), 'naranja', '(es) fruits.orange');
123
+ t.is(ctx.t(['fruits', 'grape']), 'uva', '(es) ["fruits","grape"]');
124
+ t.is(ctx.t('fruits.404'), '', '(es) fruits.404 ~> ""');
125
+ t.is(ctx.t('error.404'), '', '(es) error.404 ~> ""');
126
+ });
127
+
128
+ test('arrays', (t) => {
129
+ let ctx = createTranslate({
130
+ en: {
131
+ foo: '{{0}} + {{1}} = {{2}}',
132
+ bar: [
133
+ {
134
+ baz: 'roses are {{colors.0}}, violets are {{colors.1}}',
135
+ },
136
+ ],
137
+ },
138
+ });
139
+
140
+ ctx.locale('en');
141
+
142
+ t.is(ctx.t('foo', [1, 2, 3]), '1 + 2 = 3', '~> foo');
143
+
144
+ t.is(ctx.t('bar.0.baz', { colors: ['red', 'blue'] }), 'roses are red, violets are blue', '~> bar.0.baz');
145
+ });
146
+
147
+ test('invalid value', (t) => {
148
+ let ctx = createTranslate({
149
+ en: {
150
+ foo: ['bar'],
151
+ },
152
+ });
153
+
154
+ t.deepEqual(ctx.t('foo', null as any, 'en'), ['bar']);
155
+ });
@@ -0,0 +1,52 @@
1
+ import { get } from '../objects/get';
2
+ import { ObjectPathLike } from '../objects/parseObjectPath';
3
+ import { renderTemplate } from '../strings/renderTemplate';
4
+
5
+ export interface Translate<T extends object> {
6
+ /** Get/Set the language key */
7
+ locale(lang?: string): string;
8
+
9
+ /** Define the dict of translations for a language */
10
+ dict(lang: string, dict: T): void;
11
+
12
+ /** Get the dict of translations for a language */
13
+ dict(lang: string): T;
14
+
15
+ /** Retrieve a translation segment for the current language */
16
+ t<X extends Record<string, any> | any[]>(key: ObjectPathLike, params?: X, lang?: string): string;
17
+ }
18
+
19
+ export function createTranslate<T extends object>(obj?: Record<string, T>): Translate<T> {
20
+ let locale = '';
21
+ const tree = obj || {};
22
+
23
+ return {
24
+ locale(lang) {
25
+ return (locale = lang || locale);
26
+ },
27
+
28
+ dict: ((lang, dict?) => {
29
+ if (dict) {
30
+ tree[lang] = Object.assign(tree[lang] || {}, dict);
31
+ return;
32
+ }
33
+ return tree[lang];
34
+ }) as Translate<T>['dict'],
35
+
36
+ t(key, params, lang) {
37
+ const val = get(tree[lang || locale], key, '') as any;
38
+ if (process.env.NODE_ENV === 'development') {
39
+ if (val == null) {
40
+ return console.error(
41
+ `[Translate] Missing the "${[].concat(key as any).join('.')}" key within the "${
42
+ lang || locale
43
+ }" dictionary`,
44
+ );
45
+ }
46
+ }
47
+ if (typeof val === 'function') return val(params);
48
+ if (typeof val === 'string') return renderTemplate(val, params!, 'common');
49
+ return val;
50
+ },
51
+ };
52
+ }
package/src/index.ts CHANGED
@@ -13,7 +13,7 @@ export { set } from './objects/set';
13
13
  export { parseObjectPath } from './objects/parseObjectPath';
14
14
 
15
15
  // async
16
- export { createLazyPromise, type LazyPromise } from './asyncs/LazyPromise';
16
+ export { createLazyPromise, type LazyPromise } from './asyncs/createLazyPromise';
17
17
  export { setAsyncInterval, clearAsyncInterval } from './asyncs/AsyncInterval';
18
18
  export { type MaybePromise } from './asyncs/MaybePromise';
19
19
 
@@ -26,12 +26,15 @@ export { isPromise } from './asyncs/isPromise';
26
26
  export { isClass } from './validations/isClass';
27
27
  export { isDefined } from './validations/isDefined';
28
28
  export { isEmptyObject } from './validations/isEmptyObject';
29
- export { shallow } from './validations/shallow';
30
- export { dequal } from './validations/dequal';
29
+ export { shallowEqual } from './langs/shallowEqual';
30
+ export { deepEqual } from './langs/deepEqual';
31
+ export { isUUID } from './validations/isUUID';
32
+
33
+ export { classOf } from './langs/classOf';
31
34
 
32
35
  // modules
33
36
  export { parseModuleId, type ParsedModuleId } from './modules/parseModuleId';
34
- export { isModule } from './modules/isModule';
37
+ export { isModule, type Module } from './modules/isModule';
35
38
 
36
39
  // logging
37
40
  export { type Logger, type LogLevel } from './logging/Logger';
@@ -42,21 +45,30 @@ export { createChildLogger } from './logging/createChildLogger';
42
45
  // strings
43
46
  export { pascalCase, camelCase } from './strings/camelCase';
44
47
  export { renderTemplate } from './strings/renderTemplate';
48
+ export { formatBytes } from './strings/formatBytes';
45
49
 
46
- export { createRandom } from './maths/random';
50
+ // i18n
51
+ export { createTranslate } from './i18n/createTranslate';
52
+
53
+ // io
47
54
  export { isBuffer } from './io/isBuffer';
55
+ export { isTransferable } from './io/isTransferable';
48
56
 
57
+ // browser
49
58
  export { copy } from './browsers/copy';
50
59
  export { download } from './browsers/download';
51
60
  export { loadScripts, loadStyles } from './browsers/loaders';
52
61
  export { getFileFromDataTransfer } from './browsers/getFileFromDataTransfer';
53
62
 
63
+ // polyfills
54
64
  export { getGlobalThis } from './isomorphics/getGlobalThis';
55
-
56
- export { formatBytes } from './formats/formatBytes';
57
- export { urljoin } from './shim/urljoin';
65
+ export { structuredClone } from './isomorphics/structuredClone';
58
66
 
59
67
  // crypto
60
68
  export { randomUUID } from './crypto/randomUUID';
61
69
  export { sha1, sha256, sha384, sha512 } from './crypto/hashing';
62
70
  export { hex } from './crypto/hex';
71
+
72
+ // misc
73
+ export { createRandom } from './maths/random';
74
+ export { urljoin } from './shim/urljoin';
@@ -0,0 +1,7 @@
1
+ import test from 'ava';
2
+ import { Buffer } from 'node:buffer';
3
+ import { isBuffer } from './isBuffer';
4
+
5
+ test('isBuffer', (t) => {
6
+ t.true(isBuffer(Buffer.from('')));
7
+ });
@@ -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
+ * {@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
+ let c = _clone(k);
11
+ t.deepEqual(c, v);
12
+ t.is(classOf(c), classOf(v));
13
+ }
14
+ });
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Chrome 98, Safari 15.4
3
+ *
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}
6
+ */
7
+ import { classOf } from '../langs/classOf';
8
+
9
+ export const structuredClone: <T>(value: T, options?: StructuredSerializeOptions) => T =
10
+ globalThis.structuredClone || _clone;
11
+
12
+ function set(obj: any, key: any, val: any) {
13
+ if (typeof val.value === 'object') val.value = _clone(val.value);
14
+ if (!val.enumerable || val.get || val.set || !val.configurable || !val.writable || key === '__proto__') {
15
+ Object.defineProperty(obj, key, val);
16
+ } else obj[key] = val.value;
17
+ }
18
+
19
+ /**
20
+ * {@link https://github.com/lukeed/klona/blob/master/src/full.js klona}
21
+ */
22
+ export function _clone(x: any): any {
23
+ // too complex
24
+ // https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/web.structured-clone.js
25
+
26
+ if (typeof x !== 'object') return x;
27
+
28
+ let i = 0;
29
+ let k;
30
+ let list;
31
+ let tmp: any;
32
+ const str = classOf(x);
33
+ switch (str) {
34
+ case 'Array':
35
+ tmp = Array(x.length);
36
+ break;
37
+ case 'Object':
38
+ tmp = Object.create(x.__proto__ || null);
39
+ break;
40
+ case 'Set':
41
+ tmp = new Set();
42
+ x.forEach(function (val: any) {
43
+ tmp.add(_clone(val));
44
+ });
45
+ break;
46
+ case 'Map':
47
+ tmp = new Map();
48
+ x.forEach(function (val: any, key: any) {
49
+ tmp.set(_clone(key), _clone(val));
50
+ });
51
+ break;
52
+ case 'Date':
53
+ tmp = new Date(+x);
54
+ break;
55
+ case 'RegExp':
56
+ tmp = new RegExp(x.source, x.flags);
57
+ break;
58
+ case 'DataView':
59
+ tmp = new x.constructor(_clone(x.buffer));
60
+ break;
61
+ case 'ArrayBuffer':
62
+ tmp = x.slice(0);
63
+ break;
64
+ default:
65
+ // typed arrays
66
+ if (str.endsWith('Array')) {
67
+ // ArrayBuffer.isView(x)
68
+ // ~> `new` bcuz `Buffer.slice` => ref
69
+ tmp = new x.constructor(x);
70
+ }
71
+ }
72
+
73
+ if (tmp) {
74
+ for (list = Object.getOwnPropertySymbols(x); i < list.length; i++) {
75
+ set(tmp, list[i], Object.getOwnPropertyDescriptor(x, list[i]));
76
+ }
77
+
78
+ for (i = 0, list = Object.getOwnPropertyNames(x); i < list.length; i++) {
79
+ if (Object.hasOwnProperty.call(tmp, (k = list[i])) && tmp[k] === x[k]) continue;
80
+ set(tmp, k, Object.getOwnPropertyDescriptor(x, k));
81
+ }
82
+ }
83
+
84
+ return tmp || x;
85
+ }
@@ -0,0 +1,3 @@
1
+ export function classOf(o: any) {
2
+ return Object.prototype.toString.call(o).slice(8, -1);
3
+ }
@@ -1,9 +1,9 @@
1
1
  import test from 'ava';
2
- import { dequal } from './dequal';
2
+ import { deepEqual } from './deepEqual';
3
3
 
4
4
  test('deep equal', (t) => {
5
5
  t.true(
6
- dequal(
6
+ deepEqual(
7
7
  {
8
8
  a: null,
9
9
  b: Infinity,
@@ -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 (dequal(key, tar)) return key;
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 dequal(foo: any, bar: any) {
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-- && dequal(foo[len], bar[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 (!dequal(len[1], bar.get(tmp))) {
55
+ if (!deepEqual(len[1], bar.get(tmp))) {
56
56
  return false;
57
57
  }
58
58
  }
@@ -95,7 +95,7 @@ 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) || !dequal(foo[ctor], bar[ctor])) return false;
98
+ if (!(ctor in bar) || !deepEqual(foo[ctor], bar[ctor])) return false;
99
99
  }
100
100
  return Object.keys(bar).length === len;
101
101
  }
@@ -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 shallow<T, U>(objA: T, objB: U) {
6
+ export function shallowEqual<T, U>(objA: T, objB: U) {
7
7
  if (Object.is(objA, objB)) {
8
8
  return true;
9
9
  }
@@ -0,0 +1,15 @@
1
+ import test from 'ava';
2
+ import { polyfillBrowser } from './polyfillBrowser';
3
+
4
+ test.before(async () => {
5
+ await polyfillBrowser();
6
+ });
7
+
8
+ test('polyfillBrowser', (t) => {
9
+ t.truthy(fetch);
10
+ t.truthy(window);
11
+ t.truthy(document);
12
+ t.truthy(crypto);
13
+ // not the same
14
+ t.not(window, globalThis);
15
+ });
@@ -0,0 +1,9 @@
1
+ import { polyfillCrypto } from './polyfillCrypto';
2
+ import { polyfillFetch } from './polyfillFetch';
3
+ import { polyfillJsDom } from './polyfillJsDom';
4
+
5
+ export async function polyfillBrowser() {
6
+ await polyfillCrypto();
7
+ await polyfillFetch();
8
+ await polyfillJsDom();
9
+ }
@@ -0,0 +1,7 @@
1
+ export async function polyfillCrypto() {
2
+ if ('crypto' in globalThis) {
3
+ return false;
4
+ }
5
+ globalThis.crypto = (await import('node:crypto')).webcrypto as Crypto;
6
+ return true;
7
+ }
@@ -0,0 +1,29 @@
1
+ export async function polyfillFetch() {
2
+ if ('fetch' in globalThis) {
3
+ return false;
4
+ }
5
+ const {
6
+ default: fetch,
7
+ Response,
8
+ Headers,
9
+ Request,
10
+ AbortError,
11
+ FetchError,
12
+ FormData,
13
+ Blob,
14
+ File,
15
+ // @ts-ignore
16
+ } = await import('node-fetch');
17
+ Object.assign(globalThis, {
18
+ fetch,
19
+ Response,
20
+ Headers,
21
+ Request,
22
+ AbortError,
23
+ FetchError,
24
+ FormData,
25
+ Blob,
26
+ File,
27
+ });
28
+ return true;
29
+ }