@getstrata/bootstrap 0.2.26 → 0.2.28
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/listeners/invalidateCacheOnModelWrite.d.ts +1 -1
- package/dist/entries/buildModuleRoutes.js +3 -0
- package/dist/entries/buildWebModuleRoutes.js +3 -0
- package/dist/entries/context.js +148 -124
- package/dist/entries/createSpaRoutes.js +62 -0
- package/dist/entries/createWebRoutes.js +3 -0
- package/dist/entries/dependencies.js +148 -124
- package/dist/entries/health.js +212 -0
- package/dist/entries/httpKernel.js +3 -0
- package/dist/entries/listeners/invalidateCacheOnModelWrite.js +118 -0
- package/dist/entries/metricsRoutes.js +16 -0
- package/dist/entries/providers/view.js +22 -0
- package/dist/entries/providers.js +226 -202
- package/dist/entries/web/routing.js +3 -0
- package/dist/index.js +441 -555
- package/package.json +22 -2
|
@@ -13,6 +13,9 @@ function readFrontendMode() {
|
|
|
13
13
|
function isViewsEnabled() {
|
|
14
14
|
return readFrontendMode() === "server-htmx";
|
|
15
15
|
}
|
|
16
|
+
function isSpaEnabled() {
|
|
17
|
+
return readFrontendMode() === "spa-react";
|
|
18
|
+
}
|
|
16
19
|
|
|
17
20
|
// ../../src/core/runtime/asyncContextStore.ts
|
|
18
21
|
import { AsyncLocalStorage } from "async_hooks";
|
|
@@ -213,6 +216,25 @@ function getDb() {
|
|
|
213
216
|
getDatabase();
|
|
214
217
|
return getDefaultDatabaseQuery();
|
|
215
218
|
}
|
|
219
|
+
async function pingDatabase(connection = getDatabase()) {
|
|
220
|
+
try {
|
|
221
|
+
await connection`SELECT 1`;
|
|
222
|
+
return true;
|
|
223
|
+
} catch {
|
|
224
|
+
return false;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
async function ensureDatabaseConnection() {
|
|
228
|
+
if (await pingDatabase()) {
|
|
229
|
+
return getDatabase();
|
|
230
|
+
}
|
|
231
|
+
await getDatabase().close().catch(() => {
|
|
232
|
+
return;
|
|
233
|
+
});
|
|
234
|
+
connectionHolder.connection = createDatabaseConnection(databaseConfig);
|
|
235
|
+
registerDefaultDatabasePool(connectionHolder.connection);
|
|
236
|
+
return getDatabase();
|
|
237
|
+
}
|
|
216
238
|
var db = new Proxy(function database() {}, {
|
|
217
239
|
apply(_target, _thisArg, args) {
|
|
218
240
|
return getDb()(...args);
|
|
@@ -201,6 +201,25 @@ function getDb() {
|
|
|
201
201
|
getDatabase();
|
|
202
202
|
return getDefaultDatabaseQuery();
|
|
203
203
|
}
|
|
204
|
+
async function pingDatabase(connection = getDatabase()) {
|
|
205
|
+
try {
|
|
206
|
+
await connection`SELECT 1`;
|
|
207
|
+
return true;
|
|
208
|
+
} catch {
|
|
209
|
+
return false;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
async function ensureDatabaseConnection() {
|
|
213
|
+
if (await pingDatabase()) {
|
|
214
|
+
return getDatabase();
|
|
215
|
+
}
|
|
216
|
+
await getDatabase().close().catch(() => {
|
|
217
|
+
return;
|
|
218
|
+
});
|
|
219
|
+
connectionHolder.connection = createDatabaseConnection(databaseConfig);
|
|
220
|
+
registerDefaultDatabasePool(connectionHolder.connection);
|
|
221
|
+
return getDatabase();
|
|
222
|
+
}
|
|
204
223
|
var db = new Proxy(function database() {}, {
|
|
205
224
|
apply(_target, _thisArg, args) {
|
|
206
225
|
return getDb()(...args);
|
|
@@ -1310,25 +1329,190 @@ function discoverListeners() {
|
|
|
1310
1329
|
return appListeners;
|
|
1311
1330
|
}
|
|
1312
1331
|
|
|
1313
|
-
// ../../src/
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1332
|
+
// ../../src/bootstrap/listeners/invalidateCacheOnModelWrite.ts
|
|
1333
|
+
import { eventBus as eventBus2, modelEventName as modelEventName2 } from "@getstrata/core/events";
|
|
1334
|
+
import InvalidateCacheTagsJob from "@getstrata/core/jobs/invalidateCacheTagsJob";
|
|
1335
|
+
import { createTrackedJob } from "@getstrata/core/queue/createAppQueue";
|
|
1336
|
+
|
|
1337
|
+
// ../../src/bootstrap/applicationRegistry.ts
|
|
1338
|
+
import {
|
|
1339
|
+
resolveApplicationAuth,
|
|
1340
|
+
resolveApplicationCache,
|
|
1341
|
+
resolveApplicationConfig,
|
|
1342
|
+
resolveApplicationDependencies,
|
|
1343
|
+
resolveApplicationEventBus,
|
|
1344
|
+
resolveApplicationLogger,
|
|
1345
|
+
resolveApplicationPolicyGate,
|
|
1346
|
+
resolveApplicationQueue,
|
|
1347
|
+
setActiveApplicationContext
|
|
1348
|
+
} from "@getstrata/core/runtime/applicationRegistry";
|
|
1349
|
+
|
|
1350
|
+
// ../../src/bootstrap/discoverModules.ts
|
|
1351
|
+
import { readdirSync as readdirSync2 } from "fs";
|
|
1352
|
+
import { join as join2 } from "path";
|
|
1353
|
+
import { pathToFileURL as pathToFileURL2 } from "url";
|
|
1354
|
+
var DISCOVER_MODULES_STATE_KEY = Symbol.for("@getstrata/discoverModulesState");
|
|
1355
|
+
function readDiscoverModulesState() {
|
|
1356
|
+
const existing = globalThis[DISCOVER_MODULES_STATE_KEY];
|
|
1357
|
+
if (existing) {
|
|
1358
|
+
return existing;
|
|
1359
|
+
}
|
|
1360
|
+
const state = { appModules: [] };
|
|
1361
|
+
globalThis[DISCOVER_MODULES_STATE_KEY] = state;
|
|
1362
|
+
return state;
|
|
1363
|
+
}
|
|
1364
|
+
function configureModulesDirectory(modulesDir) {
|
|
1365
|
+
readDiscoverModulesState().configuredModulesDir = modulesDir;
|
|
1366
|
+
}
|
|
1367
|
+
function resolveModulesDirectory(options) {
|
|
1368
|
+
const state = readDiscoverModulesState();
|
|
1369
|
+
if (options?.modulesDir) {
|
|
1370
|
+
return options.modulesDir;
|
|
1371
|
+
}
|
|
1372
|
+
if (state.configuredModulesDir) {
|
|
1373
|
+
return state.configuredModulesDir;
|
|
1374
|
+
}
|
|
1375
|
+
return join2(import.meta.dir, "../modules");
|
|
1376
|
+
}
|
|
1377
|
+
async function loadDiscoveredModules(options) {
|
|
1378
|
+
const modulesDirectory = resolveModulesDirectory(options);
|
|
1379
|
+
let moduleNames;
|
|
1380
|
+
try {
|
|
1381
|
+
moduleNames = readdirSync2(modulesDirectory, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
|
|
1382
|
+
} catch (error) {
|
|
1383
|
+
if (error.code === "ENOENT") {
|
|
1384
|
+
return [];
|
|
1385
|
+
}
|
|
1386
|
+
throw error;
|
|
1387
|
+
}
|
|
1388
|
+
const modules = await Promise.all(moduleNames.map(async (moduleName) => {
|
|
1389
|
+
const moduleUrl = pathToFileURL2(join2(modulesDirectory, moduleName, "index.ts")).href;
|
|
1390
|
+
const loaded = await import(moduleUrl);
|
|
1391
|
+
return loaded.default;
|
|
1392
|
+
}));
|
|
1393
|
+
return modules.filter((module) => module?.name !== undefined).sort((left, right) => (left.order ?? 100) - (right.order ?? 100));
|
|
1394
|
+
}
|
|
1395
|
+
async function ensureModulesLoaded(options) {
|
|
1396
|
+
const state = readDiscoverModulesState();
|
|
1397
|
+
if (state.appModules.length > 0) {
|
|
1398
|
+
return state.appModules;
|
|
1399
|
+
}
|
|
1400
|
+
state.modulesReady ??= loadDiscoveredModules(options).then((modules) => {
|
|
1401
|
+
state.appModules.splice(0, state.appModules.length, ...modules);
|
|
1402
|
+
return state.appModules;
|
|
1403
|
+
});
|
|
1404
|
+
return state.modulesReady;
|
|
1405
|
+
}
|
|
1406
|
+
function discoverModules() {
|
|
1407
|
+
return readDiscoverModulesState().appModules;
|
|
1318
1408
|
}
|
|
1319
1409
|
|
|
1320
|
-
// ../../src/
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1410
|
+
// ../../src/bootstrap/cache/modelCacheTags.ts
|
|
1411
|
+
function cacheTagsForModelWrite(tableName, action) {
|
|
1412
|
+
const module = discoverModules().find((entry) => entry.tableName === tableName);
|
|
1413
|
+
const baseTags = module?.cacheTags ?? [`${tableName}s`];
|
|
1414
|
+
const isDelete = action === "deleted" || action === "force-deleted";
|
|
1415
|
+
const extraTags = isDelete ? module?.cacheDeleteExtraTags ?? [] : [];
|
|
1416
|
+
return [...new Set([...baseTags, ...extraTags])];
|
|
1417
|
+
}
|
|
1418
|
+
function discoverModelTableNames() {
|
|
1419
|
+
return discoverModules().map((module) => module.tableName).filter((tableName) => tableName !== undefined);
|
|
1420
|
+
}
|
|
1421
|
+
|
|
1422
|
+
// ../../src/bootstrap/listeners/invalidateCacheOnModelWrite.ts
|
|
1423
|
+
var MODEL_WRITE_ACTIONS = ["created", "updated", "deleted", "restored", "force-deleted"];
|
|
1424
|
+
function registerInvalidateCacheOnModelWriteListeners(bus = eventBus2) {
|
|
1425
|
+
for (const tableName of discoverModelTableNames()) {
|
|
1426
|
+
for (const action of MODEL_WRITE_ACTIONS) {
|
|
1427
|
+
bus.listen(modelEventName2(tableName, action), async () => {
|
|
1428
|
+
const tags = cacheTagsForModelWrite(tableName, action);
|
|
1429
|
+
if (tags.length === 0) {
|
|
1430
|
+
return;
|
|
1431
|
+
}
|
|
1432
|
+
let cache;
|
|
1433
|
+
let queue;
|
|
1434
|
+
try {
|
|
1435
|
+
cache = resolveApplicationCache();
|
|
1436
|
+
queue = resolveApplicationQueue();
|
|
1437
|
+
} catch {
|
|
1438
|
+
return;
|
|
1439
|
+
}
|
|
1440
|
+
const job = createTrackedJob("cache.invalidate-tags", new InvalidateCacheTagsJob(cache));
|
|
1441
|
+
await queue.dispatch(job, { tags });
|
|
1442
|
+
});
|
|
1443
|
+
}
|
|
1326
1444
|
}
|
|
1327
|
-
|
|
1328
|
-
|
|
1445
|
+
}
|
|
1446
|
+
|
|
1447
|
+
// ../../src/bootstrap/providers/listeners.ts
|
|
1448
|
+
var registeredListenerGroups = new Set;
|
|
1449
|
+
function registerListenerGroup(name, register) {
|
|
1450
|
+
if (registeredListenerGroups.has(name)) {
|
|
1451
|
+
return;
|
|
1452
|
+
}
|
|
1453
|
+
registeredListenerGroups.add(name);
|
|
1454
|
+
register();
|
|
1455
|
+
}
|
|
1456
|
+
var listenersProvider = {
|
|
1457
|
+
name: "core.listeners",
|
|
1458
|
+
boot() {
|
|
1459
|
+
registerListenerGroup("cache.invalidate-on-model-write", () => {
|
|
1460
|
+
registerInvalidateCacheOnModelWriteListeners();
|
|
1461
|
+
});
|
|
1462
|
+
for (const [index, registerListener] of discoverListeners().entries()) {
|
|
1463
|
+
registerListenerGroup(`app.listener.${index}`, registerListener);
|
|
1464
|
+
}
|
|
1465
|
+
}
|
|
1466
|
+
};
|
|
1467
|
+
var listeners_default = listenersProvider;
|
|
1468
|
+
|
|
1469
|
+
// ../../src/core/auth/policy.ts
|
|
1470
|
+
var BLOCKED_POLICY_ACTIONS = new Set([
|
|
1471
|
+
"constructor",
|
|
1472
|
+
"toString",
|
|
1473
|
+
"valueOf",
|
|
1474
|
+
"hasOwnProperty",
|
|
1475
|
+
"isPrototypeOf",
|
|
1476
|
+
"propertyIsEnumerable",
|
|
1477
|
+
"__proto__"
|
|
1478
|
+
]);
|
|
1479
|
+
|
|
1480
|
+
class PolicyGate {
|
|
1481
|
+
constructor() {}
|
|
1482
|
+
policies = new Map;
|
|
1483
|
+
register(resource, policy) {
|
|
1484
|
+
this.policies.set(resource, policy);
|
|
1485
|
+
}
|
|
1486
|
+
allows(resource, action, user, model) {
|
|
1487
|
+
const policy = this.policies.get(resource);
|
|
1488
|
+
if (!policy) {
|
|
1489
|
+
return false;
|
|
1490
|
+
}
|
|
1491
|
+
if (BLOCKED_POLICY_ACTIONS.has(action) || !(action in policy)) {
|
|
1492
|
+
return false;
|
|
1493
|
+
}
|
|
1494
|
+
const handler = policy[action];
|
|
1495
|
+
if (typeof handler !== "function") {
|
|
1496
|
+
return false;
|
|
1497
|
+
}
|
|
1498
|
+
const resolvedUser = user === undefined ? currentAuthUser() : user;
|
|
1499
|
+
return model === undefined ? handler.call(policy, resolvedUser) : handler.call(policy, resolvedUser, model);
|
|
1500
|
+
}
|
|
1501
|
+
authorize(resource, action, user, model) {
|
|
1502
|
+
if (!this.allows(resource, action, user, model)) {
|
|
1503
|
+
throw new ForbiddenError2;
|
|
1504
|
+
}
|
|
1329
1505
|
}
|
|
1330
1506
|
}
|
|
1331
|
-
|
|
1507
|
+
|
|
1508
|
+
// ../../src/bootstrap/providers/policy.ts
|
|
1509
|
+
var policyProvider = {
|
|
1510
|
+
name: "core.policy",
|
|
1511
|
+
register({ container }) {
|
|
1512
|
+
container.set(CORE_POLICY_GATE_TOKEN, new PolicyGate);
|
|
1513
|
+
}
|
|
1514
|
+
};
|
|
1515
|
+
var policy_default = policyProvider;
|
|
1332
1516
|
|
|
1333
1517
|
// ../../src/core/pagination/index.ts
|
|
1334
1518
|
function buildPaginationMeta(input) {
|
|
@@ -1620,10 +1804,10 @@ function buildHavingClause(tableName, having, params) {
|
|
|
1620
1804
|
return body.length > 0 ? ` HAVING ${body}` : "";
|
|
1621
1805
|
}
|
|
1622
1806
|
function buildJoinClause(joins = []) {
|
|
1623
|
-
return joins.map((
|
|
1624
|
-
const joinType =
|
|
1625
|
-
const onClause =
|
|
1626
|
-
return ` ${joinType} ${quoteIdentifier(
|
|
1807
|
+
return joins.map((join3) => {
|
|
1808
|
+
const joinType = join3.type === "left" ? "LEFT JOIN" : "INNER JOIN";
|
|
1809
|
+
const onClause = join3.on.map(({ left, right }) => `${qualifyColumn(left.table, left.column)} = ${qualifyColumn(right.table, right.column)}`).join(" AND ");
|
|
1810
|
+
return ` ${joinType} ${quoteIdentifier(join3.table)} ON ${onClause}`;
|
|
1627
1811
|
}).join("");
|
|
1628
1812
|
}
|
|
1629
1813
|
function buildLimitClause(limit) {
|
|
@@ -2059,7 +2243,7 @@ class RepositoryQuery {
|
|
|
2059
2243
|
const rightRef = parseQualifiedColumn(right);
|
|
2060
2244
|
const table = type === "inner" ? rightRef.table : rightRef.table;
|
|
2061
2245
|
const joins = this.queryOptions.joins ?? [];
|
|
2062
|
-
const existing = joins.find((
|
|
2246
|
+
const existing = joins.find((join3) => join3.table === table && join3.type === type);
|
|
2063
2247
|
if (existing) {
|
|
2064
2248
|
existing.on.push({ left: leftRef, right: rightRef });
|
|
2065
2249
|
return this;
|
|
@@ -3216,9 +3400,6 @@ class ResilientQueue {
|
|
|
3216
3400
|
function createFailedJobService() {
|
|
3217
3401
|
return new failedJobService_default(new failedJobRepository_default);
|
|
3218
3402
|
}
|
|
3219
|
-
function createTrackedJob(name, job) {
|
|
3220
|
-
return jobRegistry.track(name, job);
|
|
3221
|
-
}
|
|
3222
3403
|
function createProductionQueue(driver, options = {}) {
|
|
3223
3404
|
options.registerJobs?.();
|
|
3224
3405
|
const failedJobs = options.failedJobs ?? createFailedJobService();
|
|
@@ -3241,189 +3422,16 @@ function createAppQueue(driver, redisUrl, failedJobs = createFailedJobService(),
|
|
|
3241
3422
|
});
|
|
3242
3423
|
}
|
|
3243
3424
|
|
|
3244
|
-
// ../../src/bootstrap/applicationRegistry.ts
|
|
3245
|
-
import {
|
|
3246
|
-
resolveApplicationAuth,
|
|
3247
|
-
resolveApplicationCache,
|
|
3248
|
-
resolveApplicationConfig,
|
|
3249
|
-
resolveApplicationDependencies,
|
|
3250
|
-
resolveApplicationEventBus,
|
|
3251
|
-
resolveApplicationLogger,
|
|
3252
|
-
resolveApplicationPolicyGate,
|
|
3253
|
-
resolveApplicationQueue,
|
|
3254
|
-
setActiveApplicationContext
|
|
3255
|
-
} from "@getstrata/core/runtime/applicationRegistry";
|
|
3256
|
-
|
|
3257
|
-
// ../../src/bootstrap/discoverModules.ts
|
|
3258
|
-
import { readdirSync as readdirSync2 } from "fs";
|
|
3259
|
-
import { join as join2 } from "path";
|
|
3260
|
-
import { pathToFileURL as pathToFileURL2 } from "url";
|
|
3261
|
-
var DISCOVER_MODULES_STATE_KEY = Symbol.for("@getstrata/discoverModulesState");
|
|
3262
|
-
function readDiscoverModulesState() {
|
|
3263
|
-
const existing = globalThis[DISCOVER_MODULES_STATE_KEY];
|
|
3264
|
-
if (existing) {
|
|
3265
|
-
return existing;
|
|
3266
|
-
}
|
|
3267
|
-
const state = { appModules: [] };
|
|
3268
|
-
globalThis[DISCOVER_MODULES_STATE_KEY] = state;
|
|
3269
|
-
return state;
|
|
3270
|
-
}
|
|
3271
|
-
function configureModulesDirectory(modulesDir) {
|
|
3272
|
-
readDiscoverModulesState().configuredModulesDir = modulesDir;
|
|
3273
|
-
}
|
|
3274
|
-
function resolveModulesDirectory(options) {
|
|
3275
|
-
const state = readDiscoverModulesState();
|
|
3276
|
-
if (options?.modulesDir) {
|
|
3277
|
-
return options.modulesDir;
|
|
3278
|
-
}
|
|
3279
|
-
if (state.configuredModulesDir) {
|
|
3280
|
-
return state.configuredModulesDir;
|
|
3281
|
-
}
|
|
3282
|
-
return join2(import.meta.dir, "../modules");
|
|
3283
|
-
}
|
|
3284
|
-
async function loadDiscoveredModules(options) {
|
|
3285
|
-
const modulesDirectory = resolveModulesDirectory(options);
|
|
3286
|
-
let moduleNames;
|
|
3287
|
-
try {
|
|
3288
|
-
moduleNames = readdirSync2(modulesDirectory, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
|
|
3289
|
-
} catch (error) {
|
|
3290
|
-
if (error.code === "ENOENT") {
|
|
3291
|
-
return [];
|
|
3292
|
-
}
|
|
3293
|
-
throw error;
|
|
3294
|
-
}
|
|
3295
|
-
const modules = await Promise.all(moduleNames.map(async (moduleName) => {
|
|
3296
|
-
const moduleUrl = pathToFileURL2(join2(modulesDirectory, moduleName, "index.ts")).href;
|
|
3297
|
-
const loaded = await import(moduleUrl);
|
|
3298
|
-
return loaded.default;
|
|
3299
|
-
}));
|
|
3300
|
-
return modules.filter((module) => module?.name !== undefined).sort((left, right) => (left.order ?? 100) - (right.order ?? 100));
|
|
3301
|
-
}
|
|
3302
|
-
async function ensureModulesLoaded(options) {
|
|
3303
|
-
const state = readDiscoverModulesState();
|
|
3304
|
-
if (state.appModules.length > 0) {
|
|
3305
|
-
return state.appModules;
|
|
3306
|
-
}
|
|
3307
|
-
state.modulesReady ??= loadDiscoveredModules(options).then((modules) => {
|
|
3308
|
-
state.appModules.splice(0, state.appModules.length, ...modules);
|
|
3309
|
-
return state.appModules;
|
|
3310
|
-
});
|
|
3311
|
-
return state.modulesReady;
|
|
3312
|
-
}
|
|
3313
|
-
function discoverModules() {
|
|
3314
|
-
return readDiscoverModulesState().appModules;
|
|
3315
|
-
}
|
|
3316
|
-
|
|
3317
|
-
// ../../src/bootstrap/cache/modelCacheTags.ts
|
|
3318
|
-
function cacheTagsForModelWrite(tableName, action) {
|
|
3319
|
-
const module = discoverModules().find((entry) => entry.tableName === tableName);
|
|
3320
|
-
const baseTags = module?.cacheTags ?? [`${tableName}s`];
|
|
3321
|
-
const isDelete = action === "deleted" || action === "force-deleted";
|
|
3322
|
-
const extraTags = isDelete ? module?.cacheDeleteExtraTags ?? [] : [];
|
|
3323
|
-
return [...new Set([...baseTags, ...extraTags])];
|
|
3324
|
-
}
|
|
3325
|
-
function discoverModelTableNames() {
|
|
3326
|
-
return discoverModules().map((module) => module.tableName).filter((tableName) => tableName !== undefined);
|
|
3327
|
-
}
|
|
3328
|
-
|
|
3329
|
-
// ../../src/bootstrap/listeners/invalidateCacheOnModelWrite.ts
|
|
3330
|
-
var MODEL_WRITE_ACTIONS = ["created", "updated", "deleted", "restored", "force-deleted"];
|
|
3331
|
-
function registerInvalidateCacheOnModelWriteListeners(bus = eventBus) {
|
|
3332
|
-
for (const tableName of discoverModelTableNames()) {
|
|
3333
|
-
for (const action of MODEL_WRITE_ACTIONS) {
|
|
3334
|
-
bus.listen(modelEventName(tableName, action), async () => {
|
|
3335
|
-
const tags = cacheTagsForModelWrite(tableName, action);
|
|
3336
|
-
if (tags.length === 0) {
|
|
3337
|
-
return;
|
|
3338
|
-
}
|
|
3339
|
-
let cache;
|
|
3340
|
-
let queue;
|
|
3341
|
-
try {
|
|
3342
|
-
cache = resolveApplicationCache();
|
|
3343
|
-
queue = resolveApplicationQueue();
|
|
3344
|
-
} catch {
|
|
3345
|
-
return;
|
|
3346
|
-
}
|
|
3347
|
-
const job = createTrackedJob("cache.invalidate-tags", new invalidateCacheTagsJob_default(cache));
|
|
3348
|
-
await queue.dispatch(job, { tags });
|
|
3349
|
-
});
|
|
3350
|
-
}
|
|
3351
|
-
}
|
|
3352
|
-
}
|
|
3353
|
-
|
|
3354
|
-
// ../../src/bootstrap/providers/listeners.ts
|
|
3355
|
-
var registeredListenerGroups = new Set;
|
|
3356
|
-
function registerListenerGroup(name, register) {
|
|
3357
|
-
if (registeredListenerGroups.has(name)) {
|
|
3358
|
-
return;
|
|
3359
|
-
}
|
|
3360
|
-
registeredListenerGroups.add(name);
|
|
3361
|
-
register();
|
|
3362
|
-
}
|
|
3363
|
-
var listenersProvider = {
|
|
3364
|
-
name: "core.listeners",
|
|
3365
|
-
boot() {
|
|
3366
|
-
registerListenerGroup("cache.invalidate-on-model-write", () => {
|
|
3367
|
-
registerInvalidateCacheOnModelWriteListeners();
|
|
3368
|
-
});
|
|
3369
|
-
for (const [index, registerListener] of discoverListeners().entries()) {
|
|
3370
|
-
registerListenerGroup(`app.listener.${index}`, registerListener);
|
|
3371
|
-
}
|
|
3372
|
-
}
|
|
3373
|
-
};
|
|
3374
|
-
var listeners_default = listenersProvider;
|
|
3375
|
-
|
|
3376
|
-
// ../../src/core/auth/policy.ts
|
|
3377
|
-
var BLOCKED_POLICY_ACTIONS = new Set([
|
|
3378
|
-
"constructor",
|
|
3379
|
-
"toString",
|
|
3380
|
-
"valueOf",
|
|
3381
|
-
"hasOwnProperty",
|
|
3382
|
-
"isPrototypeOf",
|
|
3383
|
-
"propertyIsEnumerable",
|
|
3384
|
-
"__proto__"
|
|
3385
|
-
]);
|
|
3386
|
-
|
|
3387
|
-
class PolicyGate {
|
|
3388
|
-
constructor() {}
|
|
3389
|
-
policies = new Map;
|
|
3390
|
-
register(resource, policy) {
|
|
3391
|
-
this.policies.set(resource, policy);
|
|
3392
|
-
}
|
|
3393
|
-
allows(resource, action, user, model) {
|
|
3394
|
-
const policy = this.policies.get(resource);
|
|
3395
|
-
if (!policy) {
|
|
3396
|
-
return false;
|
|
3397
|
-
}
|
|
3398
|
-
if (BLOCKED_POLICY_ACTIONS.has(action) || !(action in policy)) {
|
|
3399
|
-
return false;
|
|
3400
|
-
}
|
|
3401
|
-
const handler = policy[action];
|
|
3402
|
-
if (typeof handler !== "function") {
|
|
3403
|
-
return false;
|
|
3404
|
-
}
|
|
3405
|
-
const resolvedUser = user === undefined ? currentAuthUser() : user;
|
|
3406
|
-
return model === undefined ? handler.call(policy, resolvedUser) : handler.call(policy, resolvedUser, model);
|
|
3407
|
-
}
|
|
3408
|
-
authorize(resource, action, user, model) {
|
|
3409
|
-
if (!this.allows(resource, action, user, model)) {
|
|
3410
|
-
throw new ForbiddenError2;
|
|
3411
|
-
}
|
|
3412
|
-
}
|
|
3413
|
-
}
|
|
3414
|
-
|
|
3415
|
-
// ../../src/bootstrap/providers/policy.ts
|
|
3416
|
-
var policyProvider = {
|
|
3417
|
-
name: "core.policy",
|
|
3418
|
-
register({ container }) {
|
|
3419
|
-
container.set(CORE_POLICY_GATE_TOKEN, new PolicyGate);
|
|
3420
|
-
}
|
|
3421
|
-
};
|
|
3422
|
-
var policy_default = policyProvider;
|
|
3423
|
-
|
|
3424
3425
|
// ../../src/core/jobs/dispatchWebhookJob.ts
|
|
3425
3426
|
import { createHmac as createHmac2 } from "crypto";
|
|
3426
3427
|
|
|
3428
|
+
// ../../src/core/queue/index.ts
|
|
3429
|
+
class Job {
|
|
3430
|
+
maxAttempts;
|
|
3431
|
+
backoffMs;
|
|
3432
|
+
priority;
|
|
3433
|
+
}
|
|
3434
|
+
|
|
3427
3435
|
// ../../src/core/security/safeUrl.ts
|
|
3428
3436
|
import { lookup as dnsLookupImpl } from "dns/promises";
|
|
3429
3437
|
var dnsLookup = dnsLookupImpl;
|
|
@@ -3608,6 +3616,19 @@ class DispatchWebhookJob extends Job {
|
|
|
3608
3616
|
}
|
|
3609
3617
|
var dispatchWebhookJob_default = DispatchWebhookJob;
|
|
3610
3618
|
|
|
3619
|
+
// ../../src/core/jobs/invalidateCacheTagsJob.ts
|
|
3620
|
+
class InvalidateCacheTagsJob2 extends Job {
|
|
3621
|
+
cache;
|
|
3622
|
+
constructor(cache) {
|
|
3623
|
+
super();
|
|
3624
|
+
this.cache = cache;
|
|
3625
|
+
}
|
|
3626
|
+
async handle(payload) {
|
|
3627
|
+
await this.cache.tags(...payload.tags).flush();
|
|
3628
|
+
}
|
|
3629
|
+
}
|
|
3630
|
+
var invalidateCacheTagsJob_default = InvalidateCacheTagsJob2;
|
|
3631
|
+
|
|
3611
3632
|
// ../../src/core/contracts/di.ts
|
|
3612
3633
|
function getRequiredDependency(dependencies, key) {
|
|
3613
3634
|
const dependency = dependencies[key];
|
|
@@ -3845,6 +3866,9 @@ function readFrontendMode() {
|
|
|
3845
3866
|
function isViewsEnabled() {
|
|
3846
3867
|
return readFrontendMode() === "server-htmx";
|
|
3847
3868
|
}
|
|
3869
|
+
function isSpaEnabled() {
|
|
3870
|
+
return readFrontendMode() === "spa-react";
|
|
3871
|
+
}
|
|
3848
3872
|
|
|
3849
3873
|
// ../../src/core/http/requestMetaContext.ts
|
|
3850
3874
|
var requestMetaContext = createAsyncContextStore("@getstrata/requestMetaContext");
|
|
@@ -336,6 +336,9 @@ function readFrontendMode() {
|
|
|
336
336
|
function isViewsEnabled() {
|
|
337
337
|
return readFrontendMode() === "server-htmx";
|
|
338
338
|
}
|
|
339
|
+
function isSpaEnabled() {
|
|
340
|
+
return readFrontendMode() === "spa-react";
|
|
341
|
+
}
|
|
339
342
|
|
|
340
343
|
// ../../src/config/rateLimit.ts
|
|
341
344
|
var LOCAL_LOGIN_RATE_LIMIT = {
|