@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.
Files changed (137) hide show
  1. package/README.md +5 -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 +55 -0
  16. package/lib/asyncs/createLazyPromise.js.map +1 -0
  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 +3 -5
  28. package/lib/crypto/randomUUID.js.map +1 -1
  29. package/lib/i18n/createTranslate.js +37 -0
  30. package/lib/i18n/createTranslate.js.map +1 -0
  31. package/lib/index.js +12 -7
  32. package/lib/index.js.map +1 -1
  33. package/lib/io/ArrayBuffers.js +164 -0
  34. package/lib/io/ArrayBuffers.js.map +1 -0
  35. package/lib/io/isBuffer.js +1 -1
  36. package/lib/io/isBuffer.js.map +1 -1
  37. package/lib/io/isTransferable.js +23 -0
  38. package/lib/io/isTransferable.js.map +1 -0
  39. package/lib/isomorphics/structuredClone.js +70 -0
  40. package/lib/isomorphics/structuredClone.js.map +1 -0
  41. package/lib/langs/classOf.js +6 -0
  42. package/lib/langs/classOf.js.map +1 -0
  43. package/lib/{validations/dequal.js → langs/deepEqual.js} +7 -7
  44. package/lib/langs/deepEqual.js.map +1 -0
  45. package/lib/{validations/shallow.js → langs/shallowEqual.js} +3 -3
  46. package/lib/langs/shallowEqual.js.map +1 -0
  47. package/lib/logging/createNoopLogger.js.map +1 -1
  48. package/lib/modules/isModule.js.map +1 -1
  49. package/lib/modules/parseModuleId.js +7 -5
  50. package/lib/modules/parseModuleId.js.map +1 -1
  51. package/lib/objects/parseObjectPath.js.map +1 -1
  52. package/lib/objects/set.js.map +1 -1
  53. package/lib/server/polyfillBrowser.js +12 -0
  54. package/lib/server/polyfillBrowser.js.map +1 -0
  55. package/lib/server/polyfillCrypto.js +10 -0
  56. package/lib/server/polyfillCrypto.js.map +1 -0
  57. package/lib/server/polyfillFetch.js +31 -0
  58. package/lib/server/polyfillFetch.js.map +1 -0
  59. package/lib/server/polyfillJsDom.js +49 -0
  60. package/lib/server/polyfillJsDom.js.map +1 -0
  61. package/lib/server.js +4 -1
  62. package/lib/server.js.map +1 -1
  63. package/lib/{formats → strings}/formatBytes.js +1 -1
  64. package/lib/{formats → strings}/formatBytes.js.map +1 -1
  65. package/lib/strings/renderTemplate.js +4 -2
  66. package/lib/strings/renderTemplate.js.map +1 -1
  67. package/lib/validations/isUUID.js +6 -0
  68. package/lib/validations/isUUID.js.map +1 -0
  69. package/package.json +14 -2
  70. package/src/arrays/MaybeArray.ts +1 -1
  71. package/src/asyncs/createLazyPromise.test.ts +39 -0
  72. package/src/asyncs/createLazyPromise.ts +63 -0
  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/hashing.test.ts +12 -8
  79. package/src/crypto/hashing.ts +4 -4
  80. package/src/crypto/randomUUID.ts +6 -4
  81. package/src/i18n/createTranslate.test.ts +155 -0
  82. package/src/i18n/createTranslate.ts +52 -0
  83. package/src/index.ts +22 -9
  84. package/src/io/AbstractEncoding.ts +21 -0
  85. package/src/io/ArrayBuffer.test-d.ts +4 -0
  86. package/src/io/ArrayBuffers.base64.test.ts +61 -0
  87. package/src/io/ArrayBuffers.test.ts +23 -0
  88. package/src/io/ArrayBuffers.ts +272 -0
  89. package/src/io/Buffer.ts +16 -0
  90. package/src/io/isBuffer.test.ts +9 -0
  91. package/src/io/isBuffer.ts +3 -8
  92. package/src/io/isTransferable.test.ts +10 -0
  93. package/src/io/isTransferable.ts +50 -0
  94. package/src/isomorphics/structuredClone.test.ts +14 -0
  95. package/src/isomorphics/structuredClone.ts +88 -0
  96. package/src/langs/classOf.ts +3 -0
  97. package/src/{validations/dequal.test.ts → langs/deepEqual.test.ts} +2 -2
  98. package/src/{validations/dequal.ts → langs/deepEqual.ts} +6 -5
  99. package/src/langs/langs.test.ts +23 -0
  100. package/src/{validations/shallow.ts → langs/shallowEqual.ts} +2 -2
  101. package/src/logging/Logger.ts +6 -0
  102. package/src/logging/createNoopLogger.ts +1 -1
  103. package/src/logging/logger.test.ts +3 -3
  104. package/src/modules/isModule.ts +3 -0
  105. package/src/modules/parseModuleId.test.ts +7 -2
  106. package/src/modules/parseModuleId.ts +15 -9
  107. package/src/objects/get.test-d.ts +51 -0
  108. package/src/objects/get.test.ts +2 -55
  109. package/src/objects/parseObjectPath.ts +4 -3
  110. package/src/objects/set.test.ts +32 -31
  111. package/src/objects/set.ts +2 -2
  112. package/src/server/polyfillBrowser.test.ts +15 -0
  113. package/src/server/polyfillBrowser.ts +17 -0
  114. package/src/server/polyfillCrypto.ts +7 -0
  115. package/src/server/polyfillFetch.ts +28 -0
  116. package/src/server/polyfillJsDom.ts +85 -0
  117. package/src/server.ts +4 -1
  118. package/src/{formats → strings}/formatBytes.ts +1 -1
  119. package/src/strings/renderTemplate.test.ts +1 -0
  120. package/src/strings/renderTemplate.ts +12 -6
  121. package/src/typedoc.ts +2 -0
  122. package/src/validations/isUUID.ts +3 -0
  123. package/tsconfig.json +2 -1
  124. package/lib/asyncs/LazyPromise.js +0 -27
  125. package/lib/asyncs/LazyPromise.js.map +0 -1
  126. package/lib/crypto/hex.js.map +0 -1
  127. package/lib/server/polyfill.js +0 -8
  128. package/lib/server/polyfill.js.map +0 -1
  129. package/lib/shim/urljoin.js +0 -51
  130. package/lib/shim/urljoin.js.map +0 -1
  131. package/lib/validations/dequal.js.map +0 -1
  132. package/lib/validations/shallow.js.map +0 -1
  133. package/src/asyncs/LazyPromise.ts +0 -29
  134. package/src/server/polyfill.ts +0 -5
  135. package/src/shim/urljoin.test.ts +0 -6
  136. package/src/shim/urljoin.ts +0 -75
  137. package/src/types.d.ts +0 -7
