@wener/common 1.0.1 → 1.0.3
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/DivisionCode.js +311 -0
- package/lib/cn/DivisionCode.js.map +1 -0
- package/lib/cn/Mod11Checksum.js +42 -0
- package/lib/cn/Mod11Checksum.js.map +1 -0
- package/lib/cn/Mod31Checksum.js +48 -0
- package/lib/cn/Mod31Checksum.js.map +1 -0
- package/lib/cn/ResidentIdentityCardNumber.js +50 -0
- package/lib/cn/ResidentIdentityCardNumber.js.map +1 -0
- package/lib/cn/UnifiedSocialCreditCode.js +118 -0
- package/lib/cn/UnifiedSocialCreditCode.js.map +1 -0
- package/lib/cn/formatDate.js +15 -0
- package/lib/cn/formatDate.js.map +1 -0
- package/lib/cn/index.js +4 -0
- package/lib/cn/index.js.map +1 -0
- package/lib/cn/parseSex.js +22 -0
- package/lib/cn/parseSex.js.map +1 -0
- package/lib/cn/types.d.js +8 -0
- package/lib/cn/types.d.js.map +1 -0
- package/lib/meta/defineFileType.js +44 -0
- package/lib/meta/defineFileType.js.map +1 -0
- package/lib/meta/defineMetadata.js +14 -3
- package/lib/meta/defineMetadata.js.map +1 -1
- package/lib/meta/index.js +1 -0
- package/lib/meta/index.js.map +1 -1
- package/lib/parseSort.js +15 -0
- package/lib/parseSort.js.map +1 -1
- package/lib/search/AdvanceSearch.js +10 -0
- package/lib/search/AdvanceSearch.js.map +1 -0
- package/lib/search/formatAdvanceSearch.js +64 -0
- package/lib/search/formatAdvanceSearch.js.map +1 -0
- package/lib/search/index.js +2 -0
- package/lib/search/index.js.map +1 -0
- package/lib/search/optimizeAdvanceSearch.js +89 -0
- package/lib/search/optimizeAdvanceSearch.js.map +1 -0
- package/lib/search/parseAdvanceSearch.js +20 -0
- package/lib/search/parseAdvanceSearch.js.map +1 -0
- package/lib/search/parser.d.js +3 -0
- package/lib/search/parser.d.js.map +1 -0
- package/lib/search/parser.js +3065 -0
- package/lib/search/parser.js.map +1 -0
- package/lib/search/types.d.js +3 -0
- package/lib/search/types.d.js.map +1 -0
- package/package.json +12 -4
- package/src/cn/DivisionCode.test.ts +50 -0
- package/src/cn/DivisionCode.ts +253 -0
- package/src/cn/Mod11Checksum.ts +24 -0
- package/src/cn/Mod31Checksum.ts +36 -0
- package/src/cn/ResidentIdentityCardNumber.test.ts +21 -0
- package/src/cn/ResidentIdentityCardNumber.ts +96 -0
- package/src/cn/UnifiedSocialCreditCode.test.ts +16 -0
- package/src/cn/UnifiedSocialCreditCode.ts +148 -0
- package/src/cn/__snapshots__/ResidentIdentityCardNumber.test.ts.snap +15 -0
- package/src/cn/__snapshots__/UnifiedSocialCreditCode.test.ts.snap +41 -0
- package/src/cn/formatDate.ts +12 -0
- package/src/cn/index.ts +3 -0
- package/src/cn/parseSex.ts +27 -0
- package/src/cn/types.d.ts +51 -0
- package/src/meta/defineFileType.tsx +68 -0
- package/src/meta/defineMetadata.ts +16 -3
- package/src/meta/index.ts +2 -0
- package/src/parseSort.test.ts +1 -0
- package/src/parseSort.ts +18 -0
- package/src/search/AdvanceSearch.test.ts +156 -0
- package/src/search/AdvanceSearch.ts +14 -0
- package/src/search/Makefile +2 -0
- package/src/search/__snapshots__/AdvanceSearch.test.ts.snap +675 -0
- package/src/search/formatAdvanceSearch.ts +61 -0
- package/src/search/index.ts +1 -0
- package/src/search/optimizeAdvanceSearch.ts +90 -0
- package/src/search/parseAdvanceSearch.ts +26 -0
- package/src/search/parser.d.ts +8 -0
- package/src/search/parser.js +2794 -0
- package/src/search/parser.peggy +237 -0
- package/src/search/types.d.ts +71 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export function parseSex(s) {
|
|
2
|
+
if (!s) return undefined;
|
|
3
|
+
switch(s.toLowerCase()){
|
|
4
|
+
case '男':
|
|
5
|
+
case 'male':
|
|
6
|
+
return {
|
|
7
|
+
sex: 'Male',
|
|
8
|
+
male: true,
|
|
9
|
+
female: false
|
|
10
|
+
};
|
|
11
|
+
case '女':
|
|
12
|
+
case 'female':
|
|
13
|
+
return {
|
|
14
|
+
sex: 'Female',
|
|
15
|
+
male: false,
|
|
16
|
+
female: true
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
//# sourceMappingURL=parseSex.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/cn/parseSex.ts"],"sourcesContent":["export function parseSex(s: string):\n | undefined\n | {\n sex: 'Male' | 'Female';\n male: boolean;\n female: boolean;\n } {\n if (!s) return undefined;\n\n switch (s.toLowerCase()) {\n case '男':\n case 'male':\n return {\n sex: 'Male',\n male: true,\n female: false,\n };\n case '女':\n case 'female':\n return {\n sex: 'Female',\n male: false,\n female: true,\n };\n }\n return undefined;\n}\n"],"names":["parseSex","s","undefined","toLowerCase","sex","male","female"],"mappings":"AAAA,OAAO,SAASA,SAASC,CAAS;IAOhC,IAAI,CAACA,GAAG,OAAOC;IAEf,OAAQD,EAAEE,WAAW;QACnB,KAAK;QACL,KAAK;YACH,OAAO;gBACLC,KAAK;gBACLC,MAAM;gBACNC,QAAQ;YACV;QACF,KAAK;QACL,KAAK;YACH,OAAO;gBACLF,KAAK;gBACLC,MAAM;gBACNC,QAAQ;YACV;IACJ;IACA,OAAOJ;AACT"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/cn/types.d.ts"],"sourcesContent":["/**\n * 居民身份证\n *\n * @see https://en.wikipedia.org/wiki/Resident_Identity_Card\n * @see https://en.wikipedia.org/wiki/Foreign_Permanent_Resident_ID_Card\n */\nexport interface ResidentIdentityCardInfo {\n /**\n * @title 姓名\n */\n name: string;\n /**\n * @title 性别\n */\n sex: 'Male' | 'Female';\n /**\n * @title 民族\n * 例如 '汉'/'满'/'回'\n */\n ethnicity: string;\n /**\n * @title 出生日期\n * @format date\n */\n birthDate: string;\n /**\n * @title 地址\n *\n * - 通常为 domicile/户籍地\n */\n address: string;\n /**\n * @title 身份证号\n */\n identityCardNumber: string;\n /**\n * @title 签发机关\n */\n issuer: string;\n /**\n * @title 有效期开始日期\n * @format date\n */\n validStartDate: string;\n /**\n * @title 有效期结束日期\n * @format date\n * @description 如长期有效则为 空\n */\n validEndDate?: string;\n}\n"],"names":[],"mappings":"AAAA;;;;;CAKC,GACD,WA4CC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
let _all = [];
|
|
2
|
+
export function defineFileType({ type = '', types = [], extension = '', extensions = [], ...opts }) {
|
|
3
|
+
if (!type) {
|
|
4
|
+
type = types[0] || '';
|
|
5
|
+
}
|
|
6
|
+
if (!extension) {
|
|
7
|
+
extension = extensions[0] || '';
|
|
8
|
+
}
|
|
9
|
+
if (!types.includes(type)) {
|
|
10
|
+
types = [
|
|
11
|
+
type,
|
|
12
|
+
...types
|
|
13
|
+
];
|
|
14
|
+
}
|
|
15
|
+
if (!extensions.includes(extension)) {
|
|
16
|
+
extensions = [
|
|
17
|
+
extension,
|
|
18
|
+
...extensions
|
|
19
|
+
];
|
|
20
|
+
}
|
|
21
|
+
const def = {
|
|
22
|
+
title: opts.title || opts.name,
|
|
23
|
+
type,
|
|
24
|
+
extension,
|
|
25
|
+
types,
|
|
26
|
+
extensions,
|
|
27
|
+
tags: [],
|
|
28
|
+
metadata: {},
|
|
29
|
+
...opts
|
|
30
|
+
};
|
|
31
|
+
let idx = _all.findIndex((v)=>v.name === def.name);
|
|
32
|
+
if (idx >= 0) {
|
|
33
|
+
_all[idx] = def;
|
|
34
|
+
console.warn(`File type ${def.name} is redefined`);
|
|
35
|
+
} else {
|
|
36
|
+
_all.push(def);
|
|
37
|
+
}
|
|
38
|
+
return def;
|
|
39
|
+
}
|
|
40
|
+
export function getFileType() {
|
|
41
|
+
return _all;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
//# sourceMappingURL=defineFileType.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/meta/defineFileType.tsx"],"sourcesContent":["type DefineFileTypeOptions = {\n name: string;\n title?: string;\n description?: string;\n type?: string;\n types?: string[];\n extension?: string;\n extensions?: string[];\n tags?: string[];\n metadata?: Record<string, any>;\n};\nexport type FileTypeDef = {\n name: string;\n title: string;\n description?: string;\n type: string; // primary type\n extension: string; // primary extension\n types: string[];\n extensions: string[];\n tags: string[];\n metadata: Record<string, any>;\n};\n\nlet _all: FileTypeDef[] = [];\n\nexport function defineFileType({\n type = '',\n types = [],\n extension = '',\n extensions = [],\n ...opts\n}: DefineFileTypeOptions): FileTypeDef {\n if (!type) {\n type = types[0] || '';\n }\n if (!extension) {\n extension = extensions[0] || '';\n }\n if (!types.includes(type)) {\n types = [type, ...types];\n }\n if (!extensions.includes(extension)) {\n extensions = [extension, ...extensions];\n }\n\n const def: FileTypeDef = {\n title: opts.title || opts.name,\n type,\n extension,\n types,\n extensions,\n tags: [],\n metadata: {},\n ...opts,\n };\n let idx = _all.findIndex((v) => v.name === def.name);\n if (idx >= 0) {\n _all[idx] = def;\n console.warn(`File type ${def.name} is redefined`);\n } else {\n _all.push(def);\n }\n return def;\n}\n\nexport function getFileType(): FileTypeDef[] {\n return _all;\n}\n"],"names":["_all","defineFileType","type","types","extension","extensions","opts","includes","def","title","name","tags","metadata","idx","findIndex","v","console","warn","push","getFileType"],"mappings":"AAuBA,IAAIA,OAAsB,EAAE;AAE5B,OAAO,SAASC,eAAe,EAC7BC,OAAO,EAAE,EACTC,QAAQ,EAAE,EACVC,YAAY,EAAE,EACdC,aAAa,EAAE,EACf,GAAGC,MACmB;IACtB,IAAI,CAACJ,MAAM;QACTA,OAAOC,KAAK,CAAC,EAAE,IAAI;IACrB;IACA,IAAI,CAACC,WAAW;QACdA,YAAYC,UAAU,CAAC,EAAE,IAAI;IAC/B;IACA,IAAI,CAACF,MAAMI,QAAQ,CAACL,OAAO;QACzBC,QAAQ;YAACD;eAASC;SAAM;IAC1B;IACA,IAAI,CAACE,WAAWE,QAAQ,CAACH,YAAY;QACnCC,aAAa;YAACD;eAAcC;SAAW;IACzC;IAEA,MAAMG,MAAmB;QACvBC,OAAOH,KAAKG,KAAK,IAAIH,KAAKI,IAAI;QAC9BR;QACAE;QACAD;QACAE;QACAM,MAAM,EAAE;QACRC,UAAU,CAAC;QACX,GAAGN,IAAI;IACT;IACA,IAAIO,MAAMb,KAAKc,SAAS,CAAC,CAACC,IAAMA,EAAEL,IAAI,KAAKF,IAAIE,IAAI;IACnD,IAAIG,OAAO,GAAG;QACZb,IAAI,CAACa,IAAI,GAAGL;QACZQ,QAAQC,IAAI,CAAC,CAAC,UAAU,EAAET,IAAIE,IAAI,CAAC,aAAa,CAAC;IACnD,OAAO;QACLV,KAAKkB,IAAI,CAACV;IACZ;IACA,OAAOA;AACT;AAEA,OAAO,SAASW;IACd,OAAOnB;AACT"}
|
|
@@ -18,9 +18,20 @@ export function createMetadataKey(a, b) {
|
|
|
18
18
|
}
|
|
19
19
|
return k;
|
|
20
20
|
}
|
|
21
|
-
export function defineMetadata(
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
export function defineMetadata(a, b, c) {
|
|
22
|
+
if (Array.isArray(b)) {
|
|
23
|
+
const key = a;
|
|
24
|
+
const items = b;
|
|
25
|
+
for (const [res, opts] of items){
|
|
26
|
+
defineMetadata(res, key, opts);
|
|
27
|
+
}
|
|
28
|
+
} else {
|
|
29
|
+
const res = a;
|
|
30
|
+
const key = b;
|
|
31
|
+
const opts = c;
|
|
32
|
+
res.metadata = res.metadata || {};
|
|
33
|
+
set(res.metadata, key.key, opts);
|
|
34
|
+
}
|
|
24
35
|
}
|
|
25
36
|
export function getMetadata(res, key) {
|
|
26
37
|
if (!res?.metadata) return undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/meta/defineMetadata.ts"],"sourcesContent":["import { startCase } from 'es-toolkit';\nimport { get, set } from 'es-toolkit/compat';\n\ntype HasMetadata = {\n metadata?: Record<string, any>;\n};\n\ntype MetadataKey<T> = {\n key: string;\n type: T;\n title: string;\n description?: string;\n};\n\ninterface CreateMetadataKeyOptions {\n key: string;\n title?: string;\n description?: string;\n}\n\nexport function createMetadataKey<T = never>(key: string, opts?: Omit<CreateMetadataKeyOptions, 'key'>): MetadataKey<T>;\nexport function createMetadataKey<T = never>(opts: CreateMetadataKeyOptions): MetadataKey<T>;\nexport function createMetadataKey<T = never>(a: any, b?: any): MetadataKey<T> {\n const opts: CreateMetadataKeyOptions =\n typeof a === 'string'\n ? {\n key: a,\n ...b,\n }\n : a;\n\n const { key } = opts;\n opts.title ||= startCase(key);\n\n const k: MetadataKey<T> = {\n ...opts,\n type: null as any,\n } as MetadataKey<T>;\n\n if ('toStringTag' in Symbol && typeof Symbol.toStringTag === 'symbol') {\n Object.defineProperty(k, Symbol.toStringTag, {\n value: key,\n });\n }\n\n return k;\n}\n\nexport function defineMetadata<T>(res: HasMetadata, key: MetadataKey<T>, opts: T) {\n res.metadata = res.metadata || {};\n
|
|
1
|
+
{"version":3,"sources":["../../src/meta/defineMetadata.ts"],"sourcesContent":["import { startCase } from 'es-toolkit';\nimport { get, set } from 'es-toolkit/compat';\n\ntype HasMetadata = {\n metadata?: Record<string, any>;\n};\n\ntype MetadataKey<T> = {\n key: string;\n type: T;\n title: string;\n description?: string;\n};\n\ninterface CreateMetadataKeyOptions {\n key: string;\n title?: string;\n description?: string;\n}\n\nexport function createMetadataKey<T = never>(key: string, opts?: Omit<CreateMetadataKeyOptions, 'key'>): MetadataKey<T>;\nexport function createMetadataKey<T = never>(opts: CreateMetadataKeyOptions): MetadataKey<T>;\nexport function createMetadataKey<T = never>(a: any, b?: any): MetadataKey<T> {\n const opts: CreateMetadataKeyOptions =\n typeof a === 'string'\n ? {\n key: a,\n ...b,\n }\n : a;\n\n const { key } = opts;\n opts.title ||= startCase(key);\n\n const k: MetadataKey<T> = {\n ...opts,\n type: null as any,\n } as MetadataKey<T>;\n\n if ('toStringTag' in Symbol && typeof Symbol.toStringTag === 'symbol') {\n Object.defineProperty(k, Symbol.toStringTag, {\n value: key,\n });\n }\n\n return k;\n}\n\nexport function defineMetadata<T>(res: HasMetadata, key: MetadataKey<T>, opts: T): void;\nexport function defineMetadata<T>(key: MetadataKey<T>, items: Array<[HasMetadata, T]>): void;\nexport function defineMetadata<T>(a: any, b: any, c?: any) {\n if (Array.isArray(b)) {\n const key = a;\n const items = b;\n for (const [res, opts] of items) {\n defineMetadata(res, key, opts);\n }\n } else {\n const res = a;\n const key = b;\n const opts = c;\n res.metadata = res.metadata || {};\n set(res.metadata, key.key, opts);\n }\n}\n\nexport function getMetadata<T>(res: HasMetadata | undefined | null, key: MetadataKey<T>): T | undefined {\n if (!res?.metadata) return undefined;\n return get(res.metadata, key.key);\n}\n"],"names":["startCase","get","set","createMetadataKey","a","b","opts","key","title","k","type","Symbol","toStringTag","Object","defineProperty","value","defineMetadata","c","Array","isArray","items","res","metadata","getMetadata","undefined"],"mappings":"AAAA,SAASA,SAAS,QAAQ,aAAa;AACvC,SAASC,GAAG,EAAEC,GAAG,QAAQ,oBAAoB;AAqB7C,OAAO,SAASC,kBAA6BC,CAAM,EAAEC,CAAO;IAC1D,MAAMC,OACJ,OAAOF,MAAM,WACT;QACEG,KAAKH;QACL,GAAGC,CAAC;IACN,IACAD;IAEN,MAAM,EAAEG,GAAG,EAAE,GAAGD;IAChBA,KAAKE,KAAK,KAAKR,UAAUO;IAEzB,MAAME,IAAoB;QACxB,GAAGH,IAAI;QACPI,MAAM;IACR;IAEA,IAAI,iBAAiBC,UAAU,OAAOA,OAAOC,WAAW,KAAK,UAAU;QACrEC,OAAOC,cAAc,CAACL,GAAGE,OAAOC,WAAW,EAAE;YAC3CG,OAAOR;QACT;IACF;IAEA,OAAOE;AACT;AAIA,OAAO,SAASO,eAAkBZ,CAAM,EAAEC,CAAM,EAAEY,CAAO;IACvD,IAAIC,MAAMC,OAAO,CAACd,IAAI;QACpB,MAAME,MAAMH;QACZ,MAAMgB,QAAQf;QACd,KAAK,MAAM,CAACgB,KAAKf,KAAK,IAAIc,MAAO;YAC/BJ,eAAeK,KAAKd,KAAKD;QAC3B;IACF,OAAO;QACL,MAAMe,MAAMjB;QACZ,MAAMG,MAAMF;QACZ,MAAMC,OAAOW;QACbI,IAAIC,QAAQ,GAAGD,IAAIC,QAAQ,IAAI,CAAC;QAChCpB,IAAImB,IAAIC,QAAQ,EAAEf,IAAIA,GAAG,EAAED;IAC7B;AACF;AAEA,OAAO,SAASiB,YAAeF,GAAmC,EAAEd,GAAmB;IACrF,IAAI,CAACc,KAAKC,UAAU,OAAOE;IAC3B,OAAOvB,IAAIoB,IAAIC,QAAQ,EAAEf,IAAIA,GAAG;AAClC"}
|
package/lib/meta/index.js
CHANGED
package/lib/meta/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/meta/index.ts"],"sourcesContent":["export { createMetadataKey, defineMetadata, getMetadata } from './defineMetadata';\n\nexport { defineInit, type InitDef, runInit } from './defineInit';\n"],"names":["createMetadataKey","defineMetadata","getMetadata","defineInit","runInit"],"mappings":"AAAA,SAASA,iBAAiB,EAAEC,cAAc,EAAEC,WAAW,QAAQ,mBAAmB;AAElF,SAASC,UAAU,EAAgBC,OAAO,QAAQ,eAAe"}
|
|
1
|
+
{"version":3,"sources":["../../src/meta/index.ts"],"sourcesContent":["export { createMetadataKey, defineMetadata, getMetadata } from './defineMetadata';\n\nexport { defineInit, type InitDef, runInit } from './defineInit';\n\nexport { defineFileType, getFileType, type FileTypeDef } from './defineFileType';\n"],"names":["createMetadataKey","defineMetadata","getMetadata","defineInit","runInit","defineFileType","getFileType"],"mappings":"AAAA,SAASA,iBAAiB,EAAEC,cAAc,EAAEC,WAAW,QAAQ,mBAAmB;AAElF,SAASC,UAAU,EAAgBC,OAAO,QAAQ,eAAe;AAEjE,SAASC,cAAc,EAAEC,WAAW,QAA0B,mBAAmB"}
|
package/lib/parseSort.js
CHANGED
|
@@ -87,5 +87,20 @@ function _parse(v) {
|
|
|
87
87
|
nulls
|
|
88
88
|
};
|
|
89
89
|
}
|
|
90
|
+
export function formatSort(s) {
|
|
91
|
+
return s.map(({ field, order, nulls })=>{
|
|
92
|
+
if (field) {
|
|
93
|
+
let r = field;
|
|
94
|
+
if (order) {
|
|
95
|
+
r += ` ${order}`;
|
|
96
|
+
}
|
|
97
|
+
if (nulls) {
|
|
98
|
+
r += ` nulls ${nulls}`;
|
|
99
|
+
}
|
|
100
|
+
return r;
|
|
101
|
+
}
|
|
102
|
+
return '';
|
|
103
|
+
}).filter(Boolean);
|
|
104
|
+
}
|
|
90
105
|
|
|
91
106
|
//# sourceMappingURL=parseSort.js.map
|
package/lib/parseSort.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/parseSort.ts"],"sourcesContent":["import { arrayOfMaybeArray, type MaybeArray } from '@wener/utils';\n\nexport type SortRule = {\n field: string;\n order: 'asc' | 'desc';\n nulls?: 'last' | 'first';\n};\n\n/**\n * parsing order string\n *\n * e.g.\n * ```\n * a desc\n * +a,-b\n * a asc nulls last\n * a desc first\n * ```\n */\nexport function parseSort(\n order:\n | MaybeArray<\n | {\n field?: string;\n order?: string;\n nulls?: string;\n }\n | string\n >\n | undefined\n | null,\n): SortRule[] {\n if (!order) {\n return [];\n }\n\n return arrayOfMaybeArray(order).flatMap((v): MaybeArray<SortRule> => {\n if (!v) return [];\n if (typeof v === 'object') {\n // invalid\n if (!v.field) {\n return [];\n }\n let rule: SortRule = {\n field: v.field,\n order: v.order?.toLowerCase() === 'asc' ? 'asc' : 'desc',\n };\n if (v.nulls) {\n rule.nulls = v.nulls.toLowerCase() === 'last' ? 'last' : 'first';\n }\n return rule;\n }\n return v\n .split(',')\n .map((v) => v.trim())\n .filter(Boolean)\n .map(_parse);\n });\n}\n\nfunction _parse(v: string) {\n // const sp = v.match(/^(?<field>[a-z0-9_]+)(\\s+(?<order>asc|desc))?(\\s+(?<nulls>nulls\\s+(?<nulls_order>last|first)))?$/i);\n const sp = v.split(/\\s+/);\n let field = '';\n let order: SortRule['order'];\n let nulls: SortRule['nulls'];\n\n const f = sp.shift()!;\n if (f.startsWith('-') || f.startsWith('+')) {\n // (order = f.slice(1).trim()), f.startsWith('-') ? 'desc' : 'asc';\n field = f.slice(1).trim();\n order = f.startsWith('-') ? 'desc' : 'asc';\n } else {\n field = f.trim();\n }\n\n while (true) {\n const v = sp.shift()?.trim()?.toLowerCase();\n if (!v) {\n break;\n }\n\n switch (v) {\n case 'asc':\n case 'desc': {\n order = v;\n break;\n }\n\n case 'nulls': {\n nulls = sp.shift()?.trim()?.toLowerCase() === 'last' ? 'last' : 'first';\n break;\n }\n\n case 'last':\n case 'first': {\n nulls = v;\n break;\n }\n }\n }\n\n order ||= 'asc';\n // avoid undefined\n // NOTE pg default nulls first for desc, last for asc\n // https://www.postgresql.org/docs/current/queries-order.html\n if (!nulls) {\n return { field, order };\n }\n return {\n field,\n order,\n nulls,\n };\n}\n"],"names":["arrayOfMaybeArray","parseSort","order","flatMap","v","field","rule","toLowerCase","nulls","split","map","trim","filter","Boolean","_parse","sp","f","shift","startsWith","slice"],"mappings":"AAAA,SAASA,iBAAiB,QAAyB,eAAe;AAQlE;;;;;;;;;;CAUC,GACD,OAAO,SAASC,UACdC,KAUQ;IAER,IAAI,CAACA,OAAO;QACV,OAAO,EAAE;IACX;IAEA,OAAOF,kBAAkBE,OAAOC,OAAO,CAAC,CAACC;QACvC,IAAI,CAACA,GAAG,OAAO,EAAE;QACjB,IAAI,OAAOA,MAAM,UAAU;YACzB,UAAU;YACV,IAAI,CAACA,EAAEC,KAAK,EAAE;gBACZ,OAAO,EAAE;YACX;YACA,IAAIC,OAAiB;gBACnBD,OAAOD,EAAEC,KAAK;gBACdH,OAAOE,EAAEF,KAAK,EAAEK,kBAAkB,QAAQ,QAAQ;YACpD;YACA,IAAIH,EAAEI,KAAK,EAAE;gBACXF,KAAKE,KAAK,GAAGJ,EAAEI,KAAK,CAACD,WAAW,OAAO,SAAS,SAAS;YAC3D;YACA,OAAOD;QACT;QACA,OAAOF,EACJK,KAAK,CAAC,KACNC,GAAG,CAAC,CAACN,IAAMA,EAAEO,IAAI,IACjBC,MAAM,CAACC,SACPH,GAAG,CAACI;IACT;AACF;AAEA,SAASA,OAAOV,CAAS;IACvB,2HAA2H;IAC3H,MAAMW,KAAKX,EAAEK,KAAK,CAAC;IACnB,IAAIJ,QAAQ;IACZ,IAAIH;IACJ,IAAIM;IAEJ,MAAMQ,IAAID,GAAGE,KAAK;IAClB,IAAID,EAAEE,UAAU,CAAC,QAAQF,EAAEE,UAAU,CAAC,MAAM;QAC1C,mEAAmE;QACnEb,QAAQW,EAAEG,KAAK,CAAC,GAAGR,IAAI;QACvBT,QAAQc,EAAEE,UAAU,CAAC,OAAO,SAAS;IACvC,OAAO;QACLb,QAAQW,EAAEL,IAAI;IAChB;IAEA,MAAO,KAAM;QACX,MAAMP,IAAIW,GAAGE,KAAK,IAAIN,QAAQJ;QAC9B,IAAI,CAACH,GAAG;YACN;QACF;QAEA,OAAQA;YACN,KAAK;YACL,KAAK;gBAAQ;oBACXF,QAAQE;oBACR;gBACF;YAEA,KAAK;gBAAS;oBACZI,QAAQO,GAAGE,KAAK,IAAIN,QAAQJ,kBAAkB,SAAS,SAAS;oBAChE;gBACF;YAEA,KAAK;YACL,KAAK;gBAAS;oBACZC,QAAQJ;oBACR;gBACF;QACF;IACF;IAEAF,UAAU;IACV,kBAAkB;IAClB,qDAAqD;IACrD,6DAA6D;IAC7D,IAAI,CAACM,OAAO;QACV,OAAO;YAAEH;YAAOH;QAAM;IACxB;IACA,OAAO;QACLG;QACAH;QACAM;IACF;AACF"}
|
|
1
|
+
{"version":3,"sources":["../src/parseSort.ts"],"sourcesContent":["import { arrayOfMaybeArray, type MaybeArray } from '@wener/utils';\n\nexport type SortRule = {\n field: string;\n order: 'asc' | 'desc';\n nulls?: 'last' | 'first';\n};\n\n/**\n * parsing order string\n *\n * e.g.\n * ```\n * a desc\n * +a,-b\n * a asc nulls last\n * a desc first\n * ```\n */\nexport function parseSort(\n order:\n | MaybeArray<\n | {\n field?: string;\n order?: string;\n nulls?: string;\n }\n | string\n >\n | undefined\n | null,\n): SortRule[] {\n if (!order) {\n return [];\n }\n\n return arrayOfMaybeArray(order).flatMap((v): MaybeArray<SortRule> => {\n if (!v) return [];\n if (typeof v === 'object') {\n // invalid\n if (!v.field) {\n return [];\n }\n let rule: SortRule = {\n field: v.field,\n order: v.order?.toLowerCase() === 'asc' ? 'asc' : 'desc',\n };\n if (v.nulls) {\n rule.nulls = v.nulls.toLowerCase() === 'last' ? 'last' : 'first';\n }\n return rule;\n }\n return v\n .split(',')\n .map((v) => v.trim())\n .filter(Boolean)\n .map(_parse);\n });\n}\n\nfunction _parse(v: string) {\n // const sp = v.match(/^(?<field>[a-z0-9_]+)(\\s+(?<order>asc|desc))?(\\s+(?<nulls>nulls\\s+(?<nulls_order>last|first)))?$/i);\n const sp = v.split(/\\s+/);\n let field = '';\n let order: SortRule['order'];\n let nulls: SortRule['nulls'];\n\n const f = sp.shift()!;\n if (f.startsWith('-') || f.startsWith('+')) {\n // (order = f.slice(1).trim()), f.startsWith('-') ? 'desc' : 'asc';\n field = f.slice(1).trim();\n order = f.startsWith('-') ? 'desc' : 'asc';\n } else {\n field = f.trim();\n }\n\n while (true) {\n const v = sp.shift()?.trim()?.toLowerCase();\n if (!v) {\n break;\n }\n\n switch (v) {\n case 'asc':\n case 'desc': {\n order = v;\n break;\n }\n\n case 'nulls': {\n nulls = sp.shift()?.trim()?.toLowerCase() === 'last' ? 'last' : 'first';\n break;\n }\n\n case 'last':\n case 'first': {\n nulls = v;\n break;\n }\n }\n }\n\n order ||= 'asc';\n // avoid undefined\n // NOTE pg default nulls first for desc, last for asc\n // https://www.postgresql.org/docs/current/queries-order.html\n if (!nulls) {\n return { field, order };\n }\n return {\n field,\n order,\n nulls,\n };\n}\n\nexport function formatSort(s: SortRule[]): string[] {\n return s\n .map(({ field, order, nulls }) => {\n if (field) {\n let r = field;\n if (order) {\n r += ` ${order}`;\n }\n if (nulls) {\n r += ` nulls ${nulls}`;\n }\n return r;\n }\n return '';\n })\n .filter(Boolean);\n}\n"],"names":["arrayOfMaybeArray","parseSort","order","flatMap","v","field","rule","toLowerCase","nulls","split","map","trim","filter","Boolean","_parse","sp","f","shift","startsWith","slice","formatSort","s","r"],"mappings":"AAAA,SAASA,iBAAiB,QAAyB,eAAe;AAQlE;;;;;;;;;;CAUC,GACD,OAAO,SAASC,UACdC,KAUQ;IAER,IAAI,CAACA,OAAO;QACV,OAAO,EAAE;IACX;IAEA,OAAOF,kBAAkBE,OAAOC,OAAO,CAAC,CAACC;QACvC,IAAI,CAACA,GAAG,OAAO,EAAE;QACjB,IAAI,OAAOA,MAAM,UAAU;YACzB,UAAU;YACV,IAAI,CAACA,EAAEC,KAAK,EAAE;gBACZ,OAAO,EAAE;YACX;YACA,IAAIC,OAAiB;gBACnBD,OAAOD,EAAEC,KAAK;gBACdH,OAAOE,EAAEF,KAAK,EAAEK,kBAAkB,QAAQ,QAAQ;YACpD;YACA,IAAIH,EAAEI,KAAK,EAAE;gBACXF,KAAKE,KAAK,GAAGJ,EAAEI,KAAK,CAACD,WAAW,OAAO,SAAS,SAAS;YAC3D;YACA,OAAOD;QACT;QACA,OAAOF,EACJK,KAAK,CAAC,KACNC,GAAG,CAAC,CAACN,IAAMA,EAAEO,IAAI,IACjBC,MAAM,CAACC,SACPH,GAAG,CAACI;IACT;AACF;AAEA,SAASA,OAAOV,CAAS;IACvB,2HAA2H;IAC3H,MAAMW,KAAKX,EAAEK,KAAK,CAAC;IACnB,IAAIJ,QAAQ;IACZ,IAAIH;IACJ,IAAIM;IAEJ,MAAMQ,IAAID,GAAGE,KAAK;IAClB,IAAID,EAAEE,UAAU,CAAC,QAAQF,EAAEE,UAAU,CAAC,MAAM;QAC1C,mEAAmE;QACnEb,QAAQW,EAAEG,KAAK,CAAC,GAAGR,IAAI;QACvBT,QAAQc,EAAEE,UAAU,CAAC,OAAO,SAAS;IACvC,OAAO;QACLb,QAAQW,EAAEL,IAAI;IAChB;IAEA,MAAO,KAAM;QACX,MAAMP,IAAIW,GAAGE,KAAK,IAAIN,QAAQJ;QAC9B,IAAI,CAACH,GAAG;YACN;QACF;QAEA,OAAQA;YACN,KAAK;YACL,KAAK;gBAAQ;oBACXF,QAAQE;oBACR;gBACF;YAEA,KAAK;gBAAS;oBACZI,QAAQO,GAAGE,KAAK,IAAIN,QAAQJ,kBAAkB,SAAS,SAAS;oBAChE;gBACF;YAEA,KAAK;YACL,KAAK;gBAAS;oBACZC,QAAQJ;oBACR;gBACF;QACF;IACF;IAEAF,UAAU;IACV,kBAAkB;IAClB,qDAAqD;IACrD,6DAA6D;IAC7D,IAAI,CAACM,OAAO;QACV,OAAO;YAAEH;YAAOH;QAAM;IACxB;IACA,OAAO;QACLG;QACAH;QACAM;IACF;AACF;AAEA,OAAO,SAASY,WAAWC,CAAa;IACtC,OAAOA,EACJX,GAAG,CAAC,CAAC,EAAEL,KAAK,EAAEH,KAAK,EAAEM,KAAK,EAAE;QAC3B,IAAIH,OAAO;YACT,IAAIiB,IAAIjB;YACR,IAAIH,OAAO;gBACToB,KAAK,CAAC,CAAC,EAAEpB,OAAO;YAClB;YACA,IAAIM,OAAO;gBACTc,KAAK,CAAC,OAAO,EAAEd,OAAO;YACxB;YACA,OAAOc;QACT;QACA,OAAO;IACT,GACCV,MAAM,CAACC;AACZ"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { formatAdvanceSearch } from "./formatAdvanceSearch.js";
|
|
2
|
+
import { optimizeAdvanceSearch } from "./optimizeAdvanceSearch.js";
|
|
3
|
+
import { parseAdvanceSearch } from "./parseAdvanceSearch.js";
|
|
4
|
+
(function (AdvanceSearch) {
|
|
5
|
+
AdvanceSearch.parse = parseAdvanceSearch;
|
|
6
|
+
AdvanceSearch.format = formatAdvanceSearch;
|
|
7
|
+
AdvanceSearch.optimize = optimizeAdvanceSearch;
|
|
8
|
+
})(AdvanceSearch || (AdvanceSearch = {}));
|
|
9
|
+
export var AdvanceSearch;
|
|
10
|
+
//# sourceMappingURL=AdvanceSearch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/search/AdvanceSearch.ts"],"sourcesContent":["import { formatAdvanceSearch } from './formatAdvanceSearch';\nimport { optimizeAdvanceSearch } from './optimizeAdvanceSearch';\nimport { parseAdvanceSearch } from './parseAdvanceSearch';\nimport type * as types from './types';\n\nexport namespace AdvanceSearch {\n export type Exprs = types.Exprs;\n export type Expr = types.Expr;\n export type Value = types.Value;\n\n export const parse = parseAdvanceSearch;\n export const format = formatAdvanceSearch;\n export const optimize = optimizeAdvanceSearch;\n}\n"],"names":["formatAdvanceSearch","optimizeAdvanceSearch","parseAdvanceSearch","AdvanceSearch","parse","format","optimize"],"mappings":"AAAA,SAASA,mBAAmB,QAAQ,wBAAwB;AAC5D,SAASC,qBAAqB,QAAQ,0BAA0B;AAChE,SAASC,kBAAkB,QAAQ,uBAAuB;UAGzCC;kBAKFC,QAAQF;kBACRG,SAASL;kBACTM,WAAWL;AAC1B,GARiBE,kBAAAA"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { match } from "ts-pattern";
|
|
2
|
+
export function formatAdvanceSearch(input) {
|
|
3
|
+
const OP = {
|
|
4
|
+
match: ':',
|
|
5
|
+
eq: ':=',
|
|
6
|
+
ne: ':!=',
|
|
7
|
+
gt: ':>',
|
|
8
|
+
lt: ':<',
|
|
9
|
+
gte: ':>=',
|
|
10
|
+
lte: ':<=',
|
|
11
|
+
range: ':'
|
|
12
|
+
};
|
|
13
|
+
const _exprs = (s)=>{
|
|
14
|
+
return s.map(_expr).join(' ');
|
|
15
|
+
};
|
|
16
|
+
const _expr = (s)=>{
|
|
17
|
+
return match(s).with({
|
|
18
|
+
type: 'keyword'
|
|
19
|
+
}, ({ value, exact, negative })=>{
|
|
20
|
+
return `${negative ? '-' : ''}${exact ? `"${value}"` : value}`;
|
|
21
|
+
}).with({
|
|
22
|
+
type: 'logical'
|
|
23
|
+
}, ({ operator, value })=>value.map(_expr).join(` ${operator.toLocaleUpperCase()} `)).with({
|
|
24
|
+
type: 'not'
|
|
25
|
+
}, ({ value })=>`NOT ${_expr(value)}`).with({
|
|
26
|
+
type: 'compare'
|
|
27
|
+
}, ({ field, operator, value, negative, mention })=>{
|
|
28
|
+
return `${negative ? '-' : ''}${mention ? '@' : ''}${field}${OP[operator]}${_value(value)}`;
|
|
29
|
+
}).with({
|
|
30
|
+
type: 'comment'
|
|
31
|
+
}, ({ value })=>`/* ${value} */`).with({
|
|
32
|
+
type: 'parentheses'
|
|
33
|
+
}, ({ value })=>`(${_exprs(value)})`).exhaustive();
|
|
34
|
+
};
|
|
35
|
+
const _literal = (s)=>{
|
|
36
|
+
if (typeof s === 'string') {
|
|
37
|
+
return s.includes(' ') ? `"${s}"` : s;
|
|
38
|
+
}
|
|
39
|
+
return JSON.stringify(s);
|
|
40
|
+
};
|
|
41
|
+
const _value = (v)=>{
|
|
42
|
+
return match(v).with({
|
|
43
|
+
type: 'range'
|
|
44
|
+
}, ({ minimum, maximum, minimumExclusive, maximumExclusive })=>{
|
|
45
|
+
if (minimumExclusive === undefined && maximumExclusive === undefined) {
|
|
46
|
+
let min = minimum === undefined ? '*' : _value(minimum);
|
|
47
|
+
let max = maximum === undefined ? '*' : _value(maximum);
|
|
48
|
+
return `${min}..${max}`;
|
|
49
|
+
}
|
|
50
|
+
let min = minimum === undefined ? '' : _value(minimum);
|
|
51
|
+
let max = maximum === undefined ? '' : _value(maximum);
|
|
52
|
+
return `${minimumExclusive ? '(' : '['}${min},${max}${maximumExclusive ? ')' : ']'}`;
|
|
53
|
+
}).with({
|
|
54
|
+
format: 'mention'
|
|
55
|
+
}, ({ value })=>{
|
|
56
|
+
return `@${value}`;
|
|
57
|
+
}).otherwise((value)=>{
|
|
58
|
+
return _literal(value.value);
|
|
59
|
+
});
|
|
60
|
+
};
|
|
61
|
+
return _exprs(input);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
//# sourceMappingURL=formatAdvanceSearch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/search/formatAdvanceSearch.ts"],"sourcesContent":["import { match } from 'ts-pattern';\nimport { AdvanceSearch } from './AdvanceSearch';\n\nexport function formatAdvanceSearch(input: AdvanceSearch.Expr[]) {\n const OP = {\n match: ':',\n eq: ':=',\n ne: ':!=',\n gt: ':>',\n lt: ':<',\n gte: ':>=',\n lte: ':<=',\n range: ':',\n } as const;\n\n const _exprs = (s: AdvanceSearch.Expr[]): string => {\n return s.map(_expr).join(' ');\n };\n const _expr = (s: AdvanceSearch.Expr): string => {\n return match(s)\n .with({ type: 'keyword' }, ({ value, exact, negative }) => {\n return `${negative ? '-' : ''}${exact ? `\"${value}\"` : value}`;\n })\n .with({ type: 'logical' }, ({ operator, value }) => value.map(_expr).join(` ${operator.toLocaleUpperCase()} `))\n .with({ type: 'not' }, ({ value }) => `NOT ${_expr(value)}`)\n .with({ type: 'compare' }, ({ field, operator, value, negative, mention }) => {\n return `${negative ? '-' : ''}${mention ? '@' : ''}${field}${OP[operator]}${_value(value)}`;\n })\n .with({ type: 'comment' }, ({ value }) => `/* ${value} */`)\n .with({ type: 'parentheses' }, ({ value }) => `(${_exprs(value)})`)\n .exhaustive();\n };\n\n const _literal = (s: string | null | number) => {\n if (typeof s === 'string') {\n return s.includes(' ') ? `\"${s}\"` : s;\n }\n return JSON.stringify(s);\n };\n const _value = (v: AdvanceSearch.Value): string => {\n return match(v)\n .with({ type: 'range' }, ({ minimum, maximum, minimumExclusive, maximumExclusive }) => {\n if (minimumExclusive === undefined && maximumExclusive === undefined) {\n let min = minimum === undefined ? '*' : _value(minimum);\n let max = maximum === undefined ? '*' : _value(maximum);\n return `${min}..${max}`;\n }\n let min = minimum === undefined ? '' : _value(minimum);\n let max = maximum === undefined ? '' : _value(maximum);\n return `${minimumExclusive ? '(' : '['}${min},${max}${maximumExclusive ? ')' : ']'}`;\n })\n .with({ format: 'mention' }, ({ value }) => {\n return `@${value}`;\n })\n .otherwise((value) => {\n return _literal(value.value);\n });\n };\n\n return _exprs(input);\n}\n"],"names":["match","formatAdvanceSearch","input","OP","eq","ne","gt","lt","gte","lte","range","_exprs","s","map","_expr","join","with","type","value","exact","negative","operator","toLocaleUpperCase","field","mention","_value","exhaustive","_literal","includes","JSON","stringify","v","minimum","maximum","minimumExclusive","maximumExclusive","undefined","min","max","format","otherwise"],"mappings":"AAAA,SAASA,KAAK,QAAQ,aAAa;AAGnC,OAAO,SAASC,oBAAoBC,KAA2B;IAC7D,MAAMC,KAAK;QACTH,OAAO;QACPI,IAAI;QACJC,IAAI;QACJC,IAAI;QACJC,IAAI;QACJC,KAAK;QACLC,KAAK;QACLC,OAAO;IACT;IAEA,MAAMC,SAAS,CAACC;QACd,OAAOA,EAAEC,GAAG,CAACC,OAAOC,IAAI,CAAC;IAC3B;IACA,MAAMD,QAAQ,CAACF;QACb,OAAOZ,MAAMY,GACVI,IAAI,CAAC;YAAEC,MAAM;QAAU,GAAG,CAAC,EAAEC,KAAK,EAAEC,KAAK,EAAEC,QAAQ,EAAE;YACpD,OAAO,GAAGA,WAAW,MAAM,KAAKD,QAAQ,CAAC,CAAC,EAAED,MAAM,CAAC,CAAC,GAAGA,OAAO;QAChE,GACCF,IAAI,CAAC;YAAEC,MAAM;QAAU,GAAG,CAAC,EAAEI,QAAQ,EAAEH,KAAK,EAAE,GAAKA,MAAML,GAAG,CAACC,OAAOC,IAAI,CAAC,CAAC,CAAC,EAAEM,SAASC,iBAAiB,GAAG,CAAC,CAAC,GAC5GN,IAAI,CAAC;YAAEC,MAAM;QAAM,GAAG,CAAC,EAAEC,KAAK,EAAE,GAAK,CAAC,IAAI,EAAEJ,MAAMI,QAAQ,EAC1DF,IAAI,CAAC;YAAEC,MAAM;QAAU,GAAG,CAAC,EAAEM,KAAK,EAAEF,QAAQ,EAAEH,KAAK,EAAEE,QAAQ,EAAEI,OAAO,EAAE;YACvE,OAAO,GAAGJ,WAAW,MAAM,KAAKI,UAAU,MAAM,KAAKD,QAAQpB,EAAE,CAACkB,SAAS,GAAGI,OAAOP,QAAQ;QAC7F,GACCF,IAAI,CAAC;YAAEC,MAAM;QAAU,GAAG,CAAC,EAAEC,KAAK,EAAE,GAAK,CAAC,GAAG,EAAEA,MAAM,GAAG,CAAC,EACzDF,IAAI,CAAC;YAAEC,MAAM;QAAc,GAAG,CAAC,EAAEC,KAAK,EAAE,GAAK,CAAC,CAAC,EAAEP,OAAOO,OAAO,CAAC,CAAC,EACjEQ,UAAU;IACf;IAEA,MAAMC,WAAW,CAACf;QAChB,IAAI,OAAOA,MAAM,UAAU;YACzB,OAAOA,EAAEgB,QAAQ,CAAC,OAAO,CAAC,CAAC,EAAEhB,EAAE,CAAC,CAAC,GAAGA;QACtC;QACA,OAAOiB,KAAKC,SAAS,CAAClB;IACxB;IACA,MAAMa,SAAS,CAACM;QACd,OAAO/B,MAAM+B,GACVf,IAAI,CAAC;YAAEC,MAAM;QAAQ,GAAG,CAAC,EAAEe,OAAO,EAAEC,OAAO,EAAEC,gBAAgB,EAAEC,gBAAgB,EAAE;YAChF,IAAID,qBAAqBE,aAAaD,qBAAqBC,WAAW;gBACpE,IAAIC,MAAML,YAAYI,YAAY,MAAMX,OAAOO;gBAC/C,IAAIM,MAAML,YAAYG,YAAY,MAAMX,OAAOQ;gBAC/C,OAAO,GAAGI,IAAI,EAAE,EAAEC,KAAK;YACzB;YACA,IAAID,MAAML,YAAYI,YAAY,KAAKX,OAAOO;YAC9C,IAAIM,MAAML,YAAYG,YAAY,KAAKX,OAAOQ;YAC9C,OAAO,GAAGC,mBAAmB,MAAM,MAAMG,IAAI,CAAC,EAAEC,MAAMH,mBAAmB,MAAM,KAAK;QACtF,GACCnB,IAAI,CAAC;YAAEuB,QAAQ;QAAU,GAAG,CAAC,EAAErB,KAAK,EAAE;YACrC,OAAO,CAAC,CAAC,EAAEA,OAAO;QACpB,GACCsB,SAAS,CAAC,CAACtB;YACV,OAAOS,SAAST,MAAMA,KAAK;QAC7B;IACJ;IAEA,OAAOP,OAAOT;AAChB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/search/index.ts"],"sourcesContent":["export { AdvanceSearch } from './AdvanceSearch';\n"],"names":["AdvanceSearch"],"mappings":"AAAA,SAASA,aAAa,QAAQ,kBAAkB"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { arrayOfMaybeArray, deepEqual } from "@wener/utils";
|
|
2
|
+
import { match } from "ts-pattern";
|
|
3
|
+
export function optimizeAdvanceSearch(expr) {
|
|
4
|
+
const NEG = {
|
|
5
|
+
eq: 'ne',
|
|
6
|
+
ne: 'eq',
|
|
7
|
+
gt: 'lte',
|
|
8
|
+
lt: 'gte',
|
|
9
|
+
gte: 'lt',
|
|
10
|
+
lte: 'gt'
|
|
11
|
+
};
|
|
12
|
+
const _expr = (e)=>{
|
|
13
|
+
// merge Exprs to AND ?
|
|
14
|
+
return match(e)// (EXPR) -> EXPR
|
|
15
|
+
// TODO (EXPR EXPR) -> EXPR AND EXPR
|
|
16
|
+
.with({
|
|
17
|
+
type: 'parentheses'
|
|
18
|
+
}, (expr)=>{
|
|
19
|
+
// unwrap
|
|
20
|
+
if (expr.value.length < 2) {
|
|
21
|
+
return expr.value[0];
|
|
22
|
+
}
|
|
23
|
+
expr.value = expr.value.flatMap(_expr);
|
|
24
|
+
return expr;
|
|
25
|
+
}).with({
|
|
26
|
+
type: 'comment'
|
|
27
|
+
}, (expr)=>{
|
|
28
|
+
// remove empty comment
|
|
29
|
+
if (!expr.value.length) {
|
|
30
|
+
return [];
|
|
31
|
+
}
|
|
32
|
+
return expr;
|
|
33
|
+
})// NOT
|
|
34
|
+
.with({
|
|
35
|
+
type: 'not'
|
|
36
|
+
}, (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 match(expr.value)// NOT NOT EXPR -> EXPR
|
|
46
|
+
.with({
|
|
47
|
+
type: 'not'
|
|
48
|
+
}, (expr)=>expr.value)// NOT EXPR -> -EXPR
|
|
49
|
+
.with({
|
|
50
|
+
type: 'compare'
|
|
51
|
+
}, (expr)=>{
|
|
52
|
+
return {
|
|
53
|
+
...expr,
|
|
54
|
+
negative: !expr.negative
|
|
55
|
+
};
|
|
56
|
+
}).with({
|
|
57
|
+
type: 'keyword'
|
|
58
|
+
}, (expr)=>{
|
|
59
|
+
return {
|
|
60
|
+
...expr,
|
|
61
|
+
negative: !expr.negative
|
|
62
|
+
};
|
|
63
|
+
}).otherwise(()=>expr);
|
|
64
|
+
}).with({
|
|
65
|
+
type: 'compare'
|
|
66
|
+
}, (expr)=>{
|
|
67
|
+
// negative by swap operator
|
|
68
|
+
if (expr.negative) {
|
|
69
|
+
const ne = NEG[expr.operator];
|
|
70
|
+
if (ne) {
|
|
71
|
+
expr.operator = ne;
|
|
72
|
+
expr.negative = false;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
if (expr.operator === 'range') {}
|
|
76
|
+
return expr;
|
|
77
|
+
}).otherwise((e)=>e);
|
|
78
|
+
};
|
|
79
|
+
let last = expr;
|
|
80
|
+
while(true){
|
|
81
|
+
let next = structuredClone(last).flatMap(_expr);
|
|
82
|
+
if (deepEqual(last, next)) {
|
|
83
|
+
return last;
|
|
84
|
+
}
|
|
85
|
+
last = next;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
//# sourceMappingURL=optimizeAdvanceSearch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/search/optimizeAdvanceSearch.ts"],"sourcesContent":["import { arrayOfMaybeArray, deepEqual, type MaybeArray } from '@wener/utils';\nimport { match } from 'ts-pattern';\nimport { AdvanceSearch } from './AdvanceSearch';\n\nexport function optimizeAdvanceSearch(expr: AdvanceSearch.Exprs): AdvanceSearch.Exprs {\n const NEG = {\n eq: 'ne',\n ne: 'eq',\n gt: 'lte',\n lt: 'gte',\n gte: 'lt',\n lte: 'gt',\n } as const;\n const _expr = (e: AdvanceSearch.Expr): MaybeArray<AdvanceSearch.Expr> => {\n // merge Exprs to AND ?\n return (\n match(e)\n // (EXPR) -> EXPR\n // TODO (EXPR EXPR) -> EXPR AND EXPR\n .with({ type: 'parentheses' }, (expr) => {\n // unwrap\n if (expr.value.length < 2) {\n return expr.value[0];\n }\n expr.value = expr.value.flatMap(_expr);\n return expr;\n })\n .with({ type: 'comment' }, (expr) => {\n // remove empty comment\n if (!expr.value.length) {\n return [];\n }\n return expr;\n })\n // NOT\n .with({ type: 'not' }, (expr) => {\n let out = arrayOfMaybeArray(_expr(expr.value));\n if (!out.length) {\n return [];\n } else if (out.length === 1) {\n expr.value = out[0];\n } else {\n throw new Error('NOT should have only one value');\n }\n return (\n match(expr.value)\n // NOT NOT EXPR -> EXPR\n .with({ type: 'not' }, (expr) => expr.value)\n // NOT EXPR -> -EXPR\n .with({ type: 'compare' }, (expr) => {\n return {\n ...expr,\n negative: !expr.negative,\n };\n })\n .with({ type: 'keyword' }, (expr) => {\n return {\n ...expr,\n negative: !expr.negative,\n };\n })\n .otherwise(() => expr)\n );\n })\n .with({ type: 'compare' }, (expr) => {\n // negative by swap operator\n if (expr.negative) {\n const ne = NEG[expr.operator as keyof typeof NEG];\n if (ne) {\n expr.operator = ne;\n expr.negative = false;\n }\n }\n if (expr.operator === 'range') {\n }\n return expr;\n })\n .otherwise((e) => e)\n );\n };\n\n let last = expr;\n while (true) {\n let next = structuredClone(last).flatMap(_expr);\n if (deepEqual(last, next)) {\n return last;\n }\n last = next;\n }\n}\n"],"names":["arrayOfMaybeArray","deepEqual","match","optimizeAdvanceSearch","expr","NEG","eq","ne","gt","lt","gte","lte","_expr","e","with","type","value","length","flatMap","out","Error","negative","otherwise","operator","last","next","structuredClone"],"mappings":"AAAA,SAASA,iBAAiB,EAAEC,SAAS,QAAyB,eAAe;AAC7E,SAASC,KAAK,QAAQ,aAAa;AAGnC,OAAO,SAASC,sBAAsBC,IAAyB;IAC7D,MAAMC,MAAM;QACVC,IAAI;QACJC,IAAI;QACJC,IAAI;QACJC,IAAI;QACJC,KAAK;QACLC,KAAK;IACP;IACA,MAAMC,QAAQ,CAACC;QACb,uBAAuB;QACvB,OACEX,MAAMW,EACJ,iBAAiB;QACjB,oCAAoC;SACnCC,IAAI,CAAC;YAAEC,MAAM;QAAc,GAAG,CAACX;YAC9B,SAAS;YACT,IAAIA,KAAKY,KAAK,CAACC,MAAM,GAAG,GAAG;gBACzB,OAAOb,KAAKY,KAAK,CAAC,EAAE;YACtB;YACAZ,KAAKY,KAAK,GAAGZ,KAAKY,KAAK,CAACE,OAAO,CAACN;YAChC,OAAOR;QACT,GACCU,IAAI,CAAC;YAAEC,MAAM;QAAU,GAAG,CAACX;YAC1B,uBAAuB;YACvB,IAAI,CAACA,KAAKY,KAAK,CAACC,MAAM,EAAE;gBACtB,OAAO,EAAE;YACX;YACA,OAAOb;QACT,EACA,MAAM;SACLU,IAAI,CAAC;YAAEC,MAAM;QAAM,GAAG,CAACX;YACtB,IAAIe,MAAMnB,kBAAkBY,MAAMR,KAAKY,KAAK;YAC5C,IAAI,CAACG,IAAIF,MAAM,EAAE;gBACf,OAAO,EAAE;YACX,OAAO,IAAIE,IAAIF,MAAM,KAAK,GAAG;gBAC3Bb,KAAKY,KAAK,GAAGG,GAAG,CAAC,EAAE;YACrB,OAAO;gBACL,MAAM,IAAIC,MAAM;YAClB;YACA,OACElB,MAAME,KAAKY,KAAK,CACd,uBAAuB;aACtBF,IAAI,CAAC;gBAAEC,MAAM;YAAM,GAAG,CAACX,OAASA,KAAKY,KAAK,CAC3C,oBAAoB;aACnBF,IAAI,CAAC;gBAAEC,MAAM;YAAU,GAAG,CAACX;gBAC1B,OAAO;oBACL,GAAGA,IAAI;oBACPiB,UAAU,CAACjB,KAAKiB,QAAQ;gBAC1B;YACF,GACCP,IAAI,CAAC;gBAAEC,MAAM;YAAU,GAAG,CAACX;gBAC1B,OAAO;oBACL,GAAGA,IAAI;oBACPiB,UAAU,CAACjB,KAAKiB,QAAQ;gBAC1B;YACF,GACCC,SAAS,CAAC,IAAMlB;QAEvB,GACCU,IAAI,CAAC;YAAEC,MAAM;QAAU,GAAG,CAACX;YAC1B,4BAA4B;YAC5B,IAAIA,KAAKiB,QAAQ,EAAE;gBACjB,MAAMd,KAAKF,GAAG,CAACD,KAAKmB,QAAQ,CAAqB;gBACjD,IAAIhB,IAAI;oBACNH,KAAKmB,QAAQ,GAAGhB;oBAChBH,KAAKiB,QAAQ,GAAG;gBAClB;YACF;YACA,IAAIjB,KAAKmB,QAAQ,KAAK,SAAS,CAC/B;YACA,OAAOnB;QACT,GACCkB,SAAS,CAAC,CAACT,IAAMA;IAExB;IAEA,IAAIW,OAAOpB;IACX,MAAO,KAAM;QACX,IAAIqB,OAAOC,gBAAgBF,MAAMN,OAAO,CAACN;QACzC,IAAIX,UAAUuB,MAAMC,OAAO;YACzB,OAAOD;QACT;QACAA,OAAOC;IACT;AACF"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { parse } from "./parser.js";
|
|
2
|
+
export function parseAdvanceSearch(s) {
|
|
3
|
+
s = s?.trim();
|
|
4
|
+
if (!s) {
|
|
5
|
+
return [];
|
|
6
|
+
}
|
|
7
|
+
// no Logical, no Compare, no Quote, no Comment
|
|
8
|
+
if (!/AND|OR|NOT|[-"():]|\/\*/.test(s)) {
|
|
9
|
+
// fast path
|
|
10
|
+
return s.split(/\s+/).map((v)=>v.trim()).filter(Boolean).map((v)=>{
|
|
11
|
+
return {
|
|
12
|
+
type: 'keyword',
|
|
13
|
+
value: v
|
|
14
|
+
};
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
return parse(s);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
//# sourceMappingURL=parseAdvanceSearch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/search/parseAdvanceSearch.ts"],"sourcesContent":["import { AdvanceSearch } from './AdvanceSearch';\nimport { parse } from './parser';\n\nexport function parseAdvanceSearch(s: string | undefined | null): AdvanceSearch.Expr[] {\n s = s?.trim();\n if (!s) {\n return [];\n }\n\n // no Logical, no Compare, no Quote, no Comment\n if (!/AND|OR|NOT|[-\"():]|\\/\\*/.test(s)) {\n // fast path\n return s\n .split(/\\s+/)\n .map((v) => v.trim())\n .filter(Boolean)\n .map((v) => {\n return {\n type: 'keyword',\n value: v,\n };\n });\n }\n\n return parse(s);\n}\n"],"names":["parse","parseAdvanceSearch","s","trim","test","split","map","v","filter","Boolean","type","value"],"mappings":"AACA,SAASA,KAAK,QAAQ,cAAW;AAEjC,OAAO,SAASC,mBAAmBC,CAA4B;IAC7DA,IAAIA,GAAGC;IACP,IAAI,CAACD,GAAG;QACN,OAAO,EAAE;IACX;IAEA,+CAA+C;IAC/C,IAAI,CAAC,0BAA0BE,IAAI,CAACF,IAAI;QACtC,YAAY;QACZ,OAAOA,EACJG,KAAK,CAAC,OACNC,GAAG,CAAC,CAACC,IAAMA,EAAEJ,IAAI,IACjBK,MAAM,CAACC,SACPH,GAAG,CAAC,CAACC;YACJ,OAAO;gBACLG,MAAM;gBACNC,OAAOJ;YACT;QACF;IACJ;IAEA,OAAOP,MAAME;AACf"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/search/parser.d.ts"],"sourcesContent":["export function parse(input: string, options?: ParseOptions): any;\n\nexport interface ParseOptions {\n grammarSource?: string;\n startRule?: string;\n\n [k: string]: any;\n}\n"],"names":[],"mappings":"AAEA,WAKC"}
|