@getstrata/bootstrap 0.2.9 → 0.2.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/dist/bootstrap/cache/modelCacheTags.d.ts +3 -0
  2. package/dist/bootstrap/discoverModules.d.ts +3 -2
  3. package/dist/bootstrap/modules.d.ts +1 -1
  4. package/dist/bootstrap/preloadModules.d.ts +1 -0
  5. package/dist/bootstrap/public-api.d.ts +1 -0
  6. package/dist/bootstrap/routeRegistry.d.ts +1 -5
  7. package/dist/bootstrap/server.d.ts +1 -1
  8. package/dist/core/auth/authContext.d.ts +1 -2
  9. package/dist/core/auth/guard.d.ts +2 -2
  10. package/dist/core/auth/membershipContext.d.ts +1 -2
  11. package/dist/core/auth/sessionGuard.d.ts +2 -2
  12. package/dist/core/cache/modelCacheTags.d.ts +1 -3
  13. package/dist/core/contracts/serviceContainer.d.ts +5 -0
  14. package/dist/core/http/requestMetaContext.d.ts +1 -2
  15. package/dist/core/openapi/registeredRoute.d.ts +6 -0
  16. package/dist/core/runtime/asyncContextStore.d.ts +3 -0
  17. package/dist/core/tenant/tenantContext.d.ts +1 -2
  18. package/dist/core/tracing/traceContext.d.ts +1 -2
  19. package/dist/core/view/webLayoutData.d.ts +2 -2
  20. package/dist/entries/applicationRegistry.js +15 -2
  21. package/dist/entries/cache/modelCacheTags.js +22 -0
  22. package/dist/entries/context.js +150 -147
  23. package/dist/entries/createWebRoutes.js +22 -29
  24. package/dist/entries/http/securedRouteModelBinding.js +31 -6
  25. package/dist/entries/membershipService.js +32 -10
  26. package/dist/entries/providers/view.js +17 -6
  27. package/dist/entries/providers.js +59 -52
  28. package/dist/entries/queue/defaultJobs.js +30 -4
  29. package/dist/framework/public-api.d.ts +1 -0
  30. package/dist/index.js +69 -68
  31. package/package.json +8 -3
package/dist/index.js CHANGED
@@ -70,9 +70,22 @@ function getBoundDatabaseConnection() {
70
70
  return boundConnectionHolder.connection;
71
71
  }
72
72
 
73
- // ../../src/core/database/connectionContext.ts
73
+ // ../../src/core/runtime/asyncContextStore.ts
74
74
  import { AsyncLocalStorage } from "async_hooks";
75
- var activeConnection = new AsyncLocalStorage;
75
+ function createAsyncContextStore(key) {
76
+ const symbol = Symbol.for(key);
77
+ const globalRecord = globalThis;
78
+ const existing = globalRecord[symbol];
79
+ if (existing) {
80
+ return existing;
81
+ }
82
+ const store = new AsyncLocalStorage;
83
+ globalRecord[symbol] = store;
84
+ return store;
85
+ }
86
+
87
+ // ../../src/core/database/connectionContext.ts
88
+ var activeConnection = createAsyncContextStore("@getstrata/databaseConnectionContext");
76
89
  function getActiveDatabaseConnection(fallback) {
77
90
  return activeConnection.getStore() ?? fallback;
78
91
  }
@@ -596,15 +609,28 @@ function resolveService(dependencies, token) {
596
609
  }
597
610
 
598
611
  // ../../src/bootstrap/applicationRegistry.ts
612
+ var APPLICATION_CONTEXT_KEY = Symbol.for("@getstrata/applicationContext");
599
613
  var activeContext;
614
+ function readStoredApplicationContext() {
615
+ if (activeContext) {
616
+ return activeContext;
617
+ }
618
+ const globalContext = globalThis[APPLICATION_CONTEXT_KEY];
619
+ if (globalContext) {
620
+ activeContext = globalContext;
621
+ }
622
+ return activeContext;
623
+ }
600
624
  function setActiveApplicationContext(context) {
601
625
  activeContext = context;
626
+ globalThis[APPLICATION_CONTEXT_KEY] = context;
602
627
  }
