@tamyla/clodo-framework 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.
Files changed (130) hide show
  1. package/CHANGELOG.md +564 -0
  2. package/LICENSE +21 -0
  3. package/README.md +1393 -0
  4. package/bin/README.md +71 -0
  5. package/bin/clodo-service.js +416 -0
  6. package/bin/security/security-cli.js +96 -0
  7. package/bin/service-management/README.md +74 -0
  8. package/bin/service-management/create-service.js +129 -0
  9. package/bin/service-management/init-service.js +102 -0
  10. package/bin/service-management/init-service.js.backup +889 -0
  11. package/bin/shared/config/customer-cli.js +293 -0
  12. package/dist/config/ConfigurationManager.js +159 -0
  13. package/dist/config/CustomerConfigCLI.js +220 -0
  14. package/dist/config/FeatureManager.js +426 -0
  15. package/dist/config/customers.js +441 -0
  16. package/dist/config/domains.js +180 -0
  17. package/dist/config/features.js +225 -0
  18. package/dist/config/index.js +6 -0
  19. package/dist/database/database-orchestrator.js +730 -0
  20. package/dist/database/index.js +4 -0
  21. package/dist/deployment/auditor.js +971 -0
  22. package/dist/deployment/index.js +10 -0
  23. package/dist/deployment/rollback-manager.js +523 -0
  24. package/dist/deployment/testers/api-tester.js +80 -0
  25. package/dist/deployment/testers/auth-tester.js +129 -0
  26. package/dist/deployment/testers/core.js +217 -0
  27. package/dist/deployment/testers/database-tester.js +105 -0
  28. package/dist/deployment/testers/index.js +74 -0
  29. package/dist/deployment/testers/load-tester.js +120 -0
  30. package/dist/deployment/testers/performance-tester.js +105 -0
  31. package/dist/deployment/validator.js +558 -0
  32. package/dist/deployment/wrangler-deployer.js +574 -0
  33. package/dist/handlers/GenericRouteHandler.js +532 -0
  34. package/dist/index.js +39 -0
  35. package/dist/migration/MigrationAdapters.js +562 -0
  36. package/dist/modules/ModuleManager.js +668 -0
  37. package/dist/modules/security.js +98 -0
  38. package/dist/orchestration/cross-domain-coordinator.js +1083 -0
  39. package/dist/orchestration/index.js +5 -0
  40. package/dist/orchestration/modules/DeploymentCoordinator.js +258 -0
  41. package/dist/orchestration/modules/DomainResolver.js +196 -0
  42. package/dist/orchestration/modules/StateManager.js +332 -0
  43. package/dist/orchestration/multi-domain-orchestrator.js +255 -0
  44. package/dist/routing/EnhancedRouter.js +158 -0
  45. package/dist/schema/SchemaManager.js +778 -0
  46. package/dist/security/ConfigurationValidator.js +490 -0
  47. package/dist/security/DeploymentManager.js +208 -0
  48. package/dist/security/SecretGenerator.js +142 -0
  49. package/dist/security/SecurityCLI.js +228 -0
  50. package/dist/security/index.js +51 -0
  51. package/dist/security/patterns/environment-rules.js +66 -0
  52. package/dist/security/patterns/insecure-patterns.js +21 -0
  53. package/dist/service-management/ConfirmationEngine.js +411 -0
  54. package/dist/service-management/ErrorTracker.js +294 -0
  55. package/dist/service-management/GenerationEngine.js +3109 -0
  56. package/dist/service-management/InputCollector.js +237 -0
  57. package/dist/service-management/ServiceCreator.js +229 -0
  58. package/dist/service-management/ServiceInitializer.js +448 -0
  59. package/dist/service-management/ServiceOrchestrator.js +638 -0
  60. package/dist/service-management/handlers/ConfigMutator.js +130 -0
  61. package/dist/service-management/handlers/ConfirmationHandler.js +71 -0
  62. package/dist/service-management/handlers/GenerationHandler.js +80 -0
  63. package/dist/service-management/handlers/InputHandler.js +59 -0
  64. package/dist/service-management/handlers/ValidationHandler.js +203 -0
  65. package/dist/service-management/index.js +7 -0
  66. package/dist/services/GenericDataService.js +488 -0
  67. package/dist/shared/cloudflare/domain-discovery.js +562 -0
  68. package/dist/shared/cloudflare/domain-manager.js +912 -0
  69. package/dist/shared/cloudflare/index.js +8 -0
  70. package/dist/shared/cloudflare/ops.js +387 -0
  71. package/dist/shared/config/cache.js +1167 -0
  72. package/dist/shared/config/command-config-manager.js +174 -0
  73. package/dist/shared/config/customer-cli.js +258 -0
  74. package/dist/shared/config/index.js +9 -0
  75. package/dist/shared/config/manager.js +289 -0
  76. package/dist/shared/database/connection-manager.js +338 -0
  77. package/dist/shared/database/index.js +7 -0
  78. package/dist/shared/database/orchestrator.js +632 -0
  79. package/dist/shared/deployment/auditor.js +971 -0
  80. package/dist/shared/deployment/index.js +10 -0
  81. package/dist/shared/deployment/rollback-manager.js +523 -0
  82. package/dist/shared/deployment/validator.js +558 -0
  83. package/dist/shared/index.js +32 -0
  84. package/dist/shared/monitoring/health-checker.js +250 -0
  85. package/dist/shared/monitoring/index.js +8 -0
  86. package/dist/shared/monitoring/memory-manager.js +382 -0
  87. package/dist/shared/monitoring/production-monitor.js +390 -0
  88. package/dist/shared/production-tester/api-tester.js +80 -0
  89. package/dist/shared/production-tester/auth-tester.js +129 -0
  90. package/dist/shared/production-tester/core.js +217 -0
  91. package/dist/shared/production-tester/database-tester.js +105 -0
  92. package/dist/shared/production-tester/index.js +74 -0
  93. package/dist/shared/production-tester/load-tester.js +120 -0
  94. package/dist/shared/production-tester/performance-tester.js +105 -0
  95. package/dist/shared/security/api-token-manager.js +296 -0
  96. package/dist/shared/security/index.js +8 -0
  97. package/dist/shared/security/secret-generator.js +918 -0
  98. package/dist/shared/security/secure-token-manager.js +379 -0
  99. package/dist/shared/utils/error-recovery.js +240 -0
  100. package/dist/shared/utils/graceful-shutdown-manager.js +380 -0
  101. package/dist/shared/utils/index.js +9 -0
  102. package/dist/shared/utils/interactive-prompts.js +134 -0
  103. package/dist/shared/utils/rate-limiter.js +249 -0
  104. package/dist/utils/ErrorHandler.js +173 -0
  105. package/dist/utils/deployment/config-cache.js +1160 -0
  106. package/dist/utils/deployment/index.js +6 -0
  107. package/dist/utils/deployment/interactive-prompts.js +97 -0
  108. package/dist/utils/deployment/secret-generator.js +896 -0
  109. package/dist/utils/dirname-helper.js +35 -0
  110. package/dist/utils/domain-config.js +159 -0
  111. package/dist/utils/error-recovery.js +240 -0
  112. package/dist/utils/esm-helper.js +52 -0
  113. package/dist/utils/framework-config.js +481 -0
  114. package/dist/utils/graceful-shutdown-manager.js +379 -0
  115. package/dist/utils/health-checker.js +114 -0
  116. package/dist/utils/index.js +36 -0
  117. package/dist/utils/prompt-handler.js +98 -0
  118. package/dist/utils/usage-tracker.js +252 -0
  119. package/dist/utils/validation.js +112 -0
  120. package/dist/version/VersionDetector.js +723 -0
  121. package/dist/worker/index.js +4 -0
  122. package/dist/worker/integration.js +332 -0
  123. package/docs/FRAMEWORK-ARCHITECTURE-OVERVIEW.md +206 -0
  124. package/docs/INTEGRATION_GUIDE.md +2045 -0
  125. package/docs/README.md +82 -0
  126. package/docs/SECURITY.md +242 -0
  127. package/docs/deployment/deployment-guide.md +540 -0
  128. package/docs/overview.md +280 -0
  129. package/package.json +176 -0
  130. package/types/index.d.ts +575 -0
