irgen 0.2.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (269) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/README.md +2 -1
  3. package/dist/cli.d.ts +0 -1
  4. package/dist/cli.js +30 -5
  5. package/dist/dsl/aggregator.d.ts +0 -1
  6. package/dist/dsl/aggregator.js +0 -1
  7. package/dist/dsl/frontend-runtime.d.ts +110 -8
  8. package/dist/dsl/frontend-runtime.js +49 -30
  9. package/dist/dsl/runtime.d.ts +0 -1
  10. package/dist/dsl/runtime.js +16 -15
  11. package/dist/emit/backend/adapters.d.ts +0 -1
  12. package/dist/emit/backend/adapters.js +0 -1
  13. package/dist/emit/backend/backend-tsmorph.d.ts +0 -1
  14. package/dist/emit/backend/backend-tsmorph.js +0 -1
  15. package/dist/emit/backend/fake-backend.d.ts +0 -1
  16. package/dist/emit/backend/fake-backend.js +0 -1
  17. package/dist/emit/backend/packaging.d.ts +0 -1
  18. package/dist/emit/backend/packaging.js +0 -1
  19. package/dist/emit/backend/server.d.ts +0 -1
  20. package/dist/emit/backend/server.js +0 -1
  21. package/dist/emit/cli/cli-fake.d.ts +0 -1
  22. package/dist/emit/cli/cli-fake.js +0 -1
  23. package/dist/emit/electron/electron-shell.d.ts +0 -1
  24. package/dist/emit/electron/electron-shell.js +0 -1
  25. package/dist/emit/engine.d.ts +0 -1
  26. package/dist/emit/engine.js +0 -1
  27. package/dist/emit/format.d.ts +0 -1
  28. package/dist/emit/format.js +0 -1
  29. package/dist/emit/frontend/frontend-components.d.ts +6 -0
  30. package/dist/emit/frontend/frontend-components.js +1428 -0
  31. package/dist/emit/frontend/frontend-helpers.d.ts +15 -0
  32. package/dist/emit/frontend/frontend-helpers.js +219 -0
  33. package/dist/emit/frontend/frontend-package.d.ts +2 -0
  34. package/dist/emit/frontend/frontend-package.js +106 -0
  35. package/dist/emit/frontend/frontend-pages.d.ts +3 -0
  36. package/dist/emit/frontend/frontend-pages.js +51 -0
  37. package/dist/emit/frontend/frontend-pwa.d.ts +2 -0
  38. package/dist/emit/frontend/frontend-pwa.js +77 -0
  39. package/dist/emit/frontend/frontend-react.d.ts +0 -1
  40. package/dist/emit/frontend/frontend-react.js +415 -1682
  41. package/dist/emit/frontend/frontend-shared.d.ts +4 -0
  42. package/dist/emit/frontend/frontend-shared.js +89 -0
  43. package/dist/emit/frontend/frontend-tailwind.d.ts +2 -0
  44. package/dist/emit/frontend/frontend-tailwind.js +27 -0
  45. package/dist/emit/frontend/frontend-vite.d.ts +3 -0
  46. package/dist/emit/frontend/frontend-vite.js +29 -0
  47. package/dist/emit/frontend/registry.d.ts +0 -1
  48. package/dist/emit/frontend/registry.js +0 -1
  49. package/dist/emit/frontend/runtime-emitter.d.ts +0 -1
  50. package/dist/emit/frontend/runtime-emitter.js +224 -6
  51. package/dist/emit/frontend/runtime-template.d.ts +7 -2
  52. package/dist/emit/frontend/runtime-template.js +104 -11
  53. package/dist/emit/frontend/ssg.d.ts +0 -1
  54. package/dist/emit/frontend/ssg.js +19 -9
  55. package/dist/emit/registry.d.ts +0 -1
  56. package/dist/emit/registry.js +0 -1
  57. package/dist/emit/static-site/css.d.ts +0 -1
  58. package/dist/emit/static-site/css.js +0 -1
  59. package/dist/emit/static-site/enhancements.d.ts +0 -1
  60. package/dist/emit/static-site/enhancements.js +0 -1
  61. package/dist/emit/static-site/static-site-html.d.ts +0 -1
  62. package/dist/emit/static-site/static-site-html.js +0 -1
  63. package/dist/emit/utils/sdk.d.ts +0 -1
  64. package/dist/emit/utils/sdk.js +0 -1
  65. package/dist/extensions/context.d.ts +0 -1
  66. package/dist/extensions/context.js +0 -1
  67. package/dist/index.d.ts +0 -1
  68. package/dist/index.js +29 -4
  69. package/dist/ir/decl/backend.raw.schema.d.ts +0 -1
  70. package/dist/ir/decl/backend.raw.schema.js +0 -1
  71. package/dist/ir/decl/bundle.d.ts +0 -1
  72. package/dist/ir/decl/bundle.js +0 -1
  73. package/dist/ir/decl/cli.raw.schema.d.ts +0 -1
  74. package/dist/ir/decl/cli.raw.schema.js +0 -1
  75. package/dist/ir/decl/frontend.raw.schema.d.ts +1953 -86
  76. package/dist/ir/decl/frontend.raw.schema.js +37 -4
  77. package/dist/ir/decl/index.d.ts +0 -1
  78. package/dist/ir/decl/index.js +0 -1
  79. package/dist/ir/decl/normalize.schema.d.ts +2476 -117
  80. package/dist/ir/decl/normalize.schema.js +0 -1
  81. package/dist/ir/domain/backend.d.ts +0 -1
  82. package/dist/ir/domain/backend.js +0 -1
  83. package/dist/ir/domain/cli.d.ts +0 -1
  84. package/dist/ir/domain/cli.js +0 -1
  85. package/dist/ir/domain/frontend/index.d.ts +36 -2
  86. package/dist/ir/domain/frontend/index.js +0 -1
  87. package/dist/ir/domain/frontend.d.ts +0 -1
  88. package/dist/ir/domain/frontend.js +0 -1
  89. package/dist/ir/frontend-contract.d.ts +0 -1
  90. package/dist/ir/frontend-contract.js +0 -1
  91. package/dist/ir/target/backend.d.ts +0 -1
  92. package/dist/ir/target/backend.js +0 -1
  93. package/dist/ir/target/backend.policy.d.ts +30 -31
  94. package/dist/ir/target/backend.policy.js +0 -1
  95. package/dist/ir/target/cli.d.ts +0 -1
  96. package/dist/ir/target/cli.js +0 -1
  97. package/dist/ir/target/electron.d.ts +0 -1
  98. package/dist/ir/target/electron.js +0 -1
  99. package/dist/ir/target/electron.policy.d.ts +0 -1
  100. package/dist/ir/target/electron.policy.js +0 -1
  101. package/dist/ir/target/frontend.d.ts +0 -1
  102. package/dist/ir/target/frontend.js +0 -1
  103. package/dist/ir/target/frontend.policy.d.ts +101 -1
  104. package/dist/ir/target/frontend.policy.js +16 -1
  105. package/dist/ir/target/index.d.ts +0 -1
  106. package/dist/ir/target/index.js +0 -1
  107. package/dist/ir/target/static-site.d.ts +0 -1
  108. package/dist/ir/target/static-site.js +0 -1
  109. package/dist/ir/target/static-site.policy.d.ts +0 -1
  110. package/dist/ir/target/static-site.policy.js +0 -1
  111. package/dist/lowering/backend.d.ts +0 -1
  112. package/dist/lowering/backend.js +0 -1
  113. package/dist/lowering/cli.d.ts +0 -1
  114. package/dist/lowering/cli.js +0 -1
  115. package/dist/lowering/engine.d.ts +0 -1
  116. package/dist/lowering/engine.js +0 -1
  117. package/dist/lowering/frontend/macros/index.d.ts +2 -0
  118. package/dist/lowering/frontend/macros/index.js +15 -0
  119. package/dist/lowering/frontend/macros/pages.d.ts +3 -0
  120. package/dist/lowering/frontend/macros/pages.js +119 -0
  121. package/dist/lowering/frontend/macros/pricing.d.ts +2 -0
  122. package/dist/lowering/frontend/macros/pricing.js +22 -0
  123. package/dist/lowering/frontend/macros/registry.d.ts +5 -0
  124. package/dist/lowering/frontend/macros/registry.js +13 -0
  125. package/dist/lowering/frontend/macros/tablePage.d.ts +2 -0
  126. package/dist/lowering/frontend/macros/tablePage.js +101 -0
  127. package/dist/lowering/frontend.d.ts +0 -1
  128. package/dist/lowering/frontend.js +96 -28
  129. package/dist/lowering/targets/to-backend.d.ts +0 -1
  130. package/dist/lowering/targets/to-backend.js +0 -1
  131. package/dist/lowering/targets/to-cli.d.ts +0 -1
  132. package/dist/lowering/targets/to-cli.js +0 -1
  133. package/dist/lowering/targets/to-electron.d.ts +0 -1
  134. package/dist/lowering/targets/to-electron.js +0 -1
  135. package/dist/lowering/targets/to-frontend.d.ts +0 -1
  136. package/dist/lowering/targets/to-frontend.js +0 -1
  137. package/dist/lowering/targets/to-static-site.d.ts +0 -1
  138. package/dist/lowering/targets/to-static-site.js +0 -1
  139. package/dist/mappers/index.d.ts +1 -2
  140. package/dist/mappers/index.js +0 -1
  141. package/dist/types/extension.d.ts +0 -1
  142. package/dist/types/extension.js +0 -1
  143. package/dist/utils/array.d.ts +0 -1
  144. package/dist/utils/array.js +0 -1
  145. package/dist/utils/index.d.ts +2 -3
  146. package/dist/utils/index.js +2 -3
  147. package/dist/utils/string.d.ts +0 -1
  148. package/dist/utils/string.js +0 -1
  149. package/package.json +8 -3
  150. package/dist/cli.d.ts.map +0 -1
  151. package/dist/cli.js.map +0 -1
  152. package/dist/dsl/aggregator.d.ts.map +0 -1
  153. package/dist/dsl/aggregator.js.map +0 -1
  154. package/dist/dsl/frontend-runtime.d.ts.map +0 -1
  155. package/dist/dsl/frontend-runtime.js.map +0 -1
  156. package/dist/dsl/runtime.d.ts.map +0 -1
  157. package/dist/dsl/runtime.js.map +0 -1
  158. package/dist/emit/backend/adapters.d.ts.map +0 -1
  159. package/dist/emit/backend/adapters.js.map +0 -1
  160. package/dist/emit/backend/backend-tsmorph.d.ts.map +0 -1
  161. package/dist/emit/backend/backend-tsmorph.js.map +0 -1
  162. package/dist/emit/backend/fake-backend.d.ts.map +0 -1
  163. package/dist/emit/backend/fake-backend.js.map +0 -1
  164. package/dist/emit/backend/packaging.d.ts.map +0 -1
  165. package/dist/emit/backend/packaging.js.map +0 -1
  166. package/dist/emit/backend/server.d.ts.map +0 -1
  167. package/dist/emit/backend/server.js.map +0 -1
  168. package/dist/emit/cli/cli-fake.d.ts.map +0 -1
  169. package/dist/emit/cli/cli-fake.js.map +0 -1
  170. package/dist/emit/electron/electron-shell.d.ts.map +0 -1
  171. package/dist/emit/electron/electron-shell.js.map +0 -1
  172. package/dist/emit/engine.d.ts.map +0 -1
  173. package/dist/emit/engine.js.map +0 -1
  174. package/dist/emit/format.d.ts.map +0 -1
  175. package/dist/emit/format.js.map +0 -1
  176. package/dist/emit/frontend/frontend-react.d.ts.map +0 -1
  177. package/dist/emit/frontend/frontend-react.js.map +0 -1
  178. package/dist/emit/frontend/registry.d.ts.map +0 -1
  179. package/dist/emit/frontend/registry.js.map +0 -1
  180. package/dist/emit/frontend/runtime-emitter.d.ts.map +0 -1
  181. package/dist/emit/frontend/runtime-emitter.js.map +0 -1
  182. package/dist/emit/frontend/runtime-template.d.ts.map +0 -1
  183. package/dist/emit/frontend/runtime-template.js.map +0 -1
  184. package/dist/emit/frontend/ssg.d.ts.map +0 -1
  185. package/dist/emit/frontend/ssg.js.map +0 -1
  186. package/dist/emit/registry.d.ts.map +0 -1
  187. package/dist/emit/registry.js.map +0 -1
  188. package/dist/emit/static-site/css.d.ts.map +0 -1
  189. package/dist/emit/static-site/css.js.map +0 -1
  190. package/dist/emit/static-site/enhancements.d.ts.map +0 -1
  191. package/dist/emit/static-site/enhancements.js.map +0 -1
  192. package/dist/emit/static-site/static-site-html.d.ts.map +0 -1
  193. package/dist/emit/static-site/static-site-html.js.map +0 -1
  194. package/dist/emit/utils/sdk.d.ts.map +0 -1
  195. package/dist/emit/utils/sdk.js.map +0 -1
  196. package/dist/extensions/context.d.ts.map +0 -1
  197. package/dist/extensions/context.js.map +0 -1
  198. package/dist/index.d.ts.map +0 -1
  199. package/dist/index.js.map +0 -1
  200. package/dist/ir/decl/backend.raw.schema.d.ts.map +0 -1
  201. package/dist/ir/decl/backend.raw.schema.js.map +0 -1
  202. package/dist/ir/decl/bundle.d.ts.map +0 -1
  203. package/dist/ir/decl/bundle.js.map +0 -1
  204. package/dist/ir/decl/cli.raw.schema.d.ts.map +0 -1
  205. package/dist/ir/decl/cli.raw.schema.js.map +0 -1
  206. package/dist/ir/decl/frontend.raw.schema.d.ts.map +0 -1
  207. package/dist/ir/decl/frontend.raw.schema.js.map +0 -1
  208. package/dist/ir/decl/index.d.ts.map +0 -1
  209. package/dist/ir/decl/index.js.map +0 -1
  210. package/dist/ir/decl/normalize.schema.d.ts.map +0 -1
  211. package/dist/ir/decl/normalize.schema.js.map +0 -1
  212. package/dist/ir/domain/backend.d.ts.map +0 -1
  213. package/dist/ir/domain/backend.js.map +0 -1
  214. package/dist/ir/domain/cli.d.ts.map +0 -1
  215. package/dist/ir/domain/cli.js.map +0 -1
  216. package/dist/ir/domain/frontend/index.d.ts.map +0 -1
  217. package/dist/ir/domain/frontend/index.js.map +0 -1
  218. package/dist/ir/domain/frontend.d.ts.map +0 -1
  219. package/dist/ir/domain/frontend.js.map +0 -1
  220. package/dist/ir/frontend-contract.d.ts.map +0 -1
  221. package/dist/ir/frontend-contract.js.map +0 -1
  222. package/dist/ir/target/backend.d.ts.map +0 -1
  223. package/dist/ir/target/backend.js.map +0 -1
  224. package/dist/ir/target/backend.policy.d.ts.map +0 -1
  225. package/dist/ir/target/backend.policy.js.map +0 -1
  226. package/dist/ir/target/cli.d.ts.map +0 -1
  227. package/dist/ir/target/cli.js.map +0 -1
  228. package/dist/ir/target/electron.d.ts.map +0 -1
  229. package/dist/ir/target/electron.js.map +0 -1
  230. package/dist/ir/target/electron.policy.d.ts.map +0 -1
  231. package/dist/ir/target/electron.policy.js.map +0 -1
  232. package/dist/ir/target/frontend.d.ts.map +0 -1
  233. package/dist/ir/target/frontend.js.map +0 -1
  234. package/dist/ir/target/frontend.policy.d.ts.map +0 -1
  235. package/dist/ir/target/frontend.policy.js.map +0 -1
  236. package/dist/ir/target/index.d.ts.map +0 -1
  237. package/dist/ir/target/index.js.map +0 -1
  238. package/dist/ir/target/static-site.d.ts.map +0 -1
  239. package/dist/ir/target/static-site.js.map +0 -1
  240. package/dist/ir/target/static-site.policy.d.ts.map +0 -1
  241. package/dist/ir/target/static-site.policy.js.map +0 -1
  242. package/dist/lowering/backend.d.ts.map +0 -1
  243. package/dist/lowering/backend.js.map +0 -1
  244. package/dist/lowering/cli.d.ts.map +0 -1
  245. package/dist/lowering/cli.js.map +0 -1
  246. package/dist/lowering/engine.d.ts.map +0 -1
  247. package/dist/lowering/engine.js.map +0 -1
  248. package/dist/lowering/frontend.d.ts.map +0 -1
  249. package/dist/lowering/frontend.js.map +0 -1
  250. package/dist/lowering/targets/to-backend.d.ts.map +0 -1
  251. package/dist/lowering/targets/to-backend.js.map +0 -1
  252. package/dist/lowering/targets/to-cli.d.ts.map +0 -1
  253. package/dist/lowering/targets/to-cli.js.map +0 -1
  254. package/dist/lowering/targets/to-electron.d.ts.map +0 -1
  255. package/dist/lowering/targets/to-electron.js.map +0 -1
  256. package/dist/lowering/targets/to-frontend.d.ts.map +0 -1
  257. package/dist/lowering/targets/to-frontend.js.map +0 -1
  258. package/dist/lowering/targets/to-static-site.d.ts.map +0 -1
  259. package/dist/lowering/targets/to-static-site.js.map +0 -1
  260. package/dist/mappers/index.d.ts.map +0 -1
  261. package/dist/mappers/index.js.map +0 -1
  262. package/dist/types/extension.d.ts.map +0 -1
  263. package/dist/types/extension.js.map +0 -1
  264. package/dist/utils/array.d.ts.map +0 -1
  265. package/dist/utils/array.js.map +0 -1
  266. package/dist/utils/index.d.ts.map +0 -1
  267. package/dist/utils/index.js.map +0 -1
  268. package/dist/utils/string.d.ts.map +0 -1
  269. package/dist/utils/string.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -2,6 +2,55 @@
