@mantajs/cli 0.2.0-beta.0

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 (282) hide show
  1. package/bin/manta.mjs +20 -0
  2. package/bin/manta.ts +13 -0
  3. package/dist/admin/generate-admin-config.d.ts +8 -0
  4. package/dist/admin/generate-admin-config.d.ts.map +1 -0
  5. package/dist/admin/generate-admin-config.js +127 -0
  6. package/dist/admin/generate-admin-config.js.map +1 -0
  7. package/dist/ai/chat-handler.d.ts +10 -0
  8. package/dist/ai/chat-handler.d.ts.map +1 -0
  9. package/dist/ai/chat-handler.js +1353 -0
  10. package/dist/ai/chat-handler.js.map +1 -0
  11. package/dist/bootstrap/boot.d.ts +25 -0
  12. package/dist/bootstrap/boot.d.ts.map +1 -0
  13. package/dist/bootstrap/boot.js +344 -0
  14. package/dist/bootstrap/boot.js.map +1 -0
  15. package/dist/bootstrap/bootstrap-app.d.ts +71 -0
  16. package/dist/bootstrap/bootstrap-app.d.ts.map +1 -0
  17. package/dist/bootstrap/bootstrap-app.js +308 -0
  18. package/dist/bootstrap/bootstrap-app.js.map +1 -0
  19. package/dist/bootstrap/bootstrap-context.d.ts +76 -0
  20. package/dist/bootstrap/bootstrap-context.d.ts.map +1 -0
  21. package/dist/bootstrap/bootstrap-context.js +4 -0
  22. package/dist/bootstrap/bootstrap-context.js.map +1 -0
  23. package/dist/bootstrap/bootstrap-helpers.d.ts +71 -0
  24. package/dist/bootstrap/bootstrap-helpers.d.ts.map +1 -0
  25. package/dist/bootstrap/bootstrap-helpers.js +373 -0
  26. package/dist/bootstrap/bootstrap-helpers.js.map +1 -0
  27. package/dist/bootstrap/generate-types.d.ts +7 -0
  28. package/dist/bootstrap/generate-types.d.ts.map +1 -0
  29. package/dist/bootstrap/generate-types.js +832 -0
  30. package/dist/bootstrap/generate-types.js.map +1 -0
  31. package/dist/bootstrap/phases/assemble/index.d.ts +5 -0
  32. package/dist/bootstrap/phases/assemble/index.d.ts.map +1 -0
  33. package/dist/bootstrap/phases/assemble/index.js +5 -0
  34. package/dist/bootstrap/phases/assemble/index.js.map +1 -0
  35. package/dist/bootstrap/phases/assemble/load-links.d.ts +3 -0
  36. package/dist/bootstrap/phases/assemble/load-links.d.ts.map +1 -0
  37. package/dist/bootstrap/phases/assemble/load-links.js +160 -0
  38. package/dist/bootstrap/phases/assemble/load-links.js.map +1 -0
  39. package/dist/bootstrap/phases/assemble/load-modules.d.ts +3 -0
  40. package/dist/bootstrap/phases/assemble/load-modules.d.ts.map +1 -0
  41. package/dist/bootstrap/phases/assemble/load-modules.js +163 -0
  42. package/dist/bootstrap/phases/assemble/load-modules.js.map +1 -0
  43. package/dist/bootstrap/phases/assemble/load-resources.d.ts +3 -0
  44. package/dist/bootstrap/phases/assemble/load-resources.d.ts.map +1 -0
  45. package/dist/bootstrap/phases/assemble/load-resources.js +270 -0
  46. package/dist/bootstrap/phases/assemble/load-resources.js.map +1 -0
  47. package/dist/bootstrap/phases/assemble/wire-commands.d.ts +3 -0
  48. package/dist/bootstrap/phases/assemble/wire-commands.d.ts.map +1 -0
  49. package/dist/bootstrap/phases/assemble/wire-commands.js +408 -0
  50. package/dist/bootstrap/phases/assemble/wire-commands.js.map +1 -0
  51. package/dist/bootstrap/phases/assemble-modules.d.ts +3 -0
  52. package/dist/bootstrap/phases/assemble-modules.d.ts.map +1 -0
  53. package/dist/bootstrap/phases/assemble-modules.js +14 -0
  54. package/dist/bootstrap/phases/assemble-modules.js.map +1 -0
  55. package/dist/bootstrap/phases/build-app.d.ts +3 -0
  56. package/dist/bootstrap/phases/build-app.d.ts.map +1 -0
  57. package/dist/bootstrap/phases/build-app.js +15 -0
  58. package/dist/bootstrap/phases/build-app.js.map +1 -0
  59. package/dist/bootstrap/phases/discover-resources.d.ts +3 -0
  60. package/dist/bootstrap/phases/discover-resources.d.ts.map +1 -0
  61. package/dist/bootstrap/phases/discover-resources.js +60 -0
  62. package/dist/bootstrap/phases/discover-resources.js.map +1 -0
  63. package/dist/bootstrap/phases/index.d.ts +7 -0
  64. package/dist/bootstrap/phases/index.d.ts.map +1 -0
  65. package/dist/bootstrap/phases/index.js +7 -0
  66. package/dist/bootstrap/phases/index.js.map +1 -0
  67. package/dist/bootstrap/phases/init-infra.d.ts +3 -0
  68. package/dist/bootstrap/phases/init-infra.d.ts.map +1 -0
  69. package/dist/bootstrap/phases/init-infra.js +193 -0
  70. package/dist/bootstrap/phases/init-infra.js.map +1 -0
  71. package/dist/bootstrap/phases/seed-dev-users.d.ts +3 -0
  72. package/dist/bootstrap/phases/seed-dev-users.d.ts.map +1 -0
  73. package/dist/bootstrap/phases/seed-dev-users.js +93 -0
  74. package/dist/bootstrap/phases/seed-dev-users.js.map +1 -0
  75. package/dist/bootstrap/phases/wire/auth-helpers.d.ts +12 -0
  76. package/dist/bootstrap/phases/wire/auth-helpers.d.ts.map +1 -0
  77. package/dist/bootstrap/phases/wire/auth-helpers.js +25 -0
  78. package/dist/bootstrap/phases/wire/auth-helpers.js.map +1 -0
  79. package/dist/bootstrap/phases/wire/contexts/context-registry.d.ts +4 -0
  80. package/dist/bootstrap/phases/wire/contexts/context-registry.d.ts.map +1 -0
  81. package/dist/bootstrap/phases/wire/contexts/context-registry.js +96 -0
  82. package/dist/bootstrap/phases/wire/contexts/context-registry.js.map +1 -0
  83. package/dist/bootstrap/phases/wire/contexts/cqrs-routes.d.ts +3 -0
  84. package/dist/bootstrap/phases/wire/contexts/cqrs-routes.d.ts.map +1 -0
  85. package/dist/bootstrap/phases/wire/contexts/cqrs-routes.js +138 -0
  86. package/dist/bootstrap/phases/wire/contexts/cqrs-routes.js.map +1 -0
  87. package/dist/bootstrap/phases/wire/contexts/index.d.ts +6 -0
  88. package/dist/bootstrap/phases/wire/contexts/index.d.ts.map +1 -0
  89. package/dist/bootstrap/phases/wire/contexts/index.js +6 -0
  90. package/dist/bootstrap/phases/wire/contexts/index.js.map +1 -0
  91. package/dist/bootstrap/phases/wire/contexts/query-endpoints.d.ts +3 -0
  92. package/dist/bootstrap/phases/wire/contexts/query-endpoints.d.ts.map +1 -0
  93. package/dist/bootstrap/phases/wire/contexts/query-endpoints.js +116 -0
  94. package/dist/bootstrap/phases/wire/contexts/query-endpoints.js.map +1 -0
  95. package/dist/bootstrap/phases/wire/contexts/spa-warnings.d.ts +3 -0
  96. package/dist/bootstrap/phases/wire/contexts/spa-warnings.d.ts.map +1 -0
  97. package/dist/bootstrap/phases/wire/contexts/spa-warnings.js +17 -0
  98. package/dist/bootstrap/phases/wire/contexts/spa-warnings.js.map +1 -0
  99. package/dist/bootstrap/phases/wire/contexts/user-routes.d.ts +3 -0
  100. package/dist/bootstrap/phases/wire/contexts/user-routes.d.ts.map +1 -0
  101. package/dist/bootstrap/phases/wire/contexts/user-routes.js +83 -0
  102. package/dist/bootstrap/phases/wire/contexts/user-routes.js.map +1 -0
  103. package/dist/bootstrap/phases/wire/index.d.ts +5 -0
  104. package/dist/bootstrap/phases/wire/index.d.ts.map +1 -0
  105. package/dist/bootstrap/phases/wire/index.js +5 -0
  106. package/dist/bootstrap/phases/wire/index.js.map +1 -0
  107. package/dist/bootstrap/phases/wire/wire-adapter.d.ts +12 -0
  108. package/dist/bootstrap/phases/wire/wire-adapter.d.ts.map +1 -0
  109. package/dist/bootstrap/phases/wire/wire-adapter.js +156 -0
  110. package/dist/bootstrap/phases/wire/wire-adapter.js.map +1 -0
  111. package/dist/bootstrap/phases/wire/wire-auth.d.ts +3 -0
  112. package/dist/bootstrap/phases/wire/wire-auth.d.ts.map +1 -0
  113. package/dist/bootstrap/phases/wire/wire-auth.js +46 -0
  114. package/dist/bootstrap/phases/wire/wire-auth.js.map +1 -0
  115. package/dist/bootstrap/phases/wire/wire-contexts.d.ts +3 -0
  116. package/dist/bootstrap/phases/wire/wire-contexts.d.ts.map +1 -0
  117. package/dist/bootstrap/phases/wire/wire-contexts.js +15 -0
  118. package/dist/bootstrap/phases/wire/wire-contexts.js.map +1 -0
  119. package/dist/bootstrap/phases/wire/wire-cron-routes.d.ts +3 -0
  120. package/dist/bootstrap/phases/wire/wire-cron-routes.d.ts.map +1 -0
  121. package/dist/bootstrap/phases/wire/wire-cron-routes.js +102 -0
  122. package/dist/bootstrap/phases/wire/wire-cron-routes.js.map +1 -0
  123. package/dist/bootstrap/phases/wire/wire-extras.d.ts +3 -0
  124. package/dist/bootstrap/phases/wire/wire-extras.d.ts.map +1 -0
  125. package/dist/bootstrap/phases/wire/wire-extras.js +305 -0
  126. package/dist/bootstrap/phases/wire/wire-extras.js.map +1 -0
  127. package/dist/bootstrap/phases/wire/wire-workflow-routes.d.ts +3 -0
  128. package/dist/bootstrap/phases/wire/wire-workflow-routes.d.ts.map +1 -0
  129. package/dist/bootstrap/phases/wire/wire-workflow-routes.js +212 -0
  130. package/dist/bootstrap/phases/wire/wire-workflow-routes.js.map +1 -0
  131. package/dist/bootstrap/phases/wire-http.d.ts +3 -0
  132. package/dist/bootstrap/phases/wire-http.d.ts.map +1 -0
  133. package/dist/bootstrap/phases/wire-http.js +10 -0
  134. package/dist/bootstrap/phases/wire-http.js.map +1 -0
  135. package/dist/bootstrap/validate-generated-ts.d.ts +6 -0
  136. package/dist/bootstrap/validate-generated-ts.d.ts.map +1 -0
  137. package/dist/bootstrap/validate-generated-ts.js +26 -0
  138. package/dist/bootstrap/validate-generated-ts.js.map +1 -0
  139. package/dist/build/generate-manifest.d.ts +10 -0
  140. package/dist/build/generate-manifest.d.ts.map +1 -0
  141. package/dist/build/generate-manifest.js +138 -0
  142. package/dist/build/generate-manifest.js.map +1 -0
  143. package/dist/cli.d.ts +3 -0
  144. package/dist/cli.d.ts.map +1 -0
  145. package/dist/cli.js +421 -0
  146. package/dist/cli.js.map +1 -0
  147. package/dist/commands/build.d.ts +21 -0
  148. package/dist/commands/build.d.ts.map +1 -0
  149. package/dist/commands/build.js +399 -0
  150. package/dist/commands/build.js.map +1 -0
  151. package/dist/commands/db/create.d.ts +17 -0
  152. package/dist/commands/db/create.d.ts.map +1 -0
  153. package/dist/commands/db/create.js +94 -0
  154. package/dist/commands/db/create.js.map +1 -0
  155. package/dist/commands/db/diff.d.ts +39 -0
  156. package/dist/commands/db/diff.d.ts.map +1 -0
  157. package/dist/commands/db/diff.js +81 -0
  158. package/dist/commands/db/diff.js.map +1 -0
  159. package/dist/commands/db/generate.d.ts +58 -0
  160. package/dist/commands/db/generate.d.ts.map +1 -0
  161. package/dist/commands/db/generate.js +138 -0
  162. package/dist/commands/db/generate.js.map +1 -0
  163. package/dist/commands/db/migrate.d.ts +29 -0
  164. package/dist/commands/db/migrate.d.ts.map +1 -0
  165. package/dist/commands/db/migrate.js +118 -0
  166. package/dist/commands/db/migrate.js.map +1 -0
  167. package/dist/commands/db/pg-deps.d.ts +30 -0
  168. package/dist/commands/db/pg-deps.d.ts.map +1 -0
  169. package/dist/commands/db/pg-deps.js +178 -0
  170. package/dist/commands/db/pg-deps.js.map +1 -0
  171. package/dist/commands/db/rollback.d.ts +21 -0
  172. package/dist/commands/db/rollback.d.ts.map +1 -0
  173. package/dist/commands/db/rollback.js +85 -0
  174. package/dist/commands/db/rollback.js.map +1 -0
  175. package/dist/commands/db/types.d.ts +113 -0
  176. package/dist/commands/db/types.d.ts.map +1 -0
  177. package/dist/commands/db/types.js +4 -0
  178. package/dist/commands/db/types.js.map +1 -0
  179. package/dist/commands/dev.d.ts +12 -0
  180. package/dist/commands/dev.d.ts.map +1 -0
  181. package/dist/commands/dev.js +79 -0
  182. package/dist/commands/dev.js.map +1 -0
  183. package/dist/commands/exec.d.ts +21 -0
  184. package/dist/commands/exec.d.ts.map +1 -0
  185. package/dist/commands/exec.js +148 -0
  186. package/dist/commands/exec.js.map +1 -0
  187. package/dist/commands/generate.d.ts +11 -0
  188. package/dist/commands/generate.d.ts.map +1 -0
  189. package/dist/commands/generate.js +19 -0
  190. package/dist/commands/generate.js.map +1 -0
  191. package/dist/commands/init.d.ts +14 -0
  192. package/dist/commands/init.d.ts.map +1 -0
  193. package/dist/commands/init.js +476 -0
  194. package/dist/commands/init.js.map +1 -0
  195. package/dist/commands/start.d.ts +15 -0
  196. package/dist/commands/start.d.ts.map +1 -0
  197. package/dist/commands/start.js +121 -0
  198. package/dist/commands/start.js.map +1 -0
  199. package/dist/commands/user.d.ts +19 -0
  200. package/dist/commands/user.d.ts.map +1 -0
  201. package/dist/commands/user.js +125 -0
  202. package/dist/commands/user.js.map +1 -0
  203. package/dist/config/load-config.d.ts +23 -0
  204. package/dist/config/load-config.d.ts.map +1 -0
  205. package/dist/config/load-config.js +105 -0
  206. package/dist/config/load-config.js.map +1 -0
  207. package/dist/config/load-env.d.ts +11 -0
  208. package/dist/config/load-env.d.ts.map +1 -0
  209. package/dist/config/load-env.js +61 -0
  210. package/dist/config/load-env.js.map +1 -0
  211. package/dist/config/resolve-adapters.d.ts +23 -0
  212. package/dist/config/resolve-adapters.d.ts.map +1 -0
  213. package/dist/config/resolve-adapters.js +96 -0
  214. package/dist/config/resolve-adapters.js.map +1 -0
  215. package/dist/index.d.ts +18 -0
  216. package/dist/index.d.ts.map +1 -0
  217. package/dist/index.js +19 -0
  218. package/dist/index.js.map +1 -0
  219. package/dist/jiti.d.ts +2 -0
  220. package/dist/jiti.d.ts.map +1 -0
  221. package/dist/jiti.js +2 -0
  222. package/dist/jiti.js.map +1 -0
  223. package/dist/openapi/generate-spec.d.ts +56 -0
  224. package/dist/openapi/generate-spec.d.ts.map +1 -0
  225. package/dist/openapi/generate-spec.js +491 -0
  226. package/dist/openapi/generate-spec.js.map +1 -0
  227. package/dist/openapi/index.d.ts +4 -0
  228. package/dist/openapi/index.d.ts.map +1 -0
  229. package/dist/openapi/index.js +3 -0
  230. package/dist/openapi/index.js.map +1 -0
  231. package/dist/openapi/swagger-html.d.ts +2 -0
  232. package/dist/openapi/swagger-html.d.ts.map +1 -0
  233. package/dist/openapi/swagger-html.js +29 -0
  234. package/dist/openapi/swagger-html.js.map +1 -0
  235. package/dist/plugins/merge-resources.d.ts +18 -0
  236. package/dist/plugins/merge-resources.d.ts.map +1 -0
  237. package/dist/plugins/merge-resources.js +76 -0
  238. package/dist/plugins/merge-resources.js.map +1 -0
  239. package/dist/plugins/resolve-plugins.d.ts +14 -0
  240. package/dist/plugins/resolve-plugins.d.ts.map +1 -0
  241. package/dist/plugins/resolve-plugins.js +73 -0
  242. package/dist/plugins/resolve-plugins.js.map +1 -0
  243. package/dist/resource-loader.d.ts +151 -0
  244. package/dist/resource-loader.d.ts.map +1 -0
  245. package/dist/resource-loader.js +456 -0
  246. package/dist/resource-loader.js.map +1 -0
  247. package/dist/route-discovery.d.ts +33 -0
  248. package/dist/route-discovery.d.ts.map +1 -0
  249. package/dist/route-discovery.js +69 -0
  250. package/dist/route-discovery.js.map +1 -0
  251. package/dist/server-bootstrap.d.ts +38 -0
  252. package/dist/server-bootstrap.d.ts.map +1 -0
  253. package/dist/server-bootstrap.js +21 -0
  254. package/dist/server-bootstrap.js.map +1 -0
  255. package/dist/spa/generate-spa.d.ts +15 -0
  256. package/dist/spa/generate-spa.d.ts.map +1 -0
  257. package/dist/spa/generate-spa.js +357 -0
  258. package/dist/spa/generate-spa.js.map +1 -0
  259. package/dist/templates/agent/nextjs.md +129 -0
  260. package/dist/templates/agent/nuxt.md +98 -0
  261. package/dist/templates/agent/standalone.md +498 -0
  262. package/dist/types.d.ts +145 -0
  263. package/dist/types.d.ts.map +1 -0
  264. package/dist/types.js +3 -0
  265. package/dist/types.js.map +1 -0
  266. package/dist/utils/colors.d.ts +7 -0
  267. package/dist/utils/colors.d.ts.map +1 -0
  268. package/dist/utils/colors.js +8 -0
  269. package/dist/utils/colors.js.map +1 -0
  270. package/dist/utils/logger.d.ts +10 -0
  271. package/dist/utils/logger.d.ts.map +1 -0
  272. package/dist/utils/logger.js +27 -0
  273. package/dist/utils/logger.js.map +1 -0
  274. package/dist/utils/prompts.d.ts +6 -0
  275. package/dist/utils/prompts.d.ts.map +1 -0
  276. package/dist/utils/prompts.js +28 -0
  277. package/dist/utils/prompts.js.map +1 -0
  278. package/dist/utils/spinner.d.ts +7 -0
  279. package/dist/utils/spinner.d.ts.map +1 -0
  280. package/dist/utils/spinner.js +20 -0
  281. package/dist/utils/spinner.js.map +1 -0
  282. package/package.json +80 -0
