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.
- package/CHANGELOG.md +49 -0
- package/README.md +2 -1
- package/dist/cli.d.ts +0 -1
- package/dist/cli.js +30 -5
- package/dist/dsl/aggregator.d.ts +0 -1
- package/dist/dsl/aggregator.js +0 -1
- package/dist/dsl/frontend-runtime.d.ts +110 -8
- package/dist/dsl/frontend-runtime.js +49 -30
- package/dist/dsl/runtime.d.ts +0 -1
- package/dist/dsl/runtime.js +16 -15
- package/dist/emit/backend/adapters.d.ts +0 -1
- package/dist/emit/backend/adapters.js +0 -1
- package/dist/emit/backend/backend-tsmorph.d.ts +0 -1
- package/dist/emit/backend/backend-tsmorph.js +0 -1
- package/dist/emit/backend/fake-backend.d.ts +0 -1
- package/dist/emit/backend/fake-backend.js +0 -1
- package/dist/emit/backend/packaging.d.ts +0 -1
- package/dist/emit/backend/packaging.js +0 -1
- package/dist/emit/backend/server.d.ts +0 -1
- package/dist/emit/backend/server.js +0 -1
- package/dist/emit/cli/cli-fake.d.ts +0 -1
- package/dist/emit/cli/cli-fake.js +0 -1
- package/dist/emit/electron/electron-shell.d.ts +0 -1
- package/dist/emit/electron/electron-shell.js +0 -1
- package/dist/emit/engine.d.ts +0 -1
- package/dist/emit/engine.js +0 -1
- package/dist/emit/format.d.ts +0 -1
- package/dist/emit/format.js +0 -1
- package/dist/emit/frontend/frontend-components.d.ts +6 -0
- package/dist/emit/frontend/frontend-components.js +1428 -0
- package/dist/emit/frontend/frontend-helpers.d.ts +15 -0
- package/dist/emit/frontend/frontend-helpers.js +219 -0
- package/dist/emit/frontend/frontend-package.d.ts +2 -0
- package/dist/emit/frontend/frontend-package.js +106 -0
- package/dist/emit/frontend/frontend-pages.d.ts +3 -0
- package/dist/emit/frontend/frontend-pages.js +51 -0
- package/dist/emit/frontend/frontend-pwa.d.ts +2 -0
- package/dist/emit/frontend/frontend-pwa.js +77 -0
- package/dist/emit/frontend/frontend-react.d.ts +0 -1
- package/dist/emit/frontend/frontend-react.js +415 -1682
- package/dist/emit/frontend/frontend-shared.d.ts +4 -0
- package/dist/emit/frontend/frontend-shared.js +89 -0
- package/dist/emit/frontend/frontend-tailwind.d.ts +2 -0
- package/dist/emit/frontend/frontend-tailwind.js +27 -0
- package/dist/emit/frontend/frontend-vite.d.ts +3 -0
- package/dist/emit/frontend/frontend-vite.js +29 -0
- package/dist/emit/frontend/registry.d.ts +0 -1
- package/dist/emit/frontend/registry.js +0 -1
- package/dist/emit/frontend/runtime-emitter.d.ts +0 -1
- package/dist/emit/frontend/runtime-emitter.js +224 -6
- package/dist/emit/frontend/runtime-template.d.ts +7 -2
- package/dist/emit/frontend/runtime-template.js +104 -11
- package/dist/emit/frontend/ssg.d.ts +0 -1
- package/dist/emit/frontend/ssg.js +19 -9
- package/dist/emit/registry.d.ts +0 -1
- package/dist/emit/registry.js +0 -1
- package/dist/emit/static-site/css.d.ts +0 -1
- package/dist/emit/static-site/css.js +0 -1
- package/dist/emit/static-site/enhancements.d.ts +0 -1
- package/dist/emit/static-site/enhancements.js +0 -1
- package/dist/emit/static-site/static-site-html.d.ts +0 -1
- package/dist/emit/static-site/static-site-html.js +0 -1
- package/dist/emit/utils/sdk.d.ts +0 -1
- package/dist/emit/utils/sdk.js +0 -1
- package/dist/extensions/context.d.ts +0 -1
- package/dist/extensions/context.js +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +29 -4
- package/dist/ir/decl/backend.raw.schema.d.ts +0 -1
- package/dist/ir/decl/backend.raw.schema.js +0 -1
- package/dist/ir/decl/bundle.d.ts +0 -1
- package/dist/ir/decl/bundle.js +0 -1
- package/dist/ir/decl/cli.raw.schema.d.ts +0 -1
- package/dist/ir/decl/cli.raw.schema.js +0 -1
- package/dist/ir/decl/frontend.raw.schema.d.ts +1953 -86
- package/dist/ir/decl/frontend.raw.schema.js +37 -4
- package/dist/ir/decl/index.d.ts +0 -1
- package/dist/ir/decl/index.js +0 -1
- package/dist/ir/decl/normalize.schema.d.ts +2476 -117
- package/dist/ir/decl/normalize.schema.js +0 -1
- package/dist/ir/domain/backend.d.ts +0 -1
- package/dist/ir/domain/backend.js +0 -1
- package/dist/ir/domain/cli.d.ts +0 -1
- package/dist/ir/domain/cli.js +0 -1
- package/dist/ir/domain/frontend/index.d.ts +36 -2
- package/dist/ir/domain/frontend/index.js +0 -1
- package/dist/ir/domain/frontend.d.ts +0 -1
- package/dist/ir/domain/frontend.js +0 -1
- package/dist/ir/frontend-contract.d.ts +0 -1
- package/dist/ir/frontend-contract.js +0 -1
- package/dist/ir/target/backend.d.ts +0 -1
- package/dist/ir/target/backend.js +0 -1
- package/dist/ir/target/backend.policy.d.ts +30 -31
- package/dist/ir/target/backend.policy.js +0 -1
- package/dist/ir/target/cli.d.ts +0 -1
- package/dist/ir/target/cli.js +0 -1
- package/dist/ir/target/electron.d.ts +0 -1
- package/dist/ir/target/electron.js +0 -1
- package/dist/ir/target/electron.policy.d.ts +0 -1
- package/dist/ir/target/electron.policy.js +0 -1
- package/dist/ir/target/frontend.d.ts +0 -1
- package/dist/ir/target/frontend.js +0 -1
- package/dist/ir/target/frontend.policy.d.ts +101 -1
- package/dist/ir/target/frontend.policy.js +16 -1
- package/dist/ir/target/index.d.ts +0 -1
- package/dist/ir/target/index.js +0 -1
- package/dist/ir/target/static-site.d.ts +0 -1
- package/dist/ir/target/static-site.js +0 -1
- package/dist/ir/target/static-site.policy.d.ts +0 -1
- package/dist/ir/target/static-site.policy.js +0 -1
- package/dist/lowering/backend.d.ts +0 -1
- package/dist/lowering/backend.js +0 -1
- package/dist/lowering/cli.d.ts +0 -1
- package/dist/lowering/cli.js +0 -1
- package/dist/lowering/engine.d.ts +0 -1
- package/dist/lowering/engine.js +0 -1
- package/dist/lowering/frontend/macros/index.d.ts +2 -0
- package/dist/lowering/frontend/macros/index.js +15 -0
- package/dist/lowering/frontend/macros/pages.d.ts +3 -0
- package/dist/lowering/frontend/macros/pages.js +119 -0
- package/dist/lowering/frontend/macros/pricing.d.ts +2 -0
- package/dist/lowering/frontend/macros/pricing.js +22 -0
- package/dist/lowering/frontend/macros/registry.d.ts +5 -0
- package/dist/lowering/frontend/macros/registry.js +13 -0
- package/dist/lowering/frontend/macros/tablePage.d.ts +2 -0
- package/dist/lowering/frontend/macros/tablePage.js +101 -0
- package/dist/lowering/frontend.d.ts +0 -1
- package/dist/lowering/frontend.js +96 -28
- package/dist/lowering/targets/to-backend.d.ts +0 -1
- package/dist/lowering/targets/to-backend.js +0 -1
- package/dist/lowering/targets/to-cli.d.ts +0 -1
- package/dist/lowering/targets/to-cli.js +0 -1
- package/dist/lowering/targets/to-electron.d.ts +0 -1
- package/dist/lowering/targets/to-electron.js +0 -1
- package/dist/lowering/targets/to-frontend.d.ts +0 -1
- package/dist/lowering/targets/to-frontend.js +0 -1
- package/dist/lowering/targets/to-static-site.d.ts +0 -1
- package/dist/lowering/targets/to-static-site.js +0 -1
- package/dist/mappers/index.d.ts +1 -2
- package/dist/mappers/index.js +0 -1
- package/dist/types/extension.d.ts +0 -1
- package/dist/types/extension.js +0 -1
- package/dist/utils/array.d.ts +0 -1
- package/dist/utils/array.js +0 -1
- package/dist/utils/index.d.ts +2 -3
- package/dist/utils/index.js +2 -3
- package/dist/utils/string.d.ts +0 -1
- package/dist/utils/string.js +0 -1
- package/package.json +8 -3
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/dsl/aggregator.d.ts.map +0 -1
- package/dist/dsl/aggregator.js.map +0 -1
- package/dist/dsl/frontend-runtime.d.ts.map +0 -1
- package/dist/dsl/frontend-runtime.js.map +0 -1
- package/dist/dsl/runtime.d.ts.map +0 -1
- package/dist/dsl/runtime.js.map +0 -1
- package/dist/emit/backend/adapters.d.ts.map +0 -1
- package/dist/emit/backend/adapters.js.map +0 -1
- package/dist/emit/backend/backend-tsmorph.d.ts.map +0 -1
- package/dist/emit/backend/backend-tsmorph.js.map +0 -1
- package/dist/emit/backend/fake-backend.d.ts.map +0 -1
- package/dist/emit/backend/fake-backend.js.map +0 -1
- package/dist/emit/backend/packaging.d.ts.map +0 -1
- package/dist/emit/backend/packaging.js.map +0 -1
- package/dist/emit/backend/server.d.ts.map +0 -1
- package/dist/emit/backend/server.js.map +0 -1
- package/dist/emit/cli/cli-fake.d.ts.map +0 -1
- package/dist/emit/cli/cli-fake.js.map +0 -1
- package/dist/emit/electron/electron-shell.d.ts.map +0 -1
- package/dist/emit/electron/electron-shell.js.map +0 -1
- package/dist/emit/engine.d.ts.map +0 -1
- package/dist/emit/engine.js.map +0 -1
- package/dist/emit/format.d.ts.map +0 -1
- package/dist/emit/format.js.map +0 -1
- package/dist/emit/frontend/frontend-react.d.ts.map +0 -1
- package/dist/emit/frontend/frontend-react.js.map +0 -1
- package/dist/emit/frontend/registry.d.ts.map +0 -1
- package/dist/emit/frontend/registry.js.map +0 -1
- package/dist/emit/frontend/runtime-emitter.d.ts.map +0 -1
- package/dist/emit/frontend/runtime-emitter.js.map +0 -1
- package/dist/emit/frontend/runtime-template.d.ts.map +0 -1
- package/dist/emit/frontend/runtime-template.js.map +0 -1
- package/dist/emit/frontend/ssg.d.ts.map +0 -1
- package/dist/emit/frontend/ssg.js.map +0 -1
- package/dist/emit/registry.d.ts.map +0 -1
- package/dist/emit/registry.js.map +0 -1
- package/dist/emit/static-site/css.d.ts.map +0 -1
- package/dist/emit/static-site/css.js.map +0 -1
- package/dist/emit/static-site/enhancements.d.ts.map +0 -1
- package/dist/emit/static-site/enhancements.js.map +0 -1
- package/dist/emit/static-site/static-site-html.d.ts.map +0 -1
- package/dist/emit/static-site/static-site-html.js.map +0 -1
- package/dist/emit/utils/sdk.d.ts.map +0 -1
- package/dist/emit/utils/sdk.js.map +0 -1
- package/dist/extensions/context.d.ts.map +0 -1
- package/dist/extensions/context.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/ir/decl/backend.raw.schema.d.ts.map +0 -1
- package/dist/ir/decl/backend.raw.schema.js.map +0 -1
- package/dist/ir/decl/bundle.d.ts.map +0 -1
- package/dist/ir/decl/bundle.js.map +0 -1
- package/dist/ir/decl/cli.raw.schema.d.ts.map +0 -1
- package/dist/ir/decl/cli.raw.schema.js.map +0 -1
- package/dist/ir/decl/frontend.raw.schema.d.ts.map +0 -1
- package/dist/ir/decl/frontend.raw.schema.js.map +0 -1
- package/dist/ir/decl/index.d.ts.map +0 -1
- package/dist/ir/decl/index.js.map +0 -1
- package/dist/ir/decl/normalize.schema.d.ts.map +0 -1
- package/dist/ir/decl/normalize.schema.js.map +0 -1
- package/dist/ir/domain/backend.d.ts.map +0 -1
- package/dist/ir/domain/backend.js.map +0 -1
- package/dist/ir/domain/cli.d.ts.map +0 -1
- package/dist/ir/domain/cli.js.map +0 -1
- package/dist/ir/domain/frontend/index.d.ts.map +0 -1
- package/dist/ir/domain/frontend/index.js.map +0 -1
- package/dist/ir/domain/frontend.d.ts.map +0 -1
- package/dist/ir/domain/frontend.js.map +0 -1
- package/dist/ir/frontend-contract.d.ts.map +0 -1
- package/dist/ir/frontend-contract.js.map +0 -1
- package/dist/ir/target/backend.d.ts.map +0 -1
- package/dist/ir/target/backend.js.map +0 -1
- package/dist/ir/target/backend.policy.d.ts.map +0 -1
- package/dist/ir/target/backend.policy.js.map +0 -1
- package/dist/ir/target/cli.d.ts.map +0 -1
- package/dist/ir/target/cli.js.map +0 -1
- package/dist/ir/target/electron.d.ts.map +0 -1
- package/dist/ir/target/electron.js.map +0 -1
- package/dist/ir/target/electron.policy.d.ts.map +0 -1
- package/dist/ir/target/electron.policy.js.map +0 -1
- package/dist/ir/target/frontend.d.ts.map +0 -1
- package/dist/ir/target/frontend.js.map +0 -1
- package/dist/ir/target/frontend.policy.d.ts.map +0 -1
- package/dist/ir/target/frontend.policy.js.map +0 -1
- package/dist/ir/target/index.d.ts.map +0 -1
- package/dist/ir/target/index.js.map +0 -1
- package/dist/ir/target/static-site.d.ts.map +0 -1
- package/dist/ir/target/static-site.js.map +0 -1
- package/dist/ir/target/static-site.policy.d.ts.map +0 -1
- package/dist/ir/target/static-site.policy.js.map +0 -1
- package/dist/lowering/backend.d.ts.map +0 -1
- package/dist/lowering/backend.js.map +0 -1
- package/dist/lowering/cli.d.ts.map +0 -1
- package/dist/lowering/cli.js.map +0 -1
- package/dist/lowering/engine.d.ts.map +0 -1
- package/dist/lowering/engine.js.map +0 -1
- package/dist/lowering/frontend.d.ts.map +0 -1
- package/dist/lowering/frontend.js.map +0 -1
- package/dist/lowering/targets/to-backend.d.ts.map +0 -1
- package/dist/lowering/targets/to-backend.js.map +0 -1
- package/dist/lowering/targets/to-cli.d.ts.map +0 -1
- package/dist/lowering/targets/to-cli.js.map +0 -1
- package/dist/lowering/targets/to-electron.d.ts.map +0 -1
- package/dist/lowering/targets/to-electron.js.map +0 -1
- package/dist/lowering/targets/to-frontend.d.ts.map +0 -1
- package/dist/lowering/targets/to-frontend.js.map +0 -1
- package/dist/lowering/targets/to-static-site.d.ts.map +0 -1
- package/dist/lowering/targets/to-static-site.js.map +0 -1
- package/dist/mappers/index.d.ts.map +0 -1
- package/dist/mappers/index.js.map +0 -1
- package/dist/types/extension.d.ts.map +0 -1
- package/dist/types/extension.js.map +0 -1
- package/dist/utils/array.d.ts.map +0 -1
- package/dist/utils/array.js.map +0 -1
- package/dist/utils/index.d.ts.map +0 -1
- package/dist/utils/index.js.map +0 -1
- package/dist/utils/string.d.ts.map +0 -1
- 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
|
-
-
|
|
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
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
|
|
191
|
-
const modUrl = pathToFileURL(abs).href;
|
|
217
|
+
const modUrl = resolveExtensionModule(modPath);
|
|
192
218
|
const imported = await import(modUrl);
|
|
193
|
-
const fn = (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
|
package/dist/dsl/aggregator.d.ts
CHANGED
package/dist/dsl/aggregator.js
CHANGED
|
@@ -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,
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
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 (!
|
|
12
|
+
if (!_global.__IR_CURRENT_FRONTEND)
|
|
11
13
|
return;
|
|
12
|
-
|
|
13
|
-
const existing = (
|
|
14
|
-
|
|
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(
|
|
42
|
-
|
|
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(
|
|
46
|
-
|
|
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(
|
|
50
|
-
|
|
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(
|
|
54
|
-
|
|
55
|
-
|
|
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(
|
|
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(
|
|
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 (
|
|
114
|
-
|
|
125
|
+
if (_global.__IR_CURRENT_FRONTEND)
|
|
126
|
+
_global.__IR_CURRENT_FRONTEND.components.push(finalized);
|
|
115
127
|
}
|
|
116
128
|
});
|
|
117
129
|
}
|
|
118
|
-
if (
|
|
119
|
-
|
|
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(
|
|
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 (
|
|
159
|
-
|
|
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
|
-
|
|
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(
|
|
194
|
-
|
|
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
|
-
|
|
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 (!
|
|
247
|
+
if (!_global.__IR_CURRENT_FRONTEND)
|
|
228
248
|
throw new Error(`Frontend DSL did not call frontend(...)`);
|
|
229
|
-
const parsed = DeclFrontendAppSchema.parse(
|
|
249
|
+
const parsed = DeclFrontendAppSchema.parse(_global.__IR_CURRENT_FRONTEND);
|
|
230
250
|
return parsed;
|
|
231
251
|
}
|
|
232
|
-
//# sourceMappingURL=frontend-runtime.js.map
|
package/dist/dsl/runtime.d.ts
CHANGED