@wener/common 1.0.3 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. package/lib/cn/DivisionCode.js.map +1 -1
  2. package/lib/cn/Mod11Checksum.js.map +1 -1
  3. package/lib/cn/Mod31Checksum.js.map +1 -1
  4. package/lib/cn/ResidentIdentityCardNumber.js.map +1 -1
  5. package/lib/cn/UnifiedSocialCreditCode.js.map +1 -1
  6. package/lib/cn/formatDate.js.map +1 -1
  7. package/lib/cn/parseSex.js.map +1 -1
  8. package/lib/cn/types.d.js.map +1 -1
  9. package/lib/data/formatSort.js +15 -0
  10. package/lib/data/formatSort.js.map +1 -0
  11. package/lib/data/index.js +4 -0
  12. package/lib/data/index.js.map +1 -0
  13. package/lib/data/maybeNumber.js +22 -0
  14. package/lib/data/maybeNumber.js.map +1 -0
  15. package/lib/data/parseSort.js +95 -0
  16. package/lib/data/parseSort.js.map +1 -0
  17. package/lib/data/resolvePagination.js +36 -0
  18. package/lib/data/resolvePagination.js.map +1 -0
  19. package/lib/data/types.d.js +3 -0
  20. package/lib/data/types.d.js.map +1 -0
  21. package/lib/index.js +6 -2
  22. package/lib/index.js.map +1 -1
  23. package/lib/jsonschema/JsonSchema.js +4 -4
  24. package/lib/jsonschema/JsonSchema.js.map +1 -1
  25. package/lib/jsonschema/types.d.js.map +1 -1
  26. package/lib/meta/defineFileType.js.map +1 -1
  27. package/lib/meta/defineInit.js.map +1 -1
  28. package/lib/meta/defineMetadata.js.map +1 -1
  29. package/lib/password/PHC.js +8 -8
  30. package/lib/password/PHC.js.map +1 -1
  31. package/lib/password/Password.js.map +1 -1
  32. package/lib/password/createArgon2PasswordAlgorithm.js.map +1 -1
  33. package/lib/password/createBase64PasswordAlgorithm.js.map +1 -1
  34. package/lib/password/createBcryptPasswordAlgorithm.js.map +1 -1
  35. package/lib/password/createPBKDF2PasswordAlgorithm.js.map +1 -1
  36. package/lib/password/createScryptPasswordAlgorithm.js.map +1 -1
  37. package/lib/search/AdvanceSearch.js.map +1 -1
  38. package/lib/search/formatAdvanceSearch.js.map +1 -1
  39. package/lib/search/optimizeAdvanceSearch.js.map +1 -1
  40. package/lib/search/parseAdvanceSearch.js.map +1 -1
  41. package/lib/search/parser.d.js.map +1 -1
  42. package/lib/search/types.d.js.map +1 -1
  43. package/lib/tools/renderJsonSchemaToMarkdownDoc.js.map +1 -1
  44. package/package.json +10 -5
  45. package/src/cn/DivisionCode.test.ts +38 -45
  46. package/src/cn/DivisionCode.ts +140 -184
  47. package/src/cn/Mod11Checksum.ts +17 -17
  48. package/src/cn/Mod31Checksum.ts +25 -25
  49. package/src/cn/ResidentIdentityCardNumber.test.ts +12 -16
  50. package/src/cn/ResidentIdentityCardNumber.ts +82 -82
  51. package/src/cn/UnifiedSocialCreditCode.test.ts +11 -11
  52. package/src/cn/UnifiedSocialCreditCode.ts +115 -120
  53. package/src/cn/__snapshots__/ResidentIdentityCardNumber.test.ts.snap +1 -1
  54. package/src/cn/formatDate.ts +10 -10
  55. package/src/cn/parseSex.ts +11 -25
  56. package/src/cn/types.d.ts +43 -43
  57. package/src/data/formatSort.test.ts +13 -0
  58. package/src/data/formatSort.ts +18 -0
  59. package/src/data/index.ts +5 -0
  60. package/src/data/maybeNumber.ts +23 -0
  61. package/src/data/parseSort.test.ts +67 -0
  62. package/src/data/parseSort.ts +108 -0
  63. package/src/data/resolvePagination.test.ts +58 -0
  64. package/src/data/resolvePagination.ts +60 -0
  65. package/src/data/types.d.ts +33 -0
  66. package/src/index.ts +8 -2
  67. package/src/jsonschema/JsonSchema.test.ts +13 -22
  68. package/src/jsonschema/JsonSchema.ts +145 -177
  69. package/src/jsonschema/types.d.ts +151 -161
  70. package/src/meta/defineFileType.tsx +54 -54
  71. package/src/meta/defineInit.ts +32 -53
  72. package/src/meta/defineMetadata.test.ts +5 -7
  73. package/src/meta/defineMetadata.ts +28 -46
  74. package/src/password/PHC.test.ts +186 -277
  75. package/src/password/PHC.ts +243 -243
  76. package/src/password/Password.test.ts +38 -50
  77. package/src/password/Password.ts +73 -95
  78. package/src/password/createArgon2PasswordAlgorithm.ts +65 -69
  79. package/src/password/createBase64PasswordAlgorithm.ts +9 -9
  80. package/src/password/createBcryptPasswordAlgorithm.ts +20 -22
  81. package/src/password/createPBKDF2PasswordAlgorithm.ts +49 -61
  82. package/src/password/createScryptPasswordAlgorithm.ts +48 -59
  83. package/src/search/AdvanceSearch.test.ts +136 -143
  84. package/src/search/AdvanceSearch.ts +6 -6
  85. package/src/search/formatAdvanceSearch.ts +44 -53
  86. package/src/search/optimizeAdvanceSearch.ts +70 -83
  87. package/src/search/parseAdvanceSearch.ts +16 -19
  88. package/src/search/parser.d.ts +3 -3
  89. package/src/search/types.d.ts +28 -54
  90. package/src/tools/renderJsonSchemaToMarkdownDoc.ts +69 -69
  91. package/lib/normalizePagination.js +0 -14
  92. package/lib/normalizePagination.js.map +0 -1
  93. package/lib/parseSort.js +0 -106
  94. package/lib/parseSort.js.map +0 -1
  95. package/src/normalizePagination.ts +0 -25
  96. package/src/parseSort.test.ts +0 -42
  97. package/src/parseSort.ts +0 -133
