@happyvertical/smrt-core 0.30.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 (631) hide show
  1. package/AGENTS.md +124 -0
  2. package/CLAUDE.md +1 -0
  3. package/LICENSE +7 -0
  4. package/README.md +265 -0
  5. package/bin/smrt-prebuild.js +26 -0
  6. package/dist/__tests__/fixtures/advisor-test-classes.d.ts +28 -0
  7. package/dist/__tests__/fixtures/advisor-test-classes.d.ts.map +1 -0
  8. package/dist/__tests__/fixtures/collection-coverage-fixtures.d.ts +12 -0
  9. package/dist/__tests__/fixtures/collection-coverage-fixtures.d.ts.map +1 -0
  10. package/dist/__tests__/fixtures/inheritance-resolver-fixtures.d.ts +28 -0
  11. package/dist/__tests__/fixtures/inheritance-resolver-fixtures.d.ts.map +1 -0
  12. package/dist/__tests__/fixtures/inheritance-test-classes.d.ts +43 -0
  13. package/dist/__tests__/fixtures/inheritance-test-classes.d.ts.map +1 -0
  14. package/dist/__tests__/fixtures/mcp-integration-test-classes.d.ts +18 -0
  15. package/dist/__tests__/fixtures/mcp-integration-test-classes.d.ts.map +1 -0
  16. package/dist/__tests__/fixtures/object-ai-memory-fixtures.d.ts +15 -0
  17. package/dist/__tests__/fixtures/object-ai-memory-fixtures.d.ts.map +1 -0
  18. package/dist/__tests__/fixtures/object-spec-test-classes.d.ts +13 -0
  19. package/dist/__tests__/fixtures/object-spec-test-classes.d.ts.map +1 -0
  20. package/dist/__tests__/fixtures/registry-test-classes.d.ts +23 -0
  21. package/dist/__tests__/fixtures/registry-test-classes.d.ts.map +1 -0
  22. package/dist/adapters/ai-usage.d.ts +23 -0
  23. package/dist/adapters/ai-usage.d.ts.map +1 -0
  24. package/dist/adapters/ai-usage.js +105 -0
  25. package/dist/adapters/ai-usage.js.map +1 -0
  26. package/dist/adapters/cost-rates.d.ts +20 -0
  27. package/dist/adapters/cost-rates.d.ts.map +1 -0
  28. package/dist/adapters/cost-rates.js +40 -0
  29. package/dist/adapters/cost-rates.js.map +1 -0
  30. package/dist/adapters/index.d.ts +19 -0
  31. package/dist/adapters/index.d.ts.map +1 -0
  32. package/dist/adapters/metrics.d.ts +111 -0
  33. package/dist/adapters/metrics.d.ts.map +1 -0
  34. package/dist/adapters/metrics.js +169 -0
  35. package/dist/adapters/metrics.js.map +1 -0
  36. package/dist/adapters/pubsub.d.ts +124 -0
  37. package/dist/adapters/pubsub.d.ts.map +1 -0
  38. package/dist/adapters/pubsub.js +121 -0
  39. package/dist/adapters/pubsub.js.map +1 -0
  40. package/dist/browser.d.ts +32 -0
  41. package/dist/browser.d.ts.map +1 -0
  42. package/dist/browser.js +68 -0
  43. package/dist/browser.js.map +1 -0
  44. package/dist/child-accessors.d.ts +27 -0
  45. package/dist/child-accessors.d.ts.map +1 -0
  46. package/dist/child-accessors.js +35 -0
  47. package/dist/child-accessors.js.map +1 -0
  48. package/dist/class.d.ts +313 -0
  49. package/dist/class.d.ts.map +1 -0
  50. package/dist/class.js +896 -0
  51. package/dist/class.js.map +1 -0
  52. package/dist/collection-cache.d.ts +110 -0
  53. package/dist/collection-cache.d.ts.map +1 -0
  54. package/dist/collection-cache.js +187 -0
  55. package/dist/collection-cache.js.map +1 -0
  56. package/dist/collection.d.ts +894 -0
  57. package/dist/collection.d.ts.map +1 -0
  58. package/dist/collection.js +1987 -0
  59. package/dist/collection.js.map +1 -0
  60. package/dist/config/global-config.d.ts +3 -0
  61. package/dist/config/global-config.d.ts.map +1 -0
  62. package/dist/config/global-config.js +19 -0
  63. package/dist/config/global-config.js.map +1 -0
  64. package/dist/config.d.ts +145 -0
  65. package/dist/config.d.ts.map +1 -0
  66. package/dist/config.js +57 -0
  67. package/dist/config.js.map +1 -0
  68. package/dist/consumer-plugin/index.d.ts +22 -0
  69. package/dist/consumer-plugin/index.d.ts.map +1 -0
  70. package/dist/consumer-plugin/index.js +452 -0
  71. package/dist/consumer-plugin/index.js.map +1 -0
  72. package/dist/consumer-plugin.d.ts +8 -0
  73. package/dist/consumer-plugin.d.ts.map +1 -0
  74. package/dist/consumer-plugin.js +5 -0
  75. package/dist/consumer-plugin.js.map +1 -0
  76. package/dist/database.d.ts +95 -0
  77. package/dist/database.d.ts.map +1 -0
  78. package/dist/database.js +32 -0
  79. package/dist/database.js.map +1 -0
  80. package/dist/decorators/compatibility.d.ts +14 -0
  81. package/dist/decorators/compatibility.d.ts.map +1 -0
  82. package/dist/decorators/compatibility.js +111 -0
  83. package/dist/decorators/compatibility.js.map +1 -0
  84. package/dist/decorators/index.d.ts +381 -0
  85. package/dist/decorators/index.d.ts.map +1 -0
  86. package/dist/decorators/index.js +104 -0
  87. package/dist/decorators/index.js.map +1 -0
  88. package/dist/dispatch/bus.d.ts +306 -0
  89. package/dist/dispatch/bus.d.ts.map +1 -0
  90. package/dist/dispatch/bus.js +583 -0
  91. package/dist/dispatch/bus.js.map +1 -0
  92. package/dist/dispatch/collections/DispatchSubscriptions.d.ts +79 -0
  93. package/dist/dispatch/collections/DispatchSubscriptions.d.ts.map +1 -0
  94. package/dist/dispatch/collections/DispatchSubscriptions.js +243 -0
  95. package/dist/dispatch/collections/DispatchSubscriptions.js.map +1 -0
  96. package/dist/dispatch/collections/Dispatches.d.ts +98 -0
  97. package/dist/dispatch/collections/Dispatches.d.ts.map +1 -0
  98. package/dist/dispatch/collections/Dispatches.js +358 -0
  99. package/dist/dispatch/collections/Dispatches.js.map +1 -0
  100. package/dist/dispatch/index.d.ts +47 -0
  101. package/dist/dispatch/index.d.ts.map +1 -0
  102. package/dist/dispatch/models/Dispatch.d.ts +101 -0
  103. package/dist/dispatch/models/Dispatch.d.ts.map +1 -0
  104. package/dist/dispatch/models/Dispatch.js +162 -0
  105. package/dist/dispatch/models/Dispatch.js.map +1 -0
  106. package/dist/dispatch/models/DispatchSubscription.d.ts +83 -0
  107. package/dist/dispatch/models/DispatchSubscription.d.ts.map +1 -0
  108. package/dist/dispatch/models/DispatchSubscription.js +112 -0
  109. package/dist/dispatch/models/DispatchSubscription.js.map +1 -0
  110. package/dist/dispatch/tenant-resolver.d.ts +98 -0
  111. package/dist/dispatch/tenant-resolver.d.ts.map +1 -0
  112. package/dist/dispatch/tenant-resolver.js +32 -0
  113. package/dist/dispatch/tenant-resolver.js.map +1 -0
  114. package/dist/dispatch/types.d.ts +149 -0
  115. package/dist/dispatch/types.d.ts.map +1 -0
  116. package/dist/embeddings/hash.d.ts +33 -0
  117. package/dist/embeddings/hash.d.ts.map +1 -0
  118. package/dist/embeddings/hash.js +37 -0
  119. package/dist/embeddings/hash.js.map +1 -0
  120. package/dist/embeddings/index.d.ts +36 -0
  121. package/dist/embeddings/index.d.ts.map +1 -0
  122. package/dist/embeddings/provider.d.ts +75 -0
  123. package/dist/embeddings/provider.d.ts.map +1 -0
  124. package/dist/embeddings/provider.js +170 -0
  125. package/dist/embeddings/provider.js.map +1 -0
  126. package/dist/embeddings/similarity.d.ts +47 -0
  127. package/dist/embeddings/similarity.d.ts.map +1 -0
  128. package/dist/embeddings/similarity.js +64 -0
  129. package/dist/embeddings/similarity.js.map +1 -0
  130. package/dist/embeddings/storage.d.ts +125 -0
  131. package/dist/embeddings/storage.d.ts.map +1 -0
  132. package/dist/embeddings/storage.js +283 -0
  133. package/dist/embeddings/storage.js.map +1 -0
  134. package/dist/embeddings/types.d.ts +250 -0
  135. package/dist/embeddings/types.d.ts.map +1 -0
  136. package/dist/errors.d.ts +363 -0
  137. package/dist/errors.d.ts.map +1 -0
  138. package/dist/errors.js +669 -0
  139. package/dist/errors.js.map +1 -0
  140. package/dist/generators/cli.d.ts +162 -0
  141. package/dist/generators/cli.d.ts.map +1 -0
  142. package/dist/generators/cli.js +462 -0
  143. package/dist/generators/cli.js.map +1 -0
  144. package/dist/generators/index.d.ts +13 -0
  145. package/dist/generators/index.d.ts.map +1 -0
  146. package/dist/generators/mcp-runtime-template.d.ts +60 -0
  147. package/dist/generators/mcp-runtime-template.d.ts.map +1 -0
  148. package/dist/generators/mcp-runtime-template.js +509 -0
  149. package/dist/generators/mcp-runtime-template.js.map +1 -0
  150. package/dist/generators/mcp.d.ts +231 -0
  151. package/dist/generators/mcp.d.ts.map +1 -0
  152. package/dist/generators/mcp.js +1220 -0
  153. package/dist/generators/mcp.js.map +1 -0
  154. package/dist/generators/rest.d.ts +171 -0
  155. package/dist/generators/rest.d.ts.map +1 -0
  156. package/dist/generators/rest.js +591 -0
  157. package/dist/generators/rest.js.map +1 -0
  158. package/dist/generators/swagger.d.ts +21 -0
  159. package/dist/generators/swagger.d.ts.map +1 -0
  160. package/dist/generators/swagger.js +307 -0
  161. package/dist/generators/swagger.js.map +1 -0
  162. package/dist/generators/tenant-gate.d.ts +74 -0
  163. package/dist/generators/tenant-gate.d.ts.map +1 -0
  164. package/dist/generators/tenant-gate.js +15 -0
  165. package/dist/generators/tenant-gate.js.map +1 -0
  166. package/dist/generators.d.ts +8 -0
  167. package/dist/generators.d.ts.map +1 -0
  168. package/dist/generators.js +19 -0
  169. package/dist/generators.js.map +1 -0
  170. package/dist/hierarchical.d.ts +103 -0
  171. package/dist/hierarchical.d.ts.map +1 -0
  172. package/dist/hierarchical.js +184 -0
  173. package/dist/hierarchical.js.map +1 -0
  174. package/dist/index.d.ts +57 -0
  175. package/dist/index.d.ts.map +1 -0
  176. package/dist/index.js +202 -0
  177. package/dist/index.js.map +1 -0
  178. package/dist/interceptors.d.ts +251 -0
  179. package/dist/interceptors.d.ts.map +1 -0
  180. package/dist/interceptors.js +259 -0
  181. package/dist/interceptors.js.map +1 -0
  182. package/dist/junction.d.ts +99 -0
  183. package/dist/junction.d.ts.map +1 -0
  184. package/dist/junction.js +136 -0
  185. package/dist/junction.js.map +1 -0
  186. package/dist/knowledge.d.ts +11 -0
  187. package/dist/knowledge.d.ts.map +1 -0
  188. package/dist/knowledge.js +310 -0
  189. package/dist/knowledge.js.map +1 -0
  190. package/dist/lazy-config.d.ts +160 -0
  191. package/dist/lazy-config.d.ts.map +1 -0
  192. package/dist/lazy-config.js +146 -0
  193. package/dist/lazy-config.js.map +1 -0
  194. package/dist/manifest/discover-base-classes.d.ts +78 -0
  195. package/dist/manifest/discover-base-classes.d.ts.map +1 -0
  196. package/dist/manifest/discover-base-classes.js +85 -0
  197. package/dist/manifest/discover-base-classes.js.map +1 -0
  198. package/dist/manifest/discover-smrt-packages.d.ts +48 -0
  199. package/dist/manifest/discover-smrt-packages.d.ts.map +1 -0
  200. package/dist/manifest/discover-smrt-packages.js +361 -0
  201. package/dist/manifest/discover-smrt-packages.js.map +1 -0
  202. package/dist/manifest/generator.d.ts +93 -0
  203. package/dist/manifest/generator.d.ts.map +1 -0
  204. package/dist/manifest/generator.js +380 -0
  205. package/dist/manifest/generator.js.map +1 -0
  206. package/dist/manifest/index.d.ts +16 -0
  207. package/dist/manifest/index.d.ts.map +1 -0
  208. package/dist/manifest/index.js +51 -0
  209. package/dist/manifest/index.js.map +1 -0
  210. package/dist/manifest/manager.d.ts +51 -0
  211. package/dist/manifest/manager.d.ts.map +1 -0
  212. package/dist/manifest/manager.js +89 -0
  213. package/dist/manifest/manager.js.map +1 -0
  214. package/dist/manifest/manifest-loader.d.ts +187 -0
  215. package/dist/manifest/manifest-loader.d.ts.map +1 -0
  216. package/dist/manifest/manifest-loader.js +847 -0
  217. package/dist/manifest/manifest-loader.js.map +1 -0
  218. package/dist/manifest/sources/composite.d.ts +22 -0
  219. package/dist/manifest/sources/composite.d.ts.map +1 -0
  220. package/dist/manifest/sources/composite.js +60 -0
  221. package/dist/manifest/sources/composite.js.map +1 -0
  222. package/dist/manifest/sources/embedded.d.ts +7 -0
  223. package/dist/manifest/sources/embedded.d.ts.map +1 -0
  224. package/dist/manifest/sources/embedded.js +30 -0
  225. package/dist/manifest/sources/embedded.js.map +1 -0
  226. package/dist/manifest/sources/explicit-paths.d.ts +17 -0
  227. package/dist/manifest/sources/explicit-paths.d.ts.map +1 -0
  228. package/dist/manifest/sources/explicit-paths.js +35 -0
  229. package/dist/manifest/sources/explicit-paths.js.map +1 -0
  230. package/dist/manifest/sources/fallback.d.ts +25 -0
  231. package/dist/manifest/sources/fallback.d.ts.map +1 -0
  232. package/dist/manifest/sources/fallback.js +63 -0
  233. package/dist/manifest/sources/fallback.js.map +1 -0
  234. package/dist/manifest/sources/index.d.ts +17 -0
  235. package/dist/manifest/sources/index.d.ts.map +1 -0
  236. package/dist/manifest/sources/local-test.d.ts +7 -0
  237. package/dist/manifest/sources/local-test.d.ts.map +1 -0
  238. package/dist/manifest/sources/local-test.js +21 -0
  239. package/dist/manifest/sources/local-test.js.map +1 -0
  240. package/dist/manifest/sources/static.d.ts +7 -0
  241. package/dist/manifest/sources/static.d.ts.map +1 -0
  242. package/dist/manifest/sources/static.js +19 -0
  243. package/dist/manifest/sources/static.js.map +1 -0
  244. package/dist/manifest/sources/test.d.ts +7 -0
  245. package/dist/manifest/sources/test.d.ts.map +1 -0
  246. package/dist/manifest/sources/test.js +21 -0
  247. package/dist/manifest/sources/test.js.map +1 -0
  248. package/dist/manifest/sources/types.d.ts +79 -0
  249. package/dist/manifest/sources/types.d.ts.map +1 -0
  250. package/dist/manifest/sources/types.js +61 -0
  251. package/dist/manifest/sources/types.js.map +1 -0
  252. package/dist/manifest/static-manifest.d.ts +4 -0
  253. package/dist/manifest/static-manifest.d.ts.map +1 -0
  254. package/dist/manifest/static-manifest.js +1535 -0
  255. package/dist/manifest/static-manifest.js.map +1 -0
  256. package/dist/manifest/store.d.ts +111 -0
  257. package/dist/manifest/store.d.ts.map +1 -0
  258. package/dist/manifest/store.js +431 -0
  259. package/dist/manifest/store.js.map +1 -0
  260. package/dist/manifest/test-manifest-loader.d.ts +3 -0
  261. package/dist/manifest/test-manifest-loader.d.ts.map +1 -0
  262. package/dist/manifest/test-manifest-stub.d.ts +4 -0
  263. package/dist/manifest/test-manifest-stub.d.ts.map +1 -0
  264. package/dist/manifest/test-manifest-stub.js +80013 -0
  265. package/dist/manifest/test-manifest-stub.js.map +1 -0
  266. package/dist/manifest.d.ts +8 -0
  267. package/dist/manifest.d.ts.map +1 -0
  268. package/dist/manifest.js +20 -0
  269. package/dist/manifest.js.map +1 -0
  270. package/dist/manifest.json +1489 -0
  271. package/dist/mcp-advisor/index.d.ts +499 -0
  272. package/dist/mcp-advisor/index.d.ts.map +1 -0
  273. package/dist/mcp-advisor/tools/add-ai-methods.d.ts +6 -0
  274. package/dist/mcp-advisor/tools/add-ai-methods.d.ts.map +1 -0
  275. package/dist/mcp-advisor/tools/configure-decorators.d.ts +6 -0
  276. package/dist/mcp-advisor/tools/configure-decorators.d.ts.map +1 -0
  277. package/dist/mcp-advisor/tools/generate-collection.d.ts +6 -0
  278. package/dist/mcp-advisor/tools/generate-collection.d.ts.map +1 -0
  279. package/dist/mcp-advisor/tools/generate-field-definitions.d.ts +6 -0
  280. package/dist/mcp-advisor/tools/generate-field-definitions.d.ts.map +1 -0
  281. package/dist/mcp-advisor/tools/generate-smrt-class.d.ts +6 -0
  282. package/dist/mcp-advisor/tools/generate-smrt-class.d.ts.map +1 -0
  283. package/dist/mcp-advisor/tools/get-object-config.d.ts +6 -0
  284. package/dist/mcp-advisor/tools/get-object-config.d.ts.map +1 -0
  285. package/dist/mcp-advisor/tools/get-object-schema.d.ts +10 -0
  286. package/dist/mcp-advisor/tools/get-object-schema.d.ts.map +1 -0
  287. package/dist/mcp-advisor/tools/list-registered-objects.d.ts +9 -0
  288. package/dist/mcp-advisor/tools/list-registered-objects.d.ts.map +1 -0
  289. package/dist/mcp-advisor/tools/preview-api-endpoints.d.ts +9 -0
  290. package/dist/mcp-advisor/tools/preview-api-endpoints.d.ts.map +1 -0
  291. package/dist/mcp-advisor/tools/preview-mcp-tools.d.ts +9 -0
  292. package/dist/mcp-advisor/tools/preview-mcp-tools.d.ts.map +1 -0
  293. package/dist/mcp-advisor/tools/validate-smrt-object.d.ts +6 -0
  294. package/dist/mcp-advisor/tools/validate-smrt-object.d.ts.map +1 -0
  295. package/dist/mcp-advisor/types.d.ts +209 -0
  296. package/dist/mcp-advisor/types.d.ts.map +1 -0
  297. package/dist/migrations/backfill-tracker.d.ts +84 -0
  298. package/dist/migrations/backfill-tracker.d.ts.map +1 -0
  299. package/dist/migrations/backfill-tracker.js +118 -0
  300. package/dist/migrations/backfill-tracker.js.map +1 -0
  301. package/dist/migrations/checksum.d.ts +43 -0
  302. package/dist/migrations/checksum.d.ts.map +1 -0
  303. package/dist/migrations/checksum.js +32 -0
  304. package/dist/migrations/checksum.js.map +1 -0
  305. package/dist/migrations/differ.d.ts +186 -0
  306. package/dist/migrations/differ.d.ts.map +1 -0
  307. package/dist/migrations/differ.js +601 -0
  308. package/dist/migrations/differ.js.map +1 -0
  309. package/dist/migrations/generator.d.ts +133 -0
  310. package/dist/migrations/generator.d.ts.map +1 -0
  311. package/dist/migrations/generator.js +328 -0
  312. package/dist/migrations/generator.js.map +1 -0
  313. package/dist/migrations/index.d.ts +20 -0
  314. package/dist/migrations/index.d.ts.map +1 -0
  315. package/dist/migrations/orchestrate.d.ts +148 -0
  316. package/dist/migrations/orchestrate.d.ts.map +1 -0
  317. package/dist/migrations/orchestrate.js +118 -0
  318. package/dist/migrations/orchestrate.js.map +1 -0
  319. package/dist/migrations/tracker.d.ts +134 -0
  320. package/dist/migrations/tracker.d.ts.map +1 -0
  321. package/dist/migrations/tracker.js +624 -0
  322. package/dist/migrations/tracker.js.map +1 -0
  323. package/dist/migrations/types.d.ts +221 -0
  324. package/dist/migrations/types.d.ts.map +1 -0
  325. package/dist/migrations.d.ts +7 -0
  326. package/dist/migrations.d.ts.map +1 -0
  327. package/dist/migrations.js +26 -0
  328. package/dist/migrations.js.map +1 -0
  329. package/dist/node_modules/.pnpm/balanced-match@4.0.4/node_modules/balanced-match/dist/esm/index.js +56 -0
  330. package/dist/node_modules/.pnpm/balanced-match@4.0.4/node_modules/balanced-match/dist/esm/index.js.map +1 -0
  331. package/dist/node_modules/.pnpm/brace-expansion@5.0.5/node_modules/brace-expansion/dist/esm/index.js +163 -0
  332. package/dist/node_modules/.pnpm/brace-expansion@5.0.5/node_modules/brace-expansion/dist/esm/index.js.map +1 -0
  333. package/dist/node_modules/.pnpm/minimatch@10.2.3/node_modules/minimatch/dist/esm/assert-valid-pattern.js +13 -0
  334. package/dist/node_modules/.pnpm/minimatch@10.2.3/node_modules/minimatch/dist/esm/assert-valid-pattern.js.map +1 -0
  335. package/dist/node_modules/.pnpm/minimatch@10.2.3/node_modules/minimatch/dist/esm/ast.js +654 -0
  336. package/dist/node_modules/.pnpm/minimatch@10.2.3/node_modules/minimatch/dist/esm/ast.js.map +1 -0
  337. package/dist/node_modules/.pnpm/minimatch@10.2.3/node_modules/minimatch/dist/esm/brace-expressions.js +111 -0
  338. package/dist/node_modules/.pnpm/minimatch@10.2.3/node_modules/minimatch/dist/esm/brace-expressions.js.map +1 -0
  339. package/dist/node_modules/.pnpm/minimatch@10.2.3/node_modules/minimatch/dist/esm/escape.js +10 -0
  340. package/dist/node_modules/.pnpm/minimatch@10.2.3/node_modules/minimatch/dist/esm/escape.js.map +1 -0
  341. package/dist/node_modules/.pnpm/minimatch@10.2.3/node_modules/minimatch/dist/esm/index.js +824 -0
  342. package/dist/node_modules/.pnpm/minimatch@10.2.3/node_modules/minimatch/dist/esm/index.js.map +1 -0
  343. package/dist/node_modules/.pnpm/minimatch@10.2.3/node_modules/minimatch/dist/esm/unescape.js +10 -0
  344. package/dist/node_modules/.pnpm/minimatch@10.2.3/node_modules/minimatch/dist/esm/unescape.js.map +1 -0
  345. package/dist/object.d.ts +1202 -0
  346. package/dist/object.d.ts.map +1 -0
  347. package/dist/object.js +2731 -0
  348. package/dist/object.js.map +1 -0
  349. package/dist/polymorphic-association.d.ts +69 -0
  350. package/dist/polymorphic-association.d.ts.map +1 -0
  351. package/dist/polymorphic-association.js +96 -0
  352. package/dist/polymorphic-association.js.map +1 -0
  353. package/dist/prebuild/cli.d.ts +7 -0
  354. package/dist/prebuild/cli.d.ts.map +1 -0
  355. package/dist/prebuild/cli.js +29 -0
  356. package/dist/prebuild/cli.js.map +1 -0
  357. package/dist/prebuild/index.d.ts +22 -0
  358. package/dist/prebuild/index.d.ts.map +1 -0
  359. package/dist/prebuild/index.js +239 -0
  360. package/dist/prebuild/index.js.map +1 -0
  361. package/dist/prebuild.d.ts +8 -0
  362. package/dist/prebuild.d.ts.map +1 -0
  363. package/dist/prebuild.js +6 -0
  364. package/dist/prebuild.js.map +1 -0
  365. package/dist/registry/cache-config.d.ts +13 -0
  366. package/dist/registry/cache-config.d.ts.map +1 -0
  367. package/dist/registry/cache-config.js +17 -0
  368. package/dist/registry/cache-config.js.map +1 -0
  369. package/dist/registry/class-registration.d.ts +31 -0
  370. package/dist/registry/class-registration.d.ts.map +1 -0
  371. package/dist/registry/class-registration.js +1074 -0
  372. package/dist/registry/class-registration.js.map +1 -0
  373. package/dist/registry/collection-resolution.d.ts +45 -0
  374. package/dist/registry/collection-resolution.d.ts.map +1 -0
  375. package/dist/registry/collection-resolution.js +121 -0
  376. package/dist/registry/collection-resolution.js.map +1 -0
  377. package/dist/registry/collision-policy.d.ts +179 -0
  378. package/dist/registry/collision-policy.d.ts.map +1 -0
  379. package/dist/registry/collision-policy.js +153 -0
  380. package/dist/registry/collision-policy.js.map +1 -0
  381. package/dist/registry/diagnostics.d.ts +58 -0
  382. package/dist/registry/diagnostics.d.ts.map +1 -0
  383. package/dist/registry/diagnostics.js +54 -0
  384. package/dist/registry/diagnostics.js.map +1 -0
  385. package/dist/registry/embedding-manager.d.ts +23 -0
  386. package/dist/registry/embedding-manager.d.ts.map +1 -0
  387. package/dist/registry/embedding-manager.js +62 -0
  388. package/dist/registry/embedding-manager.js.map +1 -0
  389. package/dist/registry/index.d.ts +13 -0
  390. package/dist/registry/index.d.ts.map +1 -0
  391. package/dist/registry/inheritance-resolver.d.ts +13 -0
  392. package/dist/registry/inheritance-resolver.d.ts.map +1 -0
  393. package/dist/registry/inheritance-resolver.js +244 -0
  394. package/dist/registry/inheritance-resolver.js.map +1 -0
  395. package/dist/registry/manifest-field-merge.d.ts +4 -0
  396. package/dist/registry/manifest-field-merge.d.ts.map +1 -0
  397. package/dist/registry/manifest-field-merge.js +82 -0
  398. package/dist/registry/manifest-field-merge.js.map +1 -0
  399. package/dist/registry/name-resolver.d.ts +102 -0
  400. package/dist/registry/name-resolver.d.ts.map +1 -0
  401. package/dist/registry/name-resolver.js +241 -0
  402. package/dist/registry/name-resolver.js.map +1 -0
  403. package/dist/registry/relationship-graph.d.ts +16 -0
  404. package/dist/registry/relationship-graph.d.ts.map +1 -0
  405. package/dist/registry/relationship-graph.js +79 -0
  406. package/dist/registry/relationship-graph.js.map +1 -0
  407. package/dist/registry/schema-builder.d.ts +113 -0
  408. package/dist/registry/schema-builder.d.ts.map +1 -0
  409. package/dist/registry/schema-builder.js +474 -0
  410. package/dist/registry/schema-builder.js.map +1 -0
  411. package/dist/registry/shared-state.d.ts +62 -0
  412. package/dist/registry/shared-state.d.ts.map +1 -0
  413. package/dist/registry/shared-state.js +135 -0
  414. package/dist/registry/shared-state.js.map +1 -0
  415. package/dist/registry/types.d.ts +667 -0
  416. package/dist/registry/types.d.ts.map +1 -0
  417. package/dist/registry/validator.d.ts +13 -0
  418. package/dist/registry/validator.d.ts.map +1 -0
  419. package/dist/registry/validator.js +138 -0
  420. package/dist/registry/validator.js.map +1 -0
  421. package/dist/registry.d.ts +1358 -0
  422. package/dist/registry.d.ts.map +1 -0
  423. package/dist/registry.js +2301 -0
  424. package/dist/registry.js.map +1 -0
  425. package/dist/runtime/client.d.ts +34 -0
  426. package/dist/runtime/client.d.ts.map +1 -0
  427. package/dist/runtime/client.js +104 -0
  428. package/dist/runtime/client.js.map +1 -0
  429. package/dist/runtime/index.d.ts +10 -0
  430. package/dist/runtime/index.d.ts.map +1 -0
  431. package/dist/runtime/mcp.d.ts +47 -0
  432. package/dist/runtime/mcp.d.ts.map +1 -0
  433. package/dist/runtime/mcp.js +72 -0
  434. package/dist/runtime/mcp.js.map +1 -0
  435. package/dist/runtime/server.d.ts +92 -0
  436. package/dist/runtime/server.d.ts.map +1 -0
  437. package/dist/runtime/server.js +390 -0
  438. package/dist/runtime/server.js.map +1 -0
  439. package/dist/runtime/types.d.ts +58 -0
  440. package/dist/runtime/types.d.ts.map +1 -0
  441. package/dist/runtime.d.ts +8 -0
  442. package/dist/runtime.d.ts.map +1 -0
  443. package/dist/runtime.js +10 -0
  444. package/dist/runtime.js.map +1 -0
  445. package/dist/scanner/import-scanner.d.ts +7 -0
  446. package/dist/scanner/import-scanner.d.ts.map +1 -0
  447. package/dist/scanner/index.d.ts +12 -0
  448. package/dist/scanner/index.d.ts.map +1 -0
  449. package/dist/scanner/manifest-generator.d.ts +304 -0
  450. package/dist/scanner/manifest-generator.d.ts.map +1 -0
  451. package/dist/scanner/manifest-generator.js +1707 -0
  452. package/dist/scanner/manifest-generator.js.map +1 -0
  453. package/dist/scanner/test-file-patterns.d.ts +18 -0
  454. package/dist/scanner/test-file-patterns.d.ts.map +1 -0
  455. package/dist/scanner/test-file-patterns.js +16 -0
  456. package/dist/scanner/test-file-patterns.js.map +1 -0
  457. package/dist/scanner/types.d.ts +313 -0
  458. package/dist/scanner/types.d.ts.map +1 -0
  459. package/dist/scanner/types.js +2 -0
  460. package/dist/scanner/types.js.map +1 -0
  461. package/dist/scanner.d.ts +6 -0
  462. package/dist/scanner.d.ts.map +1 -0
  463. package/dist/scanner.js +6 -0
  464. package/dist/scanner.js.map +1 -0
  465. package/dist/schema/code-generator.d.ts +53 -0
  466. package/dist/schema/code-generator.d.ts.map +1 -0
  467. package/dist/schema/ddl/base-strategy.d.ts +80 -0
  468. package/dist/schema/ddl/base-strategy.d.ts.map +1 -0
  469. package/dist/schema/ddl/base-strategy.js +240 -0
  470. package/dist/schema/ddl/base-strategy.js.map +1 -0
  471. package/dist/schema/ddl/duckdb-strategy.d.ts +33 -0
  472. package/dist/schema/ddl/duckdb-strategy.d.ts.map +1 -0
  473. package/dist/schema/ddl/duckdb-strategy.js +74 -0
  474. package/dist/schema/ddl/duckdb-strategy.js.map +1 -0
  475. package/dist/schema/ddl/index.d.ts +53 -0
  476. package/dist/schema/ddl/index.d.ts.map +1 -0
  477. package/dist/schema/ddl/index.js +80 -0
  478. package/dist/schema/ddl/index.js.map +1 -0
  479. package/dist/schema/ddl/json-duckdb-strategy.d.ts +8 -0
  480. package/dist/schema/ddl/json-duckdb-strategy.d.ts.map +1 -0
  481. package/dist/schema/ddl/json-duckdb-strategy.js +14 -0
  482. package/dist/schema/ddl/json-duckdb-strategy.js.map +1 -0
  483. package/dist/schema/ddl/postgres-strategy.d.ts +29 -0
  484. package/dist/schema/ddl/postgres-strategy.d.ts.map +1 -0
  485. package/dist/schema/ddl/postgres-strategy.js +102 -0
  486. package/dist/schema/ddl/postgres-strategy.js.map +1 -0
  487. package/dist/schema/ddl/sqlite-strategy.d.ts +38 -0
  488. package/dist/schema/ddl/sqlite-strategy.d.ts.map +1 -0
  489. package/dist/schema/ddl/sqlite-strategy.js +74 -0
  490. package/dist/schema/ddl/sqlite-strategy.js.map +1 -0
  491. package/dist/schema/ddl/types.d.ts +114 -0
  492. package/dist/schema/ddl/types.d.ts.map +1 -0
  493. package/dist/schema/generator.d.ts +176 -0
  494. package/dist/schema/generator.d.ts.map +1 -0
  495. package/dist/schema/generator.js +1076 -0
  496. package/dist/schema/generator.js.map +1 -0
  497. package/dist/schema/index-utils.d.ts +19 -0
  498. package/dist/schema/index-utils.d.ts.map +1 -0
  499. package/dist/schema/index-utils.js +32 -0
  500. package/dist/schema/index-utils.js.map +1 -0
  501. package/dist/schema/index.d.ts +13 -0
  502. package/dist/schema/index.d.ts.map +1 -0
  503. package/dist/schema/override-system.d.ts +43 -0
  504. package/dist/schema/override-system.d.ts.map +1 -0
  505. package/dist/schema/schema-aggregator.d.ts +112 -0
  506. package/dist/schema/schema-aggregator.d.ts.map +1 -0
  507. package/dist/schema/schema-manager.d.ts +95 -0
  508. package/dist/schema/schema-manager.d.ts.map +1 -0
  509. package/dist/schema/schema-manager.js +283 -0
  510. package/dist/schema/schema-manager.js.map +1 -0
  511. package/dist/schema/sql-identifiers.d.ts +107 -0
  512. package/dist/schema/sql-identifiers.d.ts.map +1 -0
  513. package/dist/schema/sql-identifiers.js +190 -0
  514. package/dist/schema/sql-identifiers.js.map +1 -0
  515. package/dist/schema/table-verifier.d.ts +10 -0
  516. package/dist/schema/table-verifier.d.ts.map +1 -0
  517. package/dist/schema/table-verifier.js +37 -0
  518. package/dist/schema/table-verifier.js.map +1 -0
  519. package/dist/schema/types.d.ts +241 -0
  520. package/dist/schema/types.d.ts.map +1 -0
  521. package/dist/schema/utils.d.ts +32 -0
  522. package/dist/schema/utils.d.ts.map +1 -0
  523. package/dist/schema/utils.js +134 -0
  524. package/dist/schema/utils.js.map +1 -0
  525. package/dist/scripts/create-wrappers.js +89 -0
  526. package/dist/scripts/generate-manifest.js +155 -0
  527. package/dist/scripts/generate-test-manifest.js +77 -0
  528. package/dist/scripts/migrate-datetime-to-timestamp.ts +310 -0
  529. package/dist/scripts/prepack.js +49 -0
  530. package/dist/signals/bus.d.ts +64 -0
  531. package/dist/signals/bus.d.ts.map +1 -0
  532. package/dist/signals/bus.js +102 -0
  533. package/dist/signals/bus.js.map +1 -0
  534. package/dist/signals/index.d.ts +11 -0
  535. package/dist/signals/index.d.ts.map +1 -0
  536. package/dist/signals/sanitizer.d.ts +54 -0
  537. package/dist/signals/sanitizer.d.ts.map +1 -0
  538. package/dist/signals/sanitizer.js +111 -0
  539. package/dist/signals/sanitizer.js.map +1 -0
  540. package/dist/smrt-knowledge.json +335 -0
  541. package/dist/system/compatibility.d.ts +8 -0
  542. package/dist/system/compatibility.d.ts.map +1 -0
  543. package/dist/system/compatibility.js +409 -0
  544. package/dist/system/compatibility.js.map +1 -0
  545. package/dist/system/index.d.ts +9 -0
  546. package/dist/system/index.d.ts.map +1 -0
  547. package/dist/system/schema.d.ts +69 -0
  548. package/dist/system/schema.d.ts.map +1 -0
  549. package/dist/system/schema.js +271 -0
  550. package/dist/system/schema.js.map +1 -0
  551. package/dist/system/types.d.ts +135 -0
  552. package/dist/system/types.d.ts.map +1 -0
  553. package/dist/system-fields.d.ts +44 -0
  554. package/dist/system-fields.d.ts.map +1 -0
  555. package/dist/system-fields.js +55 -0
  556. package/dist/system-fields.js.map +1 -0
  557. package/dist/table-cache.d.ts +28 -0
  558. package/dist/table-cache.d.ts.map +1 -0
  559. package/dist/table-cache.js +21 -0
  560. package/dist/table-cache.js.map +1 -0
  561. package/dist/test-utils.d.ts +140 -0
  562. package/dist/test-utils.d.ts.map +1 -0
  563. package/dist/testing/database.d.ts +73 -0
  564. package/dist/testing/database.d.ts.map +1 -0
  565. package/dist/testing/database.js +204 -0
  566. package/dist/testing/database.js.map +1 -0
  567. package/dist/testing/index.d.ts +21 -0
  568. package/dist/testing/index.d.ts.map +1 -0
  569. package/dist/testing.d.ts +6 -0
  570. package/dist/testing.d.ts.map +1 -0
  571. package/dist/testing.js +5 -0
  572. package/dist/testing.js.map +1 -0
  573. package/dist/tools/index.d.ts +8 -0
  574. package/dist/tools/index.d.ts.map +1 -0
  575. package/dist/tools/tool-executor.d.ts +101 -0
  576. package/dist/tools/tool-executor.d.ts.map +1 -0
  577. package/dist/tools/tool-executor.js +142 -0
  578. package/dist/tools/tool-executor.js.map +1 -0
  579. package/dist/tools/tool-generator.d.ts +54 -0
  580. package/dist/tools/tool-generator.d.ts.map +1 -0
  581. package/dist/tools/tool-generator.js +121 -0
  582. package/dist/tools/tool-generator.js.map +1 -0
  583. package/dist/utils/chunk.d.ts +32 -0
  584. package/dist/utils/chunk.d.ts.map +1 -0
  585. package/dist/utils/chunk.js +14 -0
  586. package/dist/utils/chunk.js.map +1 -0
  587. package/dist/utils/import-workspace-module.d.ts +8 -0
  588. package/dist/utils/import-workspace-module.d.ts.map +1 -0
  589. package/dist/utils/import-workspace-module.js +81 -0
  590. package/dist/utils/import-workspace-module.js.map +1 -0
  591. package/dist/utils/json.d.ts +102 -0
  592. package/dist/utils/json.d.ts.map +1 -0
  593. package/dist/utils/json.js +43 -0
  594. package/dist/utils/json.js.map +1 -0
  595. package/dist/utils/lru-cache.d.ts +69 -0
  596. package/dist/utils/lru-cache.d.ts.map +1 -0
  597. package/dist/utils/lru-cache.js +100 -0
  598. package/dist/utils/lru-cache.js.map +1 -0
  599. package/dist/utils/naming.d.ts +16 -0
  600. package/dist/utils/naming.d.ts.map +1 -0
  601. package/dist/utils/naming.js +23 -0
  602. package/dist/utils/naming.js.map +1 -0
  603. package/dist/utils/qualified-names.d.ts +122 -0
  604. package/dist/utils/qualified-names.d.ts.map +1 -0
  605. package/dist/utils/qualified-names.js +82 -0
  606. package/dist/utils/qualified-names.js.map +1 -0
  607. package/dist/utils/scanner-module.d.ts +37 -0
  608. package/dist/utils/scanner-module.d.ts.map +1 -0
  609. package/dist/utils.d.ts +177 -0
  610. package/dist/utils.d.ts.map +1 -0
  611. package/dist/utils.js +185 -0
  612. package/dist/utils.js.map +1 -0
  613. package/dist/vite-plugin/import-build-aware.d.ts +68 -0
  614. package/dist/vite-plugin/import-build-aware.d.ts.map +1 -0
  615. package/dist/vite-plugin/import-build-aware.js +72 -0
  616. package/dist/vite-plugin/import-build-aware.js.map +1 -0
  617. package/dist/vite-plugin/index.d.ts +59 -0
  618. package/dist/vite-plugin/index.d.ts.map +1 -0
  619. package/dist/vite-plugin/index.js +1400 -0
  620. package/dist/vite-plugin/index.js.map +1 -0
  621. package/dist/vite-plugin/sveltekit-generator.d.ts +66 -0
  622. package/dist/vite-plugin/sveltekit-generator.d.ts.map +1 -0
  623. package/dist/vite-plugin/sveltekit-generator.js +1375 -0
  624. package/dist/vite-plugin/sveltekit-generator.js.map +1 -0
  625. package/dist/vite-plugin/templates/default-ui.ts +432 -0
  626. package/dist/vite-plugin/templates/default.html +206 -0
  627. package/dist/vite-plugin.d.ts +8 -0
  628. package/dist/vite-plugin.d.ts.map +1 -0
  629. package/dist/vite-plugin.js +11 -0
  630. package/dist/vite-plugin.js.map +1 -0
  631. package/package.json +208 -0
