@zintrust/core 0.7.3 → 0.7.8
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/auth/LoginFlow.d.ts +7 -1
- package/src/auth/LoginFlow.d.ts.map +1 -1
- package/src/auth/LoginFlow.js +100 -2
- package/src/cli/OptionalCliExtensions.d.ts.map +1 -1
- package/src/cli/OptionalCliExtensions.js +13 -1
- package/src/cli/commands/RoutesCommand.d.ts.map +1 -1
- package/src/cli/commands/RoutesCommand.js +39 -2
- package/src/cli/commands/schedule/ScheduleCliSupport.d.ts.map +1 -1
- package/src/cli/commands/schedule/ScheduleCliSupport.js +52 -11
- package/src/cli/scaffolding/ProjectScaffolder.d.ts.map +1 -1
- package/src/cli/scaffolding/ProjectScaffolder.js +45 -6
- package/src/cli/utils/spawn.d.ts.map +1 -1
- package/src/cli/utils/spawn.js +19 -13
- package/src/config/env.d.ts +2 -0
- package/src/config/env.d.ts.map +1 -1
- package/src/config/env.js +2 -0
- package/src/config/logger.d.ts +10 -12
- package/src/config/logger.d.ts.map +1 -1
- package/src/config/logger.js +6 -3
- package/src/http/Request.d.ts +1 -0
- package/src/http/Request.d.ts.map +1 -1
- package/src/http/Request.js +3 -0
- package/src/index.d.ts +2 -1
- package/src/index.d.ts.map +1 -1
- package/src/index.js +4 -3
- package/src/middleware/BulletproofAuthMiddleware.d.ts.map +1 -1
- package/src/middleware/BulletproofAuthMiddleware.js +7 -1
- package/src/proxy/ProxyServerUtils.d.ts.map +1 -1
- package/src/proxy/ProxyServerUtils.js +6 -2
- package/src/runtime/useFileLoader.d.ts +5 -0
- package/src/runtime/useFileLoader.d.ts.map +1 -1
- package/src/runtime/useFileLoader.js +58 -37
- package/src/security/BulletproofDeviceStore.d.ts +18 -0
- package/src/security/BulletproofDeviceStore.d.ts.map +1 -0
- package/src/security/BulletproofDeviceStore.js +132 -0
- package/src/templates/project/basic/app/Controllers/AuthController.ts.tpl +23 -9
- package/src/templates/project/basic/database/migrations/20260419000000_create_bulletproof_devices_table.ts.tpl +36 -0
package/package.json
CHANGED
package/src/auth/LoginFlow.d.ts
CHANGED
|
@@ -24,6 +24,12 @@ export type LoginFlowIssuerInput<TContext = unknown> = {
|
|
|
24
24
|
verified: LoginFlowVerifiedRecord;
|
|
25
25
|
context: TContext;
|
|
26
26
|
};
|
|
27
|
+
export type BulletproofJwtIssued = Readonly<{
|
|
28
|
+
token: string;
|
|
29
|
+
token_type: 'Bearer';
|
|
30
|
+
deviceId: string;
|
|
31
|
+
deviceSecret: string;
|
|
32
|
+
}>;
|
|
27
33
|
export type LoginFlowIssuer<TContext = unknown> = (input: LoginFlowIssuerInput<TContext>) => Promise<unknown>;
|
|
28
34
|
export type LoginFlowAuditEvent<TContext = unknown> = {
|
|
29
35
|
status: 'success' | 'failed';
|
|
@@ -36,7 +42,7 @@ export type LoginFlowAuditEvent<TContext = unknown> = {
|
|
|
36
42
|
error?: unknown;
|
|
37
43
|
context: TContext;
|
|
38
44
|
};
|
|
39
|
-
export type LoginFlowAuditor<TContext = unknown> = (event: LoginFlowAuditEvent<TContext>) => Promise<void>;
|
|
45
|
+
export type LoginFlowAuditor<TContext = unknown> = (event: LoginFlowAuditEvent<TContext>) => void | Promise<void>;
|
|
40
46
|
export type LoginFlowCreateOptions<TContext = unknown> = {
|
|
41
47
|
provider: string | LoginFlowProvider<TContext>;
|
|
42
48
|
context: TContext;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LoginFlow.d.ts","sourceRoot":"","sources":["../../../src/auth/LoginFlow.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"LoginFlow.d.ts","sourceRoot":"","sources":["../../../src/auth/LoginFlow.ts"],"names":[],"mappings":"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"}
|
package/src/auth/LoginFlow.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { SystemTraceBridge } from '../trace/SystemTraceBridge.js';
|
|
2
2
|
import { ErrorFactory } from '../exceptions/ZintrustError.js';
|
|
3
3
|
import { isFunction, isNonEmptyString, isObject } from '../helper/index.js';
|
|
4
|
+
import { detectRuntimePlatform, RuntimeServices, } from '../runtime/RuntimeServices.js';
|
|
5
|
+
import { BulletproofDeviceStore, } from '../security/BulletproofDeviceStore.js';
|
|
4
6
|
import { JwtManager } from '../security/JwtManager.js';
|
|
5
7
|
const providerRegistry = new Map();
|
|
6
8
|
const issuerRegistry = new Map();
|
|
@@ -98,12 +100,107 @@ const createJwtIssuer = async ({ verified, }) => {
|
|
|
98
100
|
}
|
|
99
101
|
return JwtManager.signAccessToken(claims);
|
|
100
102
|
};
|
|
101
|
-
const
|
|
103
|
+
const getContextRecord = (context) => {
|
|
104
|
+
return isObject(context) ? context : {};
|
|
105
|
+
};
|
|
106
|
+
const getContextRequest = (context) => {
|
|
107
|
+
const request = getContextRecord(context)['request'];
|
|
108
|
+
return isObject(request) ? request : undefined;
|
|
109
|
+
};
|
|
110
|
+
const getContextString = (context, key) => {
|
|
111
|
+
const value = getContextRecord(context)[key];
|
|
112
|
+
return typeof value === 'string' && value.trim() !== '' ? value.trim() : undefined;
|
|
113
|
+
};
|
|
114
|
+
const getBodyString = (request, key) => {
|
|
115
|
+
if (request === undefined || typeof request.getBody !== 'function')
|
|
116
|
+
return undefined;
|
|
117
|
+
const body = request.getBody();
|
|
118
|
+
if (!isObject(body))
|
|
119
|
+
return undefined;
|
|
120
|
+
const value = body[key];
|
|
121
|
+
return typeof value === 'string' && value.trim() !== '' ? value.trim() : undefined;
|
|
122
|
+
};
|
|
123
|
+
const getRequestHeaderString = (request, name) => {
|
|
124
|
+
if (request === undefined || typeof request.getHeader !== 'function')
|
|
125
|
+
return undefined;
|
|
126
|
+
const value = request.getHeader(name);
|
|
127
|
+
if (Array.isArray(value)) {
|
|
128
|
+
return typeof value[0] === 'string' && value[0].trim() !== '' ? value[0].trim() : undefined;
|
|
129
|
+
}
|
|
130
|
+
return typeof value === 'string' && value.trim() !== '' ? value.trim() : undefined;
|
|
131
|
+
};
|
|
132
|
+
const bytesToHex = (bytes) => {
|
|
133
|
+
let out = '';
|
|
134
|
+
for (const byte of bytes)
|
|
135
|
+
out += byte.toString(16).padStart(2, '0');
|
|
136
|
+
return out;
|
|
137
|
+
};
|
|
138
|
+
const getRuntimeCrypto = () => RuntimeServices.create(detectRuntimePlatform()).crypto;
|
|
139
|
+
const generateDeviceId = () => {
|
|
140
|
+
const bytes = getRuntimeCrypto().getRandomValues(new Uint8Array(16));
|
|
141
|
+
return `dev_${bytesToHex(bytes)}`;
|
|
142
|
+
};
|
|
143
|
+
const generateDeviceSecret = () => {
|
|
144
|
+
const bytes = getRuntimeCrypto().getRandomValues(new Uint8Array(32));
|
|
145
|
+
return `hex:${bytesToHex(bytes)}`;
|
|
146
|
+
};
|
|
147
|
+
const getClaimedDeviceId = (claims) => {
|
|
148
|
+
const deviceId = claims['deviceId'];
|
|
149
|
+
return typeof deviceId === 'string' && deviceId.trim() !== ''
|
|
150
|
+
? deviceId.trim()
|
|
151
|
+
: undefined;
|
|
152
|
+
};
|
|
153
|
+
const resolveBulletproofDeviceId = (context, request, claims) => {
|
|
154
|
+
return (getContextString(context, 'deviceId') ??
|
|
155
|
+
getBodyString(request, 'deviceId') ??
|
|
156
|
+
getClaimedDeviceId(claims) ??
|
|
157
|
+
generateDeviceId());
|
|
158
|
+
};
|
|
159
|
+
const resolveBulletproofUserId = (context, verified) => {
|
|
160
|
+
const subjectUserId = isNonEmptyString(verified.subject) ? verified.subject.trim() : undefined;
|
|
161
|
+
const verifiedUserId = isObject(verified.user) && verified.user['id'] !== undefined
|
|
162
|
+
? String(verified.user['id'])
|
|
163
|
+
: undefined;
|
|
164
|
+
return getContextString(context, 'userId') ?? subjectUserId ?? verifiedUserId;
|
|
165
|
+
};
|
|
166
|
+
const buildBulletproofDeviceRecord = (context, verified, request, claims, deviceSecret) => {
|
|
167
|
+
const deviceId = resolveBulletproofDeviceId(context, request, claims);
|
|
168
|
+
const userId = resolveBulletproofUserId(context, verified);
|
|
169
|
+
const userAgent = getRequestHeaderString(request, 'user-agent');
|
|
170
|
+
return {
|
|
171
|
+
deviceId,
|
|
172
|
+
record: {
|
|
173
|
+
deviceId,
|
|
174
|
+
signingSecret: deviceSecret,
|
|
175
|
+
lastSeenAt: new Date(),
|
|
176
|
+
...(isNonEmptyString(userId) ? { userId } : {}),
|
|
177
|
+
...(userAgent === undefined ? {} : { userAgent }),
|
|
178
|
+
},
|
|
179
|
+
};
|
|
180
|
+
};
|
|
181
|
+
const createBulletproofIssuer = async ({ verified, context, }) => {
|
|
182
|
+
const claims = isObject(verified.claims) ? { ...verified.claims } : {};
|
|
183
|
+
if (isNonEmptyString(verified.subject) && !isNonEmptyString(claims.sub)) {
|
|
184
|
+
claims.sub = verified.subject;
|
|
185
|
+
}
|
|
186
|
+
const request = getContextRequest(context);
|
|
187
|
+
const deviceSecret = generateDeviceSecret();
|
|
188
|
+
const { deviceId, record } = buildBulletproofDeviceRecord(context, verified, request, claims, deviceSecret);
|
|
189
|
+
claims['deviceId'] = deviceId;
|
|
190
|
+
await BulletproofDeviceStore.upsert(record);
|
|
191
|
+
const token = await JwtManager.signAccessToken(claims);
|
|
192
|
+
return Object.freeze({
|
|
193
|
+
token,
|
|
194
|
+
token_type: 'Bearer',
|
|
195
|
+
deviceId,
|
|
196
|
+
deviceSecret,
|
|
197
|
+
});
|
|
198
|
+
};
|
|
199
|
+
const createTraceAuditor = (event) => {
|
|
102
200
|
const subject = typeof event.verified?.subject === 'string' && event.verified.subject.trim() !== ''
|
|
103
201
|
? event.verified.subject
|
|
104
202
|
: undefined;
|
|
105
203
|
SystemTraceBridge.emitAuth(event.status === 'success' ? 'login' : 'failed', subject);
|
|
106
|
-
return Promise.resolve();
|
|
107
204
|
};
|
|
108
205
|
const ensureNamedRegistration = (kind, name) => {
|
|
109
206
|
if (!isNonEmptyString(name)) {
|
|
@@ -334,6 +431,7 @@ const clearRegistrations = () => {
|
|
|
334
431
|
issuerRegistry.clear();
|
|
335
432
|
auditorRegistry.clear();
|
|
336
433
|
issuerRegistry.set('jwt', createJwtIssuer);
|
|
434
|
+
issuerRegistry.set('bulletproof', createBulletproofIssuer);
|
|
337
435
|
auditorRegistry.set('trace', createTraceAuditor);
|
|
338
436
|
};
|
|
339
437
|
clearRegistrations();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OptionalCliExtensions.d.ts","sourceRoot":"","sources":["../../../src/cli/OptionalCliExtensions.ts"],"names":[],"mappings":"AAQA,MAAM,MAAM,oBAAoB,GAAG;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B,CAAC;AAEF,KAAK,8BAA8B,GAAG,SAAS,GAAG,SAAS,GAAG,gBAAgB,GAAG,SAAS,CAAC;AAE3F,MAAM,MAAM,0BAA0B,GAAG,QAAQ,CAAC;IAChD,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,8BAA8B,CAAC;CACxC,CAAC,CAAC;AAEH,KAAK,+BAA+B,GAAG,QAAQ,CAAC;IAC9C,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"OptionalCliExtensions.d.ts","sourceRoot":"","sources":["../../../src/cli/OptionalCliExtensions.ts"],"names":[],"mappings":"AAQA,MAAM,MAAM,oBAAoB,GAAG;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B,CAAC;AAEF,KAAK,8BAA8B,GAAG,SAAS,GAAG,SAAS,GAAG,gBAAgB,GAAG,SAAS,CAAC;AAE3F,MAAM,MAAM,0BAA0B,GAAG,QAAQ,CAAC;IAChD,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,8BAA8B,CAAC;CACxC,CAAC,CAAC;AAEH,KAAK,+BAA+B,GAAG,QAAQ,CAAC;IAC9C,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC,CAAC;AAuTH,eAAO,MAAM,qBAAqB;oCACM,OAAO,CAAC,0BAA0B,EAAE,CAAC;sBAQnD,MAAM,EAAE,GAAG,OAAO,CAAC,0BAA0B,EAAE,CAAC;sCAmBhE,MAAM,EAAE,YACJ,aAAa,CAAC,0BAA0B,CAAC,GAClD,0BAA0B,GAAG,SAAS;uCASN,0BAA0B,GAAG,MAAM;mCArDlC,MAAM,EAAE,KAAG,oBAAoB,GAAG,SAAS;EA8D/E,CAAC;AAEH,eAAO,MAAM,6BAA6B;yBApWhB,MAAM;8BAoBD,MAAM;wCA6G5B,oBAAoB,YACjB,+BAA+B,KACxC,MAAM,GAAG,IAAI;kCAvGqB,+BAA+B,KAAG,OAAO;4BAMnE,MAAM,QACT,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,YACnB,+BAA+B,KACxC,IAAI;8CAoHE,oBAAoB,YACjB,+BAA+B,KACxC,OAAO,CAAC,OAAO,CAAC;qCA0BV,oBAAoB,YACjB,+BAA+B,KACxC,OAAO,CAAC,OAAO,CAAC;uCAgCV,oBAAoB,YACjB,+BAA+B,KACxC,OAAO,CAAC,OAAO,CAAC;gCAuBV,oBAAoB,YACjB,+BAA+B,KACxC,OAAO,CAAC,0BAA0B,CAAC;gCAwCH,MAAM,EAAE,KAAG,MAAM,GAAG,SAAS;mCAU1B,MAAM,EAAE,KAAG,oBAAoB,GAAG,SAAS;8BAOhD,MAAM,EAAE,KAAG,OAAO;uCAvMT,oBAAoB,KAAG,MAAM,EAAE;gCAwBtC,oBAAoB,KAAG,MAAM,EAAE;EAuPhE,CAAC"}
|
|
@@ -13,11 +13,23 @@ const getProjectCwd = () => {
|
|
|
13
13
|
}
|
|
14
14
|
return packageRoot;
|
|
15
15
|
};
|
|
16
|
+
const findNearestPackageJsonDir = (cwd) => {
|
|
17
|
+
let current = cwd;
|
|
18
|
+
while (true) {
|
|
19
|
+
if (existsSync(path.join(current, 'package.json')))
|
|
20
|
+
return current;
|
|
21
|
+
const parent = path.dirname(current);
|
|
22
|
+
if (parent === current)
|
|
23
|
+
return undefined;
|
|
24
|
+
current = parent;
|
|
25
|
+
}
|
|
26
|
+
};
|
|
16
27
|
const resolveProjectRoot = () => {
|
|
17
28
|
const configured = readEnvString('ZINTRUST_PROJECT_ROOT').trim();
|
|
18
29
|
if (configured !== '')
|
|
19
30
|
return configured;
|
|
20
|
-
|
|
31
|
+
const cwd = getProjectCwd();
|
|
32
|
+
return findNearestPackageJsonDir(cwd) ?? cwd;
|
|
21
33
|
};
|
|
22
34
|
const shouldLogFailures = (options) => {
|
|
23
35
|
if (options?.logFailures === true)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RoutesCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/RoutesCommand.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAoC,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"RoutesCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/RoutesCommand.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAoC,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAoYvF,eAAO,MAAM,aAAa;cACd,YAAY;EAatB,CAAC;AAEH,eAAe,aAAa,CAAC"}
|
|
@@ -9,6 +9,8 @@ import { ErrorFactory } from '../../exceptions/ZintrustError.js';
|
|
|
9
9
|
import { isObject } from '../../helper/index.js';
|
|
10
10
|
import { getServicePrefix } from '../../microservices/ServiceManifest.js';
|
|
11
11
|
import { ProjectRuntime } from '../../runtime/ProjectRuntime.js';
|
|
12
|
+
import { resolveNodeProjectRoot } from '../../runtime/resolveNodeProjectRoot.js';
|
|
13
|
+
import { useFileLoader } from '../../runtime/useFileLoader.js';
|
|
12
14
|
const parseGroupBy = (value) => {
|
|
13
15
|
const raw = typeof value === 'string' ? value.trim().toLowerCase() : '';
|
|
14
16
|
if (raw === '' || raw === 'group')
|
|
@@ -194,6 +196,39 @@ const registerManifestRoutes = async (router) => {
|
|
|
194
196
|
}
|
|
195
197
|
}
|
|
196
198
|
};
|
|
199
|
+
const ensureProjectRootEnv = async () => {
|
|
200
|
+
const projectRoot = await resolveNodeProjectRoot();
|
|
201
|
+
if ((process.env['ZINTRUST_PROJECT_ROOT'] ?? '').trim() === '') {
|
|
202
|
+
process.env['ZINTRUST_PROJECT_ROOT'] = projectRoot;
|
|
203
|
+
}
|
|
204
|
+
return projectRoot;
|
|
205
|
+
};
|
|
206
|
+
const loadProjectRouteRegistrar = async () => {
|
|
207
|
+
await ensureProjectRootEnv();
|
|
208
|
+
const loader = useFileLoader('routes/api.ts');
|
|
209
|
+
if (loader.exists()) {
|
|
210
|
+
try {
|
|
211
|
+
const routeModule = await loader.getModule();
|
|
212
|
+
const registerRoutes = isObject(routeModule) ? routeModule['registerRoutes'] : undefined;
|
|
213
|
+
if (typeof registerRoutes === 'function') {
|
|
214
|
+
return registerRoutes;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
catch {
|
|
218
|
+
// Fall back to the framework alias import when the project file cannot be imported.
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
try {
|
|
222
|
+
const routeModule = (await import('../../../routes/api.js'));
|
|
223
|
+
const registerRoutes = isObject(routeModule) ? routeModule['registerRoutes'] : undefined;
|
|
224
|
+
return typeof registerRoutes === 'function'
|
|
225
|
+
? registerRoutes
|
|
226
|
+
: undefined;
|
|
227
|
+
}
|
|
228
|
+
catch {
|
|
229
|
+
return undefined;
|
|
230
|
+
}
|
|
231
|
+
};
|
|
197
232
|
const buildRows = async (options) => {
|
|
198
233
|
const groupBy = parseGroupBy(options.groupBy);
|
|
199
234
|
const filterText = typeof options.filter === 'string' ? options.filter.trim().toLowerCase() : '';
|
|
@@ -205,8 +240,10 @@ const buildRows = async (options) => {
|
|
|
205
240
|
registerCoreRoutes(router);
|
|
206
241
|
// 2. Try to load application routes if available
|
|
207
242
|
try {
|
|
208
|
-
const
|
|
209
|
-
registerRoutes
|
|
243
|
+
const registerRoutes = await loadProjectRouteRegistrar();
|
|
244
|
+
if (typeof registerRoutes === 'function') {
|
|
245
|
+
registerRoutes(router);
|
|
246
|
+
}
|
|
210
247
|
}
|
|
211
248
|
catch {
|
|
212
249
|
// routes/api.ts not found, continue with just core routes
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ScheduleCliSupport.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/schedule/ScheduleCliSupport.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ScheduleCliSupport.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/schedule/ScheduleCliSupport.ts"],"names":[],"mappings":"AAyPA,eAAO,MAAM,kBAAkB;sCAzEc,OAAO,CAAC,OAAO,CAAC;mBA2EtC,OAAO,CAAC,IAAI,CAAC;gCA3BG,OAAO,CAAC,IAAI,CAAC;EAqClD,CAAC;AAEH,eAAe,kBAAkB,CAAC"}
|
|
@@ -14,6 +14,28 @@ const isSchedule = (value) => {
|
|
|
14
14
|
return false;
|
|
15
15
|
return 'name' in value && typeof value.name === 'string';
|
|
16
16
|
};
|
|
17
|
+
const getDefaultExport = (moduleNamespace) => {
|
|
18
|
+
return Object.hasOwn(moduleNamespace, 'default') ? moduleNamespace['default'] : undefined;
|
|
19
|
+
};
|
|
20
|
+
const flattenScheduleCandidates = (moduleNamespace) => {
|
|
21
|
+
const candidates = [
|
|
22
|
+
...Object.values(moduleNamespace),
|
|
23
|
+
getDefaultExport(moduleNamespace),
|
|
24
|
+
];
|
|
25
|
+
return candidates.flatMap((value) => (Array.isArray(value) ? value : [value]));
|
|
26
|
+
};
|
|
27
|
+
const collectSchedules = (moduleNamespace) => {
|
|
28
|
+
const flattenedCandidates = flattenScheduleCandidates(moduleNamespace);
|
|
29
|
+
const seen = new Set();
|
|
30
|
+
return flattenedCandidates.filter(isSchedule).filter((schedule) => {
|
|
31
|
+
const normalizedName = schedule.name.trim();
|
|
32
|
+
if (normalizedName === '' || seen.has(normalizedName)) {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
seen.add(normalizedName);
|
|
36
|
+
return true;
|
|
37
|
+
});
|
|
38
|
+
};
|
|
17
39
|
const getProjectScheduleLoaders = () => [
|
|
18
40
|
useFileLoader('app/Schedules/index.ts'),
|
|
19
41
|
useFileLoader('app/Schedules.ts'),
|
|
@@ -33,16 +55,33 @@ const getProjectSourceCliEntry = (projectRoot) => {
|
|
|
33
55
|
}
|
|
34
56
|
return undefined;
|
|
35
57
|
};
|
|
36
|
-
const
|
|
58
|
+
const getCurrentCliScript = () => {
|
|
37
59
|
const script = String(process.argv[1] ?? '').trim();
|
|
38
60
|
if (script.length === 0)
|
|
39
|
-
return
|
|
61
|
+
return undefined;
|
|
40
62
|
const resolvedScript = path.resolve(script);
|
|
63
|
+
return existsSync(resolvedScript) ? resolvedScript : undefined;
|
|
64
|
+
};
|
|
65
|
+
const isRunningProjectSourceCli = (projectRoot) => {
|
|
66
|
+
const resolvedScript = getCurrentCliScript();
|
|
67
|
+
if (resolvedScript === undefined)
|
|
68
|
+
return false;
|
|
41
69
|
const sourceCliEntry = getProjectSourceCliEntry(projectRoot);
|
|
42
70
|
if (sourceCliEntry === undefined)
|
|
43
71
|
return false;
|
|
44
72
|
return resolvedScript === path.resolve(sourceCliEntry);
|
|
45
73
|
};
|
|
74
|
+
const getScheduleReentryScript = (projectRoot) => {
|
|
75
|
+
const sourceCliEntry = getProjectSourceCliEntry(projectRoot);
|
|
76
|
+
if (sourceCliEntry !== undefined) {
|
|
77
|
+
return path.relative(projectRoot, sourceCliEntry);
|
|
78
|
+
}
|
|
79
|
+
const currentCliScript = getCurrentCliScript();
|
|
80
|
+
if (currentCliScript === undefined)
|
|
81
|
+
return undefined;
|
|
82
|
+
const relativeCurrentScript = path.relative(projectRoot, currentCliScript);
|
|
83
|
+
return relativeCurrentScript.startsWith('..') ? currentCliScript : relativeCurrentScript;
|
|
84
|
+
};
|
|
46
85
|
const getExistingProjectSchedulePath = () => {
|
|
47
86
|
for (const loader of getProjectScheduleLoaders()) {
|
|
48
87
|
if (loader.exists())
|
|
@@ -63,7 +102,7 @@ const tryLoadProjectScheduleModuleFromFiles = async () => {
|
|
|
63
102
|
}
|
|
64
103
|
try {
|
|
65
104
|
return {
|
|
66
|
-
module: await entry.loader.
|
|
105
|
+
module: await entry.loader.getModule(),
|
|
67
106
|
loadedPath: entry.loadedPath,
|
|
68
107
|
};
|
|
69
108
|
}
|
|
@@ -74,13 +113,16 @@ const tryLoadProjectScheduleModuleFromFiles = async () => {
|
|
|
74
113
|
return tryAt(0);
|
|
75
114
|
};
|
|
76
115
|
const loadAppScheduleModule = async () => {
|
|
116
|
+
const fileLoaded = await tryLoadProjectScheduleModuleFromFiles();
|
|
117
|
+
if (fileLoaded !== undefined) {
|
|
118
|
+
return fileLoaded;
|
|
119
|
+
}
|
|
77
120
|
try {
|
|
78
121
|
return {
|
|
79
122
|
module: (await import('../../../../app/Schedules/index.js')),
|
|
80
123
|
};
|
|
81
124
|
}
|
|
82
125
|
catch {
|
|
83
|
-
const fileLoaded = await tryLoadProjectScheduleModuleFromFiles();
|
|
84
126
|
return fileLoaded ?? { module: {} };
|
|
85
127
|
}
|
|
86
128
|
};
|
|
@@ -88,8 +130,8 @@ const loadScheduleModules = async () => {
|
|
|
88
130
|
const coreSchedules = await import('../../../schedules/index.js');
|
|
89
131
|
const appSchedules = await loadAppScheduleModule();
|
|
90
132
|
return {
|
|
91
|
-
core:
|
|
92
|
-
app:
|
|
133
|
+
core: collectSchedules(coreSchedules),
|
|
134
|
+
app: collectSchedules(appSchedules.module),
|
|
93
135
|
};
|
|
94
136
|
};
|
|
95
137
|
const ensureProjectSourceContext = async () => {
|
|
@@ -108,14 +150,13 @@ const ensureProjectSourceContext = async () => {
|
|
|
108
150
|
if (isRunningProjectSourceCli(projectRoot)) {
|
|
109
151
|
return false;
|
|
110
152
|
}
|
|
111
|
-
const
|
|
112
|
-
if (
|
|
113
|
-
throw ErrorFactory.createCliError('Source schedules require a project CLI entrypoint at bin/zin.ts or bin/zintrust.ts');
|
|
153
|
+
const reentryScript = getScheduleReentryScript(projectRoot);
|
|
154
|
+
if (reentryScript === undefined) {
|
|
155
|
+
throw ErrorFactory.createCliError('Source schedules require either a project CLI entrypoint at bin/zin.ts or bin/zintrust.ts, or a resolvable current CLI script.');
|
|
114
156
|
}
|
|
115
|
-
const relativeSourceCliEntry = path.relative(projectRoot, sourceCliEntry);
|
|
116
157
|
const exitCode = await SpawnUtil.spawnAndWait({
|
|
117
158
|
command: 'tsx',
|
|
118
|
-
args: [
|
|
159
|
+
args: [reentryScript, ...process.argv.slice(2)],
|
|
119
160
|
cwd: projectRoot,
|
|
120
161
|
env: {
|
|
121
162
|
...process.env,
|
|
@@ -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;AAiBH,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;AAumBD,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;AAwJD;;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"}
|
|
@@ -7,6 +7,7 @@ import { EnvData } from '../scaffolding/env.js';
|
|
|
7
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
|
+
import { isNonEmptyString } from '../../helper/index.js';
|
|
10
11
|
import { randomBytes } from '../../node-singletons/crypto.js';
|
|
11
12
|
import fs from '../../node-singletons/fs.js';
|
|
12
13
|
import * as path from '../../node-singletons/path.js';
|
|
@@ -24,11 +25,38 @@ const readBundledGovernancePackage = () => {
|
|
|
24
25
|
const SAFE_PATH = '/usr/local/bin:/usr/bin:/bin';
|
|
25
26
|
const NPM_VIEW_TIMEOUT_MS = 1500;
|
|
26
27
|
const publishedVersionCache = new Map();
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
const SAFE_NPM_ENV_KEYS = Object.freeze([
|
|
29
|
+
'HOME',
|
|
30
|
+
'USERPROFILE',
|
|
31
|
+
'APPDATA',
|
|
32
|
+
'LOCALAPPDATA',
|
|
33
|
+
'npm_config_userconfig',
|
|
34
|
+
'npm_config_cache',
|
|
35
|
+
'NPM_CONFIG_CACHE',
|
|
36
|
+
'npm_config_registry',
|
|
37
|
+
'NPM_CONFIG_REGISTRY',
|
|
38
|
+
'HTTP_PROXY',
|
|
39
|
+
'HTTPS_PROXY',
|
|
40
|
+
'NO_PROXY',
|
|
41
|
+
'http_proxy',
|
|
42
|
+
'https_proxy',
|
|
43
|
+
'no_proxy',
|
|
44
|
+
'SSL_CERT_FILE',
|
|
45
|
+
'NODE_EXTRA_CA_CERTS',
|
|
46
|
+
]);
|
|
47
|
+
const createSafeNpmEnv = () => {
|
|
48
|
+
const env = {
|
|
49
|
+
NODE_ENV: process.env['NODE_ENV'] ?? 'development',
|
|
50
|
+
PATH: SAFE_PATH,
|
|
51
|
+
};
|
|
52
|
+
for (const key of SAFE_NPM_ENV_KEYS) {
|
|
53
|
+
const value = process.env[key];
|
|
54
|
+
if (isNonEmptyString(value)) {
|
|
55
|
+
env[key] = value;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return env;
|
|
59
|
+
};
|
|
32
60
|
const loadPublishedNpmVersion = (packageName) => {
|
|
33
61
|
if (publishedVersionCache.has(packageName)) {
|
|
34
62
|
return publishedVersionCache.get(packageName);
|
|
@@ -563,6 +591,14 @@ const createDirectoriesForState = (state) => {
|
|
|
563
591
|
const template = resolveTemplate(state.templateName);
|
|
564
592
|
return createDirectories(state.projectPath, template?.directories ?? []);
|
|
565
593
|
};
|
|
594
|
+
const canReuseExistingProjectPath = (projectPath) => {
|
|
595
|
+
try {
|
|
596
|
+
return fs.statSync(projectPath).isDirectory() && fs.readdirSync(projectPath).length === 0;
|
|
597
|
+
}
|
|
598
|
+
catch {
|
|
599
|
+
return false;
|
|
600
|
+
}
|
|
601
|
+
};
|
|
566
602
|
const createFilesForState = (state) => {
|
|
567
603
|
const template = resolveTemplate(state.templateName);
|
|
568
604
|
const variables = state.variables;
|
|
@@ -622,9 +658,12 @@ const scaffoldWithState = async (state, options
|
|
|
622
658
|
}
|
|
623
659
|
prepareContext(state, options);
|
|
624
660
|
if (fs.existsSync(state.projectPath)) {
|
|
625
|
-
if (options.overwrite === true) {
|
|
661
|
+
if (options.overwrite === true || options.force === true) {
|
|
626
662
|
fs.rmSync(state.projectPath, { recursive: true, force: true });
|
|
627
663
|
}
|
|
664
|
+
else if (canReuseExistingProjectPath(state.projectPath)) {
|
|
665
|
+
Logger.info(`Reusing empty project directory: ${state.projectPath}`);
|
|
666
|
+
}
|
|
628
667
|
else {
|
|
629
668
|
return {
|
|
630
669
|
success: false,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spawn.d.ts","sourceRoot":"","sources":["../../../../src/cli/utils/spawn.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"spawn.d.ts","sourceRoot":"","sources":["../../../../src/cli/utils/spawn.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAiDD,eAAO,MAAM,SAAS;wBACM,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC;EAiF7D,CAAC"}
|
package/src/cli/utils/spawn.js
CHANGED
|
@@ -3,6 +3,7 @@ import { ErrorFactory } from '../../exceptions/ZintrustError.js';
|
|
|
3
3
|
import { spawn } from '../../node-singletons/child-process.js';
|
|
4
4
|
import { existsSync } from '../../node-singletons/fs.js';
|
|
5
5
|
import * as path from '../../node-singletons/path.js';
|
|
6
|
+
import { fileURLToPath } from '../../node-singletons/url.js';
|
|
6
7
|
const getExitCode = (exitCode, signal) => {
|
|
7
8
|
if (typeof exitCode === 'number')
|
|
8
9
|
return exitCode;
|
|
@@ -10,22 +11,28 @@ const getExitCode = (exitCode, signal) => {
|
|
|
10
11
|
return 0;
|
|
11
12
|
return 1;
|
|
12
13
|
};
|
|
14
|
+
const CURRENT_PACKAGE_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../../..');
|
|
15
|
+
const buildBinCandidates = (binDir, command) => process.platform === 'win32'
|
|
16
|
+
? [
|
|
17
|
+
path.join(binDir, `${command}.cmd`),
|
|
18
|
+
path.join(binDir, `${command}.exe`),
|
|
19
|
+
path.join(binDir, `${command}.bat`),
|
|
20
|
+
path.join(binDir, command),
|
|
21
|
+
]
|
|
22
|
+
: [path.join(binDir, command)];
|
|
13
23
|
const resolveLocalBin = (command, cwd) => {
|
|
14
24
|
// If command is already a path, leave it alone.
|
|
15
25
|
if (command.includes('/') || command.includes('\\'))
|
|
16
26
|
return command;
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
for (const candidate of candidates) {
|
|
27
|
-
if (existsSync(candidate))
|
|
28
|
-
return candidate;
|
|
27
|
+
const binDirs = [
|
|
28
|
+
path.join(cwd, 'node_modules', '.bin'),
|
|
29
|
+
path.join(CURRENT_PACKAGE_ROOT, 'node_modules', '.bin'),
|
|
30
|
+
].filter((value, index, items) => items.indexOf(value) === index);
|
|
31
|
+
for (const binDir of binDirs) {
|
|
32
|
+
for (const candidate of buildBinCandidates(binDir, command)) {
|
|
33
|
+
if (existsSync(candidate))
|
|
34
|
+
return candidate;
|
|
35
|
+
}
|
|
29
36
|
}
|
|
30
37
|
return command;
|
|
31
38
|
};
|
|
@@ -34,7 +41,6 @@ const buildCommandNotFoundMessage = (command) => {
|
|
|
34
41
|
return [
|
|
35
42
|
"Error: 'tsx' not found on PATH.",
|
|
36
43
|
'Install it in the project with "npm install -D tsx".',
|
|
37
|
-
'If you want a machine-wide fallback, install it globally with "npm install -g tsx".',
|
|
38
44
|
].join(' ');
|
|
39
45
|
}
|
|
40
46
|
return `Error: '${command}' not found on PATH.`;
|
package/src/config/env.d.ts
CHANGED
|
@@ -191,6 +191,8 @@ export declare const Env: Readonly<{
|
|
|
191
191
|
JWT_REVOCATION_DRIVER: string;
|
|
192
192
|
JWT_REVOCATION_DB_CONNECTION: string;
|
|
193
193
|
JWT_REVOCATION_DB_TABLE: string;
|
|
194
|
+
BULLETPROOF_DEVICE_DB_CONNECTION: string;
|
|
195
|
+
BULLETPROOF_DEVICE_DB_TABLE: string;
|
|
194
196
|
JWT_REVOCATION_REDIS_DB: number;
|
|
195
197
|
JWT_REVOCATION_REDIS_PREFIX: string;
|
|
196
198
|
JWT_REVOCATION_KV_BINDING: string;
|
package/src/config/env.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../../src/config/env.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAGhD,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,MAAM,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAClF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,aAAa,EAAE,OAAO,CAAC;IACvB,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB,CAAC;AAsNF,eAAO,MAAM,cAAc,QAAO,WAAW,GAAG,SAAwB,CAAC;AAEzE,eAAO,MAAM,mBAAmB,GAAI,UAAU,MAAM,EAAE,WAAW,MAAM,KAAG,MAKzE,CAAC;AAEF,eAAO,MAAM,WAAW,GAAI,KAAK,MAAM,KAAG,MAAM,GAAG,SAKlD,CAAC;AAEF,eAAO,MAAM,GAAG,GAAI,KAAK,MAAM,KAAG,OAGjC,CAAC;AAEF,eAAO,MAAM,WAAW,GAAI,KAAK,MAAM,KAAG,MAAM,GAAG,SAKlD,CAAC;AAEF,eAAO,MAAM,eAAe,QAAO,MAAM,CAAC,MAAM,EAAE,MAAM,CAEvD,CAAC;AAEF,eAAO,MAAM,gBAAgB,QAAO,gBAAyC,CAAC;AAG9E,eAAO,MAAM,GAAG,GAAI,KAAK,MAAM,EAAE,eAAe,MAAM,KAAG,MAIxD,CAAC;AAEF,eAAO,MAAM,kBAAkB,QAAO,MAMrC,CAAC;AAEF,eAAO,MAAM,MAAM,GAAI,KAAK,MAAM,EAAE,cAAc,MAAM,KAAG,MAI1D,CAAC;AAEF,eAAO,MAAM,QAAQ,GAAI,KAAK,MAAM,EAAE,eAAe,MAAM,KAAG,MAI7D,CAAC;AAEF,eAAO,MAAM,OAAO,GAAI,KAAK,MAAM,EAAE,eAAe,OAAO,KAAG,OAI7D,CAAC;AAEF,eAAO,MAAM,GAAG,GAAI,KAAK,MAAM,EAAE,OAAO,MAAM,KAAG,IAGhD,CAAC;AAEF,eAAO,MAAM,KAAK,GAAI,KAAK,MAAM,KAAG,IAInC,CAAC;AAEF,eAAO,MAAM,SAAS,GAAI,QAAQ,SAAS,GAAG,IAAI,KAAG,IAEpD,CAAC;AAEF,eAAO,MAAM,QAAQ,QAAO,MAAM,CAAC,MAAM,EAAE,MAAM,CAOhD,CAAC;AAEF,eAAO,MAAM,kBAAkB,QAAO,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAKjE,CAAC;AACF,eAAO,MAAM,mBAAmB,QAAuC,CAAC;AAKxE,eAAO,MAAM,GAAG;eAnES,MAAM,iBAAiB,MAAM,KAAG,MAAM;uBA1B9B,MAAM,KAAG,MAAM,GAAG,SAAS;kBAwChC,MAAM,gBAAgB,MAAM,KAAG,MAAM;mBAYpC,MAAM,iBAAiB,OAAO,KAAG,OAAO;oBANvC,MAAM,iBAAiB,MAAM,KAAG,MAAM;eAvC3C,MAAM,KAAG,OAAO;eAmDhB,MAAM,SAAS,MAAM,KAAG,IAAI;iBAK1B,MAAM,KAAG,IAAI;wBAMN,SAAS,GAAG,IAAI,KAAG,IAAI;oBAI7B,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;uBA7DjB,MAAM,KAAG,MAAM,GAAG,SAAS;2BAOzB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;4BAIrB,gBAAgB;cAuFN,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC
|
|
1
|
+
{"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../../src/config/env.ts"],"names":[],"mappings":"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"}
|
package/src/config/env.js
CHANGED
|
@@ -440,6 +440,8 @@ export const Env = Object.freeze({
|
|
|
440
440
|
JWT_REVOCATION_DRIVER: get('JWT_REVOCATION_DRIVER', 'database'),
|
|
441
441
|
JWT_REVOCATION_DB_CONNECTION: get('JWT_REVOCATION_DB_CONNECTION', 'default'),
|
|
442
442
|
JWT_REVOCATION_DB_TABLE: get('JWT_REVOCATION_DB_TABLE', 'zintrust_jwt_revocations'),
|
|
443
|
+
BULLETPROOF_DEVICE_DB_CONNECTION: get('BULLETPROOF_DEVICE_DB_CONNECTION', 'default'),
|
|
444
|
+
BULLETPROOF_DEVICE_DB_TABLE: get('BULLETPROOF_DEVICE_DB_TABLE', 'zintrust_bulletproof_devices'),
|
|
443
445
|
JWT_REVOCATION_REDIS_DB: getInt('JWT_REVOCATION_REDIS_DB', 0),
|
|
444
446
|
JWT_REVOCATION_REDIS_PREFIX: get('JWT_REVOCATION_REDIS_PREFIX', 'zt:jwt:revoked:'),
|
|
445
447
|
JWT_REVOCATION_KV_BINDING: get('JWT_REVOCATION_KV_BINDING', 'CACHE'),
|
package/src/config/logger.d.ts
CHANGED
|
@@ -6,23 +6,21 @@ interface ILogger {
|
|
|
6
6
|
error(message: string, error?: unknown, category?: string): void;
|
|
7
7
|
fatal(message: string, error?: unknown, category?: string): void;
|
|
8
8
|
}
|
|
9
|
+
interface ILoggerNamespace extends ILogger {
|
|
10
|
+
cleanLogsOnce(): Promise<string[]>;
|
|
11
|
+
scope(scope: string): ILogger;
|
|
12
|
+
addSink(fn: LogSink): () => void;
|
|
13
|
+
withTraceSkipContext(context?: Record<string, unknown>): Record<string, unknown>;
|
|
14
|
+
shouldSkipTraceLogContext(context?: Record<string, unknown>): boolean;
|
|
15
|
+
}
|
|
9
16
|
/**
|
|
10
17
|
* External log sink. Receives every log line after the built-in sinks have fired.
|
|
11
18
|
* Return value is ignored; errors are swallowed to protect the caller.
|
|
12
19
|
*/
|
|
13
20
|
export type LogSink = (level: LogLevel, message: string, context?: Record<string, unknown>) => void;
|
|
21
|
+
export declare const withTraceSkipContext: (context?: Record<string, unknown>) => Record<string, unknown>;
|
|
22
|
+
export declare const shouldSkipTraceLogContext: (context?: Record<string, unknown>) => boolean;
|
|
14
23
|
export declare const cleanLogsOnce: () => Promise<string[]>;
|
|
15
|
-
export declare const Logger:
|
|
16
|
-
debug: (message: string, data?: unknown, category?: string) => void;
|
|
17
|
-
info: (message: string, data?: unknown, category?: string) => void;
|
|
18
|
-
warn: (message: string, data?: unknown, category?: string) => void;
|
|
19
|
-
error: (message: string, error?: unknown, category?: string) => void;
|
|
20
|
-
fatal: (message: string, error?: unknown, category?: string) => void;
|
|
21
|
-
cleanLogsOnce: () => Promise<string[]>;
|
|
22
|
-
scope: (scope: string) => ILogger;
|
|
23
|
-
addSink: (fn: LogSink) => (() => void);
|
|
24
|
-
withTraceSkipContext: (context?: Record<string, unknown>) => Record<string, unknown>;
|
|
25
|
-
shouldSkipTraceLogContext: (context?: Record<string, unknown>) => boolean;
|
|
26
|
-
}>;
|
|
24
|
+
export declare const Logger: ILoggerNamespace;
|
|
27
25
|
export default Logger;
|
|
28
26
|
//# 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;
|
|
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;AAED,UAAU,gBAAiB,SAAQ,OAAO;IACxC,aAAa,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACnC,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;IAC9B,OAAO,CAAC,EAAE,EAAE,OAAO,GAAG,MAAM,IAAI,CAAC;IACjC,oBAAoB,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjF,yBAAyB,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC;CACvE;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;AAIpG,eAAO,MAAM,oBAAoB,GAC/B,UAAU,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAChC,MAAM,CAAC,MAAM,EAAE,OAAO,CASxB,CAAC;AAEF,eAAO,MAAM,yBAAyB,GAAI,UAAU,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,OAE7E,CAAC;AAkCF,eAAO,MAAM,aAAa,QAAa,OAAO,CAAC,MAAM,EAAE,CAYtD,CAAC;AAEF,eAAO,MAAM,MAAM,EAAE,gBAWnB,CAAC;AAEH,eAAe,MAAM,CAAC"}
|