@zintrust/core 0.1.20 → 0.1.21
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/package.json +2 -1
- package/src/boot/Application.d.ts.map +1 -1
- package/src/boot/Application.js +48 -10
- package/src/boot/bootstrap.js +2 -0
- package/src/cli/commands/MigrateCommand.d.ts.map +1 -1
- package/src/cli/commands/MigrateCommand.js +36 -3
- package/src/cli/d1/D1SqlMigrations.d.ts.map +1 -1
- package/src/cli/d1/D1SqlMigrations.js +6 -1
- package/src/cli/scaffolding/ControllerGenerator.js +4 -4
- package/src/cli/scaffolding/GovernanceScaffolder.js +1 -1
- package/src/cli/scaffolding/MigrationGenerator.js +1 -1
- package/src/cli/scaffolding/ModelGenerator.js +1 -1
- package/src/cli/scaffolding/RouteGenerator.js +1 -1
- package/src/cli/scaffolding/ServiceScaffolder.js +4 -4
- package/src/config/broadcast.d.ts +14 -28
- package/src/config/broadcast.d.ts.map +1 -1
- package/src/config/broadcast.js +69 -35
- package/src/config/cache.d.ts +13 -45
- package/src/config/cache.d.ts.map +1 -1
- package/src/config/cache.js +69 -25
- package/src/config/database.d.ts +22 -64
- package/src/config/database.d.ts.map +1 -1
- package/src/config/database.js +99 -31
- package/src/config/env.d.ts +6 -0
- package/src/config/env.d.ts.map +1 -1
- package/src/config/env.js +7 -0
- package/src/config/index.d.ts +32 -136
- package/src/config/index.d.ts.map +1 -1
- package/src/config/mail.d.ts +19 -55
- package/src/config/mail.d.ts.map +1 -1
- package/src/config/mail.js +63 -21
- package/src/config/middleware.d.ts +24 -0
- package/src/config/middleware.d.ts.map +1 -1
- package/src/config/middleware.js +72 -52
- package/src/config/notification.d.ts +14 -27
- package/src/config/notification.d.ts.map +1 -1
- package/src/config/notification.js +82 -36
- package/src/config/queue.d.ts +21 -51
- package/src/config/queue.d.ts.map +1 -1
- package/src/config/queue.js +72 -27
- package/src/config/storage.d.ts +27 -34
- package/src/config/storage.d.ts.map +1 -1
- package/src/config/storage.js +97 -56
- package/src/config/type.d.ts +12 -1
- package/src/config/type.d.ts.map +1 -1
- package/src/http/parsers/MultipartParser.d.ts.map +1 -1
- package/src/http/parsers/MultipartParser.js +69 -42
- package/src/index.d.ts +9 -5
- package/src/index.d.ts.map +1 -1
- package/src/index.js +1 -0
- package/src/microservices/PostgresAdapter.d.ts.map +1 -1
- package/src/microservices/PostgresAdapter.js +0 -1
- package/src/migrations/MigratorFactory.d.ts.map +1 -1
- package/src/migrations/MigratorFactory.js +18 -2
- package/src/node-singletons/fs.d.ts +1 -1
- package/src/node-singletons/fs.d.ts.map +1 -1
- package/src/node-singletons/fs.js +1 -1
- package/src/orm/Database.d.ts +2 -1
- package/src/orm/Database.d.ts.map +1 -1
- package/src/orm/Database.js +110 -67
- package/src/orm/DatabaseAdapter.d.ts +1 -0
- package/src/orm/DatabaseAdapter.d.ts.map +1 -1
- package/src/orm/DatabaseRuntimeRegistration.d.ts.map +1 -1
- package/src/orm/DatabaseRuntimeRegistration.js +12 -0
- package/src/orm/QueryBuilder.d.ts +1 -1
- package/src/orm/QueryBuilder.d.ts.map +1 -1
- package/src/orm/QueryBuilder.js +4 -3
- package/src/orm/adapters/SQLiteAdapter.js +1 -1
- package/src/performance/Optimizer.d.ts +6 -6
- package/src/performance/Optimizer.d.ts.map +1 -1
- package/src/performance/Optimizer.js +133 -52
- package/src/routing/doc.d.ts +4 -5
- package/src/routing/doc.d.ts.map +1 -1
- package/src/routing/doc.js +35 -20
- package/src/routing/publicRoot.d.ts +9 -0
- package/src/routing/publicRoot.d.ts.map +1 -1
- package/src/routing/publicRoot.js +63 -2
- package/src/runtime/StartupConfigFileRegistry.d.ts +20 -0
- package/src/runtime/StartupConfigFileRegistry.d.ts.map +1 -0
- package/src/runtime/StartupConfigFileRegistry.js +44 -0
- package/src/runtime/useFileLoader.d.ts +26 -0
- package/src/runtime/useFileLoader.d.ts.map +1 -0
- package/src/runtime/useFileLoader.js +188 -0
- package/src/scripts/TemplateSync.js +4 -4
- package/src/security/XssProtection.d.ts.map +1 -1
- package/src/security/XssProtection.js +62 -14
- package/src/templates/project/basic/config/broadcast.ts.tpl +33 -17
- package/src/templates/project/basic/config/cache.ts.tpl +35 -17
- package/src/templates/project/basic/config/database.ts.tpl +68 -32
- package/src/templates/project/basic/config/logging/HttpLogger.ts.tpl +7 -114
- package/src/templates/project/basic/config/mail.ts.tpl +59 -13
- package/src/templates/project/basic/config/notification.ts.tpl +28 -17
- package/src/templates/project/basic/config/queue.ts.tpl +49 -17
- package/src/templates/project/basic/config/storage.ts.tpl +55 -18
- package/src/templates/project/basic/config/type.ts.tpl +0 -1
- package/src/templates/project/basic/src/index.ts.tpl +3 -0
- package/src/templates/project/basic/config/logging/KvLogger.ts.tpl +0 -181
- package/src/templates/project/basic/config/logging/SlackLogger.ts.tpl +0 -156
|
@@ -22,6 +22,7 @@ const toOrmConfig = (cfg) => {
|
|
|
22
22
|
database: cfg.database,
|
|
23
23
|
username: cfg.username,
|
|
24
24
|
password: cfg.password,
|
|
25
|
+
readHosts: cfg.readHosts,
|
|
25
26
|
};
|
|
26
27
|
case 'mysql':
|
|
27
28
|
return {
|
|
@@ -31,6 +32,17 @@ const toOrmConfig = (cfg) => {
|
|
|
31
32
|
database: cfg.database,
|
|
32
33
|
username: cfg.username,
|
|
33
34
|
password: cfg.password,
|
|
35
|
+
readHosts: cfg.readHosts,
|
|
36
|
+
};
|
|
37
|
+
case 'sqlserver':
|
|
38
|
+
return {
|
|
39
|
+
driver: 'sqlserver',
|
|
40
|
+
host: cfg.host,
|
|
41
|
+
port: cfg.port,
|
|
42
|
+
database: cfg.database,
|
|
43
|
+
username: cfg.username,
|
|
44
|
+
password: cfg.password,
|
|
45
|
+
readHosts: cfg.readHosts,
|
|
34
46
|
};
|
|
35
47
|
default:
|
|
36
48
|
// Exhaustive check (kept for future driver additions)
|
|
@@ -14,7 +14,7 @@ export interface WhereClause {
|
|
|
14
14
|
* Provides access to the created record ID, affected rows count, and the full record if available
|
|
15
15
|
*/
|
|
16
16
|
export interface InsertResult {
|
|
17
|
-
id: string | number | null;
|
|
17
|
+
id: string | number | bigint | null;
|
|
18
18
|
affectedRows: number;
|
|
19
19
|
insertedRecords?: Record<string, unknown>[];
|
|
20
20
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QueryBuilder.d.ts","sourceRoot":"","sources":["../../../src/orm/QueryBuilder.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAGzC,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,OAAO,CAAC;CAChB;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"QueryBuilder.d.ts","sourceRoot":"","sources":["../../../src/orm/QueryBuilder.ts"],"names":[],"mappings":"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"}
|
package/src/orm/QueryBuilder.js
CHANGED
|
@@ -570,13 +570,14 @@ function attachWriteMethods(builder, state, db) {
|
|
|
570
570
|
throw ErrorFactory.createDatabaseError('INSERT requires a table name');
|
|
571
571
|
const compiled = compileInsert(tableName, values, state.dialect);
|
|
572
572
|
const items = Array.isArray(values) ? values : [values];
|
|
573
|
-
await currentDb.
|
|
573
|
+
const result = await currentDb.execute(compiled.sql, compiled.parameters, false);
|
|
574
574
|
// Return InsertResult with metadata
|
|
575
575
|
// Note: lastInsertId typically only available for single-row inserts in most databases
|
|
576
576
|
// For multi-row inserts, use the insertedRecords array
|
|
577
577
|
return {
|
|
578
|
-
id:
|
|
579
|
-
|
|
578
|
+
id: result.lastInsertId ??
|
|
579
|
+
(items.length === 1 ? (items[0]?.['id'] ?? null) : null),
|
|
580
|
+
affectedRows: result.rowCount,
|
|
580
581
|
insertedRecords: items,
|
|
581
582
|
};
|
|
582
583
|
};
|
|
@@ -83,7 +83,7 @@ function executeQuery(db, sql, parameters) {
|
|
|
83
83
|
if (databaseConfig.logging.enabled) {
|
|
84
84
|
Logger.debug('SQLite query executed', { durationMs: performance.now() - start, sql });
|
|
85
85
|
}
|
|
86
|
-
return { rows: [], rowCount: info.changes };
|
|
86
|
+
return { rows: [], rowCount: info.changes, lastInsertId: info.lastInsertRowid };
|
|
87
87
|
}
|
|
88
88
|
function executeRawQuery(db, sql, parameters) {
|
|
89
89
|
const stmt = db.prepare(sql);
|
|
@@ -3,16 +3,16 @@
|
|
|
3
3
|
* Implements caching, lazy-loading, and parallel generation
|
|
4
4
|
*/
|
|
5
5
|
export interface IGenerationCache {
|
|
6
|
-
get(type: string, params: Record<string, unknown>): string | null
|
|
7
|
-
set(type: string, params: Record<string, unknown>, code: string): void
|
|
8
|
-
save(): void
|
|
9
|
-
clear(): void
|
|
10
|
-
getStats(): {
|
|
6
|
+
get(type: string, params: Record<string, unknown>): Promise<string | null>;
|
|
7
|
+
set(type: string, params: Record<string, unknown>, code: string): Promise<void>;
|
|
8
|
+
save(): Promise<void>;
|
|
9
|
+
clear(): Promise<void>;
|
|
10
|
+
getStats(): Promise<{
|
|
11
11
|
size: number;
|
|
12
12
|
entries: number;
|
|
13
13
|
diskUsage: string;
|
|
14
14
|
keys: string[];
|
|
15
|
-
}
|
|
15
|
+
}>;
|
|
16
16
|
}
|
|
17
17
|
/**
|
|
18
18
|
* Generation Cache - Cache generated code to avoid re-generating identical code
|
|
@@ -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,MAAM,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"Optimizer.d.ts","sourceRoot":"","sources":["../../../src/performance/Optimizer.ts"],"names":[],"mappings":"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"}
|
|
@@ -95,26 +95,26 @@ function startCacheCleanup(state) {
|
|
|
95
95
|
function createCacheInstance(state) {
|
|
96
96
|
return {
|
|
97
97
|
/**
|
|
98
|
-
* Get from cache
|
|
98
|
+
* Get from cache (async)
|
|
99
99
|
*/
|
|
100
|
-
get(type, params) {
|
|
100
|
+
async get(type, params) {
|
|
101
101
|
const key = getCacheKey(type, params);
|
|
102
102
|
const entry = state.cache.get(key);
|
|
103
103
|
if (entry === undefined)
|
|
104
|
-
return null;
|
|
104
|
+
return Promise.resolve(null); //NoSONAR
|
|
105
105
|
// Check TTL
|
|
106
106
|
if (Date.now() - entry.timestamp > state.ttlMs) {
|
|
107
107
|
state.cache.delete(key);
|
|
108
108
|
const file = path.join(state.cacheDir, `${key}.json`);
|
|
109
109
|
deleteFileNonBlocking(file);
|
|
110
|
-
return null;
|
|
110
|
+
return Promise.resolve(null); //NoSONAR
|
|
111
111
|
}
|
|
112
|
-
return entry.code;
|
|
112
|
+
return Promise.resolve(entry.code); //NoSONAR
|
|
113
113
|
},
|
|
114
114
|
/**
|
|
115
|
-
* Set in cache
|
|
115
|
+
* Set in cache (async)
|
|
116
116
|
*/
|
|
117
|
-
set(type, params, code) {
|
|
117
|
+
async set(type, params, code) {
|
|
118
118
|
const key = getCacheKey(type, params);
|
|
119
119
|
// If key already exists, delete first so insertion order updates for LRU
|
|
120
120
|
if (state.cache.has(key))
|
|
@@ -134,27 +134,36 @@ function createCacheInstance(state) {
|
|
|
134
134
|
deleteFileNonBlocking(file);
|
|
135
135
|
}
|
|
136
136
|
}
|
|
137
|
+
// Save to disk asynchronously
|
|
138
|
+
const file = path.join(state.cacheDir, `${key}.json`);
|
|
139
|
+
try {
|
|
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));
|
|
137
146
|
},
|
|
138
147
|
/**
|
|
139
|
-
* Save cache to disk
|
|
148
|
+
* Save cache to disk (async)
|
|
140
149
|
*/
|
|
141
|
-
save() {
|
|
142
|
-
saveCacheToDisk(state);
|
|
150
|
+
async save() {
|
|
151
|
+
await saveCacheToDisk(state);
|
|
143
152
|
},
|
|
144
153
|
/**
|
|
145
|
-
* Clear cache
|
|
154
|
+
* Clear cache (async)
|
|
146
155
|
*/
|
|
147
|
-
clear() {
|
|
156
|
+
async clear() {
|
|
148
157
|
if (state.cleanupInterval) {
|
|
149
158
|
clearInterval(state.cleanupInterval);
|
|
150
159
|
state.cleanupInterval = undefined;
|
|
151
160
|
}
|
|
152
|
-
clearCache(state);
|
|
161
|
+
await clearCache(state);
|
|
153
162
|
},
|
|
154
163
|
/**
|
|
155
|
-
* Get cache statistics
|
|
164
|
+
* Get cache statistics (async)
|
|
156
165
|
*/
|
|
157
|
-
getStats() {
|
|
166
|
+
async getStats() {
|
|
158
167
|
return getCacheStats(state);
|
|
159
168
|
},
|
|
160
169
|
};
|
|
@@ -166,38 +175,66 @@ function attachCacheStateForTests(instance, state) {
|
|
|
166
175
|
});
|
|
167
176
|
}
|
|
168
177
|
/**
|
|
169
|
-
* Save cache to disk
|
|
178
|
+
* Save cache to disk (async)
|
|
170
179
|
*/
|
|
171
|
-
function saveCacheToDisk(state) {
|
|
172
|
-
|
|
173
|
-
|
|
180
|
+
async function saveCacheToDisk(state) {
|
|
181
|
+
try {
|
|
182
|
+
try {
|
|
183
|
+
await fs.fsPromises.access(state.cacheDir);
|
|
184
|
+
}
|
|
185
|
+
catch {
|
|
186
|
+
await fs.fsPromises.mkdir(state.cacheDir, { recursive: true });
|
|
187
|
+
}
|
|
188
|
+
const writes = Array.from(state.cache.entries()).map(async ([key, entry]) => {
|
|
189
|
+
const file = path.join(state.cacheDir, `${key}.json`);
|
|
190
|
+
await fs.fsPromises.writeFile(file, JSON.stringify(entry, null, 2));
|
|
191
|
+
});
|
|
192
|
+
await Promise.all(writes);
|
|
174
193
|
}
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
fs.writeFileSync(file, JSON.stringify(entry, null, 2));
|
|
194
|
+
catch (error) {
|
|
195
|
+
Logger.error('Failed to save cache to disk', error);
|
|
178
196
|
}
|
|
179
197
|
}
|
|
180
198
|
/**
|
|
181
|
-
* Clear cache
|
|
199
|
+
* Clear cache (async)
|
|
182
200
|
*/
|
|
183
|
-
function clearCache(state) {
|
|
201
|
+
async function clearCache(state) {
|
|
184
202
|
state.cache.clear();
|
|
185
|
-
|
|
186
|
-
|
|
203
|
+
try {
|
|
204
|
+
try {
|
|
205
|
+
await fs.fsPromises.access(state.cacheDir);
|
|
206
|
+
}
|
|
207
|
+
catch {
|
|
208
|
+
return; // Dir doesn't exist
|
|
209
|
+
}
|
|
210
|
+
await fs.fsPromises.rm(state.cacheDir, { recursive: true });
|
|
211
|
+
}
|
|
212
|
+
catch (error) {
|
|
213
|
+
Logger.error('Failed to clear cache', error);
|
|
187
214
|
}
|
|
188
215
|
}
|
|
189
216
|
/**
|
|
190
|
-
* Get cache statistics
|
|
217
|
+
* Get cache statistics (async)
|
|
191
218
|
*/
|
|
192
|
-
function getCacheStats(state) {
|
|
219
|
+
async function getCacheStats(state) {
|
|
193
220
|
let diskUsage = 0;
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
const
|
|
198
|
-
|
|
221
|
+
try {
|
|
222
|
+
try {
|
|
223
|
+
await fs.fsPromises.access(state.cacheDir);
|
|
224
|
+
const files = await fs.fsPromises.readdir(state.cacheDir);
|
|
225
|
+
const sizes = await Promise.all(files.map(async (file) => {
|
|
226
|
+
const stats = await fs.fsPromises.stat(path.join(state.cacheDir, file));
|
|
227
|
+
return stats.size;
|
|
228
|
+
}));
|
|
229
|
+
diskUsage = sizes.reduce((sum, size) => sum + size, 0);
|
|
230
|
+
}
|
|
231
|
+
catch {
|
|
232
|
+
// ignore
|
|
199
233
|
}
|
|
200
234
|
}
|
|
235
|
+
catch {
|
|
236
|
+
// ignore
|
|
237
|
+
}
|
|
201
238
|
return {
|
|
202
239
|
size: diskUsage,
|
|
203
240
|
entries: state.cache.size,
|
|
@@ -242,24 +279,39 @@ function toInt32(value) {
|
|
|
242
279
|
return uint32 > 2147483647 ? uint32 - 4294967296 : uint32;
|
|
243
280
|
}
|
|
244
281
|
/**
|
|
245
|
-
* Load cache from disk
|
|
282
|
+
* Load cache from disk (async)
|
|
246
283
|
*/
|
|
247
|
-
function loadFromDisk(state) {
|
|
248
|
-
|
|
284
|
+
async function loadFromDisk(state) {
|
|
285
|
+
try {
|
|
249
286
|
try {
|
|
250
|
-
|
|
251
|
-
for (const file of files) {
|
|
252
|
-
if (file.endsWith('.json') === true) {
|
|
253
|
-
const content = fs.readFileSync(path.join(state.cacheDir, file), 'utf-8');
|
|
254
|
-
const data = JSON.parse(content);
|
|
255
|
-
state.cache.set(file.replace('.json', ''), data);
|
|
256
|
-
}
|
|
257
|
-
}
|
|
287
|
+
await fs.fsPromises.access(state.cacheDir);
|
|
258
288
|
}
|
|
259
|
-
catch
|
|
260
|
-
|
|
289
|
+
catch {
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
const files = await fs.fsPromises.readdir(state.cacheDir);
|
|
293
|
+
const jsonFiles = files.filter((file) => file.endsWith('.json') === true);
|
|
294
|
+
const parsedEntries = await Promise.all(jsonFiles.map(async (file) => {
|
|
295
|
+
const filePath = path.join(state.cacheDir, file);
|
|
296
|
+
const content = await fs.fsPromises.readFile(filePath, 'utf-8');
|
|
297
|
+
try {
|
|
298
|
+
const data = JSON.parse(content);
|
|
299
|
+
return { key: file.replace('.json', ''), data };
|
|
300
|
+
}
|
|
301
|
+
catch {
|
|
302
|
+
// ignore corrupted files
|
|
303
|
+
return null;
|
|
304
|
+
}
|
|
305
|
+
}));
|
|
306
|
+
for (const entry of parsedEntries) {
|
|
307
|
+
if (entry !== null) {
|
|
308
|
+
state.cache.set(entry.key, entry.data);
|
|
309
|
+
}
|
|
261
310
|
}
|
|
262
311
|
}
|
|
312
|
+
catch (err) {
|
|
313
|
+
Logger.error(`Failed to load cache from disk: ${err instanceof Error ? err.message : String(err)}`);
|
|
314
|
+
}
|
|
263
315
|
}
|
|
264
316
|
/**
|
|
265
317
|
* Lazy Module Loader - Load dependencies only when needed
|
|
@@ -474,17 +526,36 @@ async function generateInParallel(stats, generators, batchSize) {
|
|
|
474
526
|
*/
|
|
475
527
|
async function generateWithCache(cache, stats, type, params, generatorFn) {
|
|
476
528
|
// Try cache
|
|
477
|
-
|
|
529
|
+
let cached = null;
|
|
530
|
+
try {
|
|
531
|
+
cached = await cache.get(type, params);
|
|
532
|
+
}
|
|
533
|
+
catch (err) {
|
|
534
|
+
Logger.warn('GenerationCache.get failed; treating as cache miss', {
|
|
535
|
+
type,
|
|
536
|
+
error: err instanceof Error ? err.message : String(err),
|
|
537
|
+
});
|
|
538
|
+
}
|
|
478
539
|
if (cached !== null) {
|
|
479
|
-
|
|
480
|
-
|
|
540
|
+
try {
|
|
541
|
+
stats.cacheHits++;
|
|
542
|
+
return JSON.parse(cached);
|
|
543
|
+
}
|
|
544
|
+
catch (err) {
|
|
545
|
+
Logger.warn('Failed to parse cached generation result; treating as cache miss', {
|
|
546
|
+
type,
|
|
547
|
+
error: err instanceof Error ? err.message : String(err),
|
|
548
|
+
});
|
|
549
|
+
}
|
|
481
550
|
}
|
|
482
551
|
// Generate
|
|
483
552
|
const startTime = performance.now();
|
|
484
553
|
const result = await generatorFn();
|
|
485
554
|
const duration = performance.now() - startTime;
|
|
486
|
-
// Cache result
|
|
487
|
-
cache
|
|
555
|
+
// Cache result (fire-and-forget)
|
|
556
|
+
void cache
|
|
557
|
+
.set(type, params, JSON.stringify(result))
|
|
558
|
+
.catch((err) => Logger.error('GenerationCache.set failed', err));
|
|
488
559
|
stats.cacheMisses++;
|
|
489
560
|
stats.savedTime += duration;
|
|
490
561
|
return result;
|
|
@@ -492,6 +563,16 @@ async function generateWithCache(cache, stats, type, params, generatorFn) {
|
|
|
492
563
|
/**
|
|
493
564
|
* Get optimization statistics
|
|
494
565
|
*/
|
|
566
|
+
function getCacheStatusSync(cache) {
|
|
567
|
+
const state = cache[GENERATION_CACHE_STATE_SYMBOL];
|
|
568
|
+
const map = state?.cache;
|
|
569
|
+
if (!(map instanceof Map))
|
|
570
|
+
return { size: 0, keys: [] };
|
|
571
|
+
return {
|
|
572
|
+
size: map.size,
|
|
573
|
+
keys: Array.from(map.keys()),
|
|
574
|
+
};
|
|
575
|
+
}
|
|
495
576
|
function getOptimizerStats(cache, stats) {
|
|
496
577
|
const total = stats.cacheHits + stats.cacheMisses;
|
|
497
578
|
const hitRate = total > 0 ? (stats.cacheHits / total) * 100 : 0;
|
|
@@ -501,7 +582,7 @@ function getOptimizerStats(cache, stats) {
|
|
|
501
582
|
hitRate: `${hitRate.toFixed(1)}%`,
|
|
502
583
|
parallelRuns: stats.parallelRuns,
|
|
503
584
|
estimatedSavedTime: `${stats.savedTime.toFixed(2)}ms`,
|
|
504
|
-
cacheStatus: cache
|
|
585
|
+
cacheStatus: getCacheStatusSync(cache),
|
|
505
586
|
};
|
|
506
587
|
}
|
|
507
588
|
export default PerformanceOptimizer;
|
package/src/routing/doc.d.ts
CHANGED
|
@@ -8,21 +8,20 @@ export { MIME_TYPES_MAP } from './common';
|
|
|
8
8
|
/**
|
|
9
9
|
* Find the package root directory
|
|
10
10
|
*/
|
|
11
|
-
export { findPackageRoot, getFrameworkPublicRoots, getPublicRoot } from './publicRoot';
|
|
11
|
+
export { findPackageRoot, findPackageRootAsync, getFrameworkPublicRoots, getFrameworkPublicRootsAsync, getPublicRoot, getPublicRootAsync, } from './publicRoot';
|
|
12
12
|
/**
|
|
13
13
|
* Set relaxed CSP headers for docs (allows external assets like Tailwind CDN, Google Fonts)
|
|
14
14
|
*/
|
|
15
15
|
export declare const setDocumentationCSPHeaders: (response: IResponse) => void;
|
|
16
16
|
/**
|
|
17
|
-
* Serve a documentation static file
|
|
18
|
-
* Returns true if file was served, false if not found
|
|
17
|
+
* Serve a documentation static file (async)
|
|
19
18
|
*/
|
|
20
|
-
export declare const
|
|
19
|
+
export declare const serveDocumentationFileAsync: (urlPath: string, response: IResponse) => Promise<boolean>;
|
|
21
20
|
export declare const registerDocRoutes: (router: IRouter) => void;
|
|
22
21
|
declare const _default: {
|
|
23
22
|
registerDocRoutes: (router: IRouter) => void;
|
|
24
23
|
setDocumentationCSPHeaders: (response: IResponse) => void;
|
|
25
|
-
|
|
24
|
+
serveDocumentationFileAsync: (urlPath: string, response: IResponse) => Promise<boolean>;
|
|
26
25
|
};
|
|
27
26
|
export default _default;
|
|
28
27
|
//# sourceMappingURL=doc.d.ts.map
|
package/src/routing/doc.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doc.d.ts","sourceRoot":"","sources":["../../../src/routing/doc.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAMhD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAG/C,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEjD;;GAEG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"doc.d.ts","sourceRoot":"","sources":["../../../src/routing/doc.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAMhD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAG/C,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEjD;;GAEG;AAEH,OAAO,EACL,eAAe,EACf,oBAAoB,EACpB,uBAAuB,EACvB,4BAA4B,EAC5B,aAAa,EACb,kBAAkB,GACnB,MAAM,qBAAqB,CAAC;AAiB7B;;GAEG;AACH,eAAO,MAAM,0BAA0B,GAAI,UAAU,SAAS,KAAG,IAWhE,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,2BAA2B,GACtC,SAAS,MAAM,EACf,UAAU,SAAS,KAClB,OAAO,CAAC,OAAO,CAgDjB,CAAC;AASF,eAAO,MAAM,iBAAiB,GAAI,QAAQ,OAAO,KAAG,IAMnD,CAAC;;gCANwC,OAAO,KAAG,IAAI;2CA5EH,SAAS,KAAG,IAAI;2CAiB1D,MAAM,YACL,SAAS,KAClB,OAAO,CAAC,OAAO,CAAC;;AAiEnB,wBAIE"}
|
package/src/routing/doc.js
CHANGED
|
@@ -8,19 +8,16 @@ import * as fs from '../node-singletons/fs.js';
|
|
|
8
8
|
import * as path from '../node-singletons/path.js';
|
|
9
9
|
import { MIME_TYPES_MAP, resolveSafePath, tryDecodeURIComponent } from './common.js';
|
|
10
10
|
import { ErrorRouting } from './error.js';
|
|
11
|
-
import {
|
|
11
|
+
import { getPublicRootAsync } from './publicRoot.js';
|
|
12
12
|
import { Router } from './Router.js';
|
|
13
13
|
export { MIME_TYPES_MAP } from './common.js';
|
|
14
14
|
/**
|
|
15
15
|
* Find the package root directory
|
|
16
16
|
*/
|
|
17
17
|
// Backward-compatible re-exports
|
|
18
|
-
export { findPackageRoot, getFrameworkPublicRoots, getPublicRoot } from './publicRoot.js';
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
*/
|
|
22
|
-
const mapStaticPath = (urlPath) => {
|
|
23
|
-
const publicRoot = getPublicRoot();
|
|
18
|
+
export { findPackageRoot, findPackageRootAsync, getFrameworkPublicRoots, getFrameworkPublicRootsAsync, getPublicRoot, getPublicRootAsync, } from './publicRoot.js';
|
|
19
|
+
const mapStaticPathAsync = async (urlPath) => {
|
|
20
|
+
const publicRoot = await getPublicRootAsync();
|
|
24
21
|
const normalize = (p) => (p.startsWith('/') ? p.slice(1) : p);
|
|
25
22
|
if (urlPath === '/doc' || urlPath === '/doc/')
|
|
26
23
|
return publicRoot;
|
|
@@ -45,28 +42,42 @@ export const setDocumentationCSPHeaders = (response) => {
|
|
|
45
42
|
"font-src 'self' data: https://fonts.gstatic.com;");
|
|
46
43
|
};
|
|
47
44
|
/**
|
|
48
|
-
* Serve a documentation static file
|
|
49
|
-
* Returns true if file was served, false if not found
|
|
45
|
+
* Serve a documentation static file (async)
|
|
50
46
|
*/
|
|
51
|
-
export const
|
|
52
|
-
let filePath =
|
|
47
|
+
export const serveDocumentationFileAsync = async (urlPath, response) => {
|
|
48
|
+
let filePath = await mapStaticPathAsync(urlPath);
|
|
53
49
|
if (filePath === undefined) {
|
|
54
50
|
return false;
|
|
55
51
|
}
|
|
56
52
|
try {
|
|
57
|
-
|
|
58
|
-
|
|
53
|
+
try {
|
|
54
|
+
const stats = await fs.fsPromises.stat(filePath);
|
|
55
|
+
if (stats.isDirectory()) {
|
|
56
|
+
filePath = path.join(filePath, 'index.html');
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
// ignore
|
|
59
61
|
}
|
|
60
|
-
|
|
62
|
+
const exists = async (p) => {
|
|
63
|
+
try {
|
|
64
|
+
await fs.fsPromises.access(p);
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
if (!(await exists(filePath)) && !path.extname(filePath)) {
|
|
61
72
|
const htmlPath = `${filePath}.html`;
|
|
62
|
-
if (
|
|
73
|
+
if (await exists(htmlPath)) {
|
|
63
74
|
filePath = htmlPath;
|
|
64
75
|
}
|
|
65
76
|
}
|
|
66
|
-
if (
|
|
77
|
+
if (await exists(filePath)) {
|
|
67
78
|
const ext = path.extname(filePath).toLowerCase();
|
|
68
79
|
const contentType = MIME_TYPES_MAP[ext] || 'application/octet-stream';
|
|
69
|
-
const content = fs.
|
|
80
|
+
const content = await fs.fsPromises.readFile(filePath);
|
|
70
81
|
response.setStatus(200);
|
|
71
82
|
response.setHeader('Content-Type', contentType);
|
|
72
83
|
response.send(content);
|
|
@@ -78,10 +89,10 @@ export const serveDocumentationFile = (urlPath, response) => {
|
|
|
78
89
|
}
|
|
79
90
|
return false;
|
|
80
91
|
};
|
|
81
|
-
const handleDocRequest = (req, res) => {
|
|
92
|
+
const handleDocRequest = async (req, res) => {
|
|
82
93
|
setDocumentationCSPHeaders(res);
|
|
83
94
|
const urlPath = req.getPath();
|
|
84
|
-
if (
|
|
95
|
+
if (await serveDocumentationFileAsync(urlPath, res))
|
|
85
96
|
return;
|
|
86
97
|
ErrorRouting.handleNotFound(req, res);
|
|
87
98
|
};
|
|
@@ -92,4 +103,8 @@ export const registerDocRoutes = (router) => {
|
|
|
92
103
|
// Greedy path match for nested assets like /doc/assets/app.js
|
|
93
104
|
Router.get(router, '/doc/:path*', handleDocRequest);
|
|
94
105
|
};
|
|
95
|
-
export default {
|
|
106
|
+
export default {
|
|
107
|
+
registerDocRoutes,
|
|
108
|
+
setDocumentationCSPHeaders,
|
|
109
|
+
serveDocumentationFileAsync,
|
|
110
|
+
};
|
|
@@ -6,13 +6,22 @@
|
|
|
6
6
|
* Find the package root directory.
|
|
7
7
|
*/
|
|
8
8
|
export declare const findPackageRoot: (startDir: string) => string;
|
|
9
|
+
/**
|
|
10
|
+
* Find the package root directory (async).
|
|
11
|
+
*/
|
|
12
|
+
export declare const findPackageRootAsync: (startDir: string) => Promise<string>;
|
|
9
13
|
/**
|
|
10
14
|
* Framework public roots (dist/public preferred).
|
|
11
15
|
*/
|
|
12
16
|
export declare const getFrameworkPublicRoots: () => string[];
|
|
17
|
+
export declare const getFrameworkPublicRootsAsync: () => Promise<string[]>;
|
|
13
18
|
/**
|
|
14
19
|
* Resolve the effective public root.
|
|
15
20
|
* Prefers app-local `public/` when present; otherwise falls back to framework public roots.
|
|
16
21
|
*/
|
|
17
22
|
export declare const getPublicRoot: () => string;
|
|
23
|
+
/**
|
|
24
|
+
* Resolve the effective public root (async).
|
|
25
|
+
*/
|
|
26
|
+
export declare const getPublicRootAsync: () => Promise<string>;
|
|
18
27
|
//# sourceMappingURL=publicRoot.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"publicRoot.d.ts","sourceRoot":"","sources":["../../../src/routing/publicRoot.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH;;GAEG;AACH,eAAO,MAAM,eAAe,GAAI,UAAU,MAAM,KAAG,
|
|
1
|
+
{"version":3,"file":"publicRoot.d.ts","sourceRoot":"","sources":["../../../src/routing/publicRoot.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH;;GAEG;AACH,eAAO,MAAM,eAAe,GAAI,UAAU,MAAM,KAAG,MAalD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,oBAAoB,GAAU,UAAU,MAAM,KAAG,OAAO,CAAC,MAAM,CAkB3E,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,uBAAuB,QAAO,MAAM,EAIhD,CAAC;AAEF,eAAO,MAAM,4BAA4B,QAAa,OAAO,CAAC,MAAM,EAAE,CAIrE,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,aAAa,QAAO,MAgBhC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,kBAAkB,QAAa,OAAO,CAAC,MAAM,CA+BzD,CAAC"}
|
|
@@ -11,8 +11,13 @@ import * as path from '../node-singletons/path.js';
|
|
|
11
11
|
export const findPackageRoot = (startDir) => {
|
|
12
12
|
let current = startDir;
|
|
13
13
|
for (let i = 0; i < 10; i++) {
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
try {
|
|
15
|
+
if (fs.existsSync(path.join(current, 'package.json')))
|
|
16
|
+
return current;
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
// ignore access errors
|
|
20
|
+
}
|
|
16
21
|
const parent = path.dirname(current);
|
|
17
22
|
if (parent === current)
|
|
18
23
|
break;
|
|
@@ -20,6 +25,27 @@ export const findPackageRoot = (startDir) => {
|
|
|
20
25
|
}
|
|
21
26
|
return startDir;
|
|
22
27
|
};
|
|
28
|
+
/**
|
|
29
|
+
* Find the package root directory (async).
|
|
30
|
+
*/
|
|
31
|
+
export const findPackageRootAsync = async (startDir) => {
|
|
32
|
+
const findUp = async (current, depth) => {
|
|
33
|
+
if (depth >= 10)
|
|
34
|
+
return startDir;
|
|
35
|
+
try {
|
|
36
|
+
await fs.fsPromises.access(path.join(current, 'package.json'));
|
|
37
|
+
return current;
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
// ignore
|
|
41
|
+
}
|
|
42
|
+
const parent = path.dirname(current);
|
|
43
|
+
if (parent === current)
|
|
44
|
+
return startDir;
|
|
45
|
+
return findUp(parent, depth + 1);
|
|
46
|
+
};
|
|
47
|
+
return findUp(startDir, 0);
|
|
48
|
+
};
|
|
23
49
|
/**
|
|
24
50
|
* Framework public roots (dist/public preferred).
|
|
25
51
|
*/
|
|
@@ -28,6 +54,11 @@ export const getFrameworkPublicRoots = () => {
|
|
|
28
54
|
const packageRoot = findPackageRoot(thisDir);
|
|
29
55
|
return [path.join(packageRoot, 'dist/public'), path.join(packageRoot, 'public')];
|
|
30
56
|
};
|
|
57
|
+
export const getFrameworkPublicRootsAsync = async () => {
|
|
58
|
+
const thisDir = esmDirname(import.meta.url);
|
|
59
|
+
const packageRoot = await findPackageRootAsync(thisDir);
|
|
60
|
+
return [path.join(packageRoot, 'dist/public'), path.join(packageRoot, 'public')];
|
|
61
|
+
};
|
|
31
62
|
/**
|
|
32
63
|
* Resolve the effective public root.
|
|
33
64
|
* Prefers app-local `public/` when present; otherwise falls back to framework public roots.
|
|
@@ -47,3 +78,33 @@ export const getPublicRoot = () => {
|
|
|
47
78
|
}
|
|
48
79
|
return candidates[0];
|
|
49
80
|
};
|
|
81
|
+
/**
|
|
82
|
+
* Resolve the effective public root (async).
|
|
83
|
+
*/
|
|
84
|
+
export const getPublicRootAsync = async () => {
|
|
85
|
+
const appRoots = [path.join(process.cwd(), 'public')];
|
|
86
|
+
const fwRoots = await getFrameworkPublicRootsAsync();
|
|
87
|
+
const candidates = [...appRoots, ...fwRoots];
|
|
88
|
+
const exists = async (p) => {
|
|
89
|
+
try {
|
|
90
|
+
await fs.fsPromises.access(p);
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
const hasIndex = async (root) => exists(path.join(root, 'index.html'));
|
|
98
|
+
const checks = await Promise.all(candidates.map(async (candidate) => {
|
|
99
|
+
const rootExists = await exists(candidate);
|
|
100
|
+
const indexExists = rootExists ? await hasIndex(candidate) : false;
|
|
101
|
+
return { candidate, rootExists, indexExists };
|
|
102
|
+
}));
|
|
103
|
+
const withIndex = checks.find((c) => c.indexExists);
|
|
104
|
+
if (withIndex)
|
|
105
|
+
return withIndex.candidate;
|
|
106
|
+
const firstExisting = checks.find((c) => c.rootExists);
|
|
107
|
+
if (firstExisting)
|
|
108
|
+
return firstExisting.candidate;
|
|
109
|
+
return candidates[0];
|
|
110
|
+
};
|