@mayhem93/nexxus-core-lib 0.0.1
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 +373 -0
- package/README.md +384 -0
- package/dist-cjs/common/BuiltinSchemas.js +26 -0
- package/dist-cjs/common/BuiltinSchemas.js.map +1 -0
- package/dist-cjs/common/FilterQuery.js +252 -0
- package/dist-cjs/common/FilterQuery.js.map +1 -0
- package/dist-cjs/common/JsonPatch.js +392 -0
- package/dist-cjs/common/JsonPatch.js.map +1 -0
- package/dist-cjs/common/ModelTypes.js +3 -0
- package/dist-cjs/common/ModelTypes.js.map +1 -0
- package/dist-cjs/common/QueuePayloads.js +3 -0
- package/dist-cjs/common/QueuePayloads.js.map +1 -0
- package/dist-cjs/common/SchemaValidator.js +41 -0
- package/dist-cjs/common/SchemaValidator.js.map +1 -0
- package/dist-cjs/index.js +20 -0
- package/dist-cjs/index.js.map +1 -0
- package/dist-cjs/lib/BaseService.js +83 -0
- package/dist-cjs/lib/BaseService.js.map +1 -0
- package/dist-cjs/lib/ConfigManager.js +138 -0
- package/dist-cjs/lib/ConfigManager.js.map +1 -0
- package/dist-cjs/lib/ConfigProvider.js +65 -0
- package/dist-cjs/lib/ConfigProvider.js.map +1 -0
- package/dist-cjs/lib/Exceptions.js +64 -0
- package/dist-cjs/lib/Exceptions.js.map +1 -0
- package/dist-cjs/lib/GlobalServices.js +29 -0
- package/dist-cjs/lib/GlobalServices.js.map +1 -0
- package/dist-cjs/lib/Logger.js +131 -0
- package/dist-cjs/lib/Logger.js.map +1 -0
- package/dist-cjs/models/AppModel.js +14 -0
- package/dist-cjs/models/AppModel.js.map +1 -0
- package/dist-cjs/models/Application.js +79 -0
- package/dist-cjs/models/Application.js.map +1 -0
- package/dist-cjs/models/BaseModel.js +33 -0
- package/dist-cjs/models/BaseModel.js.map +1 -0
- package/dist-cjs/models/User.js +39 -0
- package/dist-cjs/models/User.js.map +1 -0
- package/dist-cjs/types/QueuePayloads.js +3 -0
- package/dist-cjs/types/QueuePayloads.js.map +1 -0
- package/dist-esm/common/BuiltinSchemas.js +22 -0
- package/dist-esm/common/BuiltinSchemas.js.map +1 -0
- package/dist-esm/common/FilterQuery.js +247 -0
- package/dist-esm/common/FilterQuery.js.map +1 -0
- package/dist-esm/common/JsonPatch.js +387 -0
- package/dist-esm/common/JsonPatch.js.map +1 -0
- package/dist-esm/common/ModelTypes.js +2 -0
- package/dist-esm/common/ModelTypes.js.map +1 -0
- package/dist-esm/common/QueuePayloads.js +2 -0
- package/dist-esm/common/QueuePayloads.js.map +1 -0
- package/dist-esm/common/SchemaValidator.js +37 -0
- package/dist-esm/common/SchemaValidator.js.map +1 -0
- package/dist-esm/index.js +16 -0
- package/dist-esm/index.js.map +1 -0
- package/dist-esm/lib/BaseService.js +79 -0
- package/dist-esm/lib/BaseService.js.map +1 -0
- package/dist-esm/lib/ConfigManager.js +133 -0
- package/dist-esm/lib/ConfigManager.js.map +1 -0
- package/dist-esm/lib/ConfigProvider.js +56 -0
- package/dist-esm/lib/ConfigProvider.js.map +1 -0
- package/dist-esm/lib/Exceptions.js +53 -0
- package/dist-esm/lib/Exceptions.js.map +1 -0
- package/dist-esm/lib/GlobalServices.js +25 -0
- package/dist-esm/lib/GlobalServices.js.map +1 -0
- package/dist-esm/lib/Logger.js +125 -0
- package/dist-esm/lib/Logger.js.map +1 -0
- package/dist-esm/models/AppModel.js +10 -0
- package/dist-esm/models/AppModel.js.map +1 -0
- package/dist-esm/models/Application.js +74 -0
- package/dist-esm/models/Application.js.map +1 -0
- package/dist-esm/models/BaseModel.js +29 -0
- package/dist-esm/models/BaseModel.js.map +1 -0
- package/dist-esm/models/User.js +35 -0
- package/dist-esm/models/User.js.map +1 -0
- package/dist-esm/types/QueuePayloads.js +2 -0
- package/dist-esm/types/QueuePayloads.js.map +1 -0
- package/dist-types/common/BuiltinSchemas.d.ts +69 -0
- package/dist-types/common/FilterQuery.d.ts +58 -0
- package/dist-types/common/JsonPatch.d.ts +78 -0
- package/dist-types/common/ModelTypes.d.ts +24 -0
- package/dist-types/common/QueuePayloads.d.ts +78 -0
- package/dist-types/common/SchemaValidator.d.ts +4 -0
- package/dist-types/index.d.ts +15 -0
- package/dist-types/lib/BaseService.d.ts +28 -0
- package/dist-types/lib/ConfigManager.d.ts +48 -0
- package/dist-types/lib/ConfigProvider.d.ts +27 -0
- package/dist-types/lib/Exceptions.d.ts +33 -0
- package/dist-types/lib/GlobalServices.d.ts +19 -0
- package/dist-types/lib/Logger.d.ts +48 -0
- package/dist-types/models/AppModel.d.ts +9 -0
- package/dist-types/models/Application.d.ts +29 -0
- package/dist-types/models/BaseModel.d.ts +23 -0
- package/dist-types/models/User.d.ts +17 -0
- package/dist-types/types/QueuePayloads.d.ts +57 -0
- package/package.json +46 -0
- package/src/schemas/root.schema.json +8 -0
- package/src/schemas/winston-logger.schema.json +24 -0
package/README.md
ADDED
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
# @mayhem93/nexxus-core
|
|
2
|
+
|
|
3
|
+
> Foundation package for Nexxus - Shared types, models, utilities, and base classes
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Overview
|
|
8
|
+
|
|
9
|
+
The **Core package** provides the foundational building blocks used across all Nexxus packages. It contains model definitions, DSLs for querying and patching, configuration management, logging infrastructure, and base service classes.
|
|
10
|
+
|
|
11
|
+
**Key Responsibility:** Provide shared abstractions and utilities that ensure consistency across the entire Nexxus ecosystem.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## What's Inside
|
|
16
|
+
|
|
17
|
+
### 📦 Models
|
|
18
|
+
|
|
19
|
+
Built-in models with validation and serialization:
|
|
20
|
+
|
|
21
|
+
- **`Application`** - Multi-tenant app definition with schema
|
|
22
|
+
- **`User`** - User accounts with authentication support
|
|
23
|
+
- **`AppModel`** - Base class for application-specific models
|
|
24
|
+
- **`NexxusBaseModel`** - Abstract base for all models
|
|
25
|
+
|
|
26
|
+
**Features:**
|
|
27
|
+
|
|
28
|
+
- Schema validation
|
|
29
|
+
- Required field checking
|
|
30
|
+
- Type safety
|
|
31
|
+
- Serialization/deserialization
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
### 🔍 FilterQuery DSL
|
|
36
|
+
|
|
37
|
+
Database-agnostic query language for filtering data.
|
|
38
|
+
|
|
39
|
+
**Example:**
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
const query = new NexxusFilterQuery({
|
|
43
|
+
"$and": [
|
|
44
|
+
{ "status": { "$eq": "active" } },
|
|
45
|
+
{ "priority": { "$in": ["high", "urgent"] } }
|
|
46
|
+
]
|
|
47
|
+
}, { appModelDef: schema });
|
|
48
|
+
|
|
49
|
+
// Test against object
|
|
50
|
+
const matches = query.test({ status: "active", priority: "high" }); // true
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
**Operators:** `$eq`, `$ne`, `$gt`, `$gte`, `$lt`, `$lte`, `$in`, `$and`, `$or`
|
|
54
|
+
|
|
55
|
+
**Features:**
|
|
56
|
+
|
|
57
|
+
- Schema validation (field existence, types)
|
|
58
|
+
- Field-level `filterable` flag enforcement
|
|
59
|
+
- Nested object support (dot notation)
|
|
60
|
+
- Type checking based on model schema
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
### ✏️ JsonPatch (Custom Implementation)
|
|
65
|
+
|
|
66
|
+
Custom JSON Patch implementation for efficient updates.
|
|
67
|
+
|
|
68
|
+
**Differences from RFC 6902:**
|
|
69
|
+
|
|
70
|
+
- Uses `.` instead of `/` for path delimiters
|
|
71
|
+
- Supports multiple paths/values in single patch
|
|
72
|
+
- Optimized for real-time synchronization
|
|
73
|
+
|
|
74
|
+
**Example:**
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
const patch = new NexxusJsonPatch({
|
|
78
|
+
op: "replace",
|
|
79
|
+
path: ["status", "priority"],
|
|
80
|
+
value: ["completed", "low"],
|
|
81
|
+
metadata: { /* ... */ }
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// Get partial model representation
|
|
85
|
+
const partial = patch.getPartialModel();
|
|
86
|
+
// { status: "completed", priority: "low" }
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
**Operations:** `add`, `remove`, `replace`, `copy`, `move`, `test`
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
### ⚙️ Configuration Management
|
|
94
|
+
|
|
95
|
+
Hierarchical configuration with multiple providers.
|
|
96
|
+
|
|
97
|
+
**Providers:**
|
|
98
|
+
|
|
99
|
+
- **File** - JSON configuration files
|
|
100
|
+
- **Environment** - Environment variables
|
|
101
|
+
- **CLI** - Command-line arguments
|
|
102
|
+
- **Custom** - Extend `BaseConfigProvider` for AWS Secrets Manager, Vault, etc.
|
|
103
|
+
|
|
104
|
+
**Example:**
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
const configManager = new ConfigManager([
|
|
108
|
+
new FileConfigProvider('./config.json'),
|
|
109
|
+
new EnvConfigProvider(),
|
|
110
|
+
new CliConfigProvider()
|
|
111
|
+
]);
|
|
112
|
+
|
|
113
|
+
await configManager.load();
|
|
114
|
+
const dbConfig = configManager.get('database');
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
**Features:**
|
|
118
|
+
|
|
119
|
+
- Provider priority (later providers override earlier)
|
|
120
|
+
- Nested key access with dot notation
|
|
121
|
+
- Type-safe getters
|
|
122
|
+
- Async loading support
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
### 📝 Logging
|
|
127
|
+
|
|
128
|
+
Abstract logging infrastructure with pluggable implementations.
|
|
129
|
+
|
|
130
|
+
**Base Class:** `BaseLogger`
|
|
131
|
+
|
|
132
|
+
**Built-in Implementations:**
|
|
133
|
+
|
|
134
|
+
- Console logger (development)
|
|
135
|
+
- File logger (production)
|
|
136
|
+
- Custom loggers (Rollbar, Datadog, etc.)
|
|
137
|
+
|
|
138
|
+
**Example:**
|
|
139
|
+
|
|
140
|
+
```typescript
|
|
141
|
+
class CustomLogger extends BaseLogger {
|
|
142
|
+
async initialize() { /* setup */ }
|
|
143
|
+
info(message: string, label?: string) { /* log */ }
|
|
144
|
+
error(message: string, label?: string) { /* log */ }
|
|
145
|
+
// ... other levels
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const logger = new CustomLogger();
|
|
149
|
+
await logger.initialize();
|
|
150
|
+
logger.info('Server started', 'API');
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
### 🏗️ Base Services
|
|
156
|
+
|
|
157
|
+
Abstract classes for implementing pluggable services.
|
|
158
|
+
|
|
159
|
+
**`BaseService<TConfig, TData>`**
|
|
160
|
+
|
|
161
|
+
- Generic base for all services
|
|
162
|
+
- Configuration management
|
|
163
|
+
- Data access patterns
|
|
164
|
+
- Lifecycle methods (initialize, start, stop)
|
|
165
|
+
|
|
166
|
+
**Example:**
|
|
167
|
+
|
|
168
|
+
```typescript
|
|
169
|
+
class MyDatabaseService extends BaseService<DbConfig, DbConnection> {
|
|
170
|
+
async initialize() {
|
|
171
|
+
// Setup connection
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
async start() {
|
|
175
|
+
// Connect to database
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
async stop() {
|
|
179
|
+
// Close connections
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
### 📋 Type Definitions
|
|
187
|
+
|
|
188
|
+
**Model Types:**
|
|
189
|
+
|
|
190
|
+
- `NexxusModelDef` - Schema definition for app models
|
|
191
|
+
- `NexxusFieldDef` - Field definition (primitive, object, array)
|
|
192
|
+
- `PrimitiveFieldDef` - Primitive field with `filterable` flag
|
|
193
|
+
- `NexxusObjectFieldDef` - Nested object structure
|
|
194
|
+
- `NexxusArrayFieldDef` - Array field definition
|
|
195
|
+
|
|
196
|
+
**Queue Payloads:**
|
|
197
|
+
|
|
198
|
+
- `NexxusModelCreatedPayload` - Model creation event
|
|
199
|
+
- `NexxusModelUpdatedPayload` - Model update event (array of patches)
|
|
200
|
+
- `NexxusModelDeletedPayload` - Model deletion event
|
|
201
|
+
- `NexxusWebSocketJsonPatch` - WebSocket-specific patch (slim metadata)
|
|
202
|
+
|
|
203
|
+
**Common Types:**
|
|
204
|
+
|
|
205
|
+
- `NexxusDeviceTransportString` - Device identifier with transport (`deviceId|transport`)
|
|
206
|
+
- `NexxusBaseSubscriptionChannel` - Subscription channel structure
|
|
207
|
+
- `NexxusFilterQuery` - Filter query type
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## Package Structure
|
|
212
|
+
|
|
213
|
+
```
|
|
214
|
+
src/
|
|
215
|
+
├── models/ # Built-in models
|
|
216
|
+
│ ├── Application.ts # App definition with schema
|
|
217
|
+
│ ├── User.ts # User model
|
|
218
|
+
│ ├── AppModel.ts # Base for app-specific models
|
|
219
|
+
│ └── NexxusBaseModel.ts
|
|
220
|
+
│
|
|
221
|
+
├── common/ # Shared utilities
|
|
222
|
+
│ ├── FilterQuery.ts # Query DSL
|
|
223
|
+
│ ├── JsonPatch.ts # Patch operations
|
|
224
|
+
│ ├── QueuePayloads.ts # Message queue types
|
|
225
|
+
│ ├── ModelTypes.ts # Schema type definitions
|
|
226
|
+
│ └── BuiltinSchemas.ts
|
|
227
|
+
│
|
|
228
|
+
├── services/ # Base service classes
|
|
229
|
+
│ ├── BaseService.ts # Generic service base
|
|
230
|
+
│ ├── ConfigManager.ts # Configuration management
|
|
231
|
+
│ └── Logger.ts # Logging infrastructure
|
|
232
|
+
│
|
|
233
|
+
└── exceptions/ # Custom exception classes
|
|
234
|
+
├── InvalidQueryFilterException.ts
|
|
235
|
+
├── InvalidModelSchemaException.ts
|
|
236
|
+
└── ...
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
|
|
241
|
+
## Key Concepts
|
|
242
|
+
|
|
243
|
+
### Model Schema Definition
|
|
244
|
+
|
|
245
|
+
```typescript
|
|
246
|
+
const taskSchema: NexxusModelDef = {
|
|
247
|
+
title: {
|
|
248
|
+
type: 'string',
|
|
249
|
+
required: true,
|
|
250
|
+
filterable: true
|
|
251
|
+
},
|
|
252
|
+
status: {
|
|
253
|
+
type: 'string',
|
|
254
|
+
filterable: true
|
|
255
|
+
},
|
|
256
|
+
assignee: {
|
|
257
|
+
type: 'object',
|
|
258
|
+
properties: {
|
|
259
|
+
email: {
|
|
260
|
+
type: 'string',
|
|
261
|
+
filterable: true
|
|
262
|
+
},
|
|
263
|
+
name: {
|
|
264
|
+
type: 'string',
|
|
265
|
+
filterable: false
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
},
|
|
269
|
+
tags: {
|
|
270
|
+
type: 'array',
|
|
271
|
+
arrayType: 'string'
|
|
272
|
+
}
|
|
273
|
+
};
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
**Filterable Fields:**
|
|
277
|
+
|
|
278
|
+
- Must be explicitly marked with `filterable: true`
|
|
279
|
+
- Defaults to non-filterable if omitted
|
|
280
|
+
- Only available on primitive types
|
|
281
|
+
- Supports nested objects with dot notation
|
|
282
|
+
|
|
283
|
+
---
|
|
284
|
+
|
|
285
|
+
### Queue Payload Flow
|
|
286
|
+
|
|
287
|
+
```
|
|
288
|
+
API → Writer Queue
|
|
289
|
+
↓
|
|
290
|
+
NexxusModelCreatedPayload / NexxusModelUpdatedPayload / NexxusModelDeletedPayload
|
|
291
|
+
↓
|
|
292
|
+
Writer Worker → Transport Manager Queue
|
|
293
|
+
↓
|
|
294
|
+
Same payloads (with full metadata)
|
|
295
|
+
↓
|
|
296
|
+
Transport Manager → WebSocket Queue
|
|
297
|
+
↓
|
|
298
|
+
NexxusWebSocketModelUpdatedPayload (slim metadata with channel keys)
|
|
299
|
+
↓
|
|
300
|
+
WebSocket Worker → Client
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
---
|
|
304
|
+
|
|
305
|
+
## Dependencies
|
|
306
|
+
|
|
307
|
+
**Runtime:**
|
|
308
|
+
|
|
309
|
+
- None (pure TypeScript, no external runtime dependencies)
|
|
310
|
+
|
|
311
|
+
**DevDependencies:**
|
|
312
|
+
|
|
313
|
+
- TypeScript
|
|
314
|
+
- Node.js type definitions
|
|
315
|
+
|
|
316
|
+
---
|
|
317
|
+
|
|
318
|
+
## Usage in Other Packages
|
|
319
|
+
|
|
320
|
+
**All Nexxus packages depend on Core:**
|
|
321
|
+
|
|
322
|
+
```typescript
|
|
323
|
+
// In @mayhem93/nexxus-api
|
|
324
|
+
import { NexxusFilterQuery, Application, User } from '@mayhem93/nexxus-core';
|
|
325
|
+
|
|
326
|
+
// In @mayhem93/nexxus-worker
|
|
327
|
+
import { NexxusJsonPatch, NexxusModelUpdatedPayload } from '@mayhem93/nexxus-core';
|
|
328
|
+
|
|
329
|
+
// In @mayhem93/nexxus-database
|
|
330
|
+
import { NexxusModelDef, BaseService } from '@mayhem93/nexxus-core';
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
---
|
|
334
|
+
|
|
335
|
+
## Extensibility
|
|
336
|
+
|
|
337
|
+
### Custom Config Provider
|
|
338
|
+
|
|
339
|
+
```typescript
|
|
340
|
+
import { BaseConfigProvider } from '@mayhem93/nexxus-core';
|
|
341
|
+
|
|
342
|
+
export class VaultConfigProvider extends BaseConfigProvider {
|
|
343
|
+
async load(): Promise<Record<string, any>> {
|
|
344
|
+
// Fetch from HashiCorp Vault
|
|
345
|
+
return vaultClient.read('secret/nexxus');
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
### Custom Logger
|
|
351
|
+
|
|
352
|
+
```typescript
|
|
353
|
+
import { BaseLogger } from '@mayhem93/nexxus-core';
|
|
354
|
+
|
|
355
|
+
export class DatadogLogger extends BaseLogger {
|
|
356
|
+
async initialize() {
|
|
357
|
+
// Setup Datadog client
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
error(message: string, label?: string) {
|
|
361
|
+
// Send to Datadog
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
---
|
|
367
|
+
|
|
368
|
+
## Status
|
|
369
|
+
|
|
370
|
+
🚧 **Work in Progress** - Types and interfaces may evolve as features are added.
|
|
371
|
+
|
|
372
|
+
---
|
|
373
|
+
|
|
374
|
+
## Related Packages
|
|
375
|
+
|
|
376
|
+
- **[@mayhem93/nexxus-api](../api/)** - Uses models, FilterQuery, and types
|
|
377
|
+
- **[@mayhem93/nexxus-worker](../worker/)** - Uses JsonPatch, queue payloads, and base classes
|
|
378
|
+
- **[@mayhem93/nexxus-database](../database/)** - Uses FilterQuery translation and model schemas
|
|
379
|
+
|
|
380
|
+
---
|
|
381
|
+
|
|
382
|
+
## License
|
|
383
|
+
|
|
384
|
+
MPL-2.0
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NEXXUS_BUILTIN_MODEL_SCHEMAS = exports.NEXXUS_UNIVERSAL_FIELDS = void 0;
|
|
4
|
+
exports.isBuiltinModel = isBuiltinModel;
|
|
5
|
+
exports.NEXXUS_UNIVERSAL_FIELDS = {
|
|
6
|
+
id: { type: 'string', required: true },
|
|
7
|
+
createdAt: { type: 'date', required: true },
|
|
8
|
+
updatedAt: { type: 'date', required: true }
|
|
9
|
+
};
|
|
10
|
+
exports.NEXXUS_BUILTIN_MODEL_SCHEMAS = {
|
|
11
|
+
user: {
|
|
12
|
+
userType: { type: 'string', required: false, filterable: true },
|
|
13
|
+
username: { type: 'string', required: true, filterable: true },
|
|
14
|
+
password: { type: 'string', required: false },
|
|
15
|
+
authProviders: { type: 'array', required: true, arrayType: 'string' },
|
|
16
|
+
devices: { type: 'array', required: true, arrayType: 'string' },
|
|
17
|
+
details: { type: 'object', required: false, properties: {} }
|
|
18
|
+
},
|
|
19
|
+
application: {
|
|
20
|
+
name: { type: 'string', required: true, filterable: true }
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
function isBuiltinModel(modelType) {
|
|
24
|
+
return modelType in exports.NEXXUS_BUILTIN_MODEL_SCHEMAS;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=BuiltinSchemas.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BuiltinSchemas.js","sourceRoot":"","sources":["../../src/common/BuiltinSchemas.ts"],"names":[],"mappings":";;;AAmCA,wCAEC;AAjCY,QAAA,uBAAuB,GAAG;IACrC,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE;IACtC,SAAS,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE;IAC3C,SAAS,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE;CACnC,CAAC;AAKE,QAAA,4BAA4B,GAAG;IAC1C,IAAI,EAAE;QACJ,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE;QAC/D,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE;QAC9D,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE;QAC7C,aAAa,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE;QACrE,OAAO,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE;QAC/D,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,EAAE;KAC7D;IACD,WAAW,EAAE;QACX,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE;KAC3D;CACO,CAAC;AAUX,SAAgB,cAAc,CAAC,SAAiB;IAC9C,OAAO,SAAS,IAAI,oCAA4B,CAAC;AACnD,CAAC"}
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NexxusFilterQuery = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const Exceptions_1 = require("../lib/Exceptions");
|
|
6
|
+
const BuiltinSchemas_1 = require("./BuiltinSchemas");
|
|
7
|
+
const dot = tslib_1.__importStar(require("dot-prop"));
|
|
8
|
+
const sort_keys_1 = tslib_1.__importDefault(require("sort-keys"));
|
|
9
|
+
class NexxusFilterQuery {
|
|
10
|
+
query;
|
|
11
|
+
nodes = [];
|
|
12
|
+
modelDef;
|
|
13
|
+
constructor(query, config) {
|
|
14
|
+
this.query = query;
|
|
15
|
+
if ('appModelDef' in config) {
|
|
16
|
+
this.modelDef = { ...BuiltinSchemas_1.NEXXUS_UNIVERSAL_FIELDS, ...config.appModelDef, ...{ userId: { type: 'string', required: false } } };
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
const builtinSchema = BuiltinSchemas_1.NEXXUS_BUILTIN_MODEL_SCHEMAS[config.modelType];
|
|
20
|
+
this.modelDef = { ...BuiltinSchemas_1.NEXXUS_UNIVERSAL_FIELDS, ...builtinSchema };
|
|
21
|
+
if (config.modelType === 'user') {
|
|
22
|
+
if (!config.userDetailsSchema) {
|
|
23
|
+
throw new Exceptions_1.InvalidQueryFilterException("User detail schema must be provided for 'user' model queries");
|
|
24
|
+
}
|
|
25
|
+
this.modelDef.details = { type: 'object', properties: config.userDetailsSchema, required: false };
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
this.validateAndParse();
|
|
29
|
+
}
|
|
30
|
+
getNodes() {
|
|
31
|
+
return this.nodes;
|
|
32
|
+
}
|
|
33
|
+
getNormalizedQuery() {
|
|
34
|
+
return (0, sort_keys_1.default)(this.query, { deep: true });
|
|
35
|
+
}
|
|
36
|
+
*[Symbol.iterator]() {
|
|
37
|
+
yield* this.traverseNodes(this.nodes, 0);
|
|
38
|
+
}
|
|
39
|
+
test(object) {
|
|
40
|
+
return this.nodes.every(node => this.testNode(node, object));
|
|
41
|
+
}
|
|
42
|
+
testNode(node, object) {
|
|
43
|
+
if (node.type === 'field') {
|
|
44
|
+
return this.testFieldCondition(node, object);
|
|
45
|
+
}
|
|
46
|
+
if (node.operator === '$and') {
|
|
47
|
+
return node.conditions.every(childNode => this.testNode(childNode, object));
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
return node.conditions.some(childNode => this.testNode(childNode, object));
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
validateAndParse() {
|
|
54
|
+
this.nodes = this.parseQuery(this.query, this.modelDef);
|
|
55
|
+
}
|
|
56
|
+
parseQuery(query, modelSchema) {
|
|
57
|
+
const nodes = [];
|
|
58
|
+
for (const key in query) {
|
|
59
|
+
if (key === '$and' || key === '$or') {
|
|
60
|
+
const conditions = query[key];
|
|
61
|
+
if (!Array.isArray(conditions) || conditions.length === 0) {
|
|
62
|
+
throw new Exceptions_1.InvalidQueryFilterException(`Logical operator "${key}" must have at least one condition`);
|
|
63
|
+
}
|
|
64
|
+
const childNodes = conditions.flatMap(cond => this.parseQuery(cond, modelSchema));
|
|
65
|
+
nodes.push({
|
|
66
|
+
type: 'logical',
|
|
67
|
+
operator: key,
|
|
68
|
+
conditions: childNodes
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
const condition = query[key];
|
|
73
|
+
const fieldNode = this.parseFieldCondition(key, condition, modelSchema);
|
|
74
|
+
nodes.push(fieldNode);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return nodes;
|
|
78
|
+
}
|
|
79
|
+
testFieldCondition(node, object) {
|
|
80
|
+
const actualValue = dot.getProperty(object, node.field);
|
|
81
|
+
if (actualValue === undefined) {
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
switch (node.operator) {
|
|
85
|
+
case 'eq':
|
|
86
|
+
return actualValue === node.value;
|
|
87
|
+
case 'ne':
|
|
88
|
+
return actualValue !== node.value;
|
|
89
|
+
case 'gt':
|
|
90
|
+
return typeof actualValue === 'number' && actualValue > node.value;
|
|
91
|
+
case 'gte':
|
|
92
|
+
return typeof actualValue === 'number' && actualValue >= node.value;
|
|
93
|
+
case 'lt':
|
|
94
|
+
return typeof actualValue === 'number' && actualValue < node.value;
|
|
95
|
+
case 'lte':
|
|
96
|
+
return typeof actualValue === 'number' && actualValue <= node.value;
|
|
97
|
+
case 'in':
|
|
98
|
+
const values = node.value;
|
|
99
|
+
return values.some(v => actualValue === v);
|
|
100
|
+
default:
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
parseFieldCondition(path, condition, modelSchema) {
|
|
105
|
+
const fieldDef = this.getFieldFromPath(path, modelSchema);
|
|
106
|
+
if (!fieldDef) {
|
|
107
|
+
throw new Exceptions_1.InvalidQueryFilterException(`Field "${path}" does not exist in model schema`);
|
|
108
|
+
}
|
|
109
|
+
if (fieldDef.type === 'object' || fieldDef.type === 'array') {
|
|
110
|
+
throw new Exceptions_1.InvalidQueryFilterException(`Cannot filter on non-primitive field "${path}"`);
|
|
111
|
+
}
|
|
112
|
+
if (!fieldDef.filterable) {
|
|
113
|
+
throw new Exceptions_1.InvalidQueryFilterException(`Field "${path}" is not filterable`);
|
|
114
|
+
}
|
|
115
|
+
if (typeof condition !== 'object' || condition === null) {
|
|
116
|
+
this.validateValueType(condition, fieldDef, path);
|
|
117
|
+
return {
|
|
118
|
+
type: 'field',
|
|
119
|
+
field: path,
|
|
120
|
+
operator: 'eq',
|
|
121
|
+
value: condition
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
const operators = Object.keys(condition);
|
|
125
|
+
if (operators.length === 0) {
|
|
126
|
+
throw new Exceptions_1.InvalidQueryFilterException(`Field "${path}" has empty operator object`);
|
|
127
|
+
}
|
|
128
|
+
if (operators.length > 1) {
|
|
129
|
+
throw new Exceptions_1.InvalidQueryFilterException(`Field "${path}" can only have one operator per condition`);
|
|
130
|
+
}
|
|
131
|
+
const operator = operators[0];
|
|
132
|
+
const value = condition[operator];
|
|
133
|
+
this.validateOperator(operator, fieldDef, path);
|
|
134
|
+
if (operator === 'in') {
|
|
135
|
+
if (!Array.isArray(value)) {
|
|
136
|
+
throw new Exceptions_1.InvalidQueryFilterException(`Operator "in" at path "${path}" must have an array value`);
|
|
137
|
+
}
|
|
138
|
+
value.forEach(v => this.validateValueType(v, fieldDef, path));
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
this.validateValueType(value, fieldDef, path);
|
|
142
|
+
}
|
|
143
|
+
return {
|
|
144
|
+
type: 'field',
|
|
145
|
+
field: path,
|
|
146
|
+
operator,
|
|
147
|
+
value: value
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
getFieldFromPath(path, modelSchema) {
|
|
151
|
+
const parts = path.split('.');
|
|
152
|
+
let current = modelSchema;
|
|
153
|
+
for (let i = 0; i < parts.length; i++) {
|
|
154
|
+
const part = parts[i];
|
|
155
|
+
if (!(part in current)) {
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
const fieldDef = current[part];
|
|
159
|
+
if (i === parts.length - 1) {
|
|
160
|
+
return fieldDef;
|
|
161
|
+
}
|
|
162
|
+
if (fieldDef.type === 'object') {
|
|
163
|
+
current = fieldDef.properties;
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
return null;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return null;
|
|
170
|
+
}
|
|
171
|
+
validateOperator(operator, fieldDef, path) {
|
|
172
|
+
const { type } = fieldDef;
|
|
173
|
+
const comparisonOps = ['gte', 'lte', 'gt', 'lt'];
|
|
174
|
+
if (comparisonOps.includes(operator)) {
|
|
175
|
+
if (type !== 'number' && type !== 'date') {
|
|
176
|
+
throw new Exceptions_1.InvalidQueryFilterException(`Operator "${operator}" at path "${path}" can only be used with number or date fields`);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
if (operator === 'in') {
|
|
180
|
+
if (type === 'object') {
|
|
181
|
+
throw new Exceptions_1.InvalidQueryFilterException(`Operator "in" at path "${path}" cannot be used with object fields`);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
validateValueType(value, fieldDef, path) {
|
|
186
|
+
const { type } = fieldDef;
|
|
187
|
+
switch (type) {
|
|
188
|
+
case 'string':
|
|
189
|
+
if (typeof value !== 'string') {
|
|
190
|
+
throw new Exceptions_1.InvalidQueryFilterException(`Value at path "${path}" must be a string`);
|
|
191
|
+
}
|
|
192
|
+
break;
|
|
193
|
+
case 'number':
|
|
194
|
+
if (typeof value !== 'number' || isNaN(value)) {
|
|
195
|
+
throw new Exceptions_1.InvalidQueryFilterException(`Value at path "${path}" must be a number`);
|
|
196
|
+
}
|
|
197
|
+
break;
|
|
198
|
+
case 'boolean':
|
|
199
|
+
if (typeof value !== 'boolean') {
|
|
200
|
+
throw new Exceptions_1.InvalidQueryFilterException(`Value at path "${path}" must be a boolean`);
|
|
201
|
+
}
|
|
202
|
+
break;
|
|
203
|
+
case 'date':
|
|
204
|
+
const isValidDate = (typeof value === 'number' && !isNaN(value)) ||
|
|
205
|
+
(typeof value === 'string' && !isNaN(Date.parse(value)));
|
|
206
|
+
if (!isValidDate) {
|
|
207
|
+
throw new Exceptions_1.InvalidQueryFilterException(`Value at path "${path}" must be a Unix timestamp or ISO date string`);
|
|
208
|
+
}
|
|
209
|
+
break;
|
|
210
|
+
case 'array':
|
|
211
|
+
const arrayFieldDef = fieldDef;
|
|
212
|
+
const arrayType = arrayFieldDef.arrayType;
|
|
213
|
+
switch (arrayType) {
|
|
214
|
+
case 'string':
|
|
215
|
+
if (typeof value !== 'string') {
|
|
216
|
+
throw new Exceptions_1.InvalidQueryFilterException(`Value at path "${path}" must be a string (array contains strings)`);
|
|
217
|
+
}
|
|
218
|
+
break;
|
|
219
|
+
case 'number':
|
|
220
|
+
if (typeof value !== 'number') {
|
|
221
|
+
throw new Exceptions_1.InvalidQueryFilterException(`Value at path "${path}" must be a number (array contains numbers)`);
|
|
222
|
+
}
|
|
223
|
+
break;
|
|
224
|
+
case 'boolean':
|
|
225
|
+
if (typeof value !== 'boolean') {
|
|
226
|
+
throw new Exceptions_1.InvalidQueryFilterException(`Value at path "${path}" must be a boolean (array contains booleans)`);
|
|
227
|
+
}
|
|
228
|
+
break;
|
|
229
|
+
case 'date':
|
|
230
|
+
if (typeof value !== 'string' || isNaN(Date.parse(value))) {
|
|
231
|
+
throw new Exceptions_1.InvalidQueryFilterException(`Value at path "${path}" must be an ISO date string (array contains dates)`);
|
|
232
|
+
}
|
|
233
|
+
break;
|
|
234
|
+
case 'object':
|
|
235
|
+
throw new Exceptions_1.InvalidQueryFilterException(`Cannot query array of objects at path "${path}". Use dot notation for nested fields.`);
|
|
236
|
+
}
|
|
237
|
+
break;
|
|
238
|
+
case 'object':
|
|
239
|
+
throw new Exceptions_1.InvalidQueryFilterException(`Cannot query object field "${path}" directly. Use dot notation for nested fields.`);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
*traverseNodes(nodes, depth, parentOperator) {
|
|
243
|
+
for (const node of nodes) {
|
|
244
|
+
yield { ...node, depth, parentOperator };
|
|
245
|
+
if (node.type === 'logical') {
|
|
246
|
+
yield* this.traverseNodes(node.conditions, depth + 1, node.operator);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
exports.NexxusFilterQuery = NexxusFilterQuery;
|
|
252
|
+
//# sourceMappingURL=FilterQuery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FilterQuery.js","sourceRoot":"","sources":["../../src/common/FilterQuery.ts"],"names":[],"mappings":"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"}
|