@ambitresearch/genie 1.3.1

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 (301) hide show
  1. package/README.md +15 -0
  2. package/dist/auth/bearer.d.ts +49 -0
  3. package/dist/auth/bearer.d.ts.map +1 -0
  4. package/dist/auth/bearer.js +159 -0
  5. package/dist/auth/bearer.js.map +1 -0
  6. package/dist/auth/oauth/authorize.d.ts +19 -0
  7. package/dist/auth/oauth/authorize.d.ts.map +1 -0
  8. package/dist/auth/oauth/authorize.js +111 -0
  9. package/dist/auth/oauth/authorize.js.map +1 -0
  10. package/dist/auth/oauth/config.d.ts +10 -0
  11. package/dist/auth/oauth/config.d.ts.map +1 -0
  12. package/dist/auth/oauth/config.js +16 -0
  13. package/dist/auth/oauth/config.js.map +1 -0
  14. package/dist/auth/oauth/dcr.d.ts +15 -0
  15. package/dist/auth/oauth/dcr.d.ts.map +1 -0
  16. package/dist/auth/oauth/dcr.js +38 -0
  17. package/dist/auth/oauth/dcr.js.map +1 -0
  18. package/dist/auth/oauth/jwt.d.ts +13 -0
  19. package/dist/auth/oauth/jwt.d.ts.map +1 -0
  20. package/dist/auth/oauth/jwt.js +46 -0
  21. package/dist/auth/oauth/jwt.js.map +1 -0
  22. package/dist/auth/oauth/metadata.d.ts +9 -0
  23. package/dist/auth/oauth/metadata.d.ts.map +1 -0
  24. package/dist/auth/oauth/metadata.js +19 -0
  25. package/dist/auth/oauth/metadata.js.map +1 -0
  26. package/dist/auth/oauth/router.d.ts +32 -0
  27. package/dist/auth/oauth/router.d.ts.map +1 -0
  28. package/dist/auth/oauth/router.js +159 -0
  29. package/dist/auth/oauth/router.js.map +1 -0
  30. package/dist/auth/oauth/store.d.ts +55 -0
  31. package/dist/auth/oauth/store.d.ts.map +1 -0
  32. package/dist/auth/oauth/store.js +63 -0
  33. package/dist/auth/oauth/store.js.map +1 -0
  34. package/dist/auth/oauth/token.d.ts +21 -0
  35. package/dist/auth/oauth/token.d.ts.map +1 -0
  36. package/dist/auth/oauth/token.js +77 -0
  37. package/dist/auth/oauth/token.js.map +1 -0
  38. package/dist/auth/oidc/group-policy.d.ts +43 -0
  39. package/dist/auth/oidc/group-policy.d.ts.map +1 -0
  40. package/dist/auth/oidc/group-policy.js +54 -0
  41. package/dist/auth/oidc/group-policy.js.map +1 -0
  42. package/dist/auth/oidc/verifier.d.ts +42 -0
  43. package/dist/auth/oidc/verifier.d.ts.map +1 -0
  44. package/dist/auth/oidc/verifier.js +145 -0
  45. package/dist/auth/oidc/verifier.js.map +1 -0
  46. package/dist/auth/token-cli.d.ts +9 -0
  47. package/dist/auth/token-cli.d.ts.map +1 -0
  48. package/dist/auth/token-cli.js +98 -0
  49. package/dist/auth/token-cli.js.map +1 -0
  50. package/dist/cli.d.ts +3 -0
  51. package/dist/cli.d.ts.map +1 -0
  52. package/dist/cli.js +149 -0
  53. package/dist/cli.js.map +1 -0
  54. package/dist/config/redact.d.ts +20 -0
  55. package/dist/config/redact.d.ts.map +1 -0
  56. package/dist/config/redact.js +77 -0
  57. package/dist/config/redact.js.map +1 -0
  58. package/dist/config/secrets.d.ts +100 -0
  59. package/dist/config/secrets.d.ts.map +1 -0
  60. package/dist/config/secrets.js +130 -0
  61. package/dist/config/secrets.js.map +1 -0
  62. package/dist/framework/html.d.ts +103 -0
  63. package/dist/framework/html.d.ts.map +1 -0
  64. package/dist/framework/html.js +271 -0
  65. package/dist/framework/html.js.map +1 -0
  66. package/dist/framework/interface.d.ts +130 -0
  67. package/dist/framework/interface.d.ts.map +1 -0
  68. package/dist/framework/interface.js +112 -0
  69. package/dist/framework/interface.js.map +1 -0
  70. package/dist/framework/react.d.ts +133 -0
  71. package/dist/framework/react.d.ts.map +1 -0
  72. package/dist/framework/react.js +243 -0
  73. package/dist/framework/react.js.map +1 -0
  74. package/dist/framework/vue.d.ts +99 -0
  75. package/dist/framework/vue.d.ts.map +1 -0
  76. package/dist/framework/vue.js +375 -0
  77. package/dist/framework/vue.js.map +1 -0
  78. package/dist/index.d.ts +3 -0
  79. package/dist/index.d.ts.map +1 -0
  80. package/dist/index.js +3 -0
  81. package/dist/index.js.map +1 -0
  82. package/dist/llm/client.d.ts +81 -0
  83. package/dist/llm/client.d.ts.map +1 -0
  84. package/dist/llm/client.js +141 -0
  85. package/dist/llm/client.js.map +1 -0
  86. package/dist/llm/component-response.d.ts +111 -0
  87. package/dist/llm/component-response.d.ts.map +1 -0
  88. package/dist/llm/component-response.js +167 -0
  89. package/dist/llm/component-response.js.map +1 -0
  90. package/dist/llm/generated-files.d.ts +10 -0
  91. package/dist/llm/generated-files.d.ts.map +1 -0
  92. package/dist/llm/generated-files.js +26 -0
  93. package/dist/llm/generated-files.js.map +1 -0
  94. package/dist/llm/prompts/CHANGELOG.md +70 -0
  95. package/dist/llm/prompts/generate-component.system.md +99 -0
  96. package/dist/llm/prompts/refine-component.system.md +112 -0
  97. package/dist/llm/prompts.d.ts +66 -0
  98. package/dist/llm/prompts.d.ts.map +1 -0
  99. package/dist/llm/prompts.js +78 -0
  100. package/dist/llm/prompts.js.map +1 -0
  101. package/dist/llm/retry.d.ts +183 -0
  102. package/dist/llm/retry.d.ts.map +1 -0
  103. package/dist/llm/retry.js +475 -0
  104. package/dist/llm/retry.js.map +1 -0
  105. package/dist/llm/schema.d.ts +129 -0
  106. package/dist/llm/schema.d.ts.map +1 -0
  107. package/dist/llm/schema.js +147 -0
  108. package/dist/llm/schema.js.map +1 -0
  109. package/dist/llm/validate.d.ts +107 -0
  110. package/dist/llm/validate.d.ts.map +1 -0
  111. package/dist/llm/validate.js +174 -0
  112. package/dist/llm/validate.js.map +1 -0
  113. package/dist/manifest/compiler.d.ts +112 -0
  114. package/dist/manifest/compiler.d.ts.map +1 -0
  115. package/dist/manifest/compiler.js +306 -0
  116. package/dist/manifest/compiler.js.map +1 -0
  117. package/dist/manifest/ensure.d.ts +46 -0
  118. package/dist/manifest/ensure.d.ts.map +1 -0
  119. package/dist/manifest/ensure.js +49 -0
  120. package/dist/manifest/ensure.js.map +1 -0
  121. package/dist/manifest/index.d.ts +13 -0
  122. package/dist/manifest/index.d.ts.map +1 -0
  123. package/dist/manifest/index.js +13 -0
  124. package/dist/manifest/index.js.map +1 -0
  125. package/dist/middleware/plan-guard.d.ts +167 -0
  126. package/dist/middleware/plan-guard.d.ts.map +1 -0
  127. package/dist/middleware/plan-guard.js +190 -0
  128. package/dist/middleware/plan-guard.js.map +1 -0
  129. package/dist/plans/index.d.ts +71 -0
  130. package/dist/plans/index.d.ts.map +1 -0
  131. package/dist/plans/index.js +252 -0
  132. package/dist/plans/index.js.map +1 -0
  133. package/dist/schemas/component.schema.json +114 -0
  134. package/dist/server.d.ts +96 -0
  135. package/dist/server.d.ts.map +1 -0
  136. package/dist/server.js +258 -0
  137. package/dist/server.js.map +1 -0
  138. package/dist/store/empty-manifest.d.ts +58 -0
  139. package/dist/store/empty-manifest.d.ts.map +1 -0
  140. package/dist/store/empty-manifest.js +59 -0
  141. package/dist/store/empty-manifest.js.map +1 -0
  142. package/dist/store/git-host.d.ts +120 -0
  143. package/dist/store/git-host.d.ts.map +1 -0
  144. package/dist/store/git-host.js +796 -0
  145. package/dist/store/git-host.js.map +1 -0
  146. package/dist/store/index.d.ts +5 -0
  147. package/dist/store/index.d.ts.map +1 -0
  148. package/dist/store/index.js +4 -0
  149. package/dist/store/index.js.map +1 -0
  150. package/dist/store/interface.d.ts +322 -0
  151. package/dist/store/interface.d.ts.map +1 -0
  152. package/dist/store/interface.js +100 -0
  153. package/dist/store/interface.js.map +1 -0
  154. package/dist/store/kit-files.d.ts +88 -0
  155. package/dist/store/kit-files.d.ts.map +1 -0
  156. package/dist/store/kit-files.js +199 -0
  157. package/dist/store/kit-files.js.map +1 -0
  158. package/dist/store/local.d.ts +70 -0
  159. package/dist/store/local.d.ts.map +1 -0
  160. package/dist/store/local.js +651 -0
  161. package/dist/store/local.js.map +1 -0
  162. package/dist/store/manifest.d.ts +44 -0
  163. package/dist/store/manifest.d.ts.map +1 -0
  164. package/dist/store/manifest.js +116 -0
  165. package/dist/store/manifest.js.map +1 -0
  166. package/dist/store/viewer-assets.d.ts +20 -0
  167. package/dist/store/viewer-assets.d.ts.map +1 -0
  168. package/dist/store/viewer-assets.js +118 -0
  169. package/dist/store/viewer-assets.js.map +1 -0
  170. package/dist/sync/anchor.d.ts +125 -0
  171. package/dist/sync/anchor.d.ts.map +1 -0
  172. package/dist/sync/anchor.js +210 -0
  173. package/dist/sync/anchor.js.map +1 -0
  174. package/dist/sync/index.d.ts +15 -0
  175. package/dist/sync/index.d.ts.map +1 -0
  176. package/dist/sync/index.js +15 -0
  177. package/dist/sync/index.js.map +1 -0
  178. package/dist/sync/orchestrator.d.ts +160 -0
  179. package/dist/sync/orchestrator.d.ts.map +1 -0
  180. package/dist/sync/orchestrator.js +288 -0
  181. package/dist/sync/orchestrator.js.map +1 -0
  182. package/dist/tools/bind_kit.d.ts +29 -0
  183. package/dist/tools/bind_kit.d.ts.map +1 -0
  184. package/dist/tools/bind_kit.js +70 -0
  185. package/dist/tools/bind_kit.js.map +1 -0
  186. package/dist/tools/conjure.d.ts +141 -0
  187. package/dist/tools/conjure.d.ts.map +1 -0
  188. package/dist/tools/conjure.js +655 -0
  189. package/dist/tools/conjure.js.map +1 -0
  190. package/dist/tools/conjure_screen.d.ts +174 -0
  191. package/dist/tools/conjure_screen.d.ts.map +1 -0
  192. package/dist/tools/conjure_screen.js +458 -0
  193. package/dist/tools/conjure_screen.js.map +1 -0
  194. package/dist/tools/create_kit.d.ts +32 -0
  195. package/dist/tools/create_kit.d.ts.map +1 -0
  196. package/dist/tools/create_kit.js +131 -0
  197. package/dist/tools/create_kit.js.map +1 -0
  198. package/dist/tools/create_project.d.ts +267 -0
  199. package/dist/tools/create_project.d.ts.map +1 -0
  200. package/dist/tools/create_project.js +546 -0
  201. package/dist/tools/create_project.js.map +1 -0
  202. package/dist/tools/delete_files.d.ts +93 -0
  203. package/dist/tools/delete_files.d.ts.map +1 -0
  204. package/dist/tools/delete_files.js +276 -0
  205. package/dist/tools/delete_files.js.map +1 -0
  206. package/dist/tools/delete_project.d.ts +43 -0
  207. package/dist/tools/delete_project.d.ts.map +1 -0
  208. package/dist/tools/delete_project.js +118 -0
  209. package/dist/tools/delete_project.js.map +1 -0
  210. package/dist/tools/get_kit.d.ts +28 -0
  211. package/dist/tools/get_kit.d.ts.map +1 -0
  212. package/dist/tools/get_kit.js +95 -0
  213. package/dist/tools/get_kit.js.map +1 -0
  214. package/dist/tools/get_project.d.ts +37 -0
  215. package/dist/tools/get_project.d.ts.map +1 -0
  216. package/dist/tools/get_project.js +71 -0
  217. package/dist/tools/get_project.js.map +1 -0
  218. package/dist/tools/list_components.d.ts +42 -0
  219. package/dist/tools/list_components.d.ts.map +1 -0
  220. package/dist/tools/list_components.js +125 -0
  221. package/dist/tools/list_components.js.map +1 -0
  222. package/dist/tools/list_files.d.ts +32 -0
  223. package/dist/tools/list_files.d.ts.map +1 -0
  224. package/dist/tools/list_files.js +109 -0
  225. package/dist/tools/list_files.js.map +1 -0
  226. package/dist/tools/list_kits.d.ts +14 -0
  227. package/dist/tools/list_kits.d.ts.map +1 -0
  228. package/dist/tools/list_kits.js +41 -0
  229. package/dist/tools/list_kits.js.map +1 -0
  230. package/dist/tools/list_projects.d.ts +23 -0
  231. package/dist/tools/list_projects.d.ts.map +1 -0
  232. package/dist/tools/list_projects.js +66 -0
  233. package/dist/tools/list_projects.js.map +1 -0
  234. package/dist/tools/plan.d.ts +16 -0
  235. package/dist/tools/plan.d.ts.map +1 -0
  236. package/dist/tools/plan.js +146 -0
  237. package/dist/tools/plan.js.map +1 -0
  238. package/dist/tools/preview.d.ts +289 -0
  239. package/dist/tools/preview.d.ts.map +1 -0
  240. package/dist/tools/preview.js +672 -0
  241. package/dist/tools/preview.js.map +1 -0
  242. package/dist/tools/read_file.d.ts +40 -0
  243. package/dist/tools/read_file.d.ts.map +1 -0
  244. package/dist/tools/read_file.js +114 -0
  245. package/dist/tools/read_file.js.map +1 -0
  246. package/dist/tools/refine.d.ts +220 -0
  247. package/dist/tools/refine.d.ts.map +1 -0
  248. package/dist/tools/refine.js +501 -0
  249. package/dist/tools/refine.js.map +1 -0
  250. package/dist/tools/validate.d.ts +74 -0
  251. package/dist/tools/validate.d.ts.map +1 -0
  252. package/dist/tools/validate.js +224 -0
  253. package/dist/tools/validate.js.map +1 -0
  254. package/dist/tools/write_files.d.ts +158 -0
  255. package/dist/tools/write_files.d.ts.map +1 -0
  256. package/dist/tools/write_files.js +541 -0
  257. package/dist/tools/write_files.js.map +1 -0
  258. package/dist/transport.d.ts +77 -0
  259. package/dist/transport.d.ts.map +1 -0
  260. package/dist/transport.js +448 -0
  261. package/dist/transport.js.map +1 -0
  262. package/dist/ui/card-asset-broker.d.ts +42 -0
  263. package/dist/ui/card-asset-broker.d.ts.map +1 -0
  264. package/dist/ui/card-asset-broker.js +479 -0
  265. package/dist/ui/card-asset-broker.js.map +1 -0
  266. package/dist/ui/grid-resource.d.ts +252 -0
  267. package/dist/ui/grid-resource.d.ts.map +1 -0
  268. package/dist/ui/grid-resource.js +680 -0
  269. package/dist/ui/grid-resource.js.map +1 -0
  270. package/dist/ui/viewer-static/index.html +95 -0
  271. package/dist/ui/viewer-static/viewer.css +451 -0
  272. package/dist/ui/viewer-static/viewer.js +1405 -0
  273. package/dist/validate/full-scan.d.ts +87 -0
  274. package/dist/validate/full-scan.d.ts.map +1 -0
  275. package/dist/validate/full-scan.js +299 -0
  276. package/dist/validate/full-scan.js.map +1 -0
  277. package/dist/validate/index.d.ts +15 -0
  278. package/dist/validate/index.d.ts.map +1 -0
  279. package/dist/validate/index.js +18 -0
  280. package/dist/validate/index.js.map +1 -0
  281. package/dist/validate/marker.d.ts +89 -0
  282. package/dist/validate/marker.d.ts.map +1 -0
  283. package/dist/validate/marker.js +87 -0
  284. package/dist/validate/marker.js.map +1 -0
  285. package/dist/validate/phash.d.ts +135 -0
  286. package/dist/validate/phash.d.ts.map +1 -0
  287. package/dist/validate/phash.js +307 -0
  288. package/dist/validate/phash.js.map +1 -0
  289. package/dist/validate/render.d.ts +38 -0
  290. package/dist/validate/render.d.ts.map +1 -0
  291. package/dist/validate/render.js +155 -0
  292. package/dist/validate/render.js.map +1 -0
  293. package/dist/watch/index.d.ts +12 -0
  294. package/dist/watch/index.d.ts.map +1 -0
  295. package/dist/watch/index.js +12 -0
  296. package/dist/watch/index.js.map +1 -0
  297. package/dist/watch/watcher.d.ts +65 -0
  298. package/dist/watch/watcher.d.ts.map +1 -0
  299. package/dist/watch/watcher.js +238 -0
  300. package/dist/watch/watcher.js.map +1 -0
  301. package/package.json +70 -0
