@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.
Files changed (74) hide show
  1. package/lib/cn/DivisionCode.js +311 -0
  2. package/lib/cn/DivisionCode.js.map +1 -0
  3. package/lib/cn/Mod11Checksum.js +42 -0
  4. package/lib/cn/Mod11Checksum.js.map +1 -0
  5. package/lib/cn/Mod31Checksum.js +48 -0
  6. package/lib/cn/Mod31Checksum.js.map +1 -0
  7. package/lib/cn/ResidentIdentityCardNumber.js +50 -0
  8. package/lib/cn/ResidentIdentityCardNumber.js.map +1 -0
  9. package/lib/cn/UnifiedSocialCreditCode.js +118 -0
  10. package/lib/cn/UnifiedSocialCreditCode.js.map +1 -0
  11. package/lib/cn/formatDate.js +15 -0
  12. package/lib/cn/formatDate.js.map +1 -0
  13. package/lib/cn/index.js +4 -0
  14. package/lib/cn/index.js.map +1 -0
  15. package/lib/cn/parseSex.js +22 -0
  16. package/lib/cn/parseSex.js.map +1 -0
  17. package/lib/cn/types.d.js +8 -0
  18. package/lib/cn/types.d.js.map +1 -0
  19. package/lib/meta/defineFileType.js +44 -0
  20. package/lib/meta/defineFileType.js.map +1 -0
  21. package/lib/meta/defineMetadata.js +14 -3
  22. package/lib/meta/defineMetadata.js.map +1 -1
  23. package/lib/meta/index.js +1 -0
  24. package/lib/meta/index.js.map +1 -1
  25. package/lib/parseSort.js +15 -0
  26. package/lib/parseSort.js.map +1 -1
  27. package/lib/search/AdvanceSearch.js +10 -0
  28. package/lib/search/AdvanceSearch.js.map +1 -0
  29. package/lib/search/formatAdvanceSearch.js +64 -0
  30. package/lib/search/formatAdvanceSearch.js.map +1 -0
  31. package/lib/search/index.js +2 -0
  32. package/lib/search/index.js.map +1 -0
  33. package/lib/search/optimizeAdvanceSearch.js +89 -0
  34. package/lib/search/optimizeAdvanceSearch.js.map +1 -0
  35. package/lib/search/parseAdvanceSearch.js +20 -0
  36. package/lib/search/parseAdvanceSearch.js.map +1 -0
  37. package/lib/search/parser.d.js +3 -0
  38. package/lib/search/parser.d.js.map +1 -0
  39. package/lib/search/parser.js +3065 -0
  40. package/lib/search/parser.js.map +1 -0
  41. package/lib/search/types.d.js +3 -0
  42. package/lib/search/types.d.js.map +1 -0
  43. package/package.json +12 -4
  44. package/src/cn/DivisionCode.test.ts +50 -0
  45. package/src/cn/DivisionCode.ts +253 -0
  46. package/src/cn/Mod11Checksum.ts +24 -0
  47. package/src/cn/Mod31Checksum.ts +36 -0
  48. package/src/cn/ResidentIdentityCardNumber.test.ts +21 -0
  49. package/src/cn/ResidentIdentityCardNumber.ts +96 -0
  50. package/src/cn/UnifiedSocialCreditCode.test.ts +16 -0
  51. package/src/cn/UnifiedSocialCreditCode.ts +148 -0
  52. package/src/cn/__snapshots__/ResidentIdentityCardNumber.test.ts.snap +15 -0
  53. package/src/cn/__snapshots__/UnifiedSocialCreditCode.test.ts.snap +41 -0
  54. package/src/cn/formatDate.ts +12 -0
  55. package/src/cn/index.ts +3 -0
  56. package/src/cn/parseSex.ts +27 -0
  57. package/src/cn/types.d.ts +51 -0
  58. package/src/meta/defineFileType.tsx +68 -0
  59. package/src/meta/defineMetadata.ts +16 -3
  60. package/src/meta/index.ts +2 -0
  61. package/src/parseSort.test.ts +1 -0
  62. package/src/parseSort.ts +18 -0
  63. package/src/search/AdvanceSearch.test.ts +156 -0
  64. package/src/search/AdvanceSearch.ts +14 -0
  65. package/src/search/Makefile +2 -0
  66. package/src/search/__snapshots__/AdvanceSearch.test.ts.snap +675 -0
  67. package/src/search/formatAdvanceSearch.ts +61 -0
  68. package/src/search/index.ts +1 -0
  69. package/src/search/optimizeAdvanceSearch.ts +90 -0
  70. package/src/search/parseAdvanceSearch.ts +26 -0
  71. package/src/search/parser.d.ts +8 -0
  72. package/src/search/parser.js +2794 -0
  73. package/src/search/parser.peggy +237 -0
  74. 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,8 @@
1
+ /**
2
+ * 居民身份证
3
+ *
4
+ * @see https://en.wikipedia.org/wiki/Resident_Identity_Card
5
+ * @see https://en.wikipedia.org/wiki/Foreign_Permanent_Resident_ID_Card
6
+ */ export { };
7
+
8
+ //# sourceMappingURL=types.d.js.map
@@ -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(res, key, opts) {
22
- res.metadata = res.metadata || {};
23
- set(res.metadata, key.key, opts);
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 set(res.metadata, key.key, opts);\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","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;AAEA,OAAO,SAASO,eAAkBC,GAAgB,EAAEV,GAAmB,EAAED,IAAO;IAC9EW,IAAIC,QAAQ,GAAGD,IAAIC,QAAQ,IAAI,CAAC;IAChChB,IAAIe,IAAIC,QAAQ,EAAEX,IAAIA,GAAG,EAAED;AAC7B;AAEA,OAAO,SAASa,YAAeF,GAAmC,EAAEV,GAAmB;IACrF,IAAI,CAACU,KAAKC,UAAU,OAAOE;IAC3B,OAAOnB,IAAIgB,IAAIC,QAAQ,EAAEX,IAAIA,GAAG;AAClC"}
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
@@ -1,3 +1,4 @@
1
1
  export { createMetadataKey, defineMetadata, getMetadata } from "./defineMetadata.js";
2
2
  export { defineInit, runInit } from "./defineInit.js";
3
+ export { defineFileType, getFileType } from "./defineFileType.js";
3
4
  //# sourceMappingURL=index.js.map
@@ -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
@@ -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,2 @@
1
+ export { AdvanceSearch } from "./AdvanceSearch.js";
2
+ //# sourceMappingURL=index.js.map
@@ -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,3 @@
1
+ export { };
2
+
3
+ //# sourceMappingURL=parser.d.js.map
@@ -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"}