aegisnode 0.0.5 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +190 -218
- package/package.json +12 -11
- package/scripts/smoke-test.js +87 -5
- package/src/cli/commands/createapp.js +4 -3
- package/src/cli/commands/doctor.js +17 -11
- package/src/cli/commands/fixapp.js +9 -4
- package/src/cli/commands/generate.js +33 -28
- package/src/cli/commands/generateloader.js +10 -4
- package/src/cli/commands/startproject.js +19 -12
- package/src/cli/index.js +16 -6
- package/src/cli/utils/apps.js +41 -34
- package/src/cli/utils/project.js +14 -6
- package/src/cli/utils/scaffolds.js +87 -31
- package/src/index.js +1 -0
- package/src/runtime/config.js +10 -10
- package/src/runtime/kernel.js +49 -32
- package/src/runtime/typescript.js +21 -0
- package/src/utils/source-files.js +78 -0
package/src/cli/utils/apps.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import fs from 'fs/promises';
|
|
2
2
|
import path from 'path';
|
|
3
|
-
import { pathToFileURL } from 'url';
|
|
4
3
|
import { ensureDir, ensureValidName, exists, normalizeMountPath, writeFile } from './fs.js';
|
|
4
|
+
import { importProjectModule } from '../../runtime/typescript.js';
|
|
5
|
+
import {
|
|
6
|
+
detectProjectSourceExtension,
|
|
7
|
+
resolveSourceFile,
|
|
8
|
+
} from '../../utils/source-files.js';
|
|
5
9
|
import {
|
|
6
10
|
renderAppModelTest,
|
|
7
11
|
renderAppModelsFile,
|
|
@@ -15,6 +19,7 @@ import {
|
|
|
15
19
|
renderAppValidatorsFile,
|
|
16
20
|
renderAppViewsFile,
|
|
17
21
|
renderSettingsApps,
|
|
22
|
+
withSourceExtension,
|
|
18
23
|
} from './scaffolds.js';
|
|
19
24
|
|
|
20
25
|
export const APPS_START = '// AEGIS_APPS_START';
|
|
@@ -45,24 +50,23 @@ export function toImportName(appName) {
|
|
|
45
50
|
}
|
|
46
51
|
|
|
47
52
|
async function readDefaultExport(filePath) {
|
|
48
|
-
const
|
|
49
|
-
const loaded = await import(moduleUrl);
|
|
53
|
+
const loaded = await importProjectModule(filePath);
|
|
50
54
|
return loaded?.default;
|
|
51
55
|
}
|
|
52
56
|
|
|
53
57
|
export async function detectSettingsMode(projectRoot) {
|
|
54
|
-
const single = path.join(projectRoot, 'settings
|
|
55
|
-
const split = path.join(projectRoot, 'settings', 'apps
|
|
58
|
+
const single = resolveSourceFile(path.join(projectRoot, 'settings'));
|
|
59
|
+
const split = resolveSourceFile(path.join(projectRoot, 'settings', 'apps'));
|
|
56
60
|
|
|
57
|
-
if (await exists(single)) {
|
|
61
|
+
if (single && await exists(single)) {
|
|
58
62
|
return { mode: 'single', file: single };
|
|
59
63
|
}
|
|
60
64
|
|
|
61
|
-
if (await exists(split)) {
|
|
65
|
+
if (split && await exists(split)) {
|
|
62
66
|
return { mode: 'split', file: split };
|
|
63
67
|
}
|
|
64
68
|
|
|
65
|
-
throw new Error(`Not an AegisNode project root: missing
|
|
69
|
+
throw new Error(`Not an AegisNode project root: missing settings.js/settings.ts (or legacy settings/apps.js/settings/apps.ts)`);
|
|
66
70
|
}
|
|
67
71
|
|
|
68
72
|
export async function readAppsConfig(settingsMode) {
|
|
@@ -111,65 +115,67 @@ async function updateSingleSettingsApps(settingsFile, apps) {
|
|
|
111
115
|
}
|
|
112
116
|
|
|
113
117
|
export async function updateAppRegistry(projectRoot, apps, settingsMode) {
|
|
118
|
+
const sourceExtension = detectProjectSourceExtension(projectRoot);
|
|
119
|
+
|
|
114
120
|
if (settingsMode.mode === 'single') {
|
|
115
121
|
await updateSingleSettingsApps(settingsMode.file, apps);
|
|
116
122
|
return;
|
|
117
123
|
}
|
|
118
124
|
|
|
119
|
-
await writeFile(path.join(projectRoot, 'settings', 'apps
|
|
125
|
+
await writeFile(path.join(projectRoot, 'settings', withSourceExtension('apps', sourceExtension)), renderSettingsApps(apps));
|
|
120
126
|
}
|
|
121
127
|
|
|
122
|
-
export function getAppScaffoldEntries(appName) {
|
|
128
|
+
export function getAppScaffoldEntries(appName, sourceExtension = '.js') {
|
|
123
129
|
const appRoot = path.join('apps', appName);
|
|
124
130
|
return [
|
|
125
131
|
{
|
|
126
|
-
target: path.join(appRoot, 'views
|
|
127
|
-
content: renderAppViewsFile(appName),
|
|
132
|
+
target: path.join(appRoot, withSourceExtension('views', sourceExtension)),
|
|
133
|
+
content: renderAppViewsFile(appName, sourceExtension),
|
|
128
134
|
},
|
|
129
135
|
{
|
|
130
|
-
target: path.join(appRoot, 'models
|
|
136
|
+
target: path.join(appRoot, withSourceExtension('models', sourceExtension)),
|
|
131
137
|
content: renderAppModelsFile(appName),
|
|
132
138
|
},
|
|
133
139
|
{
|
|
134
|
-
target: path.join(appRoot, 'validators
|
|
140
|
+
target: path.join(appRoot, withSourceExtension('validators', sourceExtension)),
|
|
135
141
|
content: renderAppValidatorsFile(appName),
|
|
136
142
|
},
|
|
137
143
|
{
|
|
138
|
-
target: path.join(appRoot, 'services
|
|
144
|
+
target: path.join(appRoot, withSourceExtension('services', sourceExtension)),
|
|
139
145
|
content: renderAppServicesFile(appName),
|
|
140
146
|
},
|
|
141
147
|
{
|
|
142
|
-
target: path.join(appRoot, 'utils
|
|
148
|
+
target: path.join(appRoot, withSourceExtension('utils', sourceExtension)),
|
|
143
149
|
content: renderAppUtilsFile(),
|
|
144
150
|
},
|
|
145
151
|
{
|
|
146
|
-
target: path.join(appRoot, 'subscribers
|
|
152
|
+
target: path.join(appRoot, withSourceExtension('subscribers', sourceExtension)),
|
|
147
153
|
content: renderAppSubscribersFile(appName),
|
|
148
154
|
},
|
|
149
155
|
{
|
|
150
|
-
target: path.join(appRoot, 'routes
|
|
151
|
-
content: renderAppRoutes(appName),
|
|
156
|
+
target: path.join(appRoot, withSourceExtension('routes', sourceExtension)),
|
|
157
|
+
content: renderAppRoutes(appName, sourceExtension),
|
|
152
158
|
},
|
|
153
159
|
{
|
|
154
|
-
target: path.join(appRoot, 'tests', 'models.test
|
|
155
|
-
content: renderAppModelTest(appName),
|
|
160
|
+
target: path.join(appRoot, 'tests', withSourceExtension('models.test', sourceExtension)),
|
|
161
|
+
content: renderAppModelTest(appName, sourceExtension),
|
|
156
162
|
},
|
|
157
163
|
{
|
|
158
|
-
target: path.join(appRoot, 'tests', 'validators.test
|
|
159
|
-
content: renderAppValidatorTest(appName),
|
|
164
|
+
target: path.join(appRoot, 'tests', withSourceExtension('validators.test', sourceExtension)),
|
|
165
|
+
content: renderAppValidatorTest(appName, sourceExtension),
|
|
160
166
|
},
|
|
161
167
|
{
|
|
162
|
-
target: path.join(appRoot, 'tests', 'services.test
|
|
163
|
-
content: renderAppServiceTest(appName),
|
|
168
|
+
target: path.join(appRoot, 'tests', withSourceExtension('services.test', sourceExtension)),
|
|
169
|
+
content: renderAppServiceTest(appName, sourceExtension),
|
|
164
170
|
},
|
|
165
171
|
{
|
|
166
|
-
target: path.join(appRoot, 'tests', 'routes.test
|
|
167
|
-
content: renderAppRoutesTest(appName),
|
|
172
|
+
target: path.join(appRoot, 'tests', withSourceExtension('routes.test', sourceExtension)),
|
|
173
|
+
content: renderAppRoutesTest(appName, sourceExtension),
|
|
168
174
|
},
|
|
169
175
|
];
|
|
170
176
|
}
|
|
171
177
|
|
|
172
|
-
export async function ensureAppScaffold(projectRoot, appName, { overwrite = false } = {}) {
|
|
178
|
+
export async function ensureAppScaffold(projectRoot, appName, { overwrite = false, sourceExtension = '.js' } = {}) {
|
|
173
179
|
ensureValidName(appName, 'app');
|
|
174
180
|
|
|
175
181
|
const appRoot = path.join(projectRoot, 'apps', appName);
|
|
@@ -179,7 +185,7 @@ export async function ensureAppScaffold(projectRoot, appName, { overwrite = fals
|
|
|
179
185
|
const written = [];
|
|
180
186
|
const skipped = [];
|
|
181
187
|
|
|
182
|
-
for (const entry of getAppScaffoldEntries(appName)) {
|
|
188
|
+
for (const entry of getAppScaffoldEntries(appName, sourceExtension)) {
|
|
183
189
|
const target = path.join(projectRoot, entry.target);
|
|
184
190
|
if (!overwrite && await exists(target)) {
|
|
185
191
|
skipped.push(target);
|
|
@@ -197,12 +203,13 @@ export async function ensureAppScaffold(projectRoot, appName, { overwrite = fals
|
|
|
197
203
|
};
|
|
198
204
|
}
|
|
199
205
|
|
|
200
|
-
export async function updateProjectRoutesFile(projectRoot, appName, mountPath) {
|
|
201
|
-
const
|
|
202
|
-
|
|
206
|
+
export async function updateProjectRoutesFile(projectRoot, appName, mountPath, sourceExtension = null) {
|
|
207
|
+
const effectiveExtension = sourceExtension || detectProjectSourceExtension(projectRoot);
|
|
208
|
+
const routesFile = resolveSourceFile(path.join(projectRoot, 'routes'), [effectiveExtension]) || resolveSourceFile(path.join(projectRoot, 'routes'));
|
|
209
|
+
if (!routesFile || !(await exists(routesFile))) {
|
|
203
210
|
// Keep backward compatibility for legacy projects that still use routes/index.js.
|
|
204
211
|
return {
|
|
205
|
-
routesFile,
|
|
212
|
+
routesFile: routesFile || path.join(projectRoot, withSourceExtension('routes', effectiveExtension)),
|
|
206
213
|
updatedImport: false,
|
|
207
214
|
updatedRoute: false,
|
|
208
215
|
skipped: true,
|
|
@@ -210,7 +217,7 @@ export async function updateProjectRoutesFile(projectRoot, appName, mountPath) {
|
|
|
210
217
|
}
|
|
211
218
|
|
|
212
219
|
const importName = toImportName(appName);
|
|
213
|
-
const importLine = `import ${importName} from './apps/${appName}/routes
|
|
220
|
+
const importLine = `import ${importName} from './apps/${appName}/routes${effectiveExtension}';`;
|
|
214
221
|
const routeLine = ` route.use(${JSON.stringify(mountPath)}, ${importName});`;
|
|
215
222
|
const routePattern = new RegExp(`route\\.use\\([^\\n]*,\\s*${escapeRegExp(importName)}\\s*\\);`);
|
|
216
223
|
|
package/src/cli/utils/project.js
CHANGED
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
import fs from 'fs/promises';
|
|
2
2
|
import path from 'path';
|
|
3
|
-
import {
|
|
3
|
+
import { detectProjectSourceExtension, resolveSourceFile, resolveSourceIndexFile } from '../../utils/source-files.js';
|
|
4
4
|
|
|
5
5
|
export async function hasRoutesFile(projectRoot) {
|
|
6
|
-
return (
|
|
7
|
-
|
|
6
|
+
return Boolean(
|
|
7
|
+
resolveSourceFile(path.join(projectRoot, 'routes'))
|
|
8
|
+
|| resolveSourceIndexFile(path.join(projectRoot, 'routes')),
|
|
9
|
+
);
|
|
8
10
|
}
|
|
9
11
|
|
|
10
12
|
export async function hasSettingsFile(projectRoot) {
|
|
11
|
-
return (
|
|
12
|
-
|
|
13
|
-
|| (
|
|
13
|
+
return Boolean(
|
|
14
|
+
resolveSourceFile(path.join(projectRoot, 'settings'))
|
|
15
|
+
|| resolveSourceIndexFile(path.join(projectRoot, 'settings'))
|
|
16
|
+
|| resolveSourceFile(path.join(projectRoot, 'settings', 'apps')),
|
|
17
|
+
);
|
|
14
18
|
}
|
|
15
19
|
|
|
16
20
|
export async function isProjectRoot(projectRoot) {
|
|
@@ -65,3 +69,7 @@ export async function resolveProjectRoot(projectRootHint) {
|
|
|
65
69
|
|
|
66
70
|
throw new Error(`Could not find an AegisNode project from ${startDir}. Run inside project or use --project <path>.`);
|
|
67
71
|
}
|
|
72
|
+
|
|
73
|
+
export function getProjectSourceExtension(projectRoot) {
|
|
74
|
+
return detectProjectSourceExtension(projectRoot);
|
|
75
|
+
}
|
|
@@ -6,31 +6,42 @@ export function toPascalCase(value) {
|
|
|
6
6
|
.join('');
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
+
export function withSourceExtension(baseName, extension = '.js') {
|
|
10
|
+
return `${baseName}${extension}`;
|
|
11
|
+
}
|
|
12
|
+
|
|
9
13
|
function renderAppEntries(apps, indent = ' ') {
|
|
10
14
|
return apps
|
|
11
15
|
.map((app) => `${indent}{ name: ${JSON.stringify(app.name)}, mount: ${JSON.stringify(app.mount)} },`)
|
|
12
16
|
.join('\n');
|
|
13
17
|
}
|
|
14
18
|
|
|
15
|
-
export function renderProjectPackageJson(projectName) {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
test: 'node --test',
|
|
26
|
-
},
|
|
27
|
-
dependencies: {
|
|
28
|
-
aegisnode: '^0.1.0',
|
|
29
|
-
},
|
|
19
|
+
export function renderProjectPackageJson(projectName, { typescript = false } = {}) {
|
|
20
|
+
const packageJson = {
|
|
21
|
+
name: projectName,
|
|
22
|
+
version: '1.0.0',
|
|
23
|
+
private: true,
|
|
24
|
+
type: 'module',
|
|
25
|
+
scripts: {
|
|
26
|
+
dev: 'aegisnode runserver',
|
|
27
|
+
start: 'node loader.cjs',
|
|
28
|
+
test: typescript ? 'node --import tsx/esm --test' : 'node --test',
|
|
30
29
|
},
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
dependencies: {
|
|
31
|
+
aegisnode: '^0.1.0',
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
if (typescript) {
|
|
36
|
+
packageJson.scripts.typecheck = 'tsc --noEmit';
|
|
37
|
+
packageJson.devDependencies = {
|
|
38
|
+
'@types/node': '^24.0.0',
|
|
39
|
+
tsx: '^4.21.0',
|
|
40
|
+
typescript: '^5.9.3',
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return `${JSON.stringify(packageJson, null, 2)}\n`;
|
|
34
45
|
}
|
|
35
46
|
|
|
36
47
|
export function renderProjectAppJs() {
|
|
@@ -45,7 +56,18 @@ runProject({ rootDir: __dirname });
|
|
|
45
56
|
`;
|
|
46
57
|
}
|
|
47
58
|
|
|
48
|
-
export function renderProjectLoaderCjs() {
|
|
59
|
+
export function renderProjectLoaderCjs(sourceExtension = '.js') {
|
|
60
|
+
if (sourceExtension === '.ts') {
|
|
61
|
+
return `import('aegisnode').then(async ({ registerTypeScriptRuntime }) => {
|
|
62
|
+
await registerTypeScriptRuntime();
|
|
63
|
+
return import('./app.ts');
|
|
64
|
+
}).catch((error) => {
|
|
65
|
+
console.error(error?.stack || error?.message || String(error));
|
|
66
|
+
process.exitCode = 1;
|
|
67
|
+
});
|
|
68
|
+
`;
|
|
69
|
+
}
|
|
70
|
+
|
|
49
71
|
return `import('./app.js').catch((error) => {
|
|
50
72
|
console.error(error?.stack || error?.message || String(error));
|
|
51
73
|
process.exitCode = 1;
|
|
@@ -53,6 +75,33 @@ export function renderProjectLoaderCjs() {
|
|
|
53
75
|
`;
|
|
54
76
|
}
|
|
55
77
|
|
|
78
|
+
export function renderTsConfig() {
|
|
79
|
+
return `${JSON.stringify(
|
|
80
|
+
{
|
|
81
|
+
compilerOptions: {
|
|
82
|
+
target: 'ES2022',
|
|
83
|
+
module: 'NodeNext',
|
|
84
|
+
moduleResolution: 'NodeNext',
|
|
85
|
+
strict: true,
|
|
86
|
+
esModuleInterop: true,
|
|
87
|
+
skipLibCheck: true,
|
|
88
|
+
forceConsistentCasingInFileNames: true,
|
|
89
|
+
noEmit: true,
|
|
90
|
+
allowImportingTsExtensions: true,
|
|
91
|
+
types: ['node'],
|
|
92
|
+
},
|
|
93
|
+
include: [
|
|
94
|
+
'app.ts',
|
|
95
|
+
'settings.ts',
|
|
96
|
+
'routes.ts',
|
|
97
|
+
'apps/**/*.ts',
|
|
98
|
+
],
|
|
99
|
+
},
|
|
100
|
+
null,
|
|
101
|
+
2,
|
|
102
|
+
)}\n`;
|
|
103
|
+
}
|
|
104
|
+
|
|
56
105
|
export function renderProjectSettings(projectName, apps, appSecret = '') {
|
|
57
106
|
return `export default {
|
|
58
107
|
appName: '${projectName}',
|
|
@@ -60,6 +109,13 @@ export function renderProjectSettings(projectName, apps, appSecret = '') {
|
|
|
60
109
|
host: process.env.HOST || '0.0.0.0',
|
|
61
110
|
port: process.env.PORT ? Number(process.env.PORT) : 3000,
|
|
62
111
|
trustProxy: false,
|
|
112
|
+
staticDir: 'public',
|
|
113
|
+
templates: {
|
|
114
|
+
enabled: true,
|
|
115
|
+
engine: 'ejs',
|
|
116
|
+
dir: 'templates',
|
|
117
|
+
base: 'base',
|
|
118
|
+
},
|
|
63
119
|
security: {
|
|
64
120
|
// Loaded from .env by default. Scaffold also embeds the generated secret as a fallback.
|
|
65
121
|
// Replace or rotate APP_SECRET in production.
|
|
@@ -81,7 +137,7 @@ export function renderProjectSettings(projectName, apps, appSecret = '') {
|
|
|
81
137
|
},
|
|
82
138
|
|
|
83
139
|
// Optional sections you can add manually when needed:
|
|
84
|
-
// maintenance, https,
|
|
140
|
+
// maintenance, https, i18n, helpers, websocket, uploads, auth, api, mail, swagger,
|
|
85
141
|
// architecture, loaders, environments, security.headers/ddos/csrf
|
|
86
142
|
|
|
87
143
|
apps: [
|
|
@@ -177,7 +233,7 @@ export function renderController(appName) {
|
|
|
177
233
|
return renderView(appName);
|
|
178
234
|
}
|
|
179
235
|
|
|
180
|
-
export function renderAppViewsFile(appName) {
|
|
236
|
+
export function renderAppViewsFile(appName, sourceExtension = '.js') {
|
|
181
237
|
const className = `${toPascalCase(appName)}View`;
|
|
182
238
|
return `class ${className} {
|
|
183
239
|
static home(_context, req, res, next) {
|
|
@@ -470,9 +526,9 @@ export default {
|
|
|
470
526
|
`;
|
|
471
527
|
}
|
|
472
528
|
|
|
473
|
-
export function renderAppRoutes(appName) {
|
|
529
|
+
export function renderAppRoutes(appName, sourceExtension = '.js') {
|
|
474
530
|
const viewClass = `${toPascalCase(appName)}View`;
|
|
475
|
-
return `import ${viewClass} from './views
|
|
531
|
+
return `import ${viewClass} from './views${sourceExtension}';
|
|
476
532
|
|
|
477
533
|
export default {
|
|
478
534
|
appName: ${JSON.stringify(appName)},
|
|
@@ -492,10 +548,10 @@ export default {
|
|
|
492
548
|
`;
|
|
493
549
|
}
|
|
494
550
|
|
|
495
|
-
export function renderAppModelTest(appName) {
|
|
551
|
+
export function renderAppModelTest(appName, sourceExtension = '.js') {
|
|
496
552
|
return `import test from 'node:test';
|
|
497
553
|
import assert from 'node:assert/strict';
|
|
498
|
-
import models from '../models
|
|
554
|
+
import models from '../models${sourceExtension}';
|
|
499
555
|
|
|
500
556
|
test('${appName} model exposes basic CRUD methods', async () => {
|
|
501
557
|
const Model = models[${JSON.stringify(appName)}];
|
|
@@ -517,10 +573,10 @@ test('${appName} model exposes basic CRUD methods', async () => {
|
|
|
517
573
|
`;
|
|
518
574
|
}
|
|
519
575
|
|
|
520
|
-
export function renderAppValidatorTest(appName) {
|
|
576
|
+
export function renderAppValidatorTest(appName, sourceExtension = '.js') {
|
|
521
577
|
return `import test from 'node:test';
|
|
522
578
|
import assert from 'node:assert/strict';
|
|
523
|
-
import validators from '../validators
|
|
579
|
+
import validators from '../validators${sourceExtension}';
|
|
524
580
|
|
|
525
581
|
test('${appName} validator validates id and payload', () => {
|
|
526
582
|
const Validator = validators[${JSON.stringify(appName)}];
|
|
@@ -537,10 +593,10 @@ test('${appName} validator validates id and payload', () => {
|
|
|
537
593
|
`;
|
|
538
594
|
}
|
|
539
595
|
|
|
540
|
-
export function renderAppServiceTest(appName) {
|
|
596
|
+
export function renderAppServiceTest(appName, sourceExtension = '.js') {
|
|
541
597
|
return `import test from 'node:test';
|
|
542
598
|
import assert from 'node:assert/strict';
|
|
543
|
-
import services from '../services
|
|
599
|
+
import services from '../services${sourceExtension}';
|
|
544
600
|
|
|
545
601
|
test('${appName} service delegates to model layer', async () => {
|
|
546
602
|
const Service = services[${JSON.stringify(appName)}];
|
|
@@ -580,10 +636,10 @@ test('${appName} service delegates to model layer', async () => {
|
|
|
580
636
|
`;
|
|
581
637
|
}
|
|
582
638
|
|
|
583
|
-
export function renderAppRoutesTest(appName) {
|
|
639
|
+
export function renderAppRoutesTest(appName, sourceExtension = '.js') {
|
|
584
640
|
return `import test from 'node:test';
|
|
585
641
|
import assert from 'node:assert/strict';
|
|
586
|
-
import routes from '../routes
|
|
642
|
+
import routes from '../routes${sourceExtension}';
|
|
587
643
|
|
|
588
644
|
test('${appName} routes register expected CRUD endpoints', () => {
|
|
589
645
|
const calls = [];
|
package/src/index.js
CHANGED
|
@@ -5,6 +5,7 @@ export { createLogger } from './runtime/logger.js';
|
|
|
5
5
|
export { deepMerge, normalizeApps } from './runtime/config.js';
|
|
6
6
|
export { createAuthManager, normalizeAuthConfig, createAuthGuard } from './runtime/auth.js';
|
|
7
7
|
export { createMailManager, normalizeMailConfig } from './runtime/mail.js';
|
|
8
|
+
export { registerTypeScriptRuntime } from './runtime/typescript.js';
|
|
8
9
|
export {
|
|
9
10
|
money,
|
|
10
11
|
number,
|
package/src/runtime/config.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
|
-
import {
|
|
3
|
+
import { resolveSourceFile, resolveSourceIndexFile } from '../utils/source-files.js';
|
|
4
|
+
import { importProjectModule } from './typescript.js';
|
|
4
5
|
|
|
5
6
|
const BASE_PROCESS_ENV = new Map(Object.entries(process.env));
|
|
6
7
|
const FRAMEWORK_LOADED_ENV_KEYS = new Set();
|
|
@@ -286,7 +287,7 @@ export function defaultConfig(rootDir) {
|
|
|
286
287
|
ddos: {
|
|
287
288
|
enabled: true,
|
|
288
289
|
windowMs: 60000,
|
|
289
|
-
maxRequests:
|
|
290
|
+
maxRequests: 300,
|
|
290
291
|
message: 'Too many requests, please try again later.',
|
|
291
292
|
statusCode: 429,
|
|
292
293
|
standardHeaders: true,
|
|
@@ -419,12 +420,11 @@ export function defaultConfig(rootDir) {
|
|
|
419
420
|
}
|
|
420
421
|
|
|
421
422
|
async function importDefaultIfExists(filePath) {
|
|
422
|
-
if (!fs.existsSync(filePath)) {
|
|
423
|
+
if (!filePath || !fs.existsSync(filePath)) {
|
|
423
424
|
return null;
|
|
424
425
|
}
|
|
425
426
|
|
|
426
|
-
const
|
|
427
|
-
const loaded = await import(moduleUrl);
|
|
427
|
+
const loaded = await importProjectModule(filePath);
|
|
428
428
|
return loaded?.default ?? null;
|
|
429
429
|
}
|
|
430
430
|
|
|
@@ -432,12 +432,12 @@ export async function loadProjectConfig(rootDir, logger = null) {
|
|
|
432
432
|
loadEnvironmentFiles(rootDir, logger);
|
|
433
433
|
const config = defaultConfig(rootDir);
|
|
434
434
|
|
|
435
|
-
const settingsFile = path.join(rootDir, 'settings
|
|
435
|
+
const settingsFile = resolveSourceFile(path.join(rootDir, 'settings'));
|
|
436
436
|
const settingsDir = path.join(rootDir, 'settings');
|
|
437
|
-
const indexFile =
|
|
438
|
-
const dbFile = path.join(settingsDir, 'db
|
|
439
|
-
const cacheFile = path.join(settingsDir, 'cache
|
|
440
|
-
const appsFile = path.join(settingsDir, 'apps
|
|
437
|
+
const indexFile = resolveSourceIndexFile(settingsDir);
|
|
438
|
+
const dbFile = resolveSourceFile(path.join(settingsDir, 'db'));
|
|
439
|
+
const cacheFile = resolveSourceFile(path.join(settingsDir, 'cache'));
|
|
440
|
+
const appsFile = resolveSourceFile(path.join(settingsDir, 'apps'));
|
|
441
441
|
|
|
442
442
|
const [settingsConfig, indexConfig, dbConfig, cacheConfig, appsConfig] = await Promise.all([
|
|
443
443
|
importDefaultIfExists(settingsFile),
|