@wener/utils 1.1.8 → 1.1.10
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/dist/LICENSE.txt +135 -0
- package/dist/cjs/index-da9513d6.js +13 -0
- package/dist/cjs/index-da9513d6.js.map +1 -0
- package/dist/cjs/index.cjs +9 -1
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/server.cjs +1 -1
- package/dist/cjs/server.cjs.map +1 -1
- package/dist/esm/index-c696799a.js +13 -0
- package/dist/esm/index-c696799a.js.map +1 -0
- package/dist/esm/index.js +9 -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-2dfef0f3.js +13 -0
- package/dist/system/index-2dfef0f3.js.map +1 -0
- package/dist/system/index.js +9 -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/arrays/arrayFromAsync.js +9 -0
- package/lib/arrays/arrayFromAsync.js.map +1 -0
- package/lib/asyncs/createLazyPromise.js +3 -1
- package/lib/asyncs/createLazyPromise.js.map +1 -1
- package/lib/browsers/getFileFromDataTransfer.js.map +1 -1
- package/lib/crypto/getRandomValues.js +4 -4
- package/lib/crypto/getRandomValues.js.map +1 -1
- package/lib/crypto/pem/pem.js +37 -0
- package/lib/crypto/pem/pem.js.map +1 -0
- package/lib/crypto/randomUUID.js +1 -1
- package/lib/crypto/randomUUID.js.map +1 -1
- package/lib/crypto/ulid.js +3 -3
- package/lib/crypto/ulid.js.map +1 -1
- package/lib/i18n/createTranslate.js.map +1 -1
- package/lib/index.js +11 -5
- package/lib/index.js.map +1 -1
- package/lib/io/ArrayBuffers.js +25 -13
- package/lib/io/ArrayBuffers.js.map +1 -1
- package/lib/io/Buffer.js +3 -0
- package/lib/io/Buffer.js.map +1 -1
- package/lib/io/base64.js +53 -0
- package/lib/io/base64.js.map +1 -0
- package/lib/isomorphics/structuredClone.js +1 -1
- package/lib/isomorphics/structuredClone.js.map +1 -1
- package/lib/langs/MaybeFunction.js +9 -0
- package/lib/langs/MaybeFunction.js.map +1 -0
- package/lib/langs/deepEqual.js.map +1 -1
- package/lib/{validations → langs}/isClass.js +0 -0
- package/lib/langs/isClass.js.map +1 -0
- package/lib/{validations → langs}/isDefined.js +0 -0
- package/lib/langs/isDefined.js.map +1 -0
- package/lib/{validations → langs}/isEmptyObject.js +0 -0
- package/lib/langs/isEmptyObject.js.map +1 -0
- package/lib/{validations → langs}/isPlainObject.js +1 -1
- package/lib/langs/isPlainObject.js.map +1 -0
- package/lib/langs/memoize.js +24 -0
- package/lib/langs/memoize.js.map +1 -0
- package/lib/langs/parseBoolean.js +31 -0
- package/lib/langs/parseBoolean.js.map +1 -0
- package/lib/langs/shallowEqual.js.map +1 -1
- package/lib/logging/createChildLogger.js +2 -2
- package/lib/logging/createChildLogger.js.map +1 -1
- package/lib/logging/createLogger.js +26 -0
- package/lib/logging/createLogger.js.map +1 -0
- package/lib/modules/isModule.js.map +1 -1
- package/lib/objects/get.js.map +1 -1
- package/lib/objects/set.js +4 -1
- package/lib/objects/set.js.map +1 -1
- package/lib/server.js +5 -4
- package/lib/server.js.map +1 -1
- package/lib/servers/createProxyFetch.js +32 -0
- package/lib/servers/createProxyFetch.js.map +1 -0
- package/lib/{server → servers}/polyfillBrowser.js +0 -0
- package/lib/servers/polyfillBrowser.js.map +1 -0
- package/lib/{server → servers}/polyfillCrypto.js +0 -0
- package/lib/servers/polyfillCrypto.js.map +1 -0
- package/lib/servers/polyfillFetch.js +24 -0
- package/lib/servers/polyfillFetch.js.map +1 -0
- package/lib/{server → servers}/polyfillJsDom.js +6 -1
- package/lib/servers/polyfillJsDom.js.map +1 -0
- package/lib/strings/camelCase.js.map +1 -1
- package/lib/strings/formatBytes.js.map +1 -1
- package/lib/strings/renderTemplate.js.map +1 -1
- package/lib/validations/parseTimestamp.js +25 -0
- package/lib/validations/parseTimestamp.js.map +1 -0
- package/package.json +7 -9
- package/src/arrays/arrayFromAsync.ts +5 -0
- package/src/asyncs/createLazyPromise.ts +2 -1
- package/src/asyncs/isThenable.ts +4 -0
- package/src/crypto/getRandomValues.ts +12 -7
- package/src/crypto/hashing.test.ts +2 -2
- package/src/crypto/pem/pem.test.ts +63 -0
- package/src/crypto/pem/pem.test.ts.md +24 -0
- package/src/crypto/pem/pem.test.ts.snap +0 -0
- package/src/crypto/pem/pem.ts +74 -0
- package/src/crypto/randomUUID.ts +1 -1
- package/src/crypto/ulid.test.ts +11 -3
- package/src/crypto/ulid.ts +5 -4
- package/src/fetch/index.ts +1 -0
- package/src/index.ts +13 -6
- package/src/io/ArrayBuffers.base64.test.ts +3 -2
- package/src/io/ArrayBuffers.ts +30 -14
- package/src/io/base64.ts +64 -0
- package/src/langs/MaybeFunction.ts +9 -0
- package/src/langs/README.md +4 -0
- package/src/{validations → langs}/isClass.ts +0 -0
- package/src/{validations → langs}/isDefined.ts +0 -0
- package/src/{validations → langs}/isEmptyObject.ts +0 -0
- package/src/{validations → langs}/isFunction.ts +0 -0
- package/src/{validations → langs}/isPlainObject.ts +1 -1
- package/src/langs/memoize.ts +32 -0
- package/src/langs/parseBoolean.ts +30 -0
- package/src/logging/createChildLogger.ts +2 -2
- package/src/logging/{createWriteLogger.ts → createLogger.ts} +19 -3
- package/src/logging/logger.test.ts +5 -3
- package/src/server.ts +5 -4
- package/src/servers/createProxyFetch.ts +36 -0
- package/src/{server → servers}/polyfillBrowser.test.ts +6 -1
- package/src/{server → servers}/polyfillBrowser.ts +0 -0
- package/src/{server → servers}/polyfillCrypto.ts +0 -0
- package/src/servers/polyfillFetch.ts +26 -0
- package/src/{server → servers}/polyfillJsDom.ts +0 -0
- package/src/typedoc.ts +2 -2
- package/src/validations/parseTimestamp.test.ts +7 -0
- package/src/validations/parseTimestamp.ts +29 -0
- package/lib/logging/createWriteLogger.js +0 -13
- package/lib/logging/createWriteLogger.js.map +0 -1
- package/lib/server/polyfillBrowser.js.map +0 -1
- package/lib/server/polyfillCrypto.js.map +0 -1
- package/lib/server/polyfillFetch.js +0 -31
- package/lib/server/polyfillFetch.js.map +0 -1
- package/lib/server/polyfillJsDom.js.map +0 -1
- package/lib/validations/isClass.js.map +0 -1
- package/lib/validations/isDefined.js.map +0 -1
- package/lib/validations/isEmptyObject.js.map +0 -1
- package/lib/validations/isPlainObject.js.map +0 -1
- package/src/server/polyfillFetch.ts +0 -28
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
function parseTimestamp(raw) {
|
|
2
|
+
if (!raw) {
|
|
3
|
+
return void 0;
|
|
4
|
+
}
|
|
5
|
+
if (raw instanceof Date) {
|
|
6
|
+
return raw;
|
|
7
|
+
}
|
|
8
|
+
if (typeof raw === "string" && /^[0-9.]+$/.test(raw)) {
|
|
9
|
+
let n = parseFloat(raw);
|
|
10
|
+
const len = Math.floor(n).toString().length;
|
|
11
|
+
if (len <= 11) {
|
|
12
|
+
n *= 1e3;
|
|
13
|
+
}
|
|
14
|
+
return new Date(n);
|
|
15
|
+
} else if (typeof raw === "string") {
|
|
16
|
+
const date = new Date(raw);
|
|
17
|
+
if (!isNaN(+date)) {
|
|
18
|
+
return date;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
throw new Error(`parseTimestamp: invalid "${raw}"`);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export { parseTimestamp };
|
|
25
|
+
//# sourceMappingURL=parseTimestamp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parseTimestamp.js","sources":["../../src/validations/parseTimestamp.ts"],"sourcesContent":["export function parseTimestamp(raw?: string | number | Date): Date | undefined {\n if (!raw) {\n return undefined;\n }\n if (raw instanceof Date) {\n return raw;\n }\n\n if (typeof raw === 'string' && /^[0-9.]+$/.test(raw)) {\n let n = parseFloat(raw);\n const len = Math.floor(n).toString().length;\n /*\n 最常见的是 10 位和 13 位\n 9999999999 - 10*9 - 1970-04-26\n 99999999999 - 11*9 - 1973\n 999999999999 - 12*9 - 2001\n */\n if (len <= 11) {\n n *= 1000;\n }\n return new Date(n);\n } else if (typeof raw === 'string') {\n const date = new Date(raw);\n if (!isNaN(+date)) {\n return date;\n }\n }\n throw new Error(`parseTimestamp: invalid \"${raw}\"`);\n}\n"],"names":[],"mappings":"AAAO,SAAS,eAAe,GAAgD,EAAA;AAC7E,EAAA,IAAI,CAAC,GAAK,EAAA;AACR,IAAO,OAAA,KAAA,CAAA,CAAA;AAAA,GACT;AACA,EAAA,IAAI,eAAe,IAAM,EAAA;AACvB,IAAO,OAAA,GAAA,CAAA;AAAA,GACT;AAEA,EAAA,IAAI,OAAO,GAAQ,KAAA,QAAA,IAAY,WAAY,CAAA,IAAA,CAAK,GAAG,CAAG,EAAA;AACpD,IAAI,IAAA,CAAA,GAAI,WAAW,GAAG,CAAA,CAAA;AACtB,IAAA,MAAM,MAAM,IAAK,CAAA,KAAA,CAAM,CAAC,CAAA,CAAE,UAAW,CAAA,MAAA,CAAA;AAOrC,IAAA,IAAI,OAAO,EAAI,EAAA;AACb,MAAK,CAAA,IAAA,GAAA,CAAA;AAAA,KACP;AACA,IAAO,OAAA,IAAI,KAAK,CAAC,CAAA,CAAA;AAAA,GACnB,MAAA,IAAW,OAAO,GAAA,KAAQ,QAAU,EAAA;AAClC,IAAM,MAAA,IAAA,GAAO,IAAI,IAAA,CAAK,GAAG,CAAA,CAAA;AACzB,IAAA,IAAI,CAAC,KAAA,CAAM,CAAC,IAAI,CAAG,EAAA;AACjB,MAAO,OAAA,IAAA,CAAA;AAAA,KACT;AAAA,GACF;AACA,EAAM,MAAA,IAAI,KAAM,CAAA,CAAA,yBAAA,EAA4B,GAAM,CAAA,CAAA,CAAA,CAAA,CAAA;AACpD;;;;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wener/utils",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.10",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Utils for daily use",
|
|
6
6
|
"repository": {
|
|
@@ -10,10 +10,6 @@
|
|
|
10
10
|
"homepage": "https://github.com/wenerme/wode#readme",
|
|
11
11
|
"author": "wener",
|
|
12
12
|
"license": "MIT",
|
|
13
|
-
"engines": {
|
|
14
|
-
"node": "16",
|
|
15
|
-
"npm": "8"
|
|
16
|
-
},
|
|
17
13
|
"main": "dist/cjs/index.cjs",
|
|
18
14
|
"module": "lib/index.js",
|
|
19
15
|
"exports": {
|
|
@@ -61,10 +57,11 @@
|
|
|
61
57
|
"lodash"
|
|
62
58
|
],
|
|
63
59
|
"devDependencies": {
|
|
64
|
-
"@types/lodash": "^4.14.
|
|
65
|
-
"ava": "^5.
|
|
66
|
-
"
|
|
67
|
-
"
|
|
60
|
+
"@types/lodash": "^4.14.191",
|
|
61
|
+
"ava": "^5.1.1",
|
|
62
|
+
"https-proxy-agent": "^5.0.1",
|
|
63
|
+
"lodash": "^4.17.21",
|
|
64
|
+
"tsd": "^0.25.0"
|
|
68
65
|
},
|
|
69
66
|
"publishConfig": {
|
|
70
67
|
"registry": "https://registry.npmjs.org",
|
|
@@ -77,6 +74,7 @@
|
|
|
77
74
|
},
|
|
78
75
|
"nodeArguments": [
|
|
79
76
|
"--conditions=typescript",
|
|
77
|
+
"--experimental-import-meta-resolve",
|
|
80
78
|
"--require=@wener/wode/suppress-experimental.cjs",
|
|
81
79
|
"--loader=tsx"
|
|
82
80
|
]
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { MaybePromise } from './MaybePromise';
|
|
2
|
+
import { isPromise } from './isPromise';
|
|
2
3
|
|
|
3
4
|
export type LazyPromise<T> = Promise<T> & {
|
|
4
5
|
reject(reason?: any): void;
|
|
@@ -51,7 +52,7 @@ export function createLazyPromise<T = any>(
|
|
|
51
52
|
// kind of bad
|
|
52
53
|
const result = executor(holder.resolve, holder.reject);
|
|
53
54
|
// ensure resolve/reject is called
|
|
54
|
-
if (result
|
|
55
|
+
if (isPromise(result)) {
|
|
55
56
|
result.then(holder.resolve, holder.reject);
|
|
56
57
|
} else if (result !== undefined) {
|
|
57
58
|
holder.resolve(result);
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
|
|
2
|
+
import type { TypedArray } from '../io/ArrayBuffers';
|
|
3
|
+
|
|
2
4
|
let nodeCrypto: Awaited<typeof import('node:crypto')>;
|
|
3
5
|
// globalThis.process?.release?.name
|
|
4
6
|
|
|
5
|
-
//
|
|
6
|
-
if (
|
|
7
|
+
// avoid process.browser
|
|
8
|
+
if (typeof window === 'undefined') {
|
|
7
9
|
try {
|
|
10
|
+
// UnhandledSchemeError https://github.com/vercel/next.js/issues/28774
|
|
8
11
|
if (typeof require === 'undefined') {
|
|
9
12
|
void import('node:crypto').then((v) => (nodeCrypto = v.default));
|
|
10
13
|
} else {
|
|
@@ -13,12 +16,14 @@ if (!(process as any).browser) {
|
|
|
13
16
|
} catch (e) {}
|
|
14
17
|
}
|
|
15
18
|
|
|
16
|
-
export let getRandomValues: <T extends Exclude<
|
|
17
|
-
globalThis.crypto?.getRandomValues
|
|
19
|
+
export let getRandomValues: <T extends Exclude<TypedArray, Float32Array | Float64Array>>(typedArray: T) => T =
|
|
20
|
+
globalThis.crypto?.getRandomValues?.bind(globalThis.crypto) ||
|
|
21
|
+
(globalThis as any).msCrypto?.getRandomValues?.bind((globalThis as any).msCrypto) ||
|
|
22
|
+
_getRandomValues;
|
|
18
23
|
|
|
19
|
-
function _getRandomValues<T extends Exclude<
|
|
24
|
+
function _getRandomValues<T extends Exclude<TypedArray, Float32Array | Float64Array>>(buf: T) {
|
|
20
25
|
if (nodeCrypto?.webcrypto?.getRandomValues) {
|
|
21
|
-
getRandomValues = nodeCrypto?.webcrypto?.getRandomValues;
|
|
26
|
+
getRandomValues = nodeCrypto?.webcrypto?.getRandomValues?.bind(nodeCrypto?.webcrypto);
|
|
22
27
|
return nodeCrypto.webcrypto.getRandomValues(buf);
|
|
23
28
|
}
|
|
24
29
|
if (nodeCrypto?.randomBytes) {
|
|
@@ -36,5 +41,5 @@ function _getRandomValues<T extends Exclude<NodeJS.TypedArray, Float32Array | Fl
|
|
|
36
41
|
buf.set(bytes);
|
|
37
42
|
return buf;
|
|
38
43
|
}
|
|
39
|
-
throw new Error('No secure random number generator available.');
|
|
44
|
+
throw new Error('[getRandomValues]: No secure random number generator available.');
|
|
40
45
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import test from 'ava';
|
|
2
|
-
import { polyfillCrypto } from '../
|
|
2
|
+
import { polyfillCrypto } from '../servers/polyfillCrypto';
|
|
3
3
|
import { isUUID } from '../validations/isUUID';
|
|
4
|
-
import { sha1, sha256, sha384, sha512 } from './hashing';
|
|
5
4
|
import { hex } from './base';
|
|
5
|
+
import { sha1, sha256, sha384, sha512 } from './hashing';
|
|
6
6
|
import { _randomUUID } from './randomUUID';
|
|
7
7
|
|
|
8
8
|
test.before(async () => {
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import test from 'ava';
|
|
2
|
+
import { ArrayBuffers } from '../../io/ArrayBuffers';
|
|
3
|
+
import { PEM } from './pem';
|
|
4
|
+
|
|
5
|
+
const { decode, encode } = PEM;
|
|
6
|
+
|
|
7
|
+
test('pem', (t) => {
|
|
8
|
+
const pem = `-----BEGIN RSA PRIVATE KEY-----
|
|
9
|
+
Proc-Type: 4,ENCRYPTED
|
|
10
|
+
DEK-Info: DES-EDE3-CBC,ABC
|
|
11
|
+
|
|
12
|
+
MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw
|
|
13
|
+
MDAwMDAwMDAwMDAwMDAwMA==
|
|
14
|
+
-----END RSA PRIVATE KEY-----
|
|
15
|
+
`;
|
|
16
|
+
const input = `Nice\n${pem}Hello
|
|
17
|
+
`;
|
|
18
|
+
const out = {
|
|
19
|
+
block: {
|
|
20
|
+
type: 'RSA PRIVATE KEY',
|
|
21
|
+
header: {
|
|
22
|
+
'Proc-Type': '4,ENCRYPTED',
|
|
23
|
+
'DEK-Info': 'DES-EDE3-CBC,ABC',
|
|
24
|
+
},
|
|
25
|
+
bytes: ArrayBuffers.from('0'.repeat(64)),
|
|
26
|
+
},
|
|
27
|
+
head: 'Nice\n',
|
|
28
|
+
tail: 'Hello\n',
|
|
29
|
+
};
|
|
30
|
+
t.deepEqual(decode(input), out);
|
|
31
|
+
t.is(encode(out.block), pem);
|
|
32
|
+
});
|
|
33
|
+
test('cases', (t) => {
|
|
34
|
+
for (const b of [
|
|
35
|
+
{
|
|
36
|
+
type: 'RSA PRIVATE KEY',
|
|
37
|
+
bytes: 'Hello',
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
type: 'RSA PRIVATE KEY',
|
|
41
|
+
header: {
|
|
42
|
+
Name: 'N-:1/=',
|
|
43
|
+
Age: '1234',
|
|
44
|
+
},
|
|
45
|
+
bytes: ArrayBuffers.from('Nice'),
|
|
46
|
+
},
|
|
47
|
+
]) {
|
|
48
|
+
const s = encode(b);
|
|
49
|
+
const act = decode(s);
|
|
50
|
+
t.deepEqual(
|
|
51
|
+
{
|
|
52
|
+
...act.block,
|
|
53
|
+
bytes: ArrayBuffers.toString(act.block.bytes),
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
header: {},
|
|
57
|
+
...b,
|
|
58
|
+
bytes: ArrayBuffers.toString(b.bytes),
|
|
59
|
+
},
|
|
60
|
+
);
|
|
61
|
+
t.snapshot(s);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Snapshot report for `packages/utils/src/crypto/pem.test.ts`
|
|
2
|
+
|
|
3
|
+
The actual snapshot is saved in `pem.test.ts.snap`.
|
|
4
|
+
|
|
5
|
+
Generated by [AVA](https://avajs.dev).
|
|
6
|
+
|
|
7
|
+
## cases
|
|
8
|
+
|
|
9
|
+
> Snapshot 1
|
|
10
|
+
|
|
11
|
+
`-----BEGIN RSA PRIVATE KEY-----␊
|
|
12
|
+
SGVsbG8=␊
|
|
13
|
+
-----END RSA PRIVATE KEY-----␊
|
|
14
|
+
`
|
|
15
|
+
|
|
16
|
+
> Snapshot 2
|
|
17
|
+
|
|
18
|
+
`-----BEGIN RSA PRIVATE KEY-----␊
|
|
19
|
+
Name: N-:1/=␊
|
|
20
|
+
Age: 1234␊
|
|
21
|
+
␊
|
|
22
|
+
TmljZQ==␊
|
|
23
|
+
-----END RSA PRIVATE KEY-----␊
|
|
24
|
+
`
|
|
Binary file
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { ArrayBuffers } from '../../io/ArrayBuffers';
|
|
2
|
+
|
|
3
|
+
export interface Block {
|
|
4
|
+
/**
|
|
5
|
+
* @see https://github.com/openssl/openssl/blob/master/include/openssl/pem.h#L35-L60 openssl/pem.h
|
|
6
|
+
*/
|
|
7
|
+
type:
|
|
8
|
+
| string
|
|
9
|
+
| `${'RSA' | 'DSA'} ${'PRIVATE' | 'PUBLIC'} KEY`
|
|
10
|
+
| `${'X509' | 'TRUSTED'} CERTIFICATE`
|
|
11
|
+
| 'CERTIFICATE'
|
|
12
|
+
| 'X509 CRL'
|
|
13
|
+
| 'CERTIFICATE REQUEST'
|
|
14
|
+
| 'NEW CERTIFICATE REQUEST'
|
|
15
|
+
| 'ANY PRIVATE KEY'
|
|
16
|
+
| 'PUBLIC KEY'
|
|
17
|
+
| 'PKCS7'
|
|
18
|
+
| 'PKCS #7 SIGNED DATA'
|
|
19
|
+
| 'ENCRYPTED PRIVATE KEY'
|
|
20
|
+
| 'PRIVATE KEY'
|
|
21
|
+
| 'DH PARAMETERS'
|
|
22
|
+
| 'X9.42 DH PARAMETERS'
|
|
23
|
+
| 'SSL SESSION PARAMETERS'
|
|
24
|
+
| 'DSA PARAMETERS'
|
|
25
|
+
| 'ECDSA PUBLIC KEY'
|
|
26
|
+
| 'EC PARAMETERS'
|
|
27
|
+
| 'EC PRIVATE KEY'
|
|
28
|
+
| 'PARAMETERS'
|
|
29
|
+
| 'CMS'
|
|
30
|
+
| 'SM2 PARAMETERS';
|
|
31
|
+
|
|
32
|
+
header: Record<string, string>;
|
|
33
|
+
bytes: BufferSource;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export class PEM {
|
|
37
|
+
static decode(data: string): { block: Block; tail: string; head: string } {
|
|
38
|
+
const match = data.match(
|
|
39
|
+
/^-----BEGIN (?<type>[^\r\n-]+)-----$\r?\n(?<headers>(^[^:\r\n]+:[^\n\r]+\r?\n)+\r?\n)?(?<data>[a-zA-Z0-9/_=\n\r+]+?)^-----END \1-----$\r?\n?/ms,
|
|
40
|
+
);
|
|
41
|
+
if (!match?.groups) throw new Error('Invalid PEM data');
|
|
42
|
+
const { type, headers = '', data: b64 } = match.groups;
|
|
43
|
+
const header = headers
|
|
44
|
+
.split('\n')
|
|
45
|
+
.filter((v) => v.trim())
|
|
46
|
+
.map((h) => {
|
|
47
|
+
const [k, ...v] = h.split(':');
|
|
48
|
+
return [k.trim(), v.join(':').trim()];
|
|
49
|
+
})
|
|
50
|
+
.reduce((a, [k, v]) => ({ ...a, [k]: v }), {});
|
|
51
|
+
return {
|
|
52
|
+
block: {
|
|
53
|
+
type,
|
|
54
|
+
header,
|
|
55
|
+
// avoid replaceAll
|
|
56
|
+
bytes: ArrayBuffers.from(b64.replace(/[\r\n]/g, ''), 'base64'),
|
|
57
|
+
},
|
|
58
|
+
head: data.slice(0, match.index || 0),
|
|
59
|
+
tail: data.slice((match.index || 0) + match[0].length),
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
static encode(block: { type: string; bytes: string | BufferSource; header?: Record<string, string> }): string {
|
|
64
|
+
const { type, header, bytes } = block;
|
|
65
|
+
const headers = Object.entries(header || {})
|
|
66
|
+
.map(([k, v]) => `${k}: ${v}`)
|
|
67
|
+
.join('\n');
|
|
68
|
+
return `-----BEGIN ${type}-----\n${headers}${headers.length ? '\n\n' : ''}${
|
|
69
|
+
ArrayBuffers.toString(bytes, 'base64')
|
|
70
|
+
.match(/.{1,64}/g)
|
|
71
|
+
?.join('\n') || ''
|
|
72
|
+
}\n-----END ${type}-----\n`;
|
|
73
|
+
}
|
|
74
|
+
}
|
package/src/crypto/randomUUID.ts
CHANGED
package/src/crypto/ulid.test.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import test from 'ava';
|
|
2
|
-
import { createULID, parseULID } from './ulid';
|
|
2
|
+
import { createULID, isULID, parseULID } from './ulid';
|
|
3
3
|
|
|
4
4
|
test('ulid', (t) => {
|
|
5
5
|
// monotonic
|
|
@@ -13,10 +13,18 @@ test('ulid', (t) => {
|
|
|
13
13
|
});
|
|
14
14
|
|
|
15
15
|
const ulid1 = ulid();
|
|
16
|
-
t.is(parseULID(ulid1).
|
|
16
|
+
t.is(parseULID(ulid1).timestamp, lastTime);
|
|
17
|
+
t.true(isULID(ulid1), ulid1);
|
|
17
18
|
|
|
18
19
|
const ulid2 = ulid();
|
|
19
20
|
t.true(ulid1 < ulid2);
|
|
20
|
-
t.
|
|
21
|
+
t.true(isULID(ulid2), ulid2);
|
|
22
|
+
t.is(parseULID(ulid2).timestamp, lastTime);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
{
|
|
26
|
+
const next = createULID();
|
|
27
|
+
t.true(isULID(next().toLowerCase()));
|
|
28
|
+
t.true(isULID('ttttttttttrrrrrrrrrrrrrrrr'));
|
|
21
29
|
}
|
|
22
30
|
});
|
package/src/crypto/ulid.ts
CHANGED
|
@@ -31,7 +31,8 @@ const RANDOM_LEN = 16;
|
|
|
31
31
|
* check give {@link str} is a valid ulid
|
|
32
32
|
*/
|
|
33
33
|
export function isULID(str: string): boolean {
|
|
34
|
-
|
|
34
|
+
// ttttttttttrrrrrrrrrrrrrrrr
|
|
35
|
+
return str?.length === 26 && /^[0-9A-HJKMNP-TV-Z]{26}$/i.test(str);
|
|
35
36
|
}
|
|
36
37
|
|
|
37
38
|
function replaceCharAt(str: string, index: number, char: string) {
|
|
@@ -109,7 +110,7 @@ function encodeRandom(len: number, prng: PRNG): string {
|
|
|
109
110
|
*
|
|
110
111
|
* @throws ULIDError
|
|
111
112
|
*/
|
|
112
|
-
export function parseULID(id: string): {
|
|
113
|
+
export function parseULID(id: string): { timestamp: number; random: string } {
|
|
113
114
|
if (id.length !== TIME_LEN + RANDOM_LEN) {
|
|
114
115
|
throw createError('malformed ulid');
|
|
115
116
|
}
|
|
@@ -127,7 +128,7 @@ export function parseULID(id: string): { time: number; random: string } {
|
|
|
127
128
|
if (time > TIME_MAX) {
|
|
128
129
|
throw createError('malformed ulid, timestamp too large');
|
|
129
130
|
}
|
|
130
|
-
return { time, random: id.substring(TIME_LEN) };
|
|
131
|
+
return { timestamp: time, random: id.substring(TIME_LEN) };
|
|
131
132
|
}
|
|
132
133
|
|
|
133
134
|
function createPrng(): PRNG {
|
|
@@ -157,7 +158,7 @@ export function createULID({
|
|
|
157
158
|
let lastRandom: string;
|
|
158
159
|
return function ulid(seedTime?: number): string {
|
|
159
160
|
seedTime ||= now();
|
|
160
|
-
if (seedTime <= lastTime) {
|
|
161
|
+
if (seedTime <= lastTime && lastRandom) {
|
|
161
162
|
const incrementedRandom = (lastRandom = incrementBase32(lastRandom));
|
|
162
163
|
return encodeTime(lastTime, TIME_LEN) + incrementedRandom;
|
|
163
164
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type FetchLike = (url: string | Request, init?: RequestInit) => Promise<Response>;
|
package/src/index.ts
CHANGED
|
@@ -6,6 +6,7 @@ export {
|
|
|
6
6
|
objectOfMaybeArray,
|
|
7
7
|
type MaybeArray,
|
|
8
8
|
} from './arrays/MaybeArray';
|
|
9
|
+
export { arrayFromAsync } from './arrays/arrayFromAsync';
|
|
9
10
|
|
|
10
11
|
// object
|
|
11
12
|
export { get } from './objects/get';
|
|
@@ -27,13 +28,16 @@ export { shallowEqual } from './langs/shallowEqual';
|
|
|
27
28
|
export { deepEqual } from './langs/deepEqual';
|
|
28
29
|
export { classOf } from './langs/classOf';
|
|
29
30
|
export { shallowClone } from './langs/shallowClone';
|
|
31
|
+
export { isClass } from './langs/isClass';
|
|
32
|
+
export { isDefined } from './langs/isDefined';
|
|
33
|
+
export { isEmptyObject } from './langs/isEmptyObject';
|
|
34
|
+
export { isPlainObject } from './langs/isPlainObject';
|
|
35
|
+
export { parseBoolean } from './langs/parseBoolean';
|
|
36
|
+
export { maybeFunction, type MaybeFunction } from './langs/MaybeFunction';
|
|
37
|
+
export { memoize } from './langs/memoize';
|
|
30
38
|
|
|
31
|
-
// assertions
|
|
32
|
-
export { isClass } from './validations/isClass';
|
|
33
|
-
export { isDefined } from './validations/isDefined';
|
|
34
|
-
export { isEmptyObject } from './validations/isEmptyObject';
|
|
35
39
|
export { isUUID } from './validations/isUUID';
|
|
36
|
-
export {
|
|
40
|
+
export { parseTimestamp } from './validations/parseTimestamp';
|
|
37
41
|
|
|
38
42
|
// modules
|
|
39
43
|
export { parseModuleId, type ParsedModuleId } from './modules/parseModuleId';
|
|
@@ -41,7 +45,7 @@ export { isModule, type Module } from './modules/isModule';
|
|
|
41
45
|
|
|
42
46
|
// logging
|
|
43
47
|
export { type Logger, type LogLevel } from './logging/Logger';
|
|
44
|
-
export {
|
|
48
|
+
export { createLogger } from './logging/createLogger';
|
|
45
49
|
export { createNoopLogger } from './logging/createNoopLogger';
|
|
46
50
|
export { createChildLogger } from './logging/createChildLogger';
|
|
47
51
|
|
|
@@ -76,6 +80,9 @@ export { getRandomValues } from './crypto/getRandomValues';
|
|
|
76
80
|
export { sha1, sha256, sha384, sha512 } from './crypto/hashing';
|
|
77
81
|
export { hex } from './crypto/base';
|
|
78
82
|
export { isULID, createULID, ulid, parseULID } from './crypto/ulid';
|
|
83
|
+
export { PEM } from './crypto/pem/pem';
|
|
79
84
|
|
|
80
85
|
// misc
|
|
81
86
|
export { createRandom } from './maths/random';
|
|
87
|
+
|
|
88
|
+
export { type FetchLike } from './fetch';
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import test from 'ava';
|
|
2
2
|
import { ArrayBuffers } from './ArrayBuffers';
|
|
3
3
|
|
|
4
|
-
test.before(() => {
|
|
5
|
-
ArrayBuffers.
|
|
4
|
+
test.before((t) => {
|
|
5
|
+
t.true(ArrayBuffers.isNativeBufferAvailable());
|
|
6
|
+
ArrayBuffers.setNativeBufferAllowed(false);
|
|
6
7
|
});
|
|
7
8
|
|
|
8
9
|
test('base64: ignore whitespace', function (t) {
|
package/src/io/ArrayBuffers.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { classOf } from '../langs/classOf';
|
|
2
|
+
import { decodeBase64ToArrayBuffer, encodeArrayBufferToBase64 } from './base64';
|
|
2
3
|
import { isBuffer } from './isBuffer';
|
|
3
4
|
|
|
4
5
|
/**
|
|
@@ -67,14 +68,20 @@ type ToStringEncoding =
|
|
|
67
68
|
| 'hex';
|
|
68
69
|
|
|
69
70
|
export class ArrayBuffers {
|
|
70
|
-
static #
|
|
71
|
+
static #nativeBufferAllowed: boolean = true;
|
|
72
|
+
static #isBufferAvailable: undefined | boolean;
|
|
71
73
|
|
|
72
|
-
static
|
|
73
|
-
|
|
74
|
+
static isNativeBufferAvailable() {
|
|
75
|
+
// eslint-disable-next-line no-return-assign
|
|
76
|
+
return (this.#isBufferAvailable ??= !(globalThis.Buffer as any)?.isPollyfill?.());
|
|
74
77
|
}
|
|
75
78
|
|
|
76
|
-
static
|
|
77
|
-
this.#
|
|
79
|
+
static isNativeBufferAllowed() {
|
|
80
|
+
return this.#nativeBufferAllowed && this.#isBufferAvailable;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
static setNativeBufferAllowed(v: boolean) {
|
|
84
|
+
this.#nativeBufferAllowed = v;
|
|
78
85
|
}
|
|
79
86
|
|
|
80
87
|
static isArrayBuffer = (v: any): v is ArrayBuffer => {
|
|
@@ -100,7 +107,7 @@ export class ArrayBuffers {
|
|
|
100
107
|
return v as I;
|
|
101
108
|
}
|
|
102
109
|
if (ArrayBuffer.isView(v) || isBuffer(v)) {
|
|
103
|
-
if (ArrayBuffers
|
|
110
|
+
if (ArrayBuffers.isNativeBufferAllowed() && (TypedArray as any) === Buffer) {
|
|
104
111
|
// new Buffer() is deprecated
|
|
105
112
|
return Buffer.from(v.buffer, byteOffset, byteLength) as I;
|
|
106
113
|
}
|
|
@@ -112,9 +119,17 @@ export class ArrayBuffers {
|
|
|
112
119
|
static toString = (buf: BufferSource | string, encoding: ToStringEncoding = 'utf8') => {
|
|
113
120
|
// 'ascii' 'utf16le' | 'ucs2' | 'ucs-2' | 'base64' | 'base64url' | 'latin1' | 'binary' | 'hex'
|
|
114
121
|
if (typeof buf === 'string') {
|
|
115
|
-
|
|
122
|
+
switch (encoding) {
|
|
123
|
+
case 'base64':
|
|
124
|
+
return btoa(buf);
|
|
125
|
+
case 'utf-8':
|
|
126
|
+
case 'utf8':
|
|
127
|
+
return buf;
|
|
128
|
+
default:
|
|
129
|
+
throw new Error(`[ArrayBuffers.toString] Unsupported encoding for string: ${encoding}`);
|
|
130
|
+
}
|
|
116
131
|
}
|
|
117
|
-
if (ArrayBuffers
|
|
132
|
+
if (ArrayBuffers.isNativeBufferAllowed()) {
|
|
118
133
|
return Buffer.from(ArrayBuffers.asView(Uint8Array, buf)).toString(encoding);
|
|
119
134
|
}
|
|
120
135
|
// reference
|
|
@@ -125,8 +140,7 @@ export class ArrayBuffers {
|
|
|
125
140
|
return [...view].map((b) => hexLookupTable[b]).join('');
|
|
126
141
|
}
|
|
127
142
|
case 'base64': {
|
|
128
|
-
|
|
129
|
-
return btoa(String.fromCharCode(...view));
|
|
143
|
+
return encodeArrayBufferToBase64(ArrayBuffers.asView(Uint8Array, buf));
|
|
130
144
|
}
|
|
131
145
|
case 'utf8':
|
|
132
146
|
// falls through
|
|
@@ -185,7 +199,7 @@ export class ArrayBuffers {
|
|
|
185
199
|
return new ArrayBuffer(0);
|
|
186
200
|
}
|
|
187
201
|
if (typeof v === 'string') {
|
|
188
|
-
if (ArrayBuffers
|
|
202
|
+
if (ArrayBuffers.isNativeBufferAllowed()) {
|
|
189
203
|
return Buffer.from(v, encoding);
|
|
190
204
|
}
|
|
191
205
|
|
|
@@ -195,8 +209,10 @@ export class ArrayBuffers {
|
|
|
195
209
|
case 'utf8':
|
|
196
210
|
return new TextEncoder().encode(v).buffer;
|
|
197
211
|
case 'base64':
|
|
198
|
-
// replaceAll
|
|
199
|
-
return
|
|
212
|
+
// replaceAll need higher version of nodejs
|
|
213
|
+
return decodeBase64ToArrayBuffer(v.replace(/[^0-9a-zA-Z=+/_]/g, ''));
|
|
214
|
+
// error in nodejs 18
|
|
215
|
+
// return Uint8Array.from(atob(v.replace(/[^0-9a-zA-Z=+/_ \r\n]/g, '')), (c) => c.charCodeAt(0));
|
|
200
216
|
default:
|
|
201
217
|
throw new Error(`[ArrayBuffers.from] Unknown encoding: ${encoding}`);
|
|
202
218
|
}
|
|
@@ -244,7 +260,7 @@ export class ArrayBuffers {
|
|
|
244
260
|
const length = buffers.reduce((a, b) => a + b.byteLength, 0);
|
|
245
261
|
const r = result ? new Uint8Array(result) : new Uint8Array(length);
|
|
246
262
|
for (const buffer of buffers) {
|
|
247
|
-
if (!buffer
|
|
263
|
+
if (!buffer?.byteLength) continue;
|
|
248
264
|
let n: Uint8Array;
|
|
249
265
|
if (buffer instanceof ArrayBuffer) {
|
|
250
266
|
n = new Uint8Array(buffer);
|
package/src/io/base64.ts
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// https://github.com/niklasvh/base64-arraybuffer/blob/master/src/index.ts
|
|
2
|
+
|
|
3
|
+
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
|
4
|
+
|
|
5
|
+
// Use a lookup table to find the index.
|
|
6
|
+
const lookup = typeof Uint8Array === 'undefined' ? [] : new Uint8Array(256);
|
|
7
|
+
for (let i = 0; i < chars.length; i++) {
|
|
8
|
+
lookup[chars.charCodeAt(i)] = i;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function encodeArrayBufferToBase64(arraybuffer: ArrayBuffer): string {
|
|
12
|
+
const bytes = new Uint8Array(arraybuffer);
|
|
13
|
+
const len = bytes.length;
|
|
14
|
+
let base64 = '';
|
|
15
|
+
|
|
16
|
+
for (let i = 0; i < len; i += 3) {
|
|
17
|
+
base64 += chars[bytes[i] >> 2];
|
|
18
|
+
base64 += chars[((bytes[i] & 3) << 4) | (bytes[i + 1] >> 4)];
|
|
19
|
+
base64 += chars[((bytes[i + 1] & 15) << 2) | (bytes[i + 2] >> 6)];
|
|
20
|
+
base64 += chars[bytes[i + 2] & 63];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (len % 3 === 2) {
|
|
24
|
+
base64 = base64.substring(0, base64.length - 1) + '=';
|
|
25
|
+
} else if (len % 3 === 1) {
|
|
26
|
+
base64 = base64.substring(0, base64.length - 2) + '==';
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return base64;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function decodeBase64ToArrayBuffer(base64: string): ArrayBuffer {
|
|
33
|
+
const len = base64.length;
|
|
34
|
+
let bufferLength = base64.length * 0.75;
|
|
35
|
+
let i;
|
|
36
|
+
let p = 0;
|
|
37
|
+
let encoded1;
|
|
38
|
+
let encoded2;
|
|
39
|
+
let encoded3;
|
|
40
|
+
let encoded4;
|
|
41
|
+
|
|
42
|
+
if (base64[base64.length - 1] === '=') {
|
|
43
|
+
bufferLength--;
|
|
44
|
+
if (base64[base64.length - 2] === '=') {
|
|
45
|
+
bufferLength--;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const arraybuffer = new ArrayBuffer(bufferLength);
|
|
50
|
+
const bytes = new Uint8Array(arraybuffer);
|
|
51
|
+
|
|
52
|
+
for (i = 0; i < len; i += 4) {
|
|
53
|
+
encoded1 = lookup[base64.charCodeAt(i)];
|
|
54
|
+
encoded2 = lookup[base64.charCodeAt(i + 1)];
|
|
55
|
+
encoded3 = lookup[base64.charCodeAt(i + 2)];
|
|
56
|
+
encoded4 = lookup[base64.charCodeAt(i + 3)];
|
|
57
|
+
|
|
58
|
+
bytes[p++] = (encoded1 << 2) | (encoded2 >> 4);
|
|
59
|
+
bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2);
|
|
60
|
+
bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return arraybuffer;
|
|
64
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type MaybeFunction<T, P extends any[] = any[]> = T | ((...args: P) => T);
|
|
2
|
+
|
|
3
|
+
export function maybeFunction<T, P extends any[] = any[]>(v: MaybeFunction<T, P>, ...args: P): T {
|
|
4
|
+
// https://github.com/microsoft/TypeScript/issues/37663#issuecomment-759728342
|
|
5
|
+
if (v instanceof Function) {
|
|
6
|
+
return v(...args);
|
|
7
|
+
}
|
|
8
|
+
return v;
|
|
9
|
+
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|