@@ -2,155 +2,148 @@ import { describe, expect, it } from 'vitest';
2
2
  import { AdvanceSearch } from './AdvanceSearch';
3
3
 
4
4
  describe('AdvanceSearch', () => {
5
- it('should parse', () => {
6
- for (const input of [
7
- //
8
- '-a',
9
- 'a',
10
- 'a b',
11
- 'a -b',
12
- 'a-b',
13
- 'a"b',
14
- 'a&b',
15
- 'NOT a',
16
- 'NOT -a',
17
- 'HELLO -WORLD',
18
- '(a)',
19
- '( a OR B )',
20
- 'A OR B',
21
- 'a:[1,2]',
22
- 'a:*..1',
23
- 'a:ok a:=1 a:>1 a:<1 a:>=1 a:<=1 a:!=1 a:1..2 a:*..1 a:1..* a:[1,2] a:(1,2) a:[1,2) a:(1,2]',
24
- 'NOT (A B) AND (a:ok AND size:>1)',
25
- 'NOT -a',
26
- 'NOT (NOT -a)',
27
- 'owner:@me owner:=@me owner:!=@me',
28
- '@AI:"Where is my car"',
29
- '/**/ a',
30
- '/* Hint */ a',
31
- '/* a */ a /* b */',
32
- ]) {
33
- let out = AdvanceSearch.parse(input);
34
- let formated = AdvanceSearch.format(out);
35
- expect(formated, `reformat`).toMatchSnapshot();
36
- let optimized = AdvanceSearch.format(AdvanceSearch.optimize(out));
37
- expect(optimized, `optimized`).toMatchSnapshot();
38
- expect(out, `parsed`).toMatchSnapshot();
39
- expect(AdvanceSearch.parse(formated), `reformat match original`).toMatchObject(out);
40
- }
41
- });
42
- it('should parse as expected', () => {
43
- type Case = [string | null | undefined, AdvanceSearch.Expr[]];
5
+ it('should parse', () => {
6
+ for (const input of [
7
+ //
8
+ '-a',
9
+ 'a',
10
+ 'a b',
11
+ 'a -b',
12
+ 'a-b',
13
+ 'a"b',
14
+ 'a&b',
15
+ 'NOT a',
16
+ 'NOT -a',
17
+ 'HELLO -WORLD',
18
+ '(a)',
19
+ '( a OR B )',
20
+ 'A OR B',
21
+ 'a:[1,2]',
22
+ 'a:*..1',
23
+ 'a:ok a:=1 a:>1 a:<1 a:>=1 a:<=1 a:!=1 a:1..2 a:*..1 a:1..* a:[1,2] a:(1,2) a:[1,2) a:(1,2]',
24
+ 'NOT (A B) AND (a:ok AND size:>1)',
25
+ 'NOT -a',
26
+ 'NOT (NOT -a)',
27
+ 'owner:@me owner:=@me owner:!=@me',
28
+ '@AI:"Where is my car"',
29
+ '/**/ a',
30
+ '/* Hint */ a',
31
+ '/* a */ a /* b */',
32
+ ]) {
33
+ let out = AdvanceSearch.parse(input);
34
+ let formated = AdvanceSearch.format(out);
35
+ expect(formated, `reformat`).toMatchSnapshot();
36
+ let optimized = AdvanceSearch.format(AdvanceSearch.optimize(out));
37
+ expect(optimized, `optimized`).toMatchSnapshot();
38
+ expect(out, `parsed`).toMatchSnapshot();
39
+ expect(AdvanceSearch.parse(formated), `reformat match original`).toMatchObject(out);
40
+ }
41
+ });
42
+ it('should parse as expected', () => {
43
+ type Case = [string | null | undefined, AdvanceSearch.Expr[]];
44
44
 
45
- const cases: Case[] = [
46
- [null, []],
47
- [undefined, []],
48
- ['', []],
49
- // fast path
50
- ['a', [{ type: 'keyword', value: 'a' }]],
51
- ['a-b', [{ type: 'keyword', value: 'a-b' }]],
52
- ['a"b', [{ type: 'keyword', value: 'a"b' }]],
53
- [
54
- 'hello world',
55
- [
56
- { type: 'keyword', value: 'hello' },
57
- { type: 'keyword', value: 'world' },
58
- ],
59
- ],
60
- // advance
61
- ['-a', [{ type: 'keyword', value: 'a', negative: true }]],
62
- [
63
- '/*Hi*/ hello -world',
64
- [
65
- { type: 'comment', value: 'Hi' },
66
- { type: 'keyword', value: 'hello', negative: false },
67
- {
68
- type: 'keyword',
69
- value: 'world',
70
- negative: true,
71
- },
72
- ],
73
- ],
74
- ['"Hello"', [{ type: 'keyword', value: 'Hello', exact: true }]],
75
- ['-"Hello"', [{ type: 'keyword', value: 'Hello', exact: true, negative: true }]],
76
- ['is:ok', [{ type: 'compare', field: 'is', operator: 'match', value: { value: 'ok' } }]],
77
- ['-is:ok', [{ type: 'compare', field: 'is', negative: true, operator: 'match', value: { value: 'ok' } }]],
78
- ];
45
+ const cases: Case[] = [
46
+ [null, []],
47
+ [undefined, []],
48
+ ['', []],
49
+ // fast path
50
+ ['a', [{ type: 'keyword', value: 'a' }]],
51
+ ['a-b', [{ type: 'keyword', value: 'a-b' }]],
52
+ ['a"b', [{ type: 'keyword', value: 'a"b' }]],
53
+ [
54
+ 'hello world',
55
+ [
56
+ { type: 'keyword', value: 'hello' },
57
+ { type: 'keyword', value: 'world' },
58
+ ],
59
+ ],
60
+ // advance
61
+ ['-a', [{ type: 'keyword', value: 'a', negative: true }]],
62
+ [
63
+ '/*Hi*/ hello -world',
64
+ [
65
+ { type: 'comment', value: 'Hi' },
66
+ { type: 'keyword', value: 'hello', negative: false },
67
+ { type: 'keyword', value: 'world', negative: true },
68
+ ],
69
+ ],
70
+ ['"Hello"', [{ type: 'keyword', value: 'Hello', exact: true }]],
71
+ ['-"Hello"', [{ type: 'keyword', value: 'Hello', exact: true, negative: true }]],
72
+ ['is:ok', [{ type: 'compare', field: 'is', operator: 'match', value: { value: 'ok' } }]],
73
+ ['-is:ok', [{ type: 'compare', field: 'is', negative: true, operator: 'match', value: { value: 'ok' } }]],
74
+ ];
79
75
 
80
- for (const [input, expected] of cases) {
81
- let out = AdvanceSearch.parse(input);
82
- expect(out).toMatchObject(expected);
83
- expect(AdvanceSearch.parse(AdvanceSearch.format(out)), 'reformat should match').toMatchObject(expected);
84
- }
85
- });
76
+ for (const [input, expected] of cases) {
77
+ let out = AdvanceSearch.parse(input);
78
+ expect(out).toMatchObject(expected);
79
+ expect(AdvanceSearch.parse(AdvanceSearch.format(out)), 'reformat should match').toMatchObject(expected);
80
+ }
81
+ });
86
82
 
87
- it('should optimize simple', () => {
88
- type Case = {
89
- input: AdvanceSearch.Expr[];
90
- expected: AdvanceSearch.Expr[];
91
- };
92
- const cases: Case[] = [
93
- // rm empty comment
94
- {
95
- input: [
96
- { type: 'comment', value: '' },
97
- { type: 'keyword', value: 'a' },
98
- ],
99
- expected: [{ type: 'keyword', value: 'a' }],
100
- },
101
- // unwrap parentheses
102
- {
103
- input: [
104
- { type: 'parentheses', value: [{ type: 'keyword', value: 'a' }] },
105
- { type: 'keyword', value: 'b' },
106
- ],
107
- expected: [
108
- { type: 'keyword', value: 'a' },
109
- { type: 'keyword', value: 'b' },
110
- ],
111
- },
112
- // not not
113
- {
114
- input: [{ type: 'not', value: { type: 'not', value: { type: 'keyword', value: 'a' } } }],
115
- expected: [{ type: 'keyword', value: 'a', negative: false }],
116
- },
117
- // not to negative
118
- {
119
- input: [{ type: 'not', value: { type: 'keyword', value: 'a' } }],
120
- expected: [{ type: 'keyword', value: 'a', negative: true }],
121
- },
122
- ];
83
+ it('should optimize simple', () => {
84
+ type Case = { input: AdvanceSearch.Expr[]; expected: AdvanceSearch.Expr[] };
85
+ const cases: Case[] = [
86
+ // rm empty comment
87
+ {
88
+ input: [
89
+ { type: 'comment', value: '' },
90
+ { type: 'keyword', value: 'a' },
91
+ ],
92
+ expected: [{ type: 'keyword', value: 'a' }],
93
+ },
94
+ // unwrap parentheses
95
+ {
96
+ input: [
97
+ { type: 'parentheses', value: [{ type: 'keyword', value: 'a' }] },
98
+ { type: 'keyword', value: 'b' },
99
+ ],
100
+ expected: [
101
+ { type: 'keyword', value: 'a' },
102
+ { type: 'keyword', value: 'b' },
103
+ ],
104
+ },
105
+ // not not
106
+ {
107
+ input: [{ type: 'not', value: { type: 'not', value: { type: 'keyword', value: 'a' } } }],
108
+ expected: [{ type: 'keyword', value: 'a', negative: false }],
109
+ },
110
+ // not to negative
111
+ {
112
+ input: [{ type: 'not', value: { type: 'keyword', value: 'a' } }],
113
+ expected: [{ type: 'keyword', value: 'a', negative: true }],
114
+ },
115
+ ];
123
116
 
124
- for (let i = 0; i < cases.length; i++) {
125
- const { input, expected } = cases[i];
126
- let out = AdvanceSearch.optimize(input);
127
- expect(out, `case #${i}`).toEqual(expected);
128
- }
129
- });
117
+ for (let i = 0; i < cases.length; i++) {
118
+ const { input, expected } = cases[i];
119
+ let out = AdvanceSearch.optimize(input);
120
+ expect(out, `case #${i}`).toEqual(expected);
121
+ }
122
+ });
130
123
 
131
- it('should optimize by formated', () => {
132
- type Case = [string, string];
124
+ it('should optimize by formated', () => {
125
+ type Case = [string, string];
133
126
 
134
- const cases: Case[] = [
135
- ['( a )', 'a'],
136
- ['NOT a', '-a'],
137
- ['NOT -a', 'a'],
138
- ['NOT is:ok', '-is:ok'],
139
- ['NOT -is:ok', 'is:ok'],
140
- ['NOT -is:=ok', 'is:=ok'],
141
- ['NOT is:=ok', 'is:!=ok'],
142
- ['NOT (NOT -a)', '-a'],
143
- ];
127
+ const cases: Case[] = [
128
+ ['( a )', 'a'],
129
+ ['NOT a', '-a'],
130
+ ['NOT -a', 'a'],
131
+ ['NOT is:ok', '-is:ok'],
132
+ ['NOT -is:ok', 'is:ok'],
133
+ ['NOT -is:=ok', 'is:=ok'],
134
+ ['NOT is:=ok', 'is:!=ok'],
135
+ ['NOT (NOT -a)', '-a'],
136
+ ];
144
137
 
145
- for (const [input, expected] of cases) {
146
- let out = AdvanceSearch.optimize(AdvanceSearch.parse(input));
147
- expect(AdvanceSearch.format(out), `${input} -> ${expected}: ${JSON.stringify(out)}`).toEqual(expected);
148
- }
149
- });
138
+ for (const [input, expected] of cases) {
139
+ let out = AdvanceSearch.optimize(AdvanceSearch.parse(input));
140
+ expect(AdvanceSearch.format(out), `${input} -> ${expected}: ${JSON.stringify(out)}`).toEqual(expected);
141
+ }
142
+ });
150
143
 
151
- it.fails('should parse parentheses', () => {
152
- let out = AdvanceSearch.parse('(a)');
153
- console.log(out);
154
- expect(out).toEqual([{ type: 'parentheses', value: [{ type: 'keyword', value: 'a' }] }]);
155
- });
144
+ it.fails('should parse parentheses', () => {
145
+ let out = AdvanceSearch.parse('(a)');
146
+ console.log(out);
147
+ expect(out).toEqual([{ type: 'parentheses', value: [{ type: 'keyword', value: 'a' }] }]);
148
+ });
156
149
  });
