Skip to content
Merged
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ A single `app.intent` YAML file at a project root is the source of truth one alt

**Detailed guide:** [`components/engine/engine-intent/CLAUDE.md`](components/engine/engine-intent/CLAUDE.md). Read it before changing anything under that module — it covers the editor-first architecture and altitude contract (model files only, never code), the YAML schema and its semantics (integer-only primary keys, `composition: true` to-one = DEPENDENT master-detail while `required` alone is just a NOT NULL FK, PascalCase property names with UPPER_SNAKE columns, decision `then`/`else`, intent-prefixed table names via `IntentNaming`), the `writeModelFile`-only write surface with the stale-output scrub, the wrong turns already made (wrong altitude, template-output paths, registry-relative vs repository-absolute paths, the `JsonHelper` Gson pitfall, **and the synchronizer-based first incarnation — do not reintroduce it**), and the follow-up list (chaining model-to-code via `.gen` descriptors, `/custom/` escape hatch). Process triggers (`trigger: { onCreate: <Entity> }`) are wired: the EDM adds a `ProcessId` field + a `triggers` collection to the `.model`, and the `template-application-events-java` template generates a `gen/events/<Process>Trigger.java` listener that starts the process on create. That persisted `ProcessId` is in turn **consumed by the generated entity-view UI**: a shared `ProcessTasks` module (`components/resources/resources-dashboard/.../dashboard/services/process-tasks.js`) surfaces the record's actionable BPM user tasks inline via an `<entity-process-tasks>` directive (correlating `entity.ProcessId === task.processInstanceId`), wired into every generated view gated on a `hasProcess` flag; the task form completes via the permission-checked `/services/inbox/tasks/{id}` and self-closes (#6074). `IntentEngineIT` is the HTTP-only end-to-end test (~1 minute, no sync cycles). The editor's diagram pane is **mxGraph** (replacing Mermaid, which had unfixable light/dark theming bugs) with a fixed brand-colour palette that reads on both themes — see the module guide's "Intent Editor diagram = mxGraph" section before touching `editor-intent/js/editor.js`.

