xjs-common 12.0.0-alpha.2 → 13.0.0-alpha.1

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/README.md CHANGED
@@ -27,6 +27,7 @@ import { delay, int2array, UHttp, retry, MaybeArray, Loggable } from "xjs-common
27
27
  retry(async () => { }, { count: 2 });
28
28
 
29
29
  // utility types
30
+ let dateCtor: Ctor = Date; // constructor type like class type.
30
31
  let maybeArray: MaybeArray<number> = 0; // also number array is applicable.
31
32
  let logger: Loggable = console; // object implements log/warn/error is applicable.
32
33
 
@@ -124,18 +125,8 @@ this flag is true by default at the target higher than `ES2022`, [here is for mo
124
125
  ```ts
125
126
  import { Type, DType, UType, UObj } from "xjs-common";
126
127
 
127
- class Cls_A {
128
- @DType.required
129
- @DType.number
130
- id: number;
131
- @DType.string
132
- strA: string;
133
- @DType.recursive
134
- objA: Cls_B;
135
- p: number;
136
- constructor() { }
137
- }
138
- class Cls_B {
128
+ interface If_B { aryB: number[], boolB: boolean, q: number }
129
+ class Cls_B implements If_B {
139
130
  @DType.array({ t: Type.number })
140
131
  aryB: number[];
141
132
  @DType.boolean
@@ -143,37 +134,51 @@ class Cls_B {
143
134
  q: number;
144
135
  constructor() { }
145
136
  }
137
+ interface If_A { id: number, strA: string, objA: If_B, p: number }
138
+ class Cls_A implements If_A {
139
+ @DType.required
140
+ @DType.number
141
+ id: number;
142
+ @DType.string
143
+ strA: string;
144
+ @DType.recursive(Cls_B)
145
+ objA: If_B;
146
+ p: number;
147
+ constructor(substance?: If_A) { Object.assign(this, substance); }
148
+ }
146
149
  (() => {
147
- const valid_b1 = Object.assign(new Cls_B(), { aryB: [1, 2, 3], boolB: true, q: 1 });
148
- const valid1 = Object.assign(new Cls_A(), { id: 1, strA: "a", objA: valid_b1, p: 1 });
150
+ const valid_b1: If_B = { aryB: [1, 2, 3], boolB: true, q: 1 };
151
+ const valid_a1: If_A = { id: 1, strA: "a", objA: valid_b1, p: 1 };
149
152
 
150
153
  // remove non decorated fields.
151
- const cropped = UObj.crop(valid1);
152
- console.log(!!cropped.id && !cropped.p && !!cropped.objA.aryB && !cropped.objA.q) // true;
154
+ const cropped = UObj.crop(valid_a1, Cls_A);
155
+ console.log(!!cropped.id && !cropped.p); // true;
156
+ console.log(!!cropped.objA.aryB && !cropped.objA.q); // true
153
157
 
154
- // validation. below are valid cases.
155
- console.log(UType.validate(valid1)); // []
158
+ // passing class object instead of ctor is allowed.
159
+ UObj.crop(new Cls_A(valid_a1));
156
160
 
157
- const valid2 = { id: 0 };
158
- console.log(UType.validate(Object.assign(new Cls_A(), valid2))); // []
161
+ // validation. below are valid cases.
162
+ console.log(UType.validate({ id: 0 }, Cls_A)); // []
163
+ console.log(UType.validate(valid_a1, Cls_A)); // []
159
164
 
160
165
  // validation. below are invalid cases.
161
166
  const invalid1 = {};
162
- console.log(UType.validate(Object.assign(new Cls_A(), invalid1))); // [ 'id' ]
167
+ console.log(UType.validate(invalid1, Cls_A)); // [ 'id' ]
163
168
 
164
- const invalid3 = { id: 0, strA: [], objA: valid_b1 };
165
- console.log(UType.validate(Object.assign(new Cls_A(), invalid3))); // [ 'strA' ]
169
+ const invalid2 = { id: 0, strA: [], objA: valid_b1 };
170
+ console.log(UType.validate(invalid2, Cls_A)); // [ 'strA' ]
166
171
 
167
- const invalid4 = { id: "0", strA: "a", objA: valid_b1 };
168
- console.log(UType.validate(Object.assign(new Cls_A(), invalid4))); // [ 'id' ]
172
+ const invalid3 = { id: "0", strA: "a", objA: valid_b1 };
173
+ console.log(UType.validate(invalid3, Cls_A)); // [ 'id' ]
169
174
 
170
- const invalid_b1 = Object.assign(new Cls_B(), { aryB: [1, 2, 3], boolB: 1 });
171
- const invalid5 = { id: 0, strA: "a", objA: invalid_b1 };
172
- console.log(UType.validate(Object.assign(new Cls_A(), invalid5))); // [ 'objA.boolB' ]
175
+ const invalid_b1 = { aryB: [1, 2, 3], boolB: 1 };
176
+ const invalid4 = { id: 0, strA: "a", objA: invalid_b1 };
177
+ console.log(UType.validate(invalid4, Cls_A)); // [ 'objA.boolB' ]
173
178
 
174
- const invalid_b2 = Object.assign(new Cls_B(), { aryB: ["1"], boolB: true });
175
- const invalid6 = { id: 0, strA: "a", objA: invalid_b2 };
176
- console.log(UType.validate(Object.assign(new Cls_A(), invalid6))); // [ 'objA.aryB' ]
179
+ const invalid_b2 = { aryB: ["1"], boolB: true };
180
+ const invalid5 = { id: 0, strA: "a", objA: invalid_b2 };
181
+ console.log(UType.validate(invalid5, Cls_A)); // [ 'objA.aryB.0' ]
177
182
  })();
178
183
  ```
179
184
  # Error definition
@@ -1,3 +1,6 @@
1
+ export type Ctor<T = any> = {
2
+ new (): T;
3
+ };
1
4
  export type IndexSignature = string | number | symbol;
2
5
  export type NormalRecord<T = any> = Record<IndexSignature, T>;
3
6
  export type MaybeArray<T = any> = T | T[];
@@ -1,30 +1,12 @@
1
- import { Type } from "../../const/types";
1
+ import { Ctor, Type } from "../../const/types";
2
2
  export declare const smbl_tm: unique symbol;
3
- interface BasicTypeDesc {
3
+ export interface TypeDesc {
4
4
  t?: Type;
5
5
  req?: boolean;
6
- }
7
- export interface TypeDesc extends BasicTypeDesc {
8
6
  ary?: TypeDesc;
9
- rec?: boolean;
10
7
  rcd?: TypeDesc;
8
+ obj?: Ctor;
11
9
  }
12
- type ArrayTypeDesc = TypeDesc & {
13
- t?: never;
14
- rec?: never;
15
- rcd?: never;
16
- };
17
- type ClassTypeDesc = TypeDesc & {
18
- t?: never;
19
- ary?: never;
20
- rcd?: never;
21
- };
22
- type RecordTypeDesc = TypeDesc & {
23
- t?: never;
24
- arys?: never;
25
- rec?: never;
26
- };
27
- type AnyTypeDesc = BasicTypeDesc | ArrayTypeDesc | ClassTypeDesc | RecordTypeDesc;
28
10
  export interface TypeMap {
29
11
  [k: string]: TypeDesc;
30
12
  }
@@ -37,10 +19,9 @@ export declare namespace DType {
37
19
  function number(target: Object, propKey: string): void;
38
20
  function boolean(target: Object, propKey: string): void;
39
21
  function required(target: Object, propKey: string): void;
40
- function array(elmDesc?: AnyTypeDesc): (target: Object, propKey: string) => void;
22
+ function array(elmDesc?: TypeDesc | Ctor): (target: Object, propKey: string) => void;
41
23
  /** NOTE: this may allow array type because array is essentialy object type has properties. */
42
- function record(elmDesc?: AnyTypeDesc): (target: Object, propKey: string) => void;
43
- function recursive(target: Object, propKey: string): void;
24
+ function record(elmDesc?: TypeDesc | Ctor): (target: Object, propKey: string) => void;
25
+ function recursive(ctor: Ctor): (target: Object, propKey: string) => void;
44
26
  function keep(target: Object, propKey: string): void;
45
27
  }
46
- export {};
@@ -1,5 +1,6 @@
1
1
  import { Type } from "../../const/types";
2
2
  import { XjsErr } from "../../obj/xjs-err";
3
+ import { UType } from "../u-type";
3
4
  const s_errCode = 30;
4
5
  export const smbl_tm = Symbol.for("xjs:typeMap");
5
6
  /**
@@ -32,16 +33,16 @@ export var DType;
32
33
  }
33
34
  DType.required = required;
34
35
  function array(elmDesc = {}) {
35
- return (target, propKey) => setDesc(target, propKey, (td) => td.ary = elmDesc);
36
+ return (target, propKey) => setDesc(target, propKey, (td) => UType.isFunction(elmDesc) ? td.ary = { obj: elmDesc } : td.ary = elmDesc);
36
37
  }
37
38
  DType.array = array;
38
39
  /** NOTE: this may allow array type because array is essentialy object type has properties. */
39
40
  function record(elmDesc = {}) {
40
- return (target, propKey) => setDesc(target, propKey, (td) => td.rcd = elmDesc);
41
+ return (target, propKey) => setDesc(target, propKey, (td) => UType.isFunction(elmDesc) ? td.rcd = { obj: elmDesc } : td.rcd = elmDesc);
41
42
  }
42
43
  DType.record = record;
43
- function recursive(target, propKey) {
44
- setDesc(target, propKey, (td) => td.rec = true);
44
+ function recursive(ctor) {
45
+ return (target, propKey) => setDesc(target, propKey, (td) => td.obj = ctor);
45
46
  }
46
47
  DType.recursive = recursive;
47
48
  function keep(target, propKey) {
@@ -50,10 +51,10 @@ export var DType;
50
51
  DType.keep = keep;
51
52
  function setDesc(target, propKey, setter) {
52
53
  const map = target[smbl_tm] ? Object.assign({}, target[smbl_tm]) : {};
53
- map[propKey] ??= { t: null, req: false, rec: false, ary: null, rcd: null };
54
+ map[propKey] ??= { t: null, req: false, obj: null, ary: null, rcd: null };
54
55
  const td = map[propKey];
55
56
  setter(td);
56
- const structualDescs = [[td.ary, "array"], [td.rec, "recursive flag"], [td.rcd, "record"]].filter(e => e[0]);
57
+ const structualDescs = [[td.ary, "array"], [td.obj, "recursive"], [td.rcd, "record"]].filter(e => e[0]);
57
58
  if (structualDescs.length > 0) {
58
59
  let ex1 = null, ex2 = null;
59
60
  if (td.t) {
@@ -3,11 +3,11 @@ export declare namespace UArray {
3
3
  /**
4
4
  * compares two arrays to valuate equality.
5
5
  * if one side is null or undefined, it returns true when other side is the same.
6
- * this function has compatibility to `AlmostArray` like `Uint8Array` etc.
6
+ * this function has compatibility {@link AlmostArray} like {@link Uint8Array} etc.
7
7
  * @param v1 it uses equal operator for comparing elements, so applying object element is not recommended.
8
8
  * @param v2 same as v1.
9
9
  * @param sort it uses {@link Array.sort()} on v1 and v2 if true. default is true.
10
- * @param useStrictEqual check equality whether `Array` or not and it uses `===` operator for compareing elements if true, otherwise using `==` operator. default is true.
10
+ * @param useStrictEqual check equality whether {@link Array} or not and it uses `===` operator for compareing elements if true, otherwise using `==` operator. default is true.
11
11
  */
12
12
  function eq(v1: any[] | AlmostArray, v2: any[] | AlmostArray, op?: {
13
13
  sort?: boolean;
@@ -28,7 +28,7 @@ export declare namespace UArray {
28
28
  }): T[];
29
29
  /**
30
30
  * chop array to partial arrays which have specified length. the remainder is added to end of a result.
31
- * this function has compatibility to `AlmostArray` like `Uint8Array` etc.
31
+ * this function has compatibility to {@link AlmostArray} like {@link Uint8Array} etc.
32
32
  */
33
33
  function chop<E>(array: E[], len: number): E[][];
34
34
  function chop<T extends AlmostArray>(array: T, len: number): T[];
@@ -4,11 +4,11 @@ export var UArray;
4
4
  /**
5
5
  * compares two arrays to valuate equality.
6
6
  * if one side is null or undefined, it returns true when other side is the same.
7
- * this function has compatibility to `AlmostArray` like `Uint8Array` etc.
7
+ * this function has compatibility {@link AlmostArray} like {@link Uint8Array} etc.
8
8
  * @param v1 it uses equal operator for comparing elements, so applying object element is not recommended.
9
9
  * @param v2 same as v1.
10
10
  * @param sort it uses {@link Array.sort()} on v1 and v2 if true. default is true.
11
- * @param useStrictEqual check equality whether `Array` or not and it uses `===` operator for compareing elements if true, otherwise using `==` operator. default is true.
11
+ * @param useStrictEqual check equality whether {@link Array} or not and it uses `===` operator for compareing elements if true, otherwise using `==` operator. default is true.
12
12
  */
13
13
  function eq(v1, v2, op = {}) {
14
14
  const { sort, useStrictEqual } = Object.assign({ sort: true, useStrictEqual: true }, op);
@@ -1,4 +1,4 @@
1
- import { MaybeArray, NonObject, NormalRecord, Type } from "../const/types";
1
+ import { Ctor, MaybeArray, NonObject, NormalRecord, Type } from "../const/types";
2
2
  export declare namespace UObj {
3
3
  /**
4
4
  * assign properties to the object with specified property keys.
@@ -9,12 +9,19 @@ export declare namespace UObj {
9
9
  */
10
10
  function assignProperties<T extends NormalRecord, S extends NormalRecord>(t: T, s: S, keys?: (keyof S)[], keepDtypeClass?: boolean): T & Partial<S>;
11
11
  /**
12
- * crop properties of the object. the properties is removed with `delete` operator.
13
- * @param o object whose properties is removed.
14
- * @param keys property names to be remained. if omit this, it removes the properties other than properties decorated {@link DType}.
15
- * @param exclusive if true, it removes `keys` instead of remaining it.
12
+ * crop properties of the object other than specified. the properties are to be removed with `delete` operator.
13
+ * @param o object whose properties to be removed.
14
+ * @param keys property names to be remained.
15
+ * @param removeKeys if true, it removes `keys` instead of remaining it.
16
16
  */
17
- function crop<T extends NormalRecord>(o: T, keys?: (keyof T)[], exclusive?: boolean): Partial<T>;
17
+ function crop<T extends NormalRecord>(o: T, keys: (keyof T)[], removeKeys?: boolean): Partial<T>;
18
+ /**
19
+ * crop properties that is not decorated with {@link DType}. the properties will be removed with `delete` operator.
20
+ * this treats constructual decorator such as {@link DType.recursive} recursively.
21
+ * @param o object whose properties to be removed. if this is class object decorated with {@link DType}, it can omits `ctor` parameter.
22
+ * @param ctor class constructor type whose properties are decorated with {@link DType}. **NOTE** that need to have public constructor without any parameter.
23
+ */
24
+ function crop<T extends NormalRecord>(o: T, ctor?: Ctor): Partial<T>;
18
25
  /**
19
26
  * manipulate properties of an object.
20
27
  * as default if the properties contains object, it also manipulates properties of that recursively.
@@ -20,20 +20,22 @@ export var UObj;
20
20
  return t;
21
21
  }
22
22
  UObj.assignProperties = assignProperties;
23
- /**
24
- * crop properties of the object. the properties is removed with `delete` operator.
25
- * @param o object whose properties is removed.
26
- * @param keys property names to be remained. if omit this, it removes the properties other than properties decorated {@link DType}.
27
- * @param exclusive if true, it removes `keys` instead of remaining it.
28
- */
29
- function crop(o, keys, exclusive) {
30
- if (!keys && !o[smbl_tm])
31
- return {};
32
- const _keys = keys ?? Object.keys(o[smbl_tm]);
23
+ function crop(o, keys_or_ctor, removeKeys) {
24
+ const tm = Array.isArray(keys_or_ctor) ? null
25
+ : (!keys_or_ctor || o instanceof keys_or_ctor ? o[smbl_tm] : new keys_or_ctor()[smbl_tm]);
26
+ const _keys = tm ? Object.keys(tm) : (keys_or_ctor ?? []);
27
+ if (_keys.length === 0)
28
+ return removeKeys ? o : {};
33
29
  Object.keys(o).filter(k => {
34
- if (!keys && o[smbl_tm]?.[k]?.rec && o[k])
35
- crop(o[k]);
36
- return !!exclusive === _keys.includes(k);
30
+ if (tm && tm[k] && o[k]) {
31
+ if (tm[k].obj)
32
+ crop(o[k], tm[k]?.obj);
33
+ else {
34
+ const vCtor = tm[k].ary?.obj ?? tm[k].rcd?.obj;
35
+ Object.values(o[k]).forEach(v => crop(v, vCtor));
36
+ }
37
+ }
38
+ return !!removeKeys === _keys.includes(k);
37
39
  }).forEach(k => delete o[k]);
38
40
  return o;
39
41
  }
@@ -1,4 +1,4 @@
1
- import { MaybeArray, Type } from "../const/types";
1
+ import { Ctor, MaybeArray, Type } from "../const/types";
2
2
  export declare namespace UType {
3
3
  function isDefined(v: any): boolean;
4
4
  function isEmpty(v: any): boolean;
@@ -17,10 +17,11 @@ export declare namespace UType {
17
17
  function isArray(v: any, t: Type.object): v is object[];
18
18
  function isArray(v: any): v is any[];
19
19
  /**
20
- * validate properties which attached decorators in {@link DType}.
21
- * @param o object to be validated.
20
+ * validate properties decorated with {@link DType}.
21
+ * @param o object to be validated. if this is class object decorated with {@link DType}, it can omits `ctor` parameter.
22
+ * @param ctor class constructor type whose properties are decorated. **NOTE** that need to have public constructor without any parameter.
22
23
  * @returns invalid property keys. returns an empty array if `o` is valid.
23
24
  */
24
- function validate(o: any): string[];
25
+ function validate(o: any, ctor?: Ctor): string[];
25
26
  function takeAsArray<T>(v: MaybeArray<T>): T[];
26
27
  }
@@ -29,14 +29,16 @@ export var UType;
29
29
  }
30
30
  UType.isArray = isArray;
31
31
  /**
32
- * validate properties which attached decorators in {@link DType}.
33
- * @param o object to be validated.
32
+ * validate properties decorated with {@link DType}.
33
+ * @param o object to be validated. if this is class object decorated with {@link DType}, it can omits `ctor` parameter.
34
+ * @param ctor class constructor type whose properties are decorated. **NOTE** that need to have public constructor without any parameter.
34
35
  * @returns invalid property keys. returns an empty array if `o` is valid.
35
36
  */
36
- function validate(o) {
37
- if (!o[smbl_tm])
37
+ function validate(o, ctor) {
38
+ const _o = (!ctor || o instanceof ctor) ? o : Object.assign(new ctor(), o);
39
+ if (!_o[smbl_tm])
38
40
  return [];
39
- return Object.entries(o[smbl_tm]).flatMap(e => validateProp(e[0], o[e[0]], e[1]));
41
+ return Object.entries(_o[smbl_tm]).flatMap(e => validateProp(e[0], _o[e[0]], e[1]));
40
42
  }
41
43
  UType.validate = validate;
42
44
  function validateProp(k, prop, td) {
@@ -51,8 +53,8 @@ export var UType;
51
53
  if (td.rcd)
52
54
  return UType.isObject(prop)
53
55
  ? Object.entries(prop).flatMap(e => validateProp(e[0], e[1], td.rcd)).map(joinKey) : [k];
54
- if (td.rec)
55
- return validate(prop).flatMap(joinKey);
56
+ if (td.obj)
57
+ return validate(prop, td.obj).flatMap(joinKey);
56
58
  return [];
57
59
  }
58
60
  function takeAsArray(v) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xjs-common",
3
- "version": "12.0.0-alpha.2",
3
+ "version": "13.0.0-alpha.1",
4
4
  "description": "library modules for typescript that bundled general-purpose implementations.",
5
5
  "repository": {
6
6
  "type": "git",