@getstrata/bootstrap 0.2.23 → 0.2.26
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/dist/bootstrap/applicationRegistry.d.ts +1 -1
- package/dist/bootstrap/buildWebModuleRoutes.d.ts +9 -0
- package/dist/bootstrap/config.d.ts +1 -1
- package/dist/bootstrap/env.d.ts +1 -1
- package/dist/bootstrap/membershipService.d.ts +1 -1
- package/dist/bootstrap/public-api.d.ts +4 -2
- package/dist/bootstrap/routeRegistry.d.ts +1 -1
- package/dist/entries/applicationRegistry.js +1 -1
- package/dist/entries/buildModuleRoutes.js +4 -219
- package/dist/entries/buildWebModuleRoutes.js +435 -0
- package/dist/entries/config.js +1 -1
- package/dist/entries/context.js +3 -19
- package/dist/entries/createWebRoutes.js +100 -682
- package/dist/entries/dependencies.js +3 -19
- package/dist/entries/http/securedRouteModelBinding.js +0 -7
- package/dist/entries/httpKernel.js +1 -1
- package/dist/entries/membershipService.js +2 -392
- package/dist/entries/providers/view.js +1 -12
- package/dist/entries/providers.js +3 -19
- package/dist/entries/queue/defaultJobs.js +0 -3
- package/dist/entries/web/routing.js +1 -8
- package/dist/index.js +139 -373
- package/package.json +8 -3
|
@@ -0,0 +1,435 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// ../../src/bootstrap/buildWebModuleRoutes.ts
|
|
3
|
+
import { applyMiddlewareToRoutes as applyMiddlewareToRoutes2 } from "@getstrata/core/http/middleware";
|
|
4
|
+
|
|
5
|
+
// ../../src/bootstrap/buildModuleRoutes.ts
|
|
6
|
+
import { conditionalJsonResponse } from "@getstrata/core/http";
|
|
7
|
+
import { applyMiddlewareToRoutes } from "@getstrata/core/http/middleware";
|
|
8
|
+
|
|
9
|
+
// ../../src/bootstrap/httpKernel.ts
|
|
10
|
+
import {
|
|
11
|
+
createAuthMiddleware,
|
|
12
|
+
createAuthorizeMiddleware,
|
|
13
|
+
createBodySizeLimitMiddleware,
|
|
14
|
+
createCorsMiddleware,
|
|
15
|
+
createCsrfMiddleware,
|
|
16
|
+
createFlashMiddleware,
|
|
17
|
+
createLoginThrottleMiddleware,
|
|
18
|
+
createMembershipMiddleware,
|
|
19
|
+
createMemoryThrottleMiddleware,
|
|
20
|
+
createMetricsMiddleware,
|
|
21
|
+
createRequestLoggingMiddleware,
|
|
22
|
+
createRequireAbilityMiddleware,
|
|
23
|
+
createRequireAuthMiddleware,
|
|
24
|
+
createRequireGlobalAdminMiddleware,
|
|
25
|
+
createRequireWebAuthMiddleware,
|
|
26
|
+
createSecurityHeadersMiddleware,
|
|
27
|
+
createTenantMiddleware,
|
|
28
|
+
createThrottleMiddleware,
|
|
29
|
+
createTracingMiddleware,
|
|
30
|
+
isPublicReadsEnabled,
|
|
31
|
+
requestIdMiddleware,
|
|
32
|
+
withMiddleware
|
|
33
|
+
} from "@getstrata/core";
|
|
34
|
+
|
|
35
|
+
// ../../src/config/frontend.ts
|
|
36
|
+
function readFrontendMode() {
|
|
37
|
+
const mode = (process.env.FRONTEND_MODE ?? "api").trim();
|
|
38
|
+
if (mode === "server-htmx") {
|
|
39
|
+
return "server-htmx";
|
|
40
|
+
}
|
|
41
|
+
if (mode === "spa-react") {
|
|
42
|
+
return "spa-react";
|
|
43
|
+
}
|
|
44
|
+
return "api";
|
|
45
|
+
}
|
|
46
|
+
function isViewsEnabled() {
|
|
47
|
+
return readFrontendMode() === "server-htmx";
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// ../../src/config/rateLimit.ts
|
|
51
|
+
var LOCAL_LOGIN_RATE_LIMIT = {
|
|
52
|
+
maxAttempts: 100,
|
|
53
|
+
decaySeconds: 60
|
|
54
|
+
};
|
|
55
|
+
var PRODUCTION_LOGIN_RATE_LIMIT = {
|
|
56
|
+
maxAttempts: 5,
|
|
57
|
+
decaySeconds: 900
|
|
58
|
+
};
|
|
59
|
+
function isLocalAppEnv() {
|
|
60
|
+
return (process.env.APP_ENV ?? "local") === "local";
|
|
61
|
+
}
|
|
62
|
+
function parsePositiveInt(value, fallback) {
|
|
63
|
+
const parsed = Number(value);
|
|
64
|
+
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
65
|
+
return fallback;
|
|
66
|
+
}
|
|
67
|
+
return Math.trunc(parsed);
|
|
68
|
+
}
|
|
69
|
+
function resolveLoginRateLimit() {
|
|
70
|
+
const defaults = isLocalAppEnv() ? LOCAL_LOGIN_RATE_LIMIT : PRODUCTION_LOGIN_RATE_LIMIT;
|
|
71
|
+
return {
|
|
72
|
+
maxAttempts: parsePositiveInt(process.env.LOGIN_RATE_LIMIT_PER_WINDOW, defaults.maxAttempts),
|
|
73
|
+
decaySeconds: parsePositiveInt(process.env.LOGIN_RATE_LIMIT_WINDOW_SECONDS, defaults.decaySeconds)
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
function resolveRegisterRateLimit() {
|
|
77
|
+
const defaults = isLocalAppEnv() ? { maxAttempts: 100, decaySeconds: 60 } : { maxAttempts: 10, decaySeconds: 60 };
|
|
78
|
+
return {
|
|
79
|
+
maxAttempts: parsePositiveInt(process.env.REGISTER_RATE_LIMIT_PER_WINDOW, defaults.maxAttempts),
|
|
80
|
+
decaySeconds: parsePositiveInt(process.env.REGISTER_RATE_LIMIT_WINDOW_SECONDS ?? process.env.REGISTER_RATE_LIMIT_WINDOW_MS ? String(Number(process.env.REGISTER_RATE_LIMIT_WINDOW_MS) / 1000) : undefined, defaults.decaySeconds)
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// ../../src/bootstrap/config.ts
|
|
85
|
+
import {
|
|
86
|
+
CORE_AUTH_TOKEN,
|
|
87
|
+
CORE_CACHE_TOKEN,
|
|
88
|
+
CORE_CONFIG_TOKEN,
|
|
89
|
+
CORE_EVENT_BUS_TOKEN,
|
|
90
|
+
CORE_POLICY_GATE_TOKEN,
|
|
91
|
+
CORE_QUEUE_TOKEN,
|
|
92
|
+
CORE_TOKEN_SERVICE_TOKEN
|
|
93
|
+
} from "@getstrata/core/contracts/serviceTokens";
|
|
94
|
+
var APP_PORT_CONFIG_KEY = "app.port";
|
|
95
|
+
var CACHE_TTL_MS_CONFIG_KEY = "cache.ttlMs";
|
|
96
|
+
var CACHE_MAX_ENTRIES_CONFIG_KEY = "cache.maxEntries";
|
|
97
|
+
var CACHE_DRIVER_CONFIG_KEY = "cache.driver";
|
|
98
|
+
var REDIS_URL_CONFIG_KEY = "cache.redisUrl";
|
|
99
|
+
var DATABASE_URL_CONFIG_KEY = "database.url";
|
|
100
|
+
var AUTH_DEV_HEADERS_CONFIG_KEY = "auth.allowDevHeaders";
|
|
101
|
+
var DEFAULT_APP_PORT = 3000;
|
|
102
|
+
var DEFAULT_CACHE_TTL_MS = 3600000;
|
|
103
|
+
var DEFAULT_CACHE_MAX_ENTRIES = 100;
|
|
104
|
+
var DEFAULT_CACHE_DRIVER = "array";
|
|
105
|
+
var DEFAULT_API_TOKEN = "";
|
|
106
|
+
var DEFAULT_QUEUE_DRIVER = "sync";
|
|
107
|
+
|
|
108
|
+
// ../../src/bootstrap/httpKernel.ts
|
|
109
|
+
class HttpKernel {
|
|
110
|
+
dependencies;
|
|
111
|
+
constructor(dependencies) {
|
|
112
|
+
this.dependencies = dependencies;
|
|
113
|
+
}
|
|
114
|
+
globalMiddleware() {
|
|
115
|
+
const auth = this.dependencies.container.resolve(CORE_AUTH_TOKEN);
|
|
116
|
+
return [
|
|
117
|
+
createCorsMiddleware(),
|
|
118
|
+
createSecurityHeadersMiddleware(),
|
|
119
|
+
createBodySizeLimitMiddleware(),
|
|
120
|
+
createTracingMiddleware(),
|
|
121
|
+
createMetricsMiddleware(),
|
|
122
|
+
createRequestLoggingMiddleware(),
|
|
123
|
+
requestIdMiddleware,
|
|
124
|
+
createAuthMiddleware(auth),
|
|
125
|
+
createMembershipMiddleware(),
|
|
126
|
+
createTenantMiddleware()
|
|
127
|
+
];
|
|
128
|
+
}
|
|
129
|
+
group(name) {
|
|
130
|
+
const auth = this.dependencies.container.resolve(CORE_AUTH_TOKEN);
|
|
131
|
+
switch (name) {
|
|
132
|
+
case "authenticated":
|
|
133
|
+
return [createRequireAuthMiddleware(auth)];
|
|
134
|
+
case "web":
|
|
135
|
+
return isViewsEnabled() ? [createFlashMiddleware(), createCsrfMiddleware()] : [];
|
|
136
|
+
case "api": {
|
|
137
|
+
if (!this.dependencies.container.has(CORE_CONFIG_TOKEN)) {
|
|
138
|
+
return [];
|
|
139
|
+
}
|
|
140
|
+
const config = this.dependencies.container.resolve(CORE_CONFIG_TOKEN);
|
|
141
|
+
const redisUrl = config.get(REDIS_URL_CONFIG_KEY)?.trim() ?? "";
|
|
142
|
+
if (!redisUrl) {
|
|
143
|
+
const maxAttempts2 = Number(process.env.RATE_LIMIT_PER_MINUTE ?? "120");
|
|
144
|
+
return [
|
|
145
|
+
createMemoryThrottleMiddleware({
|
|
146
|
+
maxAttempts: Number.isFinite(maxAttempts2) ? maxAttempts2 : 120,
|
|
147
|
+
decaySeconds: 60
|
|
148
|
+
})
|
|
149
|
+
];
|
|
150
|
+
}
|
|
151
|
+
const maxAttempts = Number(process.env.RATE_LIMIT_PER_MINUTE ?? "120");
|
|
152
|
+
return [
|
|
153
|
+
createThrottleMiddleware({
|
|
154
|
+
redisUrl,
|
|
155
|
+
maxAttempts: Number.isFinite(maxAttempts) ? maxAttempts : 120,
|
|
156
|
+
decaySeconds: 60
|
|
157
|
+
})
|
|
158
|
+
];
|
|
159
|
+
}
|
|
160
|
+
default:
|
|
161
|
+
throw new Error(`Unknown middleware group "${name}".`);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
wrap(groups, handler) {
|
|
165
|
+
const names = Array.isArray(groups) ? groups : [groups];
|
|
166
|
+
const middleware = names.flatMap((name) => this.group(name));
|
|
167
|
+
if (middleware.length === 0) {
|
|
168
|
+
return handler;
|
|
169
|
+
}
|
|
170
|
+
return withMiddleware(...middleware)(handler);
|
|
171
|
+
}
|
|
172
|
+
wrapApi(handler) {
|
|
173
|
+
return this.wrap(["api", "authenticated"], handler);
|
|
174
|
+
}
|
|
175
|
+
wrapWeb(handler) {
|
|
176
|
+
return handler;
|
|
177
|
+
}
|
|
178
|
+
wrapWebPublicRead(handler) {
|
|
179
|
+
if (isPublicReadsEnabled()) {
|
|
180
|
+
return this.wrapWeb(handler);
|
|
181
|
+
}
|
|
182
|
+
return this.wrapWebAuthenticated(handler);
|
|
183
|
+
}
|
|
184
|
+
wrapWebAuthenticated(handler) {
|
|
185
|
+
const auth = this.dependencies.container.resolve(CORE_AUTH_TOKEN);
|
|
186
|
+
return withMiddleware(createRequireWebAuthMiddleware(auth))(handler);
|
|
187
|
+
}
|
|
188
|
+
wrapWebAbility(ability, handler) {
|
|
189
|
+
const auth = this.dependencies.container.resolve(CORE_AUTH_TOKEN);
|
|
190
|
+
const abilityChecker = this.dependencies.container.resolve(CORE_TOKEN_SERVICE_TOKEN);
|
|
191
|
+
const requireAbility = createRequireAbilityMiddleware(abilityChecker);
|
|
192
|
+
const middleware = [createRequireWebAuthMiddleware(auth), requireAbility(ability)];
|
|
193
|
+
return withMiddleware(...middleware)(handler);
|
|
194
|
+
}
|
|
195
|
+
wrapWebGlobalAdmin(handler) {
|
|
196
|
+
const auth = this.dependencies.container.resolve(CORE_AUTH_TOKEN);
|
|
197
|
+
const middleware = [createRequireWebAuthMiddleware(auth), createRequireGlobalAdminMiddleware()];
|
|
198
|
+
return withMiddleware(...middleware)(handler);
|
|
199
|
+
}
|
|
200
|
+
wrapAuthenticated(handler) {
|
|
201
|
+
return this.wrap("authenticated", handler);
|
|
202
|
+
}
|
|
203
|
+
wrapPublicRead(handler) {
|
|
204
|
+
if (isPublicReadsEnabled()) {
|
|
205
|
+
return handler;
|
|
206
|
+
}
|
|
207
|
+
return this.wrapAuthenticated(handler);
|
|
208
|
+
}
|
|
209
|
+
wrapGlobalAdmin(handler) {
|
|
210
|
+
const middleware = [...this.group("authenticated"), createRequireGlobalAdminMiddleware()];
|
|
211
|
+
return withMiddleware(...middleware)(handler);
|
|
212
|
+
}
|
|
213
|
+
wrapAbility(ability, handler) {
|
|
214
|
+
const abilityChecker = this.dependencies.container.resolve(CORE_TOKEN_SERVICE_TOKEN);
|
|
215
|
+
const requireAbility = createRequireAbilityMiddleware(abilityChecker);
|
|
216
|
+
const middleware = [...this.group("authenticated"), requireAbility(ability)];
|
|
217
|
+
return withMiddleware(...middleware)(handler);
|
|
218
|
+
}
|
|
219
|
+
wrapPolicy(resource, action, handler) {
|
|
220
|
+
const auth = this.dependencies.container.resolve(CORE_AUTH_TOKEN);
|
|
221
|
+
const gate = this.dependencies.container.resolve(CORE_POLICY_GATE_TOKEN);
|
|
222
|
+
return withMiddleware(createAuthorizeMiddleware(gate, auth, resource, action))(handler);
|
|
223
|
+
}
|
|
224
|
+
wrapLogin(handler) {
|
|
225
|
+
return this.wrapThrottle("login", resolveLoginRateLimit(), handler);
|
|
226
|
+
}
|
|
227
|
+
wrapRegister(handler) {
|
|
228
|
+
return this.wrapThrottle("register", resolveRegisterRateLimit(), handler);
|
|
229
|
+
}
|
|
230
|
+
wrapThrottle(scope, rateLimit, handler) {
|
|
231
|
+
const middleware = [];
|
|
232
|
+
const memoryKeyPrefix = scope === "login" ? "login-throttle:" : "register-throttle:";
|
|
233
|
+
if (this.dependencies.container.has(CORE_CONFIG_TOKEN)) {
|
|
234
|
+
const config = this.dependencies.container.resolve(CORE_CONFIG_TOKEN);
|
|
235
|
+
const redisUrl = config.get(REDIS_URL_CONFIG_KEY)?.trim() ?? "";
|
|
236
|
+
if (redisUrl) {
|
|
237
|
+
const throttle = scope === "login" ? createLoginThrottleMiddleware({
|
|
238
|
+
redisUrl,
|
|
239
|
+
maxAttempts: rateLimit.maxAttempts,
|
|
240
|
+
decaySeconds: rateLimit.decaySeconds
|
|
241
|
+
}) : createThrottleMiddleware({
|
|
242
|
+
redisUrl,
|
|
243
|
+
maxAttempts: rateLimit.maxAttempts,
|
|
244
|
+
decaySeconds: rateLimit.decaySeconds,
|
|
245
|
+
keyPrefix: memoryKeyPrefix
|
|
246
|
+
});
|
|
247
|
+
middleware.push(throttle);
|
|
248
|
+
} else {
|
|
249
|
+
middleware.push(createMemoryThrottleMiddleware({
|
|
250
|
+
maxAttempts: rateLimit.maxAttempts,
|
|
251
|
+
decaySeconds: rateLimit.decaySeconds,
|
|
252
|
+
keyPrefix: memoryKeyPrefix
|
|
253
|
+
}));
|
|
254
|
+
}
|
|
255
|
+
} else {
|
|
256
|
+
middleware.push(createMemoryThrottleMiddleware({
|
|
257
|
+
maxAttempts: rateLimit.maxAttempts,
|
|
258
|
+
decaySeconds: rateLimit.decaySeconds,
|
|
259
|
+
keyPrefix: memoryKeyPrefix
|
|
260
|
+
}));
|
|
261
|
+
}
|
|
262
|
+
if (middleware.length === 0) {
|
|
263
|
+
return handler;
|
|
264
|
+
}
|
|
265
|
+
return withMiddleware(...middleware)(handler);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
function createHttpKernel(dependencies) {
|
|
269
|
+
return new HttpKernel(dependencies);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// ../../src/bootstrap/discoverModules.ts
|
|
273
|
+
import { readdirSync } from "fs";
|
|
274
|
+
import { join } from "path";
|
|
275
|
+
import { pathToFileURL } from "url";
|
|
276
|
+
var DISCOVER_MODULES_STATE_KEY = Symbol.for("@getstrata/discoverModulesState");
|
|
277
|
+
function readDiscoverModulesState() {
|
|
278
|
+
const existing = globalThis[DISCOVER_MODULES_STATE_KEY];
|
|
279
|
+
if (existing) {
|
|
280
|
+
return existing;
|
|
281
|
+
}
|
|
282
|
+
const state = { appModules: [] };
|
|
283
|
+
globalThis[DISCOVER_MODULES_STATE_KEY] = state;
|
|
284
|
+
return state;
|
|
285
|
+
}
|
|
286
|
+
function configureModulesDirectory(modulesDir) {
|
|
287
|
+
readDiscoverModulesState().configuredModulesDir = modulesDir;
|
|
288
|
+
}
|
|
289
|
+
function resolveModulesDirectory(options) {
|
|
290
|
+
const state = readDiscoverModulesState();
|
|
291
|
+
if (options?.modulesDir) {
|
|
292
|
+
return options.modulesDir;
|
|
293
|
+
}
|
|
294
|
+
if (state.configuredModulesDir) {
|
|
295
|
+
return state.configuredModulesDir;
|
|
296
|
+
}
|
|
297
|
+
return join(import.meta.dir, "../modules");
|
|
298
|
+
}
|
|
299
|
+
async function loadDiscoveredModules(options) {
|
|
300
|
+
const modulesDirectory = resolveModulesDirectory(options);
|
|
301
|
+
let moduleNames;
|
|
302
|
+
try {
|
|
303
|
+
moduleNames = readdirSync(modulesDirectory, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
|
|
304
|
+
} catch (error) {
|
|
305
|
+
if (error.code === "ENOENT") {
|
|
306
|
+
return [];
|
|
307
|
+
}
|
|
308
|
+
throw error;
|
|
309
|
+
}
|
|
310
|
+
const modules = await Promise.all(moduleNames.map(async (moduleName) => {
|
|
311
|
+
const moduleUrl = pathToFileURL(join(modulesDirectory, moduleName, "index.ts")).href;
|
|
312
|
+
const loaded = await import(moduleUrl);
|
|
313
|
+
return loaded.default;
|
|
314
|
+
}));
|
|
315
|
+
return modules.filter((module) => module?.name !== undefined).sort((left, right) => (left.order ?? 100) - (right.order ?? 100));
|
|
316
|
+
}
|
|
317
|
+
async function ensureModulesLoaded(options) {
|
|
318
|
+
const state = readDiscoverModulesState();
|
|
319
|
+
if (state.appModules.length > 0) {
|
|
320
|
+
return state.appModules;
|
|
321
|
+
}
|
|
322
|
+
state.modulesReady ??= loadDiscoveredModules(options).then((modules) => {
|
|
323
|
+
state.appModules.splice(0, state.appModules.length, ...modules);
|
|
324
|
+
return state.appModules;
|
|
325
|
+
});
|
|
326
|
+
return state.modulesReady;
|
|
327
|
+
}
|
|
328
|
+
function discoverModules() {
|
|
329
|
+
return readDiscoverModulesState().appModules;
|
|
330
|
+
}
|
|
331
|
+
// ../../src/bootstrap/prefixRouteMap.ts
|
|
332
|
+
function prefixRouteMap(prefix, routes) {
|
|
333
|
+
const normalizedPrefix = prefix.replace(/\/$/, "");
|
|
334
|
+
const prefixed = {};
|
|
335
|
+
for (const [path, handler] of Object.entries(routes)) {
|
|
336
|
+
const normalizedPath = path.startsWith("/") ? path : `/${path}`;
|
|
337
|
+
prefixed[`${normalizedPrefix}${normalizedPath}`] = handler;
|
|
338
|
+
}
|
|
339
|
+
return prefixed;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// ../../src/bootstrap/routeRegistry.ts
|
|
343
|
+
class RouteRegistry {
|
|
344
|
+
routes = [];
|
|
345
|
+
register(route) {
|
|
346
|
+
this.routes.push(route);
|
|
347
|
+
}
|
|
348
|
+
clear() {
|
|
349
|
+
this.routes.length = 0;
|
|
350
|
+
}
|
|
351
|
+
list() {
|
|
352
|
+
return [...this.routes].sort((left, right) => left.path.localeCompare(right.path));
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
var ROUTE_REGISTRY_KEY = Symbol.for("@getstrata/routeRegistry");
|
|
356
|
+
function readSharedRouteRegistry() {
|
|
357
|
+
const globalRegistry = globalThis[ROUTE_REGISTRY_KEY];
|
|
358
|
+
if (globalRegistry) {
|
|
359
|
+
return globalRegistry;
|
|
360
|
+
}
|
|
361
|
+
const registry = new RouteRegistry;
|
|
362
|
+
globalThis[ROUTE_REGISTRY_KEY] = registry;
|
|
363
|
+
return registry;
|
|
364
|
+
}
|
|
365
|
+
var routeRegistry = readSharedRouteRegistry();
|
|
366
|
+
|
|
367
|
+
// ../../src/bootstrap/buildModuleRoutes.ts
|
|
368
|
+
function registerOpenApiRoute(method, path, middleware) {
|
|
369
|
+
routeRegistry.register({ method, path, middleware });
|
|
370
|
+
}
|
|
371
|
+
function registerOpenApiRouteMap(routes, middleware) {
|
|
372
|
+
const registered = {};
|
|
373
|
+
for (const [path, handler] of Object.entries(routes)) {
|
|
374
|
+
if (handler && typeof handler === "object" && !Array.isArray(handler)) {
|
|
375
|
+
const methodMap = handler;
|
|
376
|
+
registered[path] = methodMap;
|
|
377
|
+
for (const method of Object.keys(methodMap)) {
|
|
378
|
+
registerOpenApiRoute(method.toUpperCase(), path, middleware);
|
|
379
|
+
}
|
|
380
|
+
continue;
|
|
381
|
+
}
|
|
382
|
+
registered[path] = handler;
|
|
383
|
+
registerOpenApiRoute("GET", path, middleware);
|
|
384
|
+
}
|
|
385
|
+
return registered;
|
|
386
|
+
}
|
|
387
|
+
function createCachedJson(dependencies) {
|
|
388
|
+
return async (cacheKey, loader, tags = [], request) => {
|
|
389
|
+
const data = tags.length > 0 ? await dependencies.cache.tags(...tags).remember(cacheKey, loader) : await dependencies.cache.remember(cacheKey, loader);
|
|
390
|
+
return conditionalJsonResponse(request, data);
|
|
391
|
+
};
|
|
392
|
+
}
|
|
393
|
+
function buildModuleRoutes(dependencies, options = {}) {
|
|
394
|
+
const { apiPrefix = "", modules = discoverModules(), clearRegistry = true } = options;
|
|
395
|
+
if (clearRegistry) {
|
|
396
|
+
routeRegistry.clear();
|
|
397
|
+
}
|
|
398
|
+
const kernel = createHttpKernel(dependencies);
|
|
399
|
+
const middleware = [...kernel.globalMiddleware(), ...kernel.group("api")];
|
|
400
|
+
const cachedJson = createCachedJson(dependencies);
|
|
401
|
+
const moduleRoutes = {};
|
|
402
|
+
for (const module of modules) {
|
|
403
|
+
if (!module.routes) {
|
|
404
|
+
continue;
|
|
405
|
+
}
|
|
406
|
+
Object.assign(moduleRoutes, module.routes({ dependencies, cachedJson, kernel }));
|
|
407
|
+
}
|
|
408
|
+
const prefixedModuleRoutes = prefixRouteMap(apiPrefix, moduleRoutes);
|
|
409
|
+
return applyMiddlewareToRoutes(registerOpenApiRouteMap(prefixedModuleRoutes, ["global", "api"]), middleware);
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
// ../../src/bootstrap/buildWebModuleRoutes.ts
|
|
413
|
+
function buildWebModuleRoutes(dependencies, options = {}) {
|
|
414
|
+
const { modules = discoverModules(), clearRegistry = true, seedRoutes = {} } = options;
|
|
415
|
+
if (clearRegistry) {
|
|
416
|
+
routeRegistry.clear();
|
|
417
|
+
}
|
|
418
|
+
const kernel = createHttpKernel(dependencies);
|
|
419
|
+
const middleware = [...kernel.globalMiddleware(), ...kernel.group("web")];
|
|
420
|
+
const moduleRoutes = { ...seedRoutes };
|
|
421
|
+
for (const module of modules) {
|
|
422
|
+
if (!module.webRoutes) {
|
|
423
|
+
continue;
|
|
424
|
+
}
|
|
425
|
+
Object.assign(moduleRoutes, module.webRoutes({
|
|
426
|
+
dependencies,
|
|
427
|
+
cachedJson: async () => new Response(""),
|
|
428
|
+
kernel
|
|
429
|
+
}));
|
|
430
|
+
}
|
|
431
|
+
return applyMiddlewareToRoutes2(registerOpenApiRouteMap(moduleRoutes, ["global", "web"]), middleware);
|
|
432
|
+
}
|
|
433
|
+
export {
|
|
434
|
+
buildWebModuleRoutes
|
|
435
|
+
};
|
package/dist/entries/config.js
CHANGED
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
CORE_POLICY_GATE_TOKEN,
|
|
9
9
|
CORE_QUEUE_TOKEN,
|
|
10
10
|
CORE_TOKEN_SERVICE_TOKEN
|
|
11
|
-
} from "@getstrata/core/contracts/serviceTokens
|
|
11
|
+
} from "@getstrata/core/contracts/serviceTokens";
|
|
12
12
|
var APP_PORT_CONFIG_KEY = "app.port";
|
|
13
13
|
var CACHE_TTL_MS_CONFIG_KEY = "cache.ttlMs";
|
|
14
14
|
var CACHE_MAX_ENTRIES_CONFIG_KEY = "cache.maxEntries";
|
package/dist/entries/context.js
CHANGED
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
resolveApplicationPolicyGate,
|
|
11
11
|
resolveApplicationQueue,
|
|
12
12
|
setActiveApplicationContext
|
|
13
|
-
} from "@getstrata/core/runtime/applicationRegistry
|
|
13
|
+
} from "@getstrata/core/runtime/applicationRegistry";
|
|
14
14
|
|
|
15
15
|
// ../../src/bootstrap/contracts.ts
|
|
16
16
|
import {
|
|
@@ -135,7 +135,7 @@ import {
|
|
|
135
135
|
CORE_POLICY_GATE_TOKEN,
|
|
136
136
|
CORE_QUEUE_TOKEN,
|
|
137
137
|
CORE_TOKEN_SERVICE_TOKEN
|
|
138
|
-
} from "@getstrata/core/contracts/serviceTokens
|
|
138
|
+
} from "@getstrata/core/contracts/serviceTokens";
|
|
139
139
|
var APP_PORT_CONFIG_KEY = "app.port";
|
|
140
140
|
var CACHE_TTL_MS_CONFIG_KEY = "cache.ttlMs";
|
|
141
141
|
var CACHE_MAX_ENTRIES_CONFIG_KEY = "cache.maxEntries";
|
|
@@ -294,7 +294,6 @@ var db = new Proxy(function database() {}, {
|
|
|
294
294
|
return typeof value === "function" ? value.bind(connection) : value;
|
|
295
295
|
}
|
|
296
296
|
});
|
|
297
|
-
var connection_default = db;
|
|
298
297
|
|
|
299
298
|
// ../../src/modules/user/apiTokenTable.ts
|
|
300
299
|
import { defineTable } from "@getstrata/core/database";
|
|
@@ -1180,9 +1179,6 @@ var queueConfig = {
|
|
|
1180
1179
|
};
|
|
1181
1180
|
|
|
1182
1181
|
// ../../src/core/config/envSchema.ts
|
|
1183
|
-
function defineEnvSchema(schema) {
|
|
1184
|
-
return schema;
|
|
1185
|
-
}
|
|
1186
1182
|
function validateEnv(schema, env = process.env) {
|
|
1187
1183
|
const resolved = {};
|
|
1188
1184
|
for (const [name, rule] of Object.entries(schema)) {
|
|
@@ -1211,6 +1207,7 @@ function validateEnv(schema, env = process.env) {
|
|
|
1211
1207
|
}
|
|
1212
1208
|
|
|
1213
1209
|
// ../../src/bootstrap/env.ts
|
|
1210
|
+
import { defineEnvSchema } from "@getstrata/core/config/envSchema";
|
|
1214
1211
|
var appEnvSchema = defineEnvSchema({
|
|
1215
1212
|
DATABASE_URL: { required: true, pattern: /^postgres(ql)?:\/\// },
|
|
1216
1213
|
PORT: {
|
|
@@ -3699,9 +3696,6 @@ function resolveApplicationAuth2() {
|
|
|
3699
3696
|
function resolveApplicationPolicyGate2() {
|
|
3700
3697
|
return requireActiveApplicationContext().container.resolve(CORE_POLICY_GATE_TOKEN2);
|
|
3701
3698
|
}
|
|
3702
|
-
function resolveApplicationDependencies2() {
|
|
3703
|
-
return requireActiveApplicationContext().dependencies;
|
|
3704
|
-
}
|
|
3705
3699
|
|
|
3706
3700
|
// ../../src/bootstrap/queue/defaultJobs.ts
|
|
3707
3701
|
function registerDefaultJobs() {
|
|
@@ -3903,16 +3897,6 @@ class EtaViewEngine {
|
|
|
3903
3897
|
});
|
|
3904
3898
|
}
|
|
3905
3899
|
}
|
|
3906
|
-
// ../../src/core/view/htmlResponse.ts
|
|
3907
|
-
function htmlResponse(html, init = {}) {
|
|
3908
|
-
return new Response(html, {
|
|
3909
|
-
status: init.status ?? 200,
|
|
3910
|
-
statusText: init.statusText,
|
|
3911
|
-
headers: {
|
|
3912
|
-
"Content-Type": "text/html; charset=utf-8"
|
|
3913
|
-
}
|
|
3914
|
-
});
|
|
3915
|
-
}
|
|
3916
3900
|
// ../../src/core/http/cookies.ts
|
|
3917
3901
|
function readRequestCookie(request, name) {
|
|
3918
3902
|
const cookies = request.cookies;
|