@@ -0,0 +1 @@
1
+ {"version":3,"file":"polyfillBrowser.js","sources":["../../src/server/polyfillBrowser.ts"],"sourcesContent":["import { polyfillCrypto } from './polyfillCrypto';\nimport { polyfillFetch } from './polyfillFetch';\nimport { polyfillJsDom } from './polyfillJsDom';\n\n/**\n * Polyfills the browser environment with the necessary APIs for the server.\n * Currently, this includes:\n * - `window`\n * - `document`\n * - `fetch`\n * - `crypto`\n */\nexport async function polyfillBrowser() {\n await polyfillCrypto();\n await polyfillFetch();\n await polyfillJsDom();\n}\n"],"names":[],"mappings":";;;;AAYA,eAAsB,eAAkB,GAAA;AACtC,EAAA,MAAM,cAAe,EAAA,CAAA;AACrB,EAAA,MAAM,aAAc,EAAA,CAAA;AACpB,EAAA,MAAM,aAAc,EAAA,CAAA;AACtB;;;;"}
@@ -0,0 +1,10 @@
1
+ async function polyfillCrypto() {
2
+ if ("crypto" in globalThis) {
3
+ return false;
4
+ }
5
+ globalThis.crypto = (await import('node:crypto')).webcrypto;
6
+ return true;
7
+ }
8
+
9
+ export { polyfillCrypto };
10
+ //# sourceMappingURL=polyfillCrypto.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"polyfillCrypto.js","sources":["../../src/server/polyfillCrypto.ts"],"sourcesContent":["export async function polyfillCrypto() {\n if ('crypto' in globalThis) {\n return false;\n }\n globalThis.crypto = (await import('node:crypto')).webcrypto as Crypto;\n return true;\n}\n"],"names":[],"mappings":"AAAA,eAAsB,cAAiB,GAAA;AACrC,EAAA,IAAI,YAAY,UAAY,EAAA;AAC1B,IAAO,OAAA,KAAA,CAAA;AAAA,GACT;AACA,EAAW,UAAA,CAAA,MAAA,GAAA,CAAU,MAAM,OAAO,aAAgB,CAAA,EAAA,SAAA,CAAA;AAClD,EAAO,OAAA,IAAA,CAAA;AACT;;;;"}
@@ -0,0 +1,31 @@
1
+ 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
+ } = await import('node-fetch');
16
+ Object.assign(globalThis, {
17
+ fetch,
18
+ Response,
19
+ Headers,
20
+ Request,
21
+ AbortError,
22
+ FetchError,
23
+ FormData,
24
+ Blob,
25
+ File
26
+ });
27
+ return true;
28
+ }
29
+
30
+ export { polyfillFetch };
31
+ //# sourceMappingURL=polyfillFetch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"polyfillFetch.js","sources":["../../src/server/polyfillFetch.ts"],"sourcesContent":["export async function polyfillFetch() {\n if ('fetch' in globalThis) {\n return false;\n }\n const {\n default: fetch,\n Response,\n Headers,\n Request,\n AbortError,\n FetchError,\n FormData,\n Blob,\n File,\n } = await import('node-fetch');\n Object.assign(globalThis, {\n fetch,\n Response,\n Headers,\n Request,\n AbortError,\n FetchError,\n FormData,\n Blob,\n File,\n });\n return true;\n}\n"],"names":[],"mappings":"AAAA,eAAsB,aAAgB,GAAA;AACpC,EAAA,IAAI,WAAW,UAAY,EAAA;AACzB,IAAO,OAAA,KAAA,CAAA;AAAA,GACT;AACA,EAAM,MAAA;AAAA,IACJ,OAAS,EAAA,KAAA;AAAA,IACT,QAAA;AAAA,IACA,OAAA;AAAA,IACA,OAAA;AAAA,IACA,UAAA;AAAA,IACA,UAAA;AAAA,IACA,QAAA;AAAA,IACA,IAAA;AAAA,IACA,IAAA;AAAA,GACF,GAAI,MAAM,OAAO,YAAA,CAAA,CAAA;AACjB,EAAA,MAAA,CAAO,OAAO,UAAY,EAAA;AAAA,IACxB,KAAA;AAAA,IACA,QAAA;AAAA,IACA,OAAA;AAAA,IACA,OAAA;AAAA,IACA,UAAA;AAAA,IACA,UAAA;AAAA,IACA,QAAA;AAAA,IACA,IAAA;AAAA,IACA,IAAA;AAAA,GACD,CAAA,CAAA;AACD,EAAO,OAAA,IAAA,CAAA;AACT;;;;"}
@@ -0,0 +1,49 @@
1
+ async function polyfillJsDom() {
2
+ if (typeof window !== "undefined") {
3
+ return false;
4
+ }
5
+ const { ResourceLoader, JSDOM } = await import('jsdom');
6
+ class Window {
7
+ constructor(opts = {}) {
8
+ const { proxy, strictSSL, userAgent, ...jsdomOpts } = opts;
9
+ const resources = new ResourceLoader({
10
+ proxy,
11
+ strictSSL,
12
+ userAgent
13
+ });
14
+ return new JSDOM(
15
+ "",
16
+ Object.assign(jsdomOpts, {
17
+ resources
18
+ })
19
+ ).window;
20
+ }
21
+ }
22
+ const defaultJsdomConfig = {};
23
+ const protectedProperties = (() => Object.getOwnPropertyNames(new Window(defaultJsdomConfig)).filter(
24
+ (prop) => typeof globalThis[prop] !== "undefined"
25
+ ))();
26
+ function installEnv(...args) {
27
+ const properties = args.filter((arg) => Array.isArray(arg))[0];
28
+ const userJsdomConfig = args.filter((arg) => !Array.isArray(arg))[0];
29
+ const window2 = new Window(Object.assign({}, userJsdomConfig, defaultJsdomConfig));
30
+ Object.getOwnPropertyNames(window2).filter((prop) => !protectedProperties.includes(prop)).filter((prop) => !(properties && properties.indexOf(prop) === -1)).filter((prop) => {
31
+ switch (prop) {
32
+ case "undefined":
33
+ return false;
34
+ }
35
+ return true;
36
+ }).forEach((prop) => {
37
+ Object.defineProperty(globalThis, prop, {
38
+ configurable: true,
39
+ get: () => window2[prop]
40
+ });
41
+ });
42
+ return window2;
43
+ }
44
+ installEnv({ url: "http://localhost" });
45
+ return true;
46
+ }
47
+
48
+ export { polyfillJsDom };
49
+ //# sourceMappingURL=polyfillJsDom.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"polyfillJsDom.js","sources":["../../src/server/polyfillJsDom.ts"],"sourcesContent":["import type { ConstructorOptions, ResourceLoaderConstructorOptions } from 'jsdom';\n\nexport async function polyfillJsDom() {\n if (typeof window !== 'undefined') {\n return false;\n }\n\n const { ResourceLoader, JSDOM } = await import('jsdom');\n\n // https://github.com/lukechilds/window/blob/master/src/index.js\n // eslint-disable-next-line @typescript-eslint/no-extraneous-class\n class Window {\n constructor(opts: ResourceLoaderConstructorOptions & ConstructorOptions = {}) {\n const { proxy, strictSSL, userAgent, ...jsdomOpts } = opts;\n const resources = new ResourceLoader({\n proxy,\n strictSSL,\n userAgent,\n });\n return new JSDOM(\n '',\n Object.assign(jsdomOpts, {\n resources,\n }),\n ).window;\n }\n }\n\n // https://github.com/lukechilds/browser-env/blob/master/src/index.js\n // Default jsdom config.\n // These settings must override any custom settings to make sure we can iterate\n // over the window object.\n const defaultJsdomConfig = {\n // features: {\n // FetchExternalResources: false,\n // ProcessExternalResources: false,\n // },\n };\n // IIFE executed on import to return an array of global Node.js properties that\n // conflict with global browser properties.\n const protectedProperties = (() =>\n Object.getOwnPropertyNames(new Window(defaultJsdomConfig)).filter(\n (prop) => typeof globalThis[prop as keyof typeof globalThis] !== 'undefined',\n ))();\n\n function installEnv(...args: any[]) {\n // Sets up global browser environment\n // Extract options from args\n const properties = args.filter((arg: any) => Array.isArray(arg))[0];\n const userJsdomConfig = args.filter((arg: any) => !Array.isArray(arg))[0];\n\n // Create window object\n const window = new Window(Object.assign({}, userJsdomConfig, defaultJsdomConfig));\n\n // Get all global browser properties\n Object.getOwnPropertyNames(window)\n\n // Remove protected properties\n .filter((prop) => !protectedProperties.includes(prop))\n\n // If we're only applying specific required properties remove everything else\n .filter((prop) => !(properties && properties.indexOf(prop) === -1))\n .filter((prop) => {\n switch (prop) {\n case 'undefined':\n return false;\n }\n return true;\n })\n\n // Copy what's left to the Node.js global scope\n .forEach((prop) => {\n // console.debug(`define globalThis.${prop}`);\n Object.defineProperty(globalThis, prop, {\n configurable: true,\n get: () => window[prop as keyof Window] as any,\n });\n });\n\n return window;\n }\n\n installEnv({ url: 'http://localhost' });\n return true;\n}\n"],"names":["window"],"mappings":"AAEA,eAAsB,aAAgB,GAAA;AACpC,EAAI,IAAA,OAAO,WAAW,WAAa,EAAA;AACjC,IAAO,OAAA,KAAA,CAAA;AAAA,GACT;AAEA,EAAA,MAAM,EAAE,cAAA,EAAgB,KAAM,EAAA,GAAI,MAAM,OAAO,OAAA,CAAA,CAAA;AAI/C,EAAA,MAAM,MAAO,CAAA;AAAA,IACX,WAAA,CAAY,IAA8D,GAAA,EAAI,EAAA;AAC5E,MAAA,MAAM,EAAE,KAAA,EAAO,SAAW,EAAA,SAAA,EAAA,GAAc,WAAc,GAAA,IAAA,CAAA;AACtD,MAAM,MAAA,SAAA,GAAY,IAAI,cAAe,CAAA;AAAA,QACnC,KAAA;AAAA,QACA,SAAA;AAAA,QACA,SAAA;AAAA,OACD,CAAA,CAAA;AACD,MAAA,OAAO,IAAI,KAAA;AAAA,QACT,EAAA;AAAA,QACA,MAAA,CAAO,OAAO,SAAW,EAAA;AAAA,UACvB,SAAA;AAAA,SACD,CAAA;AAAA,OACD,CAAA,MAAA,CAAA;AAAA,KACJ;AAAA,GACF;AAMA,EAAA,MAAM,qBAAqB,EAK3B,CAAA;AAGA,EAAM,MAAA,mBAAA,GAAA,CAAuB,MAC3B,MAAO,CAAA,mBAAA,CAAoB,IAAI,MAAO,CAAA,kBAAkB,CAAC,CAAE,CAAA,MAAA;AAAA,IACzD,CAAC,IAAA,KAAS,OAAO,UAAA,CAAW,IAAqC,CAAA,KAAA,WAAA;AAAA,GAChE,GAAA,CAAA;AAEL,EAAA,SAAS,cAAc,IAAa,EAAA;AAGlC,IAAM,MAAA,UAAA,GAAa,KAAK,MAAO,CAAA,CAAC,QAAa,KAAM,CAAA,OAAA,CAAQ,GAAG,CAAC,CAAE,CAAA,CAAA,CAAA,CAAA;AACjE,IAAM,MAAA,eAAA,GAAkB,IAAK,CAAA,MAAA,CAAO,CAAC,GAAA,KAAa,CAAC,KAAM,CAAA,OAAA,CAAQ,GAAG,CAAC,CAAE,CAAA,CAAA,CAAA,CAAA;AAGvE,IAAMA,MAAAA,OAAAA,GAAS,IAAI,MAAO,CAAA,MAAA,CAAO,OAAO,EAAC,EAAG,eAAiB,EAAA,kBAAkB,CAAC,CAAA,CAAA;AAGhF,IAAO,MAAA,CAAA,mBAAA,CAAoBA,OAAM,CAAA,CAG9B,MAAO,CAAA,CAAC,SAAS,CAAC,mBAAA,CAAoB,QAAS,CAAA,IAAI,CAAC,CAAA,CAGpD,OAAO,CAAC,IAAA,KAAS,EAAE,UAAA,IAAc,UAAW,CAAA,OAAA,CAAQ,IAAI,CAAA,KAAM,CAAG,CAAA,CAAA,CAAA,CACjE,MAAO,CAAA,CAAC,IAAS,KAAA;AAChB,MAAA,QAAQ,IAAM;AAAA,QACZ,KAAK,WAAA;AACH,UAAO,OAAA,KAAA,CAAA;AAAA,OACX;AACA,MAAO,OAAA,IAAA,CAAA;AAAA,KACR,CAAA,CAGA,OAAQ,CAAA,CAAC,IAAS,KAAA;AAEjB,MAAO,MAAA,CAAA,cAAA,CAAe,YAAY,IAAM,EAAA;AAAA,QACtC,YAAc,EAAA,IAAA;AAAA,QACd,GAAA,EAAK,MAAMA,OAAO,CAAA,IAAA,CAAA;AAAA,OACnB,CAAA,CAAA;AAAA,KACF,CAAA,CAAA;AAEH,IAAOA,OAAAA,OAAAA,CAAAA;AAAA,GACT;AAEA,EAAW,UAAA,CAAA,EAAE,GAAK,EAAA,kBAAA,EAAoB,CAAA,CAAA;AACtC,EAAO,OAAA,IAAA,CAAA;AACT;;;;"}
package/lib/server.js CHANGED
@@ -1,2 +1,5 @@
1
- export { polyfill } from './server/polyfill.js';
1
+ export { polyfillCrypto } from './server/polyfillCrypto.js';
2
+ export { polyfillFetch } from './server/polyfillFetch.js';
3
+ export { polyfillJsDom } from './server/polyfillJsDom.js';
4
+ export { polyfillBrowser } from './server/polyfillBrowser.js';
2
5
  //# sourceMappingURL=server.js.map