@@ -4,11 +4,11 @@ import { parseAdvanceSearch } from './parseAdvanceSearch';
4
4
  import type * as types from './types';
5
5
 
6
6
  export namespace AdvanceSearch {
7
- export type Exprs = types.Exprs;
8
- export type Expr = types.Expr;
9
- export type Value = types.Value;
7
+ export type Exprs = types.Exprs;
8
+ export type Expr = types.Expr;
9
+ export type Value = types.Value;
10
10
 
11
- export const parse = parseAdvanceSearch;
12
- export const format = formatAdvanceSearch;
13
- export const optimize = optimizeAdvanceSearch;
11
+ export const parse = parseAdvanceSearch;
12
+ export const format = formatAdvanceSearch;
13
+ export const optimize = optimizeAdvanceSearch;
14
14
  }
@@ -2,60 +2,51 @@ import { match } from 'ts-pattern';
2
2
  import { AdvanceSearch } from './AdvanceSearch';
3
3
 
4
4
  export function formatAdvanceSearch(input: AdvanceSearch.Expr[]) {
5
- const OP = {
6
- match: ':',
7
- eq: ':=',
8
- ne: ':!=',
9
- gt: ':>',
10
- lt: ':<',
11
- gte: ':>=',
12
- lte: ':<=',
13
- range: ':',
14
- } as const;
5
+ const OP = { match: ':', eq: ':=', ne: ':!=', gt: ':>', lt: ':<', gte: ':>=', lte: ':<=', range: ':' } as const;
15
6
 
16
- const _exprs = (s: AdvanceSearch.Expr[]): string => {
17
- return s.map(_expr).join(' ');
18
- };
19
- const _expr = (s: AdvanceSearch.Expr): string => {
20
- return match(s)
21
- .with({ type: 'keyword' }, ({ value, exact, negative }) => {
22
- return `${negative ? '-' : ''}${exact ? `"${value}"` : value}`;
23
- })
24
- .with({ type: 'logical' }, ({ operator, value }) => value.map(_expr).join(` ${operator.toLocaleUpperCase()} `))
25
- .with({ type: 'not' }, ({ value }) => `NOT ${_expr(value)}`)
26
- .with({ type: 'compare' }, ({ field, operator, value, negative, mention }) => {
27
- return `${negative ? '-' : ''}${mention ? '@' : ''}${field}${OP[operator]}${_value(value)}`;
28
- })
29
- .with({ type: 'comment' }, ({ value }) => `/* ${value} */`)
30
- .with({ type: 'parentheses' }, ({ value }) => `(${_exprs(value)})`)
31
- .exhaustive();
32
- };
7
+ const _exprs = (s: AdvanceSearch.Expr[]): string => {
8
+ return s.map(_expr).join(' ');
9
+ };
10
+ const _expr = (s: AdvanceSearch.Expr): string => {
11
+ return match(s)
12
+ .with({ type: 'keyword' }, ({ value, exact, negative }) => {
13
+ return `${negative ? '-' : ''}${exact ? `"${value}"` : value}`;
14
+ })
15
+ .with({ type: 'logical' }, ({ operator, value }) => value.map(_expr).join(` ${operator.toLocaleUpperCase()} `))
16
+ .with({ type: 'not' }, ({ value }) => `NOT ${_expr(value)}`)
17
+ .with({ type: 'compare' }, ({ field, operator, value, negative, mention }) => {
18
+ return `${negative ? '-' : ''}${mention ? '@' : ''}${field}${OP[operator]}${_value(value)}`;
19
+ })
20
+ .with({ type: 'comment' }, ({ value }) => `/* ${value} */`)
21
+ .with({ type: 'parentheses' }, ({ value }) => `(${_exprs(value)})`)
22
+ .exhaustive();
23
+ };
33
24
 
34
- const _literal = (s: string | null | number) => {
35
- if (typeof s === 'string') {
36
- return s.includes(' ') ? `"${s}"` : s;
37
- }
38
- return JSON.stringify(s);
39
- };
40
- const _value = (v: AdvanceSearch.Value): string => {
41
- return match(v)
42
- .with({ type: 'range' }, ({ minimum, maximum, minimumExclusive, maximumExclusive }) => {
43
- if (minimumExclusive === undefined && maximumExclusive === undefined) {
44
- let min = minimum === undefined ? '*' : _value(minimum);
45
- let max = maximum === undefined ? '*' : _value(maximum);
46
- return `${min}..${max}`;
47
- }
48
- let min = minimum === undefined ? '' : _value(minimum);
49
- let max = maximum === undefined ? '' : _value(maximum);
50
- return `${minimumExclusive ? '(' : '['}${min},${max}${maximumExclusive ? ')' : ']'}`;
51
- })
52
- .with({ format: 'mention' }, ({ value }) => {
53
- return `@${value}`;
54
- })
55
- .otherwise((value) => {
56
- return _literal(value.value);
57
- });
58
- };
25
+ const _literal = (s: string | null | number) => {
26
+ if (typeof s === 'string') {
27
+ return s.includes(' ') ? `"${s}"` : s;
28
+ }
29
+ return JSON.stringify(s);
30
+ };
31
+ const _value = (v: AdvanceSearch.Value): string => {
32
+ return match(v)
33
+ .with({ type: 'range' }, ({ minimum, maximum, minimumExclusive, maximumExclusive }) => {
34
+ if (minimumExclusive === undefined && maximumExclusive === undefined) {
35
+ let min = minimum === undefined ? '*' : _value(minimum);
36
+ let max = maximum === undefined ? '*' : _value(maximum);
37
+ return `${min}..${max}`;
38
+ }
39
+ let min = minimum === undefined ? '' : _value(minimum);
40
+ let max = maximum === undefined ? '' : _value(maximum);
41
+ return `${minimumExclusive ? '(' : '['}${min},${max}${maximumExclusive ? ')' : ']'}`;
42
+ })
43
+ .with({ format: 'mention' }, ({ value }) => {
44
+ return `@${value}`;
45
+ })
46
+ .otherwise((value) => {
47
+ return _literal(value.value);
48
+ });
49
+ };
59
50
 
60
- return _exprs(input);
51
+ return _exprs(input);
61
52
  }