603
628
  function requireActiveApplicationContext() {
604
- if (!activeContext) {
629
+ const context = readStoredApplicationContext();
630
+ if (!context) {
605
631
  throw new Error("The application context has not been bootstrapped.");
606
632
  }
607
- return activeContext;
633
+ return context;
608
634
  }
609
635
  function resolveApplicationCache() {
610
636
  return getRequiredDependency(requireActiveApplicationContext().dependencies, "cache");
@@ -627,32 +653,23 @@ function resolveApplicationLogger() {
627
653
  function resolveApplicationDependencies() {
628
654
  return requireActiveApplicationContext().dependencies;
629
655
  }
630
- // ../../src/bootstrap/context.ts
631
- import { setActiveApplicationContext as setActiveApplicationContext2 } from "@getstrata/core";
632
-
633
656
  // ../../src/bootstrap/discoverModules.ts
634
- import { readdirSync } from "fs";
635
- import { join } from "path";
636
- import { pathToFileURL } from "url";
637
- async function loadDiscoveredModules() {
638
- const modulesDirectory = join(import.meta.dir, "../modules");
639
- let moduleNames;
640
- try {
641
- moduleNames = readdirSync(modulesDirectory, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
642
- } catch (error) {
643
- if (error.code === "ENOENT") {
644
- return [];
645
- }
646
- throw error;
647
- }
648
- const modules = await Promise.all(moduleNames.map(async (moduleName) => {
649
- const moduleUrl = pathToFileURL(join(modulesDirectory, moduleName, "index.ts")).href;
650
- const loaded = await import(moduleUrl);
651
- return loaded.default;
652
- }));
653
- return modules.filter((module) => module?.name !== undefined).sort((left, right) => (left.order ?? 100) - (right.order ?? 100));
657
+ var appModules = [];
658
+ function discoverModules() {
659
+ return appModules;
660
+ }
661
+
662
+ // ../../src/bootstrap/cache/modelCacheTags.ts
663
+ function cacheTagsForModelWrite(tableName, action) {
664
+ const module = discoverModules().find((entry) => entry.tableName === tableName);
665
+ const baseTags = module?.cacheTags ?? [`${tableName}s`];
666
+ const isDelete = action === "deleted" || action === "force-deleted";
667
+ const extraTags = isDelete ? module?.cacheDeleteExtraTags ?? [] : [];
668
+ return [...new Set([...baseTags, ...extraTags])];
669
+ }
670
+ function discoverModelTableNames() {
671
+ return discoverModules().map((module) => module.tableName).filter((tableName) => tableName !== undefined);
654
672
  }
655
- var appModules = await loadDiscoveredModules();
656
673
  // ../../src/config/auth.ts
657
674
  var authConfig = {
658
675
  allowDevHeaders: (process.env.AUTH_DEV_HEADERS ?? "true") !== "false",
@@ -942,8 +959,7 @@ import { resolveDefaultTokenExpiryDays as resolveDefaultTokenExpiryDays2 } from
942
959
  var tokenServiceToken = CORE_TOKEN_SERVICE_TOKEN;
943
960
 
944
961
  // ../../src/core/auth/authContext.ts
945
- import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
946
- var authContext = new AsyncLocalStorage2;
962
+ var authContext = createAsyncContextStore("@getstrata/authContext");
947
963
  function currentAuthUser() {
948
964
  return authContext.getStore() ?? null;
949
965
  }
@@ -1782,14 +1798,14 @@ var eventsProvider = {
1782
1798
  var events_default = eventsProvider;
1783
1799
 
1784
1800
  // ../../src/bootstrap/discoverListeners.ts
1785
- import { readdirSync as readdirSync2 } from "fs";
1786
- import { join as join2 } from "path";
1787
- import { pathToFileURL as pathToFileURL2 } from "url";
1801
+ import { readdirSync } from "fs";
1802
+ import { join } from "path";
1803
+ import { pathToFileURL } from "url";
1788
1804
  async function loadDiscoveredListeners() {
1789
- const listenersDirectory = join2(import.meta.dir, "../listeners");
1805
+ const listenersDirectory = join(import.meta.dir, "../listeners");
1790
1806
  let entries;
1791
1807
  try {
1792
- entries = readdirSync2(listenersDirectory, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".ts")).map((entry) => entry.name);
1808
+ entries = readdirSync(listenersDirectory, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".ts")).map((entry) => entry.name);
1793
1809
  } catch (error) {
1794
1810
  if (error instanceof Error && "code" in error && error.code === "ENOENT") {
1795
1811
  return [];
@@ -1797,7 +1813,7 @@ async function loadDiscoveredListeners() {
1797
1813
  throw error;
1798
1814
  }
1799
1815
  const listeners = await Promise.all(entries.map(async (fileName) => {
1800
- const moduleUrl = pathToFileURL2(join2(listenersDirectory, fileName)).href;
1816
+ const moduleUrl = pathToFileURL(join(listenersDirectory, fileName)).href;
1801
1817
  const loaded = await import(moduleUrl);
1802
1818
  return loaded.default;
1803
1819
  }));
@@ -1808,18 +1824,6 @@ function discoverListeners() {
1808
1824
  return appListeners;
1809
1825
  }
1810
1826
 
1811
- // ../../src/core/cache/modelCacheTags.ts
1812
- function cacheTagsForModelWrite(tableName, action) {
1813
- const module = appModules.find((entry) => entry.tableName === tableName);
1814
- const baseTags = module?.cacheTags ?? [`${tableName}s`];
1815
- const isDelete = action === "deleted" || action === "force-deleted";
1816
- const extraTags = isDelete ? module?.cacheDeleteExtraTags ?? [] : [];
1817
- return [...new Set([...baseTags, ...extraTags])];
1818
- }
1819
- function discoverModelTableNames() {
1820
- return appModules.map((module) => module.tableName).filter((tableName) => tableName !== undefined);
1821
- }
1822
-
1823
1827
  // ../../src/core/queue/index.ts
1824
1828
  class Job {
1825
1829
  maxAttempts;
@@ -2130,10 +2134,10 @@ function buildHavingClause(tableName, having, params) {
2130
2134
  return body.length > 0 ? ` HAVING ${body}` : "";
2131
2135
  }
2132
2136
  function buildJoinClause(joins = []) {
2133
- return joins.map((join3) => {
2134
- const joinType = join3.type === "left" ? "LEFT JOIN" : "INNER JOIN";
2135
- const onClause = join3.on.map(({ left, right }) => `${qualifyColumn(left.table, left.column)} = ${qualifyColumn(right.table, right.column)}`).join(" AND ");
2136
- return ` ${joinType} ${quoteIdentifier(join3.table)} ON ${onClause}`;
2137
+ return joins.map((join2) => {
2138
+ const joinType = join2.type === "left" ? "LEFT JOIN" : "INNER JOIN";
2139
+ const onClause = join2.on.map(({ left, right }) => `${qualifyColumn(left.table, left.column)} = ${qualifyColumn(right.table, right.column)}`).join(" AND ");
2140
+ return ` ${joinType} ${quoteIdentifier(join2.table)} ON ${onClause}`;
2137
2141
  }).join("");
2138
2142
  }
2139
2143
  function buildLimitClause(limit) {
@@ -2546,7 +2550,7 @@ class RepositoryQuery {
2546
2550
  const rightRef = parseQualifiedColumn(right);
2547
2551
  const table = type === "inner" ? rightRef.table : rightRef.table;
2548
2552
  const joins = this.queryOptions.joins ?? [];
2549
- const existing = joins.find((join3) => join3.table === table && join3.type === type);
2553
+ const existing = joins.find((join2) => join2.table === table && join2.type === type);
2550
2554
  if (existing) {
2551
2555
  existing.on.push({ left: leftRef, right: rightRef });
2552
2556
  return this;
@@ -3899,7 +3903,7 @@ var queue_default = queueProvider;
3899
3903
 
3900
3904
  // ../../src/core/storage/storage.ts
3901
3905
  import { mkdir, readFile, unlink, writeFile } from "fs/promises";
3902
- import { dirname, join as join3 } from "path";
3906
+ import { dirname, join as join2 } from "path";
3903
3907
  var {S3Client } = globalThis.Bun;
3904
3908
 
3905
3909
  class LocalStorageDriver {
@@ -3911,7 +3915,7 @@ class LocalStorageDriver {
3911
3915
  return this.rootDirectory ?? process.env.STORAGE_PATH ?? "storage";
3912
3916
  }
3913
3917
  resolvePath(path) {
3914
- return join3(this.resolveRootDirectory(), path.replace(/^\/+/, ""));
3918
+ return join2(this.resolveRootDirectory(), path.replace(/^\/+/, ""));
3915
3919
  }
3916
3920
  async put(path, contents) {
3917
3921
  const absolutePath = this.resolvePath(path);
@@ -4035,8 +4039,7 @@ function isViewsEnabled() {
4035
4039
  }
4036
4040
 
4037
4041
  // ../../src/core/http/requestMetaContext.ts
4038
- import { AsyncLocalStorage as AsyncLocalStorage3 } from "async_hooks";
4039
- var requestMetaContext = new AsyncLocalStorage3;
4042
+ var requestMetaContext = createAsyncContextStore("@getstrata/requestMetaContext");
4040
4043
  function currentRequestMeta() {
4041
4044
  return requestMetaContext.getStore() ?? {
4042
4045
  ipAddress: null,
@@ -4045,9 +4048,9 @@ function currentRequestMeta() {
4045
4048
  }
4046
4049
 
4047
4050
  // ../../src/core/view/etaViewEngine.ts
4048
- import { join as join4 } from "path";
4051
+ import { join as join3 } from "path";
4049
4052
  import { Eta } from "eta";
4050
- var DEFAULT_VIEWS_DIRECTORY = join4(process.cwd(), "resources/views");
4053
+ var DEFAULT_VIEWS_DIRECTORY = join3(process.cwd(), "resources/views");
4051
4054
  var DEFAULT_LAYOUT = "layouts/app.eta";
4052
4055
 
4053
4056
  class EtaViewEngine {
@@ -4369,11 +4372,11 @@ function createAppContext() {
4369
4372
  config,
4370
4373
  dependencies
4371
4374
  };
4372
- setActiveApplicationContext2(appContext);
4375
+ setActiveApplicationContext(appContext);
4373
4376
  return appContext;
4374
4377
  }
4375
4378
  // ../../src/bootstrap/createWebRoutes.ts
4376
- import { join as join5 } from "path";
4379
+ import { join as join4 } from "path";
4377
4380
 
4378
4381
  // ../../src/core/http/middleware.ts
4379
4382
  function isRouteHandler(value) {
@@ -4707,7 +4710,7 @@ function createWebRoutes(dependencies) {
4707
4710
  registerRoute("GET", "/assets/*", ["global", "web"]);
4708
4711
  const pathname = new URL(request.url).pathname;
4709
4712
  const relativePath = pathname.replace(/^\//, "");
4710
- const file = Bun.file(join5(process.cwd(), "public", relativePath));
4713
+ const file = Bun.file(join4(process.cwd(), "public", relativePath));
4711
4714
  if (!await file.exists()) {
4712
4715
  return htmlResponse("Not Found", { status: 404 });
4713
4716
  }
@@ -4817,8 +4820,7 @@ function applyConditionalGet(request, response, etag) {
4817
4820
  }
4818
4821
 
4819
4822
  // ../../src/core/tenant/tenantContext.ts
4820
- import { AsyncLocalStorage as AsyncLocalStorage4 } from "async_hooks";
4821
- var tenantContext = new AsyncLocalStorage4;
4823
+ var tenantContext = createAsyncContextStore("@getstrata/tenantContext");
4822
4824
 
4823
4825
  // ../../src/core/http/validation.ts
4824
4826
  function parsePositiveIntParam(value, name = "id") {
@@ -4899,9 +4901,6 @@ function resolveUserId(user) {
4899
4901
  return userId;
4900
4902
  }
4901
4903
 
4902
- // ../../src/core/auth/membershipContext.ts
4903
- import { AsyncLocalStorage as AsyncLocalStorage5 } from "async_hooks";
4904
-
4905
4904
  // ../../src/modules/organization/memberRepository.ts
4906
4905
  class OrganizationMemberRepository {
4907
4906
  constructor() {}
@@ -4954,7 +4953,7 @@ class OrganizationMemberRepository {
4954
4953
  var memberRepository_default = OrganizationMemberRepository;
4955
4954
 
4956
4955
  // ../../src/core/auth/membershipContext.ts
4957
- var membershipContext = new AsyncLocalStorage5;
4956
+ var membershipContext = createAsyncContextStore("@getstrata/membershipContext");
4958
4957
  var membershipRepository = new memberRepository_default;
4959
4958
 
4960
4959
  // ../../src/core/auth/membershipService.ts
@@ -5275,6 +5274,7 @@ export {
5275
5274
  parseFormBody,
5276
5275
  mergeWebRoutes,
5277
5276
  getRequiredDependency,
5277
+ discoverModelTableNames,
5278
5278
  createWebServer,
5279
5279
  createWebRoutes,
5280
5280
  createRouteKernel,
@@ -5283,6 +5283,7 @@ export {
5283
5283
  createAppContext,
5284
5284
  coreProviders,
5285
5285
  collectProviders,
5286
+ cacheTagsForModelWrite,
5286
5287
  assertAppDependenciesComplete,
5287
5288
  appSchedule,
5288
5289
  ServiceContainer,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@getstrata/bootstrap",
3
- "version": "0.2.9",
3
+ "version": "0.2.12",
4
4
  "description": "Strata application bootstrap — HttpKernel, DI, web session helpers",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -15,6 +15,11 @@
15
15
  "import": "./dist/index.js",
16
16
  "default": "./dist/index.js"
17
17
  },
18
+ "./cache/modelCacheTags": {
19
+ "types": "./dist/bootstrap/cache/modelCacheTags.d.ts",
20
+ "import": "./dist/entries/cache/modelCacheTags.js",
21
+ "default": "./dist/entries/cache/modelCacheTags.js"
22
+ },
18
23
  "./applicationRegistry": {
19
24
  "types": "./dist/bootstrap/applicationRegistry.d.ts",
20
25
  "import": "./dist/entries/applicationRegistry.js",
@@ -82,14 +87,14 @@
82
87
  "build:bundle": "bun build index.ts --outdir dist --target bun --external bun --external eta --external @getstrata/core",
83
88
  "build:types": "tsc -p tsconfig.types.json",
84
89
  "prepublishOnly": "bun run build",
85
- "build:subpaths": "bun build entries/applicationRegistry.ts entries/config.ts entries/context.ts entries/contracts.ts entries/createWebRoutes.ts entries/http/securedRouteModelBinding.ts entries/httpKernel.ts entries/membershipService.ts entries/queue/defaultJobs.ts entries/providers.ts entries/providers/view.ts --outdir dist --root . --target bun --external bun --external eta --external @getstrata/core",
90
+ "build:subpaths": "bun build entries/applicationRegistry.ts entries/cache/modelCacheTags.ts entries/config.ts entries/context.ts entries/contracts.ts entries/createWebRoutes.ts entries/http/securedRouteModelBinding.ts entries/httpKernel.ts entries/membershipService.ts entries/queue/defaultJobs.ts entries/providers.ts entries/providers/view.ts --outdir dist --root . --target bun --external bun --external eta --external @getstrata/core",
86
91
  "build:shims": "true"
87
92
  },
88
93
  "publishConfig": {
89
94
  "access": "public"
90
95
  },
91
96
  "peerDependencies": {
92
- "@getstrata/core": "^0.5.17",
97
+ "@getstrata/core": "^0.5.20",
93
98
  "typescript": "^5.9.0"
94
99
  }
95
100
  }