@zintrust/core 0.1.21 → 0.1.23
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/bin/z.d.ts +1 -1
- package/bin/z.js +1 -1
- package/bin/zin.d.ts +1 -1
- package/bin/zin.js +1 -1
- package/bin/zintrust-main.d.ts +1 -1
- package/bin/zintrust-main.js +2 -2
- package/bin/zintrust-microservices.d.ts +1 -1
- package/bin/zintrust-microservices.js +1 -1
- package/bin/zintrust.d.ts +1 -1
- package/bin/zintrust.js +1 -1
- package/bin/zt.d.ts +1 -1
- package/bin/zt.js +1 -1
- package/package.json +2 -3
- package/public/index.html +3 -3
- package/routes/api.js +1 -1
- package/routes/health.d.ts +3 -4
- package/routes/health.d.ts.map +1 -1
- package/routes/health.js +3 -125
- package/src/boot/Application.d.ts.map +1 -1
- package/src/boot/Application.js +11 -22
- package/src/boot/bootstrap.d.ts +1 -1
- package/src/boot/bootstrap.js +48 -7
- package/src/builder/BundleOptimizer.d.ts +1 -1
- package/src/builder/BundleOptimizer.js +1 -1
- package/src/cache/drivers/KVRemoteDriver.d.ts +1 -1
- package/src/cache/drivers/KVRemoteDriver.js +1 -1
- package/src/cli/CLI.d.ts.map +1 -1
- package/src/cli/CLI.js +15 -1
- package/src/cli/ErrorHandler.js +3 -3
- package/src/cli/commands/AddCommand.d.ts +1 -1
- package/src/cli/commands/AddCommand.d.ts.map +1 -1
- package/src/cli/commands/AddCommand.js +1 -1
- package/src/cli/commands/DbSeedCommand.js +1 -1
- package/src/cli/commands/MakeMailTemplateCommand.js +2 -1
- package/src/cli/commands/MakeNotificationTemplateCommand.js +2 -1
- package/src/cli/commands/MigrateCommand.d.ts.map +1 -1
- package/src/cli/commands/MigrateCommand.js +1 -1
- package/src/cli/commands/MigrateWorkerCommand.d.ts +9 -0
- package/src/cli/commands/MigrateWorkerCommand.d.ts.map +1 -0
- package/src/cli/commands/MigrateWorkerCommand.js +182 -0
- package/src/cli/commands/NewCommand.d.ts +1 -1
- package/src/cli/commands/NewCommand.d.ts.map +1 -1
- package/src/cli/commands/NewCommand.js +21 -7
- package/src/cli/commands/PublishCommand.d.ts +5 -0
- package/src/cli/commands/PublishCommand.d.ts.map +1 -0
- package/src/cli/commands/PublishCommand.js +54 -0
- package/src/cli/commands/QACommand.js +4 -4
- package/src/cli/commands/ResourceControlCommand.d.ts +6 -0
- package/src/cli/commands/ResourceControlCommand.d.ts.map +1 -0
- package/src/cli/commands/ResourceControlCommand.js +43 -0
- package/src/cli/commands/SimulateCommand.d.ts +1 -1
- package/src/cli/commands/SimulateCommand.js +4 -4
- package/src/cli/commands/StartCommand.d.ts.map +1 -1
- package/src/cli/commands/StartCommand.js +19 -7
- package/src/cli/commands/UpgradeCommand.d.ts +1 -1
- package/src/cli/commands/UpgradeCommand.js +2 -2
- package/src/cli/commands/WorkerCommands.d.ts +17 -0
- package/src/cli/commands/WorkerCommands.d.ts.map +1 -0
- package/src/cli/commands/WorkerCommands.js +264 -0
- package/src/cli/commands/index.d.ts +2 -0
- package/src/cli/commands/index.d.ts.map +1 -1
- package/src/cli/commands/index.js +2 -0
- package/src/cli/config/ConfigSchema.d.ts +1 -1
- package/src/cli/config/ConfigSchema.d.ts.map +1 -1
- package/src/cli/config/ConfigSchema.js +4 -3
- package/src/cli/d1/D1SqlMigrations.d.ts.map +1 -1
- package/src/cli/d1/D1SqlMigrations.js +4 -3
- package/src/cli/scaffolding/ModelGenerator.d.ts +1 -1
- package/src/cli/scaffolding/ModelGenerator.d.ts.map +1 -1
- package/src/cli/scaffolding/ModelGenerator.js +10 -2
- package/src/cli/scaffolding/ProjectScaffolder.js +5 -5
- package/src/cli/scaffolding/RouteGenerator.d.ts.map +1 -1
- package/src/cli/scaffolding/RouteGenerator.js +21 -2
- package/src/cli/scaffolding/TemplateEngine.js +1 -1
- package/src/cli/utils/EnvFileLoader.d.ts.map +1 -1
- package/src/common/ExternalServiceUtils.d.ts +63 -0
- package/src/common/ExternalServiceUtils.d.ts.map +1 -0
- package/src/common/ExternalServiceUtils.js +116 -0
- package/src/common/HealthRoutes.d.ts +10 -0
- package/src/common/HealthRoutes.d.ts.map +1 -0
- package/src/common/HealthRoutes.js +114 -0
- package/src/config/SecretsManager.d.ts.map +1 -1
- package/src/config/SecretsManager.js +2 -1
- package/src/config/app.d.ts +2 -1
- package/src/config/app.d.ts.map +1 -1
- package/src/config/app.js +98 -52
- package/src/config/broadcast.d.ts.map +1 -1
- package/src/config/broadcast.js +2 -2
- package/src/config/cache.d.ts.map +1 -1
- package/src/config/cache.js +2 -2
- package/src/config/database.d.ts.map +1 -1
- package/src/config/database.js +24 -5
- package/src/config/env.d.ts +43 -1
- package/src/config/env.d.ts.map +1 -1
- package/src/config/env.js +68 -21
- package/src/config/index.d.ts +10 -1
- package/src/config/index.d.ts.map +1 -1
- package/src/config/index.js +1 -0
- package/src/config/mail.d.ts.map +1 -1
- package/src/config/mail.js +3 -3
- package/src/config/middleware.d.ts.map +1 -1
- package/src/config/middleware.js +1 -1
- package/src/config/notification.d.ts.map +1 -1
- package/src/config/notification.js +2 -2
- package/src/config/queue.d.ts +14 -0
- package/src/config/queue.d.ts.map +1 -1
- package/src/config/queue.js +61 -36
- package/src/config/security.js +2 -2
- package/src/config/storage.d.ts.map +1 -1
- package/src/config/storage.js +5 -5
- package/src/config/type.d.ts +122 -0
- package/src/config/type.d.ts.map +1 -1
- package/src/config/type.js +10 -1
- package/src/config/workers.d.ts +13 -0
- package/src/config/workers.d.ts.map +1 -0
- package/src/config/workers.js +173 -0
- package/src/database/Paginator.d.ts +37 -0
- package/src/database/Paginator.d.ts.map +1 -0
- package/src/database/Paginator.js +81 -0
- package/src/exceptions/ZintrustError.d.ts +5 -2
- package/src/exceptions/ZintrustError.d.ts.map +1 -1
- package/src/exceptions/ZintrustError.js +6 -2
- package/src/features/Auth.d.ts +1 -1
- package/src/features/Auth.d.ts.map +1 -1
- package/src/features/Auth.js +3 -2
- package/src/features/Queue.d.ts.map +1 -1
- package/src/features/Queue.js +0 -2
- package/src/index.d.ts +15 -5
- package/src/index.d.ts.map +1 -1
- package/src/index.js +24 -3
- package/src/microservices/MicroserviceBootstrap.d.ts.map +1 -1
- package/src/microservices/MicroserviceBootstrap.js +3 -1
- package/src/microservices/MicroserviceGenerator.js +4 -4
- package/src/microservices/MicroserviceManager.d.ts +1 -1
- package/src/microservices/MicroserviceManager.js +1 -1
- package/src/middleware/RateLimiter.d.ts.map +1 -1
- package/src/middleware/RateLimiter.js +4 -3
- package/src/migrations/MigrationLoader.d.ts +1 -1
- package/src/migrations/MigrationLoader.d.ts.map +1 -1
- package/src/migrations/Migrator.d.ts +3 -3
- package/src/migrations/Migrator.d.ts.map +1 -1
- package/src/migrations/Migrator.js +1 -1
- package/src/migrations/MigratorFactory.d.ts +1 -1
- package/src/migrations/MigratorFactory.d.ts.map +1 -1
- package/src/migrations/MigratorFactory.js +3 -3
- package/src/migrations/enum/index.d.ts +93 -0
- package/src/migrations/enum/index.d.ts.map +1 -0
- package/src/migrations/enum/index.js +92 -0
- package/src/migrations/schema/Blueprint.d.ts +1 -1
- package/src/migrations/schema/Blueprint.d.ts.map +1 -1
- package/src/migrations/schema/Blueprint.js +27 -25
- package/src/migrations/schema/Schema.d.ts +1 -1
- package/src/migrations/schema/Schema.d.ts.map +1 -1
- package/src/migrations/schema/Schema.js +4 -3
- package/src/migrations/schema/SchemaCompiler.d.ts +1 -1
- package/src/migrations/schema/SchemaCompiler.d.ts.map +1 -1
- package/src/migrations/schema/SchemaCompiler.js +99 -91
- package/src/migrations/schema/index.d.ts +4 -4
- package/src/migrations/schema/index.d.ts.map +1 -1
- package/src/migrations/schema/index.js +3 -3
- package/src/migrations/schema/types.d.ts +2 -1
- package/src/migrations/schema/types.d.ts.map +1 -1
- package/src/node-singletons/crypto.d.ts +1 -1
- package/src/node-singletons/crypto.d.ts.map +1 -1
- package/src/node-singletons/crypto.js +1 -1
- package/src/node-singletons/os.d.ts +10 -1
- package/src/node-singletons/os.d.ts.map +1 -1
- package/src/node-singletons/os.js +10 -1
- package/src/openapi/OpenApiGenerator.js +2 -2
- package/src/orm/ConnectionManager.d.ts +7 -5
- package/src/orm/ConnectionManager.d.ts.map +1 -1
- package/src/orm/ConnectionManager.js +249 -93
- package/src/orm/Database.d.ts +2 -1
- package/src/orm/Database.d.ts.map +1 -1
- package/src/orm/DatabaseAdapter.d.ts +3 -2
- package/src/orm/DatabaseAdapter.d.ts.map +1 -1
- package/src/orm/DatabaseAdapter.js +17 -0
- package/src/orm/Model.d.ts +8 -1
- package/src/orm/Model.d.ts.map +1 -1
- package/src/orm/Model.js +109 -26
- package/src/orm/QueryBuilder.d.ts +12 -2
- package/src/orm/QueryBuilder.d.ts.map +1 -1
- package/src/orm/QueryBuilder.js +438 -38
- package/src/orm/Relationships.d.ts +61 -1
- package/src/orm/Relationships.d.ts.map +1 -1
- package/src/orm/Relationships.js +190 -0
- package/src/orm/adapters/D1Adapter.d.ts.map +1 -1
- package/src/orm/adapters/D1Adapter.js +2 -1
- package/src/orm/adapters/D1RemoteAdapter.d.ts +1 -1
- package/src/orm/adapters/D1RemoteAdapter.d.ts.map +1 -1
- package/src/orm/adapters/D1RemoteAdapter.js +3 -2
- package/src/orm/adapters/MySQLAdapter.d.ts.map +1 -1
- package/src/orm/adapters/MySQLAdapter.js +2 -1
- package/src/orm/adapters/SQLServerAdapter.d.ts.map +1 -1
- package/src/orm/adapters/SQLServerAdapter.js +2 -1
- package/src/orm/adapters/SQLiteAdapter.d.ts.map +1 -1
- package/src/orm/adapters/SQLiteAdapter.js +2 -1
- package/src/orm/migrations/MigrationStore.d.ts.map +1 -1
- package/src/performance/Optimizer.d.ts.map +1 -1
- package/src/performance/Optimizer.js +57 -18
- package/src/profiling/RequestProfiler.d.ts.map +1 -1
- package/src/profiling/RequestProfiler.js +3 -1
- package/src/routing/CoreRoutes.d.ts +1 -1
- package/src/routing/CoreRoutes.d.ts.map +1 -1
- package/src/routing/CoreRoutes.js +2 -116
- package/src/routing/error.d.ts.map +1 -1
- package/src/routing/error.js +3 -2
- package/src/routing/publicRoot.d.ts.map +1 -1
- package/src/routing/publicRoot.js +4 -2
- package/src/runtime/PluginAutoImports.d.ts.map +1 -1
- package/src/runtime/PluginAutoImports.js +20 -4
- package/src/runtime/PluginManager.d.ts.map +1 -1
- package/src/runtime/PluginManager.js +23 -6
- package/src/runtime/RuntimeAdapter.d.ts +3 -3
- package/src/runtime/RuntimeAdapter.d.ts.map +1 -1
- package/src/runtime/StartupConfigFileRegistry.d.ts +15 -13
- package/src/runtime/StartupConfigFileRegistry.d.ts.map +1 -1
- package/src/runtime/StartupConfigFileRegistry.js +12 -12
- package/src/runtime/adapters/CloudflareAdapter.d.ts.map +1 -1
- package/src/runtime/adapters/CloudflareAdapter.js +1 -1
- package/src/runtime/adapters/DenoAdapter.d.ts.map +1 -1
- package/src/runtime/adapters/DenoAdapter.js +1 -1
- package/src/runtime/adapters/FargateAdapter.d.ts +2 -2
- package/src/runtime/adapters/FargateAdapter.d.ts.map +1 -1
- package/src/runtime/adapters/FargateAdapter.js +1 -1
- package/src/runtime/adapters/LambdaAdapter.d.ts +1 -1
- package/src/runtime/adapters/LambdaAdapter.d.ts.map +1 -1
- package/src/runtime/adapters/LambdaAdapter.js +6 -4
- package/src/runtime/adapters/NodeServerAdapter.js +1 -1
- package/src/scripts/GenerateEnvArtifacts.js +1 -1
- package/src/security/SignedRequest.js +1 -1
- package/src/security/StartupSecretValidation.d.ts.map +1 -1
- package/src/security/StartupSecretValidation.js +7 -1
- package/src/start.d.ts.map +1 -1
- package/src/start.js +0 -2
- package/src/templates/features/Auth.ts.tpl +4 -4
- package/src/templates/project/basic/README.md.tpl +1 -1
- package/src/templates/project/basic/app/Middleware/index.ts.tpl +1 -1
- package/src/templates/project/basic/config/notification.ts.tpl +1 -1
- package/src/templates/project/basic/routes/api.ts.tpl +1 -3
- package/src/templates/project/basic/src/index.ts.tpl +1 -1
- package/src/templates/project/basic/src/zintrust.plugins.ts.tpl +1 -1
- package/src/templates/project/basic/template.json +1 -1
- package/src/toolkit/Secrets/index.d.ts.map +1 -1
- package/src/toolkit/Secrets/index.js +13 -9
- package/src/toolkit/Secrets/providers/AwsSecretsManager.d.ts.map +1 -1
- package/src/toolkit/Secrets/providers/AwsSecretsManager.js +20 -7
- package/src/toolkit/Secrets/providers/CloudflareKv.d.ts.map +1 -1
- package/src/toolkit/Secrets/providers/CloudflareKv.js +19 -6
- package/src/tools/http/Http.js +1 -1
- package/src/tools/mail/drivers/Ses.d.ts.map +1 -1
- package/src/tools/mail/drivers/Ses.js +5 -4
- package/src/tools/mail/templates/index.js +2 -2
- package/src/tools/notification/drivers/Termii.d.ts.map +1 -1
- package/src/tools/notification/drivers/Termii.js +6 -17
- package/src/tools/notification/testingHelpers.d.ts.map +1 -1
- package/src/tools/queue/Queue.d.ts.map +1 -1
- package/src/tools/queue/Queue.js +3 -5
- package/src/tools/queue/drivers/Redis.d.ts.map +1 -1
- package/src/tools/queue/drivers/Redis.js +7 -1
- package/src/tools/storage/drivers/S3.d.ts.map +1 -1
- package/src/tools/storage/drivers/S3.js +16 -3
- package/src/routes/health.d.ts +0 -2
- package/src/routes/health.d.ts.map +0 -1
- package/src/routes/health.js +0 -1
- package/src/runtime/RuntimeDetector.d.ts +0 -15
- package/src/runtime/RuntimeDetector.d.ts.map +0 -1
- package/src/runtime/RuntimeDetector.js +0 -271
- package/src/templates/project/basic/routes/health.ts.tpl +0 -143
- package/src/templates/project/basic/routes/metrics.ts.tpl +0 -22
- package/src/workers/BroadcastWorker.d.ts +0 -22
- package/src/workers/BroadcastWorker.d.ts.map +0 -1
- package/src/workers/BroadcastWorker.js +0 -24
- package/src/workers/NotificationWorker.d.ts +0 -22
- package/src/workers/NotificationWorker.d.ts.map +0 -1
- package/src/workers/NotificationWorker.js +0 -23
- package/src/workers/createQueueWorker.d.ts +0 -24
- package/src/workers/createQueueWorker.d.ts.map +0 -1
- package/src/workers/createQueueWorker.js +0 -114
package/src/orm/Relationships.js
CHANGED
|
@@ -114,3 +114,193 @@ export const BelongsToMany = Object.freeze({
|
|
|
114
114
|
};
|
|
115
115
|
},
|
|
116
116
|
});
|
|
117
|
+
/**
|
|
118
|
+
* MorphOne Relationship
|
|
119
|
+
* Polymorphic one-to-one relationship
|
|
120
|
+
* Sealed namespace object following Pattern 2
|
|
121
|
+
*
|
|
122
|
+
* @see FRAMEWORK_REFACTOR_FUNCTION_PATTERN.md for Pattern 2 details
|
|
123
|
+
*/
|
|
124
|
+
export const MorphOne = Object.freeze({
|
|
125
|
+
create(relatedModel, morphName, morphType, morphId, localKeyColumn = 'id') {
|
|
126
|
+
const morphTypeColumn = morphType ?? `${morphName}_type`;
|
|
127
|
+
const morphIdColumn = morphId ?? `${morphName}_id`;
|
|
128
|
+
return {
|
|
129
|
+
type: 'morphOne',
|
|
130
|
+
related: relatedModel,
|
|
131
|
+
foreignKey: morphIdColumn,
|
|
132
|
+
localKey: localKeyColumn,
|
|
133
|
+
morphType: morphTypeColumn,
|
|
134
|
+
morphId: morphIdColumn,
|
|
135
|
+
morphName,
|
|
136
|
+
async get(instance) {
|
|
137
|
+
const value = instance.getAttribute(localKeyColumn);
|
|
138
|
+
if (value === undefined || value === null || value === '')
|
|
139
|
+
return null;
|
|
140
|
+
const modelName = instance.getTable();
|
|
141
|
+
return relatedModel
|
|
142
|
+
.query()
|
|
143
|
+
.where(morphTypeColumn, '=', modelName)
|
|
144
|
+
.where(morphIdColumn, '=', value)
|
|
145
|
+
.first();
|
|
146
|
+
},
|
|
147
|
+
};
|
|
148
|
+
},
|
|
149
|
+
});
|
|
150
|
+
/**
|
|
151
|
+
* MorphMany Relationship
|
|
152
|
+
* Polymorphic one-to-many relationship
|
|
153
|
+
* Sealed namespace object following Pattern 2
|
|
154
|
+
*
|
|
155
|
+
* @see FRAMEWORK_REFACTOR_FUNCTION_PATTERN.md for Pattern 2 details
|
|
156
|
+
*/
|
|
157
|
+
export const MorphMany = Object.freeze({
|
|
158
|
+
create(relatedModel, morphName, morphType, morphId, localKeyColumn = 'id') {
|
|
159
|
+
const morphTypeColumn = morphType ?? `${morphName}_type`;
|
|
160
|
+
const morphIdColumn = morphId ?? `${morphName}_id`;
|
|
161
|
+
return {
|
|
162
|
+
type: 'morphMany',
|
|
163
|
+
related: relatedModel,
|
|
164
|
+
foreignKey: morphIdColumn,
|
|
165
|
+
localKey: localKeyColumn,
|
|
166
|
+
morphType: morphTypeColumn,
|
|
167
|
+
morphId: morphIdColumn,
|
|
168
|
+
morphName,
|
|
169
|
+
async get(instance) {
|
|
170
|
+
const value = instance.getAttribute(localKeyColumn);
|
|
171
|
+
if (value === undefined || value === null || value === '')
|
|
172
|
+
return [];
|
|
173
|
+
const modelName = instance.getTable();
|
|
174
|
+
return relatedModel
|
|
175
|
+
.query()
|
|
176
|
+
.where(morphTypeColumn, '=', modelName)
|
|
177
|
+
.where(morphIdColumn, '=', value)
|
|
178
|
+
.get();
|
|
179
|
+
},
|
|
180
|
+
};
|
|
181
|
+
},
|
|
182
|
+
});
|
|
183
|
+
/**
|
|
184
|
+
* MorphTo Relationship
|
|
185
|
+
* Inverse of polymorphic relationships
|
|
186
|
+
* Sealed namespace object following Pattern 2
|
|
187
|
+
*
|
|
188
|
+
* @see FRAMEWORK_REFACTOR_FUNCTION_PATTERN.md for Pattern 2 details
|
|
189
|
+
*/
|
|
190
|
+
export const MorphTo = Object.freeze({
|
|
191
|
+
create(morphName, morphMap, morphType, morphId) {
|
|
192
|
+
const morphTypeColumn = morphType ?? `${morphName}_type`;
|
|
193
|
+
const morphIdColumn = morphId ?? `${morphName}_id`;
|
|
194
|
+
return {
|
|
195
|
+
type: 'morphTo',
|
|
196
|
+
related: Object.values(morphMap)[0],
|
|
197
|
+
foreignKey: morphIdColumn,
|
|
198
|
+
localKey: 'id',
|
|
199
|
+
morphType: morphTypeColumn,
|
|
200
|
+
morphId: morphIdColumn,
|
|
201
|
+
morphName,
|
|
202
|
+
morphMap,
|
|
203
|
+
async get(instance) {
|
|
204
|
+
const type = instance.getAttribute(morphTypeColumn);
|
|
205
|
+
const id = instance.getAttribute(morphIdColumn);
|
|
206
|
+
if (type === undefined ||
|
|
207
|
+
type === null ||
|
|
208
|
+
type === '' ||
|
|
209
|
+
id === undefined ||
|
|
210
|
+
id === null ||
|
|
211
|
+
id === '') {
|
|
212
|
+
return null;
|
|
213
|
+
}
|
|
214
|
+
const relatedModel = morphMap[String(type)];
|
|
215
|
+
if (relatedModel === undefined) {
|
|
216
|
+
throw ErrorFactory.createConfigError(`Unknown morph type: ${String(type)}. Available types: ${Object.keys(morphMap).join(', ')}`);
|
|
217
|
+
}
|
|
218
|
+
return relatedModel.query().where('id', '=', id).first();
|
|
219
|
+
},
|
|
220
|
+
};
|
|
221
|
+
},
|
|
222
|
+
});
|
|
223
|
+
/**
|
|
224
|
+
* HasOneThrough Relationship
|
|
225
|
+
* Access a distant relation through an intermediate model
|
|
226
|
+
* Example: Country -> User -> Post (Country hasOneThrough Post through User)
|
|
227
|
+
* Sealed namespace object following Pattern 2
|
|
228
|
+
*
|
|
229
|
+
* @see FRAMEWORK_REFACTOR_FUNCTION_PATTERN.md for Pattern 2 details
|
|
230
|
+
*/
|
|
231
|
+
export const HasOneThrough = Object.freeze({
|
|
232
|
+
create(relatedModel, through, foreignKey, throughForeignKey, localKey, secondLocalKey) {
|
|
233
|
+
const throughTable = getRelatedTableName(through);
|
|
234
|
+
const relatedTable = getRelatedTableName(relatedModel);
|
|
235
|
+
// Default keys
|
|
236
|
+
const firstKey = throughForeignKey ?? 'id';
|
|
237
|
+
const secondKey = foreignKey ?? `${throughTable.slice(0, -1)}_id`;
|
|
238
|
+
const localKeyColumn = localKey ?? 'id';
|
|
239
|
+
const secondLocalKeyColumn = secondLocalKey ?? 'id';
|
|
240
|
+
return {
|
|
241
|
+
type: 'hasOneThrough',
|
|
242
|
+
related: relatedModel,
|
|
243
|
+
foreignKey: secondKey,
|
|
244
|
+
localKey: localKeyColumn,
|
|
245
|
+
through,
|
|
246
|
+
throughForeignKey: firstKey,
|
|
247
|
+
secondLocalKey: secondLocalKeyColumn,
|
|
248
|
+
async get(instance) {
|
|
249
|
+
const value = instance.getAttribute(localKeyColumn);
|
|
250
|
+
if (value === undefined || value === null || value === '')
|
|
251
|
+
return null;
|
|
252
|
+
// Join through intermediate table
|
|
253
|
+
// SELECT related.* FROM related
|
|
254
|
+
// INNER JOIN through ON related.through_id = through.id
|
|
255
|
+
// WHERE through.parent_id = value
|
|
256
|
+
return relatedModel
|
|
257
|
+
.query()
|
|
258
|
+
.join(throughTable, `${relatedTable}.${secondKey} = ${throughTable}.${secondLocalKeyColumn}`)
|
|
259
|
+
.where(`${throughTable}.${firstKey}`, '=', value)
|
|
260
|
+
.first();
|
|
261
|
+
},
|
|
262
|
+
};
|
|
263
|
+
},
|
|
264
|
+
});
|
|
265
|
+
/**
|
|
266
|
+
* HasManyThrough Relationship
|
|
267
|
+
* Access distant relations through an intermediate model
|
|
268
|
+
* Example: Country -> User -> Post (Country hasManyThrough Posts through Users)
|
|
269
|
+
* Sealed namespace object following Pattern 2
|
|
270
|
+
*
|
|
271
|
+
* @see FRAMEWORK_REFACTOR_FUNCTION_PATTERN.md for Pattern 2 details
|
|
272
|
+
*/
|
|
273
|
+
export const HasManyThrough = Object.freeze({
|
|
274
|
+
create(relatedModel, through, foreignKey, throughForeignKey, localKey, secondLocalKey) {
|
|
275
|
+
const throughTable = getRelatedTableName(through);
|
|
276
|
+
const relatedTable = getRelatedTableName(relatedModel);
|
|
277
|
+
// Default keys
|
|
278
|
+
const firstKey = throughForeignKey ?? 'id';
|
|
279
|
+
const secondKey = foreignKey ?? `${throughTable.slice(0, -1)}_id`;
|
|
280
|
+
const localKeyColumn = localKey ?? 'id';
|
|
281
|
+
const secondLocalKeyColumn = secondLocalKey ?? 'id';
|
|
282
|
+
return {
|
|
283
|
+
type: 'hasManyThrough',
|
|
284
|
+
related: relatedModel,
|
|
285
|
+
foreignKey: secondKey,
|
|
286
|
+
localKey: localKeyColumn,
|
|
287
|
+
through,
|
|
288
|
+
throughForeignKey: firstKey,
|
|
289
|
+
secondLocalKey: secondLocalKeyColumn,
|
|
290
|
+
async get(instance) {
|
|
291
|
+
const value = instance.getAttribute(localKeyColumn);
|
|
292
|
+
if (value === undefined || value === null || value === '')
|
|
293
|
+
return [];
|
|
294
|
+
// Join through intermediate table
|
|
295
|
+
// SELECT related.* FROM related
|
|
296
|
+
// INNER JOIN through ON related.through_id = through.id
|
|
297
|
+
// WHERE through.parent_id = value
|
|
298
|
+
return relatedModel
|
|
299
|
+
.query()
|
|
300
|
+
.join(throughTable, `${relatedTable}.${secondKey} = ${throughTable}.${secondLocalKeyColumn}`)
|
|
301
|
+
.where(`${throughTable}.${firstKey}`, '=', value)
|
|
302
|
+
.get();
|
|
303
|
+
},
|
|
304
|
+
};
|
|
305
|
+
},
|
|
306
|
+
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"D1Adapter.d.ts","sourceRoot":"","sources":["../../../../src/orm/adapters/D1Adapter.ts"],"names":[],"mappings":"AAAA;;GAEG;
|
|
1
|
+
{"version":3,"file":"D1Adapter.d.ts","sourceRoot":"","sources":["../../../../src/orm/adapters/D1Adapter.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH,OAAO,KAAK,EACV,cAAc,EAEd,gBAAgB,EAEjB,MAAM,sBAAsB,CAAC;AAU9B;;GAEG;AACH,eAAO,MAAM,SAAS;IACpB;;OAEG;oBAEa,cAAc,GAAG,gBAAgB;EAkHjD,CAAC;AAEH,eAAe,SAAS,CAAC"}
|
|
@@ -5,6 +5,7 @@ import { Cloudflare } from '../../config/cloudflare.js';
|
|
|
5
5
|
import { FeatureFlags } from '../../config/features.js';
|
|
6
6
|
import { Logger } from '../../config/logger.js';
|
|
7
7
|
import { ErrorFactory } from '../../exceptions/ZintrustError.js';
|
|
8
|
+
import { AdaptersEnum } from '../../migrations/enum/index.js';
|
|
8
9
|
import { QueryBuilder } from '../QueryBuilder.js';
|
|
9
10
|
/**
|
|
10
11
|
* Get D1 binding from config or global environment
|
|
@@ -96,7 +97,7 @@ export const D1Adapter = Object.freeze({
|
|
|
96
97
|
}
|
|
97
98
|
},
|
|
98
99
|
getType() {
|
|
99
|
-
return
|
|
100
|
+
return AdaptersEnum.d1;
|
|
100
101
|
},
|
|
101
102
|
isConnected() {
|
|
102
103
|
return connected;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* D1 Remote Database Adapter
|
|
3
3
|
*
|
|
4
|
-
* Calls a
|
|
4
|
+
* Calls a ZinTrust Cloudflare Worker proxy over HTTPS.
|
|
5
5
|
*/
|
|
6
6
|
import type { DatabaseConfig, IDatabaseAdapter } from '../DatabaseAdapter';
|
|
7
7
|
export declare const D1RemoteAdapter: Readonly<{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"D1RemoteAdapter.d.ts","sourceRoot":"","sources":["../../../../src/orm/adapters/D1RemoteAdapter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"D1RemoteAdapter.d.ts","sourceRoot":"","sources":["../../../../src/orm/adapters/D1RemoteAdapter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAe,MAAM,sBAAsB,CAAC;AA+I1F,eAAO,MAAM,eAAe;oBACV,cAAc,GAAG,gBAAgB;EA+EjD,CAAC;AAEH,eAAe,eAAe,CAAC"}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* D1 Remote Database Adapter
|
|
3
3
|
*
|
|
4
|
-
* Calls a
|
|
4
|
+
* Calls a ZinTrust Cloudflare Worker proxy over HTTPS.
|
|
5
5
|
*/
|
|
6
6
|
import { RemoteSignedJson } from '../../common/RemoteSignedJson.js';
|
|
7
7
|
import { Env } from '../../config/env.js';
|
|
8
8
|
import { ErrorFactory } from '../../exceptions/ZintrustError.js';
|
|
9
|
+
import { AdaptersEnum } from '../../migrations/enum/index.js';
|
|
9
10
|
import { QueryBuilder } from '../QueryBuilder.js';
|
|
10
11
|
import { SignedRequest } from '../../security/SignedRequest.js';
|
|
11
12
|
const createRemoteConfig = () => {
|
|
@@ -148,7 +149,7 @@ export const D1RemoteAdapter = Object.freeze({
|
|
|
148
149
|
return out.rows;
|
|
149
150
|
},
|
|
150
151
|
getType() {
|
|
151
|
-
return
|
|
152
|
+
return AdaptersEnum.d1Remote;
|
|
152
153
|
},
|
|
153
154
|
isConnected() {
|
|
154
155
|
return connected;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MySQLAdapter.d.ts","sourceRoot":"","sources":["../../../../src/orm/adapters/MySQLAdapter.ts"],"names":[],"mappings":"AACA;;GAEG;
|
|
1
|
+
{"version":3,"file":"MySQLAdapter.d.ts","sourceRoot":"","sources":["../../../../src/orm/adapters/MySQLAdapter.ts"],"names":[],"mappings":"AACA;;GAEG;AAMH,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAe,MAAM,sBAAsB,CAAC;AAyG1F;;;GAGG;AACH,eAAO,MAAM,YAAY;IACvB;;OAEG;mBACY,cAAc,GAAG,gBAAgB;EAIhD,CAAC;AAEH,eAAe,YAAY,CAAC"}
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import { FeatureFlags } from '../../config/features.js';
|
|
6
6
|
import { Logger } from '../../config/logger.js';
|
|
7
7
|
import { ErrorFactory } from '../../exceptions/ZintrustError.js';
|
|
8
|
+
import { AdaptersEnum } from '../../migrations/enum/index.js';
|
|
8
9
|
import { QueryBuilder } from '../QueryBuilder.js';
|
|
9
10
|
function createRawQuery(state) {
|
|
10
11
|
return async function rawQuery(sql, parameters) {
|
|
@@ -68,7 +69,7 @@ function createMySQLAdapterInstance(config, state) {
|
|
|
68
69
|
}
|
|
69
70
|
},
|
|
70
71
|
getType() {
|
|
71
|
-
return
|
|
72
|
+
return AdaptersEnum.mysql;
|
|
72
73
|
},
|
|
73
74
|
isConnected() {
|
|
74
75
|
return state.connected;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SQLServerAdapter.d.ts","sourceRoot":"","sources":["../../../../src/orm/adapters/SQLServerAdapter.ts"],"names":[],"mappings":"AACA;;GAEG;
|
|
1
|
+
{"version":3,"file":"SQLServerAdapter.d.ts","sourceRoot":"","sources":["../../../../src/orm/adapters/SQLServerAdapter.ts"],"names":[],"mappings":"AACA;;GAEG;AAMH,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAe,MAAM,sBAAsB,CAAC;AAG1F;;;GAGG;AACH,eAAO,MAAM,gBAAgB;IAC3B;;OAEG;mBACY,cAAc,GAAG,gBAAgB;EA4EhD,CAAC;AAEH,eAAe,gBAAgB,CAAC"}
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import { FeatureFlags } from '../../config/features.js';
|
|
6
6
|
import { Logger } from '../../config/logger.js';
|
|
7
7
|
import { ErrorFactory } from '../../exceptions/ZintrustError.js';
|
|
8
|
+
import { AdaptersEnum } from '../../migrations/enum/index.js';
|
|
8
9
|
import { QueryBuilder } from '../QueryBuilder.js';
|
|
9
10
|
/**
|
|
10
11
|
* SQL Server adapter implementation
|
|
@@ -50,7 +51,7 @@ export const SQLServerAdapter = Object.freeze({
|
|
|
50
51
|
}
|
|
51
52
|
},
|
|
52
53
|
getType() {
|
|
53
|
-
return
|
|
54
|
+
return AdaptersEnum.sqlserver;
|
|
54
55
|
},
|
|
55
56
|
isConnected() {
|
|
56
57
|
return connected;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SQLiteAdapter.d.ts","sourceRoot":"","sources":["../../../../src/orm/adapters/SQLiteAdapter.ts"],"names":[],"mappings":"AACA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"SQLiteAdapter.d.ts","sourceRoot":"","sources":["../../../../src/orm/adapters/SQLiteAdapter.ts"],"names":[],"mappings":"AACA;;;GAGG;AAUH,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAe,MAAM,sBAAsB,CAAC;AA6M1F,iBAAS,mBAAmB,CAAC,MAAM,EAAE,cAAc,GAAG,gBAAgB,CA0FrE;AAED,eAAO,MAAM,aAAa;;EAExB,CAAC"}
|
|
@@ -7,6 +7,7 @@ import { databaseConfig } from '../../config/database.js';
|
|
|
7
7
|
import { FeatureFlags } from '../../config/features.js';
|
|
8
8
|
import { Logger } from '../../config/logger.js';
|
|
9
9
|
import { ErrorFactory } from '../../exceptions/ZintrustError.js';
|
|
10
|
+
import { AdaptersEnum } from '../../migrations/enum/index.js';
|
|
10
11
|
import fs from '../../node-singletons/fs.js';
|
|
11
12
|
import * as path from '../../node-singletons/path.js';
|
|
12
13
|
import { performance } from '../../node-singletons/perf-hooks.js';
|
|
@@ -208,7 +209,7 @@ function createSQLiteAdapter(config) {
|
|
|
208
209
|
await adapter.query('PRAGMA foreign_keys = ON', []);
|
|
209
210
|
},
|
|
210
211
|
getType() {
|
|
211
|
-
return
|
|
212
|
+
return AdaptersEnum.sqlite;
|
|
212
213
|
},
|
|
213
214
|
isConnected() {
|
|
214
215
|
return Boolean(state.db);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MigrationStore.d.ts","sourceRoot":"","sources":["../../../../src/orm/migrations/MigrationStore.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAI/C,OAAO,KAAK,EAAE,eAAe,EAAE,qBAAqB,EAAE,cAAc,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"MigrationStore.d.ts","sourceRoot":"","sources":["../../../../src/orm/migrations/MigrationStore.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAI/C,OAAO,KAAK,EAAE,eAAe,EAAE,qBAAqB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AA8ChG,eAAO,MAAM,cAAc;oBACH,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;8BASzC,SAAS,UACN,cAAc,YACZ,MAAM,GACd,OAAO,CAAC,MAAM,CAAC;sBAiBZ,SAAS,SACN,cAAc,WACZ,MAAM,GACd,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;sBAyBlC,SAAS,UACL;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,cAAc,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAC9E,OAAO,CAAC,IAAI,CAAC;mBAuCV,SAAS,UACL;QACN,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,cAAc,CAAC;QACtB,OAAO,EAAE,MAAM,CAAC;QAChB,MAAM,EAAE,qBAAqB,CAAC;QAC9B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KAC3B,GACA,OAAO,CAAC,IAAI,CAAC;kCAiBV,SAAS,UACL;QAAE,KAAK,EAAE,cAAc,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GACnE,OAAO,CAAC,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;8BAyB5C,SAAS,UACL;QAAE,KAAK,EAAE,cAAc,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GACjD,OAAO,CAAC,MAAM,EAAE,CAAC;qBAgBd,SAAS,UACL;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,cAAc,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAC/D,OAAO,CAAC,IAAI,CAAC;EAShB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Optimizer.d.ts","sourceRoot":"","sources":["../../../src/performance/Optimizer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AASH,MAAM,WAAW,gBAAgB;IAC/B,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC3E,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChF,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,QAAQ,IAAI,OAAO,CAAC;QAClB,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,SAAS,EAAE,MAAM,CAAC;QAClB,IAAI,EAAE,MAAM,EAAE,CAAC;KAChB,CAAC,CAAC;CACJ;
|
|
1
|
+
{"version":3,"file":"Optimizer.d.ts","sourceRoot":"","sources":["../../../src/performance/Optimizer.ts"],"names":[],"mappings":"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"}
|
|
@@ -59,8 +59,52 @@ function createCacheState(cacheDir, ttlMs, maxEntries) {
|
|
|
59
59
|
cacheDir,
|
|
60
60
|
ttlMs,
|
|
61
61
|
maxEntries,
|
|
62
|
+
pendingWrites: new Map(),
|
|
62
63
|
};
|
|
63
64
|
}
|
|
65
|
+
async function ensureCacheDir(cacheDir) {
|
|
66
|
+
try {
|
|
67
|
+
await fs.fsPromises.access(cacheDir);
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
await fs.fsPromises.mkdir(cacheDir, { recursive: true });
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
async function flushPendingWrites(state) {
|
|
74
|
+
if (state.pendingWrites.size === 0) {
|
|
75
|
+
state.flushTimer = undefined;
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
const pending = state.pendingWrites;
|
|
79
|
+
state.pendingWrites = new Map();
|
|
80
|
+
state.flushTimer = undefined;
|
|
81
|
+
try {
|
|
82
|
+
await ensureCacheDir(state.cacheDir);
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
Logger.error('Failed to ensure cache directory before flush', error);
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
const writes = Array.from(pending.entries()).map(async ([key, entry]) => {
|
|
89
|
+
const file = path.join(state.cacheDir, `${key}.json`);
|
|
90
|
+
await fs.fsPromises.writeFile(file, entry.payload);
|
|
91
|
+
});
|
|
92
|
+
await Promise.all(writes);
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
function scheduleCacheWrite(state, key, payload) {
|
|
96
|
+
state.pendingWrites.set(key, { payload });
|
|
97
|
+
if (state.flushTimer !== undefined)
|
|
98
|
+
return;
|
|
99
|
+
state.flushTimer = setTimeout(() => {
|
|
100
|
+
void flushPendingWrites(state).catch((error) => {
|
|
101
|
+
Logger.error('Failed to flush generation cache writes', error);
|
|
102
|
+
});
|
|
103
|
+
}, 50);
|
|
104
|
+
if (isUnrefableTimer(state.flushTimer)) {
|
|
105
|
+
state.flushTimer.unref();
|
|
106
|
+
}
|
|
107
|
+
}
|
|
64
108
|
function initializeCacheState(state) {
|
|
65
109
|
loadFromDisk(state);
|
|
66
110
|
}
|
|
@@ -134,15 +178,9 @@ function createCacheInstance(state) {
|
|
|
134
178
|
deleteFileNonBlocking(file);
|
|
135
179
|
}
|
|
136
180
|
}
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
await fs.fsPromises.access(state.cacheDir);
|
|
141
|
-
}
|
|
142
|
-
catch {
|
|
143
|
-
await fs.fsPromises.mkdir(state.cacheDir, { recursive: true });
|
|
144
|
-
}
|
|
145
|
-
await fs.fsPromises.writeFile(file, JSON.stringify({ code, timestamp: Date.now() }, null, 2));
|
|
181
|
+
const payload = JSON.stringify({ code, timestamp: Date.now() }, null, 2);
|
|
182
|
+
scheduleCacheWrite(state, key, payload);
|
|
183
|
+
return Promise.resolve();
|
|
146
184
|
},
|
|
147
185
|
/**
|
|
148
186
|
* Save cache to disk (async)
|
|
@@ -158,6 +196,11 @@ function createCacheInstance(state) {
|
|
|
158
196
|
clearInterval(state.cleanupInterval);
|
|
159
197
|
state.cleanupInterval = undefined;
|
|
160
198
|
}
|
|
199
|
+
if (state.flushTimer) {
|
|
200
|
+
clearTimeout(state.flushTimer);
|
|
201
|
+
state.flushTimer = undefined;
|
|
202
|
+
}
|
|
203
|
+
state.pendingWrites.clear();
|
|
161
204
|
await clearCache(state);
|
|
162
205
|
},
|
|
163
206
|
/**
|
|
@@ -179,11 +222,9 @@ function attachCacheStateForTests(instance, state) {
|
|
|
179
222
|
*/
|
|
180
223
|
async function saveCacheToDisk(state) {
|
|
181
224
|
try {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
catch {
|
|
186
|
-
await fs.fsPromises.mkdir(state.cacheDir, { recursive: true });
|
|
225
|
+
const flushedEnsured = await flushPendingWrites(state);
|
|
226
|
+
if (!flushedEnsured) {
|
|
227
|
+
await ensureCacheDir(state.cacheDir);
|
|
187
228
|
}
|
|
188
229
|
const writes = Array.from(state.cache.entries()).map(async ([key, entry]) => {
|
|
189
230
|
const file = path.join(state.cacheDir, `${key}.json`);
|
|
@@ -200,6 +241,7 @@ async function saveCacheToDisk(state) {
|
|
|
200
241
|
*/
|
|
201
242
|
async function clearCache(state) {
|
|
202
243
|
state.cache.clear();
|
|
244
|
+
state.pendingWrites.clear();
|
|
203
245
|
try {
|
|
204
246
|
try {
|
|
205
247
|
await fs.fsPromises.access(state.cacheDir);
|
|
@@ -242,9 +284,6 @@ async function getCacheStats(state) {
|
|
|
242
284
|
keys: Array.from(state.cache.keys()),
|
|
243
285
|
};
|
|
244
286
|
}
|
|
245
|
-
/**
|
|
246
|
-
* Format bytes as human-readable
|
|
247
|
-
*/
|
|
248
287
|
function formatBytes(bytes) {
|
|
249
288
|
const units = ['B', 'KB', 'MB'];
|
|
250
289
|
let size = bytes;
|
|
@@ -260,8 +299,8 @@ function formatBytes(bytes) {
|
|
|
260
299
|
*/
|
|
261
300
|
function getCacheKey(type, params) {
|
|
262
301
|
// Use a more efficient key generation
|
|
263
|
-
const paramStr = JSON.stringify(params);
|
|
264
302
|
// Simple hash-like string for the key
|
|
303
|
+
const paramStr = JSON.stringify(params, Object.keys(params).sort((a, b) => a.localeCompare(b)));
|
|
265
304
|
let hash = 0;
|
|
266
305
|
for (let i = 0; i < paramStr.length; i++) {
|
|
267
306
|
const char = paramStr.codePointAt(i);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RequestProfiler.d.ts","sourceRoot":"","sources":["../../../src/profiling/RequestProfiler.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,eAAe,
|
|
1
|
+
{"version":3,"file":"RequestProfiler.d.ts","sourceRoot":"","sources":["../../../src/profiling/RequestProfiler.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAGjE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAE3D,OAAO,KAAK,EAAE,WAAW,EAAa,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAE9E,MAAM,WAAW,gBAAgB;IAC/B,cAAc,IAAI,YAAY,CAAC;IAC/B,aAAa,IAAI,WAAW,CAAC;IAC7B,iBAAiB,IAAI,eAAe,CAAC;IACrC,cAAc,CAAC,EAAE,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IACnE,cAAc,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM,CAAC;CAChD;AAED;;;GAGG;AACH,eAAO,MAAM,eAAe;IAC1B;;OAEG;cACO,gBAAgB;EAsE1B,CAAC;AAmBH;;GAEG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAE3D,eAAe,eAAe,CAAC"}
|
|
@@ -49,13 +49,15 @@ export const RequestProfiler = Object.freeze({
|
|
|
49
49
|
const queriesExecuted = queryLog.length;
|
|
50
50
|
const patterns = n1Detector.detect(queryLog);
|
|
51
51
|
const memoryDelta = memoryProfiler.delta();
|
|
52
|
-
|
|
52
|
+
const report = {
|
|
53
53
|
duration,
|
|
54
54
|
queriesExecuted,
|
|
55
55
|
n1Patterns: patterns,
|
|
56
56
|
memoryDelta,
|
|
57
57
|
timestamp: new Date(),
|
|
58
58
|
};
|
|
59
|
+
queryLogger.clear('profiling');
|
|
60
|
+
return report;
|
|
59
61
|
},
|
|
60
62
|
generateReport(profile) {
|
|
61
63
|
const n1Section = formatN1Section(profile.n1Patterns);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CoreRoutes.d.ts","sourceRoot":"","sources":["../../../src/routing/CoreRoutes.ts"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"CoreRoutes.d.ts","sourceRoot":"","sources":["../../../src/routing/CoreRoutes.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAwBhD;;GAEG;AACH,eAAO,MAAM,kBAAkB,GAAI,QAAQ,OAAO,KAAG,IAMpD,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
|
|
@@ -3,127 +3,13 @@
|
|
|
3
3
|
* Health, metrics, and documentation endpoints
|
|
4
4
|
* Not customizable by developers; provide env-based configuration
|
|
5
5
|
*/
|
|
6
|
-
import { RuntimeHealthProbes } from '../health/RuntimeHealthProbes.js';
|
|
7
6
|
import { PrometheusMetrics } from '../observability/PrometheusMetrics.js';
|
|
8
|
-
import {
|
|
7
|
+
import { Router } from '../routing/Router.js';
|
|
8
|
+
import { registerHealthRoutes } from '../common/HealthRoutes.js';
|
|
9
9
|
import { Env } from '../config/env.js';
|
|
10
|
-
import { Logger } from '../config/logger.js';
|
|
11
|
-
import { useDatabase } from '../orm/Database.js';
|
|
12
|
-
import { QueryBuilder } from '../orm/QueryBuilder.js';
|
|
13
10
|
import { registerDocRoutes } from './doc.js';
|
|
14
11
|
import { registerErrorRoutes } from './error.js';
|
|
15
12
|
import { registerErrorPagesRoutes } from './errorPages.js';
|
|
16
|
-
import { Router } from './Router.js';
|
|
17
|
-
/**
|
|
18
|
-
* Register health endpoints
|
|
19
|
-
*/
|
|
20
|
-
async function handleHealthRoute(_req, res) {
|
|
21
|
-
const environment = Env.NODE_ENV ?? 'development';
|
|
22
|
-
try {
|
|
23
|
-
const db = useDatabase();
|
|
24
|
-
const maybeIsConnected = db.isConnected;
|
|
25
|
-
const maybeConnect = db.connect;
|
|
26
|
-
if (typeof maybeIsConnected === 'function' && maybeIsConnected.call(db) === false) {
|
|
27
|
-
if (typeof maybeConnect === 'function') {
|
|
28
|
-
await maybeConnect.call(db);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
await QueryBuilder.ping(db);
|
|
32
|
-
const uptime = typeof process !== 'undefined' && typeof process.uptime === 'function' ? process.uptime() : 0;
|
|
33
|
-
res.json({
|
|
34
|
-
status: 'healthy',
|
|
35
|
-
timestamp: new Date().toISOString(),
|
|
36
|
-
uptime,
|
|
37
|
-
database: 'connected',
|
|
38
|
-
environment,
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
catch (error) {
|
|
42
|
-
Logger.error('Health check failed:', error);
|
|
43
|
-
const isProd = environment === 'production' || environment === 'prod';
|
|
44
|
-
res.setStatus(503).json({
|
|
45
|
-
status: 'unhealthy',
|
|
46
|
-
timestamp: new Date().toISOString(),
|
|
47
|
-
database: 'disconnected',
|
|
48
|
-
error: isProd ? 'Service unavailable' : error.message,
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
function handleHealthLiveRoute(_req, res) {
|
|
53
|
-
const uptime = typeof process !== 'undefined' && typeof process.uptime === 'function' ? process.uptime() : 0;
|
|
54
|
-
res.json({
|
|
55
|
-
status: 'alive',
|
|
56
|
-
timestamp: new Date().toISOString(),
|
|
57
|
-
uptime,
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
async function handleHealthReadyRoute(_req, res) {
|
|
61
|
-
const startTime = Date.now();
|
|
62
|
-
const environment = appConfig.environment;
|
|
63
|
-
let databaseResponseTime = null;
|
|
64
|
-
let cacheResponseTime = null;
|
|
65
|
-
try {
|
|
66
|
-
const db = useDatabase();
|
|
67
|
-
const maybeIsConnected = db.isConnected;
|
|
68
|
-
const maybeConnect = db.connect;
|
|
69
|
-
if (typeof maybeIsConnected === 'function' && maybeIsConnected.call(db) === false) {
|
|
70
|
-
if (typeof maybeConnect === 'function') {
|
|
71
|
-
await maybeConnect.call(db);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
await QueryBuilder.ping(db);
|
|
75
|
-
databaseResponseTime = Date.now() - startTime;
|
|
76
|
-
cacheResponseTime = await RuntimeHealthProbes.pingKvCache(2000);
|
|
77
|
-
res.json({
|
|
78
|
-
status: 'ready',
|
|
79
|
-
timestamp: new Date().toISOString(),
|
|
80
|
-
environment,
|
|
81
|
-
dependencies: {
|
|
82
|
-
database: {
|
|
83
|
-
status: 'ready',
|
|
84
|
-
responseTime: databaseResponseTime,
|
|
85
|
-
},
|
|
86
|
-
...(cacheResponseTime === null
|
|
87
|
-
? {}
|
|
88
|
-
: {
|
|
89
|
-
cache: {
|
|
90
|
-
status: 'ready',
|
|
91
|
-
responseTime: cacheResponseTime,
|
|
92
|
-
},
|
|
93
|
-
}),
|
|
94
|
-
},
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
|
-
catch (error) {
|
|
98
|
-
Logger.error('Readiness check failed:', error);
|
|
99
|
-
const isProd = environment === 'production';
|
|
100
|
-
const responseTime = Date.now() - startTime;
|
|
101
|
-
const dependencies = {
|
|
102
|
-
database: {
|
|
103
|
-
status: databaseResponseTime === null ? 'unavailable' : 'ready',
|
|
104
|
-
responseTime: databaseResponseTime ?? responseTime,
|
|
105
|
-
},
|
|
106
|
-
};
|
|
107
|
-
if (RuntimeHealthProbes.getCacheDriverName() === 'kv') {
|
|
108
|
-
dependencies['cache'] = {
|
|
109
|
-
status: 'unavailable',
|
|
110
|
-
responseTime: cacheResponseTime ?? responseTime,
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
res.setStatus(503).json({
|
|
114
|
-
status: 'not_ready',
|
|
115
|
-
timestamp: new Date().toISOString(),
|
|
116
|
-
environment,
|
|
117
|
-
dependencies,
|
|
118
|
-
error: isProd ? 'Service unavailable' : error.message,
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
function registerHealthRoutes(router) {
|
|
123
|
-
Router.get(router, '/health', handleHealthRoute);
|
|
124
|
-
Router.get(router, '/health/live', handleHealthLiveRoute);
|
|
125
|
-
Router.get(router, '/health/ready', handleHealthReadyRoute);
|
|
126
|
-
}
|
|
127
13
|
/**
|
|
128
14
|
* Register metrics endpoint
|
|
129
15
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../../../src/routing/error.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,KAAK,IAAI,MAAM,uBAAuB,CAAC;AAEnD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../../../src/routing/error.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,KAAK,IAAI,MAAM,uBAAuB,CAAC;AAEnD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AA0J/C;;GAEG;AACH,eAAO,MAAM,mBAAmB,GAAI,QAAQ,OAAO,KAAG,IAGrD,CAAC;AAEF,eAAO,MAAM,YAAY;;kCALmB,OAAO,KAAG,IAAI;8BAlGzB,QAAQ,YAAY,SAAS,cAAc,MAAM,KAAG,IAAI;qDAiB9E,QAAQ,YACP,SAAS,SACZ,OAAO,cACF,MAAM,KACjB,IAAI;wCA0DoC,IAAI,CAAC,cAAc,KAAG,IAAI;EA8BnE,CAAC;AAEH,eAAe,YAAY,CAAC"}
|