@gblikas/querykit 0.0.0 → 0.2.0

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.
@@ -1,6 +1,80 @@
1
1
  import { clsx, type ClassValue } from 'clsx';
2
2
  import { twMerge } from 'tailwind-merge';
3
+ // Use the signature from @vercel/analytics: Record<string, AllowedPropertyValues>
4
+ type AnalyticsEventProps = Record<string, string | number | boolean | null>;
3
5
 
4
6
  export function cn(...inputs: ClassValue[]): string {
5
7
  return twMerge(clsx(inputs));
6
8
  }
9
+
10
+ // Lightweight telemetry helpers using Vercel Analytics custom events
11
+ // See: https://vercel.com/docs/analytics#events
12
+ export interface IQueryKitIssueEvent {
13
+ errorName: string;
14
+ errorMessage: string;
15
+ stage: 'parse' | 'translate' | 'execute' | 'explain' | 'seed' | 'search';
16
+ query?: string;
17
+ }
18
+
19
+ export async function trackQueryKitIssue(event: IQueryKitIssueEvent): Promise<void> {
20
+ try {
21
+ const { track } = await import('@vercel/analytics');
22
+ const props: AnalyticsEventProps = {
23
+ errorName: event.errorName,
24
+ errorMessage: event.errorMessage,
25
+ stage: event.stage,
26
+ query: event.query ?? null
27
+ };
28
+ track('qk_issue', props);
29
+ } catch {
30
+ // no-op in dev or if analytics not available
31
+ }
32
+ }
33
+
34
+ export interface IQueryKitUsageEvent {
35
+ usedQueryKit: boolean;
36
+ operators: string[];
37
+ }
38
+
39
+ export async function trackQueryKitUsage(event: IQueryKitUsageEvent): Promise<void> {
40
+ try {
41
+ const { track } = await import('@vercel/analytics');
42
+ const props: AnalyticsEventProps = {
43
+ usedQueryKit: event.usedQueryKit,
44
+ operators: (event.operators || []).join(',')
45
+ };
46
+ track('qk_usage', props);
47
+ } catch {
48
+ // no-op
49
+ }
50
+ }
51
+
52
+ export interface IQueryKitSpeedEvent {
53
+ usedQueryKit: boolean;
54
+ baselineMs?: number | null;
55
+ parseTranslateMs?: number | null;
56
+ explainLatencyMs?: number | null;
57
+ dbExecutionMs?: number | null;
58
+ totalMs?: number | null;
59
+ rowsScanned?: number | null;
60
+ results?: number | null;
61
+ }
62
+
63
+ export async function trackQueryKitSpeed(event: IQueryKitSpeedEvent): Promise<void> {
64
+ try {
65
+ const { track } = await import('@vercel/analytics');
66
+ const props: AnalyticsEventProps = {
67
+ usedQueryKit: event.usedQueryKit,
68
+ baselineMs: event.baselineMs ?? null,
69
+ parseTranslateMs: event.parseTranslateMs ?? null,
70
+ explainLatencyMs: event.explainLatencyMs ?? null,
71
+ dbExecutionMs: event.dbExecutionMs ?? null,
72
+ totalMs: event.totalMs ?? null,
73
+ rowsScanned: event.rowsScanned ?? null,
74
+ results: event.results ?? null
75
+ };
76
+ track('qk_speed', props);
77
+ } catch {
78
+ // no-op
79
+ }
80
+ }
@@ -11,15 +11,17 @@
11
11
  "dependencies": {
12
12
  "@electric-sql/pglite": "^0.3.7",
13
13
  "@electric-sql/pglite-react": "^0.2.25",
14
- "@gblikas/querykit": "file:../..",
14
+ "@gblikas/querykit": "^0.0.0",
15
15
  "@radix-ui/react-dialog": "^1.1.15",
16
16
  "@radix-ui/react-hover-card": "^1.1.15",
17
+ "@vercel/analytics": "^1.5.0",
18
+ "@vercel/speed-insights": "^1.2.0",
17
19
  "class-variance-authority": "^0.7.1",
18
20
  "clsx": "^2.1.1",
19
21
  "cmdk": "^1.0.0",
20
22
  "drizzle-orm": "^0.44.4",
21
23
  "lucide-react": "^0.539.0",
22
- "next": "15.4.6",
24
+ "next": "15.4.10",
23
25
  "next-themes": "^0.4.6",
24
26
  "ogl": "^1.0.11",
25
27
  "prism-react-renderer": "^2.4.1",
@@ -45,4 +47,4 @@
45
47
  "tw-animate-css": "^1.3.6",
46
48
  "typescript": "^5"
47
49
  }
