@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.
Files changed (95) hide show
  1. package/LICENSE +373 -0
  2. package/README.md +384 -0
  3. package/dist-cjs/common/BuiltinSchemas.js +26 -0
  4. package/dist-cjs/common/BuiltinSchemas.js.map +1 -0
  5. package/dist-cjs/common/FilterQuery.js +252 -0
  6. package/dist-cjs/common/FilterQuery.js.map +1 -0
  7. package/dist-cjs/common/JsonPatch.js +392 -0
  8. package/dist-cjs/common/JsonPatch.js.map +1 -0
  9. package/dist-cjs/common/ModelTypes.js +3 -0
  10. package/dist-cjs/common/ModelTypes.js.map +1 -0
  11. package/dist-cjs/common/QueuePayloads.js +3 -0
  12. package/dist-cjs/common/QueuePayloads.js.map +1 -0
  13. package/dist-cjs/common/SchemaValidator.js +41 -0
  14. package/dist-cjs/common/SchemaValidator.js.map +1 -0
  15. package/dist-cjs/index.js +20 -0
  16. package/dist-cjs/index.js.map +1 -0
  17. package/dist-cjs/lib/BaseService.js +83 -0
  18. package/dist-cjs/lib/BaseService.js.map +1 -0
  19. package/dist-cjs/lib/ConfigManager.js +138 -0
  20. package/dist-cjs/lib/ConfigManager.js.map +1 -0
  21. package/dist-cjs/lib/ConfigProvider.js +65 -0
  22. package/dist-cjs/lib/ConfigProvider.js.map +1 -0
  23. package/dist-cjs/lib/Exceptions.js +64 -0
  24. package/dist-cjs/lib/Exceptions.js.map +1 -0
  25. package/dist-cjs/lib/GlobalServices.js +29 -0
  26. package/dist-cjs/lib/GlobalServices.js.map +1 -0
  27. package/dist-cjs/lib/Logger.js +131 -0
  28. package/dist-cjs/lib/Logger.js.map +1 -0
  29. package/dist-cjs/models/AppModel.js +14 -0
  30. package/dist-cjs/models/AppModel.js.map +1 -0
  31. package/dist-cjs/models/Application.js +79 -0
  32. package/dist-cjs/models/Application.js.map +1 -0
  33. package/dist-cjs/models/BaseModel.js +33 -0
  34. package/dist-cjs/models/BaseModel.js.map +1 -0
  35. package/dist-cjs/models/User.js +39 -0
  36. package/dist-cjs/models/User.js.map +1 -0
  37. package/dist-cjs/types/QueuePayloads.js +3 -0
  38. package/dist-cjs/types/QueuePayloads.js.map +1 -0
  39. package/dist-esm/common/BuiltinSchemas.js +22 -0
  40. package/dist-esm/common/BuiltinSchemas.js.map +1 -0
  41. package/dist-esm/common/FilterQuery.js +247 -0
  42. package/dist-esm/common/FilterQuery.js.map +1 -0
  43. package/dist-esm/common/JsonPatch.js +387 -0
  44. package/dist-esm/common/JsonPatch.js.map +1 -0
  45. package/dist-esm/common/ModelTypes.js +2 -0
  46. package/dist-esm/common/ModelTypes.js.map +1 -0
  47. package/dist-esm/common/QueuePayloads.js +2 -0
  48. package/dist-esm/common/QueuePayloads.js.map +1 -0
  49. package/dist-esm/common/SchemaValidator.js +37 -0
  50. package/dist-esm/common/SchemaValidator.js.map +1 -0
  51. package/dist-esm/index.js +16 -0
  52. package/dist-esm/index.js.map +1 -0
  53. package/dist-esm/lib/BaseService.js +79 -0
  54. package/dist-esm/lib/BaseService.js.map +1 -0
  55. package/dist-esm/lib/ConfigManager.js +133 -0
  56. package/dist-esm/lib/ConfigManager.js.map +1 -0
  57. package/dist-esm/lib/ConfigProvider.js +56 -0
  58. package/dist-esm/lib/ConfigProvider.js.map +1 -0
  59. package/dist-esm/lib/Exceptions.js +53 -0
  60. package/dist-esm/lib/Exceptions.js.map +1 -0
  61. package/dist-esm/lib/GlobalServices.js +25 -0
  62. package/dist-esm/lib/GlobalServices.js.map +1 -0
  63. package/dist-esm/lib/Logger.js +125 -0
  64. package/dist-esm/lib/Logger.js.map +1 -0
  65. package/dist-esm/models/AppModel.js +10 -0
  66. package/dist-esm/models/AppModel.js.map +1 -0
  67. package/dist-esm/models/Application.js +74 -0
  68. package/dist-esm/models/Application.js.map +1 -0
  69. package/dist-esm/models/BaseModel.js +29 -0
  70. package/dist-esm/models/BaseModel.js.map +1 -0
  71. package/dist-esm/models/User.js +35 -0
  72. package/dist-esm/models/User.js.map +1 -0
  73. package/dist-esm/types/QueuePayloads.js +2 -0
  74. package/dist-esm/types/QueuePayloads.js.map +1 -0
  75. package/dist-types/common/BuiltinSchemas.d.ts +69 -0
  76. package/dist-types/common/FilterQuery.d.ts +58 -0
  77. package/dist-types/common/JsonPatch.d.ts +78 -0
  78. package/dist-types/common/ModelTypes.d.ts +24 -0
  79. package/dist-types/common/QueuePayloads.d.ts +78 -0
  80. package/dist-types/common/SchemaValidator.d.ts +4 -0
  81. package/dist-types/index.d.ts +15 -0
  82. package/dist-types/lib/BaseService.d.ts +28 -0
  83. package/dist-types/lib/ConfigManager.d.ts +48 -0
  84. package/dist-types/lib/ConfigProvider.d.ts +27 -0
  85. package/dist-types/lib/Exceptions.d.ts +33 -0
  86. package/dist-types/lib/GlobalServices.d.ts +19 -0
  87. package/dist-types/lib/Logger.d.ts +48 -0
  88. package/dist-types/models/AppModel.d.ts +9 -0
  89. package/dist-types/models/Application.d.ts +29 -0
  90. package/dist-types/models/BaseModel.d.ts +23 -0
  91. package/dist-types/models/User.d.ts +17 -0
  92. package/dist-types/types/QueuePayloads.d.ts +57 -0
  93. package/package.json +46 -0
  94. package/src/schemas/root.schema.json +8 -0
  95. 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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"}