@getstrata/bootstrap 0.2.8 → 0.2.10

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.
@@ -1,6 +1,6 @@
1
1
  // @bun
2
2
  // ../../src/bootstrap/context.ts
3
- import { setActiveApplicationContext as setActiveApplicationContext2 } from "@getstrata/core";
3
+ import { setActiveApplicationContext } from "@getstrata/core";
4
4
 
5
5
  // ../../src/bootstrap/contracts.ts
6
6
  class ServiceContainer {
@@ -217,9 +217,22 @@ var databaseConfig = {
217
217
  connectionTimeoutSeconds: readInteger("DB_CONNECTION_TIMEOUT", 10)
218
218
  };
219
219
 
220
- // ../../src/core/database/connectionContext.ts
220
+ // ../../src/core/runtime/asyncContextStore.ts
221
221
  import { AsyncLocalStorage } from "async_hooks";
222
- var activeConnection = new AsyncLocalStorage;
222
+ function createAsyncContextStore(key) {
223
+ const symbol = Symbol.for(key);
224
+ const globalRecord = globalThis;
225
+ const existing = globalRecord[symbol];
226
+ if (existing) {
227
+ return existing;
228
+ }
229
+ const store = new AsyncLocalStorage;
230
+ globalRecord[symbol] = store;
231
+ return store;
232
+ }
233
+
234
+ // ../../src/core/database/connectionContext.ts
235
+ var activeConnection = createAsyncContextStore("@getstrata/databaseConnectionContext");
223
236
  function getActiveDatabaseConnection(fallback) {
224
237
  return activeConnection.getStore() ?? fallback;
225
238
  }
@@ -306,6 +319,7 @@ var db = new Proxy(function database() {}, {
306
319
  return typeof value === "function" ? value.bind(connection) : value;
307
320
  }
308
321
  });
322
+ var connection_default = db;
309
323
 
310
324
  // ../../src/modules/user/apiTokenTable.ts
311
325
  import { defineTable } from "@getstrata/core/database";
@@ -534,8 +548,7 @@ class PreconditionFailedError extends HttpError {
534
548
  }
535
549
 
536
550
  // ../../src/core/auth/authContext.ts
537
- import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
538
- var authContext = new AsyncLocalStorage2;
551
+ var authContext = createAsyncContextStore("@getstrata/authContext");
539
552
  function currentAuthUser() {
540
553
  return authContext.getStore() ?? null;
541
554
  }
@@ -1409,6 +1422,9 @@ function discoverListeners() {
1409
1422
  return appListeners;
1410
1423
  }
1411
1424
 
1425
+ // ../../src/bootstrap/listeners/invalidateCacheOnModelWrite.ts
1426
+ import { resolveApplicationCache as resolveApplicationCache2, resolveApplicationQueue } from "@getstrata/core";
1427
+
1412
1428
  // ../../src/core/cache/modelCacheTags.ts
