@flusys/nestjs-entity-builder 9.1.1 → 9.1.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/README.md CHANGED
@@ -53,7 +53,13 @@ Works on PostgreSQL and MySQL (via `SchemaDialectAdapterService`). Import `Entit
53
53
  - Changes made outside the entity builder (a column dropped by hand) show up in `inspect` and are fixed by `repair`; extra columns are reported and never dropped automatically.
54
54
  - The entity/field metadata `update` endpoints are gone on purpose: every edit goes through `apply-change` so the table, the metadata and the schema cache cannot disagree.
55
55
  - Identifiers must match `^[a-z][a-z0-9_]{2,59}$`, not be an SQL reserved word, and the table (`eb_<code>`) must not already exist. Every DDL change takes a per-entity lock (`pg_advisory_xact_lock` / `GET_LOCK`, names over 64 characters hashed) - plus the lock of any relation target it points at - and is written to `eb_schema_change_log`.
56
- - Every filter/sort key of a flow's **Find records** step and of a `lookup` is checked against the entity's real fields; unknown keys are rejected (never interpolated into SQL). A filter value is a plain value (`=`) or `{ op, value? }` with `op` one of `eq`, `ne`, `gt`, `gte`, `lt`, `lte`, `in` (a list of at most 100 scalars; an empty list matches nothing), `is_null`, `not_null`. Operators map to a fixed SQL table and every value is a bound parameter. A Find step's `sort` is `{ field, direction? }` with a column code and `ASC` / `DESC` (left out: `ASC`); anything else is a save error (`flow.validation.node.sort.invalid`).
56
+ - Every filter/sort key of a flow's **Find records** step and of a `lookup` is checked against the entity's real fields; unknown keys are rejected (never interpolated into SQL). A filter value is a plain value (`=`; `null` means `IS NULL`) or `{ op, value? }`. Each operator has a value kind (`FILTER_OP_VALUE_KIND`):
57
+ - **single** - `eq`, `ne` (`null` = is / is not null), `gt`, `gte`, `lt`, `lte`, and the case-insensitive text operators `ieq`, `contains`, `not_contains`, `starts_with`, `ends_with` (`%`, `_`, `\` in the text match literally; a blank text is refused, since it would match every record).
58
+ - **list** (at most 100 scalars; a single scalar counts as a one-item list) - `in` (empty: matches nothing), `not_in` (empty: matches everything), and the multi-select operators `has_any` (empty: nothing), `has_all`, `has_none` (empty: everything).
59
+ - **range** - `between` / `not_between` on `[from, to]`, both ends included (in a flow: `{ from, to }`, each its own expression).
60
+ - **none** - `is_null` / `not_null` (SQL null, any field), `is_empty` / `not_empty` (null or blank text, or null or an empty multi-select list).
61
+
62
+ Operators must fit the field (`entity_builder.generic_record.filter.operator.not.for.field` otherwise): text operators need a text, long text, email or single-select field; `has_*` a multi-select; blank checks a text or multi-select; on multi-select and JSON fields only the null and blank checks are allowed. As in SQL, a negation (`ne`, `not_in`, `not_contains`, `not_between`, `has_none`) never matches a record whose field has no value - combine with `is_null` in another filter when those are wanted. Text matching is `ILIKE` on PostgreSQL and `LIKE` on MySQL (case-insensitive under its default collation); multi-select matching is `@>` / `JSON_CONTAINS`. Every value is a bound parameter. A Find step's `sort` is `{ field, direction? }` with a column code and `ASC` / `DESC` (left out: `ASC`); anything else is a save error (`flow.validation.node.sort.invalid`).
57
63
  - **Search** (a Find records step's search text) matches every searchable field by its text form, case-insensitively on both drivers (`CAST ... AS TEXT ILIKE` / `CAST ... AS CHAR LIKE`), so non-text fields can be searchable; `%` and `_` in the search text are literal.
58
64
  - Each entity gets the IAM actions `entity_builder.entity.<code>.<create|read|update|delete>` (only when IAM is installed). Flow steps do not check them (a flow's URL access is its gate): the entity's ready-made flow asks for them as its URLs' `permission` access, and any Request step or Check permission step can name them in its rule. DECIMAL fields are returned as numbers. `RELATION`/`FILE` are plain uuid columns (`char(36)` on MySQL, which has no uuid type) with no foreign-key constraint. Record events are `entity-builder.<code>.created` / `updated` / `deleted`, or `purged` for a delete on an entity with soft delete turned off - the same name whether the write ran inside a transactional flow or not.
59
65
  - **Tenants never share schemas**: every tenant DataSource gets its own copy of the entities array (`getEntityBuilderEntities()` returns a copy), and runtime schemas are registered per DataSource.
@@ -81,7 +87,7 @@ A flow is an endpoint (`POST /api-flows/<slug>`) whose behaviour is a graph of s
81
87
  - **Reference timing** (validation warnings): a step's result exists for the steps on a path after it; once a loop is done (`done` branch) its whole body's results exist too (their last pass). The validator warns when a step reads `context.<id>` of a step that has not run yet when it runs (later on the path, on another branch, or later in the same loop body), `loop.*` outside a loop's `each` branch (a foreach's own `collect` counts as inside), `loop.parent` beyond the loops around the step, or `context.<loop>.results` inside that loop (only `count` exists until it is done). Unreachable steps are not checked (they already warn).
82
88
 
83
89
  - **Validate**: `{ checks: [{ id, rule, message, field? }], mode: 'all' | 'first', statusCode? }`. `all` (default) evaluates every check and rejects with every failure; `first` stops at the first. The answer is `statusCode` (default 400, or 403 when every failed check is a permission check) with `errors: [{ field, message }]` (`field` defaults to the check id); one failure uses its message as the top-level message, several use `flow.checks.failed`. Example (attendance check-out): check 1 `left` = lookup `attendance` with `employee_id = input.employeeId`, `out_time is_null`, `in_time gte START_OF_DAY(NOW())`, mode `exists`, `is_true`; check 2 `left` = `DATE_DIFF(NOW(), <same lookup, mode first, field in_time>, 'hour')` `greater_or_equal` 5.
84
- - **Check permission** (`permission_check`): `{ permissions, onDenied: 'reject' | 'branch', statusCode?, message? }` - `permissions` is an AND / OR rule of permission codes (`ILogicNode` of nestjs-shared: `{ type: 'action', actionId: <code> }` or `{ type: 'group', operator: 'AND' | 'OR', children }`, nested up to 5 group levels, at most 50 codes; evaluated by `evaluatePermissionLogic()`, `*` / `prefix.*` grants match) `reject` (default) answers `statusCode` (403) with `message` (or `flow.permission.denied`) and stops, otherwise follows `out`; `branch` follows `allowed` / `denied` and never rejects. Checks the caller's effective permissions in their current company and branch (the same codes `my-permissions` returns). Output `{ allowed, missing }` - `missing` lists every code the rule names that the caller does not hold, whether or not the rule passed. A caller who is not signed in is denied (and the validator warns when any URL of the flow is `public` / `api_key`).
90
+ - **Check permission** (`permission_check`): `{ permissions, subject?, userId?, companyId?, branchId?, onDenied: 'reject' | 'branch', statusCode?, message? }` - `permissions` is an AND / OR rule of permission codes (`ILogicNode` of nestjs-shared: `{ type: 'action', actionId: <code> }` or `{ type: 'group', operator: 'AND' | 'OR', children }`, nested up to 5 group levels, at most 50 codes; evaluated by `evaluatePermissionLogic()`, `*` / `prefix.*` grants match) `reject` (default) answers `statusCode` (403) with `message` (or `flow.permission.denied`) and stops, otherwise follows `out`; `branch` follows `allowed` / `denied` and never rejects. Checks the effective permissions (the same codes `my-permissions` returns) of the signed-in caller (`subject: 'caller'`, the default) or of the user `userId` names (`subject: 'user'`, signed in or not - e.g. the approver of a record, also on a public or API-key URL). The scope is `companyId` (left out: the caller's current company) plus `branchId` (left out: the caller's current branch when checking the caller in that company, otherwise company-wide grants only; resolving to nothing: company-wide only) - with the company feature a branch adds its own grants on top of the company-wide ones; without it IAM ignores both. The caller in their current company and branch uses the run's cached codes; any other scope is first checked against what the user is granted (`COMPANY_ACCESS_RESOLVER`: the company, and the branch inside it) - a company or branch they are not granted holds no permissions - then asked of `PERMISSION_RESOLVER` (`RuleEngineService.permissionCodes`). Output `{ allowed, missing }` - `missing` lists every code the rule names that the user does not hold, whether or not the rule passed. No user (a caller who is not signed in, or a `userId` that resolves to nothing) is denied; the validator warns when a check of the caller sits behind a `public` / `api_key` URL (not one of another user), and requires `userId` for `subject: 'user'` (`node.access.user.required`).
85
91
  - **Company & Branch check** (`company_branch_check`, company feature): `{ subject?, userId?, companyIds?, branchIds?, branchMatch?, branchCompany?, onDenied?, statusCode?, message? }` - what a user may work in: the signed-in caller (`subject: 'caller'`, the default) or the user `userId` names (`subject: 'user'`, signed in or not - e.g. the owner of a record, also on a public or API-key URL). It needs no permission codes: it gets exactly what company select offers that user - the active companies granted to them and, inside those, the active branches granted to them. Output: `{ userId, currentCompanyId, currentBranchId, companies, branches }` - `companies` as `{ id, name }` (by name), `branches` as `{ id, companyId, parentId, name }` (per company, by serial); `currentCompanyId` / `currentBranchId` are the caller's current ones (null for another user). `companyIds` / `branchIds` (expressions: one id or a list, typically the record being changed; the designer starts the caller's on `user.companyId` / `user.branchId`) turn it into a guard: each id must be within reach (`allowed`, `missing: { companyIds, branchIds }`); a target that resolves to nothing is a denial. A company is within reach when it is granted; a branch per `branchMatch`: `direct` (default) - one of the granted branches; `within` - a granted branch or anywhere under one (`parentId` tree, `getDescendantIds(granted, { includeSelf: true })`, walked only when an asked-for branch is not granted itself), a child needing no grant of its own and the current branch playing no part. A user with no granted branch reaches none; without the branch tree `within` passes only granted branches. `branchCompany` picks whose branches count, for both matches (a walk starts only from the granted branches it keeps): `any` (default, stored as no key) - every company of the user; `current` - the caller's current company (refused on save for another user, who has none; no current company counts none). Then `onDenied` rejects (default, `statusCode` 403) or follows `allowed` / `denied` (which needs a target). No user means nothing is reachable. The data comes from `COMPANY_ACCESS_RESOLVER` and the tree from `BRANCH_HIERARCHY_RESOLVER` (nestjs-shared), both provided by nestjs-auth when the company feature is on (the grants `UserPermissionService` lists, kept to active companies and branches, looked up once per user per run); without them nothing is reachable. Save warns about a check of the caller on a URL reached without signing in (`permission.without.user`), not about one of another user. The designer offers the step only with the company feature.
86
92
  - **Code**: `{ code, timeoutMs? }` runs `code` as the body of a synchronous function in a QuickJS WebAssembly sandbox (`quickjs-emscripten`) on a worker thread (a small pool, at most 4), so a busy code step never blocks the server's event loop; the host also kills a worker that overruns its deadline. It reads a deep-frozen JSON copy of `{ input, vars, context, loop, user: { id, email, name, companyId, branchId, permissions? } }` as the global `ctx` (no request headers; `permissions`, the caller's codes in the current branch, is fetched only when the code mentions permissions). `hasPermission(code)`, `hasAnyPermission(...codes)` and `hasAllPermissions(...codes)` are plain JavaScript inside the sandbox over `ctx.user.permissions` with the server's wildcards and `return`s a JSON value, which becomes `context.<id>`. Nothing of the host is reachable (no `require`, `process`, network, filesystem, timers or database); `console.log` is captured into the trace (`trace[].logs`, 50 lines of 500 characters, sensitive-looking keys masked). Every run gets a fresh runtime with a 32 MB memory limit, a 512 KB stack and an interrupt deadline of `timeoutMs` (default 1000, 10-5000) clamped to the time left in the flow; the output may be at most 1 MB. A throw, time-out or memory overflow is a node error (`flow.error.code.*`), so `onError: continue` and the `error` port work. Code nodes also run in dry runs. Saving a flow that contains a code node needs `entity_builder.flow_definition.code`.
87
93
  - **Create / Update / Delete record** write several records in one step through `target`: `one` (default, left out) writes one record; `many` writes one per item of `items` (up to `FLOW_LIMITS.MAX_WRITE_ITEMS` = 1000), and the step's per-record values (`fields`, `id`) read the item as `loop.item` / `loop.index` with a loop around the step as `loop.parent`; `filter` (update / delete) writes every record matching `filter` (same shape as Find), read as `loop.item` (e.g. `stock = loop.item.stock - 1`). A filter that resolves to nothing is refused (`flow.error.write.filter.empty`) instead of changing every record, and more matches than `limit` (1-1000, default 100) fail the step (`flow.error.too.many.matches`) instead of changing some. In `many` mode `id` defaults to the item's own id (the item itself when it is text, else `item.id`). `onNotFound`: `error` (default), `skip`, or for update `insert` (upsert: a missing record, or in `many` mode an item with an empty id, is created with the same field values - needs the entity's `create` permission too). Create takes `children` (up to 10): `{ as, entityCode, parentField, items, fields }` saves child records under every saved record, `parentField` filled with the parent's id; `items` is read in the parent's scope (`loop.item.lines` in `many` mode, `input.lines` otherwise) and child `fields` read the child item as `loop.item` and the parent's scope as `loop.parent`. Results: create one = the record plus one array per `as`; create many = `{ items, count }`; update one = the record (`null` when skipped); update many / filter = `{ items, count, updated, created, skipped }`; delete one = `{ id, deleted }`; delete many / filter = `{ ids, count, skipped }` (an id listed twice is deleted once). A create never takes an `id` field (`generic_record.system.column.readonly`), so it cannot overwrite an existing record; an upsert's created record ignores a mapped `id`. A step that writes several records (`many`, `filter`, or any `children`) is **all-or-nothing on its own**: inside a transactional run it uses the run's transaction, otherwise it opens a transaction for just that step and publishes its record events after that commit. Every record written counts against `FLOW_LIMITS.MAX_WRITES_PER_RUN` (5000, shared with called flows).
@@ -92,7 +98,7 @@ A flow is an endpoint (`POST /api-flows/<slug>`) whose behaviour is a graph of s
92
98
  - **Body type** (a Request step's `config.bodyType`, default `object`, left out when `object`): `object` - the body is one object and the input fields are its keys (`input.<name>`); `list` - the body itself is a list, like `insert-many` (`POST api-flows/<slug>` with `[{...}, {...}]`), the input fields describe each item, every item is checked the same way (errors name the index: `[0].sku`; a body that is not a list is refused with `flow.input.body.not.list`), and the flow reads the list as `input` (a For each over `input`, or `input.0.<name>`). With no fields declared a list body is passed through as-is. A Call flow step sends a list-bodied flow one expression, `inputList`, instead of named `input`s; saving checks the step matches the called flow's body type (`node.flow.input.list.required` / `.unexpected`). The test run accepts a list `input` too.
93
99
  - **Input**: each Request step declares its request fields (`config.inputSchema`) (type, required, default, min/max, choices). The body is checked and converted with the same validator entity records use; undeclared keys are dropped; every problem is returned at once (400). An `object` field may declare its own `fields`; an `array` field may declare an `itemType` (any type but `array`) that every item must have - min/max/length/options then apply to each item - and a list of objects (`itemType: 'object'`) declares the `fields` of each item. Nested values are checked the same way (undeclared keys inside them are dropped too), errors name their path (`address.city`, `items[0].qty`), and nesting goes at most `FLOW_LIMITS.MAX_INPUT_DEPTH` (4) levels. Without `fields` / `itemType` the value is only checked to be an object / a list. Generated entity flows declare `ids` as a list of ids and a multi-select field as a list of its choices; their bulk flows use a `list` body whose items are the entity fields.
94
100
  - **Who can call it**: set on each Request step - there is no flow-level access. `config.authMode`: `jwt` (any signed-in user; the default, stored as no setting), `permission` (`config.permissions`: an AND / OR rule of permission codes (`ILogicNode` of nestjs-shared: `{ type: 'action', actionId: <code> }` or `{ type: 'group', operator: 'AND' | 'OR', children }`, nested up to 5 group levels, at most 50 codes; evaluated by `evaluatePermissionLogic()`, `*` / `prefix.*` grants match); none: `entity_builder.flow.<slug>.execute`, provisioned as an IAM action on publish - a rule names existing actions, which are not re-registered. The guard checks it with `SharedPermissionCacheService.assertPermissionLogic`), `api_key` (the step's own key, sent as `x-api-key`: the designer makes it (`fk_<8 hex>_<32 hex>`) and sends it in `config.apiKey` once; every save replaces it with `{ prefix, hash }` (SHA-256, `sealApiKeys()`), so the key itself is never stored and cannot be shown again. The guard compares in constant time against the published step's hash; a wrong or missing key answers 401 `flow.api.key.invalid`, and one step's key never opens another. A step without a key cannot be saved (`trigger.api.key.required`, or `.invalid` for a malformed one); a new key replaces the old one once the flow is published; a step that leaves API-key access drops its key), `public`, or `internal` - **other flows only**: the step has no URL (it answers 404), only other flows' Call flow steps start there, and that run takes the calling flow's user. A flow whose every Request step is `internal` is a **function** (`isFunctionFlow()`). A URL reached without signing in (`public`, `api_key`) runs with no `user`: permission checks and the caller's Company & Branch check deny, while its record steps run for anyone who can call it (validator warning `keyless.entity`, naming the URLs and the entities they read or change). Unknown, inactive and never-published flows all answer 404. Each Request step's per-caller-IP rate limit (`config.rateLimitPerMinute`, default 60, 0 = unlimited; counted per step) runs **before** credentials are checked (in memory per server instance, fixed one-minute windows, at most 10,000 tracked callers - the oldest window is dropped beyond that).
95
- - **Find record** filters accept the `{ op, value }` operators (the value side is an expression). A filter entry is an operator only when it is authored as exactly `{ op, value? }` with a known `op` (any other key, or an unknown `op`, and it is not a condition - so an expression such as `{ type: 'arithmetic', op: 'add', ... }` is a plain value). A value resolved at run time (from input, a variable, a step result) is only ever an operand: an object or list is compared for equality and refused as not one value, never read as an operator, so `{ "op": "not_null" }` sent as input cannot widen a Find, lookup, update or delete. On a Find an entry that resolves to nothing is left out; on an update / delete by filter it fails the step (`flow.error.filter.value.missing`) instead of widening the write.
101
+ - **Find record** filters accept the `{ op, value }` operators (the value side is an expression). A filter entry is an operator only when it is authored as exactly `{ op, value? }` with a known `op` (any other key, or an unknown `op`, and it is not a condition - so an expression such as `{ type: 'arithmetic', op: 'add', ... }` is a plain value). A value resolved at run time (from input, a variable, a step result) is only ever an operand: an object or list is compared for equality and refused as not one value, never read as an operator, so `{ "op": "not_null" }` sent as input cannot widen a Find, lookup, update or delete. On a Find an entry that resolves to nothing (for a range: either bound) is left out; on an update / delete by filter it fails the step (`flow.error.filter.value.missing`) instead of widening the write. A range's value must be `{ from, to }` (`flow.shape.filter.range.invalid`). Flows and lookups resolve every entry through `resolveFilterEntry()` (`rule-values.ts`).
96
102
  - **Checks cannot be carried past**: a failed Validate or Check permission step (like Save progress) always ends the run, whatever its `onError` says.
97
103
  - **Access is the gate**: a Request step's *Who can call it* decides who may start a run, and then every step reads and writes records with no per-entity permission check (`entity_builder.entity.<entity>.<action>` counts only where an access rule or a Check permission step names it, as the ready-made entity flow does) and may notify any company. Finer rules are the flow's own: a **Check permission** step, a **Company & Branch check**, or `HAS_PERMISSION()` in a condition. Since whoever may save flows decides what each URL exposes, grant `flow_definition.create` / `.update` like deploy rights.
98
104
  - **Transactions** (a Request step's `config.isTransactional`, the designer's "All writes together"): the entity writes of a run that starts at a transactional Request step commit or roll back together; the flow's other URLs open no transaction unless they set it too; entity events and **Publish event** steps are published only after the commit, in order, and never for a run that rolled back - nor for the rows of a step whose savepoint (`onError: continue`) rolled back. Metadata a transactional run needs (entity and field definitions, called flows) is read on the run's own transaction, so a run never waits on a second pooled connection. HTTP calls cannot be rolled back, so a transactional Request step whose runs reach an HTTP step is flagged in the warnings. In a run without a transaction each step commits on its own, except that a multi-record write step (many, or with child records) is always all-or-nothing (see above); make the Request step transactional when several steps must succeed or fail together, and add **Save progress** steps where the work so far must be kept even if a later step fails.
@@ -56,6 +56,7 @@ export declare const GENERIC_RECORD_MESSAGES: {
56
56
  readonly FILTER_OPERATOR_UNKNOWN: "entity_builder.generic_record.filter.operator.unknown";
57
57
  readonly FILTER_VALUE_INVALID: "entity_builder.generic_record.filter.value.invalid";
58
58
  readonly FILTER_TOO_MANY_VALUES: "entity_builder.generic_record.filter.too.many.values";
59
+ readonly FILTER_OPERATOR_NOT_FOR_FIELD: "entity_builder.generic_record.filter.operator.not.for.field";
59
60
  };
60
61
  export declare const SCHEMA_MESSAGES: {
61
62
  readonly BUSY: "entity_builder.schema.busy";
@@ -490,6 +491,7 @@ export declare const FLOW_SHAPE_MESSAGES: {
490
491
  readonly LOOKUP_FIELD_INVALID: "entity_builder.flow.shape.lookup.field.invalid";
491
492
  readonly FILTER_OPERATOR_UNKNOWN: "entity_builder.flow.shape.filter.operator.unknown";
492
493
  readonly FILTER_VALUE_REQUIRED: "entity_builder.flow.shape.filter.value.required";
494
+ readonly FILTER_RANGE_INVALID: "entity_builder.flow.shape.filter.range.invalid";
493
495
  };
494
496
  export declare const FLOW_SUBJECT_MESSAGES: {
495
497
  readonly THE_RULE: "entity_builder.flow.subject.the.rule";
@@ -510,6 +512,7 @@ export declare const FLOW_SUBJECT_MESSAGES: {
510
512
  readonly THE_COMPANY: "entity_builder.flow.subject.the.company";
511
513
  readonly THE_COMPANIES: "entity_builder.flow.subject.the.companies";
512
514
  readonly THE_BRANCHES: "entity_builder.flow.subject.the.branches";
515
+ readonly THE_BRANCH: "entity_builder.flow.subject.the.branch";
513
516
  readonly THE_USER: "entity_builder.flow.subject.the.user";
514
517
  readonly THE_CC: "entity_builder.flow.subject.the.cc";
515
518
  readonly THE_BCC: "entity_builder.flow.subject.the.bcc";
package/fesm/21.js CHANGED
@@ -61,7 +61,8 @@ const GENERIC_RECORD_MESSAGES = {
61
61
  REFERENCE_VIOLATION: 'entity_builder.generic_record.reference.violation',
62
62
  FILTER_OPERATOR_UNKNOWN: 'entity_builder.generic_record.filter.operator.unknown',
63
63
  FILTER_VALUE_INVALID: 'entity_builder.generic_record.filter.value.invalid',
64
- FILTER_TOO_MANY_VALUES: 'entity_builder.generic_record.filter.too.many.values'
64
+ FILTER_TOO_MANY_VALUES: 'entity_builder.generic_record.filter.too.many.values',
65
+ FILTER_OPERATOR_NOT_FOR_FIELD: 'entity_builder.generic_record.filter.operator.not.for.field'
65
66
  };
66
67
  const SCHEMA_MESSAGES = {
67
68
  BUSY: 'entity_builder.schema.busy',
@@ -495,7 +496,8 @@ const FLOW_MESSAGES = {
495
496
  LOOKUP_FILTER_INVALID: 'entity_builder.flow.shape.lookup.filter.invalid',
496
497
  LOOKUP_FIELD_INVALID: 'entity_builder.flow.shape.lookup.field.invalid',
497
498
  FILTER_OPERATOR_UNKNOWN: 'entity_builder.flow.shape.filter.operator.unknown',
498
- FILTER_VALUE_REQUIRED: 'entity_builder.flow.shape.filter.value.required'
499
+ FILTER_VALUE_REQUIRED: 'entity_builder.flow.shape.filter.value.required',
500
+ FILTER_RANGE_INVALID: 'entity_builder.flow.shape.filter.range.invalid'
499
501
  };
500
502
  /** What a flow node problem is about (`what` variable of the node validation messages). */ const FLOW_SUBJECT_MESSAGES = {
501
503
  THE_RULE: 'entity_builder.flow.subject.the.rule',
@@ -516,6 +518,7 @@ const FLOW_MESSAGES = {
516
518
  THE_COMPANY: 'entity_builder.flow.subject.the.company',
517
519
  THE_COMPANIES: 'entity_builder.flow.subject.the.companies',
518
520
  THE_BRANCHES: 'entity_builder.flow.subject.the.branches',
521
+ THE_BRANCH: 'entity_builder.flow.subject.the.branch',
519
522
  THE_USER: 'entity_builder.flow.subject.the.user',
520
523
  THE_CC: 'entity_builder.flow.subject.the.cc',
521
524
  THE_BCC: 'entity_builder.flow.subject.the.bcc',
package/fesm/458.js CHANGED
@@ -34,8 +34,8 @@ var event_actions = __webpack_require__(982);
34
34
  var controllers = __webpack_require__(729);
35
35
  // EXTERNAL MODULE: ./projects/nestjs-entity-builder/src/interfaces/reference-provider.interface.ts
36
36
  var reference_provider_interface = __webpack_require__(2492);
37
- // EXTERNAL MODULE: ./projects/nestjs-entity-builder/src/rule-engine/index.ts + 1 modules
38
- var rule_engine = __webpack_require__(8429);
37
+ // EXTERNAL MODULE: ./projects/nestjs-entity-builder/src/rule-engine/index.ts + 2 modules
38
+ var rule_engine = __webpack_require__(8552);
39
39
  // EXTERNAL MODULE: ./projects/nestjs-entity-builder/src/services/index.ts + 3 modules
40
40
  var services = __webpack_require__(8752);
41
41
  // EXTERNAL MODULE: ./projects/nestjs-entity-builder/src/guards/index.ts