@getstrata/bootstrap 0.2.49 → 0.2.51
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/CHANGELOG.md +13 -0
- package/README.md +3 -1
- package/dist/bootstrap/config.d.ts +1 -1
- package/dist/bootstrap/health.d.ts +8 -2
- package/dist/bootstrap/public-api.d.ts +4 -2
- package/dist/bootstrap/web/index.d.ts +1 -1
- package/dist/bootstrap/web/session.d.ts +42 -3
- package/dist/entries/buildModuleRoutes.js +19 -4
- package/dist/entries/buildWebModuleRoutes.js +19 -4
- package/dist/entries/config.js +4 -0
- package/dist/entries/context.js +2 -0
- package/dist/entries/createRoutes.js +203 -155
- package/dist/entries/createSpaRoutes.js +1 -1
- package/dist/entries/createWebRoutes.js +19 -4
- package/dist/entries/dependencies.js +2 -0
- package/dist/entries/health.js +69 -152
- package/dist/entries/httpKernel.js +19 -4
- package/dist/entries/providers.js +2 -0
- package/dist/entries/secretsGuard.js +64 -10
- package/dist/entries/web/routing.js +19 -4
- package/dist/entries/web/session.js +128 -28
- package/dist/index.js +309 -41
- package/package.json +6 -5
package/dist/index.js
CHANGED
|
@@ -20,6 +20,7 @@ import { applyMiddlewareToRoutes } from "@getstrata/core/http/middleware";
|
|
|
20
20
|
|
|
21
21
|
// ../../src/bootstrap/httpKernel.ts
|
|
22
22
|
import { createMembershipMiddleware } from "@getstrata/core/auth/membershipMiddleware";
|
|
23
|
+
import { resolveAbilityChecker } from "@getstrata/core/contracts/serviceTokens";
|
|
23
24
|
import { createAuthMiddleware } from "@getstrata/core/http/authMiddleware";
|
|
24
25
|
import { createAuthorizeMiddleware } from "@getstrata/core/http/authorizeMiddleware";
|
|
25
26
|
import { createBodySizeLimitMiddleware } from "@getstrata/core/http/bodySizeLimitMiddleware";
|
|
@@ -77,24 +78,38 @@ function parsePositiveInt(value, fallback) {
|
|
|
77
78
|
}
|
|
78
79
|
return Math.trunc(parsed);
|
|
79
80
|
}
|
|
81
|
+
function parseWindowSeconds(secondsValue, msValue, fallback) {
|
|
82
|
+
if (secondsValue !== undefined && secondsValue.trim() !== "") {
|
|
83
|
+
return parsePositiveInt(secondsValue, fallback);
|
|
84
|
+
}
|
|
85
|
+
if (msValue !== undefined && msValue.trim() !== "") {
|
|
86
|
+
const parsedMs = Number(msValue);
|
|
87
|
+
if (Number.isFinite(parsedMs) && parsedMs > 0) {
|
|
88
|
+
return Math.max(1, Math.trunc(parsedMs / 1000));
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return fallback;
|
|
92
|
+
}
|
|
80
93
|
function resolveLoginRateLimit() {
|
|
81
94
|
const defaults = isLocalAppEnv() ? LOCAL_LOGIN_RATE_LIMIT : PRODUCTION_LOGIN_RATE_LIMIT;
|
|
82
95
|
return {
|
|
83
96
|
maxAttempts: parsePositiveInt(process.env.LOGIN_RATE_LIMIT_PER_WINDOW, defaults.maxAttempts),
|
|
84
|
-
decaySeconds:
|
|
97
|
+
decaySeconds: parseWindowSeconds(process.env.LOGIN_RATE_LIMIT_WINDOW_SECONDS, process.env.LOGIN_RATE_LIMIT_WINDOW_MS, defaults.decaySeconds)
|
|
85
98
|
};
|
|
86
99
|
}
|
|
87
100
|
function resolveRegisterRateLimit() {
|
|
88
101
|
const defaults = isLocalAppEnv() ? { maxAttempts: 100, decaySeconds: 60 } : { maxAttempts: 10, decaySeconds: 60 };
|
|
89
102
|
return {
|
|
90
103
|
maxAttempts: parsePositiveInt(process.env.REGISTER_RATE_LIMIT_PER_WINDOW, defaults.maxAttempts),
|
|
91
|
-
decaySeconds:
|
|
104
|
+
decaySeconds: parseWindowSeconds(process.env.REGISTER_RATE_LIMIT_WINDOW_SECONDS, process.env.REGISTER_RATE_LIMIT_WINDOW_MS, defaults.decaySeconds)
|
|
92
105
|
};
|
|
93
106
|
}
|
|
94
107
|
|
|
95
108
|
// ../../src/bootstrap/config.ts
|
|
96
109
|
import {
|
|
110
|
+
CORE_ABILITY_CHECKER_TOKEN,
|
|
97
111
|
CORE_AUTH_TOKEN,
|
|
112
|
+
CORE_AUTH_USER_DIRECTORY_TOKEN,
|
|
98
113
|
CORE_CACHE_TOKEN,
|
|
99
114
|
CORE_CONFIG_TOKEN,
|
|
100
115
|
CORE_EVENT_BUS_TOKEN,
|
|
@@ -197,7 +212,7 @@ class HttpKernel {
|
|
|
197
212
|
}
|
|
198
213
|
wrapWebAbility(ability, handler) {
|
|
199
214
|
const auth = this.dependencies.container.resolve(CORE_AUTH_TOKEN);
|
|
200
|
-
const abilityChecker = this.dependencies.container
|
|
215
|
+
const abilityChecker = resolveAbilityChecker(this.dependencies.container);
|
|
201
216
|
const requireAbility = createRequireAbilityMiddleware(abilityChecker);
|
|
202
217
|
const middleware = [createRequireWebAuthMiddleware(auth), requireAbility(ability)];
|
|
203
218
|
return this.wrapWeb(withMiddleware(...middleware)(handler));
|
|
@@ -221,7 +236,7 @@ class HttpKernel {
|
|
|
221
236
|
return withMiddleware(...middleware)(handler);
|
|
222
237
|
}
|
|
223
238
|
wrapAbility(ability, handler) {
|
|
224
|
-
const abilityChecker = this.dependencies.container
|
|
239
|
+
const abilityChecker = resolveAbilityChecker(this.dependencies.container);
|
|
225
240
|
const requireAbility = createRequireAbilityMiddleware(abilityChecker);
|
|
226
241
|
const middleware = [...this.group("authenticated"), requireAbility(ability)];
|
|
227
242
|
return withMiddleware(...middleware)(handler);
|
|
@@ -891,6 +906,101 @@ function mergeWebRoutes(dependencies, routes) {
|
|
|
891
906
|
function createAppDependencies() {
|
|
892
907
|
return createAppContext().dependencies;
|
|
893
908
|
}
|
|
909
|
+
// ../../src/bootstrap/health.ts
|
|
910
|
+
import { getBoundDatabaseConnection } from "@getstrata/core/database/boundConnection";
|
|
911
|
+
import { getDefaultDatabasePool } from "@getstrata/core/database/defaultConnection";
|
|
912
|
+
import { jsonResponse } from "@getstrata/core/http/response";
|
|
913
|
+
var {RedisClient } = globalThis.Bun;
|
|
914
|
+
function resolveRedisUrl(dependencies) {
|
|
915
|
+
if (!dependencies.container.has(CORE_CONFIG_TOKEN)) {
|
|
916
|
+
return process.env.REDIS_URL?.trim() || undefined;
|
|
917
|
+
}
|
|
918
|
+
const config = dependencies.container.resolve(CORE_CONFIG_TOKEN);
|
|
919
|
+
const redisUrl = config.get(REDIS_URL_CONFIG_KEY)?.trim();
|
|
920
|
+
return redisUrl || undefined;
|
|
921
|
+
}
|
|
922
|
+
function resolveHealthDatabase() {
|
|
923
|
+
const bound = getBoundDatabaseConnection();
|
|
924
|
+
if (bound) {
|
|
925
|
+
return bound;
|
|
926
|
+
}
|
|
927
|
+
try {
|
|
928
|
+
return getDefaultDatabasePool();
|
|
929
|
+
} catch {
|
|
930
|
+
return null;
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
async function pingDatabaseClient(connection) {
|
|
934
|
+
try {
|
|
935
|
+
await connection.unsafe("SELECT 1");
|
|
936
|
+
return true;
|
|
937
|
+
} catch {
|
|
938
|
+
return false;
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
async function checkDatabase() {
|
|
942
|
+
const connection = resolveHealthDatabase();
|
|
943
|
+
if (!connection) {
|
|
944
|
+
return false;
|
|
945
|
+
}
|
|
946
|
+
return await pingDatabaseClient(connection);
|
|
947
|
+
}
|
|
948
|
+
async function pingDatabase() {
|
|
949
|
+
return await checkDatabase();
|
|
950
|
+
}
|
|
951
|
+
async function checkRedis(redisUrl) {
|
|
952
|
+
try {
|
|
953
|
+
const client = new RedisClient(redisUrl);
|
|
954
|
+
const response = await client.ping();
|
|
955
|
+
return response === "PONG";
|
|
956
|
+
} catch {
|
|
957
|
+
return false;
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
async function resolveExtraFields(extra) {
|
|
961
|
+
if (!extra) {
|
|
962
|
+
return {};
|
|
963
|
+
}
|
|
964
|
+
return typeof extra === "function" ? await extra() : extra;
|
|
965
|
+
}
|
|
966
|
+
async function collectDependencyChecks(dependencies) {
|
|
967
|
+
const checks = {
|
|
968
|
+
database: await checkDatabase() ? "ok" : "error"
|
|
969
|
+
};
|
|
970
|
+
const redisUrl = resolveRedisUrl(dependencies);
|
|
971
|
+
if (redisUrl) {
|
|
972
|
+
checks.redis = await checkRedis(redisUrl) ? "ok" : "error";
|
|
973
|
+
} else {
|
|
974
|
+
checks.redis = "skipped";
|
|
975
|
+
}
|
|
976
|
+
const ready = checks.database === "ok" && (checks.redis === "ok" || checks.redis === "skipped");
|
|
977
|
+
return { checks, ready };
|
|
978
|
+
}
|
|
979
|
+
function createHealthRoutes(dependencies, options = {}) {
|
|
980
|
+
return {
|
|
981
|
+
"/health": async () => {
|
|
982
|
+
const extra = await resolveExtraFields(options.extra);
|
|
983
|
+
if (!options.pingOnHealth) {
|
|
984
|
+
return jsonResponse({ status: "ok", ...extra });
|
|
985
|
+
}
|
|
986
|
+
const { checks, ready } = await collectDependencyChecks(dependencies);
|
|
987
|
+
return jsonResponse({
|
|
988
|
+
status: ready ? "ok" : "error",
|
|
989
|
+
checks,
|
|
990
|
+
...extra
|
|
991
|
+
}, { status: ready ? 200 : 503 });
|
|
992
|
+
},
|
|
993
|
+
"/ready": async () => {
|
|
994
|
+
const extra = await resolveExtraFields(options.extra);
|
|
995
|
+
const { checks, ready } = await collectDependencyChecks(dependencies);
|
|
996
|
+
return jsonResponse({
|
|
997
|
+
status: ready ? "ready" : "not_ready",
|
|
998
|
+
checks,
|
|
999
|
+
...extra
|
|
1000
|
+
}, { status: ready ? 200 : 503 });
|
|
1001
|
+
}
|
|
1002
|
+
};
|
|
1003
|
+
}
|
|
894
1004
|
// ../../src/bootstrap/http/securedRouteModelBinding.ts
|
|
895
1005
|
import {
|
|
896
1006
|
securedBindRouteModel,
|
|
@@ -902,6 +1012,7 @@ import { resolveMembershipService } from "@getstrata/core/auth/membershipService
|
|
|
902
1012
|
var DEFAULT_ADMIN_API_TOKEN = "workhub-admin-test-token";
|
|
903
1013
|
var DEFAULT_MEMBER_API_TOKEN = "workhub-member-test-token";
|
|
904
1014
|
var DEFAULT_SCIM_BEARER_TOKEN = "workhub-scim-test-token";
|
|
1015
|
+
var MIN_SESSION_SECRET_LENGTH = 32;
|
|
905
1016
|
var DEFAULT_TOKENS = new Set([DEFAULT_ADMIN_API_TOKEN, DEFAULT_MEMBER_API_TOKEN]);
|
|
906
1017
|
var DEFAULT_SCIM_TOKENS = new Set([DEFAULT_SCIM_BEARER_TOKEN]);
|
|
907
1018
|
function isEnabled(value, defaultEnabled) {
|
|
@@ -910,19 +1021,31 @@ function isEnabled(value, defaultEnabled) {
|
|
|
910
1021
|
}
|
|
911
1022
|
return defaultEnabled ? value !== "false" : value === "true";
|
|
912
1023
|
}
|
|
913
|
-
function
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
1024
|
+
function isTokenAuthEnabled(env) {
|
|
1025
|
+
return Boolean(env.ADMIN_API_TOKEN?.trim()) || Boolean(env.MEMBER_API_TOKEN?.trim()) || env.FEATURE_API_TOKENS === "true";
|
|
1026
|
+
}
|
|
1027
|
+
function isOAuthEnabled(env) {
|
|
1028
|
+
return isEnabled(env.FEATURE_OAUTH, false) || isEnabled(env.FEATURE_SAML, false) || Boolean(env.GITHUB_CLIENT_ID?.trim()) || Boolean(env.OIDC_ISSUER?.trim()) || Boolean(env.SAML_LOGIN_URL?.trim());
|
|
1029
|
+
}
|
|
1030
|
+
function isCorsConfigured(env) {
|
|
1031
|
+
return env.CORS_ALLOWED_ORIGINS !== undefined;
|
|
1032
|
+
}
|
|
1033
|
+
function assertAuthDevHeadersDisabled(env) {
|
|
1034
|
+
if (isEnabled(env.AUTH_DEV_HEADERS, true)) {
|
|
1035
|
+
throw new Error("Production startup blocked: set AUTH_DEV_HEADERS=false to disable development auth headers.");
|
|
917
1036
|
}
|
|
1037
|
+
}
|
|
1038
|
+
function assertSessionSecret(env) {
|
|
1039
|
+
const secret = env.SESSION_SECRET?.trim() ?? "";
|
|
1040
|
+
if (secret.length < MIN_SESSION_SECRET_LENGTH) {
|
|
1041
|
+
throw new Error("Production startup blocked: set SESSION_SECRET when FRONTEND_MODE=server-htmx (32+ characters).");
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
1044
|
+
function assertWorkHubProductionSecrets(env) {
|
|
918
1045
|
const adminToken = env.ADMIN_API_TOKEN ?? DEFAULT_ADMIN_API_TOKEN;
|
|
919
1046
|
const memberToken = env.MEMBER_API_TOKEN ?? DEFAULT_MEMBER_API_TOKEN;
|
|
920
1047
|
const scimToken = env.SCIM_BEARER_TOKEN ?? DEFAULT_SCIM_BEARER_TOKEN;
|
|
921
1048
|
const encryptionEnabled = isEnabled(env.FEATURE_FIELD_ENCRYPTION, true);
|
|
922
|
-
const devHeadersEnabled = isEnabled(env.AUTH_DEV_HEADERS, true);
|
|
923
|
-
if (devHeadersEnabled) {
|
|
924
|
-
throw new Error("Production startup blocked: set AUTH_DEV_HEADERS=false to disable development auth headers.");
|
|
925
|
-
}
|
|
926
1049
|
if (DEFAULT_TOKENS.has(adminToken) || DEFAULT_TOKENS.has(memberToken)) {
|
|
927
1050
|
throw new Error("Production startup blocked: rotate ADMIN_API_TOKEN and MEMBER_API_TOKEN away from default WorkHub test values.");
|
|
928
1051
|
}
|
|
@@ -954,9 +1077,50 @@ function assertProductionSecrets(env = process.env) {
|
|
|
954
1077
|
if (!env.API_TOKEN_DEFAULT_EXPIRY_DAYS?.trim()) {
|
|
955
1078
|
throw new Error("Production startup blocked: set API_TOKEN_DEFAULT_EXPIRY_DAYS to enforce token rotation.");
|
|
956
1079
|
}
|
|
1080
|
+
}
|
|
1081
|
+
function assertSiblingProductionSecrets(env) {
|
|
1082
|
+
if (isEnabled(env.FEATURE_SCIM, false)) {
|
|
1083
|
+
const scimToken = env.SCIM_BEARER_TOKEN ?? DEFAULT_SCIM_BEARER_TOKEN;
|
|
1084
|
+
if (DEFAULT_SCIM_TOKENS.has(scimToken) || !env.SCIM_BEARER_TOKEN?.trim()) {
|
|
1085
|
+
throw new Error("Production startup blocked: rotate SCIM_BEARER_TOKEN away from default WorkHub test values.");
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1088
|
+
if (isEnabled(env.FEATURE_FIELD_ENCRYPTION, false) && !env.KMS_ENCRYPTION_KEY?.trim()) {
|
|
1089
|
+
throw new Error("Production startup blocked: set KMS_ENCRYPTION_KEY when field encryption is enabled.");
|
|
1090
|
+
}
|
|
1091
|
+
if (isEnabled(env.FEATURE_BILLING, false) && !env.STRIPE_WEBHOOK_SECRET?.trim()) {
|
|
1092
|
+
throw new Error("Production startup blocked: set STRIPE_WEBHOOK_SECRET when billing webhooks are enabled.");
|
|
1093
|
+
}
|
|
1094
|
+
if (isOAuthEnabled(env) && !env.OAUTH_STATE_SECRET?.trim()) {
|
|
1095
|
+
throw new Error("Production startup blocked: set OAUTH_STATE_SECRET for OAuth CSRF protection.");
|
|
1096
|
+
}
|
|
1097
|
+
if (isCorsConfigured(env)) {
|
|
1098
|
+
const corsOrigins = (env.CORS_ALLOWED_ORIGINS ?? "*").split(",").map((origin) => origin.trim());
|
|
1099
|
+
if (corsOrigins.includes("*")) {
|
|
1100
|
+
throw new Error("Production startup blocked: set explicit CORS_ALLOWED_ORIGINS instead of wildcard.");
|
|
1101
|
+
}
|
|
1102
|
+
}
|
|
1103
|
+
if (isEnabled(env.FEATURE_PUBLIC_READS, false)) {
|
|
1104
|
+
throw new Error("Production startup blocked: set FEATURE_PUBLIC_READS=false for authenticated-only reads.");
|
|
1105
|
+
}
|
|
1106
|
+
if (!env.SIEM_EXPORT_URL?.trim() && isEnabled(env.FEATURE_SIEM_EXPORT, false)) {
|
|
1107
|
+
console.warn("[secrets] SIEM_EXPORT_URL is not configured; audit logs remain database-only.");
|
|
1108
|
+
}
|
|
1109
|
+
}
|
|
1110
|
+
function assertProductionSecrets(env = process.env) {
|
|
1111
|
+
const appEnv = env.APP_ENV ?? "local";
|
|
1112
|
+
if (appEnv !== "production") {
|
|
1113
|
+
return;
|
|
1114
|
+
}
|
|
1115
|
+
assertAuthDevHeadersDisabled(env);
|
|
1116
|
+
if (isTokenAuthEnabled(env)) {
|
|
1117
|
+
assertWorkHubProductionSecrets(env);
|
|
1118
|
+
} else {
|
|
1119
|
+
assertSiblingProductionSecrets(env);
|
|
1120
|
+
}
|
|
957
1121
|
const frontendMode = (env.FRONTEND_MODE ?? "api").trim();
|
|
958
|
-
if (frontendMode === "server-htmx"
|
|
959
|
-
|
|
1122
|
+
if (frontendMode === "server-htmx") {
|
|
1123
|
+
assertSessionSecret(env);
|
|
960
1124
|
}
|
|
961
1125
|
}
|
|
962
1126
|
// ../../src/bootstrap/web/forms.ts
|
|
@@ -1090,18 +1254,71 @@ function createWebServer(options) {
|
|
|
1090
1254
|
}
|
|
1091
1255
|
// ../../src/bootstrap/web/session.ts
|
|
1092
1256
|
import { createHash, randomBytes } from "crypto";
|
|
1257
|
+
import { AuthManager as AuthManager2 } from "@getstrata/core/auth/guard";
|
|
1258
|
+
import { getBoundDatabaseConnection as getBoundDatabaseConnection2 } from "@getstrata/core/database/boundConnection";
|
|
1259
|
+
import { getDefaultDatabasePool as getDefaultDatabasePool2 } from "@getstrata/core/database/defaultConnection";
|
|
1093
1260
|
import { readRequestCookie } from "@getstrata/core/http/cookies";
|
|
1261
|
+
function isSqlClient(value) {
|
|
1262
|
+
return typeof value.unsafe === "function";
|
|
1263
|
+
}
|
|
1264
|
+
function resolveSql(source) {
|
|
1265
|
+
if (isSqlClient(source)) {
|
|
1266
|
+
return source;
|
|
1267
|
+
}
|
|
1268
|
+
return source();
|
|
1269
|
+
}
|
|
1270
|
+
function defaultSessionSql() {
|
|
1271
|
+
const bound = getBoundDatabaseConnection2();
|
|
1272
|
+
if (bound) {
|
|
1273
|
+
return bound;
|
|
1274
|
+
}
|
|
1275
|
+
return getDefaultDatabasePool2();
|
|
1276
|
+
}
|
|
1277
|
+
function defaultMapSessionUser(user) {
|
|
1278
|
+
return {
|
|
1279
|
+
id: user.id,
|
|
1280
|
+
role: user.is_admin ? "admin" : "member"
|
|
1281
|
+
};
|
|
1282
|
+
}
|
|
1283
|
+
async function defaultLoadSessionUser(sql, sessionId) {
|
|
1284
|
+
const rows = await sql.unsafe(`SELECT s.id, s.user_id, s.expires_at, u.name, u.email, u.learn_subscriber,
|
|
1285
|
+
COALESCE(u.is_admin, false) AS is_admin
|
|
1286
|
+
FROM sessions s
|
|
1287
|
+
INNER JOIN users u ON u.id = s.user_id
|
|
1288
|
+
WHERE s.id = $1 AND s.expires_at > NOW()`, [sessionId]);
|
|
1289
|
+
const row = rows[0];
|
|
1290
|
+
if (!row)
|
|
1291
|
+
return null;
|
|
1292
|
+
return {
|
|
1293
|
+
id: row.user_id,
|
|
1294
|
+
name: row.name,
|
|
1295
|
+
email: row.email,
|
|
1296
|
+
learn_subscriber: row.learn_subscriber,
|
|
1297
|
+
is_admin: row.is_admin
|
|
1298
|
+
};
|
|
1299
|
+
}
|
|
1300
|
+
function redirectWithCookie(location, setCookie, status) {
|
|
1301
|
+
return new Response(null, {
|
|
1302
|
+
status,
|
|
1303
|
+
headers: {
|
|
1304
|
+
Location: location,
|
|
1305
|
+
"Set-Cookie": setCookie
|
|
1306
|
+
}
|
|
1307
|
+
});
|
|
1308
|
+
}
|
|
1094
1309
|
|
|
1095
1310
|
class CookieSessionStore {
|
|
1096
|
-
|
|
1311
|
+
sqlSource;
|
|
1097
1312
|
secret;
|
|
1098
1313
|
cookieName;
|
|
1099
1314
|
maxAgeSeconds;
|
|
1100
|
-
|
|
1101
|
-
|
|
1315
|
+
loadSessionUser;
|
|
1316
|
+
constructor(sqlSource, secret, cookieName = "strata_session", maxAgeSeconds = 60 * 60 * 24 * 14, loadSessionUser = defaultLoadSessionUser) {
|
|
1317
|
+
this.sqlSource = sqlSource;
|
|
1102
1318
|
this.secret = secret;
|
|
1103
1319
|
this.cookieName = cookieName;
|
|
1104
1320
|
this.maxAgeSeconds = maxAgeSeconds;
|
|
1321
|
+
this.loadSessionUser = loadSessionUser;
|
|
1105
1322
|
}
|
|
1106
1323
|
cookieHeader(_user, sessionId) {
|
|
1107
1324
|
const payload = `${sessionId}.${this.sign(sessionId)}`;
|
|
@@ -1110,16 +1327,30 @@ class CookieSessionStore {
|
|
|
1110
1327
|
clearCookieHeader() {
|
|
1111
1328
|
return this.withSecureFlag(`${this.cookieName}=; Path=/; HttpOnly; SameSite=Lax; Max-Age=0`);
|
|
1112
1329
|
}
|
|
1330
|
+
sessionIdFromRequest(request) {
|
|
1331
|
+
const cookie = readRequestCookie(request, this.cookieName);
|
|
1332
|
+
const raw = cookie ?? null;
|
|
1333
|
+
if (!raw)
|
|
1334
|
+
return null;
|
|
1335
|
+
const [sessionId, signature] = raw.split(".");
|
|
1336
|
+
if (!sessionId || !signature || signature !== this.sign(sessionId)) {
|
|
1337
|
+
return null;
|
|
1338
|
+
}
|
|
1339
|
+
return sessionId;
|
|
1340
|
+
}
|
|
1113
1341
|
withSecureFlag(header) {
|
|
1114
1342
|
if (true) {
|
|
1115
1343
|
return header;
|
|
1116
1344
|
}
|
|
1117
1345
|
return header.includes("Secure") ? header : `${header}; Secure`;
|
|
1118
1346
|
}
|
|
1347
|
+
sql() {
|
|
1348
|
+
return resolveSql(this.sqlSource);
|
|
1349
|
+
}
|
|
1119
1350
|
async create(user) {
|
|
1120
1351
|
const id = randomBytes(32).toString("hex");
|
|
1121
1352
|
const expires = new Date(Date.now() + this.maxAgeSeconds * 1000);
|
|
1122
|
-
await this.sql.unsafe(`INSERT INTO sessions (id, user_id, expires_at) VALUES ($1, $2, $3)`, [
|
|
1353
|
+
await this.sql().unsafe(`INSERT INTO sessions (id, user_id, expires_at) VALUES ($1, $2, $3)`, [
|
|
1123
1354
|
id,
|
|
1124
1355
|
user.id,
|
|
1125
1356
|
expires
|
|
@@ -1127,50 +1358,82 @@ class CookieSessionStore {
|
|
|
1127
1358
|
return id;
|
|
1128
1359
|
}
|
|
1129
1360
|
async destroy(sessionId) {
|
|
1130
|
-
await this.sql.unsafe(`DELETE FROM sessions WHERE id = $1`, [sessionId]);
|
|
1361
|
+
await this.sql().unsafe(`DELETE FROM sessions WHERE id = $1`, [sessionId]);
|
|
1131
1362
|
}
|
|
1132
1363
|
async read(request) {
|
|
1133
|
-
const
|
|
1134
|
-
|
|
1135
|
-
if (!raw)
|
|
1136
|
-
return null;
|
|
1137
|
-
const [sessionId, signature] = raw.split(".");
|
|
1138
|
-
if (!sessionId || !signature || signature !== this.sign(sessionId)) {
|
|
1139
|
-
return null;
|
|
1140
|
-
}
|
|
1141
|
-
const rows = await this.sql.unsafe(`SELECT s.id, s.user_id, s.expires_at, u.name, u.email, u.learn_subscriber,
|
|
1142
|
-
COALESCE(u.is_admin, false) AS is_admin
|
|
1143
|
-
FROM sessions s
|
|
1144
|
-
INNER JOIN users u ON u.id = s.user_id
|
|
1145
|
-
WHERE s.id = $1 AND s.expires_at > NOW()`, [sessionId]);
|
|
1146
|
-
const row = rows[0];
|
|
1147
|
-
if (!row)
|
|
1364
|
+
const sessionId = this.sessionIdFromRequest(request);
|
|
1365
|
+
if (!sessionId)
|
|
1148
1366
|
return null;
|
|
1149
|
-
return
|
|
1150
|
-
id: row.user_id,
|
|
1151
|
-
name: row.name,
|
|
1152
|
-
email: row.email,
|
|
1153
|
-
learn_subscriber: row.learn_subscriber,
|
|
1154
|
-
is_admin: row.is_admin
|
|
1155
|
-
};
|
|
1367
|
+
return this.loadSessionUser(this.sql(), sessionId);
|
|
1156
1368
|
}
|
|
1157
1369
|
sign(value) {
|
|
1158
1370
|
return createHash("sha256").update(`${value}.${this.secret}`).digest("hex").slice(0, 32);
|
|
1159
1371
|
}
|
|
1160
1372
|
}
|
|
1373
|
+
|
|
1374
|
+
class CookieSessionGuard {
|
|
1375
|
+
store;
|
|
1376
|
+
mapUser;
|
|
1377
|
+
constructor(store, mapUser = defaultMapSessionUser) {
|
|
1378
|
+
this.store = store;
|
|
1379
|
+
this.mapUser = mapUser;
|
|
1380
|
+
}
|
|
1381
|
+
async resolve(request) {
|
|
1382
|
+
const user = await this.store.read(request);
|
|
1383
|
+
if (!user) {
|
|
1384
|
+
return null;
|
|
1385
|
+
}
|
|
1386
|
+
return this.mapUser(user);
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
|
|
1390
|
+
class CookieSessionAuthManager extends AuthManager2 {
|
|
1391
|
+
store;
|
|
1392
|
+
constructor(store, mapUser = defaultMapSessionUser) {
|
|
1393
|
+
super(new CookieSessionGuard(store, mapUser));
|
|
1394
|
+
this.store = store;
|
|
1395
|
+
}
|
|
1396
|
+
async signIn(user) {
|
|
1397
|
+
const sessionId = await this.store.create(user);
|
|
1398
|
+
return { sessionId, setCookie: this.store.cookieHeader(user, sessionId) };
|
|
1399
|
+
}
|
|
1400
|
+
async signOut(request) {
|
|
1401
|
+
const sessionId = this.store.sessionIdFromRequest(request);
|
|
1402
|
+
if (sessionId) {
|
|
1403
|
+
await this.store.destroy(sessionId);
|
|
1404
|
+
}
|
|
1405
|
+
return { setCookie: this.store.clearCookieHeader() };
|
|
1406
|
+
}
|
|
1407
|
+
async signInRedirect(user, location, status = 302) {
|
|
1408
|
+
const { setCookie } = await this.signIn(user);
|
|
1409
|
+
return redirectWithCookie(location, setCookie, status);
|
|
1410
|
+
}
|
|
1411
|
+
async signOutRedirect(request, location, status = 302) {
|
|
1412
|
+
const { setCookie } = await this.signOut(request);
|
|
1413
|
+
return redirectWithCookie(location, setCookie, status);
|
|
1414
|
+
}
|
|
1415
|
+
}
|
|
1416
|
+
function createCookieSessionAuthManager(options = {}) {
|
|
1417
|
+
const store = options.store ?? new CookieSessionStore(options.sql ?? defaultSessionSql, options.secret ?? process.env.SESSION_SECRET?.trim() ?? "", options.cookieName, options.maxAgeSeconds, options.loadSessionUser);
|
|
1418
|
+
return new CookieSessionAuthManager(store, options.mapUser ?? defaultMapSessionUser);
|
|
1419
|
+
}
|
|
1161
1420
|
// ../../src/bootstrap/web/slug.ts
|
|
1162
1421
|
function slugify(value) {
|
|
1163
1422
|
return value.toLowerCase().trim().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
|
|
1164
1423
|
}
|
|
1165
1424
|
export {
|
|
1166
1425
|
APP_PORT_CONFIG_KEY,
|
|
1426
|
+
CORE_ABILITY_CHECKER_TOKEN,
|
|
1167
1427
|
CORE_AUTH_TOKEN,
|
|
1428
|
+
CORE_AUTH_USER_DIRECTORY_TOKEN,
|
|
1168
1429
|
CORE_CACHE_TOKEN,
|
|
1169
1430
|
CORE_CONFIG_TOKEN,
|
|
1170
1431
|
CORE_EVENT_BUS_TOKEN,
|
|
1171
1432
|
CORE_POLICY_GATE_TOKEN,
|
|
1172
1433
|
CORE_QUEUE_TOKEN,
|
|
1173
1434
|
CORE_TOKEN_SERVICE_TOKEN,
|
|
1435
|
+
CookieSessionAuthManager,
|
|
1436
|
+
CookieSessionGuard,
|
|
1174
1437
|
CookieSessionStore,
|
|
1175
1438
|
DATABASE_URL_CONFIG_KEY,
|
|
1176
1439
|
DEFAULT_APP_PORT,
|
|
@@ -1184,12 +1447,16 @@ export {
|
|
|
1184
1447
|
buildModuleRoutes,
|
|
1185
1448
|
buildWebModuleRoutes,
|
|
1186
1449
|
cacheTagsForModelWrite,
|
|
1450
|
+
checkDatabase,
|
|
1451
|
+
checkRedis,
|
|
1187
1452
|
collectProviders,
|
|
1188
1453
|
configureModulesDirectory,
|
|
1189
1454
|
coreProviders,
|
|
1190
1455
|
createAppContext,
|
|
1191
1456
|
createAppDependencies,
|
|
1457
|
+
createCookieSessionAuthManager,
|
|
1192
1458
|
createCsrfProtection,
|
|
1459
|
+
createHealthRoutes,
|
|
1193
1460
|
createHttpKernel,
|
|
1194
1461
|
createRouteKernel,
|
|
1195
1462
|
createWebRoutes,
|
|
@@ -1200,6 +1467,7 @@ export {
|
|
|
1200
1467
|
getRequiredDependency,
|
|
1201
1468
|
mergeWebRoutes,
|
|
1202
1469
|
parseFormBody,
|
|
1470
|
+
pingDatabase,
|
|
1203
1471
|
prefixRouteMap,
|
|
1204
1472
|
registerDefaultJobs,
|
|
1205
1473
|
resolveApplicationAuth,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@getstrata/bootstrap",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.51",
|
|
4
4
|
"description": "Strata application bootstrap — HttpKernel, DI, web session helpers",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -116,7 +116,7 @@
|
|
|
116
116
|
"default": "./dist/entries/providers.js"
|
|
117
117
|
},
|
|
118
118
|
"./providers/view": {
|
|
119
|
-
"types": "./dist/bootstrap/providers/view
|
|
119
|
+
"types": "./dist/bootstrap/providers/view.d.ts",
|
|
120
120
|
"import": "./dist/entries/providers/view.js",
|
|
121
121
|
"default": "./dist/entries/providers/view.js"
|
|
122
122
|
},
|
|
@@ -165,21 +165,22 @@
|
|
|
165
165
|
"types": "./dist/bootstrap/public-api.d.ts",
|
|
166
166
|
"files": [
|
|
167
167
|
"dist",
|
|
168
|
-
"README.md"
|
|
168
|
+
"README.md",
|
|
169
|
+
"CHANGELOG.md"
|
|
169
170
|
],
|
|
170
171
|
"scripts": {
|
|
171
172
|
"build": "bun run build:bundle && bun run build:shims && bun run build:subpaths && bun run build:types",
|
|
172
173
|
"build:bundle": "bun build index.ts --outdir dist --target bun --external bun --external eta --external @getstrata/core",
|
|
173
174
|
"build:types": "tsc -p tsconfig.types.json && bun ../../scripts/prune-bootstrap-dist-types.ts",
|
|
174
175
|
"prepublishOnly": "bun run build",
|
|
175
|
-
"build:subpaths": "bun build entries/applicationRegistry.ts entries/buildModuleRoutes.ts entries/buildWebModuleRoutes.ts entries/cache/modelCacheTags.ts entries/config.ts entries/context.ts entries/contracts.ts entries/createWebRoutes.ts entries/createRoutes.ts entries/createSpaRoutes.ts entries/dependencies.ts entries/discoverModules.ts entries/health.ts entries/http/securedRouteModelBinding.ts entries/httpKernel.ts entries/listeners/invalidateCacheOnModelWrite.ts entries/membershipService.ts entries/metricsRoutes.ts entries/queue/defaultJobs.ts entries/providers.ts entries/providers/view.ts entries/routeRegistry.ts entries/schedule.ts entries/secretsGuard.ts entries/web/forms.ts entries/web/routing.ts entries/web/server.ts entries/web/session.ts entries/web/slug.ts --outdir dist --root . --target bun --external bun --external eta --external @getstrata/core --external @getstrata/bootstrap --external @getstrata/bootstrap/applicationRegistry --external @getstrata/bootstrap/buildModuleRoutes --external @getstrata/bootstrap/buildWebModuleRoutes --external @getstrata/bootstrap/cache/modelCacheTags --external @getstrata/bootstrap/config --external @getstrata/bootstrap/context --external @getstrata/bootstrap/contracts --external @getstrata/bootstrap/createWebRoutes --external @getstrata/bootstrap/createRoutes --external @getstrata/bootstrap/createSpaRoutes --external @getstrata/bootstrap/dependencies --external @getstrata/bootstrap/discoverModules --external @getstrata/bootstrap/health --external @getstrata/bootstrap/http/securedRouteModelBinding --external @getstrata/bootstrap/httpKernel --external @getstrata/bootstrap/listeners/invalidateCacheOnModelWrite --external @getstrata/bootstrap/membershipService --external @getstrata/bootstrap/metricsRoutes --external @getstrata/bootstrap/queue/defaultJobs --external @getstrata/bootstrap/providers --external @getstrata/bootstrap/providers/view --external @getstrata/bootstrap/routeRegistry --external @getstrata/bootstrap/schedule --external @getstrata/bootstrap/secretsGuard --external @getstrata/bootstrap/web/forms --external @getstrata/bootstrap/web/routing --external @getstrata/bootstrap/web/server --external @getstrata/bootstrap/web/session --external @getstrata/bootstrap/web/slug --external @getstrata/core/auth/accessControl --external @getstrata/core/auth/abilityChecker --external @getstrata/core/auth/authContext --external @getstrata/core/auth/guard --external @getstrata/core/auth/membershipContext --external @getstrata/core/auth/membershipMiddleware --external @getstrata/core/auth/membershipScope --external @getstrata/core/auth/membershipService --external @getstrata/core/auth/oauth/oidcProvider --external @getstrata/core/auth/oauth/providers --external @getstrata/core/auth/oauth/samlProvider --external @getstrata/core/auth/oauth/types --external @getstrata/core/auth/password --external @getstrata/core/auth/policy --external @getstrata/core/auth/scimAuthMiddleware --external @getstrata/core/auth/sessionCookie --external @getstrata/core/auth/sessionGuard --external @getstrata/core/auth/tokenHash --external @getstrata/core/audit/exportAuditLogs --external @getstrata/core/audit/siemFormatter --external @getstrata/core/admin/formatValue --external @getstrata/core/admin/registry --external @getstrata/core/admin/types --external @getstrata/core/cache/tags --external @getstrata/core/cache/createCacheStore --external @getstrata/core/cache/repository --external @getstrata/core/cache/simpleCache --external @getstrata/core/cache/simpleCacheStore --external @getstrata/core/config/envSchema --external @getstrata/core/contracts/serviceTokens --external @getstrata/core/contracts/container --external @getstrata/core/contracts/di --external @getstrata/core/crypto/fieldEncryption --external @getstrata/core/crypto/mfaSecret --external @getstrata/core/database --external @getstrata/core/database/baseRepository --external @getstrata/core/database/bindConnection --external @getstrata/core/database/boundConnection --external @getstrata/core/database/connection --external @getstrata/core/database/defaultConnection --external @getstrata/core/database/errors --external @getstrata/core/database/factory --external @getstrata/core/database/migrations --external @getstrata/core/database/migrations/types --external @getstrata/core/database/model --external @getstrata/core/database/query --external @getstrata/core/database/relationships --external @getstrata/core/database/repositoryConnection --external @getstrata/core/database/repositoryQuery --external @getstrata/core/database/seeders --external @getstrata/core/database/seeders/types --external @getstrata/core/database/schema --external @getstrata/core/database/table --external @getstrata/core/database/transaction --external @getstrata/core/database/types --external @getstrata/core/database/whereBuilder --external @getstrata/core/errors/http --external @getstrata/core/events --external @getstrata/core/facades --external @getstrata/core/http --external @getstrata/core/http/authMiddleware --external @getstrata/core/http/authorizeMiddleware --external @getstrata/core/http/bodySizeLimitMiddleware --external @getstrata/core/http/clientIp --external @getstrata/core/http/cookies --external @getstrata/core/http/contentNegotiation --external @getstrata/core/http/conditionalResponse --external @getstrata/core/http/corsMiddleware --external @getstrata/core/http/csrfMiddleware --external @getstrata/core/http/csrfProtection --external @getstrata/core/http/csrfToken --external @getstrata/core/http/etag --external @getstrata/core/http/flashSession --external @getstrata/core/http/flashMiddleware --external @getstrata/core/http/formRequest --external @getstrata/core/http/middleware --external @getstrata/core/http/metricsMiddleware --external @getstrata/core/http/loginThrottleMiddleware --external @getstrata/core/http/memoryThrottleMiddleware --external @getstrata/core/http/pagination --external @getstrata/core/http/parseFormBody --external @getstrata/core/http/parseMultipartUpload --external @getstrata/core/http/requireAbilityMiddleware --external @getstrata/core/http/requireAuthMiddleware --external @getstrata/core/http/requireGlobalAdminMiddleware --external @getstrata/core/http/requireWebAuthMiddleware --external @getstrata/core/http/resources --external @getstrata/core/http/response --external @getstrata/core/http/route --external @getstrata/core/http/routeMiddleware --external @getstrata/core/http/routeModelBinding --external @getstrata/core/http/scimThrottleMiddleware --external @getstrata/core/http/securityHeadersMiddleware --external @getstrata/core/http/securedRouteModelBinding --external @getstrata/core/http/requestMetaContext --external @getstrata/core/http/webErrorResponse --external @getstrata/core/http/webFormRequest --external @getstrata/core/http/throttleMiddleware --external @getstrata/core/http/validation --external @getstrata/core/jobs/dispatchWebhookJob --external @getstrata/core/jobs/invalidateCacheTagsJob --external @getstrata/core/lifecycle/gracefulShutdown --external @getstrata/core/logging/logger --external @getstrata/core/logging/requestLoggingMiddleware --external @getstrata/core/mail/mailer --external @getstrata/core/mail/markdownMail --external @getstrata/core/mail/markdownMailable --external @getstrata/core/media/imageTransform --external @getstrata/core/metrics/prometheus --external @getstrata/core/notifications --external @getstrata/core/openapi/generator --external @getstrata/core/openapi/registeredRoute --external @getstrata/core/openapi/validate --external @getstrata/core/pagination --external @getstrata/core/queue --external @getstrata/core/queue/createAppQueue --external @getstrata/core/queue/failedJobRepository --external @getstrata/core/queue/failedJobService --external @getstrata/core/queue/jobRegistry --external @getstrata/core/queue/jobRunner --external @getstrata/core/queue/queueMetrics --external @getstrata/core/queue/publicQueue --external @getstrata/core/queue/redisQueue --external @getstrata/core/queue/types --external @getstrata/core/runtime/applicationRegistry --external @getstrata/core/runtime/asyncContextStore --external @getstrata/core/scheduler/schedule --external @getstrata/core/scheduler/osCron --external @getstrata/core/security/oauthState --external @getstrata/core/security/publicReads --external @getstrata/core/security/safeFetch --external @getstrata/core/security/safeUrl --external @getstrata/core/security/scimTenantTokens --external @getstrata/core/security/securityEvents --external @getstrata/core/security/stripeWebhook --external @getstrata/core/security/timingSafeCompare --external @getstrata/core/security/tokenExpiry --external @getstrata/core/security/totp --external @getstrata/core/storage/storage --external @getstrata/core/tenant/tenancyConfig --external @getstrata/core/tenant/tenantContext --external @getstrata/core/tenant/tenantDatabaseScope --external @getstrata/core/tenant/databaseTenantContext --external @getstrata/core/tenant/tenantMiddleware --external @getstrata/core/terminal/runShell --external @getstrata/core/tracing/traceContext --external @getstrata/core/tracing/tracingMiddleware --external @getstrata/core/validation/rules --external @getstrata/core/view",
|
|
176
|
+
"build:subpaths": "bun build entries/applicationRegistry.ts entries/buildModuleRoutes.ts entries/buildWebModuleRoutes.ts entries/cache/modelCacheTags.ts entries/config.ts entries/context.ts entries/contracts.ts entries/createWebRoutes.ts entries/createRoutes.ts entries/createSpaRoutes.ts entries/dependencies.ts entries/discoverModules.ts entries/health.ts entries/http/securedRouteModelBinding.ts entries/httpKernel.ts entries/listeners/invalidateCacheOnModelWrite.ts entries/membershipService.ts entries/metricsRoutes.ts entries/queue/defaultJobs.ts entries/providers.ts entries/providers/view.ts entries/routeRegistry.ts entries/schedule.ts entries/secretsGuard.ts entries/web/forms.ts entries/web/routing.ts entries/web/server.ts entries/web/session.ts entries/web/slug.ts --outdir dist --root . --target bun --external bun --external eta --external @getstrata/core --external @getstrata/bootstrap --external @getstrata/bootstrap/applicationRegistry --external @getstrata/bootstrap/buildModuleRoutes --external @getstrata/bootstrap/buildWebModuleRoutes --external @getstrata/bootstrap/cache/modelCacheTags --external @getstrata/bootstrap/config --external @getstrata/bootstrap/context --external @getstrata/bootstrap/contracts --external @getstrata/bootstrap/createWebRoutes --external @getstrata/bootstrap/createRoutes --external @getstrata/bootstrap/createSpaRoutes --external @getstrata/bootstrap/dependencies --external @getstrata/bootstrap/discoverModules --external @getstrata/bootstrap/health --external @getstrata/bootstrap/http/securedRouteModelBinding --external @getstrata/bootstrap/httpKernel --external @getstrata/bootstrap/listeners/invalidateCacheOnModelWrite --external @getstrata/bootstrap/membershipService --external @getstrata/bootstrap/metricsRoutes --external @getstrata/bootstrap/queue/defaultJobs --external @getstrata/bootstrap/providers --external @getstrata/bootstrap/providers/view --external @getstrata/bootstrap/routeRegistry --external @getstrata/bootstrap/schedule --external @getstrata/bootstrap/secretsGuard --external @getstrata/bootstrap/web/forms --external @getstrata/bootstrap/web/routing --external @getstrata/bootstrap/web/server --external @getstrata/bootstrap/web/session --external @getstrata/bootstrap/web/slug --external @getstrata/core/auth/accessControl --external @getstrata/core/auth/abilityChecker --external @getstrata/core/auth/authContext --external @getstrata/core/auth/guard --external @getstrata/core/auth/membershipContext --external @getstrata/core/auth/membershipMiddleware --external @getstrata/core/auth/membershipScope --external @getstrata/core/auth/membershipService --external @getstrata/core/auth/oauth/oidcProvider --external @getstrata/core/auth/oauth/providers --external @getstrata/core/auth/oauth/samlProvider --external @getstrata/core/auth/oauth/types --external @getstrata/core/auth/password --external @getstrata/core/auth/policy --external @getstrata/core/auth/scimAuthMiddleware --external @getstrata/core/auth/sessionCookie --external @getstrata/core/auth/sessionGuard --external @getstrata/core/auth/tokenHash --external @getstrata/core/audit/exportAuditLogs --external @getstrata/core/audit/siemFormatter --external @getstrata/core/admin/formatValue --external @getstrata/core/admin/registry --external @getstrata/core/admin/types --external @getstrata/core/cache/tags --external @getstrata/core/cache/createCacheStore --external @getstrata/core/cache/repository --external @getstrata/core/cache/simpleCache --external @getstrata/core/cache/simpleCacheStore --external @getstrata/core/config/envSchema --external @getstrata/core/contracts/serviceTokens --external @getstrata/core/contracts/container --external @getstrata/core/contracts/di --external @getstrata/core/crypto/fieldEncryption --external @getstrata/core/crypto/mfaSecret --external @getstrata/core/database --external @getstrata/core/database/baseRepository --external @getstrata/core/database/bindConnection --external @getstrata/core/database/boundConnection --external @getstrata/core/database/bunSql --external @getstrata/core/database/connection --external @getstrata/core/database/defaultConnection --external @getstrata/core/database/errors --external @getstrata/core/database/factory --external @getstrata/core/database/migrations --external @getstrata/core/database/migrations/types --external @getstrata/core/database/model --external @getstrata/core/database/query --external @getstrata/core/database/relationships --external @getstrata/core/database/repositoryConnection --external @getstrata/core/database/repositoryQuery --external @getstrata/core/database/seeders --external @getstrata/core/database/seeders/types --external @getstrata/core/database/schema --external @getstrata/core/database/table --external @getstrata/core/database/transaction --external @getstrata/core/database/types --external @getstrata/core/database/whereBuilder --external @getstrata/core/errors/http --external @getstrata/core/events --external @getstrata/core/facades --external @getstrata/core/http --external @getstrata/core/http/authMiddleware --external @getstrata/core/http/authorizeMiddleware --external @getstrata/core/http/bodySizeLimitMiddleware --external @getstrata/core/http/clientIp --external @getstrata/core/http/cookies --external @getstrata/core/http/contentNegotiation --external @getstrata/core/http/conditionalResponse --external @getstrata/core/http/corsMiddleware --external @getstrata/core/http/csrfMiddleware --external @getstrata/core/http/csrfProtection --external @getstrata/core/http/csrfToken --external @getstrata/core/http/etag --external @getstrata/core/http/flashSession --external @getstrata/core/http/flashMiddleware --external @getstrata/core/http/formRequest --external @getstrata/core/http/middleware --external @getstrata/core/http/metricsMiddleware --external @getstrata/core/http/loginThrottleMiddleware --external @getstrata/core/http/memoryThrottleMiddleware --external @getstrata/core/http/pagination --external @getstrata/core/http/parseFormBody --external @getstrata/core/http/parseMultipartUpload --external @getstrata/core/http/requireAbilityMiddleware --external @getstrata/core/http/requireAuthMiddleware --external @getstrata/core/http/requireGlobalAdminMiddleware --external @getstrata/core/http/requireWebAuthMiddleware --external @getstrata/core/http/resources --external @getstrata/core/http/response --external @getstrata/core/http/route --external @getstrata/core/http/routeMiddleware --external @getstrata/core/http/routeModelBinding --external @getstrata/core/http/scimThrottleMiddleware --external @getstrata/core/http/securityHeadersMiddleware --external @getstrata/core/http/securedRouteModelBinding --external @getstrata/core/http/requestMetaContext --external @getstrata/core/http/webErrorResponse --external @getstrata/core/http/webFormRequest --external @getstrata/core/http/throttleMiddleware --external @getstrata/core/http/validation --external @getstrata/core/jobs/dispatchWebhookJob --external @getstrata/core/jobs/invalidateCacheTagsJob --external @getstrata/core/lifecycle/gracefulShutdown --external @getstrata/core/logging/logger --external @getstrata/core/logging/requestLoggingMiddleware --external @getstrata/core/mail/mailer --external @getstrata/core/mail/markdownMail --external @getstrata/core/mail/markdownMailable --external @getstrata/core/media/imageTransform --external @getstrata/core/metrics/prometheus --external @getstrata/core/notifications --external @getstrata/core/openapi/generator --external @getstrata/core/openapi/registeredRoute --external @getstrata/core/openapi/validate --external @getstrata/core/pagination --external @getstrata/core/queue --external @getstrata/core/queue/createAppQueue --external @getstrata/core/queue/failedJobRepository --external @getstrata/core/queue/failedJobService --external @getstrata/core/queue/jobRegistry --external @getstrata/core/queue/jobRunner --external @getstrata/core/queue/queueMetrics --external @getstrata/core/queue/publicQueue --external @getstrata/core/queue/redisQueue --external @getstrata/core/queue/types --external @getstrata/core/runtime/applicationRegistry --external @getstrata/core/runtime/asyncContextStore --external @getstrata/core/scheduler/schedule --external @getstrata/core/scheduler/osCron --external @getstrata/core/security/oauthState --external @getstrata/core/security/publicReads --external @getstrata/core/security/safeFetch --external @getstrata/core/security/safeUrl --external @getstrata/core/security/scimTenantTokens --external @getstrata/core/security/securityEvents --external @getstrata/core/security/stripeWebhook --external @getstrata/core/security/timingSafeCompare --external @getstrata/core/security/tokenExpiry --external @getstrata/core/security/totp --external @getstrata/core/storage/storage --external @getstrata/core/tenant/tenancyConfig --external @getstrata/core/tenant/tenantContext --external @getstrata/core/tenant/tenantDatabaseScope --external @getstrata/core/tenant/databaseTenantContext --external @getstrata/core/tenant/tenantMiddleware --external @getstrata/core/terminal/runShell --external @getstrata/core/tracing/traceContext --external @getstrata/core/tracing/tracingMiddleware --external @getstrata/core/validation/rules --external @getstrata/core/view",
|
|
176
177
|
"build:shims": "true"
|
|
177
178
|
},
|
|
178
179
|
"publishConfig": {
|
|
179
180
|
"access": "public"
|
|
180
181
|
},
|
|
181
182
|
"peerDependencies": {
|
|
182
|
-
"@getstrata/core": "^0.5.
|
|
183
|
+
"@getstrata/core": "^0.5.60",
|
|
183
184
|
"typescript": "^5.9.0"
|
|
184
185
|
}
|
|
185
186
|
}
|