@zintrust/core 0.4.11 → 0.4.13
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 +1 -1
- package/src/boot/registry/registerRoute.d.ts.map +1 -1
- package/src/boot/registry/registerRoute.js +1 -0
- package/src/cli/commands/StartCommand.d.ts.map +1 -1
- package/src/cli/commands/StartCommand.js +35 -4
- package/src/cli/utils/EnvFileLoader.d.ts +2 -0
- package/src/cli/utils/EnvFileLoader.d.ts.map +1 -1
- package/src/cli/utils/EnvFileLoader.js +85 -24
- package/src/index.js +3 -3
- package/src/runtime/PluginAutoImports.d.ts.map +1 -1
- package/src/runtime/PluginAutoImports.js +66 -29
- package/src/start.d.ts.map +1 -1
- package/src/start.js +63 -0
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registerRoute.d.ts","sourceRoot":"","sources":["../../../../src/boot/registry/registerRoute.ts"],"names":[],"mappings":"AAEA,OAAO,EAAU,KAAK,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAW3D,eAAO,MAAM,kBAAkB,QAAO,OAKrC,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAU,CAAC,EAAE,YAAY,MAAM,KAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAMpF,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAU,CAAC,EAAE,YAAY,MAAM,KAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAOrF,CAAC;
|
|
1
|
+
{"version":3,"file":"registerRoute.d.ts","sourceRoot":"","sources":["../../../../src/boot/registry/registerRoute.ts"],"names":[],"mappings":"AAEA,OAAO,EAAU,KAAK,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAW3D,eAAO,MAAM,kBAAkB,QAAO,OAKrC,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAU,CAAC,EAAE,YAAY,MAAM,KAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAMpF,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAU,CAAC,EAAE,YAAY,MAAM,KAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAOrF,CAAC;AA4FF,eAAO,MAAM,oBAAoB,GAC/B,kBAAkB,MAAM,EACxB,QAAQ,OAAO,KACd,OAAO,CAAC,IAAI,CAoBd,CAAC"}
|
|
@@ -64,6 +64,7 @@ const registerAppRoutes = async (resolvedBasePath, router) => {
|
|
|
64
64
|
}
|
|
65
65
|
};
|
|
66
66
|
const registerManifestRoutes = async (router) => {
|
|
67
|
+
await ProjectRuntime.tryLoadNodeRuntime();
|
|
67
68
|
const serviceManifest = ProjectRuntime.getServiceManifest();
|
|
68
69
|
if (serviceManifest.length === 0)
|
|
69
70
|
return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StartCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/StartCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoC,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"StartCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/StartCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoC,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAmvBvF,eAAO,MAAM,YAAY;cACb,YAAY;EAmCtB,CAAC"}
|
|
@@ -7,6 +7,7 @@ import * as Common from '../../common/index.js';
|
|
|
7
7
|
import { ErrorFactory } from '../../exceptions/ZintrustError.js';
|
|
8
8
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from '../../node-singletons/fs.js';
|
|
9
9
|
import * as path from '../../node-singletons/path.js';
|
|
10
|
+
const isAbsolutePath = (value) => value.startsWith('/') || /^[A-Za-z]:[\\/]/.test(value);
|
|
10
11
|
const resolveNpmPath = () => {
|
|
11
12
|
try {
|
|
12
13
|
return typeof Common.resolveNpmPath === 'function' ? Common.resolveNpmPath() : 'npm';
|
|
@@ -168,6 +169,26 @@ const resolveCacheEnabledPreference = (options) => {
|
|
|
168
169
|
return options.cache;
|
|
169
170
|
return undefined;
|
|
170
171
|
};
|
|
172
|
+
const resolveRootEnvPreference = (options) => {
|
|
173
|
+
const hasRootEnv = hasFlag('--root-env');
|
|
174
|
+
const hasNoRootEnv = hasFlag('--no-root-env');
|
|
175
|
+
if (hasRootEnv && hasNoRootEnv) {
|
|
176
|
+
throw ErrorFactory.createCliError('Error: Cannot use both --root-env and --no-root-env.');
|
|
177
|
+
}
|
|
178
|
+
if (hasRootEnv)
|
|
179
|
+
return true;
|
|
180
|
+
if (hasNoRootEnv)
|
|
181
|
+
return false;
|
|
182
|
+
if (typeof options.rootEnv === 'boolean')
|
|
183
|
+
return options.rootEnv;
|
|
184
|
+
return true;
|
|
185
|
+
};
|
|
186
|
+
const resolveEnvPath = (options, projectRoot) => {
|
|
187
|
+
const raw = typeof options.envPath === 'string' ? options.envPath.trim() : '';
|
|
188
|
+
if (raw === '')
|
|
189
|
+
return undefined;
|
|
190
|
+
return isAbsolutePath(raw) ? raw : path.join(projectRoot, raw);
|
|
191
|
+
};
|
|
171
192
|
const findNearestPackageJsonDir = (cwd) => {
|
|
172
193
|
let current = path.resolve(cwd);
|
|
173
194
|
while (true) {
|
|
@@ -210,9 +231,16 @@ const buildStartEnv = (projectRoot) => ({
|
|
|
210
231
|
...process.env,
|
|
211
232
|
ZINTRUST_PROJECT_ROOT: projectRoot,
|
|
212
233
|
});
|
|
213
|
-
const ensureStartEnvLoaded = (context) => {
|
|
214
|
-
const
|
|
215
|
-
|
|
234
|
+
const ensureStartEnvLoaded = (context, options) => {
|
|
235
|
+
const envPath = resolveEnvPath(options, context.projectRoot);
|
|
236
|
+
const rootEnv = resolveRootEnvPreference(options);
|
|
237
|
+
const extraCwds = envPath === undefined && context.cwd !== context.projectRoot ? [context.cwd] : [];
|
|
238
|
+
EnvFileLoader.ensureLoaded({
|
|
239
|
+
cwd: context.projectRoot,
|
|
240
|
+
includeCwd: rootEnv,
|
|
241
|
+
extraCwds,
|
|
242
|
+
...(envPath === undefined ? {} : { envPaths: [envPath] }),
|
|
243
|
+
});
|
|
216
244
|
};
|
|
217
245
|
const isFrameworkRepo = (packageJson) => packageJson.name === '@zintrust/core';
|
|
218
246
|
const hasDevScript = (packageJson) => {
|
|
@@ -483,7 +511,7 @@ const executeSplitStart = async (cmd, context, _options) => {
|
|
|
483
511
|
const executeStart = async (options, cmd) => {
|
|
484
512
|
const cwd = process.cwd();
|
|
485
513
|
const context = resolveStartContext(cwd);
|
|
486
|
-
ensureStartEnvLoaded(context);
|
|
514
|
+
ensureStartEnvLoaded(context, options);
|
|
487
515
|
const mode = resolveMode(options);
|
|
488
516
|
const port = resolvePort(options);
|
|
489
517
|
const runtime = resolveRuntime(options);
|
|
@@ -541,8 +569,11 @@ export const StartCommand = Object.freeze({
|
|
|
541
569
|
.option('--no-cache', 'Disable cache functionality')
|
|
542
570
|
.option('--watch', 'Force watch mode (Node only)')
|
|
543
571
|
.option('--no-watch', 'Disable watch mode (Node only)')
|
|
572
|
+
.option('--root-env', 'Load root project .env files for standalone service start')
|
|
573
|
+
.option('--no-root-env', 'Skip root project .env files for standalone service start')
|
|
544
574
|
.option('--mode <development|production|testing>', 'Override app mode')
|
|
545
575
|
.option('--env <name>', 'Wrangler environment name (Wrangler mode only)')
|
|
576
|
+
.option('--env-path <path>', 'Explicit env directory or .env file path for standalone service start')
|
|
546
577
|
.option('--wrangler-config <path>', 'Wrangler config path (Wrangler mode only)')
|
|
547
578
|
.option('--runtime <nodejs|cloudflare|lambda|deno|auto>', 'Set RUNTIME for spawned Node')
|
|
548
579
|
.option('-p, --port <number>', 'Override server port');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EnvFileLoader.d.ts","sourceRoot":"","sources":["../../../../src/cli/utils/EnvFileLoader.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"EnvFileLoader.d.ts","sourceRoot":"","sources":["../../../../src/cli/utils/EnvFileLoader.ts"],"names":[],"mappings":"AASA,KAAK,QAAQ,GAAG,aAAa,GAAG,YAAY,GAAG,SAAS,CAAC;AAmIzD,KAAK,WAAW,GAAG;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B,CAAC;AAEF,KAAK,SAAS,GAAG;IACf,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAaF,KAAK,YAAY,GAAG;IAClB,OAAO,CAAC,EAAE,QAAQ,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB,CAAC;AAgMF,eAAO,MAAM,aAAa;qBAjDH,WAAW,KAAQ,SAAS;6BAapB,IAAI,CAAC,WAAW,EAAE,kBAAkB,CAAC,KAAQ,SAAS;mCAG/C,YAAY,KAAG,IAAI;oBA+BpC,SAAS;EAO5B,CAAC"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Env } from '../../config/env.js';
|
|
2
|
+
import { isArray, isNonEmptyString } from '../../helper/index.js';
|
|
2
3
|
import { existsSync, readFileSync } from '../../node-singletons/fs.js';
|
|
3
|
-
import
|
|
4
|
+
import * as path from '../../node-singletons/path.js';
|
|
4
5
|
const safeEnvGet = (key, defaultValue = '') => {
|
|
5
6
|
const envAny = Env;
|
|
6
7
|
if (typeof envAny.get === 'function')
|
|
@@ -102,7 +103,7 @@ const applyToProcessEnv = (values, overrideExisting) => {
|
|
|
102
103
|
}
|
|
103
104
|
};
|
|
104
105
|
const readEnvFileIfExists = (cwd, filename) => {
|
|
105
|
-
const fullPath = join(cwd, filename);
|
|
106
|
+
const fullPath = path.join(cwd, filename);
|
|
106
107
|
if (!existsSync(fullPath))
|
|
107
108
|
return undefined;
|
|
108
109
|
const raw = readFileSync(fullPath, 'utf-8');
|
|
@@ -120,20 +121,20 @@ const resolveAppMode = (cwd) => {
|
|
|
120
121
|
};
|
|
121
122
|
const filesLoader = (cwd, mode) => {
|
|
122
123
|
const files = [];
|
|
123
|
-
if (existsSync(join(cwd, '.env')))
|
|
124
|
+
if (existsSync(path.join(cwd, '.env')))
|
|
124
125
|
files.push('.env');
|
|
125
126
|
// Per your rule: production uses .env; dev uses .env.dev
|
|
126
127
|
if (mode !== undefined && mode !== '' && mode !== 'production') {
|
|
127
128
|
const modeFile = `.env.${mode}`;
|
|
128
|
-
if (existsSync(join(cwd, modeFile)))
|
|
129
|
+
if (existsSync(path.join(cwd, modeFile)))
|
|
129
130
|
files.push(modeFile);
|
|
130
131
|
}
|
|
131
132
|
const local = '.env.local';
|
|
132
|
-
if (existsSync(join(cwd, local)))
|
|
133
|
+
if (existsSync(path.join(cwd, local)))
|
|
133
134
|
files.push(local);
|
|
134
135
|
if (mode !== undefined && mode !== '') {
|
|
135
136
|
const modeLocal = `.env.${mode}.local`;
|
|
136
|
-
if (existsSync(join(cwd, modeLocal)))
|
|
137
|
+
if (existsSync(path.join(cwd, modeLocal)))
|
|
137
138
|
files.push(modeLocal);
|
|
138
139
|
}
|
|
139
140
|
return files;
|
|
@@ -161,25 +162,85 @@ const loadFromCwd = (cwd, overrideExisting) => {
|
|
|
161
162
|
}
|
|
162
163
|
return { loadedFiles: files, mode };
|
|
163
164
|
};
|
|
164
|
-
const
|
|
165
|
-
if (
|
|
166
|
-
return
|
|
167
|
-
const
|
|
168
|
-
const
|
|
169
|
-
|
|
170
|
-
|
|
165
|
+
const loadFromFile = (filePath, overrideExisting) => {
|
|
166
|
+
if (!existsSync(filePath))
|
|
167
|
+
return { loadedFiles: [] };
|
|
168
|
+
const raw = readFileSync(filePath, 'utf-8');
|
|
169
|
+
const parsed = parseEnvFile(raw);
|
|
170
|
+
applyToProcessEnv(parsed, overrideExisting);
|
|
171
|
+
const rawMode = parsed['NODE_ENV'];
|
|
172
|
+
const mode = isNonEmptyString(rawMode) ? normalizeAppMode(rawMode) : undefined;
|
|
173
|
+
if (mode !== undefined) {
|
|
174
|
+
safeEnvSet('NODE_ENV', mode);
|
|
175
|
+
}
|
|
176
|
+
return { loadedFiles: [filePath], mode };
|
|
177
|
+
};
|
|
178
|
+
const normalizeCwdList = (value) => {
|
|
179
|
+
if (!isArray(value))
|
|
180
|
+
return [];
|
|
181
|
+
return value
|
|
182
|
+
.filter(isNonEmptyString)
|
|
183
|
+
.map((item) => item.trim())
|
|
184
|
+
.filter((item) => item !== '');
|
|
185
|
+
};
|
|
186
|
+
const normalizeEnvPathList = (value) => normalizeCwdList(value);
|
|
187
|
+
const createLoadPlan = (options) => {
|
|
188
|
+
const cwd = isNonEmptyString(options.cwd) ? options.cwd : process.cwd();
|
|
189
|
+
const includeCwd = options.includeCwd !== false;
|
|
190
|
+
const extraCwds = normalizeCwdList(options.extraCwds);
|
|
191
|
+
const envPaths = normalizeEnvPathList(options.envPaths);
|
|
171
192
|
const overrideExisting = options.overrideExisting ?? true;
|
|
172
|
-
const
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
193
|
+
const sources = [];
|
|
194
|
+
if (includeCwd) {
|
|
195
|
+
sources.push({
|
|
196
|
+
key: `cwd:${cwd}`,
|
|
197
|
+
path: cwd,
|
|
198
|
+
kind: 'cwd',
|
|
199
|
+
overrideExisting,
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
for (const extraCwd of extraCwds) {
|
|
203
|
+
sources.push({
|
|
204
|
+
key: `cwd:${extraCwd}`,
|
|
205
|
+
path: extraCwd,
|
|
206
|
+
kind: 'cwd',
|
|
207
|
+
overrideExisting: true,
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
for (const envPath of envPaths) {
|
|
211
|
+
const looksLikeFile = path.basename(envPath).startsWith('.env');
|
|
212
|
+
sources.push({
|
|
213
|
+
key: `${looksLikeFile ? 'file' : 'cwd'}:${envPath}`,
|
|
214
|
+
path: envPath,
|
|
215
|
+
kind: looksLikeFile ? 'file' : 'cwd',
|
|
216
|
+
overrideExisting: true,
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
return sources.filter((source, index, items) => items.findIndex((item) => item.key === source.key) === index);
|
|
220
|
+
};
|
|
221
|
+
const loadSource = (source) => {
|
|
222
|
+
if (source.kind === 'file')
|
|
223
|
+
return loadFromFile(source.path, source.overrideExisting);
|
|
224
|
+
return loadFromCwd(source.path, source.overrideExisting);
|
|
225
|
+
};
|
|
226
|
+
const mergeCachedState = (state, source, next) => {
|
|
227
|
+
state.loadedSourceKeys.push(source.key);
|
|
228
|
+
if (next.mode !== undefined && state.mode === undefined) {
|
|
229
|
+
state.mode = next.mode;
|
|
230
|
+
}
|
|
231
|
+
if (next.loadedFiles.length > 0) {
|
|
232
|
+
state.loadedFiles.push(...next.loadedFiles);
|
|
233
|
+
}
|
|
234
|
+
return state;
|
|
235
|
+
};
|
|
236
|
+
const load = (options = {}) => {
|
|
237
|
+
const plan = createLoadPlan(options);
|
|
238
|
+
cached ??= { loadedFiles: [], loadedSourceKeys: [] };
|
|
239
|
+
for (const source of plan) {
|
|
240
|
+
if (cached.loadedSourceKeys.includes(source.key))
|
|
241
|
+
continue;
|
|
242
|
+
mergeCachedState(cached, source, loadSource(source));
|
|
243
|
+
}
|
|
183
244
|
return cached;
|
|
184
245
|
};
|
|
185
246
|
const ensureLoaded = (options = {}) => load({ ...options, overrideExisting: false });
|
package/src/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @zintrust/core v0.4.
|
|
2
|
+
* @zintrust/core v0.4.13
|
|
3
3
|
*
|
|
4
4
|
* ZinTrust Framework - Production-Grade TypeScript Backend
|
|
5
5
|
* Built for performance, type safety, and exceptional developer experience
|
|
6
6
|
*
|
|
7
7
|
* Build Information:
|
|
8
|
-
* Built: 2026-03-
|
|
8
|
+
* Built: 2026-03-23T14:57:40.299Z
|
|
9
9
|
* Node: >=20.0.0
|
|
10
10
|
* License: MIT
|
|
11
11
|
*
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
* Available at runtime for debugging and health checks
|
|
22
22
|
*/
|
|
23
23
|
export const ZINTRUST_VERSION = '0.1.41';
|
|
24
|
-
export const ZINTRUST_BUILD_DATE = '2026-03-
|
|
24
|
+
export const ZINTRUST_BUILD_DATE = '2026-03-23T14:57:40.266Z'; // Replaced during build
|
|
25
25
|
export { Application } from './boot/Application.js';
|
|
26
26
|
export { AwsSigV4 } from './common/index.js';
|
|
27
27
|
export { SignedRequest } from './security/SignedRequest.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PluginAutoImports.d.ts","sourceRoot":"","sources":["../../../src/runtime/PluginAutoImports.ts"],"names":[],"mappings":"AAKA,OAAO,EAAmB,KAAK,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAEzF,KAAK,YAAY,GACb;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAChC;IACE,EAAE,EAAE,KAAK,CAAC;IACV,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,WAAW,GAAG,eAAe,CAAC;IACtC,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;
|
|
1
|
+
{"version":3,"file":"PluginAutoImports.d.ts","sourceRoot":"","sources":["../../../src/runtime/PluginAutoImports.ts"],"names":[],"mappings":"AAKA,OAAO,EAAmB,KAAK,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAEzF,KAAK,YAAY,GACb;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAChC;IACE,EAAE,EAAE,KAAK,CAAC;IACV,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,WAAW,GAAG,eAAe,CAAC;IACtC,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AA6MN,eAAO,MAAM,iBAAiB;uCACY,uBAAuB,GAAY,OAAO,CAAC,YAAY,CAAC;IAkBhG;;;;;;OAMG;mCACkC,OAAO,CAAC,YAAY,CAAC;qCAkEnB,MAAM,EAAE,GAAG,OAAO,CAAC,YAAY,CAAC;EAavE,CAAC"}
|
|
@@ -94,6 +94,47 @@ const resolveLocalPackageSpecifier = (specifier) => {
|
|
|
94
94
|
return null;
|
|
95
95
|
return pathToFileURL(resolved).href;
|
|
96
96
|
};
|
|
97
|
+
const isMissingPackageImport = (error, specifier) => {
|
|
98
|
+
if (specifier.startsWith('.'))
|
|
99
|
+
return false;
|
|
100
|
+
if (error === null || typeof error !== 'object')
|
|
101
|
+
return false;
|
|
102
|
+
const maybe = error;
|
|
103
|
+
const message = typeof maybe.message === 'string' ? maybe.message : '';
|
|
104
|
+
if (maybe.code === 'ERR_MODULE_NOT_FOUND' && message.length === 0)
|
|
105
|
+
return true;
|
|
106
|
+
if (maybe.code === 'ERR_MODULE_NOT_FOUND' && message.includes(specifier))
|
|
107
|
+
return true;
|
|
108
|
+
return (message.includes(`Cannot find package '${specifier}'`) ||
|
|
109
|
+
message.includes(`Cannot find module '${specifier}'`));
|
|
110
|
+
};
|
|
111
|
+
const getMissingPackageStatus = (error, specifier) => {
|
|
112
|
+
if (isMissingPackageImport(error, specifier)) {
|
|
113
|
+
Logger.debug('[plugins] Optional auto-import package not installed', {
|
|
114
|
+
specifier,
|
|
115
|
+
});
|
|
116
|
+
return 'missing';
|
|
117
|
+
}
|
|
118
|
+
return 'failed';
|
|
119
|
+
};
|
|
120
|
+
const importFromLocalFallback = async (specifier, fallback) => {
|
|
121
|
+
try {
|
|
122
|
+
await import(fallback);
|
|
123
|
+
Logger.debug('[plugins] Loaded auto-import specifier from local fallback', {
|
|
124
|
+
specifier,
|
|
125
|
+
fallback,
|
|
126
|
+
});
|
|
127
|
+
return 'loaded';
|
|
128
|
+
}
|
|
129
|
+
catch (fallbackError) {
|
|
130
|
+
Logger.debug('[plugins] Failed auto-import local fallback', {
|
|
131
|
+
specifier,
|
|
132
|
+
fallback,
|
|
133
|
+
error: fallbackError instanceof Error ? fallbackError.message : String(fallbackError),
|
|
134
|
+
});
|
|
135
|
+
return getMissingPackageStatus(fallbackError, specifier);
|
|
136
|
+
}
|
|
137
|
+
};
|
|
97
138
|
const importSingleSpecifier = async (entry) => {
|
|
98
139
|
const target = entry.specifier.startsWith('.')
|
|
99
140
|
? resolveRelativeSpecifier(entry)
|
|
@@ -101,52 +142,48 @@ const importSingleSpecifier = async (entry) => {
|
|
|
101
142
|
try {
|
|
102
143
|
await import(target);
|
|
103
144
|
Logger.debug('[plugins] Loaded auto-import specifier', { specifier: entry.specifier });
|
|
104
|
-
return
|
|
145
|
+
return 'loaded';
|
|
105
146
|
}
|
|
106
|
-
catch {
|
|
147
|
+
catch (error) {
|
|
107
148
|
const fallback = resolveLocalPackageSpecifier(entry.specifier);
|
|
108
|
-
if (fallback !== null)
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
Logger.debug('[plugins] Loaded auto-import specifier from local fallback', {
|
|
112
|
-
specifier: entry.specifier,
|
|
113
|
-
fallback,
|
|
114
|
-
});
|
|
115
|
-
return true;
|
|
116
|
-
}
|
|
117
|
-
catch (fallbackError) {
|
|
118
|
-
Logger.debug('[plugins] Failed auto-import local fallback', {
|
|
119
|
-
specifier: entry.specifier,
|
|
120
|
-
fallback,
|
|
121
|
-
error: fallbackError instanceof Error ? fallbackError.message : String(fallbackError),
|
|
122
|
-
});
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
return false;
|
|
149
|
+
if (fallback !== null)
|
|
150
|
+
return importFromLocalFallback(entry.specifier, fallback);
|
|
151
|
+
return getMissingPackageStatus(error, entry.specifier);
|
|
126
152
|
}
|
|
127
153
|
};
|
|
128
154
|
const importSpecifiers = async (specifiers) => {
|
|
129
155
|
// Import all specifiers in parallel
|
|
130
156
|
const importPromises = Array.from(specifiers).map(async (entry) => {
|
|
131
|
-
const
|
|
132
|
-
return { specifier: entry.specifier,
|
|
157
|
+
const status = await importSingleSpecifier(entry);
|
|
158
|
+
return { specifier: entry.specifier, status };
|
|
133
159
|
});
|
|
134
160
|
const results = await Promise.allSettled(importPromises);
|
|
135
|
-
|
|
136
|
-
|
|
161
|
+
return results.reduce((summary, result) => {
|
|
162
|
+
if (result.status !== 'fulfilled') {
|
|
163
|
+
summary.failed += 1;
|
|
164
|
+
return summary;
|
|
165
|
+
}
|
|
166
|
+
if (result.value.status === 'loaded')
|
|
167
|
+
summary.loaded += 1;
|
|
168
|
+
else if (result.value.status === 'missing')
|
|
169
|
+
summary.missing += 1;
|
|
170
|
+
else
|
|
171
|
+
summary.failed += 1;
|
|
172
|
+
return summary;
|
|
173
|
+
}, { loaded: 0, missing: 0, failed: 0 });
|
|
137
174
|
};
|
|
138
175
|
export const PluginAutoImports = Object.freeze({
|
|
139
176
|
async tryImportRuntimeAutoImports(mode = 'base') {
|
|
140
177
|
const specifiers = OfficialPlugins.getAutoImports(mode);
|
|
141
|
-
const
|
|
142
|
-
if (
|
|
178
|
+
const summary = await importSpecifiers(specifiers.map((specifier) => ({ specifier, filePath: `official:${mode}` })));
|
|
179
|
+
if (summary.failed === 0) {
|
|
143
180
|
return { ok: true, loadedPath: `official:${mode}` };
|
|
144
181
|
}
|
|
145
182
|
return {
|
|
146
183
|
ok: false,
|
|
147
184
|
loadedPath: `official:${mode}`,
|
|
148
185
|
reason: 'import-failed',
|
|
149
|
-
errorMessage: `Loaded ${loaded}/${specifiers.length} official plugin imports`,
|
|
186
|
+
errorMessage: `Loaded ${summary.loaded}/${specifiers.length} official plugin imports`,
|
|
150
187
|
};
|
|
151
188
|
},
|
|
152
189
|
/**
|
|
@@ -209,8 +246,8 @@ export const PluginAutoImports = Object.freeze({
|
|
|
209
246
|
if (specifiers.length === 0) {
|
|
210
247
|
return { ok: false, reason: 'import-failed', errorMessage: 'No import specifiers found' };
|
|
211
248
|
}
|
|
212
|
-
const
|
|
213
|
-
if (loaded > 0) {
|
|
249
|
+
const summary = await importSpecifiers(specifiers);
|
|
250
|
+
if (summary.loaded > 0) {
|
|
214
251
|
return { ok: true, loadedPath: 'manual-imports' };
|
|
215
252
|
}
|
|
216
253
|
return { ok: false, reason: 'import-failed', errorMessage: 'All specifier imports failed' };
|
package/src/start.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../../src/start.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../../src/start.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,gCAAgC,CAAC;AAuBxC,eAAO,MAAM,UAAU,GAAI,eAAe,MAAM,KAAG,OAYlD,CAAC;AAEF,eAAO,MAAM,0BAA0B,GAAI,eAAe,OAAO,KAAG,oBASnE,CAAC;AAqFF,eAAO,MAAM,qBAAqB,GAChC,eAAe,MAAM,EACrB,eAAe,OAAO,KACrB,OAAO,CAAC,oBAAoB,CAS9B,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,KAAK,QAAa,OAAO,CAAC,IAAI,CAO1C,CAAC;AAEF;;GAEG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAEhD,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEpE;;GAEG;AACH,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAElD;;GAEG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC"}
|
package/src/start.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { ErrorFactory } from './exceptions/ZintrustError.js';
|
|
2
|
+
import { isArray, isNonEmptyString, isObject } from './helper/index.js';
|
|
2
3
|
import { ZintrustLang } from './lang/lang.js';
|
|
3
4
|
import { normalizeActiveServiceRuntime, } from './microservices/ServiceManifest.js';
|
|
4
5
|
import { ProjectRuntime } from './runtime/ProjectRuntime.js';
|
|
5
6
|
import { isNodeRuntime } from './runtime/detectRuntime.js';
|
|
7
|
+
const isAbsolutePath = (value) => value.startsWith('/') || /^[A-Za-z]:[\\/]/.test(value);
|
|
6
8
|
const fileUrlToPathLike = (value) => {
|
|
7
9
|
if (!value.startsWith(ZintrustLang.FILE_PROTOCOL))
|
|
8
10
|
return value;
|
|
@@ -34,7 +36,68 @@ export const configureStandaloneService = (activeService) => {
|
|
|
34
36
|
}
|
|
35
37
|
return ProjectRuntime.set({ activeService: normalized }).activeService ?? normalized;
|
|
36
38
|
};
|
|
39
|
+
const normalizeStandaloneEnvPaths = (value) => {
|
|
40
|
+
if (isNonEmptyString(value)) {
|
|
41
|
+
const trimmed = value.trim();
|
|
42
|
+
return trimmed === '' ? [] : [trimmed];
|
|
43
|
+
}
|
|
44
|
+
if (!isArray(value))
|
|
45
|
+
return [];
|
|
46
|
+
return value
|
|
47
|
+
.filter(isNonEmptyString)
|
|
48
|
+
.map((item) => item.trim())
|
|
49
|
+
.filter((item) => item !== '');
|
|
50
|
+
};
|
|
51
|
+
const resolveStandaloneProjectRoot = async () => {
|
|
52
|
+
const configuredRoot = process.env?.['ZINTRUST_PROJECT_ROOT'] ?? '';
|
|
53
|
+
if (isNonEmptyString(configuredRoot))
|
|
54
|
+
return configuredRoot;
|
|
55
|
+
const { existsSync } = await import('./node-singletons/fs.js');
|
|
56
|
+
const path = await import('./node-singletons/path.js');
|
|
57
|
+
let current = process.cwd();
|
|
58
|
+
while (true) {
|
|
59
|
+
if (existsSync(path.join(current, 'package.json')))
|
|
60
|
+
return current;
|
|
61
|
+
const parent = path.dirname(current);
|
|
62
|
+
if (parent === current)
|
|
63
|
+
return process.cwd();
|
|
64
|
+
current = parent;
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
const resolveServiceEnvPath = async (importMetaUrl, activeService, projectRoot) => {
|
|
68
|
+
const path = await import('./node-singletons/path.js');
|
|
69
|
+
if (isObject(activeService) && isNonEmptyString(activeService['configRoot'])) {
|
|
70
|
+
return path.dirname(path.join(projectRoot, activeService['configRoot']));
|
|
71
|
+
}
|
|
72
|
+
const entryFile = fileUrlToPathLike(importMetaUrl);
|
|
73
|
+
const entryDir = path.dirname(entryFile);
|
|
74
|
+
return path.basename(entryDir) === 'src' ? path.dirname(entryDir) : entryDir;
|
|
75
|
+
};
|
|
76
|
+
const resolveConfiguredEnvPaths = async (projectRoot, activeService, importMetaUrl) => {
|
|
77
|
+
const path = await import('./node-singletons/path.js');
|
|
78
|
+
const configured = isObject(activeService)
|
|
79
|
+
? normalizeStandaloneEnvPaths(activeService['envPath'])
|
|
80
|
+
: [];
|
|
81
|
+
if (configured.length > 0) {
|
|
82
|
+
return configured.map((value) => isAbsolutePath(value) ? value : path.join(projectRoot, value));
|
|
83
|
+
}
|
|
84
|
+
return [await resolveServiceEnvPath(importMetaUrl, activeService, projectRoot)];
|
|
85
|
+
};
|
|
86
|
+
const ensureStandaloneServiceEnv = async (importMetaUrl, activeService) => {
|
|
87
|
+
if (!isNodeRuntime())
|
|
88
|
+
return;
|
|
89
|
+
const { EnvFileLoader } = await import('./cli/utils/EnvFileLoader.js');
|
|
90
|
+
const projectRoot = await resolveStandaloneProjectRoot();
|
|
91
|
+
const envPaths = await resolveConfiguredEnvPaths(projectRoot, activeService, importMetaUrl);
|
|
92
|
+
const rootEnv = !isObject(activeService) || activeService['rootEnv'] !== false;
|
|
93
|
+
EnvFileLoader.ensureLoaded({
|
|
94
|
+
cwd: projectRoot,
|
|
95
|
+
includeCwd: rootEnv,
|
|
96
|
+
envPaths,
|
|
97
|
+
});
|
|
98
|
+
};
|
|
37
99
|
export const bootStandaloneService = async (importMetaUrl, activeService) => {
|
|
100
|
+
await ensureStandaloneServiceEnv(importMetaUrl, activeService);
|
|
38
101
|
const configuredService = configureStandaloneService(activeService);
|
|
39
102
|
if (isNodeMain(importMetaUrl)) {
|
|
40
103
|
await start();
|