@zintrust/core 0.5.9 → 0.7.2
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 +7 -5
- package/src/auth/LoginFlow.d.ts +65 -0
- package/src/auth/LoginFlow.d.ts.map +1 -0
- package/src/auth/LoginFlow.js +352 -0
- package/src/cache/drivers/KVRemoteDriver.d.ts.map +1 -1
- package/src/cache/drivers/KVRemoteDriver.js +9 -3
- package/src/cli/commands/MigrateCommand.js +1 -1
- package/src/cli/commands/ScheduleListCommand.d.ts.map +1 -1
- package/src/cli/commands/ScheduleListCommand.js +3 -0
- package/src/cli/commands/ScheduleRunCommand.d.ts.map +1 -1
- package/src/cli/commands/ScheduleRunCommand.js +3 -0
- package/src/cli/commands/ScheduleStartCommand.d.ts.map +1 -1
- package/src/cli/commands/ScheduleStartCommand.js +3 -0
- package/src/cli/commands/schedule/ScheduleCliSupport.d.ts +1 -0
- package/src/cli/commands/schedule/ScheduleCliSupport.d.ts.map +1 -1
- package/src/cli/commands/schedule/ScheduleCliSupport.js +116 -6
- package/src/cli/scaffolding/GovernanceScaffolder.d.ts.map +1 -1
- package/src/cli/scaffolding/GovernanceScaffolder.js +22 -3
- package/src/cli/scaffolding/MigrationGenerator.d.ts.map +1 -1
- package/src/cli/scaffolding/MigrationGenerator.js +2 -1
- package/src/cli/scaffolding/ProjectScaffolder.d.ts.map +1 -1
- package/src/cli/scaffolding/ProjectScaffolder.js +79 -8
- package/src/cli/scaffolding/ScaffoldingVersionUtils.js +1 -1
- package/src/common/ContextLoader.d.ts +27 -0
- package/src/common/ContextLoader.d.ts.map +1 -0
- package/src/common/ContextLoader.js +187 -0
- package/src/config/logger.d.ts +2 -0
- package/src/config/logger.d.ts.map +1 -1
- package/src/config/logger.js +12 -0
- package/src/index.d.ts +7 -0
- package/src/index.d.ts.map +1 -1
- package/src/index.js +7 -3
- package/src/orm/Model.d.ts.map +1 -1
- package/src/orm/Model.js +33 -1
- package/src/orm/adapters/D1Adapter.d.ts.map +1 -1
- package/src/orm/adapters/D1Adapter.js +1 -1
- package/src/orm/adapters/MySQLAdapter.d.ts.map +1 -1
- package/src/orm/adapters/MySQLAdapter.js +1 -1
- package/src/orm/adapters/MySQLProxyAdapter.d.ts.map +1 -1
- package/src/orm/adapters/MySQLProxyAdapter.js +11 -9
- package/src/orm/adapters/PostgreSQLAdapter.js +1 -1
- package/src/orm/adapters/SQLServerAdapter.d.ts.map +1 -1
- package/src/orm/adapters/SQLServerAdapter.js +1 -1
- package/src/orm/adapters/SQLiteAdapter.js +1 -1
- package/src/proxy/ProxyServerUtils.d.ts.map +1 -1
- package/src/proxy/ProxyServerUtils.js +15 -11
- package/src/security/SecurePayload.d.ts +38 -0
- package/src/security/SecurePayload.d.ts.map +1 -0
- package/src/security/SecurePayload.js +214 -0
- package/src/templates/project/basic/app/Controllers/AuthController.ts.tpl +132 -46
- package/src/templates/project/basic/package.json.tpl +6 -2
- package/src/tools/notification/Composer.d.ts +40 -0
- package/src/tools/notification/Composer.d.ts.map +1 -0
- package/src/tools/notification/Composer.js +140 -0
- package/src/tools/notification/Notification.d.ts +6 -0
- package/src/tools/notification/Notification.d.ts.map +1 -1
- package/src/tools/notification/Notification.js +7 -0
- package/src/tools/queue/AdvancedQueue.js +15 -0
- package/src/tools/queue/Queue.d.ts +1 -0
- package/src/tools/queue/Queue.d.ts.map +1 -1
- package/src/types/Queue.d.ts +1 -0
- package/src/types/Queue.d.ts.map +1 -1
- package/src/zintrust.comon.d.ts +0 -11
- package/src/zintrust.comon.d.ts.map +0 -1
- package/src/zintrust.comon.js +0 -17
|
@@ -1,25 +1,133 @@
|
|
|
1
|
+
import { SpawnUtil } from '../../utils/spawn.js';
|
|
1
2
|
import { databaseConfig } from '../../../config/database.js';
|
|
3
|
+
import { ErrorFactory } from '../../../exceptions/ZintrustError.js';
|
|
4
|
+
import { existsSync } from '../../../node-singletons/fs.js';
|
|
5
|
+
import path from '../../../node-singletons/path.js';
|
|
2
6
|
import { registerDatabasesFromRuntimeConfig } from '../../../orm/DatabaseRuntimeRegistration.js';
|
|
7
|
+
import { ensureNodeStartupEnvLoaded } from '../../../runtime/NodeStartup.js';
|
|
8
|
+
import { resolveNodeProjectRoot } from '../../../runtime/resolveNodeProjectRoot.js';
|
|
9
|
+
import useFileLoader from '../../../runtime/useFileLoader.js';
|
|
3
10
|
import { SchedulerRuntime } from '../../../scheduler/SchedulerRuntime.js';
|
|
11
|
+
const SOURCE_REENTRY_ENV = 'ZINTRUST_SCHEDULE_CLI_SOURCE_REENTRY';
|
|
4
12
|
const isSchedule = (value) => {
|
|
5
13
|
if (value === undefined || value === null || typeof value !== 'object')
|
|
6
14
|
return false;
|
|
7
15
|
return 'name' in value && typeof value.name === 'string';
|
|
8
16
|
};
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
17
|
+
const getProjectScheduleLoaders = () => [
|
|
18
|
+
useFileLoader('app/Schedules/index.ts'),
|
|
19
|
+
useFileLoader('app/Schedules.ts'),
|
|
20
|
+
];
|
|
21
|
+
const isTypeScriptFile = (filePath) => {
|
|
22
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
23
|
+
return ext === '.ts' || ext === '.tsx' || ext === '.mts';
|
|
24
|
+
};
|
|
25
|
+
const getProjectSourceCliEntry = (projectRoot) => {
|
|
26
|
+
const candidates = [
|
|
27
|
+
path.join(projectRoot, 'bin', 'zin.ts'),
|
|
28
|
+
path.join(projectRoot, 'bin', 'zintrust.ts'),
|
|
29
|
+
];
|
|
30
|
+
for (const candidate of candidates) {
|
|
31
|
+
if (existsSync(candidate))
|
|
32
|
+
return candidate;
|
|
33
|
+
}
|
|
34
|
+
return undefined;
|
|
35
|
+
};
|
|
36
|
+
const isRunningProjectSourceCli = (projectRoot) => {
|
|
37
|
+
const script = String(process.argv[1] ?? '').trim();
|
|
38
|
+
if (script.length === 0)
|
|
39
|
+
return false;
|
|
40
|
+
const resolvedScript = path.resolve(script);
|
|
41
|
+
const sourceCliEntry = getProjectSourceCliEntry(projectRoot);
|
|
42
|
+
if (sourceCliEntry === undefined)
|
|
43
|
+
return false;
|
|
44
|
+
return resolvedScript === path.resolve(sourceCliEntry);
|
|
45
|
+
};
|
|
46
|
+
const getExistingProjectSchedulePath = () => {
|
|
47
|
+
for (const loader of getProjectScheduleLoaders()) {
|
|
48
|
+
if (loader.exists())
|
|
49
|
+
return loader.path();
|
|
50
|
+
}
|
|
51
|
+
return undefined;
|
|
52
|
+
};
|
|
53
|
+
const tryLoadProjectScheduleModuleFromFiles = async () => {
|
|
54
|
+
const existingLoaders = getProjectScheduleLoaders()
|
|
55
|
+
.filter((loader) => loader.exists())
|
|
56
|
+
.map((loader) => ({ loader, loadedPath: loader.path() }));
|
|
57
|
+
const tryAt = async (index, firstError) => {
|
|
58
|
+
const entry = existingLoaders[index];
|
|
59
|
+
if (entry === undefined) {
|
|
60
|
+
if (existingLoaders.length > 0 && firstError !== undefined)
|
|
61
|
+
throw firstError;
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
64
|
+
try {
|
|
65
|
+
return {
|
|
66
|
+
module: await entry.loader.get(),
|
|
67
|
+
loadedPath: entry.loadedPath,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
return tryAt(index + 1, firstError ?? error);
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
return tryAt(0);
|
|
75
|
+
};
|
|
76
|
+
const loadAppScheduleModule = async () => {
|
|
12
77
|
try {
|
|
13
|
-
|
|
78
|
+
return {
|
|
79
|
+
module: (await import('../../../../app/Schedules/index.js')),
|
|
80
|
+
};
|
|
14
81
|
}
|
|
15
82
|
catch {
|
|
16
|
-
|
|
83
|
+
const fileLoaded = await tryLoadProjectScheduleModuleFromFiles();
|
|
84
|
+
return fileLoaded ?? { module: {} };
|
|
17
85
|
}
|
|
86
|
+
};
|
|
87
|
+
const loadScheduleModules = async () => {
|
|
88
|
+
const coreSchedules = await import('../../../schedules/index.js');
|
|
89
|
+
const appSchedules = await loadAppScheduleModule();
|
|
18
90
|
return {
|
|
19
91
|
core: Object.values(coreSchedules).filter(isSchedule),
|
|
20
|
-
app: Object.values(appSchedules).filter(isSchedule),
|
|
92
|
+
app: Object.values(appSchedules.module).filter(isSchedule),
|
|
21
93
|
};
|
|
22
94
|
};
|
|
95
|
+
const ensureProjectSourceContext = async () => {
|
|
96
|
+
await ensureNodeStartupEnvLoaded({ entry: 'schedule-cli' });
|
|
97
|
+
const projectRoot = await resolveNodeProjectRoot();
|
|
98
|
+
if ((process.env['ZINTRUST_PROJECT_ROOT'] ?? '').trim() === '') {
|
|
99
|
+
process.env['ZINTRUST_PROJECT_ROOT'] = projectRoot;
|
|
100
|
+
}
|
|
101
|
+
const existingSchedulePath = getExistingProjectSchedulePath();
|
|
102
|
+
if (existingSchedulePath === undefined || !isTypeScriptFile(existingSchedulePath)) {
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
if (String(process.env[SOURCE_REENTRY_ENV] ?? '') === '1') {
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
if (isRunningProjectSourceCli(projectRoot)) {
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
const sourceCliEntry = getProjectSourceCliEntry(projectRoot);
|
|
112
|
+
if (sourceCliEntry === undefined) {
|
|
113
|
+
throw ErrorFactory.createCliError('Source schedules require a project CLI entrypoint at bin/zin.ts or bin/zintrust.ts');
|
|
114
|
+
}
|
|
115
|
+
const relativeSourceCliEntry = path.relative(projectRoot, sourceCliEntry);
|
|
116
|
+
const exitCode = await SpawnUtil.spawnAndWait({
|
|
117
|
+
command: 'tsx',
|
|
118
|
+
args: [relativeSourceCliEntry, ...process.argv.slice(2)],
|
|
119
|
+
cwd: projectRoot,
|
|
120
|
+
env: {
|
|
121
|
+
...process.env,
|
|
122
|
+
ZINTRUST_PROJECT_ROOT: projectRoot,
|
|
123
|
+
[SOURCE_REENTRY_ENV]: '1',
|
|
124
|
+
},
|
|
125
|
+
});
|
|
126
|
+
if (exitCode !== 0) {
|
|
127
|
+
throw ErrorFactory.createCliError(`Failed to execute schedule command via project source CLI (exit ${exitCode})`);
|
|
128
|
+
}
|
|
129
|
+
return true;
|
|
130
|
+
};
|
|
23
131
|
const shutdownCliResources = async () => {
|
|
24
132
|
try {
|
|
25
133
|
const mod = await import('../../../orm/ConnectionManager.js');
|
|
@@ -44,7 +152,9 @@ const shutdownCliResources = async () => {
|
|
|
44
152
|
}
|
|
45
153
|
};
|
|
46
154
|
export const ScheduleCliSupport = Object.freeze({
|
|
155
|
+
ensureProjectSourceContext,
|
|
47
156
|
async registerAll() {
|
|
157
|
+
await ensureNodeStartupEnvLoaded({ entry: 'schedule-cli' });
|
|
48
158
|
registerDatabasesFromRuntimeConfig(databaseConfig);
|
|
49
159
|
const modules = await loadScheduleModules();
|
|
50
160
|
SchedulerRuntime.registerMany(modules.core, 'core');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GovernanceScaffolder.d.ts","sourceRoot":"","sources":["../../../../src/cli/scaffolding/GovernanceScaffolder.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAqBH,MAAM,MAAM,yBAAyB,GAAG,QAAQ,CAAC;IAC/C,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC,CAAC;AAEH,MAAM,MAAM,wBAAwB,GAAG,QAAQ,CAAC;IAC9C,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"GovernanceScaffolder.d.ts","sourceRoot":"","sources":["../../../../src/cli/scaffolding/GovernanceScaffolder.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAqBH,MAAM,MAAM,yBAAyB,GAAG,QAAQ,CAAC;IAC/C,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC,CAAC;AAEH,MAAM,MAAM,wBAAwB,GAAG,QAAQ,CAAC;IAC9C,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC,CAAC;AA2TH,eAAO,MAAM,oBAAoB;0BAEhB,MAAM,YACV,yBAAyB,GACjC,OAAO,CAAC,wBAAwB,CAAC;EA+DpC,CAAC;AAEH,eAAe,oBAAoB,CAAC"}
|
|
@@ -51,17 +51,36 @@ const ensureDevDependency = (devDependencies, name, version) => {
|
|
|
51
51
|
devDependencies[name] = version;
|
|
52
52
|
}
|
|
53
53
|
};
|
|
54
|
+
const getBundledGovernanceVersion = () => {
|
|
55
|
+
try {
|
|
56
|
+
const pkgUrl = new URL('../../../packages/governance/package.json', import.meta.url);
|
|
57
|
+
const raw = FileGenerator.readFile(pkgUrl.toString());
|
|
58
|
+
const parsed = JSON.parse(raw);
|
|
59
|
+
return typeof parsed.version === 'string' && parsed.version.trim() !== ''
|
|
60
|
+
? toCompatibleGovernanceVersion(parsed.version)
|
|
61
|
+
: undefined;
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
return undefined;
|
|
65
|
+
}
|
|
66
|
+
};
|
|
54
67
|
const inferGovernanceVersion = (pkg) => {
|
|
68
|
+
const devDeps = getStringRecord(pkg.devDependencies);
|
|
69
|
+
const existingGovernance = devDeps?.['@zintrust/governance'];
|
|
70
|
+
if (typeof existingGovernance === 'string' && existingGovernance.trim() !== '') {
|
|
71
|
+
return existingGovernance;
|
|
72
|
+
}
|
|
55
73
|
const deps = getStringRecord(pkg.dependencies);
|
|
56
74
|
const core = deps?.['@zintrust/core'];
|
|
75
|
+
const bundledGovernanceVersion = getBundledGovernanceVersion();
|
|
57
76
|
if (typeof core === 'string' && core.trim() !== '') {
|
|
58
|
-
return toCompatibleGovernanceVersion(core);
|
|
77
|
+
return bundledGovernanceVersion ?? toCompatibleGovernanceVersion(core);
|
|
59
78
|
}
|
|
60
79
|
const currentVersion = VersionChecker.getCurrentVersion().trim();
|
|
61
80
|
if (currentVersion !== '' && currentVersion !== '0.0.0') {
|
|
62
|
-
return toCompatibleGovernanceVersion(currentVersion);
|
|
81
|
+
return bundledGovernanceVersion ?? toCompatibleGovernanceVersion(currentVersion);
|
|
63
82
|
}
|
|
64
|
-
return '^0.4.0';
|
|
83
|
+
return bundledGovernanceVersion ?? '^0.4.0';
|
|
65
84
|
};
|
|
66
85
|
const writeEslintConfig = (projectRoot) => {
|
|
67
86
|
const eslintConfigPath = path.join(projectRoot, 'eslint.config.mjs');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MigrationGenerator.d.ts","sourceRoot":"","sources":["../../../../src/cli/scaffolding/MigrationGenerator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAC;AAExD,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,gBAAgB,GAAG;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAmB/F;AAED;;GAEG;AAEH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAwE7F;
|
|
1
|
+
{"version":3,"file":"MigrationGenerator.d.ts","sourceRoot":"","sources":["../../../../src/cli/scaffolding/MigrationGenerator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAC;AAExD,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,gBAAgB,GAAG;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAmB/F;AAED;;GAEG;AAEH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAwE7F;AAqRD;;GAEG;AACH,eAAO,MAAM,kBAAkB;;;EAG7B,CAAC"}
|
|
@@ -146,6 +146,7 @@ function generateMigrationContent(options) {
|
|
|
146
146
|
}
|
|
147
147
|
}
|
|
148
148
|
function resolveMigrationImportBlock(migrationsPath) {
|
|
149
|
+
const coreImportSpecifier = ['@zintrust', 'core'].join('/');
|
|
149
150
|
const projectRoot = path.resolve(migrationsPath, '..', '..');
|
|
150
151
|
const packageJsonPath = path.join(projectRoot, 'package.json');
|
|
151
152
|
if (FileGenerator.fileExists(packageJsonPath)) {
|
|
@@ -160,7 +161,7 @@ function resolveMigrationImportBlock(migrationsPath) {
|
|
|
160
161
|
// fall through
|
|
161
162
|
}
|
|
162
163
|
}
|
|
163
|
-
return `import { MigrationSchema, type Blueprint, type IDatabase } from '
|
|
164
|
+
return `import { MigrationSchema, type Blueprint, type IDatabase } from '${coreImportSpecifier}';`;
|
|
164
165
|
}
|
|
165
166
|
/**
|
|
166
167
|
* Generate CREATE migration
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProjectScaffolder.d.ts","sourceRoot":"","sources":["../../../../src/cli/scaffolding/ProjectScaffolder.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"ProjectScaffolder.d.ts","sourceRoot":"","sources":["../../../../src/cli/scaffolding/ProjectScaffolder.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAgBH,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,cAAc,GAAG,sBAAsB,CAAC;AAEpD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/B;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,KAAK,CAAC;CACf;AAED,MAAM,WAAW,kBAAkB;IACjC,cAAc,CAAC,OAAO,EAAE,sBAAsB,GAAG,IAAI,CAAC;IACtD,YAAY,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC,eAAe,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAAC;IACpE,cAAc,IAAI,MAAM,CAAC;IACzB,sBAAsB,IAAI,OAAO,CAAC;IAClC,iBAAiB,IAAI,MAAM,CAAC;IAC5B,WAAW,CAAC,OAAO,CAAC,EAAE,sBAAsB,GAAG,MAAM,CAAC;IACtD,gBAAgB,IAAI,OAAO,CAAC;IAC5B,aAAa,IAAI,OAAO,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAAC;CAC3E;AA0kBD,wBAAgB,qBAAqB,IAAI,MAAM,EAAE,CAEhD;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAsBrE;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,sBAAsB,GAAG;IAChE,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,CAsBA;AA8ID;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,WAAW,GAAE,MAAsB,GAAG,kBAAkB,CAsB/F;AAED,wBAAsB,eAAe,CACnC,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,qBAAqB,CAAC,CAEhC;AAED;;GAEG;AACH,eAAO,MAAM,iBAAiB;;;;;;EAM5B,CAAC"}
|
|
@@ -4,22 +4,93 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { EnvFileBackfill } from '../env/EnvFileBackfill.js';
|
|
6
6
|
import { EnvData } from '../scaffolding/env.js';
|
|
7
|
-
import { toCompatibleGovernanceVersion } from '../scaffolding/ScaffoldingVersionUtils.js';
|
|
7
|
+
import { extractMajorMinorVersion, toCompatibleGovernanceVersion, } from '../scaffolding/ScaffoldingVersionUtils.js';
|
|
8
8
|
import { Logger } from '../../config/logger.js';
|
|
9
9
|
import { ErrorFactory } from '../../exceptions/ZintrustError.js';
|
|
10
10
|
import { randomBytes } from '../../node-singletons/crypto.js';
|
|
11
11
|
import fs from '../../node-singletons/fs.js';
|
|
12
12
|
import * as path from '../../node-singletons/path.js';
|
|
13
13
|
import { fileURLToPath } from '../../node-singletons/url.js';
|
|
14
|
-
|
|
14
|
+
import { execFileSync } from 'node:child_process';
|
|
15
|
+
const readBundledGovernancePackage = () => {
|
|
15
16
|
try {
|
|
16
|
-
const packageUrl = new URL('../../../package.json', import.meta.url);
|
|
17
|
-
|
|
18
|
-
return typeof packageJson.version === 'string' ? packageJson.version : '0.0.0';
|
|
17
|
+
const packageUrl = new URL('../../../packages/governance/package.json', import.meta.url);
|
|
18
|
+
return JSON.parse(fs.readFileSync(packageUrl, 'utf-8'));
|
|
19
19
|
}
|
|
20
20
|
catch {
|
|
21
|
-
return
|
|
21
|
+
return undefined;
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
const SAFE_PATH = '/usr/local/bin:/usr/bin:/bin';
|
|
25
|
+
const NPM_VIEW_TIMEOUT_MS = 1500;
|
|
26
|
+
const publishedVersionCache = new Map();
|
|
27
|
+
const createSafeNpmEnv = () => ({
|
|
28
|
+
...process.env,
|
|
29
|
+
NODE_ENV: process.env['NODE_ENV'] ?? 'development',
|
|
30
|
+
PATH: SAFE_PATH,
|
|
31
|
+
});
|
|
32
|
+
const loadPublishedNpmVersion = (packageName) => {
|
|
33
|
+
if (publishedVersionCache.has(packageName)) {
|
|
34
|
+
return publishedVersionCache.get(packageName);
|
|
35
|
+
}
|
|
36
|
+
try {
|
|
37
|
+
const raw = execFileSync('npm', ['view', packageName, 'version', '--json', '--loglevel=silent'], {
|
|
38
|
+
encoding: 'utf8',
|
|
39
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
40
|
+
env: createSafeNpmEnv(),
|
|
41
|
+
timeout: NPM_VIEW_TIMEOUT_MS,
|
|
42
|
+
}).trim();
|
|
43
|
+
const resolved = JSON.parse(raw);
|
|
44
|
+
const version = typeof resolved === 'string' && resolved.length > 0 ? resolved : undefined;
|
|
45
|
+
publishedVersionCache.set(packageName, version);
|
|
46
|
+
return version;
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
publishedVersionCache.set(packageName, undefined);
|
|
50
|
+
return undefined;
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
const loadBundledPublishedCoreVersion = () => {
|
|
54
|
+
const bundledGovernancePackage = readBundledGovernancePackage();
|
|
55
|
+
const peerDependencies = bundledGovernancePackage?.peerDependencies;
|
|
56
|
+
if (typeof peerDependencies !== 'object' || peerDependencies === null) {
|
|
57
|
+
return undefined;
|
|
58
|
+
}
|
|
59
|
+
const corePeerRange = peerDependencies['@zintrust/core'];
|
|
60
|
+
if (typeof corePeerRange !== 'string' || corePeerRange.trim() === '') {
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
63
|
+
const publishedLineVersion = extractMajorMinorVersion(corePeerRange);
|
|
64
|
+
if (publishedLineVersion === undefined) {
|
|
65
|
+
return '0.7.0';
|
|
66
|
+
}
|
|
67
|
+
return `${publishedLineVersion.major}.${publishedLineVersion.minor}.0`;
|
|
68
|
+
};
|
|
69
|
+
const loadScaffoldCoreVersion = () => {
|
|
70
|
+
const publishedVersion = loadPublishedNpmVersion('@zintrust/core');
|
|
71
|
+
if (typeof publishedVersion === 'string') {
|
|
72
|
+
return publishedVersion;
|
|
73
|
+
}
|
|
74
|
+
const publishedGovernanceVersion = loadPublishedNpmVersion('@zintrust/governance');
|
|
75
|
+
if (typeof publishedGovernanceVersion === 'string') {
|
|
76
|
+
return publishedGovernanceVersion;
|
|
77
|
+
}
|
|
78
|
+
const bundledPublishedCoreVersion = loadBundledPublishedCoreVersion();
|
|
79
|
+
if (typeof bundledPublishedCoreVersion === 'string') {
|
|
80
|
+
return bundledPublishedCoreVersion;
|
|
81
|
+
}
|
|
82
|
+
return '0.7.0';
|
|
83
|
+
};
|
|
84
|
+
const loadGovernanceVersion = () => {
|
|
85
|
+
const publishedVersion = loadPublishedNpmVersion('@zintrust/governance');
|
|
86
|
+
if (typeof publishedVersion === 'string') {
|
|
87
|
+
return publishedVersion;
|
|
88
|
+
}
|
|
89
|
+
const bundledPublishedCoreVersion = loadBundledPublishedCoreVersion();
|
|
90
|
+
if (typeof bundledPublishedCoreVersion === 'string') {
|
|
91
|
+
return bundledPublishedCoreVersion;
|
|
22
92
|
}
|
|
93
|
+
return '0.7.0';
|
|
23
94
|
};
|
|
24
95
|
const createDirectories = (projectPath, directories) => {
|
|
25
96
|
let count = 0;
|
|
@@ -476,8 +547,8 @@ const prepareContext = (state, options) => {
|
|
|
476
547
|
.replaceAll(/[-:T.Z]/g, '')
|
|
477
548
|
.slice(0, 14);
|
|
478
549
|
state.variables = {
|
|
479
|
-
coreVersion:
|
|
480
|
-
governanceVersion: toCompatibleGovernanceVersion(
|
|
550
|
+
coreVersion: loadScaffoldCoreVersion(),
|
|
551
|
+
governanceVersion: toCompatibleGovernanceVersion(loadGovernanceVersion()),
|
|
481
552
|
projectName: options.name,
|
|
482
553
|
projectSlug: options.name,
|
|
483
554
|
author: options.author ?? 'Your Name',
|
|
@@ -26,7 +26,7 @@ export const extractMajorMinorVersion = (value) => {
|
|
|
26
26
|
return undefined;
|
|
27
27
|
return { major, minor };
|
|
28
28
|
};
|
|
29
|
-
export const toCompatibleGovernanceVersion = (value, fallback = '^0.
|
|
29
|
+
export const toCompatibleGovernanceVersion = (value, fallback = '^1.0.0') => {
|
|
30
30
|
const parsed = extractMajorMinorVersion(value);
|
|
31
31
|
if (parsed === undefined)
|
|
32
32
|
return fallback;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export type ContextLoaderBatchKey = string | number;
|
|
2
|
+
export type ContextLoaderMode = 'sequential' | 'batch';
|
|
3
|
+
export type ContextLoaderContext = Record<string, unknown>;
|
|
4
|
+
export type ContextLoaderResolver<TValue = unknown, TContext extends ContextLoaderContext = ContextLoaderContext> = (context: Readonly<TContext>) => Promise<TValue>;
|
|
5
|
+
export type ContextLoaderBatchResult<TKey extends ContextLoaderBatchKey = ContextLoaderBatchKey> = Map<TKey, unknown> | Record<string, unknown> | null | undefined;
|
|
6
|
+
export type ContextLoaderBatchHandler<TKey extends ContextLoaderBatchKey = ContextLoaderBatchKey> = (keys: TKey[]) => Promise<ContextLoaderBatchResult<TKey>>;
|
|
7
|
+
export type ContextLoaderPlan = {
|
|
8
|
+
load: <TValue = unknown>(key: string, resolver: ContextLoaderResolver<TValue>) => ContextLoaderPlan;
|
|
9
|
+
fromBatch: <TKey extends ContextLoaderBatchKey = ContextLoaderBatchKey>(name: string, key: TKey) => Promise<unknown>;
|
|
10
|
+
resolve: <TResolved extends ContextLoaderContext = ContextLoaderContext>() => Promise<Readonly<TResolved>>;
|
|
11
|
+
};
|
|
12
|
+
export type ContextLoaderInstance = {
|
|
13
|
+
load: <TValue = unknown>(key: string, resolver: ContextLoaderResolver<TValue>) => ContextLoaderPlan;
|
|
14
|
+
batch: (name: string, handler: ContextLoaderBatchHandler) => ContextLoaderInstance;
|
|
15
|
+
fromBatch: (name: string, key: ContextLoaderBatchKey) => Promise<unknown>;
|
|
16
|
+
hasBatch: (name: string) => boolean;
|
|
17
|
+
listBatches: () => string[];
|
|
18
|
+
unregisterBatch: (name: string) => void;
|
|
19
|
+
clearBatches: () => void;
|
|
20
|
+
};
|
|
21
|
+
export type ContextLoaderNamespace = {
|
|
22
|
+
create: (options?: {
|
|
23
|
+
mode?: ContextLoaderMode;
|
|
24
|
+
}) => ContextLoaderInstance;
|
|
25
|
+
};
|
|
26
|
+
export declare const ContextLoader: ContextLoaderNamespace;
|
|
27
|
+
//# sourceMappingURL=ContextLoader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ContextLoader.d.ts","sourceRoot":"","sources":["../../../src/common/ContextLoader.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,qBAAqB,GAAG,MAAM,GAAG,MAAM,CAAC;AACpD,MAAM,MAAM,iBAAiB,GAAG,YAAY,GAAG,OAAO,CAAC;AAEvD,MAAM,MAAM,oBAAoB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAE3D,MAAM,MAAM,qBAAqB,CAC/B,MAAM,GAAG,OAAO,EAChB,QAAQ,SAAS,oBAAoB,GAAG,oBAAoB,IAC1D,CAAC,OAAO,EAAE,QAAQ,CAAC,QAAQ,CAAC,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;AAErD,MAAM,MAAM,wBAAwB,CAAC,IAAI,SAAS,qBAAqB,GAAG,qBAAqB,IAC3F,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,GAClB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACvB,IAAI,GACJ,SAAS,CAAC;AAEd,MAAM,MAAM,yBAAyB,CAAC,IAAI,SAAS,qBAAqB,GAAG,qBAAqB,IAC9F,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,OAAO,CAAC,wBAAwB,CAAC,IAAI,CAAC,CAAC,CAAC;AAE5D,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,CAAC,MAAM,GAAG,OAAO,EACrB,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,qBAAqB,CAAC,MAAM,CAAC,KACpC,iBAAiB,CAAC;IACvB,SAAS,EAAE,CAAC,IAAI,SAAS,qBAAqB,GAAG,qBAAqB,EACpE,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,IAAI,KACN,OAAO,CAAC,OAAO,CAAC,CAAC;IACtB,OAAO,EAAE,CAAC,SAAS,SAAS,oBAAoB,GAAG,oBAAoB,OAAO,OAAO,CACnF,QAAQ,CAAC,SAAS,CAAC,CACpB,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,IAAI,EAAE,CAAC,MAAM,GAAG,OAAO,EACrB,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,qBAAqB,CAAC,MAAM,CAAC,KACpC,iBAAiB,CAAC;IACvB,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,yBAAyB,KAAK,qBAAqB,CAAC;IACnF,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,qBAAqB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1E,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;IACpC,WAAW,EAAE,MAAM,MAAM,EAAE,CAAC;IAC5B,eAAe,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,YAAY,EAAE,MAAM,IAAI,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,iBAAiB,CAAA;KAAE,KAAK,qBAAqB,CAAC;CAC3E,CAAC;AAmQF,eAAO,MAAM,aAAa,EAAE,sBAE1B,CAAC"}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { ErrorFactory } from '../exceptions/ZintrustError.js';
|
|
2
|
+
import { isFunction, isNonEmptyString, isObject } from '../helper/index.js';
|
|
3
|
+
const scheduleMicrotask = (task) => {
|
|
4
|
+
if (typeof globalThis.queueMicrotask === 'function') {
|
|
5
|
+
globalThis.queueMicrotask(task);
|
|
6
|
+
return;
|
|
7
|
+
}
|
|
8
|
+
void Promise.resolve().then(task);
|
|
9
|
+
};
|
|
10
|
+
const normalizeBatchName = (name) => {
|
|
11
|
+
const normalized = String(name ?? '')
|
|
12
|
+
.trim()
|
|
13
|
+
.toLowerCase();
|
|
14
|
+
if (!isNonEmptyString(normalized)) {
|
|
15
|
+
throw ErrorFactory.createValidationError('ContextLoader batch name must be a non-empty string');
|
|
16
|
+
}
|
|
17
|
+
return normalized;
|
|
18
|
+
};
|
|
19
|
+
const normalizeLoadKey = (key) => {
|
|
20
|
+
const normalized = String(key ?? '').trim();
|
|
21
|
+
if (!isNonEmptyString(normalized)) {
|
|
22
|
+
throw ErrorFactory.createValidationError('ContextLoader load key must be a non-empty string');
|
|
23
|
+
}
|
|
24
|
+
return normalized;
|
|
25
|
+
};
|
|
26
|
+
const assertBatchKey = (key) => {
|
|
27
|
+
if (typeof key === 'string' && key.trim() !== '') {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
if (typeof key === 'number' && Number.isFinite(key)) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
throw ErrorFactory.createValidationError('ContextLoader batch key must be a non-empty string or finite number');
|
|
34
|
+
};
|
|
35
|
+
const extractBatchValue = (result, key) => {
|
|
36
|
+
if (result instanceof Map) {
|
|
37
|
+
return result.has(key) ? (result.get(key) ?? null) : null;
|
|
38
|
+
}
|
|
39
|
+
if (isObject(result)) {
|
|
40
|
+
const recordKey = typeof key === 'number' ? String(key) : key;
|
|
41
|
+
return recordKey in result ? (result[recordKey] ?? null) : null;
|
|
42
|
+
}
|
|
43
|
+
return null;
|
|
44
|
+
};
|
|
45
|
+
const dedupeBatchKeys = (requests) => {
|
|
46
|
+
const seen = new Set();
|
|
47
|
+
const keys = [];
|
|
48
|
+
for (const request of requests) {
|
|
49
|
+
const signature = `${typeof request.key}:${String(request.key)}`;
|
|
50
|
+
if (seen.has(signature)) {
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
seen.add(signature);
|
|
54
|
+
keys.push(request.key);
|
|
55
|
+
}
|
|
56
|
+
return keys;
|
|
57
|
+
};
|
|
58
|
+
const freezeContext = (context) => {
|
|
59
|
+
return Object.freeze({ ...context });
|
|
60
|
+
};
|
|
61
|
+
const executePlanSteps = async (steps) => {
|
|
62
|
+
const resolved = await steps.reduce(async (accPromise, step) => {
|
|
63
|
+
const accumulated = await accPromise;
|
|
64
|
+
const snapshot = freezeContext(accumulated);
|
|
65
|
+
return {
|
|
66
|
+
...accumulated,
|
|
67
|
+
[step.key]: await step.resolver(snapshot),
|
|
68
|
+
};
|
|
69
|
+
}, Promise.resolve({}));
|
|
70
|
+
return freezeContext(resolved);
|
|
71
|
+
};
|
|
72
|
+
const createFlushBatch = (batchHandlers, batchQueues) => {
|
|
73
|
+
return async (name) => {
|
|
74
|
+
const queue = batchQueues.get(name);
|
|
75
|
+
const handler = batchHandlers.get(name);
|
|
76
|
+
if (!queue || !handler) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
const requests = queue.requests.splice(0);
|
|
80
|
+
queue.scheduled = false;
|
|
81
|
+
if (requests.length === 0) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
try {
|
|
85
|
+
const keys = dedupeBatchKeys(requests);
|
|
86
|
+
const result = await handler(keys);
|
|
87
|
+
for (const request of requests) {
|
|
88
|
+
request.resolve(extractBatchValue(result, request.key));
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
for (const request of requests) {
|
|
93
|
+
request.reject(error);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
};
|
|
98
|
+
const createSequentialBatchPromise = async (handler, key) => {
|
|
99
|
+
return handler([key]).then((result) => extractBatchValue(result, key));
|
|
100
|
+
};
|
|
101
|
+
const createPlan = (root, steps) => {
|
|
102
|
+
let resolvePromise = null;
|
|
103
|
+
const plan = Object.freeze({
|
|
104
|
+
load(key, resolver) {
|
|
105
|
+
const normalizedKey = normalizeLoadKey(key);
|
|
106
|
+
if (!isFunction(resolver)) {
|
|
107
|
+
throw ErrorFactory.createValidationError('ContextLoader resolver must be a function');
|
|
108
|
+
}
|
|
109
|
+
if (steps.some((step) => step.key === normalizedKey)) {
|
|
110
|
+
throw ErrorFactory.createValidationError(`ContextLoader key already registered: ${normalizedKey}`);
|
|
111
|
+
}
|
|
112
|
+
return createPlan(root, [...steps, { key: normalizedKey, resolver }]);
|
|
113
|
+
},
|
|
114
|
+
async fromBatch(name, key) {
|
|
115
|
+
return root.fromBatch(name, key);
|
|
116
|
+
},
|
|
117
|
+
async resolve() {
|
|
118
|
+
resolvePromise ??= executePlanSteps(steps);
|
|
119
|
+
return resolvePromise;
|
|
120
|
+
},
|
|
121
|
+
});
|
|
122
|
+
return plan;
|
|
123
|
+
};
|
|
124
|
+
const create = (options = {}) => {
|
|
125
|
+
const mode = options.mode ?? 'sequential';
|
|
126
|
+
const batchHandlers = new Map();
|
|
127
|
+
const batchQueues = new Map();
|
|
128
|
+
const flushBatch = createFlushBatch(batchHandlers, batchQueues);
|
|
129
|
+
const root = Object.freeze({
|
|
130
|
+
load(key, resolver) {
|
|
131
|
+
const normalizedKey = normalizeLoadKey(key);
|
|
132
|
+
if (!isFunction(resolver)) {
|
|
133
|
+
throw ErrorFactory.createValidationError('ContextLoader resolver must be a function');
|
|
134
|
+
}
|
|
135
|
+
return createPlan(root, [{ key: normalizedKey, resolver }]);
|
|
136
|
+
},
|
|
137
|
+
batch(name, handler) {
|
|
138
|
+
const normalizedName = normalizeBatchName(name);
|
|
139
|
+
if (!isFunction(handler)) {
|
|
140
|
+
throw ErrorFactory.createValidationError('ContextLoader batch handler must be a function');
|
|
141
|
+
}
|
|
142
|
+
batchHandlers.set(normalizedName, handler);
|
|
143
|
+
return this;
|
|
144
|
+
},
|
|
145
|
+
async fromBatch(name, key) {
|
|
146
|
+
const normalizedName = normalizeBatchName(name);
|
|
147
|
+
assertBatchKey(key);
|
|
148
|
+
const handler = batchHandlers.get(normalizedName);
|
|
149
|
+
if (!handler) {
|
|
150
|
+
throw ErrorFactory.createConfigError(`ContextLoader batch not registered: ${normalizedName}`);
|
|
151
|
+
}
|
|
152
|
+
if (mode === 'sequential') {
|
|
153
|
+
return createSequentialBatchPromise(handler, key);
|
|
154
|
+
}
|
|
155
|
+
return new Promise((resolve, reject) => {
|
|
156
|
+
const queue = batchQueues.get(normalizedName) ?? { requests: [], scheduled: false };
|
|
157
|
+
queue.requests.push({ key, resolve, reject });
|
|
158
|
+
batchQueues.set(normalizedName, queue);
|
|
159
|
+
if (!queue.scheduled) {
|
|
160
|
+
queue.scheduled = true;
|
|
161
|
+
scheduleMicrotask(() => {
|
|
162
|
+
void flushBatch(normalizedName);
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
},
|
|
167
|
+
hasBatch(name) {
|
|
168
|
+
return batchHandlers.has(normalizeBatchName(name));
|
|
169
|
+
},
|
|
170
|
+
listBatches() {
|
|
171
|
+
return Array.from(batchHandlers.keys()).sort((left, right) => left.localeCompare(right));
|
|
172
|
+
},
|
|
173
|
+
unregisterBatch(name) {
|
|
174
|
+
const normalizedName = normalizeBatchName(name);
|
|
175
|
+
batchHandlers.delete(normalizedName);
|
|
176
|
+
batchQueues.delete(normalizedName);
|
|
177
|
+
},
|
|
178
|
+
clearBatches() {
|
|
179
|
+
batchHandlers.clear();
|
|
180
|
+
batchQueues.clear();
|
|
181
|
+
},
|
|
182
|
+
});
|
|
183
|
+
return root;
|
|
184
|
+
};
|
|
185
|
+
export const ContextLoader = Object.freeze({
|
|
186
|
+
create,
|
|
187
|
+
});
|
package/src/config/logger.d.ts
CHANGED
|
@@ -21,6 +21,8 @@ export declare const Logger: Readonly<{
|
|
|
21
21
|
cleanLogsOnce: () => Promise<string[]>;
|
|
22
22
|
scope: (scope: string) => ILogger;
|
|
23
23
|
addSink: (fn: LogSink) => (() => void);
|
|
24
|
+
withTraceSkipContext: (context?: Record<string, unknown>) => Record<string, unknown>;
|
|
25
|
+
shouldSkipTraceLogContext: (context?: Record<string, unknown>) => boolean;
|
|
24
26
|
}>;
|
|
25
27
|
export default Logger;
|
|
26
28
|
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../../src/config/logger.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAE7C,UAAU,OAAO;IACf,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChE,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/D,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjE,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAClE;AAkzBD;;;GAGG;AACH,MAAM,MAAM,OAAO,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../../src/config/logger.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAE7C,UAAU,OAAO;IACf,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChE,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/D,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjE,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAClE;AAkzBD;;;GAGG;AACH,MAAM,MAAM,OAAO,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;AA+CpG,eAAO,MAAM,aAAa,QAAa,OAAO,CAAC,MAAM,EAAE,CAYtD,CAAC;AAEF,eAAO,MAAM,MAAM;qBAxNQ,MAAM,SAAS,OAAO,aAAa,MAAM,KAAG,IAAI;oBAuBjD,MAAM,SAAS,OAAO,aAAa,MAAM,KAAG,IAAI;oBAuBhD,MAAM,SAAS,OAAO,aAAa,MAAM,KAAG,IAAI;qBAuB/C,MAAM,UAAU,OAAO,aAAa,MAAM,KAAG,IAAI;qBA6BjD,MAAM,UAAU,OAAO,aAAa,MAAM,KAAG,IAAI;yBAwGrC,OAAO,CAAC,MAAM,EAAE,CAAC;mBAvEtB,MAAM,KAAG,OAAO;kBA8D7B,OAAO,KAAG,CAAC,MAAM,IAAI,CAAC;qCAlCH,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;0CAO5C,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,OAAO;EA6D5E,CAAC;AAEH,eAAe,MAAM,CAAC"}
|
package/src/config/logger.js
CHANGED
|
@@ -740,6 +740,16 @@ const createLoggerScope = (scope) => {
|
|
|
740
740
|
},
|
|
741
741
|
};
|
|
742
742
|
};
|
|
743
|
+
const TRACE_SKIP_LOG_CONTEXT_KEY = '__zintrustSkipTraceLog';
|
|
744
|
+
const withTraceSkipContext = (context) => {
|
|
745
|
+
return {
|
|
746
|
+
...(context ?? {}),
|
|
747
|
+
[TRACE_SKIP_LOG_CONTEXT_KEY]: true,
|
|
748
|
+
};
|
|
749
|
+
};
|
|
750
|
+
const shouldSkipTraceLogContext = (context) => {
|
|
751
|
+
return context?.[TRACE_SKIP_LOG_CONTEXT_KEY] === true;
|
|
752
|
+
};
|
|
743
753
|
const loggerSinks = [];
|
|
744
754
|
const dispatchToSinks = (level, message, data) => {
|
|
745
755
|
if (loggerSinks.length === 0)
|
|
@@ -795,5 +805,7 @@ export const Logger = Object.freeze({
|
|
|
795
805
|
cleanLogsOnce,
|
|
796
806
|
scope: createLoggerScope,
|
|
797
807
|
addSink,
|
|
808
|
+
withTraceSkipContext,
|
|
809
|
+
shouldSkipTraceLogContext,
|
|
798
810
|
});
|
|
799
811
|
export default Logger;
|
package/src/index.d.ts
CHANGED
|
@@ -63,7 +63,9 @@ export { normalizeRouteMeta, RouteRegistry } from './routes/RouteRegistry';
|
|
|
63
63
|
export type { RouteMeta, RouteMetaInput, RouteRegistration } from './routes/RouteRegistry';
|
|
64
64
|
export { DatabaseAdapterRegistry } from './orm/DatabaseAdapterRegistry';
|
|
65
65
|
export { generateSecureJobId, generateUuid, getString, Utilities, type UtilitiesType, } from './common/utility';
|
|
66
|
+
export { ContextLoader } from './common/ContextLoader';
|
|
66
67
|
export { delay, ensureDirSafe } from './common/index';
|
|
68
|
+
export type { ContextLoaderBatchHandler, ContextLoaderBatchKey, ContextLoaderBatchResult, ContextLoaderContext, ContextLoaderInstance, ContextLoaderMode, ContextLoaderPlan, ContextLoaderResolver, } from './common/ContextLoader';
|
|
67
69
|
export { collect, Collection } from './collections/index';
|
|
68
70
|
export type { ICollection, PrimitiveKey } from './collections/index';
|
|
69
71
|
export { HttpClient } from './tools/http/Http';
|
|
@@ -180,7 +182,9 @@ export { sendSlackWebhook } from './tools/notification/drivers/Slack';
|
|
|
180
182
|
export { TermiiDriver } from './tools/notification/drivers/Termii';
|
|
181
183
|
export { sendSms } from './tools/notification/drivers/Twilio';
|
|
182
184
|
export { Notification } from './tools/notification/Notification';
|
|
185
|
+
export { NotificationComposer } from './tools/notification/Composer';
|
|
183
186
|
export { NotificationRegistry } from './tools/notification/Registry';
|
|
187
|
+
export type { NotificationChannelHandler, NotificationComposeBuilder, NotificationComposeChannelResult, NotificationComposeError, NotificationComposeOptions, NotificationComposePolicy, NotificationComposeResult, } from './tools/notification/Composer';
|
|
184
188
|
export { MarkdownRenderer } from './tools/templates';
|
|
185
189
|
export { RuntimeHealthProbes } from './health/RuntimeHealthProbes';
|
|
186
190
|
export { Broadcast } from './tools/broadcast/Broadcast';
|
|
@@ -218,6 +222,8 @@ export type { LoadedSeeder, SeederHandler } from './seeders/types';
|
|
|
218
222
|
export { default as logCleanup } from './schedules/log-cleanup';
|
|
219
223
|
export * as NodeSingletons from './node-singletons/index';
|
|
220
224
|
export { Auth } from './auth/Auth';
|
|
225
|
+
export { LoginFlow } from './auth/LoginFlow';
|
|
226
|
+
export type { LoginFlowAuditEvent, LoginFlowAuditor, LoginFlowBuilder, LoginFlowCreateOptions, LoginFlowError, LoginFlowIdentity, LoginFlowIssuer, LoginFlowIssuerInput, LoginFlowProvider, LoginFlowResult, LoginFlowStage, LoginFlowVerifiedRecord, } from './auth/LoginFlow';
|
|
221
227
|
export { MicroserviceGenerator } from './microservices/MicroserviceGenerator';
|
|
222
228
|
export type { GenerateServiceOptions, IMicroserviceGenerator, } from './microservices/MicroserviceGenerator';
|
|
223
229
|
export { ErrorHandler as ProxyErrorHandler } from './proxy/ErrorHandler';
|
|
@@ -230,6 +236,7 @@ export { PluginRegistry } from './runtime/PluginRegistry';
|
|
|
230
236
|
export { nowIso } from './common/utility';
|
|
231
237
|
export type { SanitizerError } from './exceptions/ZintrustError';
|
|
232
238
|
export { randomBytes } from './node-singletons/crypto';
|
|
239
|
+
export { SecurePayload, type SecurePayloadCoercionShape, type SecurePayloadCoercionType, type SecurePayloadDecodeOptions, type SecurePayloadDecryptor, type SecurePayloadPipeline, type SecurePayloadPipelineIssue, type SecurePayloadPipelineStage, } from './security/SecurePayload';
|
|
233
240
|
export type { MiddlewaresType } from './config/middleware';
|
|
234
241
|
export * from './config/redis';
|
|
235
242
|
export type * from './config/type';
|