@getstrata/bootstrap 0.2.9 → 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.
Files changed (31) hide show
  1. package/dist/bootstrap/cache/modelCacheTags.d.ts +3 -0
  2. package/dist/bootstrap/discoverModules.d.ts +3 -2
  3. package/dist/bootstrap/modules.d.ts +1 -1
  4. package/dist/bootstrap/preloadModules.d.ts +1 -0
  5. package/dist/bootstrap/public-api.d.ts +1 -0
  6. package/dist/bootstrap/routeRegistry.d.ts +1 -5
  7. package/dist/bootstrap/server.d.ts +1 -1
  8. package/dist/core/auth/authContext.d.ts +1 -2
  9. package/dist/core/auth/guard.d.ts +2 -2
  10. package/dist/core/auth/membershipContext.d.ts +1 -2
  11. package/dist/core/auth/sessionGuard.d.ts +2 -2
  12. package/dist/core/cache/modelCacheTags.d.ts +1 -3
  13. package/dist/core/contracts/serviceContainer.d.ts +5 -0
  14. package/dist/core/http/requestMetaContext.d.ts +1 -2
  15. package/dist/core/openapi/registeredRoute.d.ts +6 -0
  16. package/dist/core/runtime/asyncContextStore.d.ts +3 -0
  17. package/dist/core/tenant/tenantContext.d.ts +1 -2
  18. package/dist/core/tracing/traceContext.d.ts +1 -2
  19. package/dist/core/view/webLayoutData.d.ts +2 -2
  20. package/dist/entries/applicationRegistry.js +15 -2
  21. package/dist/entries/cache/modelCacheTags.js +22 -0
  22. package/dist/entries/context.js +150 -147
  23. package/dist/entries/createWebRoutes.js +22 -29
  24. package/dist/entries/http/securedRouteModelBinding.js +31 -6
  25. package/dist/entries/membershipService.js +32 -10
  26. package/dist/entries/providers/view.js +17 -6
  27. package/dist/entries/providers.js +59 -52
  28. package/dist/entries/queue/defaultJobs.js +30 -4
  29. package/dist/framework/public-api.d.ts +1 -0
  30. package/dist/index.js +69 -68
  31. package/package.json +8 -3
@@ -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 {};
@@ -5,6 +5,7 @@ export { scheduleRunCommand } from "../cli/commands/scheduleRun.ts";
5
5
  export type { ScheduledTask } from "../core/scheduler/schedule.ts";
6
6
  export { appSchedule, runDueScheduledTasks, Schedule } from "../core/scheduler/schedule.ts";
7
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,11 +1,10 @@
1
- import { AsyncLocalStorage } from "node:async_hooks";
2
1
  type AuthUser = {
3
2
  id: number | string;
4
3
  role?: string;
5
4
  abilities?: string[];
6
5
  tokenId?: number;
7
6
  };
8
- declare const authContext: AsyncLocalStorage<AuthUser | null>;
7
+ declare const authContext: import("node:async_hooks").AsyncLocalStorage<AuthUser | null>;
9
8
  declare function runWithAuthUser<T>(user: AuthUser | null, callback: () => T | Promise<T>): T | Promise<T>;
10
9
  declare function currentAuthUser(): AuthUser | null;
11
10
  export type { AuthUser };
@@ -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,11 +1,10 @@
1
- import { AsyncLocalStorage } from "node:async_hooks";
2
1
  import OrganizationMemberRepository from "../../modules/organization/memberRepository";
3
2
  import type { OrganizationMemberRole } from "../../modules/organization/memberTypes";
4
3
  type MembershipContext = {
5
4
  organizationIds: number[];
6
5
  rolesByOrganizationId: Map<number, OrganizationMemberRole>;
7
6
  };
8
- declare const membershipContext: AsyncLocalStorage<MembershipContext>;
7
+ declare const membershipContext: import("node:async_hooks").AsyncLocalStorage<MembershipContext>;
9
8
  declare const membershipRepository: OrganizationMemberRepository;