2
2
 
3
3
  All notable changes to the `irgen` project will be documented in this file.
4
4
 
5
+ ## [0.2.2] - 2026-01-18
6
+
7
+ ### Core Extensions & Architecture (Phase 10)
8
+ - **Universal Action Model**: Introduced `ActionSpec` type and `onClick` support for buttons, enabling a consistent "invoke operation" or "navigate" behavior across all UI components.
9
+ - **Operation-Backed Forms**: Updated `DeclFormSchema` to support `operationId` in submission configuration, allowing forms to bind directly to backend operations instead of hardcoded URLs.
10
+ - **Micro-Frontend Support**: Added `macro` field to `DeclComponentSchema`, enabling the definition of "Page Templates" (like `TablePage`, `EditorPage`) as single high-level components with props.
11
+ - **Dependency Declaration**: Added `requiredComponentKeys` to `DeclFrontendAppSchema`, allowing extensions and presets to explicitly declare their UI component dependencies.
12
+ - **Active Runtime Signals**: Implemented functional execution of `toast`, `redirect`, `openUrl`, and `downloadAs` signals in the headless runtime (`BaseRuntime`), replacing passive data with active behavior.
13
+ - **Frontend auth contract**: Added `frontend.auth` to declare login/logout operations, login path, and nav visibility rules in a deterministic, policy-driven way.
14
+ - **Form lifecycle upgrades**: Added `form.load` with args/when/mapFields, plus `form.submit.label` for configurable submit text.
15
+ - **Table UX contracts**: Added `table.rowNavigateTo` (row click navigation) and `table.rowActions` with per-row actions and optional confirm dialogs.
16
+ - **Runtime logic evaluation**: Frontend runtime now evaluates logic expressions for path params, action arguments, and field mapping, enabling dynamic behaviors without recompilation.
17
+ - **Frontend build hooks**: Added `build.copyTo`/`build.postbuild` policy to emit postbuild copy scripts in frontend outputs (`copyToPublic` is deprecated).
18
+ - **Component UI variants**: Added `component.props.uiVariant` (`header`/`inline`) and `component.props.layoutVariant` (`header`) to control header-style layouts without card wrappers.
19
+ - **Visual policy (best-effort)**: Emitter reads `policies.frontend.visual` knobs (`navLayout`, `contentWidth`, `density`) without adding schema validation.
20
+ - **Topbar controls (best-effort)**: `visual.topbarControls` controls right-side navbar items (search/notifications/theme/avatar), avatar visibility, and optional custom links.
21
+ - **Branding controls (best-effort)**: `visual.brand` can hide/show logos and override logo src/text/icon in topbar/sidebar.
22
+ - **Nav overrides (best-effort)**: `visual.navItems` can define separate menus for topbar and sidebar, and hide topbar.
23
+ - **Footer/search overrides (best-effort)**: `visual.footerLinks` and `visual.search` allow replacing footer links and search copy without core edits.
24
+ - **Footer layout (best-effort)**: `visual.footer` can disable or compact footer and override footer text.
25
+ - **Form styling (best-effort)**: `visual.form` allows overriding form label/input/error/button/form classes.
26
+ - **Button styling (best-effort)**: `visual.button` allows overriding base/variant button classes.
27
+ - **Table styling (best-effort)**: `visual.table` allows overriding table container/row/cell/action classes.
28
+ - **Tabs styling (best-effort)**: `visual.tabs` allows overriding tabs container/header/button/panel classes.
29
+ - **Marketing blocks (best-effort)**: `visual.marketing` allows overriding hero/features/logos/etc container/title classes.
30
+ - **Card styling (best-effort)**: `visual.cards` allows overriding card/empty/placeholder classes.
31
+ - **Prose styling (best-effort)**: `visual.prose` allows overriding markdown/prose wrapper class.
32
+ - **Motion styling (best-effort)**: `visual.motion` allows overriding page enter + hover/alert/tag motion classes.
33
+ - **Copy overrides (best-effort)**: `visual.copy` allows overriding empty/placeholder/table/tab strings plus common UI labels, including runtime error text.
34
+ - **Token overrides (best-effort)**: `visual.tokens` allows overriding typography/spacing/radius/shadow/color/motion tokens.
35
+ - **Icon overrides (best-effort)**: `visual.icons` allows overriding default UI chrome icons, including docs section + docs item + nav + footer + search modal + row action icons.
36
+ - **SSR fix**: ensure `App.tsx` imports React when using `React.createElement` in generated UI.
37
+ - **Breakpoint overrides (best-effort)**: `visual.breakpoints` allows overriding responsive layout classes (padding/sidebar/docs grid).
38
+ - **Docs/background overrides (best-effort)**: `visual.docs` and `visual.background` control docs labels/sidebar/TOC and decorative gradients.
39
+ - **Labels/avatar overrides (best-effort)**: `visual.labels.sidebarLabel` and `visual.topbarControls.avatar.src` replace hardcoded sidebar label and avatar URL.
40
+
41
+ ## [0.2.1] - 2026-01-11
42
+
43
+ ### GitHub Pages (SSG/Hybrid)
44
+ - Generate and build SSG/hybrid output for `examples/irgen-web.dsl.ts` in CI.
45
+ - Fix basePath handling so nav/docs links keep `/irgen` prefix after hydration.
46
+ - Add favicon/apple-touch-icon links in SSG output.
47
+ - Fix PWA manifest icon path and service worker cache paths under basePath.
48
+ - Set `SITE_URL` in Pages workflow for correct sitemap/robots URLs.
49
+
50
+ ### Packaging
51
+ - Remove TypeScript sourcemaps and declaration maps from build output.
52
+ - Align README outputs with generated examples and keep example script in sync.
53
+
5
54
  ## [0.2.0] - 2026-01-11
