@gblikas/querykit 0.0.0 → 0.1.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.
- package/.github/workflows/publish.yml +5 -7
- package/README.md +76 -0
- package/dist/security/types.d.ts +48 -0
- package/dist/security/types.js +2 -0
- package/dist/security/validator.d.ts +35 -0
- package/dist/security/validator.js +108 -0
- package/examples/qk-next/app/globals.css +23 -0
- package/examples/qk-next/app/hooks/use-viewport-info.ts +89 -0
- package/examples/qk-next/app/layout.tsx +26 -7
- package/examples/qk-next/app/page.tsx +423 -121
- package/examples/qk-next/lib/utils.ts +74 -0
- package/examples/qk-next/package.json +5 -3
- package/examples/qk-next/pnpm-lock.yaml +112 -47
- package/package.json +5 -1
- package/src/security/types.ts +52 -0
- package/src/security/validator.test.ts +368 -0
- package/src/security/validator.ts +117 -0
|
@@ -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": "
|
|
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.
|
|
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:
|
|
19
|
-
version:
|
|
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.
|
|
43
|
-
version: 15.4.
|
|
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@
|
|
493
|
-
resolution: {
|
|
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.
|
|
661
|
-
resolution: {integrity: sha512-
|
|
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.
|
|
667
|
-
resolution: {integrity: sha512-
|
|
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.
|
|
673
|
-
resolution: {integrity: sha512-
|
|
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.
|
|
679
|
-
resolution: {integrity: sha512-
|
|
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.
|
|
685
|
-
resolution: {integrity: sha512-
|
|
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.
|
|
691
|
-
resolution: {integrity: sha512
|
|
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.
|
|
697
|
-
resolution: {integrity: sha512-
|
|
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.
|
|
703
|
-
resolution: {integrity: sha512-
|
|
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.
|
|
709
|
-
resolution: {integrity: sha512-
|
|
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.
|
|
2333
|
-
resolution: {integrity: sha512-
|
|
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@
|
|
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.
|
|
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.
|
|
3322
|
+
'@next/swc-darwin-arm64@15.4.8':
|
|
3268
3323
|
optional: true
|
|
3269
3324
|
|
|
3270
|
-
'@next/swc-darwin-x64@15.4.
|
|
3325
|
+
'@next/swc-darwin-x64@15.4.8':
|
|
3271
3326
|
optional: true
|
|
3272
3327
|
|
|
3273
|
-
'@next/swc-linux-arm64-gnu@15.4.
|
|
3328
|
+
'@next/swc-linux-arm64-gnu@15.4.8':
|
|
3274
3329
|
optional: true
|
|
3275
3330
|
|
|
3276
|
-
'@next/swc-linux-arm64-musl@15.4.
|
|
3331
|
+
'@next/swc-linux-arm64-musl@15.4.8':
|
|
3277
3332
|
optional: true
|
|
3278
3333
|
|
|
3279
|
-
'@next/swc-linux-x64-gnu@15.4.
|
|
3334
|
+
'@next/swc-linux-x64-gnu@15.4.8':
|
|
3280
3335
|
optional: true
|
|
3281
3336
|
|
|
3282
|
-
'@next/swc-linux-x64-musl@15.4.
|
|
3337
|
+
'@next/swc-linux-x64-musl@15.4.8':
|
|
3283
3338
|
optional: true
|
|
3284
3339
|
|
|
3285
|
-
'@next/swc-win32-arm64-msvc@15.4.
|
|
3340
|
+
'@next/swc-win32-arm64-msvc@15.4.8':
|
|
3286
3341
|
optional: true
|
|
3287
3342
|
|
|
3288
|
-
'@next/swc-win32-x64-msvc@15.4.
|
|
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.
|
|
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.
|
|
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.
|
|
4915
|
-
'@next/swc-darwin-x64': 15.4.
|
|
4916
|
-
'@next/swc-linux-arm64-gnu': 15.4.
|
|
4917
|
-
'@next/swc-linux-arm64-musl': 15.4.
|
|
4918
|
-
'@next/swc-linux-x64-gnu': 15.4.
|
|
4919
|
-
'@next/swc-linux-x64-musl': 15.4.
|
|
4920
|
-
'@next/swc-win32-arm64-msvc': 15.4.
|
|
4921
|
-
'@next/swc-win32-x64-msvc': 15.4.
|
|
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.
|
|
3
|
+
"version": "0.1.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": {
|
package/src/security/types.ts
CHANGED
|
@@ -57,6 +57,56 @@ export interface ISecurityOptions {
|
|
|
57
57
|
*/
|
|
58
58
|
denyFields?: string[];
|
|
59
59
|
|
|
60
|
+
/**
|
|
61
|
+
* Map of field names to arrays of values that are denied for that field.
|
|
62
|
+
* This provides granular control over what values can be used in queries.
|
|
63
|
+
* Use this to protect against queries targeting specific sensitive values.
|
|
64
|
+
*
|
|
65
|
+
* The keys are field names (can include table prefixes like "user.role")
|
|
66
|
+
* and the values are arrays of denied values for that field.
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* ```typescript
|
|
70
|
+
* // Prevent certain values from being queried
|
|
71
|
+
* denyValues: {
|
|
72
|
+
* 'status': ['deleted', 'banned'],
|
|
73
|
+
* 'role': ['superadmin', 'system'],
|
|
74
|
+
* 'user.type': ['internal', 'bot']
|
|
75
|
+
* }
|
|
76
|
+
*
|
|
77
|
+
* // This would block queries like:
|
|
78
|
+
* // status == "deleted"
|
|
79
|
+
* // role IN ["superadmin", "admin"]
|
|
80
|
+
* // user.type == "internal"
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
denyValues?: Record<string, Array<string | number | boolean | null>>;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Whether to allow dot notation in field names (e.g., "user.name", "metadata.tags").
|
|
87
|
+
* When disabled, queries with dots in field names will be rejected.
|
|
88
|
+
*
|
|
89
|
+
* Use cases for DISABLING dot notation:
|
|
90
|
+
* - Public-facing search APIs where users should only query flat, top-level fields
|
|
91
|
+
* - Preventing access to table-qualified columns in SQL joins (e.g., "users.password")
|
|
92
|
+
* - Simpler security model when your schema doesn't have nested/JSON data
|
|
93
|
+
* - Preventing users from probing internal table structures
|
|
94
|
+
*
|
|
95
|
+
* @default true
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
* ```typescript
|
|
99
|
+
* // Disable dot notation for a public search API
|
|
100
|
+
* allowDotNotation: false
|
|
101
|
+
*
|
|
102
|
+
* // This would block queries like:
|
|
103
|
+
* // user.email == "test@example.com" // Rejected
|
|
104
|
+
* // metadata.tags == "sale" // Rejected
|
|
105
|
+
* // email == "test@example.com" // Allowed
|
|
106
|
+
* ```
|
|
107
|
+
*/
|
|
108
|
+
allowDotNotation?: boolean;
|
|
109
|
+
|
|
60
110
|
/**
|
|
61
111
|
* Maximum nesting depth of query expressions.
|
|
62
112
|
* Prevents deeply nested queries that could impact performance.
|
|
@@ -192,6 +242,8 @@ export const DEFAULT_SECURITY_OPTIONS: Required<ISecurityOptions> = {
|
|
|
192
242
|
// Field restrictions - by default, all schema fields are allowed
|
|
193
243
|
allowedFields: [], // Empty means "use schema fields"
|
|
194
244
|
denyFields: [], // Empty means no denied fields
|
|
245
|
+
denyValues: {}, // Empty means no denied values for any field
|
|
246
|
+
allowDotNotation: true, // Allow dot notation by default for backward compatibility
|
|
195
247
|
|
|
196
248
|
// Query complexity limits
|
|
197
249
|
maxQueryDepth: 10, // Maximum nesting level of expressions
|