**Multi-model + layout additions (PRs [#6089](https://github.com/eclipse-dirigible/dirigible/pull/6089)-[#6092](https://github.com/eclipse-dirigible/dirigible/pull/6092)):** the DSL now supports building an app from **several intent models that reference each other cross-model** - a top-level `uses:` block names other models, and a relation gains an optional `model:` alias; a cross-model `manyToOne`/`oneToOne` is emitted as a read-only **PROJECTION** entity + integer FK + dropdown (the codbex cross-project pattern - no local table/DAO/controller for the target), resolved against the owner's already-generated `.model` (leaf-first generation; convention fallback otherwise). **n:m** is an explicit **intermediate entity** (composition to one side + `manyToOne` to the other, which may be cross-model, plus bridge fields like `amount`) - `manyToMany` is parsed but never materialized. New field attributes: `unique`, `precision`/`scale`, `calculatedOnCreate`/`calculatedOnUpdate` (a neutral arithmetic expression for numeric totals, else emitted verbatim into the runtime), `calculatedActionOnCreate`/`calculatedActionOnUpdate` (server-side call-out to a hand-written `@Component implements org.eclipse.dirigible.sdk.db.CalculatedField<E,T>`, invoked as `Beans.get(<class>.class).calculate(entity)`, taking precedence over the expression — for logic too custom to model, e.g. number generation); field `readOnly: true` (not editable; rendered in the Harmonia form's read-only details block — Label:Value above the buttons — via `isReadOnlyProperty`; `ProcessId`/audit columns/`uuid` are auto-flagged read-only, `status`-style fields opt in); field `major: false` (kept off the entity **list** table — the model's `widgetIsMajor="false"` — still shown in forms + the record details pane; defaults true); entity `imports:` (Java `import` lines injected into the generated repository so a calculated action can be referenced by simple name — Base64-encoded into the `.model`'s `importsCode`, which the Java DAO template emits; the editor's entity-level Imports tab is the model-editor equivalent); entity `audit: true` (the four standard audit columns); entity `group:` (the perspective's nav-group id in the shared application shell). **Depends-On** is exposed as `dependsOn: { relation, valueFrom?, filterBy? }` on a to-one relation (cascading/narrowed dropdown) or a field (auto-populated value) — emitted as the EDM `widgetDependsOn*` attributes (the AngularJS stacks consume them as-is; the Harmonia runtime — form/document watchers + the metadata-driven item-dialog cascade — was added alongside); defaults are the respective primary keys, names are the target's authored property names, cross-model triggers/targets supported. **Multi-language data** (the TS-era `multilingual` port): entity `multilingual: true` → the schema layer generates a sibling `<TABLE>_LANG` table (`GUID, Id, <PascalCase translatable columns>, Language` — the codbex-uoms-data convention) and the generated Java repository overlays translated values on every read for the request's `Accept-Language` (SDK `Translator`, name-based merge); top-level `languages: [en, bg]` feeds the Harmonia shell's **Region & Language** Settings entry (an Alpine `locale` store, localStorage `codbex.harmonia.language`, sent as `Accept-Language` by the shared fetch client — one flag drives UI, data, and the Print default); translations are authored as seeds with `language: bg`, and large data sets reference an authored CSV via seed `file: data/x.csv` (subfolder mandatory — root `.csv` is scrub-owned) instead of inline rows. A master owning an `*Item` composition child renders as the **document (header-items) layout** (`MANAGE_DOCUMENT` + `documentItemsEntity`, `uiDocumentModels`), with `aggregate: true` fields shown in the totals footer. `IntentNaming.upperSnake` collapses kebab/space/`.`/`/` separators so a hyphenated model name yields a valid SQL identifier (`sales-invoices` -> `SALES_INVOICES`). Worked example: `dirigiblelabs/sample-intent-multi-model` (six interdependent projects + a navigation-groups project).
**Multi-model + layout additions (PRs [#6089](https://github.com/eclipse-dirigible/dirigible/pull/6089)-[#6092](https://github.com/eclipse-dirigible/dirigible/pull/6092)):** the DSL now supports building an app from **several intent models that reference each other cross-model** - a top-level `uses:` block names other models, and a relation gains an optional `model:` alias; a cross-model `manyToOne`/`oneToOne` is emitted as a read-only **PROJECTION** entity + integer FK + dropdown (the codbex cross-project pattern - no local table/DAO/controller for the target), resolved against the owner's already-generated `.model` (leaf-first generation; convention fallback otherwise). **n:m** is an explicit **intermediate entity** (composition to one side + `manyToOne` to the other, which may be cross-model, plus bridge fields like `amount`) - `manyToMany` is parsed but never materialized. New field attributes: `unique`, `precision`/`scale`, `calculatedOnCreate`/`calculatedOnUpdate` (a neutral arithmetic expression for numeric totals, else emitted verbatim into the runtime), `calculatedActionOnCreate`/`calculatedActionOnUpdate` (server-side call-out to a hand-written `@Component implements org.eclipse.dirigible.sdk.db.CalculatedField<E,T>`, invoked as `Beans.get(<class>.class).calculate(entity)`, taking precedence over the expression — for logic too custom to model, e.g. number generation); field `readOnly: true` (not editable; rendered in the Harmonia form's read-only details block — Label:Value above the buttons — via `isReadOnlyProperty`; `ProcessId`/audit columns/`uuid` are auto-flagged read-only, `status`-style fields opt in); field `major: false` (kept off the entity **list** table — the model's `widgetIsMajor="false"` — still shown in forms + the record details pane; defaults true); entity `imports:` (Java `import` lines injected into the generated repository so a calculated action can be referenced by simple name — Base64-encoded into the `.model`'s `importsCode`, which the Java DAO template emits; the editor's entity-level Imports tab is the model-editor equivalent); entity `audit: true` (the four standard audit columns); entity `group:` (the perspective's nav-group id in the shared application shell). **Depends-On** is exposed as `dependsOn: { relation, valueFrom?, filterBy? }` on a to-one relation (cascading/narrowed dropdown) or a field (auto-populated value) — emitted as the EDM `widgetDependsOn*` attributes (the AngularJS stacks consume them as-is; the Harmonia runtime — form/document watchers + the metadata-driven item-dialog cascade — was added alongside); defaults are the respective primary keys, names are the target's authored property names, cross-model triggers/targets supported. **Multi-language data** (the TS-era `multilingual` port): entity `multilingual: true` → the schema layer generates a sibling `<TABLE>_LANG` table (`GUID, Id, <PascalCase translatable columns>, Language` — the codbex-uoms-data convention) and the generated Java repository overlays translated values on every read for the request's `Accept-Language` (SDK `Translator`, name-based merge); the supported language set is a PLATFORM concern (`DIRIGIBLE_APPLICATION_LANGUAGES`, default `en,bg`) — the Harmonia **Region & Language** Settings entry always offers that set (an Alpine `locale` store, localStorage `codbex.harmonia.language`, sent as `Accept-Language` by the shared fetch client — one flag drives UI, data, and the Print default), while the top-level `languages: [en, bg]` only declares which languages the module PROVIDES translations for; the application shell warns about modules missing a platform language, and untranslated content falls back to the default; translations are authored as seeds with `language: bg`, and large data sets reference an authored CSV via seed `file: data/x.csv` (subfolder mandatory — root `.csv` is scrub-owned) instead of inline rows. A master owning an `*Item` composition child renders as the **document (header-items) layout** (`MANAGE_DOCUMENT` + `documentItemsEntity`, `uiDocumentModels`), with `aggregate: true` fields shown in the totals footer. `IntentNaming.upperSnake` collapses kebab/space/`.`/`/` separators so a hyphenated model name yields a valid SQL identifier (`sales-invoices` -> `SALES_INVOICES`). Worked example: `dirigiblelabs/sample-intent-multi-model` (six interdependent projects + a navigation-groups project).

**The general platform line this enshrines:** authoring artifacts (`.edm`, `.model`, `.form`, `.report`, `.intent`) get **workspace editors + an explicit Generate**; only runtime artifacts (`.roles`, `.bpmn`, `.csvim`, `.table`, jobs, listeners, …) get **synchronizers**. Applying the synchronizer hammer to an authoring artifact generates into the registry where no modeler, Projects view, or template can use it — that mistake was made once and reverted; the inventory of synchronizers (grep `extends BaseSynchronizer`) deliberately contains no authoring formats.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,15 @@ public class DirigibleJavaScriptEndpointUriFactory extends org.apache.camel.supp

private static final Set<String> PROPERTY_NAMES;
private static final Set<String> SECRET_PROPERTY_NAMES;
private static final Set<String> ENDPOINT_IDENTITY_PROPERTY_NAMES;
private static final Map<String, String> MULTI_VALUE_PREFIXES;
static {
Set<String> props = new HashSet<>(2);
props.add("javaScriptPath");
props.add("lazyStartProducer");
PROPERTY_NAMES = Collections.unmodifiableSet(props);
SECRET_PROPERTY_NAMES = Collections.emptySet();
ENDPOINT_IDENTITY_PROPERTY_NAMES = Collections.emptySet();
MULTI_VALUE_PREFIXES = Collections.emptyMap();
}

Expand Down Expand Up @@ -58,6 +60,11 @@ public Set<String> secretPropertyNames() {
return SECRET_PROPERTY_NAMES;
}

@Override
public Set<String> endpointIdentityPropertyNames() {
return ENDPOINT_IDENTITY_PROPERTY_NAMES;
}

@Override
public Map<String, String> multiValuePrefixes() {
return MULTI_VALUE_PREFIXES;
Expand Down
Loading
Loading