48
- }
50
+ }
@@ -15,14 +15,20 @@ importers:
15
15
  specifier: ^0.2.25
16
16
  version: 0.2.25(@electric-sql/pglite@0.3.7)(react@19.1.0)
17
17
  '@gblikas/querykit':
18
- specifier: file:../..
19
- version: file:../..(@electric-sql/pglite@0.3.7)(@types/react@19.1.10)(react@19.1.0)
18
+ specifier: ^0.0.0
19
+ version: 0.0.0(@electric-sql/pglite@0.3.7)(@types/react@19.1.10)(react@19.1.0)
20
20
  '@radix-ui/react-dialog':
21
21
  specifier: ^1.1.15
22
22
  version: 1.1.15(@types/react-dom@19.1.7(@types/react@19.1.10))(@types/react@19.1.10)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
23
23
  '@radix-ui/react-hover-card':
24
24
  specifier: ^1.1.15
25
25
  version: 1.1.15(@types/react-dom@19.1.7(@types/react@19.1.10))(@types/react@19.1.10)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
26
+ '@vercel/analytics':
27
+ specifier: ^1.5.0
28
+ version: 1.5.0(next@15.4.10(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0)
29
+ '@vercel/speed-insights':
30
+ specifier: ^1.2.0
31
+ version: 1.2.0(next@15.4.10(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0)
26
32
  class-variance-authority:
27
33
  specifier: ^0.7.1
28
34
  version: 0.7.1
@@ -39,8 +45,8 @@ importers:
39
45
  specifier: ^0.539.0
40
46
  version: 0.539.0(react@19.1.0)
41
47
  next:
42
- specifier: 15.4.6
43
- version: 15.4.6(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
48
+ specifier: 15.4.10
49
+ version: 15.4.10(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
44
50
  next-themes:
45
51
  specifier: ^0.4.6
46
52
  version: 0.4.6(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
@@ -489,8 +495,8 @@ packages:
489
495
  '@floating-ui/utils@0.2.10':
490
496
  resolution: {integrity: sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==}
491
497
 
492
- '@gblikas/querykit@file:../..':
493
- resolution: {directory: ../.., type: directory}
498
+ '@gblikas/querykit@0.0.0':
499
+ resolution: {integrity: sha512-kmCkPhc/YCmPJ3/WNGBEEbnHRMNeVrvWDvn3w6xi1cVOagN5Gff7s7sy6vqpXZ5fnhB3XSSnD0oj4KNDLZXdIA==}
494
500
 
495
501
  '@humanfs/core@0.19.1':
496
502
  resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==}
@@ -657,56 +663,56 @@ packages:
657
663
  '@napi-rs/wasm-runtime@0.2.12':
658
664
  resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==}
659
665
 
660
- '@next/env@15.4.6':
661
- resolution: {integrity: sha512-yHDKVTcHrZy/8TWhj0B23ylKv5ypocuCwey9ZqPyv4rPdUdRzpGCkSi03t04KBPyU96kxVtUqx6O3nE1kpxASQ==}
666
+ '@next/env@15.4.10':
667
+ resolution: {integrity: sha512-knhmoJ0Vv7VRf6pZEPSnciUG1S4bIhWx+qTYBW/AjxEtlzsiNORPk8sFDCEvqLfmKuey56UB9FL1UdHEV3uBrg==}
662
668
 
663
669
  '@next/eslint-plugin-next@15.4.6':
664
670
  resolution: {integrity: sha512-2NOu3ln+BTcpnbIDuxx6MNq+pRrCyey4WSXGaJIyt0D2TYicHeO9QrUENNjcf673n3B1s7hsiV5xBYRCK1Q8kA==}
665
671
 
666
- '@next/swc-darwin-arm64@15.4.6':
667
- resolution: {integrity: sha512-667R0RTP4DwxzmrqTs4Lr5dcEda9OxuZsVFsjVtxVMVhzSpo6nLclXejJVfQo2/g7/Z9qF3ETDmN3h65mTjpTQ==}
672
+ '@next/swc-darwin-arm64@15.4.8':
673
+ resolution: {integrity: sha512-Pf6zXp7yyQEn7sqMxur6+kYcywx5up1J849psyET7/8pG2gQTVMjU3NzgIt8SeEP5to3If/SaWmaA6H6ysBr1A==}
668
674
  engines: {node: '>= 10'}
669
675
  cpu: [arm64]
670
676
  os: [darwin]
671
677
 
672
- '@next/swc-darwin-x64@15.4.6':
673
- resolution: {integrity: sha512-KMSFoistFkaiQYVQQnaU9MPWtp/3m0kn2Xed1Ces5ll+ag1+rlac20sxG+MqhH2qYWX1O2GFOATQXEyxKiIscg==}
678
+ '@next/swc-darwin-x64@15.4.8':
679
+ resolution: {integrity: sha512-xla6AOfz68a6kq3gRQccWEvFC/VRGJmA/QuSLENSO7CZX5WIEkSz7r1FdXUjtGCQ1c2M+ndUAH7opdfLK1PQbw==}
674
680
  engines: {node: '>= 10'}
675
681
  cpu: [x64]
676
682
  os: [darwin]
677
683
 
678
- '@next/swc-linux-arm64-gnu@15.4.6':
679
- resolution: {integrity: sha512-PnOx1YdO0W7m/HWFeYd2A6JtBO8O8Eb9h6nfJia2Dw1sRHoHpNf6lN1U4GKFRzRDBi9Nq2GrHk9PF3Vmwf7XVw==}
684
+ '@next/swc-linux-arm64-gnu@15.4.8':
685
+ resolution: {integrity: sha512-y3fmp+1Px/SJD+5ntve5QLZnGLycsxsVPkTzAc3zUiXYSOlTPqT8ynfmt6tt4fSo1tAhDPmryXpYKEAcoAPDJw==}
680
686
  engines: {node: '>= 10'}
681
687
  cpu: [arm64]
682
688
  os: [linux]
683
689
 
684
- '@next/swc-linux-arm64-musl@15.4.6':
685
- resolution: {integrity: sha512-XBbuQddtY1p5FGPc2naMO0kqs4YYtLYK/8aPausI5lyOjr4J77KTG9mtlU4P3NwkLI1+OjsPzKVvSJdMs3cFaw==}
690
+ '@next/swc-linux-arm64-musl@15.4.8':
691
+ resolution: {integrity: sha512-DX/L8VHzrr1CfwaVjBQr3GWCqNNFgyWJbeQ10Lx/phzbQo3JNAxUok1DZ8JHRGcL6PgMRgj6HylnLNndxn4Z6A==}
686
692
  engines: {node: '>= 10'}
687
693
  cpu: [arm64]
688
694
  os: [linux]
689
695
 
690
- '@next/swc-linux-x64-gnu@15.4.6':
691
- resolution: {integrity: sha512-+WTeK7Qdw82ez3U9JgD+igBAP75gqZ1vbK6R8PlEEuY0OIe5FuYXA4aTjL811kWPf7hNeslD4hHK2WoM9W0IgA==}
696
+ '@next/swc-linux-x64-gnu@15.4.8':
697
+ resolution: {integrity: sha512-9fLAAXKAL3xEIFdKdzG5rUSvSiZTLLTCc6JKq1z04DR4zY7DbAPcRvNm3K1inVhTiQCs19ZRAgUerHiVKMZZIA==}
692
698
  engines: {node: '>= 10'}
693
699
  cpu: [x64]
694
700
  os: [linux]
695
701
 
696
- '@next/swc-linux-x64-musl@15.4.6':
697
- resolution: {integrity: sha512-XP824mCbgQsK20jlXKrUpZoh/iO3vUWhMpxCz8oYeagoiZ4V0TQiKy0ASji1KK6IAe3DYGfj5RfKP6+L2020OQ==}
702
+ '@next/swc-linux-x64-musl@15.4.8':
703
+ resolution: {integrity: sha512-s45V7nfb5g7dbS7JK6XZDcapicVrMMvX2uYgOHP16QuKH/JA285oy6HcxlKqwUNaFY/UC6EvQ8QZUOo19cBKSA==}
698
704
  engines: {node: '>= 10'}
699
705
  cpu: [x64]
700
706
  os: [linux]
701
707
 
702
- '@next/swc-win32-arm64-msvc@15.4.6':
703
- resolution: {integrity: sha512-FxrsenhUz0LbgRkNWx6FRRJIPe/MI1JRA4W4EPd5leXO00AZ6YU8v5vfx4MDXTvN77lM/EqsE3+6d2CIeF5NYg==}
708
+ '@next/swc-win32-arm64-msvc@15.4.8':
709
+ resolution: {integrity: sha512-KjgeQyOAq7t/HzAJcWPGA8X+4WY03uSCZ2Ekk98S9OgCFsb6lfBE3dbUzUuEQAN2THbwYgFfxX2yFTCMm8Kehw==}
704
710
  engines: {node: '>= 10'}
705
711
  cpu: [arm64]
706
712
  os: [win32]
707
713
 
708
- '@next/swc-win32-x64-msvc@15.4.6':
709
- resolution: {integrity: sha512-T4ufqnZ4u88ZheczkBTtOF+eKaM14V8kbjud/XrAakoM5DKQWjW09vD6B9fsdsWS2T7D5EY31hRHdta7QKWOng==}
714
+ '@next/swc-win32-x64-msvc@15.4.8':
715
+ resolution: {integrity: sha512-Exsmf/+42fWVnLMaZHzshukTBxZrSwuuLKFvqhGHJ+mC1AokqieLY/XzAl3jc/CqhXLqLY3RRjkKJ9YnLPcRWg==}
710
716
  engines: {node: '>= 10'}
711
717
  cpu: [x64]
712
718
  os: [win32]
@@ -1244,6 +1250,55 @@ packages:
1244
1250
  cpu: [x64]
1245
1251
  os: [win32]
1246
1252
 
1253
+ '@vercel/analytics@1.5.0':
1254
+ resolution: {integrity: sha512-MYsBzfPki4gthY5HnYN7jgInhAZ7Ac1cYDoRWFomwGHWEX7odTEzbtg9kf/QSo7XEsEAqlQugA6gJ2WS2DEa3g==}
1255
+ peerDependencies:
1256
+ '@remix-run/react': ^2
1257
+ '@sveltejs/kit': ^1 || ^2
1258
+ next: '>= 13'
1259
+ react: ^18 || ^19 || ^19.0.0-rc
1260
+ svelte: '>= 4'
1261
+ vue: ^3
1262
+ vue-router: ^4
1263
+ peerDependenciesMeta:
1264
+ '@remix-run/react':
1265
+ optional: true
1266
+ '@sveltejs/kit':
1267
+ optional: true
1268
+ next:
1269
+ optional: true
1270
+ react:
1271
+ optional: true
1272
+ svelte:
1273
+ optional: true
1274
+ vue:
1275
+ optional: true
1276
+ vue-router:
1277
+ optional: true
1278
+
1279
+ '@vercel/speed-insights@1.2.0':
1280
+ resolution: {integrity: sha512-y9GVzrUJ2xmgtQlzFP2KhVRoCglwfRQgjyfY607aU0hh0Un6d0OUyrJkjuAlsV18qR4zfoFPs/BiIj9YDS6Wzw==}
1281
+ peerDependencies:
1282
+ '@sveltejs/kit': ^1 || ^2
1283
+ next: '>= 13'
1284
+ react: ^18 || ^19 || ^19.0.0-rc
1285
+ svelte: '>= 4'
1286
+ vue: ^3
1287
+ vue-router: ^4
1288
+ peerDependenciesMeta:
1289
+ '@sveltejs/kit':
1290
+ optional: true
1291
+ next:
1292
+ optional: true
1293
+ react:
1294
+ optional: true
1295
+ svelte:
1296
+ optional: true
1297
+ vue:
1298
+ optional: true
1299
+ vue-router:
1300
+ optional: true
1301
+
1247
1302
  acorn-jsx@5.3.2:
1248
1303
  resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
1249
1304
  peerDependencies:
@@ -2329,8 +2384,8 @@ packages:
2329
2384
  react: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc
2330
2385
  react-dom: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc
2331
2386
 
2332
- next@15.4.6:
2333
- resolution: {integrity: sha512-us++E/Q80/8+UekzB3SAGs71AlLDsadpFMXVNM/uQ0BMwsh9m3mr0UNQIfjKed8vpWXsASe+Qifrnu1oLIcKEQ==}
2387
+ next@15.4.10:
2388
+ resolution: {integrity: sha512-itVlc79QjpKMFMRhP+kbGKaSG/gZM6RCvwhEbwmCNF06CdDiNaoHcbeg0PqkEa2GOcn8KJ0nnc7+yL7EjoYLHQ==}
2334
2389
  engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0}
2335
2390
  hasBin: true
2336
2391
  peerDependencies:
@@ -2723,6 +2778,7 @@ packages:
2723
2778
  tar@7.4.3:
2724
2779
  resolution: {integrity: sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==}
2725
2780
  engines: {node: '>=18'}
2781
+ deprecated: Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exhorbitant rates) by contacting i@izs.me
2726
2782
 
2727
2783
  tinyglobby@0.2.14:
2728
2784
  resolution: {integrity: sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==}
@@ -3097,11 +3153,10 @@ snapshots:
3097
3153
 
3098
3154
  '@floating-ui/utils@0.2.10': {}
3099
3155
 
3100
- '@gblikas/querykit@file:../..(@electric-sql/pglite@0.3.7)(@types/react@19.1.10)(react@19.1.0)':
3156
+ '@gblikas/querykit@0.0.0(@electric-sql/pglite@0.3.7)(@types/react@19.1.10)(react@19.1.0)':
3101
3157
  dependencies:
3102
3158
  drizzle-orm: 0.30.10(@electric-sql/pglite@0.3.7)(@types/react@19.1.10)(react@19.1.0)
3103
3159
  liqe: 3.8.3
3104
- ogl: 1.0.11
3105
3160
  transitivePeerDependencies:
3106
3161
  - '@aws-sdk/client-rds-data'
3107
3162
  - '@cloudflare/workers-types'
@@ -3258,34 +3313,34 @@ snapshots:
3258
3313
  '@tybys/wasm-util': 0.10.0
3259
3314
  optional: true
3260
3315
 
3261
- '@next/env@15.4.6': {}
3316
+ '@next/env@15.4.10': {}
3262
3317
 
3263
3318
  '@next/eslint-plugin-next@15.4.6':
3264
3319
  dependencies:
3265
3320
  fast-glob: 3.3.1
3266
3321
 
3267
- '@next/swc-darwin-arm64@15.4.6':
3322
+ '@next/swc-darwin-arm64@15.4.8':
3268
3323
  optional: true
3269
3324
 
3270
- '@next/swc-darwin-x64@15.4.6':
3325
+ '@next/swc-darwin-x64@15.4.8':
3271
3326
  optional: true
3272
3327
 
3273
- '@next/swc-linux-arm64-gnu@15.4.6':
3328
+ '@next/swc-linux-arm64-gnu@15.4.8':
3274
3329
  optional: true
3275
3330
 
3276
- '@next/swc-linux-arm64-musl@15.4.6':
3331
+ '@next/swc-linux-arm64-musl@15.4.8':
3277
3332
  optional: true
3278
3333
 
3279
- '@next/swc-linux-x64-gnu@15.4.6':
3334
+ '@next/swc-linux-x64-gnu@15.4.8':
3280
3335
  optional: true
3281
3336
 
3282
- '@next/swc-linux-x64-musl@15.4.6':
3337
+ '@next/swc-linux-x64-musl@15.4.8':
3283
3338
  optional: true
3284
3339
 
3285
- '@next/swc-win32-arm64-msvc@15.4.6':
3340
+ '@next/swc-win32-arm64-msvc@15.4.8':
3286
3341
  optional: true
3287
3342
 
3288
- '@next/swc-win32-x64-msvc@15.4.6':
3343
+ '@next/swc-win32-x64-msvc@15.4.8':
3289
3344
  optional: true
3290
3345
 
3291
3346
  '@nodelib/fs.scandir@2.1.5':
@@ -3772,6 +3827,16 @@ snapshots:
3772
3827
  '@unrs/resolver-binding-win32-x64-msvc@1.11.1':
3773
3828
  optional: true
3774
3829
 
3830
+ '@vercel/analytics@1.5.0(next@15.4.10(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0)':
3831
+ optionalDependencies:
3832
+ next: 15.4.10(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
3833
+ react: 19.1.0
3834
+
3835
+ '@vercel/speed-insights@1.2.0(next@15.4.10(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0)':
3836
+ optionalDependencies:
3837
+ next: 15.4.10(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
3838
+ react: 19.1.0
3839
+
3775
3840
  acorn-jsx@5.3.2(acorn@8.15.0):
3776
3841
  dependencies:
3777
3842
  acorn: 8.15.0
@@ -4901,9 +4966,9 @@ snapshots:
4901
4966
  react: 19.1.0
4902
4967
  react-dom: 19.1.0(react@19.1.0)
4903
4968
 
4904
- next@15.4.6(react-dom@19.1.0(react@19.1.0))(react@19.1.0):
4969
+ next@15.4.10(react-dom@19.1.0(react@19.1.0))(react@19.1.0):
4905
4970
  dependencies:
4906
- '@next/env': 15.4.6
4971
+ '@next/env': 15.4.10
4907
4972
  '@swc/helpers': 0.5.15
4908
4973
  caniuse-lite: 1.0.30001735
4909
4974
  postcss: 8.4.31
@@ -4911,14 +4976,14 @@ snapshots:
4911
4976
  react-dom: 19.1.0(react@19.1.0)
4912
4977
  styled-jsx: 5.1.6(react@19.1.0)
4913
4978
  optionalDependencies:
4914
- '@next/swc-darwin-arm64': 15.4.6
4915
- '@next/swc-darwin-x64': 15.4.6
4916
- '@next/swc-linux-arm64-gnu': 15.4.6
4917
- '@next/swc-linux-arm64-musl': 15.4.6
4918
- '@next/swc-linux-x64-gnu': 15.4.6
4919
- '@next/swc-linux-x64-musl': 15.4.6
4920
- '@next/swc-win32-arm64-msvc': 15.4.6
4921
- '@next/swc-win32-x64-msvc': 15.4.6
4979
+ '@next/swc-darwin-arm64': 15.4.8
4980
+ '@next/swc-darwin-x64': 15.4.8
4981
+ '@next/swc-linux-arm64-gnu': 15.4.8
4982
+ '@next/swc-linux-arm64-musl': 15.4.8
4983
+ '@next/swc-linux-x64-gnu': 15.4.8
4984
+ '@next/swc-linux-x64-musl': 15.4.8
4985
+ '@next/swc-win32-arm64-msvc': 15.4.8
4986
+ '@next/swc-win32-x64-msvc': 15.4.8
4922
4987
  sharp: 0.34.3
4923
4988
  transitivePeerDependencies:
4924
4989
  - '@babel/core'
package/package.json CHANGED
@@ -1,7 +1,11 @@
1
1
  {
2
2
  "name": "@gblikas/querykit",
3
- "version": "0.0.0",
3
+ "version": "0.2.0",
4
4
  "description": "A comprehensive query toolkit for TypeScript that simplifies building and executing data queries across different environments",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git+https://github.com/gblikas/querykit.git"
8
+ },
5
9
  "main": "dist/index.js",
6
10
  "types": "dist/index.d.ts",
7
11
  "lint-staged": {
@@ -1,5 +1,9 @@
1
1
  import { QueryParser, QueryParseError } from './parser';
2
- import { QueryExpression } from './types';
2
+ import {
3
+ IComparisonExpression,
4
+ ILogicalExpression,
5
+ QueryExpression
6
+ } from './types';
3
7
 
4
8
  // Replace the type definition with this approach
5
9
  type QueryParserPrivate = {
@@ -863,6 +867,210 @@ describe('QueryParser', () => {
863
867
 
864
868
  expect(parser.parse(query)).toEqual(expected);
865
869
  });
870
+
871
+ // IN operator syntax tests using consistent key:[values] pattern
872
+ describe('IN operator syntax (key:[values])', () => {
873
+ it('should parse "field:[val1, val2, val3]" bracket array syntax', () => {
874
+ const query = 'status:[todo, doing, done]';
875
+ const expected: QueryExpression = {
876
+ type: 'logical',
877
+ operator: 'OR',
878
+ left: {
879
+ type: 'logical',
880
+ operator: 'OR',
881
+ left: {
882
+ type: 'comparison',
883
+ field: 'status',
884
+ operator: '==',
885
+ value: 'todo'
886
+ },
887
+ right: {
888
+ type: 'comparison',
889
+ field: 'status',
890
+ operator: '==',
891
+ value: 'doing'
892
+ }
893
+ },
894
+ right: {
895
+ type: 'comparison',
896
+ field: 'status',
897
+ operator: '==',
898
+ value: 'done'
899
+ }
900
+ };
901
+
902
+ expect(parser.parse(query)).toEqual(expected);
903
+ });
904
+
905
+ it('should parse numeric values in bracket syntax', () => {
906
+ const query = 'id:[2, 3]';
907
+ const expected: QueryExpression = {
908
+ type: 'logical',
909
+ operator: 'OR',
910
+ left: {
911
+ type: 'comparison',
912
+ field: 'id',
913
+ operator: '==',
914
+ value: 2
915
+ },
916
+ right: {
917
+ type: 'comparison',
918
+ field: 'id',
919
+ operator: '==',
920
+ value: 3
921
+ }
922
+ };
923
+
924
+ expect(parser.parse(query)).toEqual(expected);
925
+ });
926
+
927
+ it('should parse single value in bracket syntax', () => {
928
+ const query = 'status:[active]';
929
+ const expected: QueryExpression = {
930
+ type: 'comparison',
931
+ field: 'status',
932
+ operator: '==',
933
+ value: 'active'
934
+ };
935
+
936
+ expect(parser.parse(query)).toEqual(expected);
937
+ });
938
+
939
+ it('should preserve range syntax "field:[min TO max]"', () => {
940
+ const query = 'id:[2 TO 5]';
941
+ const expected: QueryExpression = {
942
+ type: 'logical',
943
+ operator: 'AND',
944
+ left: {
945
+ type: 'comparison',
946
+ field: 'id',
947
+ operator: '>=',
948
+ value: 2
949
+ },
950
+ right: {
951
+ type: 'comparison',
952
+ field: 'id',
953
+ operator: '<=',
954
+ value: 5
955
+ }
956
+ };
957
+
958
+ expect(parser.parse(query)).toEqual(expected);
959
+ });
960
+
961
+ it('should parse exclusive range syntax "field:{min TO max}"', () => {
962
+ const query = 'id:{2 TO 5}';
963
+ const expected: QueryExpression = {
964
+ type: 'logical',
965
+ operator: 'AND',
966
+ left: {
967
+ type: 'comparison',
968
+ field: 'id',
969
+ operator: '>',
970
+ value: 2
971
+ },
972
+ right: {
973
+ type: 'comparison',
974
+ field: 'id',
975
+ operator: '<',
976
+ value: 5
977
+ }
978
+ };
979
+
980
+ expect(parser.parse(query)).toEqual(expected);
981
+ });
982
+
983
+ it('should parse bracket syntax combined with other expressions', () => {
984
+ const query = 'status:[todo, doing] AND priority:>2';
985
+ const parsed = parser.parse(query);
986
+
987
+ // Verify it's a logical AND at the top level
988
+ expect(parsed.type).toBe('logical');
989
+ expect((parsed as ILogicalExpression).operator).toBe('AND');
990
+
991
+ // Left side should be OR of status values
992
+ const left = (parsed as ILogicalExpression).left as ILogicalExpression;
993
+ expect(left.type).toBe('logical');
994
+ expect(left.operator).toBe('OR');
995
+ });
996
+
997
+ it('should handle values with spaces using quotes', () => {
998
+ const query = 'name:[John, "Jane Doe"]';
999
+ const parsed = parser.parse(query);
1000
+
1001
+ expect(parsed.type).toBe('logical');
1002
+ expect((parsed as ILogicalExpression).operator).toBe('OR');
1003
+
1004
+ const right = (parsed as ILogicalExpression)
1005
+ .right as IComparisonExpression;
1006
+ expect(right.value).toBe('Jane Doe');
1007
+ });
1008
+
1009
+ it('should validate bracket syntax queries', () => {
1010
+ expect(parser.validate('status:[todo, doing, done]')).toBe(true);
1011
+ expect(parser.validate('id:[1, 2, 3]')).toBe(true);
1012
+ expect(parser.validate('id:[1 TO 10]')).toBe(true);
1013
+ });
1014
+
1015
+ it('should handle mixed types in bracket syntax', () => {
1016
+ const query = 'priority:[1, 2, 3]';
1017
+ const parsed = parser.parse(query);
1018
+
1019
+ expect(parsed.type).toBe('logical');
1020
+ // All values should be numbers
1021
+ const getLeftmost = (expr: QueryExpression): IComparisonExpression => {
1022
+ if (expr.type === 'comparison') return expr;
1023
+ return getLeftmost((expr as ILogicalExpression).left);
1024
+ };
1025
+ expect(typeof getLeftmost(parsed).value).toBe('number');
1026
+ });
1027
+
1028
+ it('should handle quoted values with commas inside', () => {
1029
+ const query = 'name:["John, Jr.", "Jane"]';
1030
+ const parsed = parser.parse(query);
1031
+
1032
+ expect(parsed.type).toBe('logical');
1033
+ expect((parsed as ILogicalExpression).operator).toBe('OR');
1034
+
1035
+ const left = (parsed as ILogicalExpression)
1036
+ .left as IComparisonExpression;
1037
+ const right = (parsed as ILogicalExpression)
1038
+ .right as IComparisonExpression;
1039
+
1040
+ expect(left.value).toBe('John, Jr.');
1041
+ expect(right.value).toBe('Jane');
1042
+ });
1043
+
1044
+ it('should handle single-quoted values with commas inside', () => {
1045
+ const query = "name:['Hello, World', 'test']";
1046
+ const parsed = parser.parse(query);
1047
+
1048
+ expect(parsed.type).toBe('logical');
1049
+ const left = (parsed as ILogicalExpression)
1050
+ .left as IComparisonExpression;
1051
+ expect(left.value).toBe('Hello, World');
1052
+ });
1053
+
1054
+ it('should handle mixed quoted and unquoted values with commas', () => {
1055
+ const query = 'tags:["a,b,c", simple, "x,y"]';
1056
+ const parsed = parser.parse(query);
1057
+
1058
+ expect(parsed.type).toBe('logical');
1059
+ // Should have 3 values: "a,b,c", "simple", "x,y"
1060
+ const getValues = (expr: QueryExpression): string[] => {
1061
+ if (expr.type === 'comparison') {
1062
+ return [String(expr.value)];
1063
+ }
1064
+ const logical = expr as ILogicalExpression;
1065
+ return [...getValues(logical.left), ...getValues(logical.right!)];
1066
+ };
1067
+
1068
+ const values = getValues(parsed);
1069
+ expect(values).toContain('a,b,c');
1070
+ expect(values).toContain('simple');
1071
+ expect(values).toContain('x,y');
1072
+ });
1073
+ });
866
1074
  });
867
1075
 
868
1076
  describe('validate', () => {