@getstrata/bootstrap 0.2.10 → 0.2.12

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.
@@ -0,0 +1,3 @@
1
+ declare function cacheTagsForModelWrite(tableName: string, action: string): string[];
2
+ declare function discoverModelTableNames(): string[];
3
+ export { cacheTagsForModelWrite, discoverModelTableNames };
@@ -1,4 +1,5 @@
1
1
  import type { AppModule } from "./contracts";
2
- declare const appModules: AppModule[];
2
+ declare let appModules: AppModule[];
3
+ declare function ensureModulesLoaded(): Promise<AppModule[]>;
3
4
  declare function discoverModules(): AppModule[];
4
- export { appModules, discoverModules };
5
+ export { appModules, discoverModules, ensureModulesLoaded };
@@ -1 +1 @@
1
- export { appModules, discoverModules } from "./discoverModules";
1
+ export { appModules, discoverModules, ensureModulesLoaded } from "./discoverModules";
@@ -0,0 +1 @@
1
+ export {};
@@ -1,10 +1,11 @@
1
1
  /**
2
2
  * @getstrata/bootstrap — application shell for Strata sibling apps.
3
3
  */
4
- export { resolveApplicationAuth, resolveApplicationCache, resolveApplicationConfig, resolveApplicationDependencies, resolveApplicationLogger, resolveApplicationPolicyGate, resolveApplicationQueue, setActiveApplicationContext, } from "@getstrata/core";
5
4
  export { scheduleRunCommand } from "../cli/commands/scheduleRun.ts";
6
5
  export type { ScheduledTask } from "../core/scheduler/schedule.ts";
7
6
  export { appSchedule, runDueScheduledTasks, Schedule } from "../core/scheduler/schedule.ts";
7
+ export { resolveApplicationAuth, resolveApplicationCache, resolveApplicationConfig, resolveApplicationDependencies, resolveApplicationLogger, resolveApplicationPolicyGate, resolveApplicationQueue, setActiveApplicationContext, } from "./applicationRegistry.ts";
8
+ export { cacheTagsForModelWrite, discoverModelTableNames } from "./cache/modelCacheTags.ts";
8
9
  export { APP_PORT_CONFIG_KEY, CORE_AUTH_TOKEN, CORE_CACHE_TOKEN, CORE_CONFIG_TOKEN, CORE_POLICY_GATE_TOKEN, CORE_QUEUE_TOKEN, CORE_TOKEN_SERVICE_TOKEN, DATABASE_URL_CONFIG_KEY, DEFAULT_APP_PORT, REDIS_URL_CONFIG_KEY, } from "./config.ts";
9
10
  export { collectProviders, createAppContext, runProviderPhase } from "./context.ts";
10
11
  export type { AppContext, AppDependencies, AppModule, AppRouteMap, CachedJson, ConfigStore, ModuleRouteContext, MutableAppDependencies, ProviderContext, ServiceFactory, ServiceProvider, } from "./contracts.ts";