1413
1429
  function cacheTagsForModelWrite(tableName, action) {
1414
1430
  const module = appModules.find((entry) => entry.tableName === tableName);
@@ -1441,313 +1457,6 @@ class InvalidateCacheTagsJob extends Job {
1441
1457
  }
1442
1458
  var invalidateCacheTagsJob_default = InvalidateCacheTagsJob;
1443
1459
 
1444
- // ../../src/core/logging/logger.ts
1445
- class Logger {
1446
- channel;
1447
- constructor(channel = "app") {
1448
- this.channel = channel;
1449
- }
1450
- write(level, message, context = {}) {
1451
- const entry = {
1452
- level,
1453
- channel: this.channel,
1454
- message,
1455
- timestamp: new Date().toISOString(),
1456
- ...context
1457
- };
1458
- const line = JSON.stringify(entry);
1459
- if (level === "error") {
1460
- console.error(line);
1461
- return;
1462
- }
1463
- console.log(line);
1464
- }
1465
- debug(message, context) {
1466
- this.write("debug", message, context);
1467
- }
1468
- info(message, context) {
1469
- this.write("info", message, context);
1470
- }
1471
- warn(message, context) {
1472
- this.write("warn", message, context);
1473
- }
1474
- error(message, context) {
1475
- this.write("error", message, context);
1476
- }
1477
- }
1478
- var appLogger = new Logger("app");
1479
-
1480
- // ../../src/bootstrap/applicationRegistry.ts
1481
- var activeContext;
1482
- function setActiveApplicationContext(context) {
1483
- activeContext = context;
1484
- }
1485
- function requireActiveApplicationContext() {
1486
- if (!activeContext) {
1487
- throw new Error("The application context has not been bootstrapped.");
1488
- }
1489
- return activeContext;
1490
- }
1491
- function resolveApplicationCache() {
1492
- return getRequiredDependency(requireActiveApplicationContext().dependencies, "cache");
1493
- }
1494
- function resolveApplicationQueue() {
1495
- return requireActiveApplicationContext().container.resolve(CORE_QUEUE_TOKEN);
1496
- }
1497
- function resolveApplicationAuth() {
1498
- return requireActiveApplicationContext().container.resolve(CORE_AUTH_TOKEN);
1499
- }
1500
- function resolveApplicationPolicyGate() {
1501
- return requireActiveApplicationContext().container.resolve(CORE_POLICY_GATE_TOKEN);
1502
- }
1503
- function resolveApplicationConfig() {
1504
- return requireActiveApplicationContext().config;
1505
- }
1506
- function resolveApplicationLogger() {
1507
- return appLogger;
1508
- }
1509
- function resolveApplicationDependencies() {
1510
- return requireActiveApplicationContext().dependencies;
1511
- }
1512
-
1513
- // ../../src/core/jobs/dispatchWebhookJob.ts
1514
- import { createHmac as createHmac2 } from "crypto";
1515
-
1516
- // ../../src/core/database/boundConnection.ts
1517
- var boundConnectionHolder = {
1518
- connection: null
1519
- };
1520
- function getBoundDatabaseConnection() {
1521
- return boundConnectionHolder.connection;
1522
- }
1523
-
1524
- // ../../src/core/database/repositoryConnection.ts
1525
- function resolveRepositoryConnection() {
1526
- return getBoundDatabaseConnection() ?? getDefaultDatabaseQuery();
1527
- }
1528
- var repositoryConnection = new Proxy(function repositoryConnection2() {}, {
1529
- apply(_target, _thisArg, args) {
1530
- return resolveRepositoryConnection()(...args);
1531
- },
1532
- get(_target, property) {
1533
- const connection = resolveRepositoryConnection();
1534
- const value = connection[property];
1535
- return typeof value === "function" ? value.bind(connection) : value;
1536
- }
1537
- });
1538
-
1539
- // ../../src/core/security/safeUrl.ts
1540
- import { lookup as dnsLookupImpl } from "dns/promises";
1541
- var dnsLookup = dnsLookupImpl;
1542
- var BLOCKED_HOSTNAMES = new Set([
1543
- "localhost",
1544
- "127.0.0.1",
1545
- "0.0.0.0",
1546
- "::1",
1547
- "metadata.google.internal"
1548
- ]);
1549
- function isPrivateIpv4(hostname) {
1550
- const match = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/.exec(hostname);
1551
- if (!match) {
1552
- return false;
1553
- }
1554
- const octets = match.slice(1, 5).map((part) => Number.parseInt(part, 10));
1555
- if (octets.some((octet) => octet < 0 || octet > 255)) {
1556
- return true;
1557
- }
1558
- const [a = 0, b = 0] = octets;
1559
- if (a === 10) {
1560
- return true;
1561
- }
1562
- if (a === 127) {
1563
- return true;
1564
- }
1565
- if (a === 0) {
1566
- return true;
1567
- }
1568
- if (a === 169 && b === 254) {
1569
- return true;
1570
- }
1571
- if (a === 172 && b >= 16 && b <= 31) {
1572
- return true;
1573
- }
1574
- if (a === 192 && b === 168) {
1575
- return true;
1576
- }
1577
- return false;
1578
- }
1579
- function isBlockedHostname(hostname) {
1580
- const normalized = hostname.trim().toLowerCase();
1581
- if (normalized.length === 0) {
1582
- return true;
1583
- }
1584
- if (BLOCKED_HOSTNAMES.has(normalized)) {
1585
- return true;
1586
- }
1587
- if (normalized.endsWith(".local") || normalized.endsWith(".internal")) {
1588
- return true;
1589
- }
1590
- if (normalized.includes(":")) {
1591
- return true;
1592
- }
1593
- return isPrivateIpv4(normalized);
1594
- }
1595
- function assertSafeOutboundUrl(rawUrl, options = {}) {
1596
- let parsed;
1597
- try {
1598
- parsed = new URL(rawUrl);
1599
- } catch {
1600
- throw new BadRequestError("Webhook URL is invalid.");
1601
- }
1602
- if (parsed.protocol !== "https:" && !(options.allowHttp && parsed.protocol === "http:")) {
1603
- throw new BadRequestError("Webhook URL must use HTTPS.");
1604
- }
1605
- if (parsed.username || parsed.password) {
1606
- throw new BadRequestError("Webhook URL must not include credentials.");
1607
- }
1608
- if (isBlockedHostname(parsed.hostname)) {
1609
- throw new BadRequestError("Webhook URL targets a blocked host.");
1610
- }
1611
- return parsed;
1612
- }
1613
- function isBlockedIpAddress(address) {
1614
- return isBlockedHostname(address.trim().toLowerCase());
1615
- }
1616
- async function assertSafeOutboundUrlResolved(rawUrl, options = {}) {
1617
- const parsed = assertSafeOutboundUrl(rawUrl, options);
1618
- if (options.resolveDns === false) {
1619
- return parsed;
1620
- }
1621
- const hostname = parsed.hostname.trim().toLowerCase();
1622
- const results = await dnsLookup(hostname, { all: true, verbatim: true });
1623
- if (results.some((result) => isBlockedIpAddress(result.address))) {
1624
- throw new BadRequestError("Webhook URL targets a blocked host.");
1625
- }
1626
- return parsed;
1627
- }
1628
-
1629
- // ../../src/core/security/safeFetch.ts
1630
- var DEFAULT_FETCH_TIMEOUT_MS = 1e4;
1631
- async function safeFetch(input, init = {}, options = {}) {
1632
- const timeoutMs = options.timeoutMs ?? DEFAULT_FETCH_TIMEOUT_MS;
1633
- const maxRedirects = options.maxRedirects ?? 0;
1634
- const resolveDns = options.resolveDns ?? appConfig.env === "production";
1635
- const urlOptions = { allowHttp: options.allowHttp, resolveDns };
1636
- const controller = new AbortController;
1637
- const timeout = setTimeout(() => controller.abort(), timeoutMs);
1638
- try {
1639
- let currentUrl = (await assertSafeOutboundUrlResolved(input, urlOptions)).toString();
1640
- let redirectCount = 0;
1641
- while (true) {
1642
- const response = await fetch(currentUrl, {
1643
- ...init,
1644
- signal: controller.signal,
1645
- redirect: "manual"
1646
- });
1647
- if (response.status >= 300 && response.status < 400) {
1648
- const location = response.headers.get("location");
1649
- if (!location || redirectCount >= maxRedirects) {
1650
- return response;
1651
- }
1652
- currentUrl = (await assertSafeOutboundUrlResolved(new URL(location, currentUrl).toString(), urlOptions)).toString();
1653
- redirectCount += 1;
1654
- continue;
1655
- }
1656
- return response;
1657
- }
1658
- } finally {
1659
- clearTimeout(timeout);
1660
- }
1661
- }
1662
-
1663
- // ../../src/core/jobs/dispatchWebhookJob.ts
1664
- class DispatchWebhookJob extends Job {
1665
- maxAttempts = 3;
1666
- backoffMs = 2000;
1667
- async handle(payload) {
1668
- const rows = await repositoryConnection`
1669
- SELECT id, url, secret
1670
- FROM webhook
1671
- WHERE id = ${payload.webhookId} AND active = TRUE
1672
- LIMIT 1
1673
- `;
1674
- const webhook = rows[0];
1675
- if (!webhook) {
1676
- return;
1677
- }
1678
- const body = JSON.stringify({ event: payload.event, payload: payload.payload });
1679
- const signature = createHmac2("sha256", webhook.secret).update(body).digest("hex");
1680
- assertSafeOutboundUrl(webhook.url, { allowHttp: appConfig.env !== "production" });
1681
- let responseStatus = null;
1682
- let errorMessage = null;
1683
- try {
1684
- const response = await safeFetch(webhook.url, {
1685
- method: "POST",
1686
- headers: {
1687
- "content-type": "application/json",
1688
- "x-workhub-signature": signature
1689
- },
1690
- body
1691
- }, { allowHttp: appConfig.env !== "production" });
1692
- responseStatus = response.status;
1693
- if (!response.ok) {
1694
- throw new Error(`Webhook delivery failed with status ${response.status}.`);
1695
- }
1696
- } catch (error) {
1697
- errorMessage = error instanceof Error ? error.message : String(error);
1698
- await repositoryConnection`
1699
- INSERT INTO webhook_delivery (webhook_id, event, payload, response_status, error)
1700
- VALUES (
1701
- ${webhook.id},
1702
- ${payload.event},
1703
- ${JSON.stringify(payload.payload)}::jsonb,
1704
- ${responseStatus},
1705
- ${errorMessage}
1706
- )
1707
- `;
1708
- throw error instanceof Error ? error : new Error(errorMessage);
1709
- }
1710
- await repositoryConnection`
1711
- INSERT INTO webhook_delivery (webhook_id, event, payload, response_status)
1712
- VALUES (
1713
- ${webhook.id},
1714
- ${payload.event},
1715
- ${JSON.stringify(payload.payload)}::jsonb,
1716
- ${responseStatus}
1717
- )
1718
- `;
1719
- }
1720
- }
1721
- var dispatchWebhookJob_default = DispatchWebhookJob;
1722
-
1723
- // ../../src/core/queue/jobRegistry.ts
1724
- class JobRegistry {
1725
- constructor() {}
1726
- factories = new Map;
1727
- instances = new WeakMap;
1728
- register(name, factory) {
1729
- this.factories.set(name, factory);
1730
- }
1731
- resolveName(job) {
1732
- return this.instances.get(job);
1733
- }
1734
- track(name, job) {
1735
- this.instances.set(job, name);
1736
- return job;
1737
- }
1738
- create(name) {
1739
- const factory = this.factories.get(name);
1740
- if (!factory) {
1741
- return;
1742
- }
1743
- return factory();
1744
- }
1745
- names() {
1746
- return [...this.factories.keys()];
1747
- }
1748
- }
1749
- var jobRegistry = new JobRegistry;
1750
-
1751
1460
  // ../../src/core/pagination/index.ts
1752
1461
  function buildPaginationMeta(input) {
1753
1462
  const lastPage = Math.max(1, Math.ceil(input.total / input.perPage));
@@ -2287,6 +1996,29 @@ function indexMorphToRelation(children, parentsByType, relation) {
2287
1996
  return result;
2288
1997
  }
2289
1998
 
1999
+ // ../../src/core/database/boundConnection.ts
2000
+ var boundConnectionHolder = {
2001
+ connection: null
2002
+ };
2003
+ function getBoundDatabaseConnection() {
2004
+ return boundConnectionHolder.connection;
2005
+ }
2006
+
2007
+ // ../../src/core/database/repositoryConnection.ts
2008
+ function resolveRepositoryConnection() {
2009
+ return getBoundDatabaseConnection() ?? getDefaultDatabaseQuery();
2010
+ }
2011
+ var repositoryConnection = new Proxy(function repositoryConnection2() {}, {
2012
+ apply(_target, _thisArg, args) {
2013
+ return resolveRepositoryConnection()(...args);
2014
+ },
2015
+ get(_target, property) {
2016
+ const connection = resolveRepositoryConnection();
2017
+ const value = connection[property];
2018
+ return typeof value === "function" ? value.bind(connection) : value;
2019
+ }
2020
+ });
2021
+
2290
2022
  // ../../src/core/database/whereBuilder.ts
2291
2023
  class WhereBuilder {
2292
2024
  nodes = [];
@@ -3475,6 +3207,34 @@ class FailedJobService {
3475
3207
  }
3476
3208
  var failedJobService_default = FailedJobService;
3477
3209
 
3210
+ // ../../src/core/queue/jobRegistry.ts
3211
+ class JobRegistry {
3212
+ constructor() {}
3213
+ factories = new Map;
3214
+ instances = new WeakMap;
3215
+ register(name, factory) {
3216
+ this.factories.set(name, factory);
3217
+ }
3218
+ resolveName(job) {
3219
+ return this.instances.get(job);
3220
+ }
3221
+ track(name, job) {
3222
+ this.instances.set(job, name);
3223
+ return job;
3224
+ }
3225
+ create(name) {
3226
+ const factory = this.factories.get(name);
3227
+ if (!factory) {
3228
+ return;
3229
+ }
3230
+ return factory();
3231
+ }
3232
+ names() {
3233
+ return [...this.factories.keys()];
3234
+ }
3235
+ }
3236
+ var jobRegistry = new JobRegistry;
3237
+
3478
3238
  // ../../src/core/queue/jobRunner.ts
3479
3239
  async function runQueueJob(envelope, failedJobs) {
3480
3240
  const job = jobRegistry.create(envelope.name);
@@ -3589,19 +3349,211 @@ function createProductionQueue(driver, options = {}) {
3589
3349
  return new ResilientQueue(failedJobs, driver === "async");
3590
3350
  }
3591
3351
 
3592
- // ../../src/core/queue/createAppQueue.ts
3593
- var FAILED_JOB_SERVICE_TOKEN = "core.failedJobs";
3352
+ // ../../src/bootstrap/queue/defaultJobs.ts
3353
+ import { resolveApplicationCache } from "@getstrata/core";
3354
+
3355
+ // ../../src/core/jobs/dispatchWebhookJob.ts
3356
+ import { createHmac as createHmac2 } from "crypto";
3357
+
3358
+ // ../../src/core/security/safeUrl.ts
3359
+ import { lookup as dnsLookupImpl } from "dns/promises";
3360
+ var dnsLookup = dnsLookupImpl;
3361
+ var BLOCKED_HOSTNAMES = new Set([
3362
+ "localhost",
3363
+ "127.0.0.1",
3364
+ "0.0.0.0",
3365
+ "::1",
3366
+ "metadata.google.internal"
3367
+ ]);
3368
+ function isPrivateIpv4(hostname) {
3369
+ const match = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/.exec(hostname);
3370
+ if (!match) {
3371
+ return false;
3372
+ }
3373
+ const octets = match.slice(1, 5).map((part) => Number.parseInt(part, 10));
3374
+ if (octets.some((octet) => octet < 0 || octet > 255)) {
3375
+ return true;
3376
+ }
3377
+ const [a = 0, b = 0] = octets;
3378
+ if (a === 10) {
3379
+ return true;
3380
+ }
3381
+ if (a === 127) {
3382
+ return true;
3383
+ }
3384
+ if (a === 0) {
3385
+ return true;
3386
+ }
3387
+ if (a === 169 && b === 254) {
3388
+ return true;
3389
+ }
3390
+ if (a === 172 && b >= 16 && b <= 31) {
3391
+ return true;
3392
+ }
3393
+ if (a === 192 && b === 168) {
3394
+ return true;
3395
+ }
3396
+ return false;
3397
+ }
3398
+ function isBlockedHostname(hostname) {
3399
+ const normalized = hostname.trim().toLowerCase();
3400
+ if (normalized.length === 0) {
3401
+ return true;
3402
+ }
3403
+ if (BLOCKED_HOSTNAMES.has(normalized)) {
3404
+ return true;
3405
+ }
3406
+ if (normalized.endsWith(".local") || normalized.endsWith(".internal")) {
3407
+ return true;
3408
+ }
3409
+ if (normalized.includes(":")) {
3410
+ return true;
3411
+ }
3412
+ return isPrivateIpv4(normalized);
3413
+ }
3414
+ function assertSafeOutboundUrl(rawUrl, options = {}) {
3415
+ let parsed;
3416
+ try {
3417
+ parsed = new URL(rawUrl);
3418
+ } catch {
3419
+ throw new BadRequestError("Webhook URL is invalid.");
3420
+ }
3421
+ if (parsed.protocol !== "https:" && !(options.allowHttp && parsed.protocol === "http:")) {
3422
+ throw new BadRequestError("Webhook URL must use HTTPS.");
3423
+ }
3424
+ if (parsed.username || parsed.password) {
3425
+ throw new BadRequestError("Webhook URL must not include credentials.");
3426
+ }
3427
+ if (isBlockedHostname(parsed.hostname)) {
3428
+ throw new BadRequestError("Webhook URL targets a blocked host.");
3429
+ }
3430
+ return parsed;
3431
+ }
3432
+ function isBlockedIpAddress(address) {
3433
+ return isBlockedHostname(address.trim().toLowerCase());
3434
+ }
3435
+ async function assertSafeOutboundUrlResolved(rawUrl, options = {}) {
3436
+ const parsed = assertSafeOutboundUrl(rawUrl, options);
3437
+ if (options.resolveDns === false) {
3438
+ return parsed;
3439
+ }
3440
+ const hostname = parsed.hostname.trim().toLowerCase();
3441
+ const results = await dnsLookup(hostname, { all: true, verbatim: true });
3442
+ if (results.some((result) => isBlockedIpAddress(result.address))) {
3443
+ throw new BadRequestError("Webhook URL targets a blocked host.");
3444
+ }
3445
+ return parsed;
3446
+ }
3447
+
3448
+ // ../../src/core/security/safeFetch.ts
3449
+ var DEFAULT_FETCH_TIMEOUT_MS = 1e4;
3450
+ async function safeFetch(input, init = {}, options = {}) {
3451
+ const timeoutMs = options.timeoutMs ?? DEFAULT_FETCH_TIMEOUT_MS;
3452
+ const maxRedirects = options.maxRedirects ?? 0;
3453
+ const resolveDns = options.resolveDns ?? appConfig.env === "production";
3454
+ const urlOptions = { allowHttp: options.allowHttp, resolveDns };
3455
+ const controller = new AbortController;
3456
+ const timeout = setTimeout(() => controller.abort(), timeoutMs);
3457
+ try {
3458
+ let currentUrl = (await assertSafeOutboundUrlResolved(input, urlOptions)).toString();
3459
+ let redirectCount = 0;
3460
+ while (true) {
3461
+ const response = await fetch(currentUrl, {
3462
+ ...init,
3463
+ signal: controller.signal,
3464
+ redirect: "manual"
3465
+ });
3466
+ if (response.status >= 300 && response.status < 400) {
3467
+ const location = response.headers.get("location");
3468
+ if (!location || redirectCount >= maxRedirects) {
3469
+ return response;
3470
+ }
3471
+ currentUrl = (await assertSafeOutboundUrlResolved(new URL(location, currentUrl).toString(), urlOptions)).toString();
3472
+ redirectCount += 1;
3473
+ continue;
3474
+ }
3475
+ return response;
3476
+ }
3477
+ } finally {
3478
+ clearTimeout(timeout);
3479
+ }
3480
+ }
3481
+
3482
+ // ../../src/core/jobs/dispatchWebhookJob.ts
3483
+ class DispatchWebhookJob extends Job {
3484
+ maxAttempts = 3;
3485
+ backoffMs = 2000;
3486
+ async handle(payload) {
3487
+ const rows = await repositoryConnection`
3488
+ SELECT id, url, secret
3489
+ FROM webhook
3490
+ WHERE id = ${payload.webhookId} AND active = TRUE
3491
+ LIMIT 1
3492
+ `;
3493
+ const webhook = rows[0];
3494
+ if (!webhook) {
3495
+ return;
3496
+ }
3497
+ const body = JSON.stringify({ event: payload.event, payload: payload.payload });
3498
+ const signature = createHmac2("sha256", webhook.secret).update(body).digest("hex");
3499
+ assertSafeOutboundUrl(webhook.url, { allowHttp: appConfig.env !== "production" });
3500
+ let responseStatus = null;
3501
+ let errorMessage = null;
3502
+ try {
3503
+ const response = await safeFetch(webhook.url, {
3504
+ method: "POST",
3505
+ headers: {
3506
+ "content-type": "application/json",
3507
+ "x-workhub-signature": signature
3508
+ },
3509
+ body
3510
+ }, { allowHttp: appConfig.env !== "production" });
3511
+ responseStatus = response.status;
3512
+ if (!response.ok) {
3513
+ throw new Error(`Webhook delivery failed with status ${response.status}.`);
3514
+ }
3515
+ } catch (error) {
3516
+ errorMessage = error instanceof Error ? error.message : String(error);
3517
+ await repositoryConnection`
3518
+ INSERT INTO webhook_delivery (webhook_id, event, payload, response_status, error)
3519
+ VALUES (
3520
+ ${webhook.id},
3521
+ ${payload.event},
3522
+ ${JSON.stringify(payload.payload)}::jsonb,
3523
+ ${responseStatus},
3524
+ ${errorMessage}
3525
+ )
3526
+ `;
3527
+ throw error instanceof Error ? error : new Error(errorMessage);
3528
+ }
3529
+ await repositoryConnection`
3530
+ INSERT INTO webhook_delivery (webhook_id, event, payload, response_status)
3531
+ VALUES (
3532
+ ${webhook.id},
3533
+ ${payload.event},
3534
+ ${JSON.stringify(payload.payload)}::jsonb,
3535
+ ${responseStatus}
3536
+ )
3537
+ `;
3538
+ }
3539
+ }
3540
+ var dispatchWebhookJob_default = DispatchWebhookJob;
3541
+
3542
+ // ../../src/bootstrap/queue/defaultJobs.ts
3594
3543
  function registerDefaultJobs() {
3595
3544
  jobRegistry.register("cache.invalidate-tags", () => {
3596
3545
  return new invalidateCacheTagsJob_default(resolveApplicationCache());
3597
3546
  });
3598
3547
  jobRegistry.register("webhook.dispatch", () => new dispatchWebhookJob_default);
3599
3548
  }
3600
- function createAppQueue(driver, redisUrl, failedJobs = createFailedJobService()) {
3549
+
3550
+ // ../../src/core/queue/createAppQueue.ts
3551
+ var FAILED_JOB_SERVICE_TOKEN = "core.failedJobs";
3552
+ function createAppQueue(driver, redisUrl, failedJobs = createFailedJobService(), registerJobs) {
3601
3553
  return createProductionQueue(driver, {
3602
3554
  redisUrl,
3603
3555
  failedJobs,
3604
- registerJobs: registerDefaultJobs
3556
+ registerJobs
3605
3557
  });
3606
3558
  }
3607
3559
 
@@ -3618,7 +3570,7 @@ function registerInvalidateCacheOnModelWriteListeners(bus = eventBus) {
3618
3570
  let cache;
3619
3571
  let queue;
3620
3572
  try {
3621
- cache = resolveApplicationCache();
3573
+ cache = resolveApplicationCache2();
3622
3574
  queue = resolveApplicationQueue();
3623
3575
  } catch {
3624
3576
  return;
@@ -3709,7 +3661,7 @@ var queueProvider = {
3709
3661
  config.set("queue.driver", driver);
3710
3662
  const failedJobs = createFailedJobService();
3711
3663
  container.set(FAILED_JOB_SERVICE_TOKEN, failedJobs);
3712
- container.set(CORE_QUEUE_TOKEN, createAppQueue(driver, config.get(REDIS_URL_CONFIG_KEY) ?? process.env.REDIS_URL, failedJobs));
3664
+ container.set(CORE_QUEUE_TOKEN, createAppQueue(driver, config.get(REDIS_URL_CONFIG_KEY) ?? process.env.REDIS_URL, failedJobs, registerDefaultJobs));
3713
3665
  }
3714
3666
  };
3715
3667
  var queue_default = queueProvider;
@@ -3852,8 +3804,7 @@ function isViewsEnabled() {
3852
3804
  }
3853
3805
 
3854
3806
  // ../../src/core/http/requestMetaContext.ts
3855
- import { AsyncLocalStorage as AsyncLocalStorage3 } from "async_hooks";
3856
- var requestMetaContext = new AsyncLocalStorage3;
3807
+ var requestMetaContext = createAsyncContextStore("@getstrata/requestMetaContext");
3857
3808
  function currentRequestMeta() {
3858
3809
  return requestMetaContext.getStore() ?? {
3859
3810
  ipAddress: null,
@@ -4186,7 +4137,7 @@ function createAppContext() {
4186
4137
  config,
4187
4138
  dependencies
4188
4139
  };
4189
- setActiveApplicationContext2(appContext);
4140
+ setActiveApplicationContext(appContext);
4190
4141
  return appContext;
4191
4142
  }
4192
4143
  var cachedAppContext;