package/lib/server.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
1
+ {"version":3,"file":"server.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;"}
@@ -1,7 +1,7 @@
1
1
  function formatBytes(bytes, si = false, dp = 1) {
2
2
  const thresh = si ? 1e3 : 1024;
3
3
  if (Math.abs(bytes) < thresh) {
4
- return bytes + " B";
4
+ return `${bytes} B`;
5
5
  }
6
6
  const units = si ? ["kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"] : ["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"];
7
7
  let u = -1;
@@ -1 +1 @@
1
- {"version":3,"file":"formatBytes.js","sources":["../../src/formats/formatBytes.ts"],"sourcesContent":["/**\n * Format bytes as human-readable text.\n *\n * @param bytes Number of bytes.\n * @param si True to use metric (SI) units, aka powers of 1000. False to use\n * binary (IEC), aka powers of 1024.\n * @param dp Number of decimal places to display.\n *\n * @return Formatted string.\n */\nexport function formatBytes(bytes: number, si = false, dp = 1) {\n const thresh = si ? 1000 : 1024;\n\n if (Math.abs(bytes) < thresh) {\n return bytes + ' B';\n }\n\n const units = si\n ? ['kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']\n : ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];\n let u = -1;\n const r = 10 ** dp;\n\n do {\n bytes /= thresh;\n ++u;\n } while (Math.round(Math.abs(bytes) * r) / r >= thresh && u < units.length - 1);\n\n return bytes.toFixed(dp) + ' ' + units[u];\n}\n"],"names":[],"mappings":"AAUO,SAAS,WAAY,CAAA,KAAA,EAAe,EAAK,GAAA,KAAA,EAAO,KAAK,CAAG,EAAA;AAC7D,EAAM,MAAA,MAAA,GAAS,KAAK,GAAO,GAAA,IAAA,CAAA;AAE3B,EAAA,IAAI,IAAK,CAAA,GAAA,CAAI,KAAK,CAAA,GAAI,MAAQ,EAAA;AAC5B,IAAA,OAAO,KAAQ,GAAA,IAAA,CAAA;AAAA,GACjB;AAEA,EAAM,MAAA,KAAA,GAAQ,KACV,CAAC,IAAA,EAAM,MAAM,IAAM,EAAA,IAAA,EAAM,MAAM,IAAM,EAAA,IAAA,EAAM,IAAI,CAC/C,GAAA,CAAC,OAAO,KAAO,EAAA,KAAA,EAAO,OAAO,KAAO,EAAA,KAAA,EAAO,OAAO,KAAK,CAAA,CAAA;AAC3D,EAAA,IAAI,CAAI,GAAA,CAAA,CAAA,CAAA;AACR,EAAA,MAAM,IAAI,EAAM,IAAA,EAAA,CAAA;AAEhB,EAAG,GAAA;AACD,IAAS,KAAA,IAAA,MAAA,CAAA;AACT,IAAE,EAAA,CAAA,CAAA;AAAA,GACK,QAAA,IAAA,CAAK,KAAM,CAAA,IAAA,CAAK,GAAI,CAAA,KAAK,CAAI,GAAA,CAAC,CAAI,GAAA,CAAA,IAAK,MAAU,IAAA,CAAA,GAAI,MAAM,MAAS,GAAA,CAAA,EAAA;AAE7E,EAAA,OAAO,KAAM,CAAA,OAAA,CAAQ,EAAE,CAAA,GAAI,MAAM,KAAM,CAAA,CAAA,CAAA,CAAA;AACzC;;;;"}
1
+ {"version":3,"file":"formatBytes.js","sources":["../../src/strings/formatBytes.ts"],"sourcesContent":["/**\n * Format bytes as human-readable text.\n *\n * @param bytes Number of bytes.\n * @param si True to use metric (SI) units, aka powers of 1000. False to use\n * binary (IEC), aka powers of 1024.\n * @param dp Number of decimal places to display.\n *\n * @return Formatted string.\n */\nexport function formatBytes(bytes: number, si = false, dp = 1) {\n const thresh = si ? 1000 : 1024;\n\n if (Math.abs(bytes) < thresh) {\n return `${bytes} B`;\n }\n\n const units = si\n ? ['kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']\n : ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];\n let u = -1;\n const r = 10 ** dp;\n\n do {\n bytes /= thresh;\n ++u;\n } while (Math.round(Math.abs(bytes) * r) / r >= thresh && u < units.length - 1);\n\n return bytes.toFixed(dp) + ' ' + units[u];\n}\n"],"names":[],"mappings":"AAUO,SAAS,WAAY,CAAA,KAAA,EAAe,EAAK,GAAA,KAAA,EAAO,KAAK,CAAG,EAAA;AAC7D,EAAM,MAAA,MAAA,GAAS,KAAK,GAAO,GAAA,IAAA,CAAA;AAE3B,EAAA,IAAI,IAAK,CAAA,GAAA,CAAI,KAAK,CAAA,GAAI,MAAQ,EAAA;AAC5B,IAAA,OAAO,CAAG,EAAA,KAAA,CAAA,EAAA,CAAA,CAAA;AAAA,GACZ;AAEA,EAAM,MAAA,KAAA,GAAQ,KACV,CAAC,IAAA,EAAM,MAAM,IAAM,EAAA,IAAA,EAAM,MAAM,IAAM,EAAA,IAAA,EAAM,IAAI,CAC/C,GAAA,CAAC,OAAO,KAAO,EAAA,KAAA,EAAO,OAAO,KAAO,EAAA,KAAA,EAAO,OAAO,KAAK,CAAA,CAAA;AAC3D,EAAA,IAAI,CAAI,GAAA,CAAA,CAAA,CAAA;AACR,EAAA,MAAM,IAAI,EAAM,IAAA,EAAA,CAAA;AAEhB,EAAG,GAAA;AACD,IAAS,KAAA,IAAA,MAAA,CAAA;AACT,IAAE,EAAA,CAAA,CAAA;AAAA,GACK,QAAA,IAAA,CAAK,KAAM,CAAA,IAAA,CAAK,GAAI,CAAA,KAAK,CAAI,GAAA,CAAC,CAAI,GAAA,CAAA,IAAK,MAAU,IAAA,CAAA,GAAI,MAAM,MAAS,GAAA,CAAA,EAAA;AAE7E,EAAA,OAAO,KAAM,CAAA,OAAA,CAAQ,EAAE,CAAA,GAAI,MAAM,KAAM,CAAA,CAAA,CAAA,CAAA;AACzC;;;;"}
@@ -2,13 +2,15 @@ import { get } from '../objects/get.js';
2
2
 
3
3
  function renderTemplate(template, data, match = "js") {
4
4
  let getter;
5
- if (typeof data === "function") {
5
+ if (!data) {
6
+ getter = () => "";
7
+ } else if (typeof data === "function") {
6
8
  getter = data;
7
9
  } else {
8
10
  getter = (v) => get(data, v);
9
11
  }
10
12
  if (typeof match === "string") {
11
- match = Matches[match] || Matches["js"];
13
+ match = Matches[match] || Matches.js;
12
14
  }
13
15
  return template.replace(match, (_, g) => {
14
16
  return getter(g.trim());
@@ -1 +1 @@
1
- {"version":3,"file":"renderTemplate.js","sources":["../../src/strings/renderTemplate.ts"],"sourcesContent":["import { get } from '../objects/get';\n\n/**\n * 替换类似于 JS 的模板字符串\n *\n * templateString('My name is ${name}',{name:'wener'}) // => 'My name is wener'\n *\n */\nexport function renderTemplate(\n template: string,\n data: ((v: string) => any) | object,\n match: 'js' | 'common' | RegExp = 'js',\n) {\n let getter: Function;\n if (typeof data === 'function') {\n getter = data;\n } else {\n getter = (v: string) => get(data, v);\n }\n if (typeof match === 'string') {\n match = Matches[match] || Matches['js'];\n }\n return template.replace(match, (_, g) => {\n return getter(g.trim());\n });\n}\n\nconst Matches = {\n js: /\\${(.*?)}/g,\n common: /{{(.*?)}}/g,\n};\n"],"names":[],"mappings":";;AAQO,SAAS,cACd,CAAA,QAAA,EACA,IACA,EAAA,KAAA,GAAkC,IAClC,EAAA;AACA,EAAI,IAAA,MAAA,CAAA;AACJ,EAAI,IAAA,OAAO,SAAS,UAAY,EAAA;AAC9B,IAAS,MAAA,GAAA,IAAA,CAAA;AAAA,GACJ,MAAA;AACL,IAAA,MAAA,GAAS,CAAC,CAAA,KAAc,GAAI,CAAA,IAAA,EAAM,CAAC,CAAA,CAAA;AAAA,GACrC;AACA,EAAI,IAAA,OAAO,UAAU,QAAU,EAAA;AAC7B,IAAQ,KAAA,GAAA,OAAA,CAAQ,UAAU,OAAQ,CAAA,IAAA,CAAA,CAAA;AAAA,GACpC;AACA,EAAA,OAAO,QAAS,CAAA,OAAA,CAAQ,KAAO,EAAA,CAAC,GAAG,CAAM,KAAA;AACvC,IAAO,OAAA,MAAA,CAAO,CAAE,CAAA,IAAA,EAAM,CAAA,CAAA;AAAA,GACvB,CAAA,CAAA;AACH,CAAA;AAEA,MAAM,OAAU,GAAA;AAAA,EACd,EAAI,EAAA,YAAA;AAAA,EACJ,MAAQ,EAAA,YAAA;AACV,CAAA;;;;"}
1
+ {"version":3,"file":"renderTemplate.js","sources":["../../src/strings/renderTemplate.ts"],"sourcesContent":["import { get } from '../objects/get';\n\n/**\n * render template like js template string\n *\n * @example\n * renderTemplate('My name is ${name}',{name:'wener'})\n * // 'My name is wener'\n *\n * @param match `js` for `${name}`, common for `{{name}}`\n */\nexport function renderTemplate(\n template: string,\n data: ((v: string) => any) | object | undefined,\n match: 'js' | 'common' | RegExp = 'js',\n) {\n let getter: Function;\n if (!data) {\n // todo warning in dev\n getter = () => '';\n } else if (typeof data === 'function') {\n getter = data;\n } else {\n getter = (v: string) => get(data, v);\n }\n if (typeof match === 'string') {\n match = Matches[match] || Matches.js;\n }\n return template.replace(match, (_, g) => {\n return getter(g.trim());\n });\n}\n\nconst Matches: Record<string, RegExp> = {\n js: /\\${(.*?)}/g,\n common: /{{(.*?)}}/g,\n};\n"],"names":[],"mappings":";;AAWO,SAAS,cACd,CAAA,QAAA,EACA,IACA,EAAA,KAAA,GAAkC,IAClC,EAAA;AACA,EAAI,IAAA,MAAA,CAAA;AACJ,EAAA,IAAI,CAAC,IAAM,EAAA;AAET,IAAA,MAAA,GAAS,MAAM,EAAA,CAAA;AAAA,GACjB,MAAA,IAAW,OAAO,IAAA,KAAS,UAAY,EAAA;AACrC,IAAS,MAAA,GAAA,IAAA,CAAA;AAAA,GACJ,MAAA;AACL,IAAA,MAAA,GAAS,CAAC,CAAA,KAAc,GAAI,CAAA,IAAA,EAAM,CAAC,CAAA,CAAA;AAAA,GACrC;AACA,EAAI,IAAA,OAAO,UAAU,QAAU,EAAA;AAC7B,IAAQ,KAAA,GAAA,OAAA,CAAQ,UAAU,OAAQ,CAAA,EAAA,CAAA;AAAA,GACpC;AACA,EAAA,OAAO,QAAS,CAAA,OAAA,CAAQ,KAAO,EAAA,CAAC,GAAG,CAAM,KAAA;AACvC,IAAO,OAAA,MAAA,CAAO,CAAE,CAAA,IAAA,EAAM,CAAA,CAAA;AAAA,GACvB,CAAA,CAAA;AACH,CAAA;AAEA,MAAM,OAAkC,GAAA;AAAA,EACtC,EAAI,EAAA,YAAA;AAAA,EACJ,MAAQ,EAAA,YAAA;AACV,CAAA;;;;"}
@@ -0,0 +1,6 @@
1
+ function isUUID(str) {
2
+ return /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(str);
3
+ }
4
+
5
+ export { isUUID };
6
+ //# sourceMappingURL=isUUID.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"isUUID.js","sources":["../../src/validations/isUUID.ts"],"sourcesContent":["export function isUUID(str: string) {\n return /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(str);\n}\n"],"names":[],"mappings":"AAAO,SAAS,OAAO,GAAa,EAAA;AAClC,EAAO,OAAA,wEAAA,CAAyE,KAAK,GAAG,CAAA,CAAA;AAC1F;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wener/utils",
3
- "version": "1.1.5",
3
+ "version": "1.1.7",
4
4
  "type": "module",
5
5
  "description": "Utils for daily use",
6
6
  "repository": {
@@ -19,6 +19,7 @@
19
19
  "exports": {
20
20
  ".": {
21
21
  "types": "./src/index.ts",
22
+ "typescript": "./src/index.ts",
22
23
  "import": "./lib/index.js",
23
24
  "system": {
24
25
  "default": "./dist/system/index.js"
@@ -26,10 +27,11 @@
26
27
  "require": "./dist/cjs/index.js"
27
28
  },
28
29
  "./types": {
29
- "types": "./src/types.d.ts"
30
+ "types": "./types.d.ts"
30
31
  },
31
32
  "./server": {
32
33
  "types": "./src/server.ts",
34
+ "typescript": "./src/server.ts",
33
35
  "import": "./lib/server.js",
34
36
  "system": {
35
37
  "default": "./dist/system/server.js"
@@ -74,6 +76,8 @@
74
76
  "ts": "module"
75
77
  },
76
78
  "nodeArguments": [
79
+ "--conditions=typescript",
80
+ "--require=@wener/wode/suppress-experimental.cjs",
77
81
  "--loader=tsx"
78
82
  ]
79
83
  },
@@ -81,8 +85,16 @@
81
85
  "input": [
82
86
  "./src/index.ts",
83
87
  "./src/server.ts"
88
+ ],
89
+ "external": [
90
+ "jsdom",
91
+ "node-fetch"
84
92
  ]
85
93
  },
94
+ "typedoc": {
95
+ "entryPoint": "./src/typedoc.ts",
96
+ "readmeFile": "./README.md"
97
+ },
86
98
  "scripts": {
87
99
  "build": "make prepublish",
88
100
  "clean": "make clean",
@@ -31,7 +31,7 @@ export function lastOfMaybeArray<T>(v: MaybeArray<T>): T {
31
31
  return v;
32
32
  }
33
33
 
34
- export function arrayOfMaybeArray<T>(v: MaybeArray<T>): T[] {
34
+ export function arrayOfMaybeArray<T>(v: MaybeArray<T> | null | undefined): T[] {
35
35
  if (Array.isArray(v)) {
36
36
  return v;
37
37
  }
@@ -0,0 +1,39 @@
1
+ import test from 'ava';
2
+ import { createLazyPromise } from './createLazyPromise';
3
+ import { sleep } from './sleep';
4
+
5
+ test('basic', async (t) => {
6
+ const promise = createLazyPromise();
7
+ let r = 0;
8
+ void promise.then((v) => (r = v));
9
+ t.is(r, 0);
10
+ const { resolve, reject } = promise;
11
+ t.truthy(resolve);
12
+ t.truthy(reject);
13
+ resolve(1);
14
+ t.is(r, 0);
15
+ await promise;
16
+ t.is(r, 1);
17
+ });
18
+
19
+ test('manual resolve skip exec', async (t) => {
20
+ const promise = createLazyPromise(() => {
21
+ t.fail();
22
+ });
23
+ promise.resolve(-1);
24
+ t.is(await promise, -1);
25
+ });
26
+
27
+ test('exec', async (t) => {
28
+ let r = 0;
29
+ const promise = createLazyPromise((resolve) => {
30
+ r++;
31
+ resolve(10);
32
+ });
33
+ await sleep(10);
34
+ t.is(r, 0);
35
+ t.is(await promise, 10);
36
+ t.is(r, 1);
37
+ promise.resolve(20);
38
+ t.is(await promise, 10);
39
+ });
@@ -0,0 +1,63 @@
1
+ export type LazyPromise<T> = Promise<T> & {
2
+ reject(reason?: any): void;
3
+ resolve(v?: T | PromiseLike<T>): void;
4
+ };
5
+
6
+ /**
7
+ * createLazyPromise return a promise that can be resolved or rejected manually.
8
+ * if you pass a function to it, it will be executed when the promise try to resolve.
9
+ */
10
+ export function createLazyPromise<T = any>(
11
+ executor?: (resolve: LazyPromise<T>['resolve'], reject: LazyPromise<T>['reject']) => void,
12
+ ): LazyPromise<T> {
13
+ const holder = {
14
+ resolve(_: any): void {
15
+ throw new Error('pending resolve');
16
+ },
17
+ reject(_: any): void {
18
+ throw new Error('pending reject');
19
+ },
20
+ };
21
+ const future = Object.assign(
22
+ new Promise<T>((resolve, reject) => {
23
+ holder.reject = reject;
24
+ holder.resolve = resolve;
25
+ }),
26
+ {
27
+ resolve(v: any) {
28
+ holder.resolve(v);
29
+ },
30
+ reject(v: any) {
31
+ holder.resolve(v);
32
+ },
33
+ },
34
+ );
35
+ if (executor) {
36
+ const r = holder.resolve;
37
+ let shouldExec = true;
38
+ holder.resolve = (v: any) => {
39
+ shouldExec = false;
40
+ r(v);
41
+ };
42
+ const then = future.then.bind(future);
43
+ future.then = (...args) => {
44
+ if (shouldExec) {
45
+ shouldExec = false;
46
+ executor(holder.resolve, holder.reject);
47
+ }
48
+ return then(...args);
49
+ };
50
+ const like = holder as LazyPromise<T>;
51
+ like.then = future.then;
52
+ like.catch = future.catch.bind(future);
53
+ if (future.finally) like.finally = future.finally;
54
+
55
+ void Object.defineProperty(like, Symbol.species, {
56
+ get() {
57
+ return Promise;
58
+ },
59
+ });
60
+ return like;
61
+ }
62
+ return future;
63
+ }
@@ -3,6 +3,7 @@ export function* generatorOfStream<T = any>(stream: any): IterableIterator<Promi
3
3
  stream.on('end', () => {
4
4
  done = true;
5
5
  });
6
+ // eslint-disable-next-line no-unmodified-loop-condition
6
7
  while (!done) {
7
8
  yield new Promise((resolve, reject) => {
8
9
  stream.once('data', resolve);
@@ -3,7 +3,7 @@ export function timeout<T = any>(v: Promise<T>, ms: number): Promise<T> {
3
3
  let timeout: any;
4
4
  return Promise.race([
5
5
  v,
6
- new Promise((_, reject) => {
6
+ new Promise((_resolve, reject) => {
7
7
  timeout = setTimeout(() => reject(error), ms);
8
8
  }),
9
9
  ]).then(
@@ -1,6 +1,8 @@
1
- // https://gist.github.com/rproenca/64781c6a1329b48a455b645d361a9aa3
1
+ import { MaybePromise } from '../asyncs/MaybePromise';
2
+
2
3
  let _copy: (s: any) => void;
3
4
 
5
+ // https://gist.github.com/rproenca/64781c6a1329b48a455b645d361a9aa3
4
6
  function initCopy() {
5
7
  let textArea: HTMLTextAreaElement;
6
8
 
@@ -49,13 +51,12 @@ function initCopy() {
49
51
  * Write text to clipboard
50
52
  * @param content content
51
53
  */
52
- export function copy(content: string) {
54
+ export function copy(content: string): MaybePromise<void> {
53
55
  if (window.navigator?.clipboard?.writeText) {
54
- window.navigator.clipboard.writeText(content);
55
- return;
56
+ return window.navigator.clipboard.writeText(content);
56
57
  }
57
58
  if (!_copy) {
58
59
  initCopy();
59
60
  }
60
- _copy(content);
61
+ return _copy(content);
61
62
  }
@@ -26,21 +26,16 @@ export function loadScripts(
26
26
  options?: { attributes: Record<string, string> },
27
27
  ): Promise<HTMLScriptElement | HTMLScriptElement[]> {
28
28
  if (Array.isArray(src)) {
29
- return new Promise(async (resolve, reject) => {
29
+ return Promise.resolve().then(async () => {
30
30
  const all = [];
31
- try {
32
- for (let s of src) {
33
- all.push(await loadScripts(s));
34
- }
35
- } catch (e) {
36
- reject(e);
37
- return;
31
+ for (const s of src) {
32
+ all.push(await loadScripts(s));
38
33
  }
39
- resolve(all);
34
+ return all;
40
35
  });
41
36
  }
42
37
  // todo quote ?
43
- let $ele = document.querySelector(`script[src="${src}"]`) as HTMLScriptElement;
38
+ const $ele = document.querySelector(`script[src="${src}"]`) as HTMLScriptElement;
44
39
  if ($ele) {
45
40
  return Promise.resolve($ele);
46
41
  }
@@ -52,7 +47,7 @@ export function loadScripts(
52
47
  }
53
48
 
54
49
  export function loadStyles(href: string, options?: { attributes: Record<string, string> }): Promise<HTMLLinkElement> {
55
- let $ele = document.querySelector(`link[href="${href}"]`) as HTMLLinkElement;
50
+ const $ele = document.querySelector(`link[href="${href}"]`) as HTMLLinkElement;
56
51
  if ($ele) {
57
52
  return Promise.resolve($ele);
58
53
  }
@@ -1,3 +1,6 @@
1
+ /**
2
+ * hex string
3
+ */
1
4
  export function hex(s: Uint8Array | ArrayBuffer) {
2
5
  return Array.from(new Uint8Array(s))
3
6
  .map((v) => v.toString(16).padStart(2, '0'))
@@ -1,13 +1,12 @@
1
1
  import test from 'ava';
2
+ import { polyfillCrypto } from '../server/polyfillCrypto';
3
+ import { isUUID } from '../validations/isUUID';
2
4
  import { sha1, sha256, sha384, sha512 } from './hashing';
3
- import { hex } from './hex';
4
- import { randomUUID } from './randomUUID';
5
+ import { hex } from './base';
6
+ import { _randomUUID } from './randomUUID';
5
7
 
6
- test.before(async (t) => {
7
- if (!('crypto' in globalThis)) {
8
- (globalThis as any).crypto = (await import('node:crypto')).webcrypto;
9
- t.log(`load node:crypto`);
10
- }
8
+ test.before(async () => {
9
+ await polyfillCrypto();
11
10
  });
12
11
 
13
12
  test('sha', async (t) => {
@@ -22,5 +21,10 @@ test('sha', async (t) => {
22
21
  hex(await sha512('')),
23
22
  'cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e',
24
23
  );
25
- t.regex(randomUUID(), /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/);
24
+ });
25
+
26
+ test('randomUUID', (t) => {
27
+ for (let i = 0; i < 20; i++) {
28
+ t.true(isUUID(_randomUUID()));
29
+ }
26
30
  });
@@ -1,16 +1,16 @@
1
- export async function sha1(s: string | BufferSource) {
1
+ export function sha1(s: string | BufferSource) {
2
2
  return digestOf('SHA-1', s);
3
3
  }
4
4
 
5
- export async function sha256(s: string | BufferSource) {
5
+ export function sha256(s: string | BufferSource) {
6
6
  return digestOf('SHA-256', s);
7
7
  }
8
8
 
9
- export async function sha384(s: string | BufferSource) {
9
+ export function sha384(s: string | BufferSource) {
10
10
  return digestOf('SHA-384', s);
11
11
  }
12
12
 
13
- export async function sha512(s: string | BufferSource) {
13
+ export function sha512(s: string | BufferSource) {
14
14
  return digestOf('SHA-512', s);
15
15
  }
16
16
 
@@ -1,10 +1,12 @@
1
1
  /**
2
2
  * generate random UUIDv4
3
3
  */
4
- export function randomUUID() {
5
- if ('randomUUID' in crypto) {
6
- return crypto.randomUUID();
7
- }
4
+ export const randomUUID: () => string = globalThis.crypto?.randomUUID || _randomUUID;
5
+
6
+ /**
7
+ * @internal
8
+ */
9
+ export function _randomUUID() {
8
10
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
9
11
  const r = (Math.random() * 16) | 0;
10
12
  const v = c === 'x' ? r : (r & 0x3) | 0x8;