@@ -3,88 +3,75 @@ import { match } from 'ts-pattern';
3
3
  import { AdvanceSearch } from './AdvanceSearch';
4
4
 
5
5
  export function optimizeAdvanceSearch(expr: AdvanceSearch.Exprs): AdvanceSearch.Exprs {
6
- const NEG = {
7
- eq: 'ne',
8
- ne: 'eq',
9
- gt: 'lte',
10
- lt: 'gte',
11
- gte: 'lt',
12
- lte: 'gt',
13
- } as const;
14
- const _expr = (e: AdvanceSearch.Expr): MaybeArray<AdvanceSearch.Expr> => {
15
- // merge Exprs to AND ?
16
- return (
17
- match(e)
18
- // (EXPR) -> EXPR
19
- // TODO (EXPR EXPR) -> EXPR AND EXPR
20
- .with({ type: 'parentheses' }, (expr) => {
21
- // unwrap
22
- if (expr.value.length < 2) {
23
- return expr.value[0];
24
- }
25
- expr.value = expr.value.flatMap(_expr);
26
- return expr;
27
- })
28
- .with({ type: 'comment' }, (expr) => {
29
- // remove empty comment
30
- if (!expr.value.length) {
31
- return [];
32
- }
33
- return expr;
34
- })
35
- // NOT
36
- .with({ type: 'not' }, (expr) => {
37
- let out = arrayOfMaybeArray(_expr(expr.value));
38
- if (!out.length) {
39
- return [];
40
- } else if (out.length === 1) {
41
- expr.value = out[0];
42
- } else {
43
- throw new Error('NOT should have only one value');
44
- }
45
- return (
46
- match(expr.value)
47
- // NOT NOT EXPR -> EXPR
48
- .with({ type: 'not' }, (expr) => expr.value)
49
- // NOT EXPR -> -EXPR
50
- .with({ type: 'compare' }, (expr) => {
51
- return {
52
- ...expr,
53
- negative: !expr.negative,
54
- };
55
- })
56
- .with({ type: 'keyword' }, (expr) => {
57
- return {
58
- ...expr,
59
- negative: !expr.negative,
60
- };
61
- })
62
- .otherwise(() => expr)
63
- );
64
- })
65
- .with({ type: 'compare' }, (expr) => {
66
- // negative by swap operator
67
- if (expr.negative) {
68
- const ne = NEG[expr.operator as keyof typeof NEG];
69
- if (ne) {
70
- expr.operator = ne;
71
- expr.negative = false;
72
- }
73
- }
74
- if (expr.operator === 'range') {
75
- }
76
- return expr;
77
- })
78
- .otherwise((e) => e)
79
- );
80
- };
6
+ const NEG = { eq: 'ne', ne: 'eq', gt: 'lte', lt: 'gte', gte: 'lt', lte: 'gt' } as const;
7
+ const _expr = (e: AdvanceSearch.Expr): MaybeArray<AdvanceSearch.Expr> => {
8
+ // merge Exprs to AND ?
9
+ return (
10
+ match(e)
11
+ // (EXPR) -> EXPR
12
+ // TODO (EXPR EXPR) -> EXPR AND EXPR
13
+ .with({ type: 'parentheses' }, (expr) => {
14
+ // unwrap
15
+ if (expr.value.length < 2) {
16
+ return expr.value[0];
17
+ }
18
+ expr.value = expr.value.flatMap(_expr);
19
+ return expr;
20
+ })
21
+ .with({ type: 'comment' }, (expr) => {
22
+ // remove empty comment
23
+ if (!expr.value.length) {
24
+ return [];
25
+ }
26
+ return expr;
27
+ })
28
+ // NOT
29
+ .with({ type: 'not' }, (expr) => {
30
+ let out = arrayOfMaybeArray(_expr(expr.value));
31
+ if (!out.length) {
32
+ return [];
33
+ } else if (out.length === 1) {
34
+ expr.value = out[0];
35
+ } else {
36
+ throw new Error('NOT should have only one value');
37
+ }
38
+ return (
39
+ match(expr.value)
40
+ // NOT NOT EXPR -> EXPR
41
+ .with({ type: 'not' }, (expr) => expr.value)
42
+ // NOT EXPR -> -EXPR
43
+ .with({ type: 'compare' }, (expr) => {
44
+ return { ...expr, negative: !expr.negative };
45
+ })
46
+ .with({ type: 'keyword' }, (expr) => {
47
+ return { ...expr, negative: !expr.negative };
48
+ })
49
+ .otherwise(() => expr)
50
+ );
51
+ })
52
+ .with({ type: 'compare' }, (expr) => {
53
+ // negative by swap operator
54
+ if (expr.negative) {
55
+ const ne = NEG[expr.operator as keyof typeof NEG];
56
+ if (ne) {
57
+ expr.operator = ne;
58
+ expr.negative = false;
59
+ }
60
+ }
61
+ if (expr.operator === 'range') {
62
+ }
63
+ return expr;
64
+ })
65
+ .otherwise((e) => e)
66
+ );
67
+ };
81
68
 
82
- let last = expr;
83
- while (true) {
84
- let next = structuredClone(last).flatMap(_expr);
85
- if (deepEqual(last, next)) {
86
- return last;
87
- }
88
- last = next;
89
- }
69
+ let last = expr;
70
+ while (true) {
71
+ let next = structuredClone(last).flatMap(_expr);
72
+ if (deepEqual(last, next)) {
73
+ return last;
74
+ }
75
+ last = next;
76
+ }
90
77
  }