10
9
  declare function runWithMembershipContext<T>(callback: () => T | Promise<T>): Promise<T | Promise<T>>;
11
10
  declare function currentOrgRole(organizationId: number): OrganizationMemberRole | null;
@@ -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 };
@@ -1,4 +1,3 @@
1
- import { AsyncLocalStorage } from "node:async_hooks";
2
1
  type RequestMeta = {
3
2
  ipAddress: string | null;
4
3
  userAgent: string | null;
@@ -9,7 +8,7 @@ type RequestMeta = {
9
8
  } | null;
10
9
  csrfToken?: string;
11
10
  };
12
- declare const requestMetaContext: AsyncLocalStorage<RequestMeta>;
11
+ declare const requestMetaContext: import("node:async_hooks").AsyncLocalStorage<RequestMeta>;
13
12
  declare function runWithRequestMeta<T>(meta: RequestMeta, callback: () => T | Promise<T>): T | Promise<T>;
14
13
  declare function currentRequestMeta(): RequestMeta;
15
14
  export type { RequestMeta };
@@ -0,0 +1,6 @@
1
+ interface RegisteredRoute {
2
+ method: string;
3
+ path: string;
4
+ middleware: string[];
5
+ }
6
+ export type { RegisteredRoute };
@@ -0,0 +1,3 @@
1
+ import { AsyncLocalStorage } from "node:async_hooks";
2
+ declare function createAsyncContextStore<T>(key: string): AsyncLocalStorage<T>;
3
+ export { createAsyncContextStore };
@@ -1,11 +1,10 @@
1
- import { AsyncLocalStorage } from "node:async_hooks";
2
1
  type TenantContext = {
3
2
  id: number;
4
3
  slug: string;
5
4
  plan: "free" | "pro" | "enterprise";
6
5
  region: "eu" | "us" | "apac";
7
6
  };
8
- declare const tenantContext: AsyncLocalStorage<TenantContext>;
7
+ declare const tenantContext: import("node:async_hooks").AsyncLocalStorage<TenantContext>;
9
8
  declare function runWithTenant<T>(tenant: TenantContext, callback: () => T | Promise<T>): T | Promise<T>;
10
9
  declare function currentTenant(): TenantContext | null;
11
10
  declare function currentTenantId(): number;
@@ -1,9 +1,8 @@
1
- import { AsyncLocalStorage } from "node:async_hooks";
2
1
  type TraceContext = {
3
2
  traceId: string;
4
3
  spanId: string;
5
4
  };
6
- declare const traceContextStorage: AsyncLocalStorage<TraceContext>;
5
+ declare const traceContextStorage: import("node:async_hooks").AsyncLocalStorage<TraceContext>;
7
6
  declare function runWithTraceContext<T>(context: TraceContext, callback: () => T | Promise<T>): T | Promise<T>;
8
7
  declare function currentTraceId(): string | null;
9
8
  export type { TraceContext };
@@ -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 };
@@ -142,15 +142,28 @@ function resolveService(dependencies, token) {
142
142
  }
143
143
 
144
144
  // ../../src/bootstrap/applicationRegistry.ts
145
+ var APPLICATION_CONTEXT_KEY = Symbol.for("@getstrata/applicationContext");
145
146
  var activeContext;
147
+ function readStoredApplicationContext() {
148
+ if (activeContext) {
149
+ return activeContext;
150
+ }
151
+ const globalContext = globalThis[APPLICATION_CONTEXT_KEY];
152
+ if (globalContext) {
153
+ activeContext = globalContext;
154
+ }
155
+ return activeContext;
156
+ }
146
157
  function setActiveApplicationContext(context) {
147
158
  activeContext = context;
159
+ globalThis[APPLICATION_CONTEXT_KEY] = context;
148
160
  }
