@wener/common 2.0.1 → 2.0.2
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/cn/ChineseResidentIdNo.js +41 -0
- package/lib/cn/ChineseResidentIdNo.mod.js +1 -0
- package/lib/cn/{ResidentIdentityCardNumber.test.js → ChineseResidentIdNo.test.js} +7 -6
- package/lib/cn/DivisionCode.js +211 -300
- package/lib/cn/DivisionCode.mod.js +1 -0
- package/lib/cn/DivisionCode.test.js +9 -15
- package/lib/cn/{Mod11Checksum.js → Mod11.js} +1 -0
- package/lib/cn/{Mod31Checksum.js → Mod31.js} +1 -0
- package/lib/cn/UnifiedSocialCreditCode.js +130 -115
- package/lib/cn/UnifiedSocialCreditCode.mod.js +1 -0
- package/lib/cn/UnifiedSocialCreditCode.test.js +1 -1
- package/lib/cn/index.js +1 -3
- package/lib/cn/mod.js +6 -0
- package/lib/consola/formatLogObject.js +18 -6
- package/lib/dayjs/dayjs.js +38 -0
- package/lib/dayjs/formatDuration.js +58 -0
- package/lib/dayjs/formatDuration.test.js +90 -0
- package/lib/dayjs/index.js +3 -0
- package/lib/dayjs/parseDuration.js +32 -0
- package/lib/decimal/index.js +1 -0
- package/lib/decimal/parseDecimal.js +13 -0
- package/lib/{resource → foundation}/schema/SexType.js +5 -1
- package/lib/foundation/schema/index.js +1 -0
- package/lib/foundation/schema/parseSexType.js +18 -0
- package/lib/foundation/schema/types.js +5 -0
- package/lib/password/Password.js +10 -7
- package/lib/resource/ListQuery.js +119 -0
- package/lib/resource/index.js +1 -0
- package/lib/resource/schema/AnyResourceSchema.js +1 -1
- package/lib/resource/schema/index.js +5 -0
- package/lib/{resource/schema → schema}/SchemaRegistry.js +12 -5
- package/lib/schema/SchemaRegistry.mod.js +2 -0
- package/lib/schema/createSchemaData.js +1 -1
- package/lib/schema/getSchemaOptions.js +2 -2
- package/lib/schema/index.js +1 -0
- package/lib/utils/getEstimateProcessTime.js +20 -0
- package/lib/utils/index.js +1 -0
- package/package.json +23 -14
- package/src/cn/ChineseResidentIdNo.mod.ts +7 -0
- package/src/cn/ChineseResidentIdNo.test.ts +18 -0
- package/src/cn/ChineseResidentIdNo.ts +66 -0
- package/src/cn/DivisionCode.mod.ts +7 -0
- package/src/cn/DivisionCode.test.ts +3 -13
- package/src/cn/DivisionCode.ts +132 -195
- package/src/cn/{Mod11Checksum.ts → Mod11.ts} +3 -1
- package/src/cn/{Mod31Checksum.ts → Mod31.ts} +2 -0
- package/src/cn/UnifiedSocialCreditCode.mod.ts +7 -0
- package/src/cn/UnifiedSocialCreditCode.test.ts +2 -2
- package/src/cn/UnifiedSocialCreditCode.ts +105 -125
- package/src/cn/__snapshots__/ChineseResidentIdNo.test.ts.snap +14 -0
- package/src/cn/__snapshots__/UnifiedSocialCreditCode.test.ts.snap +18 -12
- package/src/cn/index.ts +1 -3
- package/src/cn/mod.ts +3 -0
- package/src/consola/formatLogObject.ts +12 -4
- package/src/dayjs/dayjs.ts +40 -0
- package/src/dayjs/formatDuration.test.ts +14 -0
- package/src/dayjs/formatDuration.ts +86 -0
- package/src/dayjs/index.ts +3 -0
- package/src/dayjs/parseDuration.ts +40 -0
- package/src/decimal/index.ts +1 -0
- package/src/decimal/parseDecimal.ts +16 -0
- package/src/foundation/schema/SexType.ts +21 -0
- package/src/foundation/schema/index.ts +1 -0
- package/src/foundation/schema/parseSexType.ts +19 -0
- package/src/foundation/schema/types.ts +8 -0
- package/src/password/Password.ts +2 -2
- package/src/resource/ListQuery.ts +53 -0
- package/src/resource/index.ts +1 -0
- package/src/resource/schema/AnyResourceSchema.ts +1 -1
- package/src/resource/schema/index.ts +5 -0
- package/src/schema/SchemaRegistry.mod.ts +1 -0
- package/src/{resource/schema → schema}/SchemaRegistry.ts +12 -8
- package/src/schema/createSchemaData.ts +1 -1
- package/src/schema/getSchemaOptions.ts +2 -2
- package/src/schema/index.ts +1 -0
- package/src/utils/getEstimateProcessTime.ts +36 -0
- package/src/utils/index.ts +1 -0
- package/lib/cn/ResidentIdentityCardNumber.js +0 -50
- package/lib/cn/formatDate.js +0 -13
- package/lib/cn/parseSex.js +0 -20
- package/lib/search/AdvanceSearch.js +0 -9
- package/lib/search/AdvanceSearch.test.js +0 -435
- package/lib/search/formatAdvanceSearch.js +0 -78
- package/lib/search/index.js +0 -1
- package/lib/search/optimizeAdvanceSearch.js +0 -143
- package/lib/search/parseAdvanceSearch.js +0 -20
- package/lib/search/parser.d.js +0 -1
- package/lib/search/parser.js +0 -3088
- package/lib/search/types.d.js +0 -1
- package/src/cn/ResidentIdentityCardNumber.test.ts +0 -17
- package/src/cn/ResidentIdentityCardNumber.ts +0 -96
- package/src/cn/__snapshots__/ResidentIdentityCardNumber.test.ts.snap +0 -15
- package/src/cn/formatDate.ts +0 -12
- package/src/cn/parseSex.ts +0 -13
- package/src/resource/schema/SexType.ts +0 -13
- package/src/search/AdvanceSearch.test.ts +0 -149
- package/src/search/AdvanceSearch.ts +0 -14
- package/src/search/Makefile +0 -2
- package/src/search/__snapshots__/AdvanceSearch.test.ts.snap +0 -675
- package/src/search/formatAdvanceSearch.ts +0 -52
- package/src/search/index.ts +0 -1
- package/src/search/optimizeAdvanceSearch.ts +0 -77
- package/src/search/parseAdvanceSearch.ts +0 -23
- package/src/search/parser.d.ts +0 -8
- package/src/search/parser.js +0 -2794
- package/src/search/parser.peggy +0 -237
- package/src/search/types.d.ts +0 -45
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
function _array_like_to_array(arr, len) {
|
|
2
|
+
if (len == null || len > arr.length) len = arr.length;
|
|
3
|
+
for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
|
|
4
|
+
return arr2;
|
|
5
|
+
}
|
|
6
|
+
function _array_without_holes(arr) {
|
|
7
|
+
if (Array.isArray(arr)) return _array_like_to_array(arr);
|
|
8
|
+
}
|
|
9
|
+
function _define_property(obj, key, value) {
|
|
10
|
+
if (key in obj) {
|
|
11
|
+
Object.defineProperty(obj, key, {
|
|
12
|
+
value: value,
|
|
13
|
+
enumerable: true,
|
|
14
|
+
configurable: true,
|
|
15
|
+
writable: true
|
|
16
|
+
});
|
|
17
|
+
} else {
|
|
18
|
+
obj[key] = value;
|
|
19
|
+
}
|
|
20
|
+
return obj;
|
|
21
|
+
}
|
|
22
|
+
function _iterable_to_array(iter) {
|
|
23
|
+
if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
|
|
24
|
+
}
|
|
25
|
+
function _non_iterable_spread() {
|
|
26
|
+
throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
27
|
+
}
|
|
28
|
+
function _object_spread(target) {
|
|
29
|
+
for(var i = 1; i < arguments.length; i++){
|
|
30
|
+
var source = arguments[i] != null ? arguments[i] : {};
|
|
31
|
+
var ownKeys = Object.keys(source);
|
|
32
|
+
if (typeof Object.getOwnPropertySymbols === "function") {
|
|
33
|
+
ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
|
|
34
|
+
return Object.getOwnPropertyDescriptor(source, sym).enumerable;
|
|
35
|
+
}));
|
|
36
|
+
}
|
|
37
|
+
ownKeys.forEach(function(key) {
|
|
38
|
+
_define_property(target, key, source[key]);
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
return target;
|
|
42
|
+
}
|
|
43
|
+
function ownKeys(object, enumerableOnly) {
|
|
44
|
+
var keys = Object.keys(object);
|
|
45
|
+
if (Object.getOwnPropertySymbols) {
|
|
46
|
+
var symbols = Object.getOwnPropertySymbols(object);
|
|
47
|
+
if (enumerableOnly) {
|
|
48
|
+
symbols = symbols.filter(function(sym) {
|
|
49
|
+
return Object.getOwnPropertyDescriptor(object, sym).enumerable;
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
keys.push.apply(keys, symbols);
|
|
53
|
+
}
|
|
54
|
+
return keys;
|
|
55
|
+
}
|
|
56
|
+
function _object_spread_props(target, source) {
|
|
57
|
+
source = source != null ? source : {};
|
|
58
|
+
if (Object.getOwnPropertyDescriptors) {
|
|
59
|
+
Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
|
|
60
|
+
} else {
|
|
61
|
+
ownKeys(Object(source)).forEach(function(key) {
|
|
62
|
+
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
return target;
|
|
66
|
+
}
|
|
67
|
+
function _to_consumable_array(arr) {
|
|
68
|
+
return _array_without_holes(arr) || _iterable_to_array(arr) || _unsupported_iterable_to_array(arr) || _non_iterable_spread();
|
|
69
|
+
}
|
|
70
|
+
function _unsupported_iterable_to_array(o, minLen) {
|
|
71
|
+
if (!o) return;
|
|
72
|
+
if (typeof o === "string") return _array_like_to_array(o, minLen);
|
|
73
|
+
var n = Object.prototype.toString.call(o).slice(8, -1);
|
|
74
|
+
if (n === "Object" && o.constructor) n = o.constructor.name;
|
|
75
|
+
if (n === "Map" || n === "Set") return Array.from(n);
|
|
76
|
+
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
|
|
77
|
+
}
|
|
78
|
+
import { z } from 'zod/v4';
|
|
79
|
+
var IntLikeSchema = z.coerce.number().multipleOf(1).min(0).optional().overwrite(function(v) {
|
|
80
|
+
return v || undefined;
|
|
81
|
+
});
|
|
82
|
+
export var ListQuerySchema = z.object({
|
|
83
|
+
id: z.coerce.string().optional(),
|
|
84
|
+
ids: z.array(z.coerce.string()).optional(),
|
|
85
|
+
filter: z.string().optional().describe('sql-like filter string'),
|
|
86
|
+
filters: z.array(z.any()).optional().describe('sql-like filter string'),
|
|
87
|
+
where: z.record(z.string(), z.any()).optional().describe('document query filter'),
|
|
88
|
+
search: z.string().optional(),
|
|
89
|
+
limit: IntLikeSchema,
|
|
90
|
+
offset: IntLikeSchema,
|
|
91
|
+
order: z.array(z.string()).optional().describe('order like "a,-b,c desc null last"'),
|
|
92
|
+
pageIndex: IntLikeSchema.describe('0-based page index'),
|
|
93
|
+
pageNumber: IntLikeSchema.describe('1-based page number'),
|
|
94
|
+
pageSize: IntLikeSchema,
|
|
95
|
+
cursor: z.string().optional(),
|
|
96
|
+
deleted: z.coerce.boolean().optional()
|
|
97
|
+
});
|
|
98
|
+
export function resolveListQuery(target) {
|
|
99
|
+
for(var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++){
|
|
100
|
+
args[_key - 1] = arguments[_key];
|
|
101
|
+
}
|
|
102
|
+
var out = args.reduce(function(a, source) {
|
|
103
|
+
if (typeof source === 'function') {
|
|
104
|
+
var result = source(a);
|
|
105
|
+
// do not use the result as merge source
|
|
106
|
+
return result || a;
|
|
107
|
+
}
|
|
108
|
+
var b = source;
|
|
109
|
+
if (!b) return a;
|
|
110
|
+
// do not resolve id to ids
|
|
111
|
+
var ids = _to_consumable_array(a.ids || []).concat(_to_consumable_array(b.ids || []));
|
|
112
|
+
return _object_spread_props(_object_spread({}, a, b), {
|
|
113
|
+
ids: ids,
|
|
114
|
+
filters: _to_consumable_array(a.filters || []).concat(_to_consumable_array(b.filters || [])),
|
|
115
|
+
search: b.search || a.search
|
|
116
|
+
});
|
|
117
|
+
}, target || {});
|
|
118
|
+
return ListQuerySchema.parse(out);
|
|
119
|
+
}
|
package/lib/resource/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from "zod/v4";
|
|
2
|
-
import { SexTypeSchema } from "
|
|
2
|
+
import { SexTypeSchema } from "../../foundation/schema/SexType.js";
|
|
3
3
|
import { rz } from "./types.js";
|
|
4
4
|
export var AnyResourceSchema = z.object({
|
|
5
5
|
id: rz.resourceId.readonly().describe("ID"),
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { ResourceStatus, ResourceStatusSchema } from "./ResourceStatus.js";
|
|
2
|
+
export { ResourceActionType, ResourceActionTypeSchema, ResourceActionDataSchema } from "./ResourceActionType.js";
|
|
3
|
+
export { AnyResourceSchema } from "./AnyResourceSchema.js";
|
|
4
|
+
export { rz } from "./types.js";
|
|
5
|
+
export { BaseResourceSchema } from "./BaseResourceSchema.js";
|
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
function _type_of(obj) {
|
|
2
|
+
"@swc/helpers - typeof";
|
|
3
|
+
return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj;
|
|
4
|
+
}
|
|
1
5
|
import { getGlobalStates } from "@wener/utils";
|
|
2
|
-
import { toJsonSchema } from "
|
|
6
|
+
import { toJsonSchema } from "./index.js";
|
|
3
7
|
var types = getGlobalStates("@wener/common/resource/schema/SchemaRegistry", function () {
|
|
4
8
|
return new Map();
|
|
5
9
|
});
|
|
@@ -10,7 +14,7 @@ export function get(needle) {
|
|
|
10
14
|
return found;
|
|
11
15
|
}
|
|
12
16
|
else {
|
|
13
|
-
if (typeof needle !== "string") {
|
|
17
|
+
if (needle && typeof needle !== "string") {
|
|
14
18
|
return toJsonSchema(needle);
|
|
15
19
|
}
|
|
16
20
|
}
|
|
@@ -30,9 +34,12 @@ function getKey(s) {
|
|
|
30
34
|
}
|
|
31
35
|
return key;
|
|
32
36
|
}
|
|
33
|
-
export function add(def) {
|
|
34
|
-
types.set(getKey(def), toJsonSchema(def));
|
|
35
|
-
}
|
|
36
37
|
export function set(key, def) {
|
|
38
|
+
if (!def) {
|
|
39
|
+
def = key;
|
|
40
|
+
if (!def || (typeof def === "undefined" ? "undefined" : _type_of(def)) !== "object") {
|
|
41
|
+
throw new Error("Invalid schema definition for: ".concat(getKey(key)));
|
|
42
|
+
}
|
|
43
|
+
}
|
|
37
44
|
types.set(getKey(key), toJsonSchema(def));
|
|
38
45
|
}
|
|
@@ -124,7 +124,7 @@ function _create(schema, options, ctx) {
|
|
|
124
124
|
type: "object"
|
|
125
125
|
}, function () {
|
|
126
126
|
var out = {};
|
|
127
|
-
var required = schema.required
|
|
127
|
+
var required = Array.isArray(schema.required) ? schema.required : [];
|
|
128
128
|
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
129
129
|
try {
|
|
130
130
|
for (var _iterator = Object.entries(schema.properties || {})[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { deepFreeze } from "@wener/utils";
|
|
2
2
|
import { getSchemaCache } from "./getSchemaCache.js";
|
|
3
|
-
import {
|
|
3
|
+
import { SchemaRegistry } from "./SchemaRegistry.mod.js";
|
|
4
4
|
export function getSchemaOptions(s) {
|
|
5
|
-
var js =
|
|
5
|
+
var js = SchemaRegistry.get(s);
|
|
6
6
|
return getSchemaCache(s, "options", function () {
|
|
7
7
|
var _this;
|
|
8
8
|
var out = ((_this = js.anyOf || js.oneOf) === null || _this === void 0 ? void 0 : _this.map(function (v) {
|
package/lib/schema/index.js
CHANGED
|
@@ -3,3 +3,4 @@ export { getSchemaOptions, getSchemaOptionLabel } from "./getSchemaOptions.js";
|
|
|
3
3
|
export { toJsonSchema } from "./toJsonSchema.js";
|
|
4
4
|
export { findJsonSchemaByPath } from "./findJsonSchemaByPath.js";
|
|
5
5
|
export { createSchemaData } from "./createSchemaData.js";
|
|
6
|
+
export { SchemaRegistry } from "./SchemaRegistry.mod.js";
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export function getEstimateProcessTime(param) {
|
|
2
|
+
var total = param.total, processed = param.processed, startTime = param.startTime, _param_elapsed = param.elapsed, elapsed = _param_elapsed === void 0 ? startTime ? (Date.now() - startTime.getTime()) / 1000 : undefined : _param_elapsed;
|
|
3
|
+
if (typeof total !== 'number' || typeof processed !== 'number' || !elapsed || processed === 0 || processed >= total) {
|
|
4
|
+
return undefined;
|
|
5
|
+
}
|
|
6
|
+
var now = new Date();
|
|
7
|
+
var rate = processed / elapsed;
|
|
8
|
+
if (rate === 0) {
|
|
9
|
+
return undefined;
|
|
10
|
+
}
|
|
11
|
+
var remaining = total - processed;
|
|
12
|
+
var eta = Math.round(remaining / rate);
|
|
13
|
+
var endTime = new Date(now.getTime() + eta * 1000);
|
|
14
|
+
return {
|
|
15
|
+
eta: eta,
|
|
16
|
+
elapsed: elapsed,
|
|
17
|
+
endTime: endTime,
|
|
18
|
+
rate: rate
|
|
19
|
+
};
|
|
20
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { getEstimateProcessTime } from "./getEstimateProcessTime.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wener/common",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "",
|
|
6
6
|
"author": "",
|
|
@@ -22,6 +22,14 @@
|
|
|
22
22
|
"types": "./src/data/index.ts",
|
|
23
23
|
"default": "./lib/data/index.js"
|
|
24
24
|
},
|
|
25
|
+
"./dayjs": {
|
|
26
|
+
"types": "./src/dayjs/index.ts",
|
|
27
|
+
"default": "./lib/dayjs/index.js"
|
|
28
|
+
},
|
|
29
|
+
"./decimal": {
|
|
30
|
+
"types": "./src/decimal/index.ts",
|
|
31
|
+
"default": "./lib/decimal/index.js"
|
|
32
|
+
},
|
|
25
33
|
"./jsonschema": {
|
|
26
34
|
"types": "./src/jsonschema/index.ts",
|
|
27
35
|
"default": "./lib/jsonschema/index.js"
|
|
@@ -38,14 +46,14 @@
|
|
|
38
46
|
"types": "./src/resource/index.ts",
|
|
39
47
|
"default": "./lib/resource/index.js"
|
|
40
48
|
},
|
|
49
|
+
"./resource/schema": {
|
|
50
|
+
"types": "./src/resource/schema/index.ts",
|
|
51
|
+
"default": "./lib/resource/schema/index.js"
|
|
52
|
+
},
|
|
41
53
|
"./schema": {
|
|
42
54
|
"types": "./src/schema/index.ts",
|
|
43
55
|
"default": "./lib/schema/index.js"
|
|
44
56
|
},
|
|
45
|
-
"./search": {
|
|
46
|
-
"types": "./src/search/index.ts",
|
|
47
|
-
"default": "./lib/search/index.js"
|
|
48
|
-
},
|
|
49
57
|
"./package.json": "./package.json"
|
|
50
58
|
},
|
|
51
59
|
"files": [
|
|
@@ -62,27 +70,28 @@
|
|
|
62
70
|
"@standard-schema/spec": "^1.0.0",
|
|
63
71
|
"@wener/utils": "^1.1.51",
|
|
64
72
|
"date-fns": "^4.1.0",
|
|
65
|
-
"es-toolkit": "^1.
|
|
73
|
+
"es-toolkit": "^1.39.10",
|
|
66
74
|
"std-env": "^3.9.0",
|
|
67
|
-
"ts-pattern": "^5.
|
|
75
|
+
"ts-pattern": "^5.8.0"
|
|
68
76
|
},
|
|
69
77
|
"devDependencies": {
|
|
70
|
-
"@sinclair/typebox": "^0.34.
|
|
78
|
+
"@sinclair/typebox": "^0.34.41",
|
|
71
79
|
"@sinclair/typebox-codegen": "^0.11.1",
|
|
72
80
|
"@types/argon2-browser": "^1.18.4",
|
|
73
|
-
"@types/bcrypt": "^
|
|
81
|
+
"@types/bcrypt": "^6.0.0",
|
|
74
82
|
"ajv": "^8.17.1",
|
|
75
83
|
"ajv-formats": "^3.0.1",
|
|
76
84
|
"ajv-i18n": "^4.2.0",
|
|
77
85
|
"ajv-keywords": "^5.1.0",
|
|
78
|
-
"argon2": "^0.
|
|
86
|
+
"argon2": "^0.44.0",
|
|
79
87
|
"argon2-browser": "^1.18.0",
|
|
80
|
-
"bcrypt": "^
|
|
88
|
+
"bcrypt": "^6.0.0",
|
|
81
89
|
"bcryptjs": "^3.0.2",
|
|
82
|
-
"chalk": "^5.
|
|
90
|
+
"chalk": "^5.6.2",
|
|
83
91
|
"consola": "^3.4.2",
|
|
84
|
-
"dayjs": "^1.11.
|
|
85
|
-
"
|
|
92
|
+
"dayjs": "^1.11.18",
|
|
93
|
+
"decimal.js": "^10.6.0",
|
|
94
|
+
"zod": "^4.1.8"
|
|
86
95
|
},
|
|
87
96
|
"scripts": {
|
|
88
97
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { ChineseResidentIdNo } from './mod';
|
|
3
|
+
|
|
4
|
+
describe('ChineseResidentIdNo', () => {
|
|
5
|
+
it('should parse', () => {
|
|
6
|
+
for (const a of ['11010519491231002X']) {
|
|
7
|
+
let out = ChineseResidentIdNo.parse(a);
|
|
8
|
+
expect(out).toBeTruthy();
|
|
9
|
+
expect(ChineseResidentIdNo.format(out!)).toBe(a);
|
|
10
|
+
expect(out).toMatchSnapshot();
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
it('should format with partial', () => {
|
|
14
|
+
expect(ChineseResidentIdNo.format({ addressCode: '110105', birthDate: new Date('1949-12-31'), sequence: 2 })).toBe(
|
|
15
|
+
'11010519491231002X',
|
|
16
|
+
);
|
|
17
|
+
});
|
|
18
|
+
});
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { z } from 'zod/v4';
|
|
2
|
+
import { SexType, SexTypeSchema } from '../foundation/schema';
|
|
3
|
+
import { Mod11 } from './Mod11';
|
|
4
|
+
|
|
5
|
+
export const ChineseResidentIdNoRegex =
|
|
6
|
+
/^(?<division>[1-9]\d{5})(?<year>(18|19|20)\d{2})(?<month>0[1-9]|1[0-2])(?<day>0[1-9]|[12]\d|3[01])(?<sequence>\d{3})(?<checkDigit>[0-9Xx])$/;
|
|
7
|
+
|
|
8
|
+
export type ParsedChineseResidentIdNo = z.infer<typeof ParsedChineseResidentIdNoSchema>;
|
|
9
|
+
export const ParsedChineseResidentIdNoSchema = z
|
|
10
|
+
.object({
|
|
11
|
+
raw: z.string().regex(ChineseResidentIdNoRegex, '无效的18位身份证号码格式').describe('身份证号码'),
|
|
12
|
+
addressCode: z.string().length(6).describe('地址码 '),
|
|
13
|
+
birthDate: z.iso.date().describe('出生日期'),
|
|
14
|
+
sequence: z.int().max(999).min(0).describe('顺序码'),
|
|
15
|
+
checkDigit: z.int().min(0).max(10).describe('校验码'),
|
|
16
|
+
sex: SexTypeSchema.describe('性别'),
|
|
17
|
+
age: z.number().optional(),
|
|
18
|
+
valid: z.boolean().optional().describe('是否有效'),
|
|
19
|
+
})
|
|
20
|
+
.describe('居民身份证号码解析内容');
|
|
21
|
+
|
|
22
|
+
export function parseChineseResidentIdNo(idNo: string): ParsedChineseResidentIdNo | undefined {
|
|
23
|
+
const reg = ChineseResidentIdNoRegex;
|
|
24
|
+
const match = idNo.match(reg);
|
|
25
|
+
if (!match || !match.groups) {
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
const { division, year, month, day, sequence, checkDigit } = match.groups;
|
|
29
|
+
let seq = parseInt(sequence, 10);
|
|
30
|
+
return {
|
|
31
|
+
raw: idNo,
|
|
32
|
+
addressCode: division,
|
|
33
|
+
birthDate: `${year}-${month}-${day}`,
|
|
34
|
+
sequence: seq,
|
|
35
|
+
checkDigit: checkDigit.toUpperCase() === 'X' ? 10 : parseInt(checkDigit),
|
|
36
|
+
sex: seq % 2 === 0 ? SexType.Male : SexType.Female,
|
|
37
|
+
age: new Date().getFullYear() - parseInt(year, 10),
|
|
38
|
+
valid: Mod11.validate(idNo),
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function formatChineseResidentIdNo({
|
|
43
|
+
addressCode,
|
|
44
|
+
birthDate,
|
|
45
|
+
sequence,
|
|
46
|
+
checkDigit,
|
|
47
|
+
}: {
|
|
48
|
+
addressCode: string;
|
|
49
|
+
birthDate: string | Date;
|
|
50
|
+
sequence: number | string;
|
|
51
|
+
checkDigit?: string | number;
|
|
52
|
+
}): string {
|
|
53
|
+
const date =
|
|
54
|
+
typeof birthDate === 'string'
|
|
55
|
+
? birthDate.replace(/-/g, '')
|
|
56
|
+
: `${birthDate.getFullYear()}${String(birthDate.getMonth() + 1).padStart(2, '0')}${String(birthDate.getDate()).padStart(2, '0')}`;
|
|
57
|
+
const seq = String(sequence).padStart(3, '0');
|
|
58
|
+
const major = `${addressCode}${date}${seq}`;
|
|
59
|
+
const check =
|
|
60
|
+
typeof checkDigit === 'number'
|
|
61
|
+
? checkDigit === 10
|
|
62
|
+
? 'X'
|
|
63
|
+
: String(checkDigit)
|
|
64
|
+
: checkDigit?.toUpperCase() || Mod11.compute(major);
|
|
65
|
+
return `${major}${check}`;
|
|
66
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import { DivisionCode } from './
|
|
2
|
+
import { DivisionCode } from './mod';
|
|
3
3
|
|
|
4
4
|
describe('DivisionCode', () => {
|
|
5
5
|
it('should parse', () => {
|
|
@@ -7,27 +7,17 @@ describe('DivisionCode', () => {
|
|
|
7
7
|
[
|
|
8
8
|
'441900003001',
|
|
9
9
|
{
|
|
10
|
-
province: '44',
|
|
11
|
-
city: '19',
|
|
12
|
-
county: '00',
|
|
13
|
-
town: '003',
|
|
14
|
-
village: '001',
|
|
15
10
|
codes: ['44', '19', '00', '003', '001'],
|
|
16
11
|
},
|
|
17
12
|
],
|
|
18
13
|
[
|
|
19
14
|
441900003001,
|
|
20
15
|
{
|
|
21
|
-
province: '44',
|
|
22
|
-
city: '19',
|
|
23
|
-
county: '00',
|
|
24
|
-
town: '003',
|
|
25
|
-
village: '001',
|
|
26
16
|
codes: ['44', '19', '00', '003', '001'],
|
|
27
17
|
},
|
|
28
18
|
],
|
|
29
|
-
[441900, {
|
|
30
|
-
['31', {
|
|
19
|
+
[441900, { codes: ['44', '19', '00'] }],
|
|
20
|
+
['31', { codes: ['31'] }],
|
|
31
21
|
['4', undefined],
|
|
32
22
|
['', undefined],
|
|
33
23
|
[null, undefined],
|