@@ -0,0 +1,488 @@
1
+ import { schemaManager } from '../schema/SchemaManager.js';
2
+
3
+ /**
4
+ * Generic Data Service
5
+ * Provides CRUD operations for any configured data model
6
+ */
7
+ export class GenericDataService {
8
+ /**
9
+ * Create a new GenericDataService instance
10
+ * @param {Object} d1Client - D1 database client
11
+ * @param {string} modelName - Name of the model to work with
12
+ * @param {Object} options - Configuration options
13
+ */
14
+ constructor(d1Client, modelName, options = {}) {
15
+ this.d1Client = d1Client;
16
+ this.modelName = modelName;
17
+ this.schema = schemaManager.getModel(modelName);
18
+ if (!this.schema) {
19
+ throw new Error(`Model '${modelName}' not registered. Use schemaManager.registerModel() first.`);
20
+ }
21
+
22
+ // Query result caching
23
+ this.queryCache = new Map();
24
+ this.cacheEnabled = options.cacheEnabled !== false;
25
+ this.defaultCacheTTL = options.defaultCacheTTL || 300; // 5 minutes default
26
+
27
+ // Security configuration
28
+ this.securityConfig = {
29
+ maxQueryLimit: options.maxQueryLimit || 1000,
30
+ // Maximum records per query
31
+ defaultQueryLimit: options.defaultQueryLimit || 100,
32
+ // Default records per query
33
+ maxBulkOperationSize: options.maxBulkOperationSize || 100,
34
+ // Maximum records in bulk operations
35
+ enablePagination: options.enablePagination !== false,
36
+ // Enable pagination by default
37
+ ...options.securityConfig
38
+ };
39
+ }
40
+
41
+ /**
42
+ * Generate cache key for query
43
+ * @param {string} operation - Operation type
44
+ * @param {Object} params - Query parameters
45
+ * @returns {string} Cache key
46
+ */
47
+ generateCacheKey(operation, params = {}) {
48
+ return `${this.modelName}:${operation}:${JSON.stringify(params)}`;
49
+ }
50
+
51
+ /**
52
+ * Get cached result if valid
53
+ * @param {string} cacheKey - Cache key
54
+ * @returns {any|null} Cached result or null if expired/not found
55
+ */
56
+ getCachedResult(cacheKey) {
57
+ if (!this.cacheEnabled) return null;
58
+ const cached = this.queryCache.get(cacheKey);
59
+ if (!cached) return null;
60
+
61
+ // Check if expired
62
+ if (Date.now() > cached.expiresAt) {
63
+ this.queryCache.delete(cacheKey);
64
+ return null;
65
+ }
66
+ return cached.data;
67
+ }
68
+
69
+ /**
70
+ * Cache query result
71
+ * @param {string} cacheKey - Cache key
72
+ * @param {any} data - Data to cache
73
+ * @param {number} ttl - Time to live in seconds
74
+ */
75
+ setCachedResult(cacheKey, data, ttl = null) {
76
+ if (!this.cacheEnabled) return;
77
+ const expiresAt = Date.now() + (ttl || this.defaultCacheTTL) * 1000;
78
+ this.queryCache.set(cacheKey, {
79
+ data,
80
+ expiresAt,
81
+ createdAt: Date.now()
82
+ });
83
+ }
84
+
85
+ /**
86
+ * Clear cache for specific operations or all cache
87
+ * @param {string} operation - Optional: specific operation to clear
88
+ * @param {Object} params - Optional: specific parameters to clear
89
+ */
90
+ clearCache(operation = null, params = null) {
91
+ if (operation && params) {
92
+ // Clear specific cache entry
93
+ const cacheKey = this.generateCacheKey(operation, params);
94
+ this.queryCache.delete(cacheKey);
95
+ } else if (operation) {
96
+ // Clear all cache entries for an operation
97
+ for (const [key] of this.queryCache) {
98
+ if (key.startsWith(`${this.modelName}:${operation}:`)) {
99
+ this.queryCache.delete(key);
100
+ }
101
+ }
102
+ } else {
103
+ // Clear all cache
104
+ this.queryCache.clear();
105
+ }
106
+ }
107
+
108
+ /**
109
+ * Format validation errors into a human-readable message
110
+ * @param {Array} errors - Validation errors array
111
+ * @returns {string} Formatted error message
112
+ */
113
+ formatValidationErrors(errors = []) {
114
+ if (!Array.isArray(errors) || errors.length === 0) {
115
+ return 'Unknown validation error';
116
+ }
117
+ const details = errors.map(error => {
118
+ if (!error) {
119
+ return null;
120
+ }
121
+ if (typeof error === 'string') {
122
+ return error;
123
+ }
124
+ if (Array.isArray(error)) {
125
+ return error.map(item => this.formatValidationErrors([item])).join('; ');
126
+ }
127
+ if (typeof error === 'object') {
128
+ const field = error.field || error.path || error.name || 'field';
129
+ if (error.message) {
130
+ return `${field}: ${error.message}`;
131
+ }
132
+ if (error.reason) {
133
+ return `${field}: ${error.reason}`;
134
+ }
135
+ if (error.code) {
136
+ return `${field}: ${error.code}`;
137
+ }
138
+ try {
139
+ return `${field}: ${JSON.stringify(error)}`;
140
+ } catch {
141
+ return `${field}: ${String(error)}`;
142
+ }
143
+ }
144
+ return String(error);
145
+ }).filter(Boolean);
146
+ return details.length > 0 ? details.join('; ') : 'Unknown validation error';
147
+ }
148
+
149
+ /**
150
+ * Create a new record
151
+ * @param {Object} data - Record data
152
+ * @returns {Promise<Object>} Created record
153
+ */
154
+ async create(data) {
155
+ // Validate data
156
+ const validation = schemaManager.validateData(this.modelName, data);
157
+ if (!validation.valid) {
158
+ const errorMessage = this.formatValidationErrors(validation.errors);
159
+ throw new Error(`Validation failed: ${errorMessage}`);
160
+ }
161
+
162
+ // Generate ID if not provided
163
+ const recordData = {
164
+ ...validation.data
165
+ };
166
+ if (!recordData.id) {
167
+ recordData.id = this.d1Client.generateId();
168
+ }
169
+
170
+ // Set timestamps
171
+ const now = this.d1Client.getCurrentTimestamp();
172
+ if (this.schema.columns.created_at && !recordData.created_at) {
173
+ recordData.created_at = now;
174
+ }
175
+ if (this.schema.columns.updated_at && !recordData.updated_at) {
176
+ recordData.updated_at = now;
177
+ }
178
+
179
+ // Generate SQL
180
+ const {
181
+ sql,
182
+ params
183
+ } = schemaManager.generateSQL(this.modelName, 'create', recordData);
184
+
185
+ // Execute
186
+ const result = await this.d1Client.run(sql, params);
187
+ if (result.success) {
188
+ // Clear relevant caches after successful creation
189
+ this.clearCache('findAll');
190
+ this.clearCache('find');
191
+ return {
192
+ ...recordData,
193
+ id: recordData.id
194
+ };
195
+ }
196
+ throw new Error('Failed to create record');
197
+ }
198
+
199
+ /**
200
+ * Find records by criteria with advanced options
201
+ * @param {Object} criteria - Search criteria
202
+ * @param {Array} include - Relationships to include
203
+ * @param {Array} fields - Fields to select
204
+ * @returns {Promise<Array>} Found records
205
+ */
206
+ async find(criteria = {}, include = [], fields = null) {
207
+ const cacheKey = this.generateCacheKey('find', {
208
+ criteria,
209
+ include,
210
+ fields
211
+ });
212
+ const cached = this.getCachedResult(cacheKey);
213
+ if (cached !== null) {
214
+ return cached;
215
+ }
216
+ let result;
217
+ if (include.length > 0) {
218
+ result = await this.findWithRelations(criteria, include, fields);
219
+ } else {
220
+ const {
221
+ sql,
222
+ params
223
+ } = schemaManager.generateSQL(this.modelName, 'read', {
224
+ where: criteria,
225
+ fields
226
+ });
227
+ result = await this.d1Client.all(sql, params);
228
+ }
229
+
230
+ // Cache the result
231
+ this.setCachedResult(cacheKey, result);
232
+ return result;
233
+ }
234
+
235
+ /**
236
+ * Find all records with pagination and security limits
237
+ * @param {Object} options - Query options
238
+ * @param {number} options.limit - Maximum records to return (default: configured default, max: configured max)
239
+ * @param {number} options.offset - Number of records to skip (default: 0)
240
+ * @param {Object} options.orderBy - Sort options {field: 'asc'|'desc'}
241
+ * @param {Object} options.where - Filter criteria
242
+ * @returns {Promise<Object>} Paginated result with data, total, limit, offset
243
+ */
244
+ async findAll(options = {}) {
245
+ // Apply security limits
246
+ const requestedLimit = options.limit !== undefined ? options.limit : this.securityConfig.defaultQueryLimit;
247
+
248
+ // Validate limit before applying security constraints
249
+ if (requestedLimit <= 0) {
250
+ throw new Error(`Invalid limit: ${requestedLimit}. Must be positive.`);
251
+ }
252
+ const limit = Math.min(requestedLimit, this.securityConfig.maxQueryLimit);
253
+ const offset = Math.max(0, options.offset || 0);
254
+
255
+ // Prevent excessive offset (basic protection against very large offsets)
256
+ if (offset > 1000000) {
257
+ throw new Error(`Offset too large: ${offset}. Maximum allowed offset is 1,000,000.`);
258
+ }
259
+ const queryOptions = {
260
+ limit,
261
+ offset,
262
+ orderBy: options.orderBy,
263
+ where: options.where || {}
264
+ };
265
+ const cacheKey = this.generateCacheKey('findAll', queryOptions);
266
+ const cached = this.getCachedResult(cacheKey);
267
+ if (cached !== null) {
268
+ return cached;
269
+ }
270
+
271
+ // Build query with pagination
272
+ let sql = `SELECT * FROM ${this.schema.tableName}`;
273
+ let params = [];
274
+
275
+ // Add WHERE clause if provided
276
+ if (options.where && Object.keys(options.where).length > 0) {
277
+ const conditions = [];
278
+ Object.entries(options.where).forEach(([key, value]) => {
279
+ conditions.push(`${key} = ?`);
280
+ params.push(value);
281
+ });
282
+ sql += ` WHERE ${conditions.join(' AND ')}`;
283
+ }
284
+
285
+ // Add ORDER BY if provided
286
+ if (options.orderBy && Object.keys(options.orderBy).length > 0) {
287
+ const orderClauses = [];
288
+ Object.entries(options.orderBy).forEach(([field, direction]) => {
289
+ orderClauses.push(`${field} ${direction.toUpperCase()}`);
290
+ });
291
+ sql += ` ORDER BY ${orderClauses.join(', ')}`;
292
+ }
293
+
294
+ // Add LIMIT and OFFSET
295
+ sql += ` LIMIT ? OFFSET ?`;
296
+ params.push(limit, offset);
297
+
298
+ // Execute the query
299
+ const data = await this.d1Client.all(sql, params);
300
+
301
+ // Get total count for pagination (without LIMIT/OFFSET)
302
+ let countSql = `SELECT COUNT(*) as total FROM ${this.schema.tableName}`;
303
+ let countParams = [];
304
+ if (options.where && Object.keys(options.where).length > 0) {
305
+ const conditions = [];
306
+ Object.entries(options.where).forEach(([key, value]) => {
307
+ conditions.push(`${key} = ?`);
308
+ countParams.push(value);
309
+ });
310
+ countSql += ` WHERE ${conditions.join(' AND ')}`;
311
+ }
312
+ const countResult = await this.d1Client.first(countSql, countParams);
313
+ const total = countResult ? countResult.total : 0;
314
+ const result = {
315
+ data,
316
+ pagination: {
317
+ total,
318
+ limit,
319
+ offset,
320
+ hasNext: offset + limit < total,
321
+ hasPrev: offset > 0,
322
+ totalPages: Math.ceil(total / limit),
323
+ currentPage: Math.floor(offset / limit) + 1
324
+ }
325
+ };
326
+
327
+ // Cache the result
328
+ this.setCachedResult(cacheKey, result);
329
+ return result;
330
+ }
331
+
332
+ /**
333
+ * Update a record
334
+ * @param {string} id - Record ID
335
+ * @param {Object} updates - Fields to update
336
+ * @returns {Promise<Object>} Updated record
337
+ */
338
+ async update(id, updates) {
339
+ // Validate updates
340
+ const validation = schemaManager.validateData(this.modelName, updates);
341
+ if (!validation.valid) {
342
+ const errorMessage = this.formatValidationErrors(validation.errors);
343
+ throw new Error(`Validation failed: ${errorMessage}`);
344
+ }
345
+
346
+ // Set updated timestamp
347
+ const updateData = {
348
+ ...validation.data,
349
+ id
350
+ };
351
+ if (this.schema.columns.updated_at) {
352
+ updateData.updated_at = this.d1Client.getCurrentTimestamp();
353
+ }
354
+
355
+ // Generate SQL
356
+ const {
357
+ sql,
358
+ params
359
+ } = schemaManager.generateSQL(this.modelName, 'update', updateData);
360
+
361
+ // Execute
362
+ const result = await this.d1Client.run(sql, params);
363
+ if (result.success) {
364
+ // Return updated record
365
+ return await this.findById(id);
366
+ } else {
367
+ throw new Error('Failed to update record');
368
+ }
369
+ }
370
+
371
+ /**
372
+ * Delete a record
373
+ * @param {string} id - Record ID
374
+ * @returns {Promise<boolean>} Success status
375
+ */
376
+ async delete(id) {
377
+ const {
378
+ sql,
379
+ params
380
+ } = schemaManager.generateSQL(this.modelName, 'delete', {
381
+ id
382
+ });
383
+ const result = await this.d1Client.run(sql, params);
384
+ return result.success;
385
+ }
386
+
387
+ /**
388
+ * Count records matching criteria
389
+ * @param {Object} criteria - Count criteria
390
+ * @returns {Promise<number>} Record count
391
+ */
392
+ async count(criteria = {}) {
393
+ let sql = `SELECT COUNT(*) as count FROM ${this.schema.tableName}`;
394
+ let params = [];
395
+ if (Object.keys(criteria).length > 0) {
396
+ const conditions = [];
397
+ Object.entries(criteria).forEach(([key, value]) => {
398
+ conditions.push(`${key} = ?`);
399
+ params.push(value);
400
+ });
401
+ sql += ` WHERE ${conditions.join(' AND ')}`;
402
+ }
403
+ const result = await this.d1Client.first(sql, params);
404
+ return result?.count || 0;
405
+ }
406
+
407
+ /**
408
+ * Check if record exists
409
+ * @param {string} id - Record ID
410
+ * @returns {Promise<boolean>} Existence status
411
+ */
412
+ async exists(id) {
413
+ const record = await this.findById(id);
414
+ return !!record;
415
+ }
416
+
417
+ /**
418
+ * Get paginated results
419
+ * @param {Object} criteria - Search criteria
420
+ * @param {Object} pagination - Pagination options
421
+ * @returns {Promise<Object>} Paginated results
422
+ */
423
+ async paginate(criteria = {}, pagination = {}) {
424
+ const {
425
+ page = 1,
426
+ limit = 10
427
+ } = pagination;
428
+ const offset = (page - 1) * limit;
429
+
430
+ // Get total count
431
+ const total = await this.count(criteria);
432
+
433
+ // Get paginated results
434
+ let sql = `SELECT * FROM ${this.schema.tableName}`;
435
+ let params = [];
436
+ if (Object.keys(criteria).length > 0) {
437
+ const conditions = [];
438
+ Object.entries(criteria).forEach(([key, value]) => {
439
+ conditions.push(`${key} = ?`);
440
+ params.push(value);
441
+ });
442
+ sql += ` WHERE ${conditions.join(' AND ')}`;
443
+ }
444
+ sql += ` LIMIT ? OFFSET ?`;
445
+ params.push(limit, offset);
446
+ const records = await this.d1Client.all(sql, params);
447
+ return {
448
+ data: records,
449
+ pagination: {
450
+ page,
451
+ limit,
452
+ total,
453
+ totalPages: Math.ceil(total / limit),
454
+ hasNext: page * limit < total,
455
+ hasPrev: page > 1
456
+ }
457
+ };
458
+ }
459
+ }
460
+
461
+ /**
462
+ * Factory function to create a data service for a model
463
+ * @param {Object} d1Client - D1 database client
464
+ * @param {string} modelName - Name of the model
465
+ * @returns {GenericDataService} Data service instance
466
+ */
467
+ /**
468
+ * Factory function to create a data service for a model
469
+ * @param {Object} d1Client - D1 database client
470
+ * @param {string} modelName - Name of the model
471
+ * @returns {GenericDataService} Data service instance
472
+ */
473
+ export function createDataService(d1Client, modelName) {
474
+ return new GenericDataService(d1Client, modelName);
475
+ }
476
+
477
+ /**
478
+ * Get all available data services
479
+ * @returns {Object} Map of model names to service instances
480
+ */
481
+ export function getAllDataServices() {
482
+ const services = {};
483
+ // Note: This would require schemaManager to have getAllModels method
484
+ // for (const [modelName] of schemaManager.getAllModels()) {
485
+ // services[modelName] = new GenericDataService(d1Client, modelName);
486
+ // }
487
+ return services;
488
+ }