149
161
  function requireActiveApplicationContext() {
150
- if (!activeContext) {
162
+ const context = readStoredApplicationContext();
163
+ if (!context) {
151
164
  throw new Error("The application context has not been bootstrapped.");
152
165
  }
153
- return activeContext;
166
+ return context;
154
167
  }
155
168
  function resolveApplicationCache() {
156
169
  return getRequiredDependency(requireActiveApplicationContext().dependencies, "cache");
@@ -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 as setActiveApplicationContext2 } 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";
@@ -217,9 +278,22 @@ var databaseConfig = {
217
278
  connectionTimeoutSeconds: readInteger("DB_CONNECTION_TIMEOUT", 10)
218
279
  };
219
280
 
220
- // ../../src/core/database/connectionContext.ts
281
+ // ../../src/core/runtime/asyncContextStore.ts
221
282
  import { AsyncLocalStorage } from "async_hooks";
222
- var activeConnection = new AsyncLocalStorage;
283
+ function createAsyncContextStore(key) {
284
+ const symbol = Symbol.for(key);
285
+ const globalRecord = globalThis;
286
+ const existing = globalRecord[symbol];
287
+ if (existing) {
288
+ return existing;
289
+ }
290
+ const store = new AsyncLocalStorage;
291
+ globalRecord[symbol] = store;
292
+ return store;
293
+ }
294
+
295
+ // ../../src/core/database/connectionContext.ts
296
+ var activeConnection = createAsyncContextStore("@getstrata/databaseConnectionContext");
223
297
  function getActiveDatabaseConnection(fallback) {
224
298
  return activeConnection.getStore() ?? fallback;
225
299
  }
@@ -535,8 +609,7 @@ class PreconditionFailedError extends HttpError {
535
609
  }
536
610
 
537
611
  // ../../src/core/auth/authContext.ts
538
- import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
539
- var authContext = new AsyncLocalStorage2;
612
+ var authContext = createAsyncContextStore("@getstrata/authContext");
540
613
  function currentAuthUser() {
541
614
  return authContext.getStore() ?? null;
542
615
  }
@@ -1384,14 +1457,14 @@ var eventsProvider = {
1384
1457
  var events_default = eventsProvider;
1385
1458
 
1386
1459
  // ../../src/bootstrap/discoverListeners.ts
1387
- import { readdirSync as readdirSync2 } from "fs";
1388
- import { join as join2 } from "path";
1389
- import { pathToFileURL as pathToFileURL2 } from "url";
1460
+ import { readdirSync } from "fs";
1461
+ import { join } from "path";
1462
+ import { pathToFileURL } from "url";
1390
1463
  async function loadDiscoveredListeners() {
1391
- const listenersDirectory = join2(import.meta.dir, "../listeners");
1464
+ const listenersDirectory = join(import.meta.dir, "../listeners");
1392
1465
  let entries;
1393
1466
  try {
1394
- 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);
1395
1468
  } catch (error) {
1396
1469
  if (error instanceof Error && "code" in error && error.code === "ENOENT") {
1397
1470
  return [];
@@ -1399,7 +1472,7 @@ async function loadDiscoveredListeners() {
1399
1472
  throw error;
1400
1473
  }
1401
1474
  const listeners = await Promise.all(entries.map(async (fileName) => {
1402
- const moduleUrl = pathToFileURL2(join2(listenersDirectory, fileName)).href;
1475
+ const moduleUrl = pathToFileURL(join(listenersDirectory, fileName)).href;
1403
1476
  const loaded = await import(moduleUrl);
1404
1477
  return loaded.default;
1405
1478
  }));
@@ -1410,18 +1483,6 @@ function discoverListeners() {
1410
1483
  return appListeners;
1411
1484
  }
1412
1485
 
1413
- // ../../src/core/cache/modelCacheTags.ts
1414
- function cacheTagsForModelWrite(tableName, action) {
1415
- const module = appModules.find((entry) => entry.tableName === tableName);
1416
- const baseTags = module?.cacheTags ?? [`${tableName}s`];
1417
- const isDelete = action === "deleted" || action === "force-deleted";
1418
- const extraTags = isDelete ? module?.cacheDeleteExtraTags ?? [] : [];
1419
- return [...new Set([...baseTags, ...extraTags])];
1420
- }
1421
- function discoverModelTableNames() {
1422
- return appModules.map((module) => module.tableName).filter((tableName) => tableName !== undefined);
1423
- }
1424
-
1425
1486
  // ../../src/core/queue/index.ts
1426
1487
  class Job {
1427
1488
  maxAttempts;
@@ -1732,10 +1793,10 @@ function buildHavingClause(tableName, having, params) {
1732
1793
  return body.length > 0 ? ` HAVING ${body}` : "";
1733
1794
  }
1734
1795
  function buildJoinClause(joins = []) {
1735
- return joins.map((join3) => {
1736
- const joinType = join3.type === "left" ? "LEFT JOIN" : "INNER JOIN";
1737
- const onClause = join3.on.map(({ left, right }) => `${qualifyColumn(left.table, left.column)} = ${qualifyColumn(right.table, right.column)}`).join(" AND ");
1738
- 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}`;
1739
1800
  }).join("");
1740
1801
  }
1741
1802
  function buildLimitClause(limit) {
@@ -2171,7 +2232,7 @@ class RepositoryQuery {
2171
2232
  const rightRef = parseQualifiedColumn(right);
2172
2233
  const table = type === "inner" ? rightRef.table : rightRef.table;
2173
2234
  const joins = this.queryOptions.joins ?? [];
2174
- const existing = joins.find((join3) => join3.table === table && join3.type === type);
2235
+ const existing = joins.find((join2) => join2.table === table && join2.type === type);
2175
2236
  if (existing) {
2176
2237
  existing.on.push({ left: leftRef, right: rightRef });
2177
2238
  return this;
@@ -3521,75 +3582,6 @@ class DispatchWebhookJob extends Job {
3521
3582
  }
3522
3583
  var dispatchWebhookJob_default = DispatchWebhookJob;
3523
3584
 
3524
- // ../../src/core/logging/logger.ts
3525
- class Logger {
3526
- channel;
3527
- constructor(channel = "app") {
3528
- this.channel = channel;
3529
- }
3530
- write(level, message, context = {}) {
3531
- const entry = {
3532
- level,
3533
- channel: this.channel,
3534
- message,
3535
- timestamp: new Date().toISOString(),
3536
- ...context
3537
- };
3538
- const line = JSON.stringify(entry);
3539
- if (level === "error") {
3540
- console.error(line);
3541
- return;
3542
- }
3543
- console.log(line);
3544
- }
3545
- debug(message, context) {
3546
- this.write("debug", message, context);
3547
- }
3548
- info(message, context) {
3549
- this.write("info", message, context);
3550
- }
3551
- warn(message, context) {
3552
- this.write("warn", message, context);
3553
- }
3554
- error(message, context) {
3555
- this.write("error", message, context);
3556
- }
3557
- }
3558
- var appLogger = new Logger("app");
3559
-
3560
- // ../../src/bootstrap/applicationRegistry.ts
3561
- var activeContext;
3562
- function setActiveApplicationContext(context) {
3563
- activeContext = context;
3564
- }
3565
- function requireActiveApplicationContext() {
3566
- if (!activeContext) {
3567
- throw new Error("The application context has not been bootstrapped.");
3568
- }
3569
- return activeContext;
3570
- }
3571
- function resolveApplicationCache() {
3572
- return getRequiredDependency(requireActiveApplicationContext().dependencies, "cache");
3573
- }
3574
- function resolveApplicationQueue() {
3575
- return requireActiveApplicationContext().container.resolve(CORE_QUEUE_TOKEN);
3576
- }
3577
- function resolveApplicationAuth() {
3578
- return requireActiveApplicationContext().container.resolve(CORE_AUTH_TOKEN);
3579
- }
3580
- function resolveApplicationPolicyGate() {
3581
- return requireActiveApplicationContext().container.resolve(CORE_POLICY_GATE_TOKEN);
3582
- }
3583
- function resolveApplicationConfig() {
3584
- return requireActiveApplicationContext().config;
3585
- }
3586
- function resolveApplicationLogger() {
3587
- return appLogger;
3588
- }
3589
- function resolveApplicationDependencies() {
3590
- return requireActiveApplicationContext().dependencies;
3591
- }
3592
-
3593
3585
  // ../../src/bootstrap/queue/defaultJobs.ts
3594
3586
  function registerDefaultJobs() {
3595
3587
  jobRegistry.register("cache.invalidate-tags", () => {
@@ -3608,6 +3600,18 @@ function createAppQueue(driver, redisUrl, failedJobs = createFailedJobService(),
3608
3600
  });
3609
3601
  }
3610
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
+
3611
3615
  // ../../src/bootstrap/listeners/invalidateCacheOnModelWrite.ts
3612
3616
  var MODEL_WRITE_ACTIONS = ["created", "updated", "deleted", "restored", "force-deleted"];
3613
3617
  function registerInvalidateCacheOnModelWriteListeners(bus = eventBus) {
@@ -3719,7 +3723,7 @@ var queue_default = queueProvider;
3719
3723
 
3720
3724
  // ../../src/core/storage/storage.ts
3721
3725
  import { mkdir, readFile, unlink, writeFile } from "fs/promises";
3722
- import { dirname, join as join3 } from "path";
3726
+ import { dirname, join as join2 } from "path";
3723
3727
  var {S3Client } = globalThis.Bun;
3724
3728
 
3725
3729
  class LocalStorageDriver {
@@ -3731,7 +3735,7 @@ class LocalStorageDriver {
3731
3735
  return this.rootDirectory ?? process.env.STORAGE_PATH ?? "storage";
3732
3736
  }
3733
3737
  resolvePath(path) {
3734
- return join3(this.resolveRootDirectory(), path.replace(/^\/+/, ""));
3738
+ return join2(this.resolveRootDirectory(), path.replace(/^\/+/, ""));
3735
3739
  }
3736
3740
  async put(path, contents) {
3737
3741
  const absolutePath = this.resolvePath(path);
@@ -3855,8 +3859,7 @@ function isViewsEnabled() {
3855
3859
  }
3856
3860
 
3857
3861
  // ../../src/core/http/requestMetaContext.ts
3858
- import { AsyncLocalStorage as AsyncLocalStorage3 } from "async_hooks";
3859
- var requestMetaContext = new AsyncLocalStorage3;
3862
+ var requestMetaContext = createAsyncContextStore("@getstrata/requestMetaContext");
3860
3863
  function currentRequestMeta() {
3861
3864
  return requestMetaContext.getStore() ?? {
3862
3865
  ipAddress: null,
@@ -3865,9 +3868,9 @@ function currentRequestMeta() {
3865
3868
  }
3866
3869
 
3867
3870
  // ../../src/core/view/etaViewEngine.ts
3868
- import { join as join4 } from "path";
3871
+ import { join as join3 } from "path";
3869
3872
  import { Eta } from "eta";
3870
- var DEFAULT_VIEWS_DIRECTORY = join4(process.cwd(), "resources/views");
3873
+ var DEFAULT_VIEWS_DIRECTORY = join3(process.cwd(), "resources/views");
3871
3874
  var DEFAULT_LAYOUT = "layouts/app.eta";
3872
3875
 
3873
3876
  class EtaViewEngine {
@@ -4189,7 +4192,7 @@ function createAppContext() {
4189
4192
  config,
4190
4193
  dependencies
4191
4194
  };
4192
- setActiveApplicationContext2(appContext);
4195
+ setActiveApplicationContext(appContext);
4193
4196
  return appContext;
4194
4197
  }
4195
4198
  var cachedAppContext;