@@ -2,25 +2,22 @@ import { AdvanceSearch } from './AdvanceSearch';
2
2
  import { parse } from './parser';
3
3
 
4
4
  export function parseAdvanceSearch(s: string | undefined | null): AdvanceSearch.Expr[] {
5
- s = s?.trim();
6
- if (!s) {
7
- return [];
8
- }
5
+ s = s?.trim();
6
+ if (!s) {
7
+ return [];
8
+ }
9
9
 
10
- // no Logical, no Compare, no Quote, no Comment
11
- if (!/AND|OR|NOT|[-"():]|\/\*/.test(s)) {
12
- // fast path
13
- return s
14
- .split(/\s+/)
15
- .map((v) => v.trim())
16
- .filter(Boolean)
17
- .map((v) => {
18
- return {
19
- type: 'keyword',
20
- value: v,
21
- };
22
- });
23
- }
10
+ // no Logical, no Compare, no Quote, no Comment
11
+ if (!/AND|OR|NOT|[-"():]|\/\*/.test(s)) {
12
+ // fast path
13
+ return s
14
+ .split(/\s+/)
15
+ .map((v) => v.trim())
16
+ .filter(Boolean)
17
+ .map((v) => {
18
+ return { type: 'keyword', value: v };
19
+ });
20
+ }
24
21
 
25
- return parse(s);
22
+ return parse(s);
26
23
  }
@@ -1,8 +1,8 @@
1
1
  export function parse(input: string, options?: ParseOptions): any;
2
2
 
3
3
  export interface ParseOptions {
4
- grammarSource?: string;
5
- startRule?: string;
4
+ grammarSource?: string;
5
+ startRule?: string;
6
6
 
7
- [k: string]: any;
7
+ [k: string]: any;
8
8
  }