@@ -0,0 +1,1707 @@
1
+ import { createHash } from "node:crypto";
2
+ import { createRequire } from "node:module";
3
+ import { loadExternalManifestSync, lookupInManifest } from "../manifest/manifest-loader.js";
4
+ import { SchemaGenerator } from "../schema/generator.js";
5
+ import { generateToolManifest } from "../tools/tool-generator.js";
6
+ import { toSnakeCase, classnameToTablename } from "../utils/naming.js";
7
+ import { createQualifiedName } from "../utils/qualified-names.js";
8
+ import { isTestFile } from "./test-file-patterns.js";
9
+ const require$1 = createRequire(import.meta.url);
10
+ const FRAMEWORK_ABSTRACT_BASE_NAMES = /* @__PURE__ */ new Set([
11
+ "SmrtJunction",
12
+ "SmrtHierarchical",
13
+ "SmrtPolymorphicAssociation"
14
+ ]);
15
+ function inferVisibility(filePath, explicitVisibility) {
16
+ if (explicitVisibility) return explicitVisibility;
17
+ if (isTestFile(filePath)) return "test";
18
+ return "public";
19
+ }
20
+ class ManifestGenerator {
21
+ /**
22
+ * Generate manifest from scan results
23
+ *
24
+ * @param scanResults - Array of scan results containing object definitions
25
+ * @param options - Optional configuration
26
+ * @param options.packageName - Package name to inject into manifest and object definitions
27
+ * @param options.packageVersion - Package version
28
+ * @param options.packageJson - Full package.json object for determining import paths
29
+ * @param options.smrtDependencies - List of SMRT package dependencies to include in manifest
30
+ * @param options.includeVisibility - Array of visibility levels to include (default: all)
31
+ * - For published packages: ['public']
32
+ * - For development: ['public', 'internal', 'test'] or omit for all
33
+ */
34
+ generateManifest(scanResults, options) {
35
+ const manifest = {
36
+ version: "1.0.0",
37
+ timestamp: Date.now(),
38
+ objects: {}
39
+ };
40
+ if (options?.packageName) {
41
+ manifest.packageName = options.packageName;
42
+ }
43
+ if (options?.packageVersion) {
44
+ manifest.packageVersion = options.packageVersion;
45
+ }
46
+ if (options?.smrtDependencies) {
47
+ manifest.smrtDependencies = options.smrtDependencies;
48
+ }
49
+ for (const result of scanResults) {
50
+ for (const objectDef of result.objects) {
51
+ if (options?.packageName) {
52
+ objectDef.packageName = options.packageName;
53
+ }
54
+ if (options?.packageVersion) {
55
+ objectDef.packageVersion = options.packageVersion;
56
+ }
57
+ if (objectDef.packageName) {
58
+ objectDef.qualifiedName = createQualifiedName(
59
+ objectDef.packageName,
60
+ objectDef.className
61
+ );
62
+ }
63
+ objectDef.visibility = inferVisibility(
64
+ objectDef.filePath,
65
+ objectDef.decoratorConfig?.visibility
66
+ );
67
+ if (options?.includeVisibility && options.includeVisibility.length > 0 && !options.includeVisibility.includes(objectDef.visibility)) {
68
+ continue;
69
+ }
70
+ if (options?.packageName && options?.packageJson) {
71
+ objectDef.importPath = this.determineImportPath(
72
+ options.packageJson,
73
+ objectDef.filePath
74
+ );
75
+ }
76
+ objectDef.exportName = objectDef.exportName || objectDef.className;
77
+ objectDef.collectionExportName = objectDef.collectionExportName || `${objectDef.className}Collection`;
78
+ if (objectDef.decoratorConfig.ai) {
79
+ const methods = Object.values(objectDef.methods);
80
+ const tools = generateToolManifest(
81
+ methods,
82
+ objectDef.decoratorConfig.ai
83
+ );
84
+ if (tools.length > 0) {
85
+ objectDef.tools = tools;
86
+ }
87
+ }
88
+ const manifestKey = objectDef.qualifiedName || objectDef.name;
89
+ if (manifest.objects[manifestKey]) {
90
+ const existing = manifest.objects[manifestKey];
91
+ throw new Error(
92
+ `Class name collision detected: '${objectDef.className}' (${manifestKey}) is defined in multiple files:
93
+ 1. ${existing.filePath}
94
+ 2. ${objectDef.filePath}
95
+
96
+ Class names must be unique within a package. Use different class names or separate packages.`
97
+ );
98
+ }
99
+ manifest.objects[manifestKey] = objectDef;
100
+ }
101
+ }
102
+ this.injectTenantScopedFields(manifest);
103
+ this.mergeInheritedFields(manifest);
104
+ this.generateValidationRules(manifest);
105
+ this.generateSchemas(manifest);
106
+ this.assertTenantScopedSchemaContract(manifest);
107
+ this.generateAgentManifests(
108
+ manifest,
109
+ options?.packageName,
110
+ options?.packageJson
111
+ );
112
+ return manifest;
113
+ }
114
+ /**
115
+ * Materialize tenantScoped schema fields.
116
+ *
117
+ * Runtime registration already injects tenant fields for
118
+ * `@smrt({ tenantScoped: true })`, but published manifests must contain the
119
+ * same field before schema generation so migrations create `tenant_id`.
120
+ */
121
+ injectTenantScopedFields(manifest) {
122
+ for (const objectDef of Object.values(manifest.objects)) {
123
+ this.injectTenantScopedField(objectDef);
124
+ }
125
+ }
126
+ injectTenantScopedField(objectDef) {
127
+ const tenantScoped = objectDef.decoratorConfig?.tenantScoped;
128
+ if (!tenantScoped) {
129
+ return;
130
+ }
131
+ const { tenantConfig, tenantOptions } = this.normalizeTenantScopedConfig(tenantScoped);
132
+ const fieldName = tenantConfig.field;
133
+ const existingField = objectDef.fields[fieldName];
134
+ const tenancyMeta = {
135
+ isTenantIdField: true,
136
+ ...tenantConfig
137
+ };
138
+ if (existingField) {
139
+ const fieldTypeFailure = this.getTenantScopedFieldTypeFailure(
140
+ objectDef,
141
+ fieldName
142
+ );
143
+ if (fieldTypeFailure) {
144
+ throw new Error(
145
+ `Tenant-scoped field configuration invalid: ${fieldTypeFailure}`
146
+ );
147
+ }
148
+ existingField._meta = {
149
+ ...existingField._meta,
150
+ sqlType: "UUID",
151
+ __tenancy: {
152
+ ...existingField._meta?.__tenancy,
153
+ ...tenancyMeta
154
+ }
155
+ };
156
+ return;
157
+ }
158
+ objectDef.fields[fieldName] = {
159
+ type: "text",
160
+ // Preserve legacy migration behavior: boolean `tenantScoped: true`
161
+ // enables required-mode runtime scoping, but does not add a NOT NULL
162
+ // column to existing tables unless mode is explicitly set.
163
+ required: tenantOptions.mode === "required",
164
+ _meta: {
165
+ generated: true,
166
+ source: "tenantScoped_decorator",
167
+ sqlType: "UUID",
168
+ __tenancy: tenancyMeta
169
+ }
170
+ };
171
+ console.log(
172
+ `[manifest-generator] Injected ${fieldName} field for ${objectDef.className} (tenantScoped: ${JSON.stringify(tenantConfig)})`
173
+ );
174
+ }
175
+ assertTenantScopedSchemaContract(manifest) {
176
+ const failures = [];
177
+ for (const objectDef of Object.values(manifest.objects)) {
178
+ const tenantScoped = objectDef.decoratorConfig?.tenantScoped;
179
+ if (!tenantScoped) {
180
+ continue;
181
+ }
182
+ const { tenantConfig } = this.normalizeTenantScopedConfig(tenantScoped);
183
+ const fieldName = tenantConfig.field;
184
+ const columnName = toSnakeCase(fieldName);
185
+ if (!objectDef.fields[fieldName]) {
186
+ failures.push(
187
+ `${objectDef.className}: missing tenant-scoped field "${fieldName}"`
188
+ );
189
+ continue;
190
+ }
191
+ const fieldTypeFailure = this.getTenantScopedFieldTypeFailure(
192
+ objectDef,
193
+ fieldName
194
+ );
195
+ if (fieldTypeFailure) {
196
+ failures.push(fieldTypeFailure);
197
+ continue;
198
+ }
199
+ const schemaOwner = this.getTenantScopedSchemaOwner(objectDef, manifest);
200
+ const schemaOwnerContext = schemaOwner === objectDef ? "" : ` on STI base "${schemaOwner.className}"`;
201
+ if (!schemaOwner.schema?.columns) {
202
+ failures.push(
203
+ `${objectDef.className}: schema has not been generated for tenant-scoped column "${columnName}"${schemaOwnerContext}`
204
+ );
205
+ continue;
206
+ }
207
+ if (!schemaOwner.schema.columns[columnName]) {
208
+ failures.push(
209
+ `${objectDef.className}: schema is missing tenant-scoped column "${columnName}"${schemaOwnerContext}`
210
+ );
211
+ }
212
+ }
213
+ if (failures.length > 0) {
214
+ throw new Error(
215
+ `Tenant-scoped schema contract failed:
216
+ ${failures.map((failure) => ` - ${failure}`).join("\n")}`
217
+ );
218
+ }
219
+ }
220
+ getTenantScopedSchemaOwner(objectDef, manifest) {
221
+ if (!this.isSTIChildClass(objectDef, manifest)) {
222
+ return objectDef;
223
+ }
224
+ const stiBase = this.findSTIBaseInfo(objectDef, manifest);
225
+ if (!stiBase) {
226
+ return objectDef;
227
+ }
228
+ const localBase = Object.values(manifest.objects).find(
229
+ (candidate) => candidate.className === stiBase.className
230
+ );
231
+ return localBase ?? objectDef;
232
+ }
233
+ getTenantScopedFieldTypeFailure(objectDef, fieldName) {
234
+ const field = objectDef.fields[fieldName];
235
+ if (!field) {
236
+ return void 0;
237
+ }
238
+ if (field.type !== "text" && field.type !== "foreignKey") {
239
+ return `${objectDef.className}: tenant-scoped field "${fieldName}" must use type "text" or "foreignKey"; received "${field.type}"`;
240
+ }
241
+ const sqlType = field._meta?.sqlType;
242
+ if (sqlType && !["TEXT", "UUID"].includes(String(sqlType).toUpperCase())) {
243
+ return `${objectDef.className}: tenant-scoped field "${fieldName}" must use SQL type "UUID" or legacy "TEXT"; received "${sqlType}"`;
244
+ }
245
+ return void 0;
246
+ }
247
+ normalizeTenantScopedConfig(tenantScoped) {
248
+ const tenantOptions = typeof tenantScoped === "boolean" ? {} : tenantScoped;
249
+ return {
250
+ tenantOptions,
251
+ tenantConfig: {
252
+ mode: tenantOptions.mode ?? "required",
253
+ field: tenantOptions.field ?? "tenantId",
254
+ autoFilter: tenantOptions.autoFilter ?? true,
255
+ autoPopulate: tenantOptions.autoPopulate ?? true,
256
+ allowSuperAdminBypass: tenantOptions.allowSuperAdminBypass ?? false
257
+ }
258
+ };
259
+ }
260
+ /**
261
+ * Generate pre-computed validation rules for all objects in the manifest.
262
+ *
263
+ * This extracts validation constraints (required, min, max, minLength, maxLength, pattern)
264
+ * from field definitions and stores them as serializable rules in the manifest.
265
+ *
266
+ * At runtime, these rules can be evaluated without creating validator closures,
267
+ * significantly reducing CLI startup time for projects with many SMRT objects.
268
+ *
269
+ * @param manifest - The manifest to process in-place
270
+ */
271
+ generateValidationRules(manifest) {
272
+ for (const [name, obj] of Object.entries(manifest.objects)) {
273
+ const rules = [];
274
+ for (const [fieldName, field] of Object.entries(obj.fields)) {
275
+ if (field.transient || field._meta?.transient) {
276
+ continue;
277
+ }
278
+ const options = field._meta || {};
279
+ if (options.required || field.required) {
280
+ rules.push({
281
+ field: fieldName,
282
+ rule: "required",
283
+ fieldType: field.type
284
+ });
285
+ }
286
+ if (field.type === "integer" || field.type === "decimal") {
287
+ if (options.min !== void 0 || field.min !== void 0) {
288
+ rules.push({
289
+ field: fieldName,
290
+ rule: "min",
291
+ value: options.min ?? field.min,
292
+ fieldType: field.type
293
+ });
294
+ }
295
+ if (options.max !== void 0 || field.max !== void 0) {
296
+ rules.push({
297
+ field: fieldName,
298
+ rule: "max",
299
+ value: options.max ?? field.max,
300
+ fieldType: field.type
301
+ });
302
+ }
303
+ }
304
+ if (field.type === "text") {
305
+ if (options.minLength !== void 0 || field.minLength !== void 0) {
306
+ rules.push({
307
+ field: fieldName,
308
+ rule: "minLength",
309
+ value: options.minLength ?? field.minLength,
310
+ fieldType: field.type
311
+ });
312
+ }
313
+ if (options.maxLength !== void 0 || field.maxLength !== void 0) {
314
+ rules.push({
315
+ field: fieldName,
316
+ rule: "maxLength",
317
+ value: options.maxLength ?? field.maxLength,
318
+ fieldType: field.type
319
+ });
320
+ }
321
+ const pattern = options.pattern;
322
+ if (pattern) {
323
+ rules.push({
324
+ field: fieldName,
325
+ rule: "pattern",
326
+ value: typeof pattern === "string" ? pattern : pattern.source,
327
+ fieldType: field.type
328
+ });
329
+ }
330
+ }
331
+ }
332
+ if (rules.length > 0) {
333
+ obj.validationRules = rules;
334
+ }
335
+ }
336
+ }
337
+ /**
338
+ * Generate pre-computed schemas for all objects in the manifest.
339
+ *
340
+ * This enables external package consumers to use pre-generated schemas
341
+ * without calling generateSchema() at runtime, eliminating latency.
342
+ *
343
+ * IMPORTANT: For STI classes, we aggregate ALL descendants from both local
344
+ * and external packages to ensure complete schemas are generated.
345
+ *
346
+ * This method is public to allow external callers (like OXC scanner) to use it.
347
+ *
348
+ * @param manifest - The manifest to process in-place
349
+ */
350
+ generateSchemas(manifest) {
351
+ const generator = new SchemaGenerator();
352
+ const aggregatedManifest = this.createAggregatedManifest(manifest);
353
+ const processedSTIBases = /* @__PURE__ */ new Set();
354
+ const localObjects = new Set(
355
+ Object.values(manifest.objects).map((o) => o.className)
356
+ );
357
+ for (const [name, obj] of Object.entries(manifest.objects)) {
358
+ const tableName = obj.decoratorConfig?.tableName || this.classNameToTableName(obj.className);
359
+ if (obj.decoratorConfig?.tableStrategy === "sti") {
360
+ if (processedSTIBases.has(name)) continue;
361
+ processedSTIBases.add(name);
362
+ console.log(
363
+ `[manifest-generator] Generating STI schema for ${name} (table: ${tableName})`
364
+ );
365
+ obj.schema = generator.generateSTISchemaFromManifest(
366
+ name,
367
+ tableName,
368
+ obj.fields,
369
+ aggregatedManifest,
370
+ obj.decoratorConfig
371
+ );
372
+ this.applySqlTypeOverrides(obj);
373
+ } else if (this.isSTIChildClass(obj, manifest)) {
374
+ const stiBase = this.findSTIBaseInfo(obj, manifest);
375
+ const baseIsLocal = stiBase && localObjects.has(stiBase.className);
376
+ if (baseIsLocal) {
377
+ console.log(
378
+ `[manifest-generator] Skipping schema for STI child ${name} (base ${stiBase?.className} is local)`
379
+ );
380
+ } else {
381
+ const baseTableName = stiBase?.tableName || tableName;
382
+ console.log(
383
+ `[manifest-generator] Generating STI schema for ${name} (external base: ${stiBase?.className}, table: ${baseTableName})`
384
+ );
385
+ obj.schema = generator.generateSTISchemaFromManifest(
386
+ stiBase?.className || name,
387
+ baseTableName,
388
+ obj.fields,
389
+ aggregatedManifest,
390
+ obj.decoratorConfig
391
+ );
392
+ this.applySqlTypeOverrides(obj);
393
+ }
394
+ } else {
395
+ console.log(
396
+ `[manifest-generator] Generating CTI schema for ${name} (table: ${tableName})`
397
+ );
398
+ obj.schema = generator.generateCTISchemaFromManifest(
399
+ name,
400
+ tableName,
401
+ obj.fields,
402
+ obj.decoratorConfig
403
+ );
404
+ this.applySqlTypeOverrides(obj);
405
+ }
406
+ }
407
+ this.resolveSamePackageForeignKeyColumnTypes(manifest, generator);
408
+ }
409
+ resolveSamePackageForeignKeyColumnTypes(manifest, generator) {
410
+ const schemaByTable = /* @__PURE__ */ new Map();
411
+ const ownerBySchema = /* @__PURE__ */ new Map();
412
+ const changedSchemas = /* @__PURE__ */ new Set();
413
+ for (const [name, obj] of Object.entries(manifest.objects)) {
414
+ if (obj.schema?.tableName) {
415
+ schemaByTable.set(obj.schema.tableName, obj.schema);
416
+ ownerBySchema.set(obj.schema, { name, obj });
417
+ }
418
+ }
419
+ for (const obj of Object.values(manifest.objects)) {
420
+ const sourceTable = this.getObjectTableName(obj);
421
+ if (!sourceTable) {
422
+ continue;
423
+ }
424
+ const sourceSchema = schemaByTable.get(sourceTable);
425
+ if (!sourceSchema) {
426
+ continue;
427
+ }
428
+ for (const [fieldName, field] of Object.entries(obj.fields || {})) {
429
+ if (field.type !== "foreignKey" || !field.related || field._meta?.sqlType) {
430
+ continue;
431
+ }
432
+ const columnName = toSnakeCase(fieldName);
433
+ const sourceColumn = sourceSchema.columns[columnName];
434
+ if (!sourceColumn) {
435
+ continue;
436
+ }
437
+ const targetSchema = this.findForeignKeyTargetSchema(
438
+ field.related,
439
+ manifest,
440
+ schemaByTable
441
+ );
442
+ const targetIdType = targetSchema?.columns.id?.type;
443
+ if (!targetIdType || sourceColumn.type === targetIdType) {
444
+ continue;
445
+ }
446
+ sourceSchema.columns[columnName] = {
447
+ ...sourceColumn,
448
+ type: targetIdType
449
+ };
450
+ changedSchemas.add(sourceSchema);
451
+ }
452
+ }
453
+ for (const schema of changedSchemas) {
454
+ this.refreshManifestSchemaDDL(
455
+ schema,
456
+ generator,
457
+ ownerBySchema.get(schema),
458
+ manifest
459
+ );
460
+ }
461
+ }
462
+ findForeignKeyTargetSchema(related, manifest, schemaByTable) {
463
+ const relatedTarget = related.split(".")[0];
464
+ if (schemaByTable.has(relatedTarget)) {
465
+ return schemaByTable.get(relatedTarget);
466
+ }
467
+ const targetObj = Object.values(manifest.objects).find(
468
+ (candidate) => candidate.className === relatedTarget || candidate.qualifiedName === relatedTarget || candidate.name === relatedTarget || candidate.decoratorConfig?.tableName === relatedTarget || candidate.schema?.tableName === relatedTarget
469
+ );
470
+ if (!targetObj && relatedTarget.includes(":")) {
471
+ return void 0;
472
+ }
473
+ const targetTable = targetObj ? this.getObjectTableName(targetObj) : this.classNameToTableName(relatedTarget);
474
+ return targetTable ? schemaByTable.get(targetTable) : void 0;
475
+ }
476
+ getObjectTableName(obj) {
477
+ return obj.schema?.tableName || obj.decoratorConfig?.tableName || this.classNameToTableName(obj.className);
478
+ }
479
+ refreshManifestSchemaDDL(schema, generator, owner, manifest) {
480
+ const schemaDefinition = {
481
+ tableName: schema.tableName,
482
+ columns: Object.fromEntries(
483
+ Object.entries(schema.columns).map(([name, column]) => [
484
+ name,
485
+ {
486
+ type: column.type,
487
+ primaryKey: column.primaryKey,
488
+ notNull: column.notNull,
489
+ unique: column.unique,
490
+ defaultValue: column.default
491
+ }
492
+ ])
493
+ ),
494
+ indexes: (schema.indexes || []).map((index) => ({
495
+ name: index.name,
496
+ columns: index.columns,
497
+ unique: index.unique,
498
+ where: index.where,
499
+ jsonPath: index.jsonPath
500
+ })),
501
+ triggers: [],
502
+ foreignKeys: [],
503
+ dependencies: [],
504
+ version: schema.version,
505
+ packageName: ""
506
+ };
507
+ schema.ddl = generator.generateSQL(schemaDefinition);
508
+ schema.version = this.computeManifestSchemaVersion(schema, owner, manifest);
509
+ }
510
+ computeManifestSchemaVersion(schema, owner, manifest) {
511
+ if (schema.columns._meta_type && owner) {
512
+ const baseClassName = owner.obj.decoratorConfig?.tableStrategy === "sti" ? owner.name : this.findSTIBaseInfo(owner.obj, manifest)?.className || owner.name;
513
+ return createHash("sha256").update(
514
+ JSON.stringify({
515
+ columns: schema.columns,
516
+ baseClassName,
517
+ descendants: this.findDescendantsInManifest(
518
+ baseClassName,
519
+ manifest
520
+ )
521
+ })
522
+ ).digest("hex").substring(0, 8);
523
+ }
524
+ return createHash("sha256").update(
525
+ JSON.stringify({
526
+ columns: schema.columns,
527
+ className: owner?.name || schema.tableName
528
+ })
529
+ ).digest("hex").substring(0, 8);
530
+ }
531
+ findDescendantsInManifest(baseClassName, manifest, visited = /* @__PURE__ */ new Set()) {
532
+ const descendants = [];
533
+ if (visited.has(baseClassName)) {
534
+ return descendants;
535
+ }
536
+ visited.add(baseClassName);
537
+ const baseClassLower = this.simpleClassName(baseClassName).toLowerCase();
538
+ for (const [name, obj] of Object.entries(manifest.objects)) {
539
+ const classNameLower = this.simpleClassName(obj.className).toLowerCase();
540
+ const extendsLower = obj.extends ? this.simpleClassName(obj.extends).toLowerCase() : void 0;
541
+ if (classNameLower === baseClassLower && extendsLower === baseClassLower) {
542
+ continue;
543
+ }
544
+ if (extendsLower === baseClassLower) {
545
+ descendants.push(name);
546
+ descendants.push(
547
+ ...this.findDescendantsInManifest(name, manifest, visited)
548
+ );
549
+ }
550
+ }
551
+ return descendants;
552
+ }
553
+ applySqlTypeOverrides(obj) {
554
+ if (!obj.schema?.columns) {
555
+ return;
556
+ }
557
+ for (const [fieldName, field] of Object.entries(obj.fields || {})) {
558
+ const sqlType = field?._meta?.sqlType;
559
+ const referenceKind = this.getReferenceKind(field);
560
+ if (!sqlType && !referenceKind) {
561
+ continue;
562
+ }
563
+ const columnName = toSnakeCase(fieldName);
564
+ if (!obj.schema.columns[columnName]) {
565
+ continue;
566
+ }
567
+ obj.schema.columns[columnName] = {
568
+ ...obj.schema.columns[columnName],
569
+ ...sqlType ? { type: String(sqlType).toUpperCase() } : {},
570
+ ...referenceKind ? { referenceKind } : {}
571
+ };
572
+ }
573
+ }
574
+ getReferenceKind(field) {
575
+ if (field?._meta?.__tenancy?.isTenantIdField) {
576
+ return "tenantId";
577
+ }
578
+ if (field?.type === "foreignKey") {
579
+ return "foreignKey";
580
+ }
581
+ if (field?.type === "crossPackageRef") {
582
+ return "crossPackageRef";
583
+ }
584
+ return void 0;
585
+ }
586
+ /**
587
+ * Create an aggregated manifest that includes objects from all external packages
588
+ *
589
+ * This is used for STI schema generation to ensure ALL descendants are found,
590
+ * regardless of which package they're defined in.
591
+ *
592
+ * @param manifest - The local manifest
593
+ * @returns Aggregated manifest with local + external objects
594
+ */
595
+ createAggregatedManifest(manifest) {
596
+ const aggregatedObjects = {
597
+ ...manifest.objects
598
+ };
599
+ if (manifest.smrtDependencies && manifest.smrtDependencies.length > 0) {
600
+ for (const packageName of manifest.smrtDependencies) {
601
+ const externalManifest = loadExternalManifestSync(packageName);
602
+ if (externalManifest) {
603
+ for (const [name, obj] of Object.entries(externalManifest.objects)) {
604
+ if (!aggregatedObjects[name]) {
605
+ aggregatedObjects[name] = obj;
606
+ }
607
+ }
608
+ console.log(
609
+ `[manifest-generator] Aggregated ${Object.keys(externalManifest.objects).length} objects from ${packageName}`
610
+ );
611
+ }
612
+ }
613
+ }
614
+ return {
615
+ ...manifest,
616
+ objects: aggregatedObjects
617
+ };
618
+ }
619
+ /**
620
+ * Check if an object is an STI child class (inherits from STI base)
621
+ *
622
+ * Walks up the inheritance chain to find if any ancestor has tableStrategy: 'sti'.
623
+ * Also checks external SMRT packages for parent class definitions.
624
+ */
625
+ isSTIChildClass(obj, manifest) {
626
+ if (!obj.extends) return false;
627
+ const objectsByName = /* @__PURE__ */ new Map();
628
+ for (const [_name, objDef] of Object.entries(manifest.objects)) {
629
+ objectsByName.set(objDef.className, objDef);
630
+ objectsByName.set(objDef.className.toLowerCase(), objDef);
631
+ }
632
+ let currentClass = obj.extends;
633
+ const visited = /* @__PURE__ */ new Set();
634
+ while (currentClass) {
635
+ if (visited.has(currentClass)) break;
636
+ visited.add(currentClass);
637
+ let parentObj = objectsByName.get(currentClass);
638
+ if (!parentObj && manifest.smrtDependencies && manifest.smrtDependencies.length > 0) {
639
+ parentObj = this.loadParentFromExternalPackage(
640
+ currentClass,
641
+ manifest.smrtDependencies,
642
+ objectsByName
643
+ );
644
+ }
645
+ if (!parentObj) break;
646
+ if (parentObj.decoratorConfig?.tableStrategy === "sti") {
647
+ return true;
648
+ }
649
+ currentClass = parentObj.extends;
650
+ }
651
+ return false;
652
+ }
653
+ /**
654
+ * Check whether `obj` extends a framework abstract base class anywhere
655
+ * in its chain.
656
+ *
657
+ * Framework abstract bases (`SmrtHierarchical`, `SmrtJunction`, …) have
658
+ * no table of their own — fields they declare must be merged into every
659
+ * subclass's manifest, even when the subclass uses CTI. Without this,
660
+ * a class like `Account extends SmrtHierarchical` would silently lose
661
+ * `parentId` from its `fields` map and downstream WHERE-clause
662
+ * validation would reject queries on the inherited column.
663
+ *
664
+ * Identified by name against the same hardcoded set the scanner's
665
+ * `FRAMEWORK_BASE_CLASSES` recognizes (`packages/scanner/src/
666
+ * inheritance-resolver.ts`). Keep the two lists in sync.
667
+ */
668
+ extendsFrameworkAbstractBase(obj, objectsByName, manifest) {
669
+ if (!obj.extends) return false;
670
+ let currentClass = obj.extends;
671
+ const visited = /* @__PURE__ */ new Set();
672
+ while (currentClass) {
673
+ if (visited.has(currentClass)) break;
674
+ visited.add(currentClass);
675
+ if (FRAMEWORK_ABSTRACT_BASE_NAMES.has(currentClass)) {
676
+ return true;
677
+ }
678
+ let parentObj = objectsByName.get(currentClass);
679
+ if (!parentObj && manifest.smrtDependencies && manifest.smrtDependencies.length > 0) {
680
+ parentObj = this.loadParentFromExternalPackage(
681
+ currentClass,
682
+ manifest.smrtDependencies,
683
+ objectsByName
684
+ );
685
+ }
686
+ if (!parentObj) break;
687
+ currentClass = parentObj.extends;
688
+ }
689
+ return false;
690
+ }
691
+ /**
692
+ * Find full STI base class info (className + tableName)
693
+ *
694
+ * Walks up the inheritance chain to find the STI base class and returns
695
+ * both its className and tableName. This is critical for external STI bases
696
+ * where the child needs to use the base's table name for schema generation.
697
+ */
698
+ findSTIBaseInfo(obj, manifest) {
699
+ if (!obj.extends) return void 0;
700
+ const objectsByName = /* @__PURE__ */ new Map();
701
+ for (const [_name, objDef] of Object.entries(manifest.objects)) {
702
+ objectsByName.set(objDef.className, objDef);
703
+ objectsByName.set(objDef.className.toLowerCase(), objDef);
704
+ }
705
+ let stiBaseInfo;
706
+ let currentClass = obj.extends;
707
+ const visited = /* @__PURE__ */ new Set();
708
+ while (currentClass) {
709
+ if (visited.has(currentClass)) break;
710
+ visited.add(currentClass);
711
+ let parentObj = objectsByName.get(currentClass);
712
+ if (!parentObj && manifest.smrtDependencies && manifest.smrtDependencies.length > 0) {
713
+ parentObj = this.loadParentFromExternalPackage(
714
+ currentClass,
715
+ manifest.smrtDependencies,
716
+ objectsByName
717
+ );
718
+ }
719
+ if (!parentObj) break;
720
+ if (parentObj.decoratorConfig?.tableStrategy === "sti") {
721
+ const tableName = parentObj.decoratorConfig?.tableName || parentObj.schema?.tableName || this.classNameToTableName(parentObj.className);
722
+ stiBaseInfo = {
723
+ className: parentObj.className,
724
+ tableName
725
+ };
726
+ }
727
+ currentClass = parentObj.extends;
728
+ }
729
+ return stiBaseInfo;
730
+ }
731
+ /**
732
+ * Convert class name to table name (snake_case pluralized)
733
+ *
734
+ * IMPORTANT: Must use the same algorithm as runtime's tableNameFromClass()
735
+ * to ensure manifest-generated table names match runtime-derived names.
736
+ */
737
+ classNameToTableName(className) {
738
+ return classnameToTablename(className);
739
+ }
740
+ normalizeFrameworkInheritedField(ancestorName, fieldName, fieldDef, childClassName) {
741
+ if (this.simpleClassName(ancestorName) === "SmrtHierarchical" && fieldName === "parentId") {
742
+ return {
743
+ ...fieldDef,
744
+ type: "foreignKey",
745
+ related: childClassName,
746
+ required: false,
747
+ _meta: {
748
+ ...fieldDef._meta || {},
749
+ nullable: true
750
+ }
751
+ };
752
+ }
753
+ return fieldDef;
754
+ }
755
+ simpleClassName(className) {
756
+ return className.includes(":") ? className.split(":").pop() || className : className;
757
+ }
758
+ /**
759
+ * Merge inherited fields into child classes (build-time inheritance resolution)
760
+ *
761
+ * For STI hierarchies, child classes don't define their own fields in source code
762
+ * (they inherit from parent). This method merges parent fields into child manifests
763
+ * so that runtime code doesn't need to do field resolution.
764
+ *
765
+ * Also handles collection classes (SmrtCollection<T>) that should inherit their
766
+ * item class's tableName and collection when the item uses STI.
767
+ *
768
+ * Handles multi-level inheritance (grandparents, great-grandparents, etc.)
769
+ * Automatically loads parent class definitions from external SMRT packages when needed
770
+ *
771
+ * @param manifest - The manifest to process in-place
772
+ */
773
+ mergeInheritedFields(manifest) {
774
+ const objectsByName = /* @__PURE__ */ new Map();
775
+ for (const [name, obj] of Object.entries(manifest.objects)) {
776
+ objectsByName.set(obj.className, obj);
777
+ objectsByName.set(obj.className.toLowerCase(), obj);
778
+ }
779
+ for (const obj of Object.values(manifest.objects)) {
780
+ if (!obj.extends) continue;
781
+ const usesSTI = this.isSTIClass(obj, objectsByName, manifest);
782
+ const extendsFrameworkBase = this.extendsFrameworkAbstractBase(
783
+ obj,
784
+ objectsByName,
785
+ manifest
786
+ );
787
+ if (!usesSTI && !extendsFrameworkBase) {
788
+ continue;
789
+ }
790
+ console.log(
791
+ `[manifest-generator] Merging inherited fields for ${obj.className} from ${obj.extends}`
792
+ );
793
+ const inheritanceChain = [];
794
+ let currentClass = obj.extends;
795
+ const visited = /* @__PURE__ */ new Set();
796
+ while (currentClass) {
797
+ if (visited.has(currentClass)) {
798
+ console.warn(
799
+ `[manifest-generator] Circular inheritance detected for ${obj.className}`
800
+ );
801
+ break;
802
+ }
803
+ visited.add(currentClass);
804
+ inheritanceChain.unshift(currentClass);
805
+ let parentObj = objectsByName.get(currentClass);
806
+ if (parentObj === obj) {
807
+ parentObj = void 0;
808
+ }
809
+ if (!parentObj && manifest.smrtDependencies && manifest.smrtDependencies.length > 0) {
810
+ parentObj = this.loadParentFromExternalPackage(
811
+ currentClass,
812
+ manifest.smrtDependencies,
813
+ objectsByName
814
+ );
815
+ }
816
+ if (!parentObj) break;
817
+ currentClass = parentObj.extends;
818
+ }
819
+ console.log(
820
+ `[manifest-generator] Inheritance chain for ${obj.className}: ${inheritanceChain.join(" -> ")}`
821
+ );
822
+ const mergedFields = {};
823
+ const mergedMethods = {};
824
+ for (const ancestorName of inheritanceChain) {
825
+ const ancestor = objectsByName.get(ancestorName);
826
+ if (!ancestor) continue;
827
+ const ancestorIsFrameworkBase = FRAMEWORK_ABSTRACT_BASE_NAMES.has(ancestorName);
828
+ if (!usesSTI && !ancestorIsFrameworkBase) {
829
+ continue;
830
+ }
831
+ for (const [fieldName, fieldDef] of Object.entries(ancestor.fields)) {
832
+ if (!mergedFields[fieldName]) {
833
+ mergedFields[fieldName] = this.normalizeFrameworkInheritedField(
834
+ ancestorName,
835
+ fieldName,
836
+ fieldDef,
837
+ obj.className
838
+ );
839
+ }
840
+ }
841
+ for (const [methodName, methodDef] of Object.entries(
842
+ ancestor.methods || {}
843
+ )) {
844
+ if (!mergedMethods[methodName]) {
845
+ mergedMethods[methodName] = methodDef;
846
+ }
847
+ }
848
+ }
849
+ for (const [fieldName, fieldDef] of Object.entries(obj.fields)) {
850
+ mergedFields[fieldName] = fieldDef;
851
+ }
852
+ for (const [methodName, methodDef] of Object.entries(obj.methods || {})) {
853
+ mergedMethods[methodName] = methodDef;
854
+ }
855
+ obj.fields = mergedFields;
856
+ obj.methods = mergedMethods;
857
+ const stiBase = this.findSTIBase(obj, objectsByName, manifest);
858
+ if (stiBase && stiBase !== obj) {
859
+ const baseTableName = stiBase.decoratorConfig?.tableName || this.classNameToTableName(stiBase.className);
860
+ obj.decoratorConfig = obj.decoratorConfig || {};
861
+ obj.decoratorConfig.tableName = baseTableName;
862
+ console.log(
863
+ `[manifest-generator] ${obj.className} inherits tableName: '${baseTableName}' from ${stiBase.className}`
864
+ );
865
+ if (stiBase.decoratorConfig?.tableStrategy) {
866
+ obj.decoratorConfig.tableStrategy = stiBase.decoratorConfig.tableStrategy;
867
+ console.log(
868
+ `[manifest-generator] ${obj.className} inherits tableStrategy: '${stiBase.decoratorConfig.tableStrategy}' from ${stiBase.className}`
869
+ );
870
+ }
871
+ if (stiBase.collection !== obj.collection) {
872
+ console.log(
873
+ `[manifest-generator] ${obj.className} inherits collection: '${stiBase.collection}' from ${stiBase.className}`
874
+ );
875
+ obj.collection = stiBase.collection;
876
+ }
877
+ }
878
+ console.log(
879
+ `[manifest-generator] ✅ ${obj.className} now has ${Object.keys(mergedFields).length} fields (including inherited)`
880
+ );
881
+ }
882
+ for (const obj of Object.values(manifest.objects)) {
883
+ const isCollection = obj.extends === "SmrtCollection" || this.extendsCollection(obj, objectsByName);
884
+ if (isCollection) {
885
+ const itemClass = this.findItemClass(obj, manifest, objectsByName);
886
+ if (itemClass) {
887
+ console.log(
888
+ `[manifest-generator] ${obj.className} is a collection class for ${itemClass.className}`
889
+ );
890
+ if (itemClass.decoratorConfig?.tableName) {
891
+ obj.decoratorConfig = obj.decoratorConfig || {};
892
+ obj.decoratorConfig.tableName = itemClass.decoratorConfig.tableName;
893
+ console.log(
894
+ `[manifest-generator] ${obj.className} inherits tableName: '${itemClass.decoratorConfig.tableName}' from item class ${itemClass.className}`
895
+ );
896
+ }
897
+ if (itemClass.collection !== obj.collection) {
898
+ console.log(
899
+ `[manifest-generator] ${obj.className} inherits collection: '${itemClass.collection}' from item class ${itemClass.className} (was '${obj.collection}')`
900
+ );
901
+ obj.collection = itemClass.collection;
902
+ }
903
+ }
904
+ }
905
+ }
906
+ }
907
+ /**
908
+ * Check if a class extends SmrtCollection (directly or indirectly)
909
+ *
910
+ * @param obj - The object definition to check
911
+ * @param objectsByName - Map of className -> objectDef for lookups
912
+ * @returns true if this class extends SmrtCollection
913
+ */
914
+ extendsCollection(obj, objectsByName) {
915
+ if (!obj.extends) return false;
916
+ let currentClass = obj.extends;
917
+ const visited = /* @__PURE__ */ new Set();
918
+ while (currentClass) {
919
+ if (visited.has(currentClass)) break;
920
+ visited.add(currentClass);
921
+ if (currentClass === "SmrtCollection") return true;
922
+ const parentObj = objectsByName.get(currentClass);
923
+ if (!parentObj) break;
924
+ currentClass = parentObj.extends;
925
+ }
926
+ return false;
927
+ }
928
+ /**
929
+ * Find the item class for a collection class
930
+ *
931
+ * Lookup priority:
932
+ * 1. extendsTypeArg - Generic type argument from extends clause (e.g., "Meeting" from SmrtCollection<Meeting>)
933
+ * 2. _itemClass static property - May be captured by AST scanner
934
+ * 3. Name-based inference - Fallback (e.g., "Meetings" -> "Meeting")
935
+ *
936
+ * @param collectionObj - The collection class definition
937
+ * @param manifest - The manifest
938
+ * @param objectsByName - Map of className -> objectDef for lookups
939
+ * @returns Item class definition or undefined
940
+ */
941
+ findItemClass(collectionObj, manifest, objectsByName) {
942
+ if (collectionObj.extendsTypeArg) {
943
+ const itemClassName = collectionObj.extendsTypeArg;
944
+ console.log(
945
+ `[manifest-generator] ${collectionObj.className} has extendsTypeArg: ${itemClassName}`
946
+ );
947
+ const itemClass = objectsByName.get(itemClassName);
948
+ if (itemClass) {
949
+ console.log(
950
+ `[manifest-generator] Found item class ${itemClassName} in local manifest`
951
+ );
952
+ return itemClass;
953
+ }
954
+ if (manifest.smrtDependencies && manifest.smrtDependencies.length > 0) {
955
+ const externalItemClass = this.loadParentFromExternalPackage(
956
+ itemClassName,
957
+ manifest.smrtDependencies,
958
+ objectsByName
959
+ );
960
+ if (externalItemClass) {
961
+ console.log(
962
+ `[manifest-generator] Found item class ${itemClassName} in external package`
963
+ );
964
+ return externalItemClass;
965
+ }
966
+ }
967
+ }
968
+ const itemClassField = collectionObj.fields._itemClass;
969
+ if (itemClassField) {
970
+ const itemClassName = itemClassField.related || itemClassField.default;
971
+ if (itemClassName && typeof itemClassName === "string") {
972
+ const itemClass = objectsByName.get(itemClassName);
973
+ if (itemClass) {
974
+ return itemClass;
975
+ }
976
+ if (manifest.smrtDependencies && manifest.smrtDependencies.length > 0) {
977
+ return this.loadParentFromExternalPackage(
978
+ itemClassName,
979
+ manifest.smrtDependencies,
980
+ objectsByName
981
+ );
982
+ }
983
+ }
984
+ }
985
+ const collectionName = collectionObj.className;
986
+ const candidates = [];
987
+ let baseName = collectionName;
988
+ if (baseName.endsWith("Collection")) {
989
+ baseName = baseName.slice(0, -"Collection".length);
990
+ }
991
+ candidates.push(baseName);
992
+ if (baseName.endsWith("s") && baseName.length > 1) {
993
+ candidates.push(baseName.slice(0, -1));
994
+ }
995
+ if (baseName.endsWith("ies") && baseName.length > 3) {
996
+ candidates.push(`${baseName.slice(0, -3)}y`);
997
+ }
998
+ if (baseName.endsWith("es") && baseName.length > 2) {
999
+ candidates.push(baseName.slice(0, -2));
1000
+ }
1001
+ for (const candidate of candidates) {
1002
+ if (candidate === collectionObj.className) continue;
1003
+ const itemClass = objectsByName.get(candidate);
1004
+ if (itemClass) {
1005
+ return itemClass;
1006
+ }
1007
+ }
1008
+ if (manifest.smrtDependencies && manifest.smrtDependencies.length > 0) {
1009
+ for (const candidate of candidates) {
1010
+ if (candidate === collectionObj.className) continue;
1011
+ const itemClass = this.loadParentFromExternalPackage(
1012
+ candidate,
1013
+ manifest.smrtDependencies,
1014
+ objectsByName
1015
+ );
1016
+ if (itemClass) {
1017
+ return itemClass;
1018
+ }
1019
+ }
1020
+ }
1021
+ return void 0;
1022
+ }
1023
+ /**
1024
+ * Check if a class uses STI (either explicitly or inherited from an ancestor)
1025
+ *
1026
+ * Walks up the inheritance chain to find if any ancestor has tableStrategy: 'sti'.
1027
+ * If found, all descendants inherit STI and should have fields merged.
1028
+ * Also checks external SMRT packages for parent class definitions.
1029
+ *
1030
+ * @param obj - The object definition to check
1031
+ * @param objectsByName - Map of className -> objectDef for lookups
1032
+ * @param manifest - The manifest (for accessing smrtDependencies)
1033
+ * @returns true if this class uses STI (directly or inherited)
1034
+ */
1035
+ isSTIClass(obj, objectsByName, manifest) {
1036
+ if (obj.decoratorConfig?.tableStrategy === "sti") {
1037
+ return true;
1038
+ }
1039
+ let currentClass = obj.extends;
1040
+ const visited = /* @__PURE__ */ new Set();
1041
+ while (currentClass) {
1042
+ if (visited.has(currentClass)) {
1043
+ break;
1044
+ }
1045
+ visited.add(currentClass);
1046
+ let parentDef = objectsByName.get(currentClass);
1047
+ if (parentDef === obj) {
1048
+ parentDef = void 0;
1049
+ }
1050
+ if (!parentDef && manifest.smrtDependencies && manifest.smrtDependencies.length > 0) {
1051
+ parentDef = this.loadParentFromExternalPackage(
1052
+ currentClass,
1053
+ manifest.smrtDependencies,
1054
+ objectsByName
1055
+ );
1056
+ }
1057
+ if (!parentDef) break;
1058
+ if (parentDef.decoratorConfig?.tableStrategy === "sti") {
1059
+ return true;
1060
+ }
1061
+ currentClass = parentDef.extends;
1062
+ }
1063
+ return false;
1064
+ }
1065
+ /**
1066
+ * Find the STI base class for a given object
1067
+ *
1068
+ * Walks up the inheritance chain to find the first ancestor that defines
1069
+ * tableStrategy: 'sti'. This is the class that owns the shared table.
1070
+ *
1071
+ * @param obj - The object definition to find the STI base for
1072
+ * @param objectsByName - Map of className -> objectDef for lookups
1073
+ * @param manifest - The manifest (for accessing smrtDependencies)
1074
+ * @returns The STI base class definition, or the object itself if it's the base
1075
+ */
1076
+ findSTIBase(obj, objectsByName, manifest) {
1077
+ let stiBase;
1078
+ if (obj.decoratorConfig?.tableStrategy === "sti") {
1079
+ stiBase = obj;
1080
+ }
1081
+ let currentClass = obj.extends;
1082
+ const visited = /* @__PURE__ */ new Set();
1083
+ while (currentClass) {
1084
+ if (visited.has(currentClass)) {
1085
+ break;
1086
+ }
1087
+ visited.add(currentClass);
1088
+ let parentDef = objectsByName.get(currentClass);
1089
+ if (parentDef === obj) {
1090
+ parentDef = void 0;
1091
+ }
1092
+ if (!parentDef && manifest.smrtDependencies && manifest.smrtDependencies.length > 0) {
1093
+ parentDef = this.loadParentFromExternalPackage(
1094
+ currentClass,
1095
+ manifest.smrtDependencies,
1096
+ objectsByName
1097
+ );
1098
+ }
1099
+ if (!parentDef) break;
1100
+ if (parentDef.decoratorConfig?.tableStrategy === "sti") {
1101
+ stiBase = parentDef;
1102
+ }
1103
+ currentClass = parentDef.extends;
1104
+ }
1105
+ return stiBase;
1106
+ }
1107
+ /**
1108
+ * Load parent class definition from external SMRT packages
1109
+ *
1110
+ * When a child class extends a parent from an external package (e.g., praeco's Council extends
1111
+ * smrt-profiles' Organization), this method loads the parent's manifest and extracts the
1112
+ * parent's field definitions.
1113
+ *
1114
+ * @param parentClassName - Name of the parent class to find
1115
+ * @param smrtDependencies - List of external SMRT packages to search
1116
+ * @param objectsByName - Map to cache loaded external objects
1117
+ * @returns Parent object definition if found, undefined otherwise
1118
+ */
1119
+ loadParentFromExternalPackage(parentClassName, smrtDependencies, objectsByName) {
1120
+ for (const packageName of smrtDependencies) {
1121
+ const externalManifest = loadExternalManifestSync(packageName);
1122
+ if (!externalManifest) {
1123
+ continue;
1124
+ }
1125
+ const parentObj = lookupInManifest(externalManifest, parentClassName);
1126
+ if (parentObj) {
1127
+ objectsByName.set(parentObj.className, parentObj);
1128
+ objectsByName.set(parentObj.className.toLowerCase(), parentObj);
1129
+ return parentObj;
1130
+ }
1131
+ }
1132
+ return void 0;
1133
+ }
1134
+ /**
1135
+ * Determine import path from package.json exports
1136
+ *
1137
+ * Tries the following strategies in order:
1138
+ * 1. package.json exports["./objects"] - Specific objects export
1139
+ * 2. package.json exports["."] - Main export
1140
+ * 3. package.json main - Main field
1141
+ * 4. Fallback to package name
1142
+ */
1143
+ determineImportPath(packageJson, _filePath) {
1144
+ const packageName = packageJson.name;
1145
+ if (packageJson.exports) {
1146
+ if (packageJson.exports["./objects"]) {
1147
+ return `${packageName}/objects`;
1148
+ }
1149
+ const mainExport = packageJson.exports["."];
1150
+ if (mainExport) {
1151
+ if (typeof mainExport === "object") {
1152
+ if (mainExport.import) {
1153
+ return packageName;
1154
+ }
1155
+ if (mainExport.default) {
1156
+ return packageName;
1157
+ }
1158
+ }
1159
+ return packageName;
1160
+ }
1161
+ }
1162
+ if (packageJson.main) {
1163
+ return packageName;
1164
+ }
1165
+ return packageName;
1166
+ }
1167
+ /**
1168
+ * Generate TypeScript interfaces from manifest
1169
+ */
1170
+ generateTypeDefinitions(manifest) {
1171
+ const interfaces = [];
1172
+ for (const [_name, obj] of Object.entries(manifest.objects)) {
1173
+ interfaces.push(this.generateInterface(obj));
1174
+ }
1175
+ return interfaces.join("\n\n");
1176
+ }
1177
+ /**
1178
+ * Generate a single interface definition
1179
+ */
1180
+ generateInterface(obj) {
1181
+ const fields = Object.entries(obj.fields).map(([name, field]) => {
1182
+ const optional = !field.required ? "?" : "";
1183
+ const type = this.mapFieldTypeToTS(field.type);
1184
+ return ` ${name}${optional}: ${type};`;
1185
+ }).join("\n");
1186
+ return `export interface ${obj.className}Data {
1187
+ ${fields}
1188
+ }`;
1189
+ }
1190
+ /**
1191
+ * Map field types to TypeScript types
1192
+ */
1193
+ mapFieldTypeToTS(fieldType) {
1194
+ switch (fieldType) {
1195
+ case "text":
1196
+ return "string";
1197
+ case "decimal":
1198
+ return "number";
1199
+ case "integer":
1200
+ return "number";
1201
+ case "boolean":
1202
+ return "boolean";
1203
+ case "datetime":
1204
+ return "Date | string";
1205
+ case "json":
1206
+ return "any";
1207
+ case "foreignKey":
1208
+ return "string";
1209
+ case "crossPackageRef":
1210
+ return "string";
1211
+ default:
1212
+ return "any";
1213
+ }
1214
+ }
1215
+ /**
1216
+ * Generate simple endpoint list for testing/documentation
1217
+ */
1218
+ generateRestEndpoints(manifest) {
1219
+ const endpoints = [];
1220
+ for (const [_name, obj] of Object.entries(manifest.objects)) {
1221
+ const apiConfig = obj.decoratorConfig.api;
1222
+ if (apiConfig !== false) {
1223
+ endpoints.push(...this.getSimpleEndpoints(obj));
1224
+ }
1225
+ }
1226
+ return endpoints.join("\n");
1227
+ }
1228
+ /**
1229
+ * Generate REST endpoint code implementations
1230
+ */
1231
+ generateRestEndpointCode(manifest) {
1232
+ const endpoints = [];
1233
+ for (const [_name, obj] of Object.entries(manifest.objects)) {
1234
+ const apiConfig = obj.decoratorConfig.api;
1235
+ if (apiConfig !== false) {
1236
+ endpoints.push(this.generateRestEndpoint(obj));
1237
+ }
1238
+ }
1239
+ return endpoints.join("\n\n");
1240
+ }
1241
+ /**
1242
+ * Get simple endpoint strings for an object
1243
+ */
1244
+ getApiRouteMetadata(obj, actionName, actionDef) {
1245
+ const config = obj.decoratorConfig.api && typeof obj.decoratorConfig.api === "object" ? obj.decoratorConfig.api : void 0;
1246
+ const routeConfig = config?.routes?.[actionName];
1247
+ const normalizedPath = (routeConfig?.path || actionName).split("/").map((segment) => segment.trim()).filter(Boolean).join("/");
1248
+ const isCollectionClass = obj.extends === "SmrtCollection" || !!obj.extendsTypeArg;
1249
+ return {
1250
+ scope: routeConfig?.scope || (isCollectionClass || actionDef.isStatic ? "collection" : "item"),
1251
+ method: routeConfig?.method?.toUpperCase() === "GET" || routeConfig?.method?.toUpperCase() === "POST" || routeConfig?.method?.toUpperCase() === "PUT" || routeConfig?.method?.toUpperCase() === "PATCH" || routeConfig?.method?.toUpperCase() === "DELETE" ? routeConfig.method.toUpperCase() : "POST",
1252
+ path: normalizedPath || actionName
1253
+ };
1254
+ }
1255
+ getSimpleEndpoints(obj) {
1256
+ const { collection } = obj;
1257
+ const config = obj.decoratorConfig.api;
1258
+ const exclude = typeof config === "object" && config?.exclude || [];
1259
+ const include = typeof config === "object" && config?.include || void 0;
1260
+ const isCollectionClass = obj.extends === "SmrtCollection" || !!obj.extendsTypeArg;
1261
+ const endpoints = [];
1262
+ const shouldInclude = (op) => {
1263
+ if (include && !include.includes(op)) return false;
1264
+ if (exclude.includes(op)) return false;
1265
+ return true;
1266
+ };
1267
+ if (!isCollectionClass) {
1268
+ if (shouldInclude("list")) {
1269
+ endpoints.push(`GET /${collection}`);
1270
+ }
1271
+ if (shouldInclude("create")) {
1272
+ endpoints.push(`POST /${collection}`);
1273
+ }
1274
+ if (shouldInclude("get")) {
1275
+ endpoints.push(`GET /${collection}/:id`);
1276
+ }
1277
+ if (shouldInclude("update")) {
1278
+ endpoints.push(`PUT /${collection}/:id`);
1279
+ }
1280
+ if (shouldInclude("delete")) {
1281
+ endpoints.push(`DELETE /${collection}/:id`);
1282
+ }
1283
+ }
1284
+ const standardActions = ["list", "get", "create", "update", "delete"];
1285
+ for (const [actionName, actionDef] of Object.entries(obj.methods)) {
1286
+ if (standardActions.includes(actionName) || !actionDef.isPublic || !shouldInclude(actionName)) {
1287
+ continue;
1288
+ }
1289
+ const route = this.getApiRouteMetadata(obj, actionName, actionDef);
1290
+ if (route.scope === "collection" && !isCollectionClass && !actionDef.isStatic) {
1291
+ continue;
1292
+ }
1293
+ if (route.scope === "item" && isCollectionClass) {
1294
+ continue;
1295
+ }
1296
+ const suffix = route.scope === "collection" ? "" : "/:id";
1297
+ endpoints.push(`${route.method} /${collection}${suffix}/${route.path}`);
1298
+ }
1299
+ return endpoints;
1300
+ }
1301
+ /**
1302
+ * Generate a single REST endpoint
1303
+ */
1304
+ generateRestEndpoint(obj) {
1305
+ const { collection, className } = obj;
1306
+ const config = obj.decoratorConfig.api;
1307
+ const exclude = typeof config === "object" && config?.exclude || [];
1308
+ const include = typeof config === "object" && config?.include || void 0;
1309
+ const operations = [];
1310
+ const shouldInclude = (op) => {
1311
+ if (include && !include.includes(op)) return false;
1312
+ if (exclude.includes(op)) return false;
1313
+ return true;
1314
+ };
1315
+ if (shouldInclude("list")) {
1316
+ operations.push(` // GET /${collection} - List ${collection}`);
1317
+ operations.push(` app.get('/${collection}', async (req: Request) => {`);
1318
+ operations.push(
1319
+ ` const collection = await get${className}Collection();`
1320
+ );
1321
+ operations.push(" const items = await collection.list(req.query);");
1322
+ operations.push(" return Response.json(items);");
1323
+ operations.push(" });");
1324
+ }
1325
+ if (shouldInclude("get")) {
1326
+ operations.push(` // GET /${collection}/:id - Get ${className}`);
1327
+ operations.push(
1328
+ ` app.get('/${collection}/:id', async (req: Request) => {`
1329
+ );
1330
+ operations.push(
1331
+ ` const collection = await get${className}Collection();`
1332
+ );
1333
+ operations.push(" const item = await collection.get(req.params.id);");
1334
+ operations.push(
1335
+ ` if (!item) return new Response('Not found', { status: 404 });`
1336
+ );
1337
+ operations.push(" return Response.json(item);");
1338
+ operations.push(" });");
1339
+ }
1340
+ if (shouldInclude("create")) {
1341
+ operations.push(` // POST /${collection} - Create ${className}`);
1342
+ operations.push(` app.post('/${collection}', async (req: Request) => {`);
1343
+ operations.push(
1344
+ ` const collection = await get${className}Collection();`
1345
+ );
1346
+ operations.push(" const data = await req.json();");
1347
+ operations.push(" const item = await collection.create(data);");
1348
+ operations.push(" return Response.json(item, { status: 201 });");
1349
+ operations.push(" });");
1350
+ }
1351
+ if (shouldInclude("update")) {
1352
+ operations.push(` // PUT /${collection}/:id - Update ${className}`);
1353
+ operations.push(
1354
+ ` app.put('/${collection}/:id', async (req: Request) => {`
1355
+ );
1356
+ operations.push(
1357
+ ` const collection = await get${className}Collection();`
1358
+ );
1359
+ operations.push(" const data = await req.json();");
1360
+ operations.push(
1361
+ " const item = await collection.update(req.params.id, data);"
1362
+ );
1363
+ operations.push(
1364
+ ` if (!item) return new Response('Not found', { status: 404 });`
1365
+ );
1366
+ operations.push(" return Response.json(item);");
1367
+ operations.push(" });");
1368
+ }
1369
+ if (shouldInclude("delete")) {
1370
+ operations.push(` // DELETE /${collection}/:id - Delete ${className}`);
1371
+ operations.push(
1372
+ ` app.delete('/${collection}/:id', async (req: Request) => {`
1373
+ );
1374
+ operations.push(
1375
+ ` const collection = await get${className}Collection();`
1376
+ );
1377
+ operations.push(
1378
+ " const success = await collection.delete(req.params.id);"
1379
+ );
1380
+ operations.push(
1381
+ ` if (!success) return new Response('Not found', { status: 404 });`
1382
+ );
1383
+ operations.push(` return new Response('', { status: 204 });`);
1384
+ operations.push(" });");
1385
+ }
1386
+ return `// ${className} endpoints
1387
+ ${operations.join("\n")}`;
1388
+ }
1389
+ /**
1390
+ * Generate simple MCP tool names for testing/documentation
1391
+ */
1392
+ generateMCPTools(manifest) {
1393
+ const tools = [];
1394
+ for (const [_name, obj] of Object.entries(manifest.objects)) {
1395
+ const mcpConfig = obj.decoratorConfig.mcp;
1396
+ if (mcpConfig !== false) {
1397
+ tools.push(...this.getSimpleMCPToolNames(obj));
1398
+ }
1399
+ }
1400
+ return tools.join("\n");
1401
+ }
1402
+ /**
1403
+ * Generate MCP tool JSON definitions
1404
+ */
1405
+ generateMCPToolsCode(manifest) {
1406
+ const tools = [];
1407
+ for (const [_name, obj] of Object.entries(manifest.objects)) {
1408
+ const mcpConfig = obj.decoratorConfig.mcp;
1409
+ if (mcpConfig !== false) {
1410
+ tools.push(this.generateMCPTool(obj));
1411
+ }
1412
+ }
1413
+ return `[
1414
+ ${tools.join(",\n")}
1415
+ ]`;
1416
+ }
1417
+ /**
1418
+ * Get simple MCP tool names for an object
1419
+ */
1420
+ getSimpleMCPToolNames(obj) {
1421
+ const { collection } = obj;
1422
+ const config = obj.decoratorConfig.mcp;
1423
+ const exclude = typeof config === "object" && config?.exclude || [];
1424
+ const include = typeof config === "object" && config?.include || void 0;
1425
+ const tools = [];
1426
+ const shouldInclude = (op) => {
1427
+ if (include && !include.includes(op)) return false;
1428
+ if (exclude.includes(op)) return false;
1429
+ return true;
1430
+ };
1431
+ if (shouldInclude("list")) {
1432
+ tools.push(`list_${collection}`);
1433
+ }
1434
+ if (shouldInclude("get")) {
1435
+ tools.push(`get_${collection}`);
1436
+ }
1437
+ if (shouldInclude("create")) {
1438
+ tools.push(`create_${collection}`);
1439
+ }
1440
+ if (shouldInclude("update")) {
1441
+ tools.push(`update_${collection}`);
1442
+ }
1443
+ if (shouldInclude("delete")) {
1444
+ tools.push(`delete_${collection}`);
1445
+ }
1446
+ return tools;
1447
+ }
1448
+ /**
1449
+ * Generate a single MCP tool
1450
+ */
1451
+ generateMCPTool(obj) {
1452
+ const { collection, className, name } = obj;
1453
+ const config = obj.decoratorConfig.mcp;
1454
+ const exclude = typeof config === "object" && config?.exclude || [];
1455
+ const include = typeof config === "object" && config?.include || void 0;
1456
+ const tools = [];
1457
+ const shouldInclude = (op) => {
1458
+ if (include && !include.includes(op)) return false;
1459
+ if (exclude.includes(op)) return false;
1460
+ return true;
1461
+ };
1462
+ if (shouldInclude("list")) {
1463
+ tools.push(` {
1464
+ name: "list_${collection}",
1465
+ description: "List ${collection}",
1466
+ inputSchema: {
1467
+ type: "object",
1468
+ properties: {
1469
+ limit: { type: "number" },
1470
+ offset: { type: "number" },
1471
+ where: { type: "object" }
1472
+ }
1473
+ }
1474
+ }`);
1475
+ }
1476
+ if (shouldInclude("get")) {
1477
+ tools.push(` {
1478
+ name: "get_${name}",
1479
+ description: "Get a ${name} by ID",
1480
+ inputSchema: {
1481
+ type: "object",
1482
+ properties: {
1483
+ id: { type: "string", description: "The ${name} ID" }
1484
+ },
1485
+ required: ["id"]
1486
+ }
1487
+ }`);
1488
+ }
1489
+ if (shouldInclude("create")) {
1490
+ const requiredFields = Object.entries(obj.fields).filter(([_, field]) => field.required).map(([fieldName]) => fieldName);
1491
+ tools.push(` {
1492
+ name: "create_${name}",
1493
+ description: "Create a new ${name}",
1494
+ inputSchema: {
1495
+ type: "object",
1496
+ properties: ${JSON.stringify(this.generateSchemaProperties(obj.fields), null, 6)},
1497
+ required: ${JSON.stringify(requiredFields)}
1498
+ }
1499
+ }`);
1500
+ }
1501
+ return tools.join(",\n");
1502
+ }
1503
+ /**
1504
+ * Generate JSON schema properties for fields
1505
+ */
1506
+ generateSchemaProperties(fields) {
1507
+ const properties = {};
1508
+ for (const [name, field] of Object.entries(fields)) {
1509
+ properties[name] = {
1510
+ type: this.mapFieldTypeToJSON(field.type),
1511
+ description: field.description || `The ${name} field`
1512
+ };
1513
+ if (field.min !== void 0) properties[name].minimum = field.min;
1514
+ if (field.max !== void 0) properties[name].maximum = field.max;
1515
+ if (field.minLength !== void 0)
1516
+ properties[name].minLength = field.minLength;
1517
+ if (field.maxLength !== void 0)
1518
+ properties[name].maxLength = field.maxLength;
1519
+ }
1520
+ return properties;
1521
+ }
1522
+ /**
1523
+ * Map field types to JSON Schema types
1524
+ */
1525
+ mapFieldTypeToJSON(fieldType) {
1526
+ switch (fieldType) {
1527
+ case "text":
1528
+ return "string";
1529
+ case "decimal":
1530
+ return "number";
1531
+ case "integer":
1532
+ return "integer";
1533
+ case "boolean":
1534
+ return "boolean";
1535
+ case "datetime":
1536
+ return "string";
1537
+ case "json":
1538
+ return "object";
1539
+ case "foreignKey":
1540
+ return "string";
1541
+ case "crossPackageRef":
1542
+ return "string";
1543
+ default:
1544
+ return "string";
1545
+ }
1546
+ }
1547
+ /**
1548
+ * Generate agent manifests for Agent subclasses (fifth pass).
1549
+ *
1550
+ * For any SmartObjectDefinition with `agent` in its decoratorConfig,
1551
+ * auto-generates:
1552
+ * - Permissions from uiSlots (manage:*) and CLI/MCP methods (execute:*)
1553
+ * - Features from uiSlots and exposed methods
1554
+ * - Menu items from uiSlots
1555
+ * - Component declarations from package.json exports
1556
+ *
1557
+ * @param manifest - The manifest to process in-place
1558
+ * @param packageName - Package name for component export paths
1559
+ * @param packageJson - Full package.json for component discovery
1560
+ */
1561
+ generateAgentManifests(manifest, packageName, packageJson) {
1562
+ for (const obj of Object.values(manifest.objects)) {
1563
+ if (!obj.decoratorConfig.agent) continue;
1564
+ const agentConfig = obj.decoratorConfig.agent;
1565
+ const slug = obj.className.toLowerCase();
1566
+ const uiSlots = obj.staticProperties?.uiSlots ?? {};
1567
+ const permissions = [];
1568
+ for (const [slotId, slot] of Object.entries(uiSlots)) {
1569
+ permissions.push({
1570
+ id: `manage:${slotId}`,
1571
+ label: `Manage ${slot.label || slotId}`,
1572
+ category: "slot",
1573
+ defaultGranted: true
1574
+ });
1575
+ }
1576
+ const exposedMethods = this.getExposedMethods(obj);
1577
+ for (const methodName of exposedMethods) {
1578
+ permissions.push({
1579
+ id: `execute:${methodName}`,
1580
+ label: `Execute ${methodName}`,
1581
+ category: "method",
1582
+ defaultGranted: true
1583
+ });
1584
+ }
1585
+ const features = [];
1586
+ for (const [slotId, slot] of Object.entries(uiSlots)) {
1587
+ const typedSlot = slot;
1588
+ features.push({
1589
+ id: slotId,
1590
+ label: typedSlot.label || slotId,
1591
+ description: typedSlot.description,
1592
+ type: "slot"
1593
+ });
1594
+ }
1595
+ for (const methodName of exposedMethods) {
1596
+ features.push({
1597
+ id: methodName,
1598
+ label: methodName,
1599
+ type: "method"
1600
+ });
1601
+ }
1602
+ const menuItems = Object.entries(uiSlots).map(([slotId, slot]) => {
1603
+ const typedSlot = slot;
1604
+ return {
1605
+ id: slotId,
1606
+ label: typedSlot.label || slotId,
1607
+ icon: typedSlot.icon,
1608
+ order: typedSlot.order ?? 999,
1609
+ path: `/agents/${slug}/${slotId}`,
1610
+ requiredPermission: `manage:${slotId}`
1611
+ };
1612
+ }).sort((a, b) => a.order - b.order);
1613
+ const components = [];
1614
+ if (packageName && packageJson?.exports) {
1615
+ for (const [exportKey, exportValue] of Object.entries(
1616
+ packageJson.exports
1617
+ )) {
1618
+ if (exportKey === "." || exportKey === "./manifest") continue;
1619
+ const hasSvelteCondition = this.hasSvelteExport(exportValue);
1620
+ if (hasSvelteCondition) {
1621
+ const type = exportKey.replace("./", "");
1622
+ components.push({
1623
+ exportPath: `${packageName}/${type}`,
1624
+ type
1625
+ });
1626
+ }
1627
+ }
1628
+ }
1629
+ const adminRoutes = obj.staticProperties?.adminRoutes ?? [];
1630
+ const signalSubscriptions = obj.staticProperties?.signalSubscriptions ?? [];
1631
+ const agentManifest = {
1632
+ name: obj.className,
1633
+ slug,
1634
+ icon: agentConfig.icon,
1635
+ tier: agentConfig.tier || "free",
1636
+ description: agentConfig.description,
1637
+ uiSlots,
1638
+ ...adminRoutes.length > 0 ? { adminRoutes } : {},
1639
+ ...signalSubscriptions.length > 0 ? { signalSubscriptions } : {},
1640
+ permissions,
1641
+ features,
1642
+ menuItems,
1643
+ components
1644
+ };
1645
+ obj.agent = agentManifest;
1646
+ console.log(
1647
+ `[manifest-generator] Generated agent manifest for ${obj.className}: ${permissions.length} permissions, ${features.length} features, ${menuItems.length} menu items, ${components.length} components`
1648
+ );
1649
+ }
1650
+ }
1651
+ /**
1652
+ * Get deduplicated list of method names exposed via CLI and MCP config
1653
+ */
1654
+ getExposedMethods(obj) {
1655
+ const methods = /* @__PURE__ */ new Set();
1656
+ const cliConfig = obj.decoratorConfig.cli;
1657
+ if (cliConfig && typeof cliConfig === "object" && cliConfig.include) {
1658
+ for (const m of cliConfig.include) {
1659
+ methods.add(m);
1660
+ }
1661
+ }
1662
+ const mcpConfig = obj.decoratorConfig.mcp;
1663
+ if (mcpConfig && typeof mcpConfig === "object" && mcpConfig.include) {
1664
+ for (const m of mcpConfig.include) {
1665
+ methods.add(m);
1666
+ }
1667
+ }
1668
+ return Array.from(methods);
1669
+ }
1670
+ /**
1671
+ * Check if an export value has a svelte condition (indicating a component export)
1672
+ */
1673
+ hasSvelteExport(exportValue) {
1674
+ if (!exportValue || typeof exportValue !== "object") return false;
1675
+ if ("svelte" in exportValue) return true;
1676
+ for (const val of Object.values(exportValue)) {
1677
+ if (val && typeof val === "object" && "svelte" in val) {
1678
+ return true;
1679
+ }
1680
+ }
1681
+ return false;
1682
+ }
1683
+ /**
1684
+ * Save manifest to file
1685
+ */
1686
+ saveManifest(manifest, filePath) {
1687
+ const fs = require$1("node:fs");
1688
+ fs.writeFileSync(filePath, JSON.stringify(manifest, null, 2));
1689
+ }
1690
+ /**
1691
+ * Load manifest from file
1692
+ */
1693
+ loadManifest(filePath) {
1694
+ const fs = require$1("node:fs");
1695
+ const content = fs.readFileSync(filePath, "utf-8");
1696
+ return JSON.parse(content);
1697
+ }
1698
+ }
1699
+ function generateManifest(scanResults, options) {
1700
+ const generator = new ManifestGenerator();
1701
+ return generator.generateManifest(scanResults, options);
1702
+ }
1703
+ export {
1704
+ ManifestGenerator,
1705
+ generateManifest
1706
+ };
1707
+ //# sourceMappingURL=manifest-generator.js.map