6
55
 
7
56
  ### General Purpose Frontend & Headless Runtime (Phase 3)
package/README.md CHANGED
@@ -38,6 +38,7 @@ irgen focuses on **architecture and determinism**, not convenience shortcuts. ir
38
38
  - **Multi-app Support**: Set `basePath` to deploy multiple apps (e.g., `/admin`, `/docs`) under a single project or domain.
39
39
  - **Form Logic & UX**: JSONLogic predicates, dependency-tracked hooks, async select with debounce/pagination/search.
40
40
  - **Submission Pipeline**: Lifecycle hooks, confirm dialogs, response handling, and draft persistence.
41
+ - **Auth + Table Contracts**: `frontend.auth` for login/logout flows; `form.load` for prefill; `table.rowNavigateTo` + `table.rowActions` for row navigation/actions.
41
42
 
42
43
  ### Static Site (HTML-first)
43
44
  - **HTML-only output**: emits final HTML (no React hydration), JS is strictly progressive enhancement.
@@ -149,7 +150,7 @@ See [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) for details on:
149
150
  - Generation Gap Pattern
150
151
  - Port & Adapters (Hexagonal)
151
152
  - Frontend Runtime & IR
152
- - Frontend SSG plan: [docs/FRONTEND-SSG-PLAN.md](docs/FRONTEND-SSG-PLAN.md)
153
+ - Macro System: [docs/MACRO-SYSTEM.md](docs/MACRO-SYSTEM.md)
153
154
 
