@getstrata/bootstrap 1.1.1 → 1.1.2

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 CHANGED
@@ -1,5 +1,14 @@
1
1
  # @getstrata/bootstrap changelog
2
2
 
3
+ ## 1.1.2
4
+
5
+ - Product CLI helpers, file migrations, and job discovery.
6
+
7
+ ## Unreleased
8
+
9
+ - `discoverJobs()` loads `src/jobs/*.ts` default exports with `static jobName` into `jobRegistry`, same cache pattern as `discoverListeners()`.
10
+ - Queue providers register default jobs and discovered jobs together.
11
+
3
12
  ## 1.1.1
4
13
 
5
14
  Fix generated app boot
@@ -0,0 +1,8 @@
1
+ import type { Job } from "@getstrata/core/queue";
2
+ type DiscoveredJobClass = (new () => Job) & {
3
+ jobName: string;
4
+ };
5
+ declare function discoverJobs(): string[];
6
+ declare function resetDiscoverJobsForTests(): void;
7
+ export type { DiscoveredJobClass };
8
+ export { discoverJobs, resetDiscoverJobsForTests };
@@ -16,6 +16,7 @@ export { assertAppDependenciesComplete, getRequiredDependency, resolveService, S
16
16
  export type { CreateWebRoutesOptions } from "./createWebRoutes.ts";
17
17
  export { createWebRoutes, mergeWebRoutes } from "./createWebRoutes.ts";
18
18
  export { createAppDependencies } from "./dependencies.ts";
19
+ export { discoverJobs, resetDiscoverJobsForTests } from "./discoverJobs.ts";
19
20
  export type { DiscoverModulesOptions } from "./discoverModules.ts";
20
21
  export { configureModulesDirectory, discoverModules, ensureModulesLoaded, } from "./discoverModules.ts";
21
22
  export type { CreateHealthRoutesOptions } from "./health.ts";
@@ -499,16 +499,81 @@ import {
499
499
  FAILED_JOB_SERVICE_TOKEN
500
500
  } from "@getstrata/core/queue/createAppQueue";
501
501
 
502
+ // ../../src/bootstrap/discoverJobs.ts
503
+ import { existsSync as existsSync2, readdirSync as readdirSync3 } from "fs";
504
+ import { createRequire as createRequire2 } from "module";
505
+ import { join as join3 } from "path";
506
+ import { jobRegistry } from "@getstrata/core/queue/jobRegistry";
507
+ var requireJob = createRequire2(import.meta.url);
508
+ var DISCOVER_JOBS_STATE_KEY = Symbol.for("@getstrata/discoverJobsState");
509
+ function readDiscoverJobsState() {
510
+ const existing = globalThis[DISCOVER_JOBS_STATE_KEY];
511
+ if (existing) {
512
+ return existing;
513
+ }
514
+ const state = {};
515
+ globalThis[DISCOVER_JOBS_STATE_KEY] = state;
516
+ return state;
517
+ }
518
+ function resolveJobsDirectory() {
519
+ const fromCwd = join3(process.cwd(), "src", "jobs");
520
+ if (existsSync2(fromCwd)) {
521
+ return fromCwd;
522
+ }
523
+ return join3(import.meta.dir, "../jobs");
524
+ }
525
+ function isDiscoveredJobClass(value) {
526
+ if (typeof value !== "function") {
527
+ return false;
528
+ }
529
+ const jobName = value.jobName;
530
+ return typeof jobName === "string" && jobName.length > 0;
531
+ }
532
+ function loadDiscoveredJobClasses() {
533
+ const jobsDirectory = resolveJobsDirectory();
534
+ let entries;
535
+ try {
536
+ entries = readdirSync3(jobsDirectory, { withFileTypes: true }).filter((entry) => entry.isFile() && /\.(ts|js)$/.test(entry.name)).map((entry) => entry.name);
537
+ } catch (error) {
538
+ if (error instanceof Error && "code" in error && error.code === "ENOENT") {
539
+ return [];
540
+ }
541
+ throw error;
542
+ }
543
+ return entries.flatMap((fileName) => {
544
+ const filePath = join3(jobsDirectory, fileName);
545
+ const loaded = requireJob(filePath);
546
+ return isDiscoveredJobClass(loaded.default) ? [loaded.default] : [];
547
+ });
548
+ }
549
+ function discoverJobs() {
550
+ const state = readDiscoverJobsState();
551
+ if (state.names) {
552
+ return state.names;
553
+ }
554
+ const names = [];
555
+ for (const JobClass of loadDiscoveredJobClasses()) {
556
+ jobRegistry.register(JobClass.jobName, () => new JobClass);
557
+ names.push(JobClass.jobName);
558
+ }
559
+ state.names = names;
560
+ return names;
561
+ }
562
+ function resetDiscoverJobsForTests() {
563
+ const state = readDiscoverJobsState();
564
+ state.names = undefined;
565
+ }
566
+
502
567
  // ../../src/bootstrap/queue/defaultJobs.ts
503
568
  import { ExportAuditLogsJob } from "@getstrata/core/jobs/exportAuditLogsJob";
504
569
  import { InvalidateCacheTagsJob as InvalidateCacheTagsJob2 } from "@getstrata/core/jobs/invalidateCacheTagsJob";
505
- import { jobRegistry } from "@getstrata/core/queue/jobRegistry";
570
+ import { jobRegistry as jobRegistry2 } from "@getstrata/core/queue/jobRegistry";
506
571
  import { resolveApplicationCache as resolveApplicationCache2 } from "@getstrata/core/runtime/applicationRegistry";
507
572
  function registerDefaultJobs() {
508
- jobRegistry.register("cache.invalidate-tags", () => {
573
+ jobRegistry2.register("cache.invalidate-tags", () => {
509
574
  return new InvalidateCacheTagsJob2(resolveApplicationCache2());
510
575
  });
511
- jobRegistry.register("audit.export", () => new ExportAuditLogsJob);
576
+ jobRegistry2.register("audit.export", () => new ExportAuditLogsJob);
512
577
  }
513
578
 
514
579
  // ../../src/bootstrap/providers/queue.ts
@@ -520,7 +585,10 @@ var queueProvider = {
520
585
  config.set("queue.driver", driver);
521
586
  const failedJobs = createFailedJobService();
522
587
  container.set(FAILED_JOB_SERVICE_TOKEN, failedJobs);
523
- container.set(CORE_QUEUE_TOKEN, createAppQueue(driver, config.get(REDIS_URL_CONFIG_KEY) ?? process.env.REDIS_URL, failedJobs, registerDefaultJobs));
588
+ container.set(CORE_QUEUE_TOKEN, createAppQueue(driver, config.get(REDIS_URL_CONFIG_KEY) ?? process.env.REDIS_URL, failedJobs, () => {
589
+ registerDefaultJobs();
590
+ discoverJobs();
591
+ }));
524
592
  }
525
593
  };
526
594
  var queue_default = queueProvider;
@@ -499,16 +499,81 @@ import {
499
499
  FAILED_JOB_SERVICE_TOKEN
500
500
  } from "@getstrata/core/queue/createAppQueue";
501
501
 
502
+ // ../../src/bootstrap/discoverJobs.ts
503
+ import { existsSync as existsSync2, readdirSync as readdirSync3 } from "fs";
504
+ import { createRequire as createRequire2 } from "module";
505
+ import { join as join3 } from "path";
506
+ import { jobRegistry } from "@getstrata/core/queue/jobRegistry";
507
+ var requireJob = createRequire2(import.meta.url);
508
+ var DISCOVER_JOBS_STATE_KEY = Symbol.for("@getstrata/discoverJobsState");
509
+ function readDiscoverJobsState() {
510
+ const existing = globalThis[DISCOVER_JOBS_STATE_KEY];
511
+ if (existing) {
512
+ return existing;
513
+ }
514
+ const state = {};
515
+ globalThis[DISCOVER_JOBS_STATE_KEY] = state;
516
+ return state;
517
+ }
518
+ function resolveJobsDirectory() {
519
+ const fromCwd = join3(process.cwd(), "src", "jobs");
520
+ if (existsSync2(fromCwd)) {
521
+ return fromCwd;
522
+ }
523
+ return join3(import.meta.dir, "../jobs");
524
+ }
525
+ function isDiscoveredJobClass(value) {
526
+ if (typeof value !== "function") {
527
+ return false;
528
+ }
529
+ const jobName = value.jobName;
530
+ return typeof jobName === "string" && jobName.length > 0;
531
+ }
532
+ function loadDiscoveredJobClasses() {
533
+ const jobsDirectory = resolveJobsDirectory();
534
+ let entries;
535
+ try {
536
+ entries = readdirSync3(jobsDirectory, { withFileTypes: true }).filter((entry) => entry.isFile() && /\.(ts|js)$/.test(entry.name)).map((entry) => entry.name);
537
+ } catch (error) {
538
+ if (error instanceof Error && "code" in error && error.code === "ENOENT") {
539
+ return [];
540
+ }
541
+ throw error;
542
+ }
543
+ return entries.flatMap((fileName) => {
544
+ const filePath = join3(jobsDirectory, fileName);
545
+ const loaded = requireJob(filePath);
546
+ return isDiscoveredJobClass(loaded.default) ? [loaded.default] : [];
547
+ });
548
+ }
549
+ function discoverJobs() {
550
+ const state = readDiscoverJobsState();
551
+ if (state.names) {
552
+ return state.names;
553
+ }
554
+ const names = [];
555
+ for (const JobClass of loadDiscoveredJobClasses()) {
556
+ jobRegistry.register(JobClass.jobName, () => new JobClass);
557
+ names.push(JobClass.jobName);
558
+ }
559
+ state.names = names;
560
+ return names;
561
+ }
562
+ function resetDiscoverJobsForTests() {
563
+ const state = readDiscoverJobsState();
564
+ state.names = undefined;
565
+ }
566
+
502
567
  // ../../src/bootstrap/queue/defaultJobs.ts
503
568
  import { ExportAuditLogsJob } from "@getstrata/core/jobs/exportAuditLogsJob";
504
569
  import { InvalidateCacheTagsJob as InvalidateCacheTagsJob2 } from "@getstrata/core/jobs/invalidateCacheTagsJob";
505
- import { jobRegistry } from "@getstrata/core/queue/jobRegistry";
570
+ import { jobRegistry as jobRegistry2 } from "@getstrata/core/queue/jobRegistry";
506
571
  import { resolveApplicationCache as resolveApplicationCache2 } from "@getstrata/core/runtime/applicationRegistry";
507
572
  function registerDefaultJobs() {
508
- jobRegistry.register("cache.invalidate-tags", () => {
573
+ jobRegistry2.register("cache.invalidate-tags", () => {
509
574
  return new InvalidateCacheTagsJob2(resolveApplicationCache2());
510
575
  });
511
- jobRegistry.register("audit.export", () => new ExportAuditLogsJob);
576
+ jobRegistry2.register("audit.export", () => new ExportAuditLogsJob);
512
577
  }
513
578
 
514
579
  // ../../src/bootstrap/providers/queue.ts
@@ -520,7 +585,10 @@ var queueProvider = {
520
585
  config.set("queue.driver", driver);
521
586
  const failedJobs = createFailedJobService();
522
587
  container.set(FAILED_JOB_SERVICE_TOKEN, failedJobs);
523
- container.set(CORE_QUEUE_TOKEN, createAppQueue(driver, config.get(REDIS_URL_CONFIG_KEY) ?? process.env.REDIS_URL, failedJobs, registerDefaultJobs));
588
+ container.set(CORE_QUEUE_TOKEN, createAppQueue(driver, config.get(REDIS_URL_CONFIG_KEY) ?? process.env.REDIS_URL, failedJobs, () => {
589
+ registerDefaultJobs();
590
+ discoverJobs();
591
+ }));
524
592
  }
525
593
  };
526
594
  var queue_default = queueProvider;
@@ -0,0 +1,69 @@
1
+ // @bun
2
+ // ../../src/bootstrap/discoverJobs.ts
3
+ import { existsSync, readdirSync } from "fs";
4
+ import { createRequire } from "module";
5
+ import { join } from "path";
6
+ import { jobRegistry } from "@getstrata/core/queue/jobRegistry";
7
+ var requireJob = createRequire(import.meta.url);
8
+ var DISCOVER_JOBS_STATE_KEY = Symbol.for("@getstrata/discoverJobsState");
9
+ function readDiscoverJobsState() {
10
+ const existing = globalThis[DISCOVER_JOBS_STATE_KEY];
11
+ if (existing) {
12
+ return existing;
13
+ }
14
+ const state = {};
15
+ globalThis[DISCOVER_JOBS_STATE_KEY] = state;
16
+ return state;
17
+ }
18
+ function resolveJobsDirectory() {
19
+ const fromCwd = join(process.cwd(), "src", "jobs");
20
+ if (existsSync(fromCwd)) {
21
+ return fromCwd;
22
+ }
23
+ return join(import.meta.dir, "../jobs");
24
+ }
25
+ function isDiscoveredJobClass(value) {
26
+ if (typeof value !== "function") {
27
+ return false;
28
+ }
29
+ const jobName = value.jobName;
30
+ return typeof jobName === "string" && jobName.length > 0;
31
+ }
32
+ function loadDiscoveredJobClasses() {
33
+ const jobsDirectory = resolveJobsDirectory();
34
+ let entries;
35
+ try {
36
+ entries = readdirSync(jobsDirectory, { withFileTypes: true }).filter((entry) => entry.isFile() && /\.(ts|js)$/.test(entry.name)).map((entry) => entry.name);
37
+ } catch (error) {
38
+ if (error instanceof Error && "code" in error && error.code === "ENOENT") {
39
+ return [];
40
+ }
41
+ throw error;
42
+ }
43
+ return entries.flatMap((fileName) => {
44
+ const filePath = join(jobsDirectory, fileName);
45
+ const loaded = requireJob(filePath);
46
+ return isDiscoveredJobClass(loaded.default) ? [loaded.default] : [];
47
+ });
48
+ }
49
+ function discoverJobs() {
50
+ const state = readDiscoverJobsState();
51
+ if (state.names) {
52
+ return state.names;
53
+ }
54
+ const names = [];
55
+ for (const JobClass of loadDiscoveredJobClasses()) {
56
+ jobRegistry.register(JobClass.jobName, () => new JobClass);
57
+ names.push(JobClass.jobName);
58
+ }
59
+ state.names = names;
60
+ return names;
61
+ }
62
+ function resetDiscoverJobsForTests() {
63
+ const state = readDiscoverJobsState();
64
+ state.names = undefined;
65
+ }
66
+ export {
67
+ discoverJobs,
68
+ resetDiscoverJobsForTests
69
+ };
@@ -489,16 +489,81 @@ import {
489
489
  FAILED_JOB_SERVICE_TOKEN
490
490
  } from "@getstrata/core/queue/createAppQueue";
491
491
 
492
+ // ../../src/bootstrap/discoverJobs.ts
493
+ import { existsSync as existsSync2, readdirSync as readdirSync3 } from "fs";
494
+ import { createRequire as createRequire2 } from "module";
495
+ import { join as join3 } from "path";
496
+ import { jobRegistry } from "@getstrata/core/queue/jobRegistry";
497
+ var requireJob = createRequire2(import.meta.url);
498
+ var DISCOVER_JOBS_STATE_KEY = Symbol.for("@getstrata/discoverJobsState");
499
+ function readDiscoverJobsState() {
500
+ const existing = globalThis[DISCOVER_JOBS_STATE_KEY];
501
+ if (existing) {
502
+ return existing;
503
+ }
504
+ const state = {};
505
+ globalThis[DISCOVER_JOBS_STATE_KEY] = state;
506
+ return state;
507
+ }
508
+ function resolveJobsDirectory() {
509
+ const fromCwd = join3(process.cwd(), "src", "jobs");
510
+ if (existsSync2(fromCwd)) {
511
+ return fromCwd;
512
+ }
513
+ return join3(import.meta.dir, "../jobs");
514
+ }
515
+ function isDiscoveredJobClass(value) {
516
+ if (typeof value !== "function") {
517
+ return false;
518
+ }
519
+ const jobName = value.jobName;
520
+ return typeof jobName === "string" && jobName.length > 0;
521
+ }
522
+ function loadDiscoveredJobClasses() {
523
+ const jobsDirectory = resolveJobsDirectory();
524
+ let entries;
525
+ try {
526
+ entries = readdirSync3(jobsDirectory, { withFileTypes: true }).filter((entry) => entry.isFile() && /\.(ts|js)$/.test(entry.name)).map((entry) => entry.name);
527
+ } catch (error) {
528
+ if (error instanceof Error && "code" in error && error.code === "ENOENT") {
529
+ return [];
530
+ }
531
+ throw error;
532
+ }
533
+ return entries.flatMap((fileName) => {
534
+ const filePath = join3(jobsDirectory, fileName);
535
+ const loaded = requireJob(filePath);
536
+ return isDiscoveredJobClass(loaded.default) ? [loaded.default] : [];
537
+ });
538
+ }
539
+ function discoverJobs() {
540
+ const state = readDiscoverJobsState();
541
+ if (state.names) {
542
+ return state.names;
543
+ }
544
+ const names = [];
545
+ for (const JobClass of loadDiscoveredJobClasses()) {
546
+ jobRegistry.register(JobClass.jobName, () => new JobClass);
547
+ names.push(JobClass.jobName);
548
+ }
549
+ state.names = names;
550
+ return names;
551
+ }
552
+ function resetDiscoverJobsForTests() {
553
+ const state = readDiscoverJobsState();
554
+ state.names = undefined;
555
+ }
556
+
492
557
  // ../../src/bootstrap/queue/defaultJobs.ts
493
558
  import { ExportAuditLogsJob } from "@getstrata/core/jobs/exportAuditLogsJob";
494
559
  import { InvalidateCacheTagsJob as InvalidateCacheTagsJob2 } from "@getstrata/core/jobs/invalidateCacheTagsJob";
495
- import { jobRegistry } from "@getstrata/core/queue/jobRegistry";
560
+ import { jobRegistry as jobRegistry2 } from "@getstrata/core/queue/jobRegistry";
496
561
  import { resolveApplicationCache as resolveApplicationCache2 } from "@getstrata/core/runtime/applicationRegistry";
497
562
  function registerDefaultJobs() {
498
- jobRegistry.register("cache.invalidate-tags", () => {
563
+ jobRegistry2.register("cache.invalidate-tags", () => {
499
564
  return new InvalidateCacheTagsJob2(resolveApplicationCache2());
500
565
  });
501
- jobRegistry.register("audit.export", () => new ExportAuditLogsJob);
566
+ jobRegistry2.register("audit.export", () => new ExportAuditLogsJob);
502
567
  }
503
568
 
504
569
  // ../../src/bootstrap/providers/queue.ts
@@ -510,7 +575,10 @@ var queueProvider = {
510
575
  config.set("queue.driver", driver);
511
576
  const failedJobs = createFailedJobService();
512
577
  container.set(FAILED_JOB_SERVICE_TOKEN, failedJobs);
513
- container.set(CORE_QUEUE_TOKEN, createAppQueue(driver, config.get(REDIS_URL_CONFIG_KEY) ?? process.env.REDIS_URL, failedJobs, registerDefaultJobs));
578
+ container.set(CORE_QUEUE_TOKEN, createAppQueue(driver, config.get(REDIS_URL_CONFIG_KEY) ?? process.env.REDIS_URL, failedJobs, () => {
579
+ registerDefaultJobs();
580
+ discoverJobs();
581
+ }));
514
582
  }
515
583
  };
516
584
  var queue_default = queueProvider;
package/dist/index.js CHANGED
@@ -884,16 +884,81 @@ import {
884
884
  FAILED_JOB_SERVICE_TOKEN
885
885
  } from "@getstrata/core/queue/createAppQueue";
886
886
 
887
+ // ../../src/bootstrap/discoverJobs.ts
888
+ import { existsSync as existsSync2, readdirSync as readdirSync3 } from "fs";
889
+ import { createRequire as createRequire2 } from "module";
890
+ import { join as join3 } from "path";
891
+ import { jobRegistry } from "@getstrata/core/queue/jobRegistry";
892
+ var requireJob = createRequire2(import.meta.url);
893
+ var DISCOVER_JOBS_STATE_KEY = Symbol.for("@getstrata/discoverJobsState");
894
+ function readDiscoverJobsState() {
895
+ const existing = globalThis[DISCOVER_JOBS_STATE_KEY];
896
+ if (existing) {
897
+ return existing;
898
+ }
899
+ const state = {};
900
+ globalThis[DISCOVER_JOBS_STATE_KEY] = state;
901
+ return state;
902
+ }
903
+ function resolveJobsDirectory() {
904
+ const fromCwd = join3(process.cwd(), "src", "jobs");
905
+ if (existsSync2(fromCwd)) {
906
+ return fromCwd;
907
+ }
908
+ return join3(import.meta.dir, "../jobs");
909
+ }
910
+ function isDiscoveredJobClass(value) {
911
+ if (typeof value !== "function") {
912
+ return false;
913
+ }
914
+ const jobName = value.jobName;
915
+ return typeof jobName === "string" && jobName.length > 0;
916
+ }
917
+ function loadDiscoveredJobClasses() {
918
+ const jobsDirectory = resolveJobsDirectory();
919
+ let entries;
920
+ try {
921
+ entries = readdirSync3(jobsDirectory, { withFileTypes: true }).filter((entry) => entry.isFile() && /\.(ts|js)$/.test(entry.name)).map((entry) => entry.name);
922
+ } catch (error) {
923
+ if (error instanceof Error && "code" in error && error.code === "ENOENT") {
924
+ return [];
925
+ }
926
+ throw error;
927
+ }
928
+ return entries.flatMap((fileName) => {
929
+ const filePath = join3(jobsDirectory, fileName);
930
+ const loaded = requireJob(filePath);
931
+ return isDiscoveredJobClass(loaded.default) ? [loaded.default] : [];
932
+ });
933
+ }
934
+ function discoverJobs() {
935
+ const state = readDiscoverJobsState();
936
+ if (state.names) {
937
+ return state.names;
938
+ }
939
+ const names = [];
940
+ for (const JobClass of loadDiscoveredJobClasses()) {
941
+ jobRegistry.register(JobClass.jobName, () => new JobClass);
942
+ names.push(JobClass.jobName);
943
+ }
944
+ state.names = names;
945
+ return names;
946
+ }
947
+ function resetDiscoverJobsForTests() {
948
+ const state = readDiscoverJobsState();
949
+ state.names = undefined;
950
+ }
951
+
887
952
  // ../../src/bootstrap/queue/defaultJobs.ts
888
953
  import { ExportAuditLogsJob } from "@getstrata/core/jobs/exportAuditLogsJob";
889
954
  import { InvalidateCacheTagsJob as InvalidateCacheTagsJob2 } from "@getstrata/core/jobs/invalidateCacheTagsJob";
890
- import { jobRegistry } from "@getstrata/core/queue/jobRegistry";
955
+ import { jobRegistry as jobRegistry2 } from "@getstrata/core/queue/jobRegistry";
891
956
  import { resolveApplicationCache as resolveApplicationCache2 } from "@getstrata/core/runtime/applicationRegistry";
892
957
  function registerDefaultJobs() {
893
- jobRegistry.register("cache.invalidate-tags", () => {
958
+ jobRegistry2.register("cache.invalidate-tags", () => {
894
959
  return new InvalidateCacheTagsJob2(resolveApplicationCache2());
895
960
  });
896
- jobRegistry.register("audit.export", () => new ExportAuditLogsJob);
961
+ jobRegistry2.register("audit.export", () => new ExportAuditLogsJob);
897
962
  }
898
963
 
899
964
  // ../../src/bootstrap/providers/queue.ts
@@ -905,7 +970,10 @@ var queueProvider = {
905
970
  config.set("queue.driver", driver);
906
971
  const failedJobs = createFailedJobService();
907
972
  container.set(FAILED_JOB_SERVICE_TOKEN, failedJobs);
908
- container.set(CORE_QUEUE_TOKEN, createAppQueue(driver, config.get(REDIS_URL_CONFIG_KEY) ?? process.env.REDIS_URL, failedJobs, registerDefaultJobs));
973
+ container.set(CORE_QUEUE_TOKEN, createAppQueue(driver, config.get(REDIS_URL_CONFIG_KEY) ?? process.env.REDIS_URL, failedJobs, () => {
974
+ registerDefaultJobs();
975
+ discoverJobs();
976
+ }));
909
977
  }
910
978
  };
911
979
  var queue_default = queueProvider;
@@ -1007,7 +1075,7 @@ function createAppContext() {
1007
1075
  return appContext;
1008
1076
  }
1009
1077
  // ../../src/bootstrap/createWebRoutes.ts
1010
- import { join as join3 } from "path";
1078
+ import { join as join4 } from "path";
1011
1079
  import { isViewsEnabled as isViewsEnabled3 } from "@getstrata/core/runtime/frontendMode";
1012
1080
  import { assertUrlPathUnderRoot } from "@getstrata/core/security/safePath";
1013
1081
  import { notFoundHtmlResponse } from "@getstrata/core/view";
@@ -1024,7 +1092,7 @@ function createWebRoutes(dependencies, options = {}) {
1024
1092
  registerRoute("GET", "/assets/*", ["global", "web"]);
1025
1093
  const pathname = new URL(request.url).pathname;
1026
1094
  try {
1027
- const filePath = assertUrlPathUnderRoot(join3(process.cwd(), "public"), pathname);
1095
+ const filePath = assertUrlPathUnderRoot(join4(process.cwd(), "public"), pathname);
1028
1096
  const file = Bun.file(filePath);
1029
1097
  if (!await file.exists()) {
1030
1098
  return notFoundHtmlResponse();
@@ -1811,6 +1879,7 @@ export {
1811
1879
  createRouteKernel,
1812
1880
  createWebRoutes,
1813
1881
  createWebServer,
1882
+ discoverJobs,
1814
1883
  discoverModelTableNames,
1815
1884
  discoverModules,
1816
1885
  ensureModulesLoaded,
@@ -1820,6 +1889,7 @@ export {
1820
1889
  pingDatabase,
1821
1890
  prefixRouteMap,
1822
1891
  registerDefaultJobs,
1892
+ resetDiscoverJobsForTests,
1823
1893
  resolveApplicationAuth,
1824
1894
  resolveApplicationCache,
1825
1895
  resolveApplicationConfig,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@getstrata/bootstrap",
3
- "version": "1.1.1",
3
+ "version": "1.1.2",
4
4
  "description": "Strata application bootstrap: HttpKernel, DI, web session helpers",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -75,6 +75,11 @@
75
75
  "import": "./dist/entries/discoverListeners.js",
76
76
  "default": "./dist/entries/discoverListeners.js"
77
77
  },
78
+ "./discoverJobs": {
79
+ "types": "./dist/bootstrap/discoverJobs.d.ts",
80
+ "import": "./dist/entries/discoverJobs.js",
81
+ "default": "./dist/entries/discoverJobs.js"
82
+ },
78
83
  "./health": {
79
84
  "types": "./dist/bootstrap/health.d.ts",
80
85
  "import": "./dist/entries/health.js",
@@ -173,14 +178,14 @@
173
178
  "build:bundle": "bun build index.ts --outdir dist --target bun --external bun --external eta --external mysql2 --external @getstrata/core",
174
179
  "build:types": "tsc -p tsconfig.types.json && bun ../../scripts/prune-bootstrap-dist-types.ts",
175
180
  "prepublishOnly": "bun run build",
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/createSpaRoutes.ts entries/dependencies.ts entries/discoverModules.ts entries/discoverListeners.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 mysql2 --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/createSpaRoutes --external @getstrata/bootstrap/dependencies --external @getstrata/bootstrap/discoverModules --external @getstrata/bootstrap/discoverListeners --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/emailVerification --external @getstrata/core/auth/guard --external @getstrata/core/auth/jwt --external @getstrata/core/auth/jwtGuard --external @getstrata/core/auth/basicAuthGuard --external @getstrata/core/auth/tokenAbilityChecker --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/saml/samlServiceProvider --external @getstrata/core/auth/password --external @getstrata/core/auth/passwordLogin --external @getstrata/core/auth/oneTimeToken --external @getstrata/core/auth/intendedUrlCookie --external @getstrata/core/auth/passwordConfirmCookie --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/authUserDirectory --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/connectionContext --external @getstrata/core/database/defaultConnection --external @getstrata/core/database/dialect --external @getstrata/core/database/mysqlConnection --external @getstrata/core/database/namedConnections --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/sqliteConnection --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/contentSecurityPolicy --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/requireVerifiedMiddleware --external @getstrata/core/http/requirePasswordConfirmMiddleware --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/safeInternalPath --external @getstrata/core/http/signedUrl --external @getstrata/core/http/statelessAuth --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/exportAuditLogsJob --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/mail/sanitizeMailHtml --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/appEnv --external @getstrata/core/runtime/appKeyPrefix --external @getstrata/core/runtime/frontendMode --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/recoveryCodes --external @getstrata/core/security/safeFetch --external @getstrata/core/security/safePath --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/tenant/enableTenantRls --external @getstrata/core/terminal/runShell --external @getstrata/core/tracing/traceContext --external @getstrata/core/tracing/tracingMiddleware --external @getstrata/core/validation/rules --external @getstrata/core/view",
181
+ "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/createSpaRoutes.ts entries/dependencies.ts entries/discoverModules.ts entries/discoverListeners.ts entries/discoverJobs.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 mysql2 --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/createSpaRoutes --external @getstrata/bootstrap/dependencies --external @getstrata/bootstrap/discoverModules --external @getstrata/bootstrap/discoverListeners --external @getstrata/bootstrap/discoverJobs --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/emailVerification --external @getstrata/core/auth/guard --external @getstrata/core/auth/jwt --external @getstrata/core/auth/jwtGuard --external @getstrata/core/auth/basicAuthGuard --external @getstrata/core/auth/tokenAbilityChecker --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/saml/samlServiceProvider --external @getstrata/core/auth/password --external @getstrata/core/auth/passwordLogin --external @getstrata/core/auth/oneTimeToken --external @getstrata/core/auth/intendedUrlCookie --external @getstrata/core/auth/passwordConfirmCookie --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/authUserDirectory --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/connectionContext --external @getstrata/core/database/defaultConnection --external @getstrata/core/database/dialect --external @getstrata/core/database/mysqlConnection --external @getstrata/core/database/namedConnections --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/sqliteConnection --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/contentSecurityPolicy --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/requireVerifiedMiddleware --external @getstrata/core/http/requirePasswordConfirmMiddleware --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/safeInternalPath --external @getstrata/core/http/signedUrl --external @getstrata/core/http/statelessAuth --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/exportAuditLogsJob --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/mail/sanitizeMailHtml --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/appEnv --external @getstrata/core/runtime/appKeyPrefix --external @getstrata/core/runtime/frontendMode --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/recoveryCodes --external @getstrata/core/security/safeFetch --external @getstrata/core/security/safePath --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/tenant/enableTenantRls --external @getstrata/core/terminal/runShell --external @getstrata/core/tracing/traceContext --external @getstrata/core/tracing/tracingMiddleware --external @getstrata/core/validation/rules --external @getstrata/core/view",
177
182
  "build:shims": "true"
178
183
  },
179
184
  "publishConfig": {
180
185
  "access": "public"
181
186
  },
182
187
  "peerDependencies": {
183
- "@getstrata/core": "^1.1.1",
188
+ "@getstrata/core": "^1.1.2",
184
189
  "typescript": "^5.9.0"
185
190
  },
186
191
  "engines": {