@quickql/server 1.0.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/LICENSE +21 -0
- package/README.md +91 -0
- package/dist/core/src/client.d.ts +57 -0
- package/dist/core/src/client.d.ts.map +1 -0
- package/dist/core/src/client.js +164 -0
- package/dist/core/src/client.js.map +1 -0
- package/dist/core/src/index.d.ts +13 -0
- package/dist/core/src/index.d.ts.map +1 -0
- package/dist/core/src/index.js +13 -0
- package/dist/core/src/index.js.map +1 -0
- package/dist/core/src/types.d.ts +82 -0
- package/dist/core/src/types.d.ts.map +1 -0
- package/dist/core/src/types.js +12 -0
- package/dist/core/src/types.js.map +1 -0
- package/dist/server/src/engine.d.ts +55 -0
- package/dist/server/src/engine.d.ts.map +1 -0
- package/dist/server/src/engine.js +422 -0
- package/dist/server/src/engine.js.map +1 -0
- package/dist/server/src/errors.d.ts +31 -0
- package/dist/server/src/errors.d.ts.map +1 -0
- package/dist/server/src/errors.js +73 -0
- package/dist/server/src/errors.js.map +1 -0
- package/dist/server/src/executor.d.ts +25 -0
- package/dist/server/src/executor.d.ts.map +1 -0
- package/dist/server/src/executor.js +121 -0
- package/dist/server/src/executor.js.map +1 -0
- package/dist/server/src/filters.d.ts +10 -0
- package/dist/server/src/filters.d.ts.map +1 -0
- package/dist/server/src/filters.js +47 -0
- package/dist/server/src/filters.js.map +1 -0
- package/dist/server/src/handler.d.ts +12 -0
- package/dist/server/src/handler.d.ts.map +1 -0
- package/dist/server/src/handler.js +138 -0
- package/dist/server/src/handler.js.map +1 -0
- package/dist/server/src/index.d.ts +25 -0
- package/dist/server/src/index.d.ts.map +1 -0
- package/dist/server/src/index.js +26 -0
- package/dist/server/src/index.js.map +1 -0
- package/dist/server/src/parser/parser.d.ts +21 -0
- package/dist/server/src/parser/parser.d.ts.map +1 -0
- package/dist/server/src/parser/parser.js +99 -0
- package/dist/server/src/parser/parser.js.map +1 -0
- package/dist/server/src/parser/tokenizer.d.ts +18 -0
- package/dist/server/src/parser/tokenizer.d.ts.map +1 -0
- package/dist/server/src/parser/tokenizer.js +94 -0
- package/dist/server/src/parser/tokenizer.js.map +1 -0
- package/dist/server/src/parser/transformer.d.ts +24 -0
- package/dist/server/src/parser/transformer.d.ts.map +1 -0
- package/dist/server/src/parser/transformer.js +61 -0
- package/dist/server/src/parser/transformer.js.map +1 -0
- package/dist/server/src/parser/types.d.ts +21 -0
- package/dist/server/src/parser/types.d.ts.map +1 -0
- package/dist/server/src/parser/types.js +11 -0
- package/dist/server/src/parser/types.js.map +1 -0
- package/dist/server/src/playground/assets.d.ts +16 -0
- package/dist/server/src/playground/assets.d.ts.map +1 -0
- package/dist/server/src/playground/assets.js +1113 -0
- package/dist/server/src/playground/assets.js.map +1 -0
- package/dist/server/src/playground/docs.d.ts +15 -0
- package/dist/server/src/playground/docs.d.ts.map +1 -0
- package/dist/server/src/playground/docs.js +223 -0
- package/dist/server/src/playground/docs.js.map +1 -0
- package/dist/server/src/playground/html.d.ts +20 -0
- package/dist/server/src/playground/html.d.ts.map +1 -0
- package/dist/server/src/playground/html.js +50 -0
- package/dist/server/src/playground/html.js.map +1 -0
- package/dist/server/src/plugins/index.d.ts +21 -0
- package/dist/server/src/plugins/index.d.ts.map +1 -0
- package/dist/server/src/plugins/index.js +38 -0
- package/dist/server/src/plugins/index.js.map +1 -0
- package/dist/server/src/relations.d.ts +22 -0
- package/dist/server/src/relations.d.ts.map +1 -0
- package/dist/server/src/relations.js +98 -0
- package/dist/server/src/relations.js.map +1 -0
- package/dist/server/src/resolver/generator.d.ts +25 -0
- package/dist/server/src/resolver/generator.d.ts.map +1 -0
- package/dist/server/src/resolver/generator.js +65 -0
- package/dist/server/src/resolver/generator.js.map +1 -0
- package/dist/server/src/resolver/mapper.d.ts +23 -0
- package/dist/server/src/resolver/mapper.d.ts.map +1 -0
- package/dist/server/src/resolver/mapper.js +96 -0
- package/dist/server/src/resolver/mapper.js.map +1 -0
- package/dist/server/src/schema/builder.d.ts +21 -0
- package/dist/server/src/schema/builder.d.ts.map +1 -0
- package/dist/server/src/schema/builder.js +23 -0
- package/dist/server/src/schema/builder.js.map +1 -0
- package/dist/server/src/schema/types.d.ts +81 -0
- package/dist/server/src/schema/types.d.ts.map +1 -0
- package/dist/server/src/schema/types.js +11 -0
- package/dist/server/src/schema/types.js.map +1 -0
- package/dist/server/src/schema/utils.d.ts +16 -0
- package/dist/server/src/schema/utils.d.ts.map +1 -0
- package/dist/server/src/schema/utils.js +42 -0
- package/dist/server/src/schema/utils.js.map +1 -0
- package/dist/server/src/security.d.ts +46 -0
- package/dist/server/src/security.d.ts.map +1 -0
- package/dist/server/src/security.js +189 -0
- package/dist/server/src/security.js.map +1 -0
- package/dist/server/src/types.d.ts +158 -0
- package/dist/server/src/types.d.ts.map +1 -0
- package/dist/server/src/types.js +11 -0
- package/dist/server/src/types.js.map +1 -0
- package/dist/server/src/validator.d.ts +30 -0
- package/dist/server/src/validator.d.ts.map +1 -0
- package/dist/server/src/validator.js +171 -0
- package/dist/server/src/validator.js.map +1 -0
- package/package.json +25 -0
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* QuickQL Security Engine
|
|
3
|
+
*
|
|
4
|
+
* Enforces authentication, authorization (RBAC), complexity limits, and rate limiting.
|
|
5
|
+
*
|
|
6
|
+
* (c) 2024-2026 Udinmo Inc. All rights reserved.
|
|
7
|
+
* Author: Udinmo Inc. <engineering@udinmo.com>
|
|
8
|
+
* License: MIT
|
|
9
|
+
*/
|
|
10
|
+
import { createSecurityError } from './errors';
|
|
11
|
+
export class SecurityEngine {
|
|
12
|
+
options;
|
|
13
|
+
schemaSnapshot;
|
|
14
|
+
rateLimitMap = new Map();
|
|
15
|
+
constructor(options, schemaSnapshot // Added to allow recursive lookup
|
|
16
|
+
) {
|
|
17
|
+
this.options = options;
|
|
18
|
+
this.schemaSnapshot = schemaSnapshot;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Enforces strict query depth limiting for security.
|
|
22
|
+
*/
|
|
23
|
+
validateDepth(query, currentDepth = 0) {
|
|
24
|
+
if (currentDepth > this.options.maxDepth) {
|
|
25
|
+
throw createSecurityError(`Security violation: Nested query depth exceeds limit of ${this.options.maxDepth}.`);
|
|
26
|
+
}
|
|
27
|
+
// Calculate Complexity Budget
|
|
28
|
+
const complexity = this.calculateComplexity(query);
|
|
29
|
+
if (this.options.maxComplexity && complexity > this.options.maxComplexity) {
|
|
30
|
+
throw createSecurityError(`Complexity violation: Query complexity ${complexity} exceeds budget of ${this.options.maxComplexity}.`);
|
|
31
|
+
}
|
|
32
|
+
if (query.include) {
|
|
33
|
+
for (const nested of Object.values(query.include)) {
|
|
34
|
+
this.validateDepth(nested, currentDepth + 1);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
calculateComplexity(query) {
|
|
39
|
+
let score = (query.select?.length || 5); // Default field weight
|
|
40
|
+
if (query.include) {
|
|
41
|
+
Object.values(query.include).forEach(nested => {
|
|
42
|
+
score += 10 + this.calculateComplexity(nested); // Relations weighted heavily
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
return score;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Verifies if the current context is authorized to access the collection or mutation.
|
|
49
|
+
*/
|
|
50
|
+
async validateAuth(name, definition, ctx, isMutation = false) {
|
|
51
|
+
const userRole = ctx.user?.role || ctx.role || 'anonymous';
|
|
52
|
+
const rbac = this.options.rbac;
|
|
53
|
+
// 0. Global RBAC Check
|
|
54
|
+
if (rbac && rbac.roles[userRole]) {
|
|
55
|
+
const config = rbac.roles[userRole];
|
|
56
|
+
const isAdmin = userRole === (rbac.adminRole || 'admin');
|
|
57
|
+
if (!isAdmin) {
|
|
58
|
+
// Explicit denylist check
|
|
59
|
+
if (config.deny?.includes(name)) {
|
|
60
|
+
throw createSecurityError(`Forbidden: Access to '${name}' is explicitly denied for role '${userRole}'`);
|
|
61
|
+
}
|
|
62
|
+
// Permission check
|
|
63
|
+
const permissions = isMutation ? config.write : config.can;
|
|
64
|
+
if (permissions && !permissions.includes(name) && !permissions.includes('*')) {
|
|
65
|
+
throw createSecurityError(`Forbidden: Role '${userRole}' does not have ${isMutation ? 'write' : 'read'} access to '${name}'`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
return; // Admin bypass!
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
// 1. Policy check (Top level)
|
|
73
|
+
if (definition?.policy) {
|
|
74
|
+
switch (definition.policy) {
|
|
75
|
+
case 'public': break; // Allow all
|
|
76
|
+
case 'private': throw createSecurityError(`Private collection '${name}': ACCESS_DENIED.`);
|
|
77
|
+
case 'authenticated':
|
|
78
|
+
if (!ctx.user)
|
|
79
|
+
throw createSecurityError(`Authenticated session required for '${name}'`);
|
|
80
|
+
break;
|
|
81
|
+
case 'owner-only':
|
|
82
|
+
if (!ctx.user)
|
|
83
|
+
throw createSecurityError(`Access denied: Ownership required for '${name}'`);
|
|
84
|
+
break;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
// 2. Roles check (Shorthand in collection)
|
|
88
|
+
if (definition?.roles && Array.isArray(definition.roles)) {
|
|
89
|
+
if (!definition.roles.includes(userRole)) {
|
|
90
|
+
throw createSecurityError(`Forbidden: Role '${userRole}' is not allowed to access '${name}'`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
// 3. Custom Auth Hook (Fine-grained)
|
|
94
|
+
if (definition?.auth) {
|
|
95
|
+
const isAuthorized = await definition.auth(ctx);
|
|
96
|
+
if (!isAuthorized) {
|
|
97
|
+
throw createSecurityError(`Unauthorized: Access denied for '${name}'.`, [name]);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Filters the results to remove fields marked as 'private' or failing field-level auth.
|
|
103
|
+
*/
|
|
104
|
+
async filterResults(collection, data, ctx) {
|
|
105
|
+
if (!data || data.length === 0)
|
|
106
|
+
return data;
|
|
107
|
+
const filteredData = await Promise.all(data.map(async (row) => {
|
|
108
|
+
const filteredRow = { ...row };
|
|
109
|
+
for (const [fieldName, fieldDef] of Object.entries(collection.fields)) {
|
|
110
|
+
// Handle both shorthand 'string' and full FieldDefinition objects
|
|
111
|
+
const isPrivate = typeof fieldDef === 'object' && fieldDef.private === true;
|
|
112
|
+
const hasAuth = typeof fieldDef === 'object' && fieldDef.auth;
|
|
113
|
+
const hasRoles = typeof fieldDef === 'object' && fieldDef.roles;
|
|
114
|
+
if (isPrivate) {
|
|
115
|
+
delete filteredRow[fieldName];
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
if (hasRoles && !fieldDef.roles.includes(ctx.user?.role || ctx.role)) {
|
|
119
|
+
delete filteredRow[fieldName];
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
if (hasAuth && !(await fieldDef.auth(ctx))) {
|
|
123
|
+
delete filteredRow[fieldName];
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
// 2. Recursively filter relations if present in the row
|
|
127
|
+
if (collection.relations) {
|
|
128
|
+
for (const [relKey, relDef] of Object.entries(collection.relations)) {
|
|
129
|
+
if (filteredRow[relKey] !== undefined) {
|
|
130
|
+
const targetName = relDef.model || relDef.from;
|
|
131
|
+
const targetCol = this.schemaSnapshot?.[targetName];
|
|
132
|
+
if (targetCol) {
|
|
133
|
+
const relData = filteredRow[relKey];
|
|
134
|
+
if (Array.isArray(relData)) {
|
|
135
|
+
filteredRow[relKey] = await this.filterResults(targetCol, relData, ctx);
|
|
136
|
+
}
|
|
137
|
+
else if (relData !== null && typeof relData === 'object') {
|
|
138
|
+
filteredRow[relKey] = (await this.filterResults(targetCol, [relData], ctx))[0];
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return filteredRow;
|
|
145
|
+
}));
|
|
146
|
+
return filteredData;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Simple Memory-based Rate Limiter.
|
|
150
|
+
*/
|
|
151
|
+
checkRateLimit(key) {
|
|
152
|
+
if (!this.options.rateLimit)
|
|
153
|
+
return;
|
|
154
|
+
const now = Date.now();
|
|
155
|
+
const windowMs = 60000; // 1 minute window
|
|
156
|
+
const userLimit = this.rateLimitMap.get(key) || { count: 0, lastReset: now };
|
|
157
|
+
if (now - userLimit.lastReset > windowMs) {
|
|
158
|
+
userLimit.count = 1;
|
|
159
|
+
userLimit.lastReset = now;
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
userLimit.count++;
|
|
163
|
+
}
|
|
164
|
+
this.rateLimitMap.set(key, userLimit);
|
|
165
|
+
if (userLimit.count > this.options.rateLimit) {
|
|
166
|
+
throw createSecurityError(`Rate limit exceeded: Please try again in a minute.`);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Basic input sanitization.
|
|
171
|
+
*/
|
|
172
|
+
sanitize(input) {
|
|
173
|
+
if (typeof input === 'string') {
|
|
174
|
+
return input.trim();
|
|
175
|
+
}
|
|
176
|
+
if (Array.isArray(input)) {
|
|
177
|
+
return input.map(i => this.sanitize(i));
|
|
178
|
+
}
|
|
179
|
+
if (typeof input === 'object' && input !== null) {
|
|
180
|
+
const sanitized = {};
|
|
181
|
+
for (const [key, value] of Object.entries(input)) {
|
|
182
|
+
sanitized[key] = this.sanitize(value);
|
|
183
|
+
}
|
|
184
|
+
return sanitized;
|
|
185
|
+
}
|
|
186
|
+
return input;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
//# sourceMappingURL=security.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security.js","sourceRoot":"","sources":["../../../src/security.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* QuickQL Server Types
|
|
3
|
+
*
|
|
4
|
+
* Core type definitions for the server engine, plugins, and configuration.
|
|
5
|
+
*
|
|
6
|
+
* (c) 2024-2026 Udinmo Inc. All rights reserved.
|
|
7
|
+
* Author: Udinmo Inc. <engineering@udinmo.com>
|
|
8
|
+
* License: MIT
|
|
9
|
+
*/
|
|
10
|
+
import { Query, Mutation } from '@quickql/core';
|
|
11
|
+
/**
|
|
12
|
+
* Global Context Interface
|
|
13
|
+
*/
|
|
14
|
+
export interface QuickQLServerContext {
|
|
15
|
+
orm: any;
|
|
16
|
+
user?: any;
|
|
17
|
+
[key: string]: any;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Internal Engine Types
|
|
21
|
+
*/
|
|
22
|
+
export interface InternalRelationDefinition {
|
|
23
|
+
from: string;
|
|
24
|
+
localKey: string;
|
|
25
|
+
foreignKey: string;
|
|
26
|
+
isSingle?: boolean;
|
|
27
|
+
}
|
|
28
|
+
export type CollectionSchema = {
|
|
29
|
+
fields: Record<string, any> | string[];
|
|
30
|
+
relations?: Record<string, InternalRelationDefinition>;
|
|
31
|
+
resolver: (query: Partial<Query>, ctx?: QuickQLServerContext) => Promise<Record<string, unknown>[]>;
|
|
32
|
+
mutationResolver?: (mutation: Mutation, ctx?: QuickQLServerContext) => Promise<Record<string, unknown>>;
|
|
33
|
+
};
|
|
34
|
+
export type SchemaConfig = Record<string, CollectionSchema>;
|
|
35
|
+
/**
|
|
36
|
+
* Hook & Plugin System
|
|
37
|
+
*/
|
|
38
|
+
export interface QuickQLPlugin {
|
|
39
|
+
name?: string;
|
|
40
|
+
/**
|
|
41
|
+
* Only run hooks if this matches the request context
|
|
42
|
+
*/
|
|
43
|
+
when?: (ctx: QuickQLServerContext) => boolean | Promise<boolean>;
|
|
44
|
+
/**
|
|
45
|
+
* Run before query execution. Can transform the query or validation state.
|
|
46
|
+
*/
|
|
47
|
+
beforeQuery?: (query: Query, ctx: QuickQLServerContext) => void | Query | Promise<void | Query>;
|
|
48
|
+
/**
|
|
49
|
+
* Run after successfull execution. Can transform the data results.
|
|
50
|
+
*/
|
|
51
|
+
afterQuery?: (result: any[], ctx: QuickQLServerContext) => void | any[] | Promise<void | any[]>;
|
|
52
|
+
/**
|
|
53
|
+
* Run when an error occurs.
|
|
54
|
+
*/
|
|
55
|
+
onError?: (error: unknown, ctx: QuickQLServerContext) => void | Promise<void>;
|
|
56
|
+
/**
|
|
57
|
+
* Run BEFORE a mutation. Can transform or block the mutation.
|
|
58
|
+
*/
|
|
59
|
+
beforeMutation?: (mutation: Mutation, ctx: QuickQLServerContext) => void | Mutation | Promise<void | Mutation>;
|
|
60
|
+
/**
|
|
61
|
+
* Run AFTER a mutation succeeds.
|
|
62
|
+
*/
|
|
63
|
+
onMutation?: (mutation: Mutation, ctx: QuickQLServerContext) => void | Promise<void>;
|
|
64
|
+
}
|
|
65
|
+
export interface RBACConfig {
|
|
66
|
+
roles: Record<string, {
|
|
67
|
+
can?: string[];
|
|
68
|
+
write?: string[];
|
|
69
|
+
deny?: string[];
|
|
70
|
+
}>;
|
|
71
|
+
adminRole?: string;
|
|
72
|
+
}
|
|
73
|
+
export interface CacheConfig {
|
|
74
|
+
enabled?: boolean;
|
|
75
|
+
ttl?: number;
|
|
76
|
+
maxItems?: number;
|
|
77
|
+
exclude?: string[];
|
|
78
|
+
}
|
|
79
|
+
export interface PlaygroundConfig {
|
|
80
|
+
endpoint?: string;
|
|
81
|
+
debug?: boolean;
|
|
82
|
+
/**
|
|
83
|
+
* If true, will hide some advanced features from the UI.
|
|
84
|
+
*/
|
|
85
|
+
readonly?: boolean;
|
|
86
|
+
}
|
|
87
|
+
export interface AuthConfig {
|
|
88
|
+
secret?: string;
|
|
89
|
+
strategies?: ('jwt' | 'apiKey' | 'session' | 'custom')[];
|
|
90
|
+
onAuth?: (ctx: QuickQLServerContext) => Promise<boolean | QuickQLServerContext> | boolean | QuickQLServerContext;
|
|
91
|
+
}
|
|
92
|
+
export interface ServerFeatures {
|
|
93
|
+
/**
|
|
94
|
+
* Automatically match plural/singular or fuzzy collection names.
|
|
95
|
+
* Default: true
|
|
96
|
+
*/
|
|
97
|
+
smartCollectionMatching?: boolean;
|
|
98
|
+
/**
|
|
99
|
+
* Automatically infer relations from field names (e.g. userId -> users).
|
|
100
|
+
* Default: true
|
|
101
|
+
*/
|
|
102
|
+
smartRelationDiscovery?: boolean;
|
|
103
|
+
/**
|
|
104
|
+
* Allow select: ['*'] to return all fields from the resolver result.
|
|
105
|
+
* Default: true
|
|
106
|
+
*/
|
|
107
|
+
superSelection?: boolean;
|
|
108
|
+
/**
|
|
109
|
+
* Include performance and security hints in response metadata.
|
|
110
|
+
* Default: true
|
|
111
|
+
*/
|
|
112
|
+
smartHints?: boolean;
|
|
113
|
+
}
|
|
114
|
+
export interface LoggingConfig {
|
|
115
|
+
level?: 'debug' | 'info' | 'warn' | 'error' | 'none';
|
|
116
|
+
customLogger?: (level: string, message: string, data?: any) => void;
|
|
117
|
+
slowQueryThreshold?: number;
|
|
118
|
+
}
|
|
119
|
+
export interface DirectiveConfig {
|
|
120
|
+
name: string;
|
|
121
|
+
handler: (value: any, args: Record<string, any>, ctx: QuickQLServerContext) => any | Promise<any>;
|
|
122
|
+
}
|
|
123
|
+
export interface TransformerConfig {
|
|
124
|
+
onInput?: (data: any) => any;
|
|
125
|
+
onOutput?: (data: any) => any;
|
|
126
|
+
}
|
|
127
|
+
export interface ErrorConfig {
|
|
128
|
+
format?: (error: any, debug?: boolean) => any;
|
|
129
|
+
maskInternalErrors?: boolean;
|
|
130
|
+
}
|
|
131
|
+
export interface ServerOptions {
|
|
132
|
+
schema: SchemaConfig;
|
|
133
|
+
features?: ServerFeatures;
|
|
134
|
+
maxDepth?: number;
|
|
135
|
+
maxComplexity?: number;
|
|
136
|
+
rateLimit?: number;
|
|
137
|
+
cors?: boolean;
|
|
138
|
+
debug?: boolean;
|
|
139
|
+
playground?: boolean | PlaygroundConfig;
|
|
140
|
+
plugins?: QuickQLPlugin[];
|
|
141
|
+
auth?: AuthConfig;
|
|
142
|
+
rbac?: RBACConfig;
|
|
143
|
+
cache?: CacheConfig;
|
|
144
|
+
logging?: LoggingConfig;
|
|
145
|
+
directives?: DirectiveConfig[];
|
|
146
|
+
transformers?: TransformerConfig;
|
|
147
|
+
errors?: ErrorConfig;
|
|
148
|
+
/**
|
|
149
|
+
* Custom context builder function.
|
|
150
|
+
* Receives the request input and returns a context object.
|
|
151
|
+
*/
|
|
152
|
+
context?: (reqInput: any) => Promise<Record<string, any>> | Record<string, any>;
|
|
153
|
+
/**
|
|
154
|
+
* Optional wrapper for atomic batch transactions (e.g. Prisma.$transaction)
|
|
155
|
+
*/
|
|
156
|
+
transactionWrapper?: (ctx: QuickQLServerContext, executeBatch: (tx: any) => Promise<any>) => Promise<any>;
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* QuickQL Server Types
|
|
3
|
+
*
|
|
4
|
+
* Core type definitions for the server engine, plugins, and configuration.
|
|
5
|
+
*
|
|
6
|
+
* (c) 2024-2026 Udinmo Inc. All rights reserved.
|
|
7
|
+
* Author: Udinmo Inc. <engineering@udinmo.com>
|
|
8
|
+
* License: MIT
|
|
9
|
+
*/
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* QuickQL Query Validator
|
|
3
|
+
*
|
|
4
|
+
* Ensures every incoming request matches the defined schema and
|
|
5
|
+
* respects the configured security rules.
|
|
6
|
+
*
|
|
7
|
+
* (c) 2024-2026 Udinmo Inc. All rights reserved.
|
|
8
|
+
* Author: Udinmo Inc. <engineering@udinmo.com>
|
|
9
|
+
* License: MIT
|
|
10
|
+
*/
|
|
11
|
+
import { Query, Mutation } from '@quickql/core';
|
|
12
|
+
import { SchemaConfig } from './types';
|
|
13
|
+
import { SchemaOptions } from './schema/types';
|
|
14
|
+
import { ServerFeatures } from './types';
|
|
15
|
+
export declare class QueryValidator {
|
|
16
|
+
private schema;
|
|
17
|
+
private maxDepth;
|
|
18
|
+
private schemaOptions?;
|
|
19
|
+
private features;
|
|
20
|
+
constructor(schema: SchemaConfig, maxDepth: number, schemaOptions?: SchemaOptions | undefined, features?: ServerFeatures);
|
|
21
|
+
private suggestionCache;
|
|
22
|
+
private fieldSetCache;
|
|
23
|
+
private getFieldsSet;
|
|
24
|
+
validateQuery(query: Query, depth?: number): void;
|
|
25
|
+
validateMutation(mutation: Mutation): void;
|
|
26
|
+
private validateArguments;
|
|
27
|
+
private findCachedSuggestion;
|
|
28
|
+
private findSuggestion;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=validator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../../src/validator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAEzC,qBAAa,cAAc;IAEvB,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,aAAa,CAAC;IACtB,OAAO,CAAC,QAAQ;gBAHR,MAAM,EAAE,YAAY,EACpB,QAAQ,EAAE,MAAM,EAChB,aAAa,CAAC,EAAE,aAAa,YAAA,EAC7B,QAAQ,GAAE,cAAgF;IAGpG,OAAO,CAAC,eAAe,CAAyC;IAChE,OAAO,CAAC,aAAa,CAAkC;IAEvD,OAAO,CAAC,YAAY;IAOpB,aAAa,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,SAAI,GAAG,IAAI;IAgF5C,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IAqB1C,OAAO,CAAC,iBAAiB;IAsCzB,OAAO,CAAC,oBAAoB;IAO5B,OAAO,CAAC,cAAc;CAYvB"}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* QuickQL Query Validator
|
|
3
|
+
*
|
|
4
|
+
* Ensures every incoming request matches the defined schema and
|
|
5
|
+
* respects the configured security rules.
|
|
6
|
+
*
|
|
7
|
+
* (c) 2024-2026 Udinmo Inc. All rights reserved.
|
|
8
|
+
* Author: Udinmo Inc. <engineering@udinmo.com>
|
|
9
|
+
* License: MIT
|
|
10
|
+
*/
|
|
11
|
+
import { createValidationError, createSecurityError } from './errors';
|
|
12
|
+
export class QueryValidator {
|
|
13
|
+
schema;
|
|
14
|
+
maxDepth;
|
|
15
|
+
schemaOptions;
|
|
16
|
+
features;
|
|
17
|
+
constructor(schema, maxDepth, schemaOptions, features = { smartCollectionMatching: true, smartRelationDiscovery: true }) {
|
|
18
|
+
this.schema = schema;
|
|
19
|
+
this.maxDepth = maxDepth;
|
|
20
|
+
this.schemaOptions = schemaOptions;
|
|
21
|
+
this.features = features;
|
|
22
|
+
}
|
|
23
|
+
suggestionCache = new Map();
|
|
24
|
+
fieldSetCache = new Map();
|
|
25
|
+
getFieldsSet(collectionName, fields) {
|
|
26
|
+
if (this.fieldSetCache.has(collectionName))
|
|
27
|
+
return this.fieldSetCache.get(collectionName);
|
|
28
|
+
const set = new Set(Array.isArray(fields) ? fields : Object.keys(fields));
|
|
29
|
+
this.fieldSetCache.set(collectionName, set);
|
|
30
|
+
return set;
|
|
31
|
+
}
|
|
32
|
+
validateQuery(query, depth = 0) {
|
|
33
|
+
if (depth > this.maxDepth) {
|
|
34
|
+
throw createSecurityError(`Security violation: Query exceeds maximum depth of ${this.maxDepth}.`);
|
|
35
|
+
}
|
|
36
|
+
const collectionName = query.from;
|
|
37
|
+
let collection = this.schema[collectionName];
|
|
38
|
+
// Smart Discovery: Try singular / plural / fuzzy variations
|
|
39
|
+
if (!collection && this.features.smartCollectionMatching) {
|
|
40
|
+
const candidates = Object.keys(this.schema);
|
|
41
|
+
const exactMatch = candidates.find(c => c === collectionName ||
|
|
42
|
+
c === `${collectionName}s` ||
|
|
43
|
+
c === `${collectionName}es` ||
|
|
44
|
+
c === collectionName.replace(/s$/, ''));
|
|
45
|
+
if (exactMatch) {
|
|
46
|
+
collection = this.schema[exactMatch];
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
const suggestion = this.findCachedSuggestion(collectionName, candidates);
|
|
50
|
+
if (suggestion) {
|
|
51
|
+
collection = this.schema[suggestion];
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
if (!collection) {
|
|
56
|
+
const suggestion = this.findCachedSuggestion(collectionName, Object.keys(this.schema));
|
|
57
|
+
throw createValidationError(`Unknown collection: ${collectionName}${suggestion ? `. Did you mean '${suggestion}'?` : ''}`);
|
|
58
|
+
}
|
|
59
|
+
// 1. Validate fields in selection
|
|
60
|
+
const fieldSet = this.getFieldsSet(collectionName, collection.fields);
|
|
61
|
+
if (query.select) {
|
|
62
|
+
for (const field of query.select) {
|
|
63
|
+
if (field === '*')
|
|
64
|
+
continue;
|
|
65
|
+
if (!fieldSet.has(field)) {
|
|
66
|
+
throw createValidationError(`Invalid field selection: '${field}' does not exist on collection '${collectionName}'`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
// 2. Validate relations in inclusion
|
|
71
|
+
if (query.include) {
|
|
72
|
+
for (const relationKey of Object.keys(query.include)) {
|
|
73
|
+
let relationDef = collection.relations?.[relationKey];
|
|
74
|
+
// Smart Discovery: If missing, allow if naming convention might match (e.g. author -> authorId)
|
|
75
|
+
if (!relationDef && this.features.smartRelationDiscovery) {
|
|
76
|
+
const possibleKeys = [`${relationKey}Id`, `${relationKey}_id`, `${relationKey}`];
|
|
77
|
+
const hasMatchingField = possibleKeys.some(k => collection.fields.includes(k));
|
|
78
|
+
const guestTarget = [relationKey, `${relationKey}s`, `${relationKey}es`].some(t => this.schema[t]);
|
|
79
|
+
if (hasMatchingField && guestTarget) {
|
|
80
|
+
// Implicitly allowed!
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
if (!relationDef) {
|
|
85
|
+
throw createValidationError(`Invalid relation inclusion: '${relationKey}' is not defined for collection '${collectionName}'`);
|
|
86
|
+
}
|
|
87
|
+
const nestedQuery = query.include?.[relationKey];
|
|
88
|
+
if (nestedQuery) {
|
|
89
|
+
// Normalize the nested query 'from' for validation
|
|
90
|
+
const schemaQuery = { ...nestedQuery, from: relationDef.from };
|
|
91
|
+
this.validateQuery(schemaQuery, depth + 1);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
// 3. Validate arguments in where clause
|
|
96
|
+
if (query.where) {
|
|
97
|
+
this.validateArguments(query.where, collection.fields, collectionName);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
validateMutation(mutation) {
|
|
101
|
+
// 1. Check if it's a custom root mutation (Schema-level)
|
|
102
|
+
if (this.schemaOptions?.mutations?.[mutation.collection]) {
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
// Fallback logic for collection-level mutations
|
|
106
|
+
const collection = this.schema[mutation.collection];
|
|
107
|
+
if (collection) {
|
|
108
|
+
if (!collection.mutationResolver) {
|
|
109
|
+
throw createValidationError(`Mutations are NOT enabled for collection: ${mutation.collection}`);
|
|
110
|
+
}
|
|
111
|
+
if ((mutation.type === 'create' || mutation.type === 'update') && !mutation.data) {
|
|
112
|
+
throw createValidationError(`Data payload is required for mutation type: ${mutation.type}`);
|
|
113
|
+
}
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
throw createValidationError(`Unknown mutation or collection: ${mutation.collection}`);
|
|
117
|
+
}
|
|
118
|
+
validateArguments(where, collectionFields, collectionName) {
|
|
119
|
+
const keys = Object.keys(where);
|
|
120
|
+
const fieldNames = Array.isArray(collectionFields) ? collectionFields : Object.keys(collectionFields);
|
|
121
|
+
for (const key of keys) {
|
|
122
|
+
if (key === 'AND' || key === 'OR') {
|
|
123
|
+
const subConditions = where[key];
|
|
124
|
+
if (Array.isArray(subConditions)) {
|
|
125
|
+
subConditions.forEach(sub => this.validateArguments(sub, collectionFields, collectionName));
|
|
126
|
+
}
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
if (!fieldNames.includes(key)) {
|
|
130
|
+
throw createValidationError(`Invalid filter: Field '${key}' does not exist on collection '${collectionName}'`);
|
|
131
|
+
}
|
|
132
|
+
// Add Type-Safety Check!
|
|
133
|
+
if (!Array.isArray(collectionFields)) {
|
|
134
|
+
const fieldDef = collectionFields[key];
|
|
135
|
+
const type = typeof fieldDef === 'string' ? fieldDef : fieldDef.type;
|
|
136
|
+
const value = where[key];
|
|
137
|
+
if (type && typeof value === 'object' && value !== null && !Array.isArray(value)) {
|
|
138
|
+
// Operator check (can't easily type check the value inside 'eq/gt' here without a mapping)
|
|
139
|
+
}
|
|
140
|
+
else if (type && value !== null) {
|
|
141
|
+
const actualType = typeof value;
|
|
142
|
+
if (type === 'number' && actualType !== 'number') {
|
|
143
|
+
throw createValidationError(`Type mismatch: Field '${key}' expects ${type}, but got ${actualType}`);
|
|
144
|
+
}
|
|
145
|
+
if (type === 'boolean' && actualType !== 'boolean') {
|
|
146
|
+
throw createValidationError(`Type mismatch: Field '${key}' expects ${type}, but got ${actualType}`);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
findCachedSuggestion(input, options) {
|
|
153
|
+
if (this.suggestionCache.has(input))
|
|
154
|
+
return this.suggestionCache.get(input);
|
|
155
|
+
const suggestion = this.findSuggestion(input, options);
|
|
156
|
+
this.suggestionCache.set(input, suggestion);
|
|
157
|
+
return suggestion;
|
|
158
|
+
}
|
|
159
|
+
findSuggestion(input, options) {
|
|
160
|
+
if (options.length === 0)
|
|
161
|
+
return undefined;
|
|
162
|
+
const inputLower = input.toLowerCase();
|
|
163
|
+
// Exact case-insensitive match
|
|
164
|
+
const nearMatch = options.find(o => o.toLowerCase() === inputLower);
|
|
165
|
+
if (nearMatch)
|
|
166
|
+
return nearMatch;
|
|
167
|
+
// Basic substring check or length proximity
|
|
168
|
+
return options.find(o => o.toLowerCase().includes(inputLower) || inputLower.includes(o.toLowerCase()));
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
//# sourceMappingURL=validator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validator.js","sourceRoot":"","sources":["../../../src/validator.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "1.0.0",
|
|
3
|
+
"name": "@quickql/server",
|
|
4
|
+
"description": "Enterprise-grade QuickQL server engine with advanced security and performance.",
|
|
5
|
+
"author": "Udinmo Inc. <engineering@udinmo.com>",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"homepage": "https://quickql.io",
|
|
8
|
+
"main": "./dist/index.js",
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"files": [
|
|
11
|
+
"dist"
|
|
12
|
+
],
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "tsc",
|
|
15
|
+
"prepublishOnly": "npm run build",
|
|
16
|
+
"test": "tsx tests/runner.ts",
|
|
17
|
+
"playground": "tsx dev.ts"
|
|
18
|
+
},
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"@quickql/core": "*"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"prismjs": "^1.30.0"
|
|
24
|
+
}
|
|
25
|
+
}
|