@@ -0,0 +1,456 @@
1
+ // SPEC-074 — ResourceLoader: filesystem-based resource discovery
2
+ // Scans project directory for modules, subscribers, workflows, jobs, links, middlewares
3
+ // Modules are discovered via entities/{name}/model.ts — no index.ts needed.
4
+ import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
5
+ import { basename, resolve } from 'node:path';
6
+ import { MantaError, toCamel } from '@mantajs/core';
7
+ /**
8
+ * Discover all resources in a project directory.
9
+ * Scans src/modules, src/subscribers, src/workflows, src/jobs, src/links, src/middlewares.ts
10
+ */
11
+ export async function discoverResources(projectRoot) {
12
+ const srcDir = resolve(projectRoot, 'src');
13
+ const result = {
14
+ modules: [],
15
+ subscribers: [],
16
+ workflows: [],
17
+ jobs: [],
18
+ links: [],
19
+ commands: [],
20
+ queries: [],
21
+ users: [],
22
+ contexts: [],
23
+ agents: [],
24
+ middlewares: null,
25
+ contextMiddlewares: [],
26
+ spas: [],
27
+ };
28
+ if (!existsSync(srcDir)) {
29
+ return result;
30
+ }
31
+ // Modules: src/modules/*/entities/*/model.ts (file-based, no index.ts needed)
32
+ result.modules = discoverModules(srcDir);
33
+ // Subscribers: src/subscribers/*.ts
34
+ result.subscribers = discoverTsFiles(resolve(srcDir, 'subscribers'), (name, path) => ({
35
+ id: name,
36
+ path,
37
+ events: [], // populated at import time during boot
38
+ }));
39
+ // Workflows: src/workflows/*.ts
40
+ result.workflows = discoverTsFiles(resolve(srcDir, 'workflows'), (name, path) => ({
41
+ id: name,
42
+ path,
43
+ }));
44
+ // Jobs: src/jobs/*.ts
45
+ result.jobs = discoverTsFiles(resolve(srcDir, 'jobs'), (name, path) => ({
46
+ id: name,
47
+ path,
48
+ }));
49
+ // Links: src/links/*.ts
50
+ result.links = discoverTsFiles(resolve(srcDir, 'links'), (name, path) => ({
51
+ id: name,
52
+ path,
53
+ modules: [], // populated at import time during boot
54
+ }));
55
+ // Commands: src/commands/*.ts (V1 flat) + src/commands/{context}/*.ts (V2 nested)
56
+ result.commands = discoverCommandsV2(srcDir);
57
+ // Queries: src/queries/{context}/*.ts (V2 only)
58
+ result.queries = discoverQueries(srcDir);
59
+ // Users: modules whose index.ts exports a defineUserModel() result
60
+ result.users = discoverUsers(result.modules, resolve(srcDir, 'modules'));
61
+ // Per-context middleware: src/middleware/{context}.ts (V2)
62
+ result.contextMiddlewares = discoverContextMiddlewares(srcDir);
63
+ // SPAs: src/spa/{name}/ (V2)
64
+ result.spas = discoverSpas(srcDir);
65
+ // Contexts: src/contexts/*.ts
66
+ result.contexts = discoverTsFiles(resolve(srcDir, 'contexts'), (name, path) => ({
67
+ id: name,
68
+ path,
69
+ }));
70
+ // Agents: src/agents/*.ts
71
+ result.agents = discoverTsFiles(resolve(srcDir, 'agents'), (name, path) => ({
72
+ id: name,
73
+ path,
74
+ }));
75
+ // Middlewares: src/middlewares.ts
76
+ const middlewaresPath = resolve(srcDir, 'middlewares.ts');
77
+ if (existsSync(middlewaresPath)) {
78
+ result.middlewares = { path: middlewaresPath };
79
+ }
80
+ return result;
81
+ }
82
+ /**
83
+ * Discover modules from src/modules/{name}/entities/{entity}/model.ts
84
+ * No index.ts required — entities are discovered directly from file structure.
85
+ *
86
+ * Structure:
87
+ * modules/{module}/entities/{entity}/model.ts — required
88
+ * modules/{module}/entities/{entity}/service.ts — optional
89
+ */
90
+ function discoverModules(srcDir) {
91
+ const modulesDir = resolve(srcDir, 'modules');
92
+ if (!existsSync(modulesDir))
93
+ return [];
94
+ const modules = [];
95
+ for (const entry of readdirSync(modulesDir)) {
96
+ const moduleDir = resolve(modulesDir, entry);
97
+ if (!statSync(moduleDir).isDirectory())
98
+ continue;
99
+ // Canonicalize directory name → camelCase JS identifier.
100
+ // `dirName` is the raw on-disk name (for filesystem + logs + URLs).
101
+ // `name` is the canonical camelCase identifier used as a JS/TS key everywhere downstream.
102
+ const dirName = entry;
103
+ const name = toCamel(entry);
104
+ // Validate that the canonicalized name is a legal JS identifier.
105
+ if (!/^[a-z][A-Za-z0-9]*$/.test(name)) {
106
+ throw new MantaError('INVALID_DATA', `Module directory "${dirName}" does not produce a valid JS identifier ("${name}"). ` +
107
+ `Use kebab-case or camelCase letters only.`);
108
+ }
109
+ // Collision detection: two different directories canonicalizing to the same identifier.
110
+ const existing = modules.find((m) => m.name === name);
111
+ if (existing) {
112
+ throw new MantaError('INVALID_DATA', `Module directory collision: "${dirName}" and "${existing.dirName}" both canonicalize to "${name}". ` +
113
+ `Rename one of them.`);
114
+ }
115
+ // Validate structure — reject model.ts/service.ts at module root
116
+ validateModuleStructure(moduleDir, dirName);
117
+ // Discover entities from entities/*/model.ts
118
+ const entities = discoverEntities(moduleDir, dirName);
119
+ if (entities.length === 0)
120
+ continue; // Skip modules with no entities
121
+ // Discover intra-module commands from commands/*.ts (commands scoped to this module)
122
+ const moduleCommands = discoverTsFiles(resolve(moduleDir, 'commands'), (name, path) => ({
123
+ id: name,
124
+ path,
125
+ }));
126
+ // Discover intra-module queries from queries/*.ts (queries scoped to this module)
127
+ const moduleQueries = discoverTsFiles(resolve(moduleDir, 'queries'), (name, path) => ({
128
+ id: name,
129
+ path,
130
+ }));
131
+ // Discover intra-module raw API routes from api/**/route.ts (escape hatch for non-CQRS)
132
+ const moduleApiRoutes = discoverModuleApiRoutes(resolve(moduleDir, 'api'));
133
+ // Discover intra-module links from links/*.ts — use canonical `name` for the modules list
134
+ // since consumers use it as a JS identifier for intra-module detection.
135
+ const moduleLinks = discoverTsFiles(resolve(moduleDir, 'links'), (linkName, path) => ({
136
+ id: linkName,
137
+ path,
138
+ modules: [name],
139
+ }));
140
+ // Service name convention: capitalize canonical name + "Service" (e.g. 'myMod' → 'MyModService')
141
+ const service = `${name.charAt(0).toUpperCase()}${name.slice(1)}Service`;
142
+ modules.push({
143
+ name,
144
+ dirName,
145
+ moduleDir,
146
+ entities,
147
+ commands: moduleCommands,
148
+ queries: moduleQueries,
149
+ apiRoutes: moduleApiRoutes,
150
+ intraLinks: moduleLinks,
151
+ // Backward compat: path = first entity's model.ts
152
+ path: entities[0].modelPath,
153
+ models: entities.map((e) => e.name),
154
+ service,
155
+ });
156
+ }
157
+ return modules;
158
+ }
159
+ /**
160
+ * Discover entities within a module's entities/ directory.
161
+ * Each entity must have model.ts. service.ts is optional.
162
+ */
163
+ function discoverEntities(moduleDir, moduleName) {
164
+ const entitiesDir = resolve(moduleDir, 'entities');
165
+ if (!existsSync(entitiesDir))
166
+ return [];
167
+ const entities = [];
168
+ for (const entityEntry of readdirSync(entitiesDir)) {
169
+ const entityDir = resolve(entitiesDir, entityEntry);
170
+ if (!statSync(entityDir).isDirectory()) {
171
+ throw new MantaError('INVALID_DATA', `Module "${moduleName}": entities/ must contain only directories (one per entity). ` +
172
+ `Found file "${entityEntry}" directly in entities/. ` +
173
+ `Move it to modules/${moduleName}/entities/${entityEntry.replace(/\.ts$/, '')}/model.ts`);
174
+ }
175
+ const modelPath = resolve(entityDir, 'model.ts');
176
+ if (!existsSync(modelPath)) {
177
+ throw new MantaError('INVALID_DATA', `Module "${moduleName}": entity "${entityEntry}" is missing model.ts. ` +
178
+ `Every entity directory must contain a model.ts file with a defineModel() call.`);
179
+ }
180
+ const servicePath = resolve(entityDir, 'service.ts');
181
+ entities.push({
182
+ name: entityEntry,
183
+ modelPath,
184
+ servicePath: existsSync(servicePath) ? servicePath : undefined,
185
+ });
186
+ }
187
+ return entities;
188
+ }
189
+ /**
190
+ * Validate that a module follows the canonical structure.
191
+ * Rejects model.ts or service.ts at module root — they must be in entities/{entity}/.
192
+ */
193
+ function validateModuleStructure(moduleDir, moduleName) {
194
+ const rootModel = resolve(moduleDir, 'model.ts');
195
+ const rootService = resolve(moduleDir, 'service.ts');
196
+ if (existsSync(rootModel)) {
197
+ throw new MantaError('INVALID_DATA', `Module "${moduleName}" has model.ts at its root. ` +
198
+ `Move it to modules/${moduleName}/entities/{entity-name}/model.ts — ` +
199
+ `the framework requires entities to be in the entities/ subdirectory.`);
200
+ }
201
+ if (existsSync(rootService)) {
202
+ throw new MantaError('INVALID_DATA', `Module "${moduleName}" has service.ts at its root. ` +
203
+ `Move it to modules/${moduleName}/entities/{entity-name}/service.ts — ` +
204
+ `each entity's service belongs next to its model.`);
205
+ }
206
+ }
207
+ /**
208
+ * Discover raw API route files in a module's api/ directory.
209
+ * Recursively walks the directory looking for route.ts files.
210
+ *
211
+ * Example:
212
+ * modules/posthog/api/[...path]/route.ts → relativePath "[...path]"
213
+ * modules/stripe/api/webhook/route.ts → relativePath "webhook"
214
+ * modules/stripe/api/oauth/callback/route.ts → relativePath "oauth/callback"
215
+ */
216
+ function discoverModuleApiRoutes(apiDir) {
217
+ if (!existsSync(apiDir))
218
+ return [];
219
+ const routes = [];
220
+ const walk = (dir, relParts) => {
221
+ for (const entry of readdirSync(dir)) {
222
+ const fullPath = resolve(dir, entry);
223
+ const stat = statSync(fullPath);
224
+ if (stat.isDirectory()) {
225
+ walk(fullPath, [...relParts, entry]);
226
+ }
227
+ else if (entry === 'route.ts' || entry === 'route.js') {
228
+ routes.push({
229
+ relativePath: relParts.join('/'),
230
+ file: fullPath,
231
+ });
232
+ }
233
+ }
234
+ };
235
+ walk(apiDir, []);
236
+ return routes;
237
+ }
238
+ /**
239
+ * Generic discovery for .ts files in a directory.
240
+ * Returns T[] where T is built from (baseName, absolutePath).
241
+ */
242
+ function discoverTsFiles(dir, mapFn) {
243
+ if (!existsSync(dir))
244
+ return [];
245
+ const results = [];
246
+ for (const file of readdirSync(dir)) {
247
+ if (!file.endsWith('.ts') && !file.endsWith('.js'))
248
+ continue;
249
+ const filePath = resolve(dir, file);
250
+ if (!statSync(filePath).isFile())
251
+ continue;
252
+ const name = basename(file, file.endsWith('.ts') ? '.ts' : '.js');
253
+ results.push(mapFn(name, filePath));
254
+ }
255
+ return results;
256
+ }
257
+ // ── V2 Discovery Functions ──────────────────────────────────────────
258
+ /**
259
+ * V2: Discover commands from both flat (V1) and nested (V2) patterns.
260
+ * - src/commands/*.ts → V1 flat commands (no context)
261
+ * - src/commands/{context}/*.ts → V2 context-scoped commands
262
+ */
263
+ function discoverCommandsV2(srcDir) {
264
+ const commandsDir = resolve(srcDir, 'commands');
265
+ if (!existsSync(commandsDir))
266
+ return [];
267
+ const commands = [];
268
+ for (const entry of readdirSync(commandsDir)) {
269
+ const entryPath = resolve(commandsDir, entry);
270
+ if (statSync(entryPath).isDirectory()) {
271
+ // V2 nested: commands/{context}/*.ts
272
+ const contextName = entry;
273
+ const contextCommands = discoverTsFiles(entryPath, (name, path) => ({
274
+ id: name,
275
+ path,
276
+ context: contextName,
277
+ }));
278
+ commands.push(...contextCommands);
279
+ }
280
+ else if (entry.endsWith('.ts') || entry.endsWith('.js')) {
281
+ // V1 flat: commands/*.ts
282
+ const name = basename(entry, entry.endsWith('.ts') ? '.ts' : '.js');
283
+ commands.push({ id: name, path: entryPath });
284
+ }
285
+ }
286
+ return commands;
287
+ }
288
+ /**
289
+ * V2: Discover queries from src/queries/{context}/*.ts.
290
+ * Queries are always context-scoped (no flat pattern).
291
+ */
292
+ function discoverQueries(srcDir) {
293
+ const queriesDir = resolve(srcDir, 'queries');
294
+ if (!existsSync(queriesDir))
295
+ return [];
296
+ const queries = [];
297
+ for (const entry of readdirSync(queriesDir)) {
298
+ const contextDir = resolve(queriesDir, entry);
299
+ if (!statSync(contextDir).isDirectory())
300
+ continue;
301
+ const contextName = entry;
302
+ const contextQueries = discoverTsFiles(contextDir, (name, path) => ({
303
+ id: name,
304
+ path,
305
+ context: contextName,
306
+ }));
307
+ queries.push(...contextQueries);
308
+ }
309
+ return queries;
310
+ }
311
+ /**
312
+ * V2: Detect user definitions by checking for index.ts in user module directories.
313
+ * Convention: modules ending with '-user' that export a defineUserModel() result.
314
+ * The actual __type check happens at import time during bootstrap.
315
+ */
316
+ /**
317
+ * Detect user definitions in ANY module.
318
+ *
319
+ * defineUserModel can be used instead of defineModel in any entity's model.ts.
320
+ * We scan all model.ts files for the string 'defineUserModel' to identify candidates.
321
+ * The actual __type: 'user' check happens at import time during bootstrap.
322
+ *
323
+ * Also supports legacy convention: modules ending with '-user' that have index.ts.
324
+ */
325
+ function discoverUsers(modules, modulesDir) {
326
+ const users = [];
327
+ for (const mod of modules) {
328
+ // Scan ALL entity model.ts files for defineUserModel usage
329
+ for (const entity of mod.entities) {
330
+ const modelPath = entity.modelPath;
331
+ if (!existsSync(modelPath))
332
+ continue;
333
+ try {
334
+ const content = readFileSync(modelPath, 'utf-8');
335
+ if (content.includes('defineUserModel')) {
336
+ // Extract context name from the defineUserModel call: defineUserModel('customer', ...)
337
+ const match = content.match(/defineUserModel\s*\(\s*['"]([^'"]+)['"]/);
338
+ const contextName = match?.[1] ?? entity.name.toLowerCase();
339
+ users.push({
340
+ contextName,
341
+ moduleName: mod.name,
342
+ path: modelPath,
343
+ });
344
+ }
345
+ }
346
+ catch {
347
+ // Can't read file — skip
348
+ }
349
+ }
350
+ // Legacy: modules ending with '-user' that have index.ts
351
+ if (mod.dirName.endsWith('-user')) {
352
+ const indexPath = resolve(modulesDir, mod.dirName, 'index.ts');
353
+ if (existsSync(indexPath)) {
354
+ const contextName = mod.dirName.replace(/-user$/, '');
355
+ // Don't add duplicate if already found via model.ts scan
356
+ if (!users.some((u) => u.contextName === contextName)) {
357
+ users.push({ contextName, moduleName: mod.name, path: indexPath });
358
+ }
359
+ }
360
+ }
361
+ }
362
+ return users;
363
+ }
364
+ /**
365
+ * V2: Discover per-context middleware from src/middleware/{context}.ts.
366
+ * Each .ts file in the middleware/ directory is a context override.
367
+ */
368
+ function discoverContextMiddlewares(srcDir) {
369
+ const middlewareDir = resolve(srcDir, 'middleware');
370
+ if (!existsSync(middlewareDir))
371
+ return [];
372
+ const middlewares = [];
373
+ for (const file of readdirSync(middlewareDir)) {
374
+ if (!file.endsWith('.ts') && !file.endsWith('.js'))
375
+ continue;
376
+ const filePath = resolve(middlewareDir, file);
377
+ if (!statSync(filePath).isFile())
378
+ continue;
379
+ const context = basename(file, file.endsWith('.ts') ? '.ts' : '.js');
380
+ middlewares.push({ context, path: filePath });
381
+ }
382
+ return middlewares;
383
+ }
384
+ /**
385
+ * V2: Discover SPAs from src/spa/{name}/.
386
+ * Each subdirectory in spa/ is a SPA to serve on /{name}.
387
+ */
388
+ function discoverSpas(srcDir) {
389
+ const spaDir = resolve(srcDir, 'spa');
390
+ if (!existsSync(spaDir))
391
+ return [];
392
+ const spas = [];
393
+ for (const entry of readdirSync(spaDir)) {
394
+ const entryPath = resolve(spaDir, entry);
395
+ if (!statSync(entryPath).isDirectory())
396
+ continue;
397
+ // Discover pages from pages/ subdirectory
398
+ const pagesDir = resolve(entryPath, 'pages');
399
+ const pages = discoverSpaPages(pagesDir, '');
400
+ // Discover custom blocks from blocks/ subdirectory
401
+ const blocks = discoverSpaBlocks(resolve(entryPath, 'blocks'));
402
+ // Discover config.ts
403
+ const configTs = resolve(entryPath, 'config.ts');
404
+ const configPath = existsSync(configTs) ? configTs : null;
405
+ spas.push({ name: entry, path: entryPath, pages, blocks, configPath });
406
+ }
407
+ return spas;
408
+ }
409
+ /**
410
+ * Recursively discover page.tsx files in a SPA directory.
411
+ * src/spa/admin/products/page.tsx → route '/products'
412
+ * src/spa/admin/page.tsx → route '/'
413
+ * src/spa/admin/orders/[id]/page.tsx → route '/orders/:id'
414
+ */
415
+ function discoverSpaPages(dir, prefix) {
416
+ const pages = [];
417
+ if (!existsSync(dir))
418
+ return pages;
419
+ for (const entry of readdirSync(dir)) {
420
+ const entryPath = resolve(dir, entry);
421
+ if (entry === 'page.tsx' || entry === 'page.ts') {
422
+ const route = prefix || '/';
423
+ pages.push({ route, path: entryPath });
424
+ }
425
+ else if (statSync(entryPath).isDirectory()) {
426
+ // Convert [param] to :param for routing
427
+ const segment = entry.startsWith('[') && entry.endsWith(']') ? `:${entry.slice(1, -1)}` : entry;
428
+ pages.push(...discoverSpaPages(entryPath, `${prefix}/${segment}`));
429
+ }
430
+ }
431
+ return pages;
432
+ }
433
+ /**
434
+ * Discover custom blocks from a SPA's blocks/ directory.
435
+ * blocks/inventory-matrix.tsx → type 'InventoryMatrix'
436
+ */
437
+ function discoverSpaBlocks(dir) {
438
+ const blocks = [];
439
+ if (!existsSync(dir))
440
+ return blocks;
441
+ for (const entry of readdirSync(dir)) {
442
+ if (!entry.endsWith('.tsx') && !entry.endsWith('.ts'))
443
+ continue;
444
+ if (entry.startsWith('.') || entry === 'index.ts' || entry === 'index.tsx')
445
+ continue;
446
+ const name = entry.replace(/\.tsx?$/, '');
447
+ // Convert kebab-case to PascalCase
448
+ const type = name
449
+ .split('-')
450
+ .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
451
+ .join('');
452
+ blocks.push({ type, path: resolve(dir, entry) });
453
+ }
454
+ return blocks;
455
+ }
456
+ //# sourceMappingURL=resource-loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resource-loader.js","sourceRoot":"","sources":["../src/resource-loader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ export interface DiscoveredRoute {
2
+ /** HTTP method (GET, POST, PUT, DELETE, PATCH) */
3
+ method: string;
4
+ /** URL path (e.g. /admin/products/:id) */
5
+ path: string;
6
+ /** Absolute file path to the route module */
7
+ file: string;
8
+ /** Export name in the module (e.g. 'GET', 'POST') */
9
+ exportName: string;
10
+ /** Optional Zod schema for body validation (from VALIDATION export) */
11
+ bodySchema?: unknown;
12
+ }
13
+ /**
14
+ * Discover routes from src/api/ directory.
15
+ *
16
+ * Convention:
17
+ * - src/api/admin/products/route.ts → /api/admin/products
18
+ * - src/api/admin/products/[id]/route.ts → /api/admin/products/:id
19
+ * - Exported named functions matching HTTP methods become handlers
20
+ * - All routes are prefixed with /api/
21
+ */
22
+ /**
23
+ * Loads a route module to read its exports. Defaults to native dynamic import
24
+ * (used by the build path). In `manta dev`, the bootstrap threads its jiti
25
+ * loader through here so route files — and their transitive TS/workspace
26
+ * imports (e.g. `@mantajs/core`, local agents) — resolve the same way the rest
27
+ * of the app does. Native ESM cannot load the framework's directory-style
28
+ * source exports, so discovering routes with a raw `import()` would 500 every
29
+ * request whose route file imports `@mantajs/core`.
30
+ */
31
+ export type RouteImportFn = (path: string) => Promise<Record<string, unknown>>;
32
+ export declare function discoverRoutes(cwd: string, importFn?: RouteImportFn): Promise<DiscoveredRoute[]>;
33
+ //# sourceMappingURL=route-discovery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route-discovery.d.ts","sourceRoot":"","sources":["../src/route-discovery.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,eAAe;IAC9B,kDAAkD;IAClD,MAAM,EAAE,MAAM,CAAA;IACd,0CAA0C;IAC1C,IAAI,EAAE,MAAM,CAAA;IACZ,6CAA6C;IAC7C,IAAI,EAAE,MAAM,CAAA;IACZ,qDAAqD;IACrD,UAAU,EAAE,MAAM,CAAA;IAClB,uEAAuE;IACvE,UAAU,CAAC,EAAE,OAAO,CAAA;CACrB;AAID;;;;;;;;GAQG;AACH;;;;;;;;GAQG;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;AAI9E,wBAAsB,cAAc,CAClC,GAAG,EAAE,MAAM,EACX,QAAQ,GAAE,aAAiC,GAC1C,OAAO,CAAC,eAAe,EAAE,CAAC,CAkD5B"}
@@ -0,0 +1,69 @@
1
+ // SPEC-039 — File-system route discovery
2
+ // Scans src/api/ and maps file paths to HTTP routes
3
+ import { existsSync, readdirSync, statSync } from 'node:fs';
4
+ import { dirname, relative, resolve } from 'node:path';
5
+ const HTTP_METHODS = new Set(['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS', 'HEAD']);
6
+ const nativeRouteImport = (path) => import(`${path}?t=${Date.now()}`);
7
+ export async function discoverRoutes(cwd, importFn = nativeRouteImport) {
8
+ const apiDir = resolve(cwd, 'src', 'api');
9
+ if (!existsSync(apiDir)) {
10
+ return [];
11
+ }
12
+ const routeFiles = findRouteFiles(apiDir);
13
+ const routes = [];
14
+ for (const file of routeFiles) {
15
+ // Derive URL path from file path
16
+ const relPath = relative(apiDir, dirname(file));
17
+ const urlPath = '/api/' +
18
+ relPath
19
+ .split('/')
20
+ .map((segment) => {
21
+ // [...path] → ** (H3/Nitro catch-all syntax)
22
+ if (segment.startsWith('[...') && segment.endsWith(']')) {
23
+ return '**';
24
+ }
25
+ // [id] → :id
26
+ if (segment.startsWith('[') && segment.endsWith(']')) {
27
+ return `:${segment.slice(1, -1)}`;
28
+ }
29
+ return segment;
30
+ })
31
+ .join('/');
32
+ // Import the module to discover exported methods
33
+ const mod = await importFn(file);
34
+ // Check for VALIDATION export: { POST: zodSchema, PUT: zodSchema, ... }
35
+ const validation = mod.VALIDATION;
36
+ for (const exportName of Object.keys(mod)) {
37
+ if (HTTP_METHODS.has(exportName) && typeof mod[exportName] === 'function') {
38
+ routes.push({
39
+ method: exportName,
40
+ path: urlPath,
41
+ file,
42
+ exportName,
43
+ bodySchema: validation?.[exportName],
44
+ });
45
+ }
46
+ }
47
+ }
48
+ return routes;
49
+ }
50
+ /**
51
+ * Recursively find all route.ts files in a directory.
52
+ */
53
+ function findRouteFiles(dir) {
54
+ const files = [];
55
+ if (!existsSync(dir))
56
+ return files;
57
+ for (const entry of readdirSync(dir)) {
58
+ const fullPath = resolve(dir, entry);
59
+ const stat = statSync(fullPath);
60
+ if (stat.isDirectory()) {
61
+ files.push(...findRouteFiles(fullPath));
62
+ }
63
+ else if (entry === 'route.ts' || entry === 'route.js') {
64
+ files.push(fullPath);
65
+ }
66
+ }
67
+ return files;
68
+ }
69
+ //# sourceMappingURL=route-discovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route-discovery.js","sourceRoot":"","sources":["../src/route-discovery.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ import type { MantaApp } from '@mantajs/core';
2
+ export { type BootstrapOptions, type BootstrappedApp, bootstrapApp } from './bootstrap/bootstrap-app';
3
+ /**
4
+ * MantaRequest — the request object passed to route handlers.
5
+ *
6
+ * @example
7
+ * export async function GET(req: MantaRequest) {
8
+ * // New way — typed, with autocompletion
9
+ * const products = await req.app.modules.product.list()
10
+ *
11
+ * // Legacy way — still works
12
+ * const svc = req.scope.resolve('productModuleService')
13
+ * }
14
+ */
15
+ export interface MantaRequest extends Request {
16
+ validatedBody?: unknown;
17
+ params: Record<string, string>;
18
+ requestId: string;
19
+ /** Typed application object — preferred for new code */
20
+ app: MantaApp<any>;
21
+ /** Query service — shorthand for req.app.resolve('query') */
22
+ query: import('@mantajs/core').QueryService;
23
+ /** Workflow registry — shorthand for req.app.workflows */
24
+ workflows: Record<string, (...args: any[]) => Promise<unknown>>;
25
+ /** Parsed query string fields (e.g. ?fields=id,title) */
26
+ queryFields?: string[];
27
+ /** @deprecated Use req.app instead */
28
+ scope: {
29
+ resolve<T = unknown>(key: string): T;
30
+ };
31
+ }
32
+ /**
33
+ * Extract the request body from a MantaRequest.
34
+ * Uses the pre-validated body if available (set by H3 middleware),
35
+ * otherwise falls back to parsing the JSON body.
36
+ */
37
+ export declare function getRequestBody<T = Record<string, unknown>>(req: Request): Promise<T>;
38
+ //# sourceMappingURL=server-bootstrap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-bootstrap.d.ts","sourceRoot":"","sources":["../src/server-bootstrap.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAG7C,OAAO,EAAE,KAAK,gBAAgB,EAAE,KAAK,eAAe,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAErG;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,YAAa,SAAQ,OAAO;IAC3C,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC9B,SAAS,EAAE,MAAM,CAAA;IACjB,wDAAwD;IAExD,GAAG,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAA;IAClB,6DAA6D;IAC7D,KAAK,EAAE,OAAO,eAAe,EAAE,YAAY,CAAA;IAC3C,0DAA0D;IAE1D,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC,CAAA;IAC/D,yDAAyD;IACzD,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;IACtB,sCAAsC;IACtC,KAAK,EAAE;QAAE,OAAO,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,CAAA;KAAE,CAAA;CAChD;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,CAQ1F"}
@@ -0,0 +1,21 @@
1
+ // Portable app bootstrap — re-exported for external hosts (Next.js, Nuxt, etc.)
2
+ // The standalone HTTP server is now handled by Nitro (host-nitro).
3
+ // Re-export for external host usage
4
+ export { bootstrapApp } from './bootstrap/bootstrap-app';
5
+ /**
6
+ * Extract the request body from a MantaRequest.
7
+ * Uses the pre-validated body if available (set by H3 middleware),
8
+ * otherwise falls back to parsing the JSON body.
9
+ */
10
+ export async function getRequestBody(req) {
11
+ const mantaReq = req;
12
+ if (mantaReq.validatedBody !== undefined)
13
+ return mantaReq.validatedBody;
14
+ try {
15
+ return (await req.clone().json());
16
+ }
17
+ catch {
18
+ return {};
19
+ }
20
+ }
21
+ //# sourceMappingURL=server-bootstrap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-bootstrap.js","sourceRoot":"","sources":["../src/server-bootstrap.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,mEAAmE;AAInE,oCAAoC;AACpC,OAAO,EAA+C,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAgCrG;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAA8B,GAAY;IAC5E,MAAM,QAAQ,GAAG,GAAmB,CAAA;IACpC,IAAI,QAAQ,CAAC,aAAa,KAAK,SAAS;QAAE,OAAO,QAAQ,CAAC,aAAkB,CAAA;IAC5E,IAAI,CAAC;QACH,OAAO,CAAC,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,CAAM,CAAA;IACxC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAO,CAAA;IAChB,CAAC;AACH,CAAC"}