@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.
- package/dist/bootstrap/cache/modelCacheTags.d.ts +3 -0
- package/dist/bootstrap/discoverModules.d.ts +3 -2
- package/dist/bootstrap/modules.d.ts +1 -1
- package/dist/bootstrap/preloadModules.d.ts +1 -0
- package/dist/bootstrap/public-api.d.ts +1 -0
- package/dist/bootstrap/routeRegistry.d.ts +1 -5
- package/dist/bootstrap/server.d.ts +1 -1
- package/dist/core/auth/authContext.d.ts +1 -2
- package/dist/core/auth/guard.d.ts +2 -2
- package/dist/core/auth/membershipContext.d.ts +1 -2
- package/dist/core/auth/sessionGuard.d.ts +2 -2
- package/dist/core/cache/modelCacheTags.d.ts +1 -3
- package/dist/core/contracts/serviceContainer.d.ts +5 -0
- package/dist/core/http/requestMetaContext.d.ts +1 -2
- package/dist/core/openapi/registeredRoute.d.ts +6 -0
- package/dist/core/runtime/asyncContextStore.d.ts +3 -0
- package/dist/core/tenant/tenantContext.d.ts +1 -2
- package/dist/core/tracing/traceContext.d.ts +1 -2
- package/dist/core/view/webLayoutData.d.ts +2 -2
- package/dist/entries/applicationRegistry.js +15 -2
- package/dist/entries/cache/modelCacheTags.js +22 -0
- package/dist/entries/context.js +150 -147
- package/dist/entries/createWebRoutes.js +22 -29
- package/dist/entries/http/securedRouteModelBinding.js +31 -6
- package/dist/entries/membershipService.js +32 -10
- package/dist/entries/providers/view.js +17 -6
- package/dist/entries/providers.js +59 -52
- package/dist/entries/queue/defaultJobs.js +30 -4
- package/dist/framework/public-api.d.ts +1 -0
- package/dist/index.js +69 -68
- package/package.json +8 -3
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { AppModule } from "./contracts";
|
|
2
|
-
declare
|
|
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
|
-
|
|
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
|
-
|
|
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 {
|
|
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:
|
|
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 {
|
|
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:
|
|
6
|
+
constructor(container: ServiceContainerLike);
|
|
7
7
|
resolve(request: Request): Promise<AuthUser | null>;
|
|
8
8
|
}
|
|
9
9
|
export { SessionGuard };
|
|
@@ -1,3 +1 @@
|
|
|
1
|
-
|
|
2
|
-
declare function discoverModelTableNames(): string[];
|
|
3
|
-
export { cacheTagsForModelWrite, discoverModelTableNames };
|
|
1
|
+
export { cacheTagsForModelWrite, discoverModelTableNames, } from "../../bootstrap/cache/modelCacheTags.ts";
|
|
@@ -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 };
|
|
@@ -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 {
|
|
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:
|
|
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
|
-
|
|
162
|
+
const context = readStoredApplicationContext();
|
|
163
|
+
if (!context) {
|
|
151
164
|
throw new Error("The application context has not been bootstrapped.");
|
|
152
165
|
}
|
|
153
|
-
return
|
|
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
|
+
};
|
package/dist/entries/context.js
CHANGED
|
@@ -1,6 +1,60 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
// ../../src/
|
|
3
|
-
|
|
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/
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
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
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
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/
|
|
281
|
+
// ../../src/core/runtime/asyncContextStore.ts
|
|
221
282
|
import { AsyncLocalStorage } from "async_hooks";
|
|
222
|
-
|
|
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
|
-
|
|
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
|
|
1388
|
-
import { join
|
|
1389
|
-
import { pathToFileURL
|
|
1460
|
+
import { readdirSync } from "fs";
|
|
1461
|
+
import { join } from "path";
|
|
1462
|
+
import { pathToFileURL } from "url";
|
|
1390
1463
|
async function loadDiscoveredListeners() {
|
|
1391
|
-
const listenersDirectory =
|
|
1464
|
+
const listenersDirectory = join(import.meta.dir, "../listeners");
|
|
1392
1465
|
let entries;
|
|
1393
1466
|
try {
|
|
1394
|
-
entries =
|
|
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 =
|
|
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((
|
|
1736
|
-
const joinType =
|
|
1737
|
-
const onClause =
|
|
1738
|
-
return ` ${joinType} ${quoteIdentifier(
|
|
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((
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
3871
|
+
import { join as join3 } from "path";
|
|
3869
3872
|
import { Eta } from "eta";
|
|
3870
|
-
var DEFAULT_VIEWS_DIRECTORY =
|
|
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
|
-
|
|
4195
|
+
setActiveApplicationContext(appContext);
|
|
4193
4196
|
return appContext;
|
|
4194
4197
|
}
|
|
4195
4198
|
var cachedAppContext;
|