@@ -1,8 +1,4 @@
1
- interface RegisteredRoute {
2
- method: string;
3
- path: string;
4
- middleware: string[];
5
- }
1
+ import type { RegisteredRoute } from "../core/openapi/registeredRoute";
6
2
  declare class RouteRegistry {
7
3
  private readonly routes;
8
4
  register(route: RegisteredRoute): void;
@@ -1 +1 @@
1
- export {};
1
+ import "./preloadModules.ts";
@@ -1,4 +1,4 @@
1
- import type { ServiceContainer } from "../../bootstrap/contracts";
1
+ import type { ServiceContainerLike } from "../contracts/serviceContainer";
2
2
  import type { AuthUser } from "./authContext";
3
3
  interface AuthGuard {
4
4
  resolve(request: Request): AuthUser | null | Promise<AuthUser | null>;
@@ -16,7 +16,7 @@ declare class ApiTokenGuard implements AuthGuard {
16
16
  }
17
17
  declare class DatabaseTokenGuard implements AuthGuard {
18
18
  private readonly container;
19
- constructor(container: ServiceContainer);
19
+ constructor(container: ServiceContainerLike);
20
20
  resolve(request: Request): Promise<AuthUser | null>;
21
21
  }
22
22
  declare class CompositeGuard implements AuthGuard {
@@ -1,9 +1,9 @@
1
- import type { ServiceContainer } from "../../bootstrap/contracts";
1
+ import type { ServiceContainerLike } from "../contracts/serviceContainer";
2
2
  import type { AuthUser } from "./authContext";
3
3
  import type { AuthGuard } from "./guard";
4
4
  declare class SessionGuard implements AuthGuard {
5
5
  private readonly container;
6
- constructor(container: ServiceContainer);
6
+ constructor(container: ServiceContainerLike);
7
7
  resolve(request: Request): Promise<AuthUser | null>;
8
8
  }
9
9
  export { SessionGuard };
@@ -1,3 +1 @@
1
- declare function cacheTagsForModelWrite(tableName: string, action: string): string[];
2
- declare function discoverModelTableNames(): string[];
3
- export { cacheTagsForModelWrite, discoverModelTableNames };
1
+ export { cacheTagsForModelWrite, discoverModelTableNames, } from "../../bootstrap/cache/modelCacheTags.ts";
@@ -0,0 +1,5 @@
1
+ interface ServiceContainerLike {
2
+ has(key: string): boolean;
3
+ resolve<T>(key: string): T;
4
+ }
5
+ export type { ServiceContainerLike };
@@ -0,0 +1,6 @@
1
+ interface RegisteredRoute {
2
+ method: string;
3
+ path: string;
4
+ middleware: string[];
5
+ }
6
+ export type { RegisteredRoute };
@@ -1,4 +1,4 @@
1
- import type { ServiceContainer } from "../../bootstrap/contracts";
1
+ import type { ServiceContainerLike } from "../contracts/serviceContainer";
2
2
  interface WebLayoutAuthUser {
3
3
  id: number;
4
4
  email: string;
@@ -12,6 +12,6 @@ interface WebLayoutData {
12
12
  message: string;
13
13
  } | null;
14
14
  }
15
- declare function resolveWebLayoutData(container: ServiceContainer, request?: Request): Promise<Record<string, unknown>>;
15
+ declare function resolveWebLayoutData(container: ServiceContainerLike, request?: Request): Promise<Record<string, unknown>>;
16
16
  export type { WebLayoutAuthUser, WebLayoutData };
17
17
  export { resolveWebLayoutData };
@@ -0,0 +1,22 @@
1
+ // @bun
2
+ // ../../src/bootstrap/discoverModules.ts
3
+ var appModules = [];
4
+ function discoverModules() {
5
+ return appModules;
6
+ }
7
+
8
+ // ../../src/bootstrap/cache/modelCacheTags.ts
9
+ function cacheTagsForModelWrite(tableName, action) {
10
+ const module = discoverModules().find((entry) => entry.tableName === tableName);
11
+ const baseTags = module?.cacheTags ?? [`${tableName}s`];
12
+ const isDelete = action === "deleted" || action === "force-deleted";
13
+ const extraTags = isDelete ? module?.cacheDeleteExtraTags ?? [] : [];
14
+ return [...new Set([...baseTags, ...extraTags])];
15
+ }
16
+ function discoverModelTableNames() {
17
+ return discoverModules().map((module) => module.tableName).filter((tableName) => tableName !== undefined);
18
+ }
19
+ export {
20
+ discoverModelTableNames,
21
+ cacheTagsForModelWrite
22
+ };
@@ -1,6 +1,60 @@
1
1
  // @bun
2
- // ../../src/bootstrap/context.ts
3
- import { setActiveApplicationContext } from "@getstrata/core";
2
+ // ../../src/core/logging/logger.ts
3
+ class Logger {
4
+ channel;
5
+ constructor(channel = "app") {
6
+ this.channel = channel;
7
+ }
8
+ write(level, message, context = {}) {
9
+ const entry = {
10
+ level,
11
+ channel: this.channel,
12
+ message,
13
+ timestamp: new Date().toISOString(),
14
+ ...context
15
+ };
16
+ const line = JSON.stringify(entry);
17
+ if (level === "error") {
18
+ console.error(line);
19
+ return;
20
+ }
21
+ console.log(line);
22
+ }
23
+ debug(message, context) {
24
+ this.write("debug", message, context);
25
+ }
26
+ info(message, context) {
27
+ this.write("info", message, context);
28
+ }
29
+ warn(message, context) {
30
+ this.write("warn", message, context);
31
+ }
32
+ error(message, context) {
33
+ this.write("error", message, context);
34
+ }
35
+ }
36
+ var appLogger = new Logger("app");
37
+
38
+ // ../../src/bootstrap/config.ts
39
+ var APP_PORT_CONFIG_KEY = "app.port";
40
+ var CACHE_TTL_MS_CONFIG_KEY = "cache.ttlMs";
41
+ var CACHE_MAX_ENTRIES_CONFIG_KEY = "cache.maxEntries";
42
+ var CACHE_DRIVER_CONFIG_KEY = "cache.driver";
43
+ var REDIS_URL_CONFIG_KEY = "cache.redisUrl";
44
+ var DATABASE_URL_CONFIG_KEY = "database.url";
45
+ var CORE_CONFIG_TOKEN = "core.config";
46
+ var CORE_CACHE_TOKEN = "core.cache";
47
+ var CORE_QUEUE_TOKEN = "core.queue";
48
+ var CORE_POLICY_GATE_TOKEN = "core.policyGate";
49
+ var CORE_AUTH_TOKEN = "core.auth";
50
+ var CORE_TOKEN_SERVICE_TOKEN = "core.tokenService";
51
+ var AUTH_DEV_HEADERS_CONFIG_KEY = "auth.allowDevHeaders";
52
+ var DEFAULT_APP_PORT = 3000;
53
+ var DEFAULT_CACHE_TTL_MS = 3600000;
54
+ var DEFAULT_CACHE_MAX_ENTRIES = 100;
55
+ var DEFAULT_CACHE_DRIVER = "array";
56
+ var DEFAULT_API_TOKEN = "";
57
+ var DEFAULT_QUEUE_DRIVER = "sync";
4
58
 
5
59
  // ../../src/bootstrap/contracts.ts
6
60
  class ServiceContainer {
@@ -87,29 +141,57 @@ function resolveService(dependencies, token) {
87
141
  return dependencies.container.resolve(token);
88
142
  }
89
143
 
90
- // ../../src/bootstrap/discoverModules.ts
91
- import { readdirSync } from "fs";
92
- import { join } from "path";
93
- import { pathToFileURL } from "url";
94
- async function loadDiscoveredModules() {
95
- const modulesDirectory = join(import.meta.dir, "../modules");
96
- let moduleNames;
97
- try {
98
- moduleNames = readdirSync(modulesDirectory, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
99
- } catch (error) {
100
- if (error.code === "ENOENT") {
101
- return [];
102
- }
103
- throw error;
144
+ // ../../src/bootstrap/applicationRegistry.ts
145
+ var APPLICATION_CONTEXT_KEY = Symbol.for("@getstrata/applicationContext");
146
+ var activeContext;
147
+ function readStoredApplicationContext() {
148
+ if (activeContext) {
149
+ return activeContext;
104
150
  }
105
- const modules = await Promise.all(moduleNames.map(async (moduleName) => {
106
- const moduleUrl = pathToFileURL(join(modulesDirectory, moduleName, "index.ts")).href;
107
- const loaded = await import(moduleUrl);
108
- return loaded.default;
109
- }));
110
- return modules.filter((module) => module?.name !== undefined).sort((left, right) => (left.order ?? 100) - (right.order ?? 100));
151
+ const globalContext = globalThis[APPLICATION_CONTEXT_KEY];
152
+ if (globalContext) {
153
+ activeContext = globalContext;
154
+ }
155
+ return activeContext;
156
+ }
157
+ function setActiveApplicationContext(context) {
158
+ activeContext = context;
159
+ globalThis[APPLICATION_CONTEXT_KEY] = context;
160
+ }
161
+ function requireActiveApplicationContext() {
162
+ const context = readStoredApplicationContext();
163
+ if (!context) {
164
+ throw new Error("The application context has not been bootstrapped.");
165
+ }
166
+ return context;
167
+ }
168
+ function resolveApplicationCache() {
169
+ return getRequiredDependency(requireActiveApplicationContext().dependencies, "cache");
170
+ }
171
+ function resolveApplicationQueue() {
172
+ return requireActiveApplicationContext().container.resolve(CORE_QUEUE_TOKEN);
173
+ }
174
+ function resolveApplicationAuth() {
175
+ return requireActiveApplicationContext().container.resolve(CORE_AUTH_TOKEN);
176
+ }
177
+ function resolveApplicationPolicyGate() {
178
+ return requireActiveApplicationContext().container.resolve(CORE_POLICY_GATE_TOKEN);
179
+ }
180
+ function resolveApplicationConfig() {
181
+ return requireActiveApplicationContext().config;
182
+ }
183
+ function resolveApplicationLogger() {
184
+ return appLogger;
185
+ }
186
+ function resolveApplicationDependencies() {
187
+ return requireActiveApplicationContext().dependencies;
188
+ }
189
+
190
+ // ../../src/bootstrap/discoverModules.ts
191
+ var appModules = [];
192
+ function discoverModules() {
193
+ return appModules;
111
194
  }
112
- var appModules = await loadDiscoveredModules();
113
195
  // ../../src/config/auth.ts
114
196
  var authConfig = {
115
197
  allowDevHeaders: (process.env.AUTH_DEV_HEADERS ?? "true") !== "false",
@@ -154,27 +236,6 @@ function resolveAbilitiesForRole(role) {
154
236
  return [...MEMBER_ABILITIES];
155
237
  }
156
238
 
157
- // ../../src/bootstrap/config.ts
158
- var APP_PORT_CONFIG_KEY = "app.port";
159
- var CACHE_TTL_MS_CONFIG_KEY = "cache.ttlMs";
160
- var CACHE_MAX_ENTRIES_CONFIG_KEY = "cache.maxEntries";
161
- var CACHE_DRIVER_CONFIG_KEY = "cache.driver";
162
- var REDIS_URL_CONFIG_KEY = "cache.redisUrl";
163
- var DATABASE_URL_CONFIG_KEY = "database.url";
164
- var CORE_CONFIG_TOKEN = "core.config";
165
- var CORE_CACHE_TOKEN = "core.cache";
166
- var CORE_QUEUE_TOKEN = "core.queue";
167
- var CORE_POLICY_GATE_TOKEN = "core.policyGate";
168
- var CORE_AUTH_TOKEN = "core.auth";
169
- var CORE_TOKEN_SERVICE_TOKEN = "core.tokenService";
170
- var AUTH_DEV_HEADERS_CONFIG_KEY = "auth.allowDevHeaders";
171
- var DEFAULT_APP_PORT = 3000;
172
- var DEFAULT_CACHE_TTL_MS = 3600000;
173
- var DEFAULT_CACHE_MAX_ENTRIES = 100;
174
- var DEFAULT_CACHE_DRIVER = "array";
175
- var DEFAULT_API_TOKEN = "";
176
- var DEFAULT_QUEUE_DRIVER = "sync";
177
-
178
239
  // ../../src/modules/user/provider.ts
179
240
  import { OidcProvider } from "@getstrata/core/auth/oauth/oidcProvider";
180
241
  import { GitHubOAuthProvider, MockOAuthProvider } from "@getstrata/core/auth/oauth/providers";
@@ -1396,14 +1457,14 @@ var eventsProvider = {
1396
1457
  var events_default = eventsProvider;
1397
1458
 
1398
1459
  // ../../src/bootstrap/discoverListeners.ts
1399
- import { readdirSync as readdirSync2 } from "fs";
1400
- import { join as join2 } from "path";
1401
- import { pathToFileURL as pathToFileURL2 } from "url";
1460
+ import { readdirSync } from "fs";
1461
+ import { join } from "path";
1462
+ import { pathToFileURL } from "url";
1402
1463
  async function loadDiscoveredListeners() {
1403
- const listenersDirectory = join2(import.meta.dir, "../listeners");
1464
+ const listenersDirectory = join(import.meta.dir, "../listeners");
1404
1465
  let entries;
1405
1466
  try {
1406
- entries = readdirSync2(listenersDirectory, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".ts")).map((entry) => entry.name);
1467
+ entries = readdirSync(listenersDirectory, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".ts")).map((entry) => entry.name);
1407
1468
  } catch (error) {
1408
1469
  if (error instanceof Error && "code" in error && error.code === "ENOENT") {
1409
1470
  return [];
@@ -1411,7 +1472,7 @@ async function loadDiscoveredListeners() {
1411
1472
  throw error;
1412
1473
  }
1413
1474
  const listeners = await Promise.all(entries.map(async (fileName) => {
1414
- const moduleUrl = pathToFileURL2(join2(listenersDirectory, fileName)).href;
1475
+ const moduleUrl = pathToFileURL(join(listenersDirectory, fileName)).href;
1415
1476
  const loaded = await import(moduleUrl);
1416
1477
  return loaded.default;
1417
1478
  }));
@@ -1422,21 +1483,6 @@ function discoverListeners() {
1422
1483
  return appListeners;
1423
1484
  }
1424
1485
 
1425
- // ../../src/bootstrap/listeners/invalidateCacheOnModelWrite.ts
1426
- import { resolveApplicationCache as resolveApplicationCache2, resolveApplicationQueue } from "@getstrata/core";
1427
-
1428
- // ../../src/core/cache/modelCacheTags.ts
1429
- function cacheTagsForModelWrite(tableName, action) {
1430
- const module = appModules.find((entry) => entry.tableName === tableName);
1431
- const baseTags = module?.cacheTags ?? [`${tableName}s`];
1432
- const isDelete = action === "deleted" || action === "force-deleted";
1433
- const extraTags = isDelete ? module?.cacheDeleteExtraTags ?? [] : [];
1434
- return [...new Set([...baseTags, ...extraTags])];
1435
- }
1436
- function discoverModelTableNames() {
1437
- return appModules.map((module) => module.tableName).filter((tableName) => tableName !== undefined);
1438
- }
1439
-
1440
1486
  // ../../src/core/queue/index.ts
1441
1487
  class Job {
1442
1488
  maxAttempts;
@@ -1747,10 +1793,10 @@ function buildHavingClause(tableName, having, params) {
1747
1793
  return body.length > 0 ? ` HAVING ${body}` : "";
1748
1794
  }
1749
1795
  function buildJoinClause(joins = []) {
1750
- return joins.map((join3) => {
1751
- const joinType = join3.type === "left" ? "LEFT JOIN" : "INNER JOIN";
1752
- const onClause = join3.on.map(({ left, right }) => `${qualifyColumn(left.table, left.column)} = ${qualifyColumn(right.table, right.column)}`).join(" AND ");
1753
- return ` ${joinType} ${quoteIdentifier(join3.table)} ON ${onClause}`;
1796
+ return joins.map((join2) => {
1797
+ const joinType = join2.type === "left" ? "LEFT JOIN" : "INNER JOIN";
1798
+ const onClause = join2.on.map(({ left, right }) => `${qualifyColumn(left.table, left.column)} = ${qualifyColumn(right.table, right.column)}`).join(" AND ");
1799
+ return ` ${joinType} ${quoteIdentifier(join2.table)} ON ${onClause}`;
1754
1800
  }).join("");
1755
1801
  }
1756
1802
  function buildLimitClause(limit) {
@@ -2186,7 +2232,7 @@ class RepositoryQuery {
2186
2232
  const rightRef = parseQualifiedColumn(right);
2187
2233
  const table = type === "inner" ? rightRef.table : rightRef.table;
2188
2234
  const joins = this.queryOptions.joins ?? [];
2189
- const existing = joins.find((join3) => join3.table === table && join3.type === type);
2235
+ const existing = joins.find((join2) => join2.table === table && join2.type === type);
2190
2236
  if (existing) {
2191
2237
  existing.on.push({ left: leftRef, right: rightRef });
2192
2238
  return this;
@@ -3349,9 +3395,6 @@ function createProductionQueue(driver, options = {}) {
3349
3395
  return new ResilientQueue(failedJobs, driver === "async");
3350
3396
  }
3351
3397
 
3352
- // ../../src/bootstrap/queue/defaultJobs.ts
3353
- import { resolveApplicationCache } from "@getstrata/core";
3354
-
3355
3398
  // ../../src/core/jobs/dispatchWebhookJob.ts
3356
3399
  import { createHmac as createHmac2 } from "crypto";
3357
3400
 
@@ -3557,6 +3600,18 @@ function createAppQueue(driver, redisUrl, failedJobs = createFailedJobService(),
3557
3600
  });
3558
3601
  }
3559
3602
 
3603
+ // ../../src/bootstrap/cache/modelCacheTags.ts
3604
+ function cacheTagsForModelWrite(tableName, action) {
3605
+ const module = discoverModules().find((entry) => entry.tableName === tableName);
3606
+ const baseTags = module?.cacheTags ?? [`${tableName}s`];
3607
+ const isDelete = action === "deleted" || action === "force-deleted";
3608
+ const extraTags = isDelete ? module?.cacheDeleteExtraTags ?? [] : [];
3609
+ return [...new Set([...baseTags, ...extraTags])];
3610
+ }
3611
+ function discoverModelTableNames() {
3612
+ return discoverModules().map((module) => module.tableName).filter((tableName) => tableName !== undefined);
3613
+ }
3614
+
3560
3615
  // ../../src/bootstrap/listeners/invalidateCacheOnModelWrite.ts
3561
3616
  var MODEL_WRITE_ACTIONS = ["created", "updated", "deleted", "restored", "force-deleted"];
3562
3617
  function registerInvalidateCacheOnModelWriteListeners(bus = eventBus) {
@@ -3570,7 +3625,7 @@ function registerInvalidateCacheOnModelWriteListeners(bus = eventBus) {
3570
3625
  let cache;
3571
3626
  let queue;
3572
3627
  try {
3573
- cache = resolveApplicationCache2();
3628
+ cache = resolveApplicationCache();
3574
3629
  queue = resolveApplicationQueue();
3575
3630
  } catch {
3576
3631
  return;
@@ -3668,7 +3723,7 @@ var queue_default = queueProvider;
3668
3723
 
3669
3724
  // ../../src/core/storage/storage.ts
3670
3725
  import { mkdir, readFile, unlink, writeFile } from "fs/promises";
3671
- import { dirname, join as join3 } from "path";
3726
+ import { dirname, join as join2 } from "path";
3672
3727
  var {S3Client } = globalThis.Bun;
3673
3728
 
3674
3729
  class LocalStorageDriver {
@@ -3680,7 +3735,7 @@ class LocalStorageDriver {
3680
3735
  return this.rootDirectory ?? process.env.STORAGE_PATH ?? "storage";
3681
3736
  }
3682
3737
  resolvePath(path) {
3683
- return join3(this.resolveRootDirectory(), path.replace(/^\/+/, ""));
3738
+ return join2(this.resolveRootDirectory(), path.replace(/^\/+/, ""));
3684
3739
  }
3685
3740
  async put(path, contents) {
3686
3741
  const absolutePath = this.resolvePath(path);
@@ -3813,9 +3868,9 @@ function currentRequestMeta() {
3813
3868
  }
3814
3869
 
3815
3870
  // ../../src/core/view/etaViewEngine.ts
3816
- import { join as join4 } from "path";
3871
+ import { join as join3 } from "path";
3817
3872
  import { Eta } from "eta";
3818
- var DEFAULT_VIEWS_DIRECTORY = join4(process.cwd(), "resources/views");
3873
+ var DEFAULT_VIEWS_DIRECTORY = join3(process.cwd(), "resources/views");
3819
3874
  var DEFAULT_LAYOUT = "layouts/app.eta";
3820
3875
 
3821
3876
  class EtaViewEngine {
@@ -1,6 +1,6 @@
1
1
  // @bun
2
2
  // ../../src/bootstrap/createWebRoutes.ts
3
- import { join as join3 } from "path";
3
+ import { join as join2 } from "path";
4
4
 
5
5
  // ../../src/config/frontend.ts
6
6
  function readFrontendMode() {
@@ -905,28 +905,10 @@ function createHttpKernel(dependencies) {
905
905
  }
906
906
 
907
907
  // ../../src/bootstrap/discoverModules.ts
908
- import { readdirSync } from "fs";
909
- import { join as join2 } from "path";
910
- import { pathToFileURL } from "url";
911
- async function loadDiscoveredModules() {
912
- const modulesDirectory = join2(import.meta.dir, "../modules");
913
- let moduleNames;
914
- try {
915
- moduleNames = readdirSync(modulesDirectory, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
916
- } catch (error) {
917
- if (error.code === "ENOENT") {
918
- return [];
919
- }
920
- throw error;
921
- }
922
- const modules = await Promise.all(moduleNames.map(async (moduleName) => {
923
- const moduleUrl = pathToFileURL(join2(modulesDirectory, moduleName, "index.ts")).href;
924
- const loaded = await import(moduleUrl);
925
- return loaded.default;
926
- }));
927
- return modules.filter((module) => module?.name !== undefined).sort((left, right) => (left.order ?? 100) - (right.order ?? 100));
908
+ var appModules = [];
909
+ function discoverModules() {
910
+ return appModules;
928
911
  }
929
- var appModules = await loadDiscoveredModules();
930
912
  // ../../src/bootstrap/routeRegistry.ts
931
913
  class RouteRegistry {
932
914
  routes = [];
@@ -984,7 +966,7 @@ function createWebRoutes(dependencies) {
984
966
  registerRoute("GET", "/assets/*", ["global", "web"]);
985
967
  const pathname = new URL(request.url).pathname;
986
968
  const relativePath = pathname.replace(/^\//, "");
987
- const file = Bun.file(join3(process.cwd(), "public", relativePath));
969
+ const file = Bun.file(join2(process.cwd(), "public", relativePath));
988
970
  if (!await file.exists()) {
989
971
  return htmlResponse("Not Found", { status: 404 });
990
972
  }