154
155
  ## Roadmap
155
156
  - [x] Separation of Concerns (Generated vs User space)
package/dist/cli.d.ts CHANGED
@@ -1,3 +1,2 @@
1
1
  #!/usr/bin/env node
2
2
  export {};
3
- //# sourceMappingURL=cli.d.ts.map
package/dist/cli.js CHANGED
@@ -1,6 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import path from "node:path";
3
+ import fs from "node:fs";
3
4
  import { pathToFileURL } from "node:url";
5
+ import { createRequire } from "node:module";
4
6
  import { aggregateDecls } from "./dsl/aggregator.js";
5
7
  import { registerBuiltins, runMapper } from "./mappers/index.js";
6
8
  // Guard: require a modern Node (tsx loader relies on module.register)
@@ -186,13 +188,37 @@ Examples:
186
188
  return;
187
189
  const { createExtensionContext } = await import("./extensions/context.js");
188
190
  const ctx = createExtensionContext();
191
+ const require = createRequire(import.meta.url);
192
+ const pickExtensionFn = (mod) => {
193
+ const candidate = (mod?.default ?? mod?.extension ?? mod);
194
+ if (typeof candidate === "function")
195
+ return candidate;
196
+ if (candidate && typeof candidate === "object") {
197
+ if (typeof candidate.default === "function")
198
+ return candidate.default;
199
+ if (typeof candidate.extension === "function")
200
+ return candidate.extension;
201
+ }
202
+ return null;
203
+ };
204
+ const resolveExtensionModule = (spec) => {
205
+ const isPathLike = path.isAbsolute(spec) || spec.startsWith(".") || spec.startsWith("/") || /^[A-Za-z]:[\\/]/.test(spec);
206
+ if (isPathLike) {
207
+ const abs = path.isAbsolute(spec) ? spec : path.resolve(process.cwd(), spec);
208
+ if (!fs.existsSync(abs)) {
209
+ throw new Error(`extension module not found: ${spec}`);
210
+ }
211
+ return pathToFileURL(abs).href;
212
+ }
213
+ const resolved = require.resolve(spec, { paths: [process.cwd()] });
214
+ return pathToFileURL(resolved).href;
215
+ };
189
216
  for (const modPath of extModules) {
190
- const abs = path.isAbsolute(modPath) ? modPath : path.resolve(process.cwd(), modPath);
191
- const modUrl = pathToFileURL(abs).href;
217
+ const modUrl = resolveExtensionModule(modPath);
192
218
  const imported = await import(modUrl);
193
- const fn = (imported.default ?? imported.extension ?? imported);
219
+ const fn = pickExtensionFn(imported);
194
220
  if (typeof fn === "function") {
195
- fn(ctx, imported.options ?? undefined);
221
+ await fn(ctx, imported.options ?? undefined);
196
222
  }
197
223
  else {
198
224
  console.warn(`extension module ${modPath} did not export a function`);
@@ -309,4 +335,3 @@ main().catch((err) => {
309
335
  console.error(err);
310
336
  process.exit(1);
311
337
  });
312
- //# sourceMappingURL=cli.js.map
@@ -5,4 +5,3 @@ import { DeclBundle } from "../ir/decl/index.js";
5
5
  export declare function aggregateDecls(entries: string[], opts?: {
6
6
  prefer?: "frontend" | "backend";
7
7
  }): Promise<DeclBundle>;
8
- //# sourceMappingURL=aggregator.d.ts.map
@@ -61,4 +61,3 @@ function mergeMeta(metas) {
61
61
  }
62
62
  return Object.keys(finalMeta).length ? finalMeta : undefined;
63
63
  }
64
- //# sourceMappingURL=aggregator.js.map
@@ -1,5 +1,5 @@
1
1
  import { DeclFrontendApp, DeclComponent } from "../ir/decl/frontend.raw.schema.js";
2
- export type RuntimeComponent = Omit<DeclComponent, "agentChat" | "cliUsage" | "table"> & {
2
+ export type RuntimeComponent = Omit<DeclComponent, "agentChat" | "cliUsage" | "table" | "macro"> & {
3
3
  field: (fieldName: string, type: string, label?: string, validators?: Record<string, any>, config?: any) => void;
4
4
  prop: (key: string, value: string) => void;
5
5
  agentChat: (data: {
@@ -39,21 +39,25 @@ export type RuntimeComponent = Omit<DeclComponent, "agentChat" | "cliUsage" | "t
39
39
  render?: string;
40
40
  }>;
41
41
  }) => void;
42
+ useMacro: (type: string, props?: Record<string, any>) => void;
42
43
  };
43
44
  type FrontendOptions = {
44
45
  basePath?: string;
45
46
  pwa?: DeclFrontendApp["pwa"];
47
+ auth?: DeclFrontendApp["auth"];
46
48
  meta?: Record<string, any>;
47
49
  policies?: Record<string, any>;
48
50
  datasources?: DeclFrontendApp["datasources"];
49
51
  operations?: DeclFrontendApp["operations"];
50
52
  resources?: DeclFrontendApp["resources"];
53
+ requiredComponentKeys?: string[];
51
54
  };
52
55
  export declare function datasource(id: string, config: any): void;
53
56
  export declare function operation(id: string, config: any): void;
54
57
  export declare function resource(id: string, config: any): void;
55
58
  export declare function meta(key: string, value: unknown): void;
56
59
  export declare function policy(target: string, value: Record<string, any>): void;
60
+ export declare function requiredComponents(keys: string[]): void;
57
61
  export declare function page(pName: string, opts: {
58
62
  path: string;
59
63
  hideHeader?: boolean;
@@ -72,6 +76,7 @@ type FrontendCallbackArgs = {
72
76
  resource: typeof resource;
73
77
  meta: typeof meta;
74
78
  policy: typeof policy;
79
+ requiredComponents: typeof requiredComponents;
75
80
  };
76
81
  export declare function frontend(name: string, optsOrFn: FrontendOptions | ((a: FrontendCallbackArgs) => void), maybeFn?: (a: FrontendCallbackArgs) => void): {
77
82
  type: "frontend";
@@ -130,7 +135,7 @@ export declare function frontend(name: string, optsOrFn: FrontendOptions | ((a:
130
135
  components: {
131
136
  type: "component";
132
137
  name: string;
133
- props?: Record<string, string> | undefined;
138
+ props?: Record<string, any> | undefined;
134
139
  form?: {
135
140
  fields: {
136
141
  type: "number" | "date" | "text" | "select" | "textarea" | "checkbox" | "radio" | "datetime" | "time" | "url" | "phone" | "file" | "slider" | "currency" | "tags" | "signature" | "daterange" | "email" | "password";
@@ -193,6 +198,8 @@ export declare function frontend(name: string, optsOrFn: FrontendOptions | ((a:
193
198
  }[];
194
199
  submit?: {
195
200
  url?: string | undefined;
201
+ label?: string | undefined;
202
+ operationId?: string | undefined;
196
203
  method?: "POST" | "PUT" | "PATCH" | undefined;
197
204
  successMessage?: string | undefined;
198
205
  errorMessage?: string | undefined;
@@ -203,6 +210,14 @@ export declare function frontend(name: string, optsOrFn: FrontendOptions | ((a:
203
210
  onError?: any;
204
211
  redirect?: string | undefined;
205
212
  } | undefined;
213
+ load?: {
214
+ operationId: string;
215
+ onSuccess?: any;
216
+ onError?: any;
217
+ args?: any;
218
+ when?: any;
219
+ mapFields?: Record<string, any> | undefined;
220
+ } | undefined;
206
221
  } | undefined;
207
222
  entityRef?: string | undefined;
208
223
  content?: string | undefined;
@@ -236,16 +251,40 @@ export declare function frontend(name: string, optsOrFn: FrontendOptions | ((a:
236
251
  button?: {
237
252
  label: string;
238
253
  icon?: string | undefined;
254
+ onClick?: {
255
+ kind: "invoke";
256
+ operationId: string;
257
+ confirmMessage?: string | undefined;
258
+ args?: any;
259
+ } | {
260
+ kind: "navigate";
261
+ confirmMessage?: string | undefined;
262
+ to?: any;
263
+ } | undefined;
239
264
  variant?: "primary" | "secondary" | "ghost" | undefined;
240
265
  } | undefined;
241
266
  table?: {
267
+ operationId?: string | undefined;
242
268
  columns?: {
243
269
  header: string;
244
270
  accessor: string;
245
271
  render?: string | undefined;
246
272
  }[] | undefined;
247
273
  resourceId?: string | undefined;
248
- operationId?: string | undefined;
274
+ rowNavigateTo?: string | undefined;
275
+ rowActions?: {
276
+ label: string;
277
+ onClick?: {
278
+ kind: "invoke";
279
+ operationId: string;
280
+ confirmMessage?: string | undefined;
281
+ args?: any;
282
+ } | {
283
+ kind: "navigate";
284
+ confirmMessage?: string | undefined;
285
+ to?: any;
286
+ } | undefined;
287
+ }[] | undefined;
249
288
  } | undefined;
250
289
  themeToggle?: boolean | undefined;
251
290
  codeBlock?: {
@@ -253,6 +292,7 @@ export declare function frontend(name: string, optsOrFn: FrontendOptions | ((a:
253
292
  language: string;
254
293
  showLineNumbers: boolean;
255
294
  } | undefined;
295
+ macro?: string | undefined;
256
296
  marketing?: {
257
297
  kind: "hero" | "features" | "testimonials" | "faq" | "logos" | "cta" | "stats" | "timeline";
258
298
  align?: "left" | "center" | undefined;
@@ -270,8 +310,18 @@ export declare function frontend(name: string, optsOrFn: FrontendOptions | ((a:
270
310
  }[] | undefined;
271
311
  actions?: {
272
312
  label: string;
273
- href: string;
274
313
  icon?: string | undefined;
314
+ href?: string | undefined;
315
+ onClick?: {
316
+ kind: "invoke";
317
+ operationId: string;
318
+ confirmMessage?: string | undefined;
319
+ args?: any;
320
+ } | {
321
+ kind: "navigate";
322
+ confirmMessage?: string | undefined;
323
+ to?: any;
324
+ } | undefined;
275
325
  variant?: "primary" | "secondary" | "ghost" | undefined;
276
326
  }[] | undefined;
277
327
  badge?: string | undefined;
@@ -285,7 +335,7 @@ export declare function frontend(name: string, optsOrFn: FrontendOptions | ((a:
285
335
  components: {
286
336
  type: "component";
287
337
  name: string;
288
- props?: Record<string, string> | undefined;
338
+ props?: Record<string, any> | undefined;
289
339
  form?: {
290
340
  fields: {
291
341
  type: "number" | "date" | "text" | "select" | "textarea" | "checkbox" | "radio" | "datetime" | "time" | "url" | "phone" | "file" | "slider" | "currency" | "tags" | "signature" | "daterange" | "email" | "password";
@@ -348,6 +398,8 @@ export declare function frontend(name: string, optsOrFn: FrontendOptions | ((a:
348
398
  }[];
349
399
  submit?: {
350
400
  url?: string | undefined;
401
+ label?: string | undefined;
402
+ operationId?: string | undefined;
351
403
  method?: "POST" | "PUT" | "PATCH" | undefined;
352
404
  successMessage?: string | undefined;
353
405
  errorMessage?: string | undefined;
@@ -358,6 +410,14 @@ export declare function frontend(name: string, optsOrFn: FrontendOptions | ((a:
358
410
  onError?: any;
359
411
  redirect?: string | undefined;
360
412
  } | undefined;
413
+ load?: {
414
+ operationId: string;
415
+ onSuccess?: any;
416
+ onError?: any;
417
+ args?: any;
418
+ when?: any;
419
+ mapFields?: Record<string, any> | undefined;
420
+ } | undefined;
361
421
  } | undefined;
362
422
  entityRef?: string | undefined;
363
423
  content?: string | undefined;
@@ -391,16 +451,40 @@ export declare function frontend(name: string, optsOrFn: FrontendOptions | ((a:
391
451
  button?: {
392
452
  label: string;
393
453
  icon?: string | undefined;
454
+ onClick?: {
455
+ kind: "invoke";
456
+ operationId: string;
457
+ confirmMessage?: string | undefined;
458
+ args?: any;
459
+ } | {
460
+ kind: "navigate";
461
+ confirmMessage?: string | undefined;
462
+ to?: any;
463
+ } | undefined;
394
464
  variant?: "primary" | "secondary" | "ghost" | undefined;
395
465
  } | undefined;
396
466
  table?: {
467
+ operationId?: string | undefined;
397
468
  columns?: {
398
469
  header: string;
399
470
  accessor: string;
400
471
  render?: string | undefined;
401
472
  }[] | undefined;
402
473
  resourceId?: string | undefined;
403
- operationId?: string | undefined;
474
+ rowNavigateTo?: string | undefined;
475
+ rowActions?: {
476
+ label: string;
477
+ onClick?: {
478
+ kind: "invoke";
479
+ operationId: string;
480
+ confirmMessage?: string | undefined;
481
+ args?: any;
482
+ } | {
483
+ kind: "navigate";
484
+ confirmMessage?: string | undefined;
485
+ to?: any;
486
+ } | undefined;
487
+ }[] | undefined;
404
488
  } | undefined;
405
489
  themeToggle?: boolean | undefined;
406
490
  codeBlock?: {
@@ -408,6 +492,7 @@ export declare function frontend(name: string, optsOrFn: FrontendOptions | ((a:
408
492
  language: string;
409
493
  showLineNumbers: boolean;
410
494
  } | undefined;
495
+ macro?: string | undefined;
411
496
  marketing?: {
412
497
  kind: "hero" | "features" | "testimonials" | "faq" | "logos" | "cta" | "stats" | "timeline";
413
498
  align?: "left" | "center" | undefined;
@@ -425,8 +510,18 @@ export declare function frontend(name: string, optsOrFn: FrontendOptions | ((a:
425
510
  }[] | undefined;
426
511
  actions?: {
427
512
  label: string;
428
- href: string;
429
513
  icon?: string | undefined;
514
+ href?: string | undefined;
515
+ onClick?: {
516
+ kind: "invoke";
517
+ operationId: string;
518
+ confirmMessage?: string | undefined;
519
+ args?: any;
520
+ } | {
521
+ kind: "navigate";
522
+ confirmMessage?: string | undefined;
523
+ to?: any;
524
+ } | undefined;
430
525
  variant?: "primary" | "secondary" | "ghost" | undefined;
431
526
  }[] | undefined;
432
527
  badge?: string | undefined;
@@ -480,7 +575,14 @@ export declare function frontend(name: string, optsOrFn: FrontendOptions | ((a:
480
575
  purpose?: string | undefined;
481
576
  }[] | undefined;
482
577
  } | undefined;
578
+ auth?: {
579
+ enabled?: boolean | undefined;
580
+ loginPath?: string | undefined;
581
+ meOperationId?: string | undefined;
582
+ logoutOperationId?: string | undefined;
583
+ hideLoginWhenAuthed?: boolean | undefined;
584
+ } | undefined;
585
+ requiredComponentKeys?: string[] | undefined;
483
586
  };
484
587
  export declare function loadFrontendDsl(entry: string): Promise<DeclFrontendApp>;
485
588
  export {};
486
- //# sourceMappingURL=frontend-runtime.d.ts.map
@@ -1,17 +1,19 @@
1
1
  import path from "node:path";
2
2
  import { pathToFileURL } from "node:url";
3
3
  import { DeclFrontendAppSchema } from "../ir/decl/frontend.raw.schema.js";
4
- let CURRENT_FRONTEND = null;
4
+ // Use globalThis to share state across multiple module instances (e.g., src vs dist)
5
+ const _global = globalThis;
6
+ _global.__IR_CURRENT_FRONTEND = _global.__IR_CURRENT_FRONTEND || null;
5
7
  function assert(cond, msg) {
6
8
  if (!cond)
7
9
  throw new Error(msg);
8
10
  }
9
11
  function mergePolicy(target, value) {
10
- if (!CURRENT_FRONTEND)
12
+ if (!_global.__IR_CURRENT_FRONTEND)
11
13
  return;
12
- CURRENT_FRONTEND.meta = CURRENT_FRONTEND.meta ?? {};
13
- const existing = (CURRENT_FRONTEND.meta.policies ?? {});
14
- CURRENT_FRONTEND.meta.policies = { ...existing, [target]: { ...(existing[target] ?? {}), ...value } };
14
+ _global.__IR_CURRENT_FRONTEND.meta = _global.__IR_CURRENT_FRONTEND.meta ?? {};
15
+ const existing = (_global.__IR_CURRENT_FRONTEND.meta.policies ?? {});
16
+ _global.__IR_CURRENT_FRONTEND.meta.policies = { ...existing, [target]: { ...(existing[target] ?? {}), ...value } };
15
17
  }
16
18
  const RUNTIME_HELPERS = [
17
19
  "field",
@@ -29,6 +31,7 @@ const RUNTIME_HELPERS = [
29
31
  "enableThemeToggle",
30
32
  "code",
31
33
  "table",
34
+ "useMacro",
32
35
  ];
33
36
  function stripRuntimeHelpers(comp) {
34
37
  for (const key of RUNTIME_HELPERS) {
@@ -38,28 +41,32 @@ function stripRuntimeHelpers(comp) {
38
41
  }
39
42
  }
40
43
  export function datasource(id, config) {
41
- assert(CURRENT_FRONTEND, "datasource() harus di dalam frontend()");
42
- CURRENT_FRONTEND.datasources.push({ id, ...config });
44
+ assert(_global.__IR_CURRENT_FRONTEND, "datasource() harus di dalam frontend()");
45
+ _global.__IR_CURRENT_FRONTEND.datasources.push({ id, ...config });
43
46
  }
44
47
  export function operation(id, config) {
45
- assert(CURRENT_FRONTEND, "operation() harus di dalam frontend()");
46
- CURRENT_FRONTEND.operations.push({ id, ...config });
48
+ assert(_global.__IR_CURRENT_FRONTEND, "operation() harus di dalam frontend()");
49
+ _global.__IR_CURRENT_FRONTEND.operations.push({ id, ...config });
47
50
  }
48
51
  export function resource(id, config) {
49
- assert(CURRENT_FRONTEND, "resource() harus di dalam frontend()");
50
- CURRENT_FRONTEND.resources.push({ id, ...config });
52
+ assert(_global.__IR_CURRENT_FRONTEND, "resource() harus di dalam frontend()");
53
+ _global.__IR_CURRENT_FRONTEND.resources.push({ id, ...config });
51
54
  }
52
55
  export function meta(key, value) {
53
- assert(CURRENT_FRONTEND, "meta() harus di dalam frontend()");
54
- CURRENT_FRONTEND.meta = CURRENT_FRONTEND.meta ?? {};
55
- CURRENT_FRONTEND.meta[key] = value;
56
+ assert(_global.__IR_CURRENT_FRONTEND, "meta() harus di dalam frontend()");
57
+ _global.__IR_CURRENT_FRONTEND.meta = _global.__IR_CURRENT_FRONTEND.meta ?? {};
58
+ _global.__IR_CURRENT_FRONTEND.meta[key] = value;
56
59
  }
57
60
  export function policy(target, value) {
58
- assert(CURRENT_FRONTEND, "policy() harus di dalam frontend()");
61
+ assert(_global.__IR_CURRENT_FRONTEND, "policy() harus di dalam frontend()");
59
62
  mergePolicy(target, value);
60
63
  }
64
+ export function requiredComponents(keys) {
65
+ assert(_global.__IR_CURRENT_FRONTEND, "requiredComponents() harus di dalam frontend()");
66
+ _global.__IR_CURRENT_FRONTEND.requiredComponentKeys = keys;
67
+ }
61
68
  export function page(pName, opts, cb) {
62
- assert(CURRENT_FRONTEND, "page() harus di dalam frontend()");
69
+ assert(_global.__IR_CURRENT_FRONTEND, "page() harus di dalam frontend()");
63
70
  const page = {
64
71
  type: "page",
65
72
  name: pName,
@@ -102,6 +109,11 @@ export function page(pName, opts, cb) {
102
109
  comp.codeBlock = { snippet, language, showLineNumbers: options?.showLineNumbers ?? true };
103
110
  };
104
111
  comp.table = function (data) { comp.table = data; };
112
+ comp.useMacro = function (type, props) {
113
+ comp.macro = type;
114
+ if (props)
115
+ comp.props = props;
116
+ };
105
117
  if (typeof cCb === "function")
106
118
  cCb(comp);
107
119
  stripRuntimeHelpers(comp);
@@ -110,16 +122,16 @@ export function page(pName, opts, cb) {
110
122
  }
111
123
  const finalized = comp;
112
124
  page.components.push(finalized);
113
- if (CURRENT_FRONTEND)
114
- CURRENT_FRONTEND.components.push(finalized);
125
+ if (_global.__IR_CURRENT_FRONTEND)
126
+ _global.__IR_CURRENT_FRONTEND.components.push(finalized);
115
127
  }
116
128
  });
117
129
  }
118
- if (CURRENT_FRONTEND)
119
- CURRENT_FRONTEND.pages.push(page);
130
+ if (_global.__IR_CURRENT_FRONTEND)
131
+ _global.__IR_CURRENT_FRONTEND.pages.push(page);
120
132
  }
121
133
  export function component(name, cb) {
122
- assert(CURRENT_FRONTEND, "component() harus di dalam frontend()");
134
+ assert(_global.__IR_CURRENT_FRONTEND, "component() harus di dalam frontend()");
123
135
  const comp = { type: "component", name: name, props: {}, form: { fields: [] } };
124
136
  // add convenience methods to the comp object for DSL users: field() and prop()
125
137
  comp.field = function (fieldName, type, label, validators, config) {
@@ -149,14 +161,19 @@ export function component(name, cb) {
149
161
  comp.codeBlock = { snippet, language, showLineNumbers: options?.showLineNumbers ?? true };
150
162
  };
151
163
  comp.table = function (data) { comp.table = data; };
164
+ comp.useMacro = function (type, props) {
165
+ comp.macro = type;
166
+ if (props)
167
+ comp.props = props;
168
+ };
152
169
  if (typeof cb === "function")
153
170
  cb(comp);
154
171
  stripRuntimeHelpers(comp);
155
172
  if (comp.html) {
156
173
  throw new Error(`component.html is not allowed (component: ${comp.name}). Use component.content with Markdown instead.`);
157
174
  }
158
- if (CURRENT_FRONTEND)
159
- CURRENT_FRONTEND.components.push(comp);
175
+ if (_global.__IR_CURRENT_FRONTEND)
176
+ _global.__IR_CURRENT_FRONTEND.components.push(comp);
160
177
  }
161
178
  export function frontend(name, optsOrFn, maybeFn) {
162
179
  assert(typeof name === "string" && name.length > 0, "frontend(name) harus string");
@@ -164,7 +181,7 @@ export function frontend(name, optsOrFn, maybeFn) {
164
181
  const fn = (typeof optsOrFn === "function" ? optsOrFn : maybeFn);
165
182
  assert(typeof fn === "function", "frontend(..., fn) fn harus function");
166
183
  const baseMeta = opts?.meta ?? {};
167
- CURRENT_FRONTEND = {
184
+ _global.__IR_CURRENT_FRONTEND = {
168
185
  type: "frontend",
169
186
  name,
170
187
  basePath: opts?.basePath ?? "/",
@@ -174,6 +191,8 @@ export function frontend(name, optsOrFn, maybeFn) {
174
191
  operations: opts?.operations ?? [],
175
192
  resources: opts?.resources ?? [],
176
193
  ...(opts?.pwa ? { pwa: opts.pwa } : {}),
194
+ ...(opts?.auth ? { auth: opts.auth } : {}),
195
+ ...(opts?.requiredComponentKeys ? { requiredComponentKeys: opts.requiredComponentKeys } : {}),
177
196
  meta: { ...baseMeta },
178
197
  };
179
198
  if (opts?.policies) {
@@ -189,16 +208,17 @@ export function frontend(name, optsOrFn, maybeFn) {
189
208
  component,
190
209
  meta,
191
210
  policy,
211
+ requiredComponents,
192
212
  });
193
- const parsed = DeclFrontendAppSchema.parse(CURRENT_FRONTEND);
194
- CURRENT_FRONTEND = parsed;
213
+ const parsed = DeclFrontendAppSchema.parse(_global.__IR_CURRENT_FRONTEND);
214
+ _global.__IR_CURRENT_FRONTEND = parsed;
195
215
  return parsed;
196
216
  }
197
217
  export async function loadFrontendDsl(entry) {
198
218
  const abs = path.resolve(process.cwd(), entry);
199
219
  const url = pathToFileURL(abs).href;
200
220
  // reset
201
- CURRENT_FRONTEND = null;
221
+ _global.__IR_CURRENT_FRONTEND = null;
202
222
  try {
203
223
  await import(url);
204
224
  }
@@ -224,9 +244,8 @@ export async function loadFrontendDsl(entry) {
224
244
  throw new Error(`Failed to load frontend DSL (${entry}): ${err2?.message ?? err2}`);
225
245
  }
226
246
  }
227
- if (!CURRENT_FRONTEND)
247
+ if (!_global.__IR_CURRENT_FRONTEND)
228
248
  throw new Error(`Frontend DSL did not call frontend(...)`);
229
- const parsed = DeclFrontendAppSchema.parse(CURRENT_FRONTEND);
249
+ const parsed = DeclFrontendAppSchema.parse(_global.__IR_CURRENT_FRONTEND);
230
250
  return parsed;
231
251
  }
232
- //# sourceMappingURL=frontend-runtime.js.map
@@ -30,4 +30,3 @@ export declare function app(name: string, opts: AppOptions, fn: (a: AppBuilder)
30
30
  */
31
31
  export declare function loadDsl(entry: string): Promise<DeclApp>;
32
32
  export {};
33
- //# sourceMappingURL=runtime.d.ts.map