@wener/utils 1.1.38 → 1.1.40
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/lib/asyncs/createAsyncIterator.js.map +1 -1
- package/lib/asyncs/createLazyPromise.js.map +1 -1
- package/lib/asyncs/firstOfAsyncIterator.js.map +1 -1
- package/lib/asyncs/nextOfAsyncIterator.js.map +1 -1
- package/lib/cn/division/DivisionCode.js +35 -43
- package/lib/cn/division/DivisionCode.js.map +1 -1
- package/lib/cn/division/binarySearch.js +27 -0
- package/lib/cn/division/binarySearch.js.map +1 -0
- package/lib/cn/id/ResidentIdNumber.js +25 -14
- package/lib/cn/id/ResidentIdNumber.js.map +1 -1
- package/lib/cn/index.js +1 -0
- package/lib/cn/index.js.map +1 -1
- package/lib/cn/pinyin/cartesianProduct.js +22 -0
- package/lib/cn/pinyin/cartesianProduct.js.map +1 -0
- package/lib/cn/pinyin/data.json +413 -0
- package/lib/cn/pinyin/toPinyinPure.js +39 -0
- package/lib/cn/pinyin/toPinyinPure.js.map +1 -0
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -1
- package/lib/langs/mixin.js +22 -0
- package/lib/langs/mixin.js.map +1 -0
- package/lib/logging/createChildLogger.js.map +1 -1
- package/lib/objects/computeIfAbsent.js.map +1 -1
- package/lib/objects/get.js.map +1 -1
- package/lib/objects/set.js.map +1 -1
- package/lib/schema/typebox/gen/codegen/typescript/typescript-to-model.js +1 -1
- package/lib/schema/typebox/gen/codegen/typescript/typescript-to-model.js.map +1 -1
- package/lib/scripts/getGenerateContext.js +86 -0
- package/lib/scripts/getGenerateContext.js.map +1 -0
- package/lib/types.d.js.map +1 -1
- package/package.json +6 -1
- package/src/asyncs/createAsyncIterator.ts +1 -1
- package/src/asyncs/createLazyPromise.ts +1 -1
- package/src/asyncs/firstOfAsyncIterator.ts +1 -1
- package/src/asyncs/nextOfAsyncIterator.ts +1 -1
- package/src/cn/division/DivisionCode.ts +37 -44
- package/src/cn/division/binarySearch.test.ts +64 -0
- package/src/cn/division/binarySearch.ts +25 -0
- package/src/cn/id/ResidentIdNumber.ts +38 -12
- package/src/cn/id/id.test.ts +1 -1
- package/src/cn/index.ts +2 -0
- package/src/cn/pinyin/cartesianProduct.test.ts +64 -0
- package/src/cn/pinyin/cartesianProduct.ts +24 -0
- package/src/cn/pinyin/data.json +413 -0
- package/src/cn/pinyin/toPinyin.test.ts +10 -0
- package/src/cn/pinyin/toPinyinPure.ts +52 -0
- package/src/cn/scripts/gen.test.ts +130 -0
- package/src/cn/uscc/uscc.test.ts +2 -2
- package/src/index.ts +3 -0
- package/src/io/ArrayBuffers.base64.test.ts +1 -1
- package/src/io/ArrayBuffers.test.ts +1 -1
- package/src/io/Buffer.test.ts +1 -1
- package/src/langs/README.md +4 -0
- package/src/langs/mixin.ts +82 -0
- package/src/logging/createChildLogger.ts +1 -1
- package/src/logging/logger.test.ts +1 -1
- package/src/modules/parseModuleId.test.ts +1 -1
- package/src/objects/computeIfAbsent.ts +2 -2
- package/src/objects/get.ts +1 -2
- package/src/objects/parseObjectPath.test.ts +1 -1
- package/src/objects/set.test.ts +1 -1
- package/src/objects/set.ts +1 -2
- package/src/schema/typebox/gen/codegen/typescript/typescript-to-model.ts +1 -1
- package/src/scripts/getGenerateContext.ts +97 -0
- package/src/server/polyfill/polyfillBrowser.test.ts +1 -1
- package/src/types.d.ts +2 -2
- package/lib/langs/hashCode.ignored.js +0 -112
- package/lib/langs/hashCode.ignored.js.map +0 -1
- package/src/langs/hashCode.ignored.ts +0 -125
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { cartesianProduct } from './cartesianProduct';
|
|
2
|
+
// import CharToPinyins from './pinyin.json' with { type: 'json' };
|
|
3
|
+
import PyToChar from './data.json' with { type: 'json' };
|
|
4
|
+
|
|
5
|
+
let CharToPinyinTable: Record<string, string[]>;
|
|
6
|
+
|
|
7
|
+
export function getCharToPinyinTable() {
|
|
8
|
+
if (!CharToPinyinTable) {
|
|
9
|
+
CharToPinyinTable = {};
|
|
10
|
+
for (let [py, chars] of Object.entries(PyToChar)) {
|
|
11
|
+
for (let c of chars) {
|
|
12
|
+
if (!CharToPinyinTable[c]) {
|
|
13
|
+
CharToPinyinTable[c] = [];
|
|
14
|
+
}
|
|
15
|
+
CharToPinyinTable[c].push(py);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return CharToPinyinTable;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function toPinyinPureFirst(s: string, sep = ','): string {
|
|
23
|
+
let tab = getCharToPinyinTable();
|
|
24
|
+
return s
|
|
25
|
+
.split('')
|
|
26
|
+
.map((c) => tab[c]?.[0])
|
|
27
|
+
.filter(Boolean)
|
|
28
|
+
.join(sep);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
export function toPinyinPure(s: string, sep = ','): string[] {
|
|
33
|
+
let tab = getCharToPinyinTable();
|
|
34
|
+
// ensure order
|
|
35
|
+
return cartesianProduct(s.split('')
|
|
36
|
+
.map((c) => tab[c] || ''))
|
|
37
|
+
.sort((a, b) => {
|
|
38
|
+
for (let i = 0; i < a.length; i++) {
|
|
39
|
+
let x = a[i];
|
|
40
|
+
let y = b[i];
|
|
41
|
+
if (x < y) return -1;
|
|
42
|
+
if (x > y) return 1;
|
|
43
|
+
}
|
|
44
|
+
return 0;
|
|
45
|
+
})
|
|
46
|
+
.map((v) => v.filter(Boolean).join(sep));
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// export function lookupPinyinPure(s: string): Array<Array<string>> {
|
|
50
|
+
// return cartesianProductOfArray(s.split('').map(c => Lookup[c]));
|
|
51
|
+
// }
|
|
52
|
+
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { test } from 'vitest';
|
|
2
|
+
import { getGenerateContext } from '../../scripts/getGenerateContext';
|
|
3
|
+
|
|
4
|
+
function parseCsv(v: string) {
|
|
5
|
+
return v
|
|
6
|
+
.split('\n')
|
|
7
|
+
.filter(Boolean)
|
|
8
|
+
.map((v) => v.split(',').slice(0, 2))
|
|
9
|
+
.slice(1); // remove header
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
test(
|
|
13
|
+
'division-gen',
|
|
14
|
+
{
|
|
15
|
+
timeout: 1000 * 60 * 30,
|
|
16
|
+
},
|
|
17
|
+
async () => {
|
|
18
|
+
await generate();
|
|
19
|
+
},
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
async function generate() {
|
|
23
|
+
const { cache, writeData, writeSrc } = await getGenerateContext('cn/division');
|
|
24
|
+
|
|
25
|
+
const stats: Record<string, any> = {};
|
|
26
|
+
const entries: Record<string, [number, string][]> = {};
|
|
27
|
+
const set = new Map<number, [number, string, number[]?]>();
|
|
28
|
+
for (const fn of ['provinces', 'cities', 'areas', 'streets', 'villages']) {
|
|
29
|
+
const rows: string[][] = await cache(
|
|
30
|
+
`https://raw.githubusercontent.com/modood/Administrative-divisions-of-China/master/dist/${fn}.csv`,
|
|
31
|
+
).then(parseCsv);
|
|
32
|
+
entries[fn] = rows.map(([k, v]) => {
|
|
33
|
+
if (!v) {
|
|
34
|
+
throw new Error(`empty value for ${k}`);
|
|
35
|
+
}
|
|
36
|
+
// csv name has quote
|
|
37
|
+
return [parseInt(k), v.replace(/"/g, '')];
|
|
38
|
+
});
|
|
39
|
+
stats[
|
|
40
|
+
{
|
|
41
|
+
areas: 'counties',
|
|
42
|
+
streets: 'towns',
|
|
43
|
+
}[fn] || fn
|
|
44
|
+
] = rows.length;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const all = Object.values(entries).flat();
|
|
48
|
+
for (const [k, v] of all) {
|
|
49
|
+
const p = parent(k);
|
|
50
|
+
set.set(k, [k, v]);
|
|
51
|
+
if (p) {
|
|
52
|
+
const par = set.get(parseInt(p));
|
|
53
|
+
if (!par) {
|
|
54
|
+
throw new Error(`missing parent ${p} for ${k}`);
|
|
55
|
+
}
|
|
56
|
+
par[2] ||= [];
|
|
57
|
+
par[2].push(k);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const full = Array.from(set.values());
|
|
62
|
+
const dataset = {
|
|
63
|
+
'village.json': full,
|
|
64
|
+
'village.csv': full.map(([code, name]) => `${code},${name}`).join('\n'),
|
|
65
|
+
'county.json': full
|
|
66
|
+
.filter((v) => {
|
|
67
|
+
return v[0] < 1000000;
|
|
68
|
+
})
|
|
69
|
+
.map((e) => {
|
|
70
|
+
const [code, name] = e;
|
|
71
|
+
// remove leaf children
|
|
72
|
+
if (code > 10000) {
|
|
73
|
+
return [code, name];
|
|
74
|
+
}
|
|
75
|
+
return e;
|
|
76
|
+
}),
|
|
77
|
+
};
|
|
78
|
+
const srcs: Record<string, string> = {
|
|
79
|
+
// preload small dataset
|
|
80
|
+
// 'dataset.gen.ts': `// This if is generated by generate.ts, DO NOT EDIT
|
|
81
|
+
// export const ProvinceCodes = [${entries.provinces.map(([k]) => JSON.stringify(String(k))).join(',')}];
|
|
82
|
+
// `,
|
|
83
|
+
};
|
|
84
|
+
for (const [name, data] of Object.entries(dataset)) {
|
|
85
|
+
await writeData(name, typeof data === 'object' ? JSON.stringify(data) : data);
|
|
86
|
+
}
|
|
87
|
+
for (const [name, data] of Object.entries(srcs)) {
|
|
88
|
+
await writeSrc(name, typeof data === 'object' ? JSON.stringify(data) : data);
|
|
89
|
+
}
|
|
90
|
+
await writeData(`stats.json`, JSON.stringify(stats, null, 2));
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
type TreeNode = [number, TreeNode[]?];
|
|
94
|
+
|
|
95
|
+
export function search(arr: TreeNode[], val: number): [boolean, number] {
|
|
96
|
+
let start = 0;
|
|
97
|
+
let end = arr.length - 1;
|
|
98
|
+
let mid;
|
|
99
|
+
while (start <= end) {
|
|
100
|
+
mid = Math.floor((start + end) / 2);
|
|
101
|
+
if (arr[mid][0] === val) {
|
|
102
|
+
return [true, mid];
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (val < arr[mid][0]) {
|
|
106
|
+
end = mid - 1;
|
|
107
|
+
} else {
|
|
108
|
+
start = mid + 1;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return [false, mid ?? 0];
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function parent(code: string | number) {
|
|
116
|
+
return split(code).slice(0, -1).join('') || undefined;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function split(code: string | number) {
|
|
120
|
+
if (!code) return [];
|
|
121
|
+
code = String(code);
|
|
122
|
+
return [
|
|
123
|
+
//
|
|
124
|
+
code.slice(0, 2),
|
|
125
|
+
code.slice(2, 4),
|
|
126
|
+
code.slice(4, 6),
|
|
127
|
+
code.slice(6, 9),
|
|
128
|
+
code.slice(9),
|
|
129
|
+
].filter((v) => parseInt(v));
|
|
130
|
+
}
|
package/src/cn/uscc/uscc.test.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { expect, test } from 'vitest';
|
|
2
|
+
import { isUSCC } from './isUSCC';
|
|
2
3
|
import { Mod31Checksum } from './Mod31Checksum';
|
|
3
4
|
import { USCC } from './USCC';
|
|
4
|
-
import { isUSCC } from './isUSCC';
|
|
5
5
|
|
|
6
6
|
test('uscc', () => {
|
|
7
7
|
let cs = Mod31Checksum.get();
|
package/src/index.ts
CHANGED
|
@@ -43,6 +43,9 @@ export { isPlainObject } from './langs/isPlainObject';
|
|
|
43
43
|
export { parseBoolean } from './langs/parseBoolean';
|
|
44
44
|
export { maybeFunction, type MaybeFunction } from './langs/MaybeFunction';
|
|
45
45
|
export { memoize } from './langs/memoize';
|
|
46
|
+
export { mixin } from './langs/mixin';
|
|
47
|
+
export type { MixinFunction, MixinInstance, MixinReturnValue } from './langs/mixin';
|
|
48
|
+
|
|
46
49
|
export { AsyncCloser } from './runtime/AsyncCloser';
|
|
47
50
|
export { Closer } from './runtime/Closer';
|
|
48
51
|
|
package/src/io/Buffer.test.ts
CHANGED
package/src/langs/README.md
CHANGED
|
@@ -2,3 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
- https://github.com/angus-c/just
|
|
4
4
|
- lodash
|
|
5
|
+
- mixin https://github.com/1nVitr0/lib-ts-mixin-extended
|
|
6
|
+
- https://developer.mozilla.org/docs/Web/JavaScript/Reference/Classes#Mix-ins
|
|
7
|
+
- http://justinfagnani.com/2015/12/21/real-mixins-with-javascript-classes/
|
|
8
|
+
- https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Helper type to convert a union to an intersection.
|
|
3
|
+
*
|
|
4
|
+
* @internal
|
|
5
|
+
*/
|
|
6
|
+
type UnionToIntersection<T> = (T extends any ? (x: T) => any : never) extends (x: infer R) => any ? R : never;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Constructor function, that creates a new instance of the given type.
|
|
10
|
+
*
|
|
11
|
+
* @typeParam T The type of the instance to create.
|
|
12
|
+
* @example ```ts
|
|
13
|
+
* function Walkable<TBase extends MixinConstructor<Positionable>>(Base: TBase) {
|
|
14
|
+
* ··return class Walkable extends Base {
|
|
15
|
+
* ····public forward() { this.x++; }
|
|
16
|
+
* ····public backward() { this.x--; }
|
|
17
|
+
* ··};
|
|
18
|
+
* }
|
|
19
|
+
* ```
|
|
20
|
+
* @example ```ts
|
|
21
|
+
* function Loggable(Base: MixinConstructor) {
|
|
22
|
+
* ··return class Loggable extends Base {
|
|
23
|
+
* ····public log(message: string) { throw new Error(404); }
|
|
24
|
+
* ··};
|
|
25
|
+
* }
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export type MixinConstructor<T = {}> = new (...args: any[]) => T;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Function that applies a mixin to a given base class.
|
|
32
|
+
*
|
|
33
|
+
* @typeParam T The type of the base class.
|
|
34
|
+
* @typeParam R The type of the returned class.
|
|
35
|
+
*/
|
|
36
|
+
export type MixinFunction<T extends MixinConstructor = MixinConstructor, R extends T = T & MixinConstructor> = (
|
|
37
|
+
Base: T,
|
|
38
|
+
) => R;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* The return type of the mixin function.
|
|
42
|
+
*
|
|
43
|
+
* @typeParam T The type of the base class.
|
|
44
|
+
* @typeParam M The type of the mixin functions.
|
|
45
|
+
*/
|
|
46
|
+
export type MixinReturnValue<T extends MixinConstructor, M extends MixinFunction<T, any>[]> = UnionToIntersection<
|
|
47
|
+
| T
|
|
48
|
+
| {
|
|
49
|
+
[K in keyof M]: M[K] extends MixinFunction<any, infer U> ? U : never;
|
|
50
|
+
}[number]
|
|
51
|
+
>;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* The instance created by a mixin function.
|
|
55
|
+
*
|
|
56
|
+
* @typeParam F The type of the mixin function.
|
|
57
|
+
*/
|
|
58
|
+
export type MixinInstance<F extends MixinFunction<any>> =
|
|
59
|
+
F extends MixinFunction<MixinConstructor<any>, infer R> ? InstanceType<R> : never;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Applies the given mixins to the a common base class.
|
|
63
|
+
*
|
|
64
|
+
* @param Base The base class to apply the mixins to.
|
|
65
|
+
* @param mixins The mixins to apply. All mixins must extend a common base class or an empty class.
|
|
66
|
+
* @returns A class constructor with all mixins applied.
|
|
67
|
+
*
|
|
68
|
+
* @typeParam T The type of the base class.
|
|
69
|
+
* @typeParam M The type of the mixin functions.
|
|
70
|
+
*
|
|
71
|
+
* @example ```ts
|
|
72
|
+
* class Dog extends mixin(Animal, FourLegged, Carnivore, PackHunting, Barking, Domesticated) {}
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
export function mixin<T extends MixinConstructor, M extends MixinFunction<T, any>[]>(
|
|
76
|
+
Base: T,
|
|
77
|
+
...mixins: M
|
|
78
|
+
): MixinReturnValue<T, M> {
|
|
79
|
+
return mixins.reduce((mix, applyMixin) => applyMixin(mix), Base) as MixinReturnValue<T, M>;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// https://github.com/1nVitr0/lib-ts-mixin-extended
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export function computeIfAbsent<K, V>(map: Map<K, V>, key: K, fn: () => V): V
|
|
2
|
-
export function computeIfAbsent<K extends string | symbol | number, V>(map: Record<K, V>, key: K, fn: () => V): V
|
|
1
|
+
export function computeIfAbsent<K, V>(map: Map<K, V>, key: K, fn: () => V): V;
|
|
2
|
+
export function computeIfAbsent<K extends string | symbol | number, V>(map: Record<K, V>, key: K, fn: () => V): V;
|
|
3
3
|
export function computeIfAbsent<K, V>(map: any, key: K, fn: () => V): V {
|
|
4
4
|
if (map instanceof Map) {
|
|
5
5
|
if (!map.has(key)) {
|
package/src/objects/get.ts
CHANGED
package/src/objects/set.test.ts
CHANGED
package/src/objects/set.ts
CHANGED
|
@@ -23,7 +23,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
23
23
|
THE SOFTWARE.
|
|
24
24
|
|
|
25
25
|
---------------------------------------------------------------------------*/
|
|
26
|
-
import {
|
|
26
|
+
import { CloneType, Kind, Type, type TSchema } from '@sinclair/typebox';
|
|
27
27
|
import * as ts from 'typescript';
|
|
28
28
|
import { TypeBoxModel } from '../model/model';
|
|
29
29
|
import { TypeScriptToTypeBox } from './typescript-to-typebox';
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { Errors, formatBytes, type MaybePromise } from '@wener/utils';
|
|
4
|
+
import { getPackageDir } from '../server';
|
|
5
|
+
|
|
6
|
+
let _root: GenerateContext;
|
|
7
|
+
|
|
8
|
+
export interface GenerateContext {
|
|
9
|
+
pkgDir: string;
|
|
10
|
+
rootDataDir: string;
|
|
11
|
+
rootCacheDir: string;
|
|
12
|
+
dataDir: string;
|
|
13
|
+
cacheDir: string;
|
|
14
|
+
srcDir: string;
|
|
15
|
+
cache: (url: string) => Promise<string>;
|
|
16
|
+
writeData: (path: string, content: string) => Promise<void>;
|
|
17
|
+
writeSrc: (path: string, content: string) => Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async function cache(dir: string, url: string): Promise<string> {
|
|
21
|
+
const key = path.basename(url);
|
|
22
|
+
await fs.mkdir(path.join(dir), { recursive: true });
|
|
23
|
+
const file = path.join(dir, key);
|
|
24
|
+
try {
|
|
25
|
+
await fs.stat(file);
|
|
26
|
+
console.info('[cache] hit', url);
|
|
27
|
+
return await fs.readFile(file, 'utf-8');
|
|
28
|
+
} catch (e) {}
|
|
29
|
+
console.info('[cache] miss', url);
|
|
30
|
+
const text = await fetch(url).then((v) => {
|
|
31
|
+
if (v.status >= 300) {
|
|
32
|
+
throw new Error(`[cache] fetch ${url} ${v.status} ${v.statusText}`);
|
|
33
|
+
}
|
|
34
|
+
return v.text();
|
|
35
|
+
});
|
|
36
|
+
const size = new Blob([text]).size;
|
|
37
|
+
console.info(`[cache] write ${file} ${formatBytes(size)} (${size})`);
|
|
38
|
+
await fs.writeFile(file, text);
|
|
39
|
+
return text;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function getGenerateContext(prefix?: string): MaybePromise<GenerateContext> {
|
|
43
|
+
if (prefix) {
|
|
44
|
+
return Promise.resolve(getGenerateContext()).then((c) => {
|
|
45
|
+
const cacheDir = path.resolve(c.cacheDir, prefix);
|
|
46
|
+
const dataDir = path.resolve(c.dataDir, prefix);
|
|
47
|
+
const srcDir = path.resolve(c.srcDir, prefix);
|
|
48
|
+
return {
|
|
49
|
+
...c,
|
|
50
|
+
dataDir,
|
|
51
|
+
cacheDir,
|
|
52
|
+
srcDir,
|
|
53
|
+
cache: (url: string) => cache(cacheDir, url),
|
|
54
|
+
writeData: (file: string, content: string) => write(dataDir, file, content),
|
|
55
|
+
writeSrc: (file: string, content: string) => write(srcDir, file, content),
|
|
56
|
+
};
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
return (
|
|
60
|
+
_root ||
|
|
61
|
+
Promise.resolve().then(async () => {
|
|
62
|
+
const pkgDir = await getPackageDir();
|
|
63
|
+
Errors.BadRequest.check(pkgDir, 'pkgDir not found');
|
|
64
|
+
const dataDir = path.resolve(pkgDir, 'data');
|
|
65
|
+
const cacheDir = path.resolve(pkgDir, 'cache');
|
|
66
|
+
const srcDir = path.resolve(pkgDir, 'src');
|
|
67
|
+
await fs.mkdir(cacheDir, { recursive: true });
|
|
68
|
+
await fs.mkdir(dataDir, { recursive: true });
|
|
69
|
+
return (_root = Object.freeze({
|
|
70
|
+
pkgDir,
|
|
71
|
+
dataDir,
|
|
72
|
+
cacheDir,
|
|
73
|
+
srcDir,
|
|
74
|
+
rootCacheDir: cacheDir,
|
|
75
|
+
rootDataDir: dataDir,
|
|
76
|
+
cache: (url: string) => cache(cacheDir, url),
|
|
77
|
+
writeData: (file: string, content: string) => write(dataDir, file, content),
|
|
78
|
+
writeSrc: (file: string, content: string) => write(srcDir, file, content),
|
|
79
|
+
}));
|
|
80
|
+
})
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async function write(dir: string, file: string, content: string) {
|
|
85
|
+
const size = new Blob([content]).size;
|
|
86
|
+
const dst = path.join(dir, file);
|
|
87
|
+
let last;
|
|
88
|
+
try {
|
|
89
|
+
last = (await fs.stat(dst)).size;
|
|
90
|
+
} catch {}
|
|
91
|
+
console.info(
|
|
92
|
+
`[write] ${path.relative(_root.pkgDir, dir)} ${file} ${
|
|
93
|
+
last ? (last !== size ? `${formatBytes(last)} (${last}) -> ` : 'SAME SIZE ') : ''
|
|
94
|
+
}${formatBytes(size)} (${size})`,
|
|
95
|
+
);
|
|
96
|
+
await fs.writeFile(dst, content);
|
|
97
|
+
}
|
package/src/types.d.ts
CHANGED
|
@@ -10,8 +10,8 @@ namespace NodeJS {
|
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
export type AbstractConstructor<T =
|
|
14
|
-
export type Constructor<T =
|
|
13
|
+
export type AbstractConstructor<T = {}> = abstract new (...args: any[]) => T;
|
|
14
|
+
export type Constructor<T = {}> = new (...args: any[]) => T;
|
|
15
15
|
export type Optional<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
|
|
16
16
|
export type PartialRequired<T, K extends keyof T> = Partial<Omit<T, K>> & Required<Pick<T, K>>;
|
|
17
17
|
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
function sortObjectKeys(obj) {
|
|
2
|
-
if (obj === null || obj === undefined) {
|
|
3
|
-
return obj;
|
|
4
|
-
}
|
|
5
|
-
if (typeof obj !== 'object') {
|
|
6
|
-
// it is a primitive: number/string (in an array)
|
|
7
|
-
return obj;
|
|
8
|
-
}
|
|
9
|
-
return Object.keys(obj).sort().reduce((acc, key)=>{
|
|
10
|
-
if (Array.isArray(obj[key])) {
|
|
11
|
-
acc[key] = obj[key].map(sortObjectKeys);
|
|
12
|
-
} else if (typeof obj[key] === 'object') {
|
|
13
|
-
acc[key] = sortObjectKeys(obj[key]);
|
|
14
|
-
} else {
|
|
15
|
-
acc[key] = obj[key];
|
|
16
|
-
}
|
|
17
|
-
return acc;
|
|
18
|
-
}, {});
|
|
19
|
-
}
|
|
20
|
-
function toDeterministicJson(o) {
|
|
21
|
-
// https://github.com/kikobeats/json-stringify-deterministic
|
|
22
|
-
// https://stackoverflow.com/a/54902696/1870054
|
|
23
|
-
// https://github.com/sinclairzx81/typebox#hash
|
|
24
|
-
// https://github.com/sinclairzx81/typebox/blob/master/src/value/hash.ts
|
|
25
|
-
// LCS longest common subsequence
|
|
26
|
-
// https://github.com/sinclairzx81/typebox/issues/272
|
|
27
|
-
let sorted = sortObjectKeys(o);
|
|
28
|
-
let out = JSON.stringify(sorted, function(_, v) {
|
|
29
|
-
return v === undefined ? 'undef' : v;
|
|
30
|
-
});
|
|
31
|
-
// Remove all whitespace
|
|
32
|
-
return out.replace(/\s+/g, '');
|
|
33
|
-
}
|
|
34
|
-
function visit(o, _v, ctx) {
|
|
35
|
-
const v = {
|
|
36
|
-
array: (o, ctx)=>o.map((x)=>v.visit(x, ctx)),
|
|
37
|
-
object: (o, ctx)=>{
|
|
38
|
-
return Object.fromEntries(Object.entries(o).map(([k, v])=>[
|
|
39
|
-
k,
|
|
40
|
-
v.visit(v, ctx)
|
|
41
|
-
]));
|
|
42
|
-
},
|
|
43
|
-
buffer: (o)=>{
|
|
44
|
-
return o;
|
|
45
|
-
},
|
|
46
|
-
boolean: (o)=>o,
|
|
47
|
-
number: (o)=>o,
|
|
48
|
-
string: (o)=>o,
|
|
49
|
-
symbol: (o)=>o,
|
|
50
|
-
bigint: (o)=>o,
|
|
51
|
-
date: (o)=>o,
|
|
52
|
-
null: (o)=>o,
|
|
53
|
-
undefined: (o)=>o,
|
|
54
|
-
unknown: (o, ctx)=>{
|
|
55
|
-
if (o instanceof Map) {
|
|
56
|
-
return new Map([
|
|
57
|
-
...o.entries()
|
|
58
|
-
].map(([k, v])=>[
|
|
59
|
-
k,
|
|
60
|
-
v.visit(v, ctx)
|
|
61
|
-
]));
|
|
62
|
-
}
|
|
63
|
-
if (o instanceof Set) {
|
|
64
|
-
return new Set([
|
|
65
|
-
...o.values()
|
|
66
|
-
].map((v)=>v.visit(v, ctx)));
|
|
67
|
-
}
|
|
68
|
-
return o;
|
|
69
|
-
},
|
|
70
|
-
visit: (o, ctx)=>{
|
|
71
|
-
if (o === null) {
|
|
72
|
-
return v.null(o, ctx);
|
|
73
|
-
}
|
|
74
|
-
switch(typeof o){
|
|
75
|
-
case 'object':
|
|
76
|
-
if (o instanceof ArrayBuffer) {
|
|
77
|
-
return v.buffer(o, ctx);
|
|
78
|
-
}
|
|
79
|
-
if (Array.isArray(o)) {
|
|
80
|
-
return v.array(o, ctx);
|
|
81
|
-
}
|
|
82
|
-
if (o instanceof Date) {
|
|
83
|
-
return v.date(o, ctx);
|
|
84
|
-
}
|
|
85
|
-
// plain object
|
|
86
|
-
if (o.constructor === Object) {
|
|
87
|
-
return v.object(o, ctx);
|
|
88
|
-
}
|
|
89
|
-
//
|
|
90
|
-
return v.unknown(o, ctx);
|
|
91
|
-
case 'boolean':
|
|
92
|
-
return v.boolean(o, ctx);
|
|
93
|
-
case 'number':
|
|
94
|
-
return v.number(o, ctx);
|
|
95
|
-
case 'string':
|
|
96
|
-
return v.string(o, ctx);
|
|
97
|
-
case 'symbol':
|
|
98
|
-
return v.symbol(o, ctx);
|
|
99
|
-
case 'bigint':
|
|
100
|
-
return v.bigint(o, ctx);
|
|
101
|
-
case 'undefined':
|
|
102
|
-
return v.undefined(o, ctx);
|
|
103
|
-
default:
|
|
104
|
-
return v.unknown(o, ctx);
|
|
105
|
-
}
|
|
106
|
-
},
|
|
107
|
-
..._v
|
|
108
|
-
};
|
|
109
|
-
return v.visit(o, ctx);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
//# sourceMappingURL=hashCode.ignored.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/langs/hashCode.ignored.ts"],"sourcesContent":["function sortObjectKeys(obj?: Record<string, any>) {\n if (obj === null || obj === undefined) {\n return obj;\n }\n if (typeof obj !== 'object') {\n // it is a primitive: number/string (in an array)\n return obj;\n }\n return Object.keys(obj)\n .sort()\n .reduce(\n (acc, key) => {\n if (Array.isArray(obj[key])) {\n acc[key] = obj[key].map(sortObjectKeys);\n } else if (typeof obj[key] === 'object') {\n acc[key] = sortObjectKeys(obj[key]);\n } else {\n acc[key] = obj[key];\n }\n return acc;\n },\n {} as Record<string, any>,\n );\n}\n\nfunction toDeterministicJson(o: any) {\n // https://github.com/kikobeats/json-stringify-deterministic\n // https://stackoverflow.com/a/54902696/1870054\n // https://github.com/sinclairzx81/typebox#hash\n // https://github.com/sinclairzx81/typebox/blob/master/src/value/hash.ts\n // LCS longest common subsequence\n // https://github.com/sinclairzx81/typebox/issues/272\n let sorted: any = sortObjectKeys(o);\n let out = JSON.stringify(sorted, function (_, v) {\n return v === undefined ? 'undef' : v;\n });\n\n // Remove all whitespace\n return out.replace(/\\s+/g, '');\n}\n\ninterface Visitor<C> {\n array: (o: any[], ctx: C) => any;\n object: (o: Record<string, any>, ctx: C) => any;\n boolean: (o: boolean, ctx: C) => any;\n number: (o: number, ctx: C) => any;\n string: (o: string, ctx: C) => any;\n symbol: (o: symbol, ctx: C) => any;\n bigint: (o: bigint, ctx: C) => any;\n date: (o: Date, ctx: C) => any;\n buffer: (o: ArrayBuffer, ctx: C) => any;\n null: (o: null, ctx: C) => any;\n undefined: (o: undefined, ctx: C) => any;\n unknown: (o: unknown, ctx: C) => any;\n visit: (o: any, ctx: C) => any;\n}\n\nfunction visit<C>(o: any, _v: Partial<Visitor<C>>, ctx: C) {\n const v = {\n array: (o: any[], ctx: C): any => o.map((x) => v.visit(x, ctx)),\n object: (o: Record<string, any>, ctx: C) => {\n return Object.fromEntries(Object.entries(o).map(([k, v]) => [k, v.visit(v, ctx)]));\n },\n buffer: (o: ArrayBuffer) => {\n return o;\n },\n boolean: (o: boolean) => o,\n number: (o: number) => o,\n string: (o: string) => o,\n symbol: (o: symbol) => o,\n bigint: (o: bigint) => o,\n date: (o: Date) => o,\n null: (o: null) => o,\n undefined: (o: undefined) => o,\n unknown: (o: unknown, ctx: C): any => {\n if (o instanceof Map) {\n return new Map([...o.entries()].map(([k, v]) => [k, v.visit(v, ctx)]));\n }\n if (o instanceof Set) {\n return new Set([...o.values()].map((v) => v.visit(v, ctx)));\n }\n return o;\n },\n visit: (o: any, ctx: C): any => {\n if (o === null) {\n return v.null(o, ctx);\n }\n switch (typeof o) {\n case 'object':\n if (o instanceof ArrayBuffer) {\n return v.buffer(o, ctx);\n }\n if (Array.isArray(o)) {\n return v.array(o, ctx);\n }\n if (o instanceof Date) {\n return v.date(o, ctx);\n }\n // plain object\n if (o.constructor === Object) {\n return v.object(o, ctx);\n }\n //\n return v.unknown(o, ctx);\n case 'boolean':\n return v.boolean(o, ctx);\n case 'number':\n return v.number(o, ctx);\n case 'string':\n return v.string(o, ctx);\n case 'symbol':\n return v.symbol(o, ctx);\n case 'bigint':\n return v.bigint(o, ctx);\n case 'undefined':\n return v.undefined(o, ctx);\n default:\n return v.unknown(o, ctx);\n }\n },\n ..._v,\n };\n\n return v.visit(o, ctx);\n}\n"],"names":["sortObjectKeys","obj","undefined","Object","keys","sort","reduce","acc","key","Array","isArray","map","toDeterministicJson","o","sorted","out","JSON","stringify","_","v","replace","visit","_v","ctx","array","x","object","fromEntries","entries","k","buffer","boolean","number","string","symbol","bigint","date","null","unknown","Map","Set","values","ArrayBuffer","Date","constructor"],"mappings":"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"}
|