@@ -0,0 +1,130 @@
1
+ /**
2
+ * `FrameworkAdapter` (M2-08 · DRO-255) — the seam that abstracts `conjure`'s
3
+ * framework-specific bits so **React lands in v1** and **Vue / vanilla HTML** can
4
+ * be added later *without refactoring the generation pipeline*.
5
+ *
6
+ * ── Why an adapter, and what it does *not* touch ─────────────────────────────
7
+ * `conjure` (M2-03) is pure generation: the configured LLM returns the whole
8
+ * validated `COMPONENT_SCHEMA` file set (source + `<Name>.html` preview + manifest
9
+ * metadata), and `conjure` never post-processes it. The *only* framework-specific
10
+ * bit `conjure` carries today is the "Target framework: …" prompt directive. This
11
+ * adapter owns that directive (via {@link FrameworkAdapter.promptDirective}) plus
12
+ * the three codegen operations — and the default-viewport metadata — a *future*
13
+ * pipeline (M4 preview compile, refine post-processing) will need per framework
14
+ * (the first three are codegen; `defaultViewport` is metadata, not codegen):
15
+ *
16
+ * - {@link FrameworkAdapter.renderSource} — the canonical source file
17
+ * - {@link FrameworkAdapter.renderPreview} — a browser-ready preview bundle (IIFE)
18
+ * - {@link FrameworkAdapter.extractDts} — the component's `.d.ts` typings
19
+ * - {@link FrameworkAdapter.defaultViewport} — the card size for this framework
20
+ *
21
+ * Cribs the staged-IR shape from `Kinglions/ui-design-to-code-mcp` (research §5
22
+ * prior art #3: `ingest_* → build_semantic_ir → build_cross_platform_nodes →
23
+ * build_target_*`): {@link RenderInput} is the neutral semantic node the three
24
+ * `render*`/`extract*` methods lower into a concrete target artefact.
25
+ *
26
+ * Only {@link ReactAdapter} implemented the codegen methods in v1; {@link VueAdapter}
27
+ * (DRO-616) and {@link HtmlAdapter} (DRO-617) graduated from stubs to real adapters
28
+ * in v2, so every framework now implements the full contract. The
29
+ * {@link NotYetImplementedError} + tracking-issue convention (AC3) is retained for
30
+ * the next framework that ships as a stub — a stub constructs fine and exposes its
31
+ * identity + viewport (so `conjure`'s adapter selection never breaks for it) while
32
+ * its codegen methods throw the structured, linked error.
33
+ */
34
+ /**
35
+ * The frameworks `conjure` can target (research §3.1: `"react" | "vue" | "html"`).
36
+ * Single source of truth: `conjure` re-exports these as `CONJURE_FRAMEWORKS` /
37
+ * `ConjureFramework` so the tool boundary and the adapter registry can never drift.
38
+ */
39
+ export declare const FRAMEWORKS: readonly ["react", "vue", "html"];
40
+ export type Framework = (typeof FRAMEWORKS)[number];
41
+ /** Default target framework (AC2 — React is the v1 framework). */
42
+ export declare const DEFAULT_FRAMEWORK: Framework;
43
+ /**
44
+ * Card/preview dimensions for a framework. Mirrors the `Viewport` `$def` in
45
+ * `COMPONENT_SCHEMA` (M2-02) so an adapter-supplied fallback slots straight into
46
+ * a `manifestEntry.viewport` without a shape conversion.
47
+ */
48
+ export interface Viewport {
49
+ width: number;
50
+ height: number;
51
+ }
52
+ /**
53
+ * The neutral, framework-agnostic description of the component to lower — the
54
+ * "semantic IR node" the adapter's target methods consume. `source` is the
55
+ * framework's own source text (for React: the `.tsx`); `componentName` is
56
+ * PascalCase and `group` is kebab-case, matching `COMPONENT_SCHEMA`.
57
+ */
58
+ export interface RenderInput {
59
+ componentName: string;
60
+ group: string;
61
+ source: string;
62
+ }
63
+ /**
64
+ * A single emitted file. Deliberately the exact shape of a `COMPONENT_SCHEMA`
65
+ * `files[]` entry (`{ path, content, mimeType }`) so adapter output composes
66
+ * directly into a component's file set, and every `path` matches the schema's
67
+ * `components/<group>/<Name>/…` `PATH_PATTERN`.
68
+ */
69
+ export interface AdapterFile {
70
+ path: string;
71
+ content: string;
72
+ mimeType: string;
73
+ }
74
+ /**
75
+ * The framework adapter contract (AC1). Metadata (`framework`, `defaultViewport`)
76
+ * is always available — `conjure` reads it during adapter selection for *every*
77
+ * framework, including the stubs. The three codegen methods are what a stub
78
+ * leaves unimplemented.
79
+ */
80
+ export interface FrameworkAdapter {
81
+ /** This adapter's framework identity (drives `conjure`'s prompt directive). */
82
+ readonly framework: Framework;
83
+ /** Default card size when a caller has no better viewport (AC1). */
84
+ readonly defaultViewport: Viewport;
85
+ /**
86
+ * The framework-specific instruction block `conjure` injects into the user
87
+ * message (AC4 — the one framework-specific bit `conjure` carries today, now
88
+ * owned by the adapter). Begins with `Target framework: <framework>` so the
89
+ * generation prompt names the target unambiguously, then adds any per-framework
90
+ * source-shape guidance. Available on **every** adapter (stubs included) — it
91
+ * is metadata the *model* uses, not codegen, so `conjure` (pure LLM generation)
92
+ * works for all three frameworks even while Vue/HTML codegen is stubbed.
93
+ */
94
+ readonly promptDirective: string;
95
+ /** Lower the IR to the canonical source file (React: `<Name>.tsx`) (AC1). */
96
+ renderSource(input: RenderInput): AdapterFile;
97
+ /** Bundle the component to a browser-ready preview IIFE (AC1/AC2). Async: it
98
+ * lazy-loads esbuild so resolving an adapter never pulls the bundler until a
99
+ * preview is actually built. */
100
+ renderPreview(input: RenderInput): Promise<AdapterFile>;
101
+ /** Extract the component's `.d.ts` typings (React: via `ts-morph`) (AC1/AC2).
102
+ * Async for the same lazy-load reason as {@link renderPreview}. */
103
+ extractDts(input: RenderInput): Promise<AdapterFile>;
104
+ }
105
+ /**
106
+ * Structured error a stub adapter throws from its codegen methods (AC3). Carries
107
+ * the `framework` and a `trackingIssue` URL so a caller (or the MCP tool
108
+ * boundary) can surface *which* framework is missing and *where* to follow its
109
+ * v2 implementation — not just an opaque "not implemented".
110
+ */
111
+ export declare class NotYetImplementedError extends Error {
112
+ readonly framework: Framework;
113
+ readonly trackingIssue: string;
114
+ readonly code: "ERR_FRAMEWORK_NOT_IMPLEMENTED";
115
+ constructor(framework: Framework, trackingIssue: string);
116
+ }
117
+ /**
118
+ * Build the shared `components/<group>/<Name>/<basename>` path every adapter
119
+ * file lives under, so the on-disk layout stays identical across frameworks and
120
+ * matches `COMPONENT_SCHEMA`'s `PATH_PATTERN`.
121
+ */
122
+ export declare function componentPath(input: RenderInput, basename: string): string;
123
+ /**
124
+ * Resolve the {@link FrameworkAdapter} for a framework (AC4). `conjure` calls
125
+ * this to pick the adapter from its `framework` input. Throws `RangeError` for a
126
+ * value outside {@link FRAMEWORKS} — but `conjure`'s Zod enum already rejects
127
+ * those upstream, so in practice this only ever sees a valid framework.
128
+ */
129
+ export declare function getAdapter(framework: Framework): Promise<FrameworkAdapter>;
130
+ //# sourceMappingURL=interface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interface.d.ts","sourceRoot":"","sources":["../../src/framework/interface.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH;;;;GAIG;AACH,eAAO,MAAM,UAAU,mCAAoC,CAAC;AAC5D,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC;AAEpD,kEAAkE;AAClE,eAAO,MAAM,iBAAiB,EAAE,SAAmB,CAAC;AAEpD;;;;GAIG;AACH,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B,+EAA+E;IAC/E,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAC9B,oEAAoE;IACpE,QAAQ,CAAC,eAAe,EAAE,QAAQ,CAAC;IACnC;;;;;;;;OAQG;IACH,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,6EAA6E;IAC7E,YAAY,CAAC,KAAK,EAAE,WAAW,GAAG,WAAW,CAAC;IAC9C;;oCAEgC;IAChC,aAAa,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IACxD;uEACmE;IACnE,UAAU,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;CACtD;AAED;;;;;GAKG;AACH,qBAAa,sBAAuB,SAAQ,KAAK;IAG7C,QAAQ,CAAC,SAAS,EAAE,SAAS;IAC7B,QAAQ,CAAC,aAAa,EAAE,MAAM;IAHhC,QAAQ,CAAC,IAAI,EAAG,+BAA+B,CAAU;gBAE9C,SAAS,EAAE,SAAS,EACpB,aAAa,EAAE,MAAM;CAQjC;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE1E;AAWD;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA8BhF"}
@@ -0,0 +1,112 @@
1
+ /**
2
+ * `FrameworkAdapter` (M2-08 · DRO-255) — the seam that abstracts `conjure`'s
3
+ * framework-specific bits so **React lands in v1** and **Vue / vanilla HTML** can
4
+ * be added later *without refactoring the generation pipeline*.
5
+ *
6
+ * ── Why an adapter, and what it does *not* touch ─────────────────────────────
7
+ * `conjure` (M2-03) is pure generation: the configured LLM returns the whole
8
+ * validated `COMPONENT_SCHEMA` file set (source + `<Name>.html` preview + manifest
9
+ * metadata), and `conjure` never post-processes it. The *only* framework-specific
10
+ * bit `conjure` carries today is the "Target framework: …" prompt directive. This
11
+ * adapter owns that directive (via {@link FrameworkAdapter.promptDirective}) plus
12
+ * the three codegen operations — and the default-viewport metadata — a *future*
13
+ * pipeline (M4 preview compile, refine post-processing) will need per framework
14
+ * (the first three are codegen; `defaultViewport` is metadata, not codegen):
15
+ *
16
+ * - {@link FrameworkAdapter.renderSource} — the canonical source file
17
+ * - {@link FrameworkAdapter.renderPreview} — a browser-ready preview bundle (IIFE)
18
+ * - {@link FrameworkAdapter.extractDts} — the component's `.d.ts` typings
19
+ * - {@link FrameworkAdapter.defaultViewport} — the card size for this framework
20
+ *
21
+ * Cribs the staged-IR shape from `Kinglions/ui-design-to-code-mcp` (research §5
22
+ * prior art #3: `ingest_* → build_semantic_ir → build_cross_platform_nodes →
23
+ * build_target_*`): {@link RenderInput} is the neutral semantic node the three
24
+ * `render*`/`extract*` methods lower into a concrete target artefact.
25
+ *
26
+ * Only {@link ReactAdapter} implemented the codegen methods in v1; {@link VueAdapter}
27
+ * (DRO-616) and {@link HtmlAdapter} (DRO-617) graduated from stubs to real adapters
28
+ * in v2, so every framework now implements the full contract. The
29
+ * {@link NotYetImplementedError} + tracking-issue convention (AC3) is retained for
30
+ * the next framework that ships as a stub — a stub constructs fine and exposes its
31
+ * identity + viewport (so `conjure`'s adapter selection never breaks for it) while
32
+ * its codegen methods throw the structured, linked error.
33
+ */
34
+ /**
35
+ * The frameworks `conjure` can target (research §3.1: `"react" | "vue" | "html"`).
36
+ * Single source of truth: `conjure` re-exports these as `CONJURE_FRAMEWORKS` /
37
+ * `ConjureFramework` so the tool boundary and the adapter registry can never drift.
38
+ */
39
+ export const FRAMEWORKS = ["react", "vue", "html"];
40
+ /** Default target framework (AC2 — React is the v1 framework). */
41
+ export const DEFAULT_FRAMEWORK = "react";
42
+ /**
43
+ * Structured error a stub adapter throws from its codegen methods (AC3). Carries
44
+ * the `framework` and a `trackingIssue` URL so a caller (or the MCP tool
45
+ * boundary) can surface *which* framework is missing and *where* to follow its
46
+ * v2 implementation — not just an opaque "not implemented".
47
+ */
48
+ export class NotYetImplementedError extends Error {
49
+ framework;
50
+ trackingIssue;
51
+ code = "ERR_FRAMEWORK_NOT_IMPLEMENTED";
52
+ constructor(framework, trackingIssue) {
53
+ super(`The "${framework}" framework adapter is not implemented yet — React is the ` +
54
+ `only framework supported in v1. Track its v2 implementation at ${trackingIssue}.`);
55
+ this.framework = framework;
56
+ this.trackingIssue = trackingIssue;
57
+ this.name = "NotYetImplementedError";
58
+ }
59
+ }
60
+ /**
61
+ * Build the shared `components/<group>/<Name>/<basename>` path every adapter
62
+ * file lives under, so the on-disk layout stays identical across frameworks and
63
+ * matches `COMPONENT_SCHEMA`'s `PATH_PATTERN`.
64
+ */
65
+ export function componentPath(input, basename) {
66
+ return `components/${input.group}/${input.componentName}/${basename}`;
67
+ }
68
+ // ── Registry (AC4) ─────────────────────────────────────────────────────────────
69
+ //
70
+ // Lazy singletons: adapters are cheap to construct, but keeping one instance
71
+ // each avoids re-allocating on every `conjure` call. Populated on first
72
+ // `getAdapter` via dynamic import so `interface.ts` stays free of a static
73
+ // dependency on the concrete adapters (and their esbuild/ts-morph imports).
74
+ const cache = new Map();
75
+ /**
76
+ * Resolve the {@link FrameworkAdapter} for a framework (AC4). `conjure` calls
77
+ * this to pick the adapter from its `framework` input. Throws `RangeError` for a
78
+ * value outside {@link FRAMEWORKS} — but `conjure`'s Zod enum already rejects
79
+ * those upstream, so in practice this only ever sees a valid framework.
80
+ */
81
+ export async function getAdapter(framework) {
82
+ const cached = cache.get(framework);
83
+ if (cached)
84
+ return cached;
85
+ let adapter;
86
+ switch (framework) {
87
+ case "react": {
88
+ const { ReactAdapter } = await import("./react.js");
89
+ adapter = new ReactAdapter();
90
+ break;
91
+ }
92
+ case "vue": {
93
+ const { VueAdapter } = await import("./vue.js");
94
+ adapter = new VueAdapter();
95
+ break;
96
+ }
97
+ case "html": {
98
+ const { HtmlAdapter } = await import("./html.js");
99
+ adapter = new HtmlAdapter();
100
+ break;
101
+ }
102
+ default: {
103
+ // Exhaustiveness guard: if `Framework` gains a member, this errors at
104
+ // compile time (never at runtime for a Zod-validated input).
105
+ const never = framework;
106
+ throw new RangeError(`Unknown framework: ${String(never)}`);
107
+ }
108
+ }
109
+ cache.set(framework, adapter);
110
+ return adapter;
111
+ }
112
+ //# sourceMappingURL=interface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interface.js","sourceRoot":"","sources":["../../src/framework/interface.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH;;;;GAIG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,OAAO,EAAE,KAAK,EAAE,MAAM,CAAU,CAAC;AAG5D,kEAAkE;AAClE,MAAM,CAAC,MAAM,iBAAiB,GAAc,OAAO,CAAC;AAoEpD;;;;;GAKG;AACH,MAAM,OAAO,sBAAuB,SAAQ,KAAK;IAGpC;IACA;IAHF,IAAI,GAAG,+BAAwC,CAAC;IACzD,YACW,SAAoB,EACpB,aAAqB;QAE9B,KAAK,CACH,QAAQ,SAAS,4DAA4D;YAC3E,kEAAkE,aAAa,GAAG,CACrF,CAAC;QANO,cAAS,GAAT,SAAS,CAAW;QACpB,kBAAa,GAAb,aAAa,CAAQ;QAM9B,IAAI,CAAC,IAAI,GAAG,wBAAwB,CAAC;IACvC,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,KAAkB,EAAE,QAAgB;IAChE,OAAO,cAAc,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,aAAa,IAAI,QAAQ,EAAE,CAAC;AACxE,CAAC;AAED,kFAAkF;AAClF,EAAE;AACF,6EAA6E;AAC7E,wEAAwE;AACxE,2EAA2E;AAC3E,4EAA4E;AAE5E,MAAM,KAAK,GAAG,IAAI,GAAG,EAA+B,CAAC;AAErD;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,SAAoB;IACnD,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IACpC,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAE1B,IAAI,OAAyB,CAAC;IAC9B,QAAQ,SAAS,EAAE,CAAC;QAClB,KAAK,OAAO,CAAC,CAAC,CAAC;YACb,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,CAAC;YACpD,OAAO,GAAG,IAAI,YAAY,EAAE,CAAC;YAC7B,MAAM;QACR,CAAC;QACD,KAAK,KAAK,CAAC,CAAC,CAAC;YACX,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC;YAChD,OAAO,GAAG,IAAI,UAAU,EAAE,CAAC;YAC3B,MAAM;QACR,CAAC;QACD,KAAK,MAAM,CAAC,CAAC,CAAC;YACZ,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC;YAClD,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;YAC5B,MAAM;QACR,CAAC;QACD,OAAO,CAAC,CAAC,CAAC;YACR,sEAAsE;YACtE,6DAA6D;YAC7D,MAAM,KAAK,GAAU,SAAS,CAAC;YAC/B,MAAM,IAAI,UAAU,CAAC,sBAAsB,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC;IACD,KAAK,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IAC9B,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -0,0 +1,133 @@
1
+ /**
2
+ * `ReactAdapter` (M2-08 · DRO-255 · AC2) — the v1 framework adapter.
3
+ *
4
+ * Lowers a neutral {@link RenderInput} (the component's `.tsx` source) into the
5
+ * three React target artefacts:
6
+ * - {@link ReactAdapter.renderSource} → `<Name>.tsx` (the canonical source)
7
+ * - {@link ReactAdapter.renderPreview} → `<Name>.preview.js` — an **esbuild IIFE
8
+ * bundle** exposing the component on `globalThis.GenieComponent` for the M4
9
+ * iframe grid to mount
10
+ * - {@link ReactAdapter.extractDts} → `<Name>.d.ts` — the component's typings,
11
+ * extracted with **ts-morph** (declaration-only in-memory emit)
12
+ *
13
+ * ── Import-time safety ────────────────────────────────────────────────────────
14
+ * `esbuild` and `ts-morph` are heavy transitive graphs. Neither is imported at
15
+ * this module's top level — each is reached through a lazy `await import(...)`
16
+ * *inside* the one method that needs it. So the registry
17
+ * (`interface.ts#getAdapter`) can resolve a `ReactAdapter` — and `conjure` can
18
+ * read its `promptDirective` / `defaultViewport` on the generation hot path —
19
+ * without ever pulling the bundler or the TS compiler, which only load when a
20
+ * preview/`.d.ts` is actually produced (M4 preview compile, refine post-process).
21
+ *
22
+ * The only esbuild reference at module scope is the `import type` below: it is a
23
+ * types-only import (erased at compile under `verbatimModuleSyntax`), so it emits
24
+ * no runtime `require("esbuild")` and does not defeat the lazy-load above.
25
+ */
26
+ import type { Plugin } from "esbuild";
27
+ import { type AdapterFile, type FrameworkAdapter, type Framework, type RenderInput, type Viewport } from "./interface.js";
28
+ /**
29
+ * The global the preview IIFE binds the component to. M4's iframe grid reads
30
+ * `window.GenieComponent` to mount the card; keeping the name here (not in M4)
31
+ * makes the adapter the single source of truth for the preview contract.
32
+ */
33
+ export declare const PREVIEW_GLOBAL_NAME = "GenieComponent";
34
+ /**
35
+ * ── Preview host contract (DRO-624 · AC1) — the single source of truth ────────
36
+ *
37
+ * The `<Name>.preview.js` bundle this adapter emits does **not** carry its own
38
+ * copy of React, nor does it `require("react")`. It resolves React from two
39
+ * **host-provided browser globals** the preview iframe must define *before* the
40
+ * bundle's `<script>` runs:
41
+ *
42
+ * - `window.{@link REACT_HOST_GLOBAL}` → the React runtime (`window.React`)
43
+ * - `window.{@link REACT_DOM_HOST_GLOBAL}` → the ReactDOM runtime (`window.ReactDOM`)
44
+ *
45
+ * and it exposes the compiled component on `window.{@link PREVIEW_GLOBAL_NAME}`
46
+ * (`{ default, <Name> }`), which the M4-03 iframe grid mounts with the same host
47
+ * `ReactDOM`.
48
+ *
49
+ * ── Why globals, not esbuild `external` ───────────────────────────────────────
50
+ * The original M2-08 code marked React `external` under `format:"iife"`. esbuild
51
+ * has no facility to map an external bare specifier to a browser global, so it
52
+ * lowered `import … from "react"` (plus the `jsx:"automatic"` runtime import)
53
+ * into `require("react")` / `require("react/jsx-runtime")` — calls that throw
54
+ * `Uncaught Error: Dynamic require of "react" is not supported`
55
+ * the instant the IIFE evaluates inside the iframe (no CommonJS `require` there).
56
+ * The bundle would never mount. (Flagged by Copilot on PR #131 `react.ts:103`,
57
+ * merged unresolved; the M2-08 conformance test only asserted on bundle *text*,
58
+ * so it never surfaced.) The fix — {@link hostReactGlobalsPlugin} — intercepts
59
+ * those specifiers at bundle time and rewrites them to read the host globals.
60
+ *
61
+ * ── How the host provides the globals (PRD §6.6 / FR-056) ─────────────────────
62
+ * Per the on-disk layout (PRD §6.6) each kit vendors the runtime under `_vendor/`:
63
+ * `_vendor/react.production.min.js` + `_vendor/react-dom.production.min.js`.
64
+ * The iframe host page `<script>`-includes those UMD builds (which self-assign
65
+ * `window.React` / `window.ReactDOM`) ahead of the component bundle. This is the
66
+ * global-based contract FR-056 already describes for the aggregate
67
+ * `_genie_bundle.js` (`window.<KitGlobal>.<Component>`); a single-component
68
+ * preview is the same shape narrowed to one export exposed on
69
+ * `window.{@link PREVIEW_GLOBAL_NAME}`.
70
+ *
71
+ * NOTE — **React 18, UMD**: the contract depends on a runtime that ships a UMD
72
+ * build defining a `window.React` global. React 19 removed the UMD builds, so
73
+ * the vendored `_vendor/react*.min.js` must be the React 18 UMD production
74
+ * bundles (the adapter's execution test pins the same major).
75
+ */
76
+ export declare const REACT_HOST_GLOBAL = "React";
77
+ export declare const REACT_DOM_HOST_GLOBAL = "ReactDOM";
78
+ /**
79
+ * esbuild plugin implementing the {@link REACT_HOST_GLOBAL} contract (DRO-624 ·
80
+ * AC2). It intercepts every React bare specifier the source (or the automatic
81
+ * JSX transform) can reference and resolves it to an in-memory virtual module
82
+ * that reads the corresponding host global — so the emitted IIFE contains **no**
83
+ * `require("react")` and instead references `window.React` / `window.ReactDOM`.
84
+ *
85
+ * - `react` → `window.React`
86
+ * - `react-dom`, `react-dom/client` → `window.ReactDOM`
87
+ * - `react/jsx-runtime`, `…/jsx-dev-runtime` → {@link JSX_RUNTIME_SHIM}
88
+ */
89
+ export declare function hostReactGlobalsPlugin(): Plugin;
90
+ export declare class ReactAdapter implements FrameworkAdapter {
91
+ readonly framework: Framework;
92
+ /**
93
+ * A comfortable default card for a React component when the caller has no
94
+ * better viewport. Matches the RFC's default preview grid cell (§7.5).
95
+ */
96
+ readonly defaultViewport: Viewport;
97
+ /**
98
+ * The framework directive `conjure` injects into the generation prompt (AC4):
99
+ * name the target framework and the React source shape the model should emit.
100
+ */
101
+ readonly promptDirective: string;
102
+ /**
103
+ * The canonical source file: `<Name>.tsx`, carrying the model-authored source
104
+ * verbatim. `text/tsx` mirrors the mimeType the M2-03 fixtures already use for
105
+ * `.tsx` entries.
106
+ */
107
+ renderSource(input: RenderInput): AdapterFile;
108
+ /**
109
+ * Bundle the component to a browser-ready **IIFE** exposing it on
110
+ * `globalThis.${PREVIEW_GLOBAL_NAME}` (AC2). React is resolved from the host
111
+ * iframe's globals via {@link hostReactGlobalsPlugin} — see the *Preview host
112
+ * contract* above — so the output is a single self-contained script the M4
113
+ * iframe can `<script>`-include and mount with its own vendored React, with no
114
+ * `Dynamic require of "react"` at runtime (DRO-624).
115
+ *
116
+ * esbuild is imported lazily here (not at module top) so resolving a
117
+ * `ReactAdapter` — which the registry does on first `getAdapter("react")` —
118
+ * doesn't pull esbuild's native binary until a preview is actually built.
119
+ */
120
+ renderPreview(input: RenderInput): Promise<AdapterFile>;
121
+ /**
122
+ * Extract the component's `.d.ts` typings with ts-morph (AC2), via an
123
+ * in-memory declaration-only emit so nothing touches disk. The virtual project
124
+ * carries `jsx: react-jsx` + `skipLibCheck` so a `.tsx` source with JSX and
125
+ * bare `react` imports emits declarations even without `@types/react` present
126
+ * in the virtual FS (we never type-check, only emit declarations).
127
+ *
128
+ * ts-morph is imported lazily (not at module top) for the same reason as
129
+ * esbuild in {@link renderPreview}: keep resolving the adapter cheap.
130
+ */
131
+ extractDts(input: RenderInput): Promise<AdapterFile>;
132
+ }
133
+ //# sourceMappingURL=react.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../../src/framework/react.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEtC,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,gBAAgB,EACrB,KAAK,SAAS,EACd,KAAK,WAAW,EAChB,KAAK,QAAQ,EACd,MAAM,gBAAgB,CAAC;AAExB;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,mBAAmB,CAAC;AAEpD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,eAAO,MAAM,iBAAiB,UAAU,CAAC;AACzC,eAAO,MAAM,qBAAqB,aAAa,CAAC;AAgDhD;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,CAyB/C;AAED,qBAAa,YAAa,YAAW,gBAAgB;IACnD,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAW;IAExC;;;OAGG;IACH,QAAQ,CAAC,eAAe,EAAE,QAAQ,CAA+B;IAEjE;;;OAGG;IACH,QAAQ,CAAC,eAAe,EAAE,MAAM,CAInB;IAEb;;;;OAIG;IACH,YAAY,CAAC,KAAK,EAAE,WAAW,GAAG,WAAW;IAQ7C;;;;;;;;;;;OAWG;IACG,aAAa,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;IAkC7D;;;;;;;;;OASG;IACG,UAAU,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;CAgC3D"}
@@ -0,0 +1,243 @@
1
+ import { componentPath, } from "./interface.js";
2
+ /**
3
+ * The global the preview IIFE binds the component to. M4's iframe grid reads
4
+ * `window.GenieComponent` to mount the card; keeping the name here (not in M4)
5
+ * makes the adapter the single source of truth for the preview contract.
6
+ */
7
+ export const PREVIEW_GLOBAL_NAME = "GenieComponent";
8
+ /**
9
+ * ── Preview host contract (DRO-624 · AC1) — the single source of truth ────────
10
+ *
11
+ * The `<Name>.preview.js` bundle this adapter emits does **not** carry its own
12
+ * copy of React, nor does it `require("react")`. It resolves React from two
13
+ * **host-provided browser globals** the preview iframe must define *before* the
14
+ * bundle's `<script>` runs:
15
+ *
16
+ * - `window.{@link REACT_HOST_GLOBAL}` → the React runtime (`window.React`)
17
+ * - `window.{@link REACT_DOM_HOST_GLOBAL}` → the ReactDOM runtime (`window.ReactDOM`)
18
+ *
19
+ * and it exposes the compiled component on `window.{@link PREVIEW_GLOBAL_NAME}`
20
+ * (`{ default, <Name> }`), which the M4-03 iframe grid mounts with the same host
21
+ * `ReactDOM`.
22
+ *
23
+ * ── Why globals, not esbuild `external` ───────────────────────────────────────
24
+ * The original M2-08 code marked React `external` under `format:"iife"`. esbuild
25
+ * has no facility to map an external bare specifier to a browser global, so it
26
+ * lowered `import … from "react"` (plus the `jsx:"automatic"` runtime import)
27
+ * into `require("react")` / `require("react/jsx-runtime")` — calls that throw
28
+ * `Uncaught Error: Dynamic require of "react" is not supported`
29
+ * the instant the IIFE evaluates inside the iframe (no CommonJS `require` there).
30
+ * The bundle would never mount. (Flagged by Copilot on PR #131 `react.ts:103`,
31
+ * merged unresolved; the M2-08 conformance test only asserted on bundle *text*,
32
+ * so it never surfaced.) The fix — {@link hostReactGlobalsPlugin} — intercepts
33
+ * those specifiers at bundle time and rewrites them to read the host globals.
34
+ *
35
+ * ── How the host provides the globals (PRD §6.6 / FR-056) ─────────────────────
36
+ * Per the on-disk layout (PRD §6.6) each kit vendors the runtime under `_vendor/`:
37
+ * `_vendor/react.production.min.js` + `_vendor/react-dom.production.min.js`.
38
+ * The iframe host page `<script>`-includes those UMD builds (which self-assign
39
+ * `window.React` / `window.ReactDOM`) ahead of the component bundle. This is the
40
+ * global-based contract FR-056 already describes for the aggregate
41
+ * `_genie_bundle.js` (`window.<KitGlobal>.<Component>`); a single-component
42
+ * preview is the same shape narrowed to one export exposed on
43
+ * `window.{@link PREVIEW_GLOBAL_NAME}`.
44
+ *
45
+ * NOTE — **React 18, UMD**: the contract depends on a runtime that ships a UMD
46
+ * build defining a `window.React` global. React 19 removed the UMD builds, so
47
+ * the vendored `_vendor/react*.min.js` must be the React 18 UMD production
48
+ * bundles (the adapter's execution test pins the same major).
49
+ */
50
+ export const REACT_HOST_GLOBAL = "React";
51
+ export const REACT_DOM_HOST_GLOBAL = "ReactDOM";
52
+ /**
53
+ * esbuild namespace the virtual React shim modules live in (kept off the real
54
+ * filesystem so nothing resolves to an on-disk `node_modules`).
55
+ */
56
+ const HOST_NAMESPACE = "genie-react-host-global";
57
+ /**
58
+ * The automatic-JSX runtime, re-expressed against `window.React`.
59
+ *
60
+ * `jsx:"automatic"` makes esbuild import `jsx` / `jsxs` / `Fragment` from
61
+ * `react/jsx-runtime`, but a vendored UMD `window.React` only exposes the classic
62
+ * `createElement` / `Fragment` — it has no `jsx-runtime` entry. This shim bridges
63
+ * the two: it re-implements the automatic runtime's `jsx(type, props, key)` in
64
+ * terms of `React.createElement`. `props.children` (where the automatic runtime
65
+ * puts children) flows straight through, and a defined `key` is merged into the
66
+ * config so `createElement` picks it up as the reserved key prop.
67
+ */
68
+ const JSX_RUNTIME_SHIM = [
69
+ `var React = window.${REACT_HOST_GLOBAL};`,
70
+ `if (!React) throw new Error(${JSON.stringify(hostMissingMessage(REACT_HOST_GLOBAL))});`,
71
+ `function jsx(type, props, key) {`,
72
+ ` return React.createElement(type, key === void 0 ? props : Object.assign({}, props, { key: key }));`,
73
+ `}`,
74
+ `exports.jsx = jsx;`,
75
+ `exports.jsxs = jsx;`,
76
+ `exports.jsxDEV = jsx;`,
77
+ `exports.Fragment = React.Fragment;`,
78
+ ].join("\n");
79
+ /** A clear, actionable error when the iframe forgot to load a vendored global. */
80
+ function hostMissingMessage(global) {
81
+ return (`genie preview host contract violated: window.${global} is not defined. ` +
82
+ `The preview iframe must load the vendored _vendor/${global === REACT_HOST_GLOBAL ? "react" : "react-dom"}.production.min.js ` +
83
+ `(React 18 UMD) before the component bundle — see the preview host contract in react.ts.`);
84
+ }
85
+ /** CJS body for a virtual module that re-exports a host global. */
86
+ function hostGlobalModule(global) {
87
+ return [
88
+ `if (!window.${global}) throw new Error(${JSON.stringify(hostMissingMessage(global))});`,
89
+ `module.exports = window.${global};`,
90
+ ].join("\n");
91
+ }
92
+ /**
93
+ * esbuild plugin implementing the {@link REACT_HOST_GLOBAL} contract (DRO-624 ·
94
+ * AC2). It intercepts every React bare specifier the source (or the automatic
95
+ * JSX transform) can reference and resolves it to an in-memory virtual module
96
+ * that reads the corresponding host global — so the emitted IIFE contains **no**
97
+ * `require("react")` and instead references `window.React` / `window.ReactDOM`.
98
+ *
99
+ * - `react` → `window.React`
100
+ * - `react-dom`, `react-dom/client` → `window.ReactDOM`
101
+ * - `react/jsx-runtime`, `…/jsx-dev-runtime` → {@link JSX_RUNTIME_SHIM}
102
+ */
103
+ export function hostReactGlobalsPlugin() {
104
+ return {
105
+ name: "genie-react-host-globals",
106
+ setup(build) {
107
+ build.onResolve({ filter: /^react$/ }, () => ({ path: "react", namespace: HOST_NAMESPACE }));
108
+ build.onResolve({ filter: /^react-dom(\/client)?$/ }, () => ({
109
+ path: "react-dom",
110
+ namespace: HOST_NAMESPACE,
111
+ }));
112
+ build.onResolve({ filter: /^react\/jsx-(dev-)?runtime$/ }, () => ({
113
+ path: "jsx-runtime",
114
+ namespace: HOST_NAMESPACE,
115
+ }));
116
+ build.onLoad({ filter: /.*/, namespace: HOST_NAMESPACE }, (args) => {
117
+ if (args.path === "react") {
118
+ return { contents: hostGlobalModule(REACT_HOST_GLOBAL), loader: "js" };
119
+ }
120
+ if (args.path === "react-dom") {
121
+ return { contents: hostGlobalModule(REACT_DOM_HOST_GLOBAL), loader: "js" };
122
+ }
123
+ return { contents: JSX_RUNTIME_SHIM, loader: "js" };
124
+ });
125
+ },
126
+ };
127
+ }
128
+ export class ReactAdapter {
129
+ framework = "react";
130
+ /**
131
+ * A comfortable default card for a React component when the caller has no
132
+ * better viewport. Matches the RFC's default preview grid cell (§7.5).
133
+ */
134
+ defaultViewport = { width: 400, height: 300 };
135
+ /**
136
+ * The framework directive `conjure` injects into the generation prompt (AC4):
137
+ * name the target framework and the React source shape the model should emit.
138
+ */
139
+ promptDirective = [
140
+ "Target framework: react",
141
+ "Emit an idiomatic React function component in TypeScript (.tsx). Type its props " +
142
+ "with an exported interface, and prefer semantic HTML with className-based styling.",
143
+ ].join("\n");
144
+ /**
145
+ * The canonical source file: `<Name>.tsx`, carrying the model-authored source
146
+ * verbatim. `text/tsx` mirrors the mimeType the M2-03 fixtures already use for
147
+ * `.tsx` entries.
148
+ */
149
+ renderSource(input) {
150
+ return {
151
+ path: componentPath(input, `${input.componentName}.tsx`),
152
+ content: input.source,
153
+ mimeType: "text/tsx",
154
+ };
155
+ }
156
+ /**
157
+ * Bundle the component to a browser-ready **IIFE** exposing it on
158
+ * `globalThis.${PREVIEW_GLOBAL_NAME}` (AC2). React is resolved from the host
159
+ * iframe's globals via {@link hostReactGlobalsPlugin} — see the *Preview host
160
+ * contract* above — so the output is a single self-contained script the M4
161
+ * iframe can `<script>`-include and mount with its own vendored React, with no
162
+ * `Dynamic require of "react"` at runtime (DRO-624).
163
+ *
164
+ * esbuild is imported lazily here (not at module top) so resolving a
165
+ * `ReactAdapter` — which the registry does on first `getAdapter("react")` —
166
+ * doesn't pull esbuild's native binary until a preview is actually built.
167
+ */
168
+ async renderPreview(input) {
169
+ const esbuild = (await import("esbuild")).default;
170
+ const result = await esbuild.build({
171
+ stdin: {
172
+ contents: input.source,
173
+ loader: "tsx",
174
+ sourcefile: `${input.componentName}.tsx`,
175
+ resolveDir: process.cwd(),
176
+ },
177
+ bundle: true,
178
+ write: false,
179
+ format: "iife",
180
+ globalName: PREVIEW_GLOBAL_NAME,
181
+ platform: "browser",
182
+ jsx: "automatic",
183
+ // React / ReactDOM / the JSX runtime are rewritten to the preview host's
184
+ // browser globals (window.React / window.ReactDOM) rather than inlined or
185
+ // left as throwing `require(...)` calls — see the Preview host contract.
186
+ plugins: [hostReactGlobalsPlugin()],
187
+ logLevel: "silent",
188
+ });
189
+ const output = result.outputFiles[0];
190
+ if (!output) {
191
+ // esbuild returns at least one output file on success; this guards the
192
+ // types, it is not an expected runtime branch.
193
+ throw new Error("esbuild produced no preview output for the React component.");
194
+ }
195
+ return {
196
+ path: componentPath(input, `${input.componentName}.preview.js`),
197
+ content: output.text,
198
+ mimeType: "text/javascript",
199
+ };
200
+ }
201
+ /**
202
+ * Extract the component's `.d.ts` typings with ts-morph (AC2), via an
203
+ * in-memory declaration-only emit so nothing touches disk. The virtual project
204
+ * carries `jsx: react-jsx` + `skipLibCheck` so a `.tsx` source with JSX and
205
+ * bare `react` imports emits declarations even without `@types/react` present
206
+ * in the virtual FS (we never type-check, only emit declarations).
207
+ *
208
+ * ts-morph is imported lazily (not at module top) for the same reason as
209
+ * esbuild in {@link renderPreview}: keep resolving the adapter cheap.
210
+ */
211
+ async extractDts(input) {
212
+ const { Project, ts } = await import("ts-morph");
213
+ const project = new Project({
214
+ useInMemoryFileSystem: true,
215
+ // `skipLibCheck` + declaration-only emit means missing lib/@types never
216
+ // block emission; we want the *shape*, not a clean type-check.
217
+ compilerOptions: {
218
+ declaration: true,
219
+ emitDeclarationOnly: true,
220
+ skipLibCheck: true,
221
+ jsx: ts.JsxEmit.ReactJSX,
222
+ target: ts.ScriptTarget.ES2022,
223
+ module: ts.ModuleKind.ESNext,
224
+ moduleResolution: ts.ModuleResolutionKind.Bundler,
225
+ },
226
+ });
227
+ const sourceName = `${input.componentName}.tsx`;
228
+ project.createSourceFile(sourceName, input.source, { overwrite: true });
229
+ const emitted = project.emitToMemory({ emitOnlyDtsFiles: true });
230
+ const dtsFile = emitted.getFiles().find((f) => f.filePath.endsWith(".d.ts"));
231
+ const content = dtsFile?.text ??
232
+ // Fallback: a source with no exported declarations legitimately yields no
233
+ // `.d.ts`. Emit a minimal module marker rather than an empty file so the
234
+ // artefact is always a valid `.d.ts`.
235
+ `export {};\n`;
236
+ return {
237
+ path: componentPath(input, `${input.componentName}.d.ts`),
238
+ content,
239
+ mimeType: "text/plain",
240
+ };
241
+ }
242
+ }
243
+ //# sourceMappingURL=react.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react.js","sourceRoot":"","sources":["../../src/framework/react.ts"],"names":[],"mappings":"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"}