@fieldia/core 0.1.0
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/LICENSE +21 -0
- package/README.md +31 -0
- package/package.json +40 -0
- package/schema/page.schema.json +2142 -0
- package/src/index.d.mts +15 -0
- package/src/index.d.ts +15 -0
- package/src/index.js +46 -0
- package/src/index.js.map +1 -0
- package/src/index.mjs +14 -0
- package/src/index.mjs.map +1 -0
- package/src/lib/expression/evaluateModifier.d.mts +55 -0
- package/src/lib/expression/evaluateModifier.d.ts +55 -0
- package/src/lib/expression/evaluateModifier.js +121 -0
- package/src/lib/expression/evaluateModifier.js.map +1 -0
- package/src/lib/expression/evaluateModifier.mjs +117 -0
- package/src/lib/expression/evaluateModifier.mjs.map +1 -0
- package/src/lib/expression/evaluator.d.mts +23 -0
- package/src/lib/expression/evaluator.d.ts +23 -0
- package/src/lib/expression/evaluator.js +122 -0
- package/src/lib/expression/evaluator.js.map +1 -0
- package/src/lib/expression/evaluator.mjs +118 -0
- package/src/lib/expression/evaluator.mjs.map +1 -0
- package/src/lib/expression/extractFieldNames.d.mts +41 -0
- package/src/lib/expression/extractFieldNames.d.ts +41 -0
- package/src/lib/expression/extractFieldNames.js +97 -0
- package/src/lib/expression/extractFieldNames.js.map +1 -0
- package/src/lib/expression/extractFieldNames.mjs +93 -0
- package/src/lib/expression/extractFieldNames.mjs.map +1 -0
- package/src/lib/expression/modifier.d.mts +14 -0
- package/src/lib/expression/modifier.d.ts +14 -0
- package/src/lib/expression/modifier.js +55 -0
- package/src/lib/expression/modifier.js.map +1 -0
- package/src/lib/expression/modifier.mjs +52 -0
- package/src/lib/expression/modifier.mjs.map +1 -0
- package/src/lib/expression/parser.d.mts +109 -0
- package/src/lib/expression/parser.d.ts +109 -0
- package/src/lib/expression/parser.js +317 -0
- package/src/lib/expression/parser.js.map +1 -0
- package/src/lib/expression/parser.mjs +313 -0
- package/src/lib/expression/parser.mjs.map +1 -0
- package/src/lib/expression/tokenizer.d.mts +31 -0
- package/src/lib/expression/tokenizer.d.ts +31 -0
- package/src/lib/expression/tokenizer.js +100 -0
- package/src/lib/expression/tokenizer.js.map +1 -0
- package/src/lib/expression/tokenizer.mjs +96 -0
- package/src/lib/expression/tokenizer.mjs.map +1 -0
- package/src/lib/format/field.d.mts +967 -0
- package/src/lib/format/field.d.ts +967 -0
- package/src/lib/format/field.js +147 -0
- package/src/lib/format/field.js.map +1 -0
- package/src/lib/format/field.mjs +144 -0
- package/src/lib/format/field.mjs.map +1 -0
- package/src/lib/format/json-schema.d.mts +6 -0
- package/src/lib/format/json-schema.d.ts +6 -0
- package/src/lib/format/json-schema.js +14 -0
- package/src/lib/format/json-schema.js.map +1 -0
- package/src/lib/format/json-schema.mjs +11 -0
- package/src/lib/format/json-schema.mjs.map +1 -0
- package/src/lib/format/json.d.mts +7 -0
- package/src/lib/format/json.d.ts +7 -0
- package/src/lib/format/json.js +7 -0
- package/src/lib/format/json.js.map +1 -0
- package/src/lib/format/json.mjs +4 -0
- package/src/lib/format/json.mjs.map +1 -0
- package/src/lib/format/layout.d.mts +521 -0
- package/src/lib/format/layout.d.ts +521 -0
- package/src/lib/format/layout.js +150 -0
- package/src/lib/format/layout.js.map +1 -0
- package/src/lib/format/layout.mjs +147 -0
- package/src/lib/format/layout.mjs.map +1 -0
- package/src/lib/format/layout.types.d.mts +22 -0
- package/src/lib/format/layout.types.d.ts +22 -0
- package/src/lib/format/layout.types.js +3 -0
- package/src/lib/format/layout.types.js.map +1 -0
- package/src/lib/format/layout.types.mjs +2 -0
- package/src/lib/format/layout.types.mjs.map +1 -0
- package/src/lib/format/page.d.mts +511 -0
- package/src/lib/format/page.d.ts +511 -0
- package/src/lib/format/page.js +27 -0
- package/src/lib/format/page.js.map +1 -0
- package/src/lib/format/page.mjs +24 -0
- package/src/lib/format/page.mjs.map +1 -0
- package/src/lib/format/validate.d.mts +23 -0
- package/src/lib/format/validate.d.ts +23 -0
- package/src/lib/format/validate.js +210 -0
- package/src/lib/format/validate.js.map +1 -0
- package/src/lib/format/validate.mjs +207 -0
- package/src/lib/format/validate.mjs.map +1 -0
- package/src/lib/record/check.d.mts +14 -0
- package/src/lib/record/check.d.ts +14 -0
- package/src/lib/record/check.js +167 -0
- package/src/lib/record/check.js.map +1 -0
- package/src/lib/record/check.mjs +163 -0
- package/src/lib/record/check.mjs.map +1 -0
- package/src/lib/record/data-source.d.mts +109 -0
- package/src/lib/record/data-source.d.ts +109 -0
- package/src/lib/record/data-source.js +3 -0
- package/src/lib/record/data-source.js.map +1 -0
- package/src/lib/record/data-source.mjs +2 -0
- package/src/lib/record/data-source.mjs.map +1 -0
- package/src/lib/record/form.d.mts +106 -0
- package/src/lib/record/form.d.ts +106 -0
- package/src/lib/record/form.js +545 -0
- package/src/lib/record/form.js.map +1 -0
- package/src/lib/record/form.mjs +542 -0
- package/src/lib/record/form.mjs.map +1 -0
- package/src/lib/record/memory-data-source.d.mts +28 -0
- package/src/lib/record/memory-data-source.d.ts +28 -0
- package/src/lib/record/memory-data-source.js +132 -0
- package/src/lib/record/memory-data-source.js.map +1 -0
- package/src/lib/record/memory-data-source.mjs +129 -0
- package/src/lib/record/memory-data-source.mjs.map +1 -0
- package/src/lib/record/messages.d.mts +35 -0
- package/src/lib/record/messages.d.ts +35 -0
- package/src/lib/record/messages.js +111 -0
- package/src/lib/record/messages.js.map +1 -0
- package/src/lib/record/messages.mjs +107 -0
- package/src/lib/record/messages.mjs.map +1 -0
- package/src/lib/record/scheduler.d.mts +12 -0
- package/src/lib/record/scheduler.d.ts +12 -0
- package/src/lib/record/scheduler.js +16 -0
- package/src/lib/record/scheduler.js.map +1 -0
- package/src/lib/record/scheduler.mjs +12 -0
- package/src/lib/record/scheduler.mjs.map +1 -0
- package/src/lib/record/values.d.mts +54 -0
- package/src/lib/record/values.d.ts +54 -0
- package/src/lib/record/values.js +78 -0
- package/src/lib/record/values.js.map +1 -0
- package/src/lib/record/values.mjs +71 -0
- package/src/lib/record/values.mjs.map +1 -0
package/src/index.d.mts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type { JsonValue } from './lib/format/json.mjs';
|
|
2
|
+
export { FIELD_NAME, FIELD_TYPES, FieldSchema, FieldsSchema, LineFieldSchema, OptionSchema, FilterConditionSchema, type Field, type Fields, type FieldType, type LineField, type Option, type FilterCondition, } from './lib/format/field.mjs';
|
|
3
|
+
export { ModifierSchema, LayoutNodeSchema, RootLayoutSchema, type Modifier, type Tone, type FieldNode, type ButtonNode, type TextNode, type SlotNode, type SectionNode, type TabNode, type TabsNode, type StepNode, type WizardNode, type SectionsNode, type SheetNode, type SheetTitle, type Statusbar, type StatButton, type Ribbon, type Alert, type LayoutNode, type RootLayout, } from './lib/format/layout.mjs';
|
|
4
|
+
export { FORMAT_VERSION, PageSchema, type Page, type PageData } from './lib/format/page.mjs';
|
|
5
|
+
export { validatePage, type PageIssue, type PageValidation } from './lib/format/validate.mjs';
|
|
6
|
+
export { pageJsonSchema } from './lib/format/json-schema.mjs';
|
|
7
|
+
export { compileModifier, type CompiledModifier } from './lib/expression/modifier.mjs';
|
|
8
|
+
export { evaluateModifier, isModifierValid } from './lib/expression/evaluateModifier.mjs';
|
|
9
|
+
export { emptyValue, initialValues, isEmpty, expressionContext, type RecordId, type RelatedRecord, type ReferenceValue, type FileValue, type Line, type Value, type Values, } from './lib/record/values.mjs';
|
|
10
|
+
export { checkValue, formatBytes } from './lib/record/check.mjs';
|
|
11
|
+
export type { DataSource, LoadRequest, SaveRequest, SaveResult, OnchangeRequest, OnchangeResult, SearchRequest, SubmitRequest, SubmitResult, ResolvedFilterCondition, RecordChanges, LineOp, LinkOp, } from './lib/record/data-source.mjs';
|
|
12
|
+
export { createMemoryDataSource, type MemoryDataSource, type MemoryDataSourceOptions } from './lib/record/memory-data-source.mjs';
|
|
13
|
+
export { hostScheduler, wait, type Scheduler } from './lib/record/scheduler.mjs';
|
|
14
|
+
export { createForm, type Form, type FormOptions, type FormState, type FormStatus, type NodeState, type DraftStore, type ActionRequest, } from './lib/record/form.mjs';
|
|
15
|
+
export { MESSAGES, fill, type Messages, type Locale } from './lib/record/messages.mjs';
|
package/src/index.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type { JsonValue } from './lib/format/json';
|
|
2
|
+
export { FIELD_NAME, FIELD_TYPES, FieldSchema, FieldsSchema, LineFieldSchema, OptionSchema, FilterConditionSchema, type Field, type Fields, type FieldType, type LineField, type Option, type FilterCondition, } from './lib/format/field';
|
|
3
|
+
export { ModifierSchema, LayoutNodeSchema, RootLayoutSchema, type Modifier, type Tone, type FieldNode, type ButtonNode, type TextNode, type SlotNode, type SectionNode, type TabNode, type TabsNode, type StepNode, type WizardNode, type SectionsNode, type SheetNode, type SheetTitle, type Statusbar, type StatButton, type Ribbon, type Alert, type LayoutNode, type RootLayout, } from './lib/format/layout';
|
|
4
|
+
export { FORMAT_VERSION, PageSchema, type Page, type PageData } from './lib/format/page';
|
|
5
|
+
export { validatePage, type PageIssue, type PageValidation } from './lib/format/validate';
|
|
6
|
+
export { pageJsonSchema } from './lib/format/json-schema';
|
|
7
|
+
export { compileModifier, type CompiledModifier } from './lib/expression/modifier';
|
|
8
|
+
export { evaluateModifier, isModifierValid } from './lib/expression/evaluateModifier';
|
|
9
|
+
export { emptyValue, initialValues, isEmpty, expressionContext, type RecordId, type RelatedRecord, type ReferenceValue, type FileValue, type Line, type Value, type Values, } from './lib/record/values';
|
|
10
|
+
export { checkValue, formatBytes } from './lib/record/check';
|
|
11
|
+
export type { DataSource, LoadRequest, SaveRequest, SaveResult, OnchangeRequest, OnchangeResult, SearchRequest, SubmitRequest, SubmitResult, ResolvedFilterCondition, RecordChanges, LineOp, LinkOp, } from './lib/record/data-source';
|
|
12
|
+
export { createMemoryDataSource, type MemoryDataSource, type MemoryDataSourceOptions } from './lib/record/memory-data-source';
|
|
13
|
+
export { hostScheduler, wait, type Scheduler } from './lib/record/scheduler';
|
|
14
|
+
export { createForm, type Form, type FormOptions, type FormState, type FormStatus, type NodeState, type DraftStore, type ActionRequest, } from './lib/record/form';
|
|
15
|
+
export { MESSAGES, fill, type Messages, type Locale } from './lib/record/messages';
|
package/src/index.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.fill = exports.MESSAGES = exports.createForm = exports.wait = exports.hostScheduler = exports.createMemoryDataSource = exports.formatBytes = exports.checkValue = exports.expressionContext = exports.isEmpty = exports.initialValues = exports.emptyValue = exports.isModifierValid = exports.evaluateModifier = exports.compileModifier = exports.pageJsonSchema = exports.validatePage = exports.PageSchema = exports.FORMAT_VERSION = exports.RootLayoutSchema = exports.LayoutNodeSchema = exports.ModifierSchema = exports.FilterConditionSchema = exports.OptionSchema = exports.LineFieldSchema = exports.FieldsSchema = exports.FieldSchema = exports.FIELD_TYPES = exports.FIELD_NAME = void 0;
|
|
4
|
+
var field_1 = require("./lib/format/field");
|
|
5
|
+
Object.defineProperty(exports, "FIELD_NAME", { enumerable: true, get: function () { return field_1.FIELD_NAME; } });
|
|
6
|
+
Object.defineProperty(exports, "FIELD_TYPES", { enumerable: true, get: function () { return field_1.FIELD_TYPES; } });
|
|
7
|
+
Object.defineProperty(exports, "FieldSchema", { enumerable: true, get: function () { return field_1.FieldSchema; } });
|
|
8
|
+
Object.defineProperty(exports, "FieldsSchema", { enumerable: true, get: function () { return field_1.FieldsSchema; } });
|
|
9
|
+
Object.defineProperty(exports, "LineFieldSchema", { enumerable: true, get: function () { return field_1.LineFieldSchema; } });
|
|
10
|
+
Object.defineProperty(exports, "OptionSchema", { enumerable: true, get: function () { return field_1.OptionSchema; } });
|
|
11
|
+
Object.defineProperty(exports, "FilterConditionSchema", { enumerable: true, get: function () { return field_1.FilterConditionSchema; } });
|
|
12
|
+
var layout_1 = require("./lib/format/layout");
|
|
13
|
+
Object.defineProperty(exports, "ModifierSchema", { enumerable: true, get: function () { return layout_1.ModifierSchema; } });
|
|
14
|
+
Object.defineProperty(exports, "LayoutNodeSchema", { enumerable: true, get: function () { return layout_1.LayoutNodeSchema; } });
|
|
15
|
+
Object.defineProperty(exports, "RootLayoutSchema", { enumerable: true, get: function () { return layout_1.RootLayoutSchema; } });
|
|
16
|
+
var page_1 = require("./lib/format/page");
|
|
17
|
+
Object.defineProperty(exports, "FORMAT_VERSION", { enumerable: true, get: function () { return page_1.FORMAT_VERSION; } });
|
|
18
|
+
Object.defineProperty(exports, "PageSchema", { enumerable: true, get: function () { return page_1.PageSchema; } });
|
|
19
|
+
var validate_1 = require("./lib/format/validate");
|
|
20
|
+
Object.defineProperty(exports, "validatePage", { enumerable: true, get: function () { return validate_1.validatePage; } });
|
|
21
|
+
var json_schema_1 = require("./lib/format/json-schema");
|
|
22
|
+
Object.defineProperty(exports, "pageJsonSchema", { enumerable: true, get: function () { return json_schema_1.pageJsonSchema; } });
|
|
23
|
+
var modifier_1 = require("./lib/expression/modifier");
|
|
24
|
+
Object.defineProperty(exports, "compileModifier", { enumerable: true, get: function () { return modifier_1.compileModifier; } });
|
|
25
|
+
var evaluateModifier_1 = require("./lib/expression/evaluateModifier");
|
|
26
|
+
Object.defineProperty(exports, "evaluateModifier", { enumerable: true, get: function () { return evaluateModifier_1.evaluateModifier; } });
|
|
27
|
+
Object.defineProperty(exports, "isModifierValid", { enumerable: true, get: function () { return evaluateModifier_1.isModifierValid; } });
|
|
28
|
+
var values_1 = require("./lib/record/values");
|
|
29
|
+
Object.defineProperty(exports, "emptyValue", { enumerable: true, get: function () { return values_1.emptyValue; } });
|
|
30
|
+
Object.defineProperty(exports, "initialValues", { enumerable: true, get: function () { return values_1.initialValues; } });
|
|
31
|
+
Object.defineProperty(exports, "isEmpty", { enumerable: true, get: function () { return values_1.isEmpty; } });
|
|
32
|
+
Object.defineProperty(exports, "expressionContext", { enumerable: true, get: function () { return values_1.expressionContext; } });
|
|
33
|
+
var check_1 = require("./lib/record/check");
|
|
34
|
+
Object.defineProperty(exports, "checkValue", { enumerable: true, get: function () { return check_1.checkValue; } });
|
|
35
|
+
Object.defineProperty(exports, "formatBytes", { enumerable: true, get: function () { return check_1.formatBytes; } });
|
|
36
|
+
var memory_data_source_1 = require("./lib/record/memory-data-source");
|
|
37
|
+
Object.defineProperty(exports, "createMemoryDataSource", { enumerable: true, get: function () { return memory_data_source_1.createMemoryDataSource; } });
|
|
38
|
+
var scheduler_1 = require("./lib/record/scheduler");
|
|
39
|
+
Object.defineProperty(exports, "hostScheduler", { enumerable: true, get: function () { return scheduler_1.hostScheduler; } });
|
|
40
|
+
Object.defineProperty(exports, "wait", { enumerable: true, get: function () { return scheduler_1.wait; } });
|
|
41
|
+
var form_1 = require("./lib/record/form");
|
|
42
|
+
Object.defineProperty(exports, "createForm", { enumerable: true, get: function () { return form_1.createForm; } });
|
|
43
|
+
var messages_1 = require("./lib/record/messages");
|
|
44
|
+
Object.defineProperty(exports, "MESSAGES", { enumerable: true, get: function () { return messages_1.MESSAGES; } });
|
|
45
|
+
Object.defineProperty(exports, "fill", { enumerable: true, get: function () { return messages_1.fill; } });
|
|
46
|
+
//# sourceMappingURL=index.js.map
|
package/src/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../libs/core/src/index.ts"],"names":[],"mappings":";;;AACA,4CAc4B;AAb1B,mGAAA,UAAU,OAAA;AACV,oGAAA,WAAW,OAAA;AACX,oGAAA,WAAW,OAAA;AACX,qGAAA,YAAY,OAAA;AACZ,wGAAA,eAAe,OAAA;AACf,qGAAA,YAAY,OAAA;AACZ,8GAAA,qBAAqB,OAAA;AAQvB,8CAwB6B;AAvB3B,wGAAA,cAAc,OAAA;AACd,0GAAA,gBAAgB,OAAA;AAChB,0GAAA,gBAAgB,OAAA;AAsBlB,0CAAyF;AAAhF,sGAAA,cAAc,OAAA;AAAE,kGAAA,UAAU,OAAA;AACnC,kDAA0F;AAAjF,wGAAA,YAAY,OAAA;AACrB,wDAA0D;AAAjD,6GAAA,cAAc,OAAA;AACvB,sDAAmF;AAA1E,2GAAA,eAAe,OAAA;AACxB,sEAAsF;AAA7E,oHAAA,gBAAgB,OAAA;AAAE,mHAAA,eAAe,OAAA;AAC1C,8CAY6B;AAX3B,oGAAA,UAAU,OAAA;AACV,uGAAA,aAAa,OAAA;AACb,iGAAA,OAAO,OAAA;AACP,2GAAA,iBAAiB,OAAA;AASnB,4CAA6D;AAApD,mGAAA,UAAU,OAAA;AAAE,oGAAA,WAAW,OAAA;AAgBhC,sEAA8H;AAArH,4HAAA,sBAAsB,OAAA;AAC/B,oDAA6E;AAApE,0GAAA,aAAa,OAAA;AAAE,iGAAA,IAAI,OAAA;AAC5B,0CAS2B;AARzB,kGAAA,UAAU,OAAA;AASZ,kDAAmF;AAA1E,oGAAA,QAAQ,OAAA;AAAE,gGAAA,IAAI,OAAA"}
|
package/src/index.mjs
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export { FIELD_NAME, FIELD_TYPES, FieldSchema, FieldsSchema, LineFieldSchema, OptionSchema, FilterConditionSchema, } from './lib/format/field.mjs';
|
|
2
|
+
export { ModifierSchema, LayoutNodeSchema, RootLayoutSchema, } from './lib/format/layout.mjs';
|
|
3
|
+
export { FORMAT_VERSION, PageSchema } from './lib/format/page.mjs';
|
|
4
|
+
export { validatePage } from './lib/format/validate.mjs';
|
|
5
|
+
export { pageJsonSchema } from './lib/format/json-schema.mjs';
|
|
6
|
+
export { compileModifier } from './lib/expression/modifier.mjs';
|
|
7
|
+
export { evaluateModifier, isModifierValid } from './lib/expression/evaluateModifier.mjs';
|
|
8
|
+
export { emptyValue, initialValues, isEmpty, expressionContext, } from './lib/record/values.mjs';
|
|
9
|
+
export { checkValue, formatBytes } from './lib/record/check.mjs';
|
|
10
|
+
export { createMemoryDataSource } from './lib/record/memory-data-source.mjs';
|
|
11
|
+
export { hostScheduler, wait } from './lib/record/scheduler.mjs';
|
|
12
|
+
export { createForm, } from './lib/record/form.mjs';
|
|
13
|
+
export { MESSAGES, fill } from './lib/record/messages.mjs';
|
|
14
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","sourceRoot":"","sources":["../../../../libs/core/src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,UAAU,EACV,WAAW,EACX,WAAW,EACX,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,qBAAqB,GAOtB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,gBAAgB,GAqBjB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,cAAc,EAAE,UAAU,EAA4B,MAAM,mBAAmB,CAAC;AACzF,OAAO,EAAE,YAAY,EAAuC,MAAM,uBAAuB,CAAC;AAC1F,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAyB,MAAM,2BAA2B,CAAC;AACnF,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AACtF,OAAO,EACL,UAAU,EACV,aAAa,EACb,OAAO,EACP,iBAAiB,GAQlB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAgB7D,OAAO,EAAE,sBAAsB,EAAuD,MAAM,iCAAiC,CAAC;AAC9H,OAAO,EAAE,aAAa,EAAE,IAAI,EAAkB,MAAM,wBAAwB,CAAC;AAC7E,OAAO,EACL,UAAU,GAQX,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,QAAQ,EAAE,IAAI,EAA8B,MAAM,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* evaluateModifier - Evaluate modifier expressions with form context
|
|
3
|
+
*
|
|
4
|
+
* Phase 2 implementation with full expression parser.
|
|
5
|
+
* Supports Python-like expressions used in Flectra modifiers.
|
|
6
|
+
*
|
|
7
|
+
* Structura Reference:
|
|
8
|
+
* - DynBehaviorManager.evaluateCondition() method
|
|
9
|
+
* - Supports Python-like expressions: "state == 'draft' and amount > 100"
|
|
10
|
+
*
|
|
11
|
+
* Supported features:
|
|
12
|
+
* - Comparison operators: ==, !=, <>, <, >, <=, >=
|
|
13
|
+
* - In operators: in, not in
|
|
14
|
+
* - Logical operators: and, or, not
|
|
15
|
+
* - Parentheses for precedence
|
|
16
|
+
* - Nested field access: partner_id.country_id.name
|
|
17
|
+
* - Truthiness checks: partner_id (true if partner_id has value)
|
|
18
|
+
*
|
|
19
|
+
* @param expression - The modifier expression to evaluate
|
|
20
|
+
* @param context - Current form values
|
|
21
|
+
* @returns Boolean result of evaluation
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```typescript
|
|
25
|
+
* // Simple boolean
|
|
26
|
+
* evaluateModifier(true, {}) // => true
|
|
27
|
+
*
|
|
28
|
+
* // String boolean
|
|
29
|
+
* evaluateModifier('1', {}) // => true
|
|
30
|
+
* evaluateModifier('True', {}) // => true
|
|
31
|
+
*
|
|
32
|
+
* // Field truthiness
|
|
33
|
+
* evaluateModifier('is_company', { is_company: true }) // => true
|
|
34
|
+
* evaluateModifier('partner_id', { partner_id: null }) // => false
|
|
35
|
+
*
|
|
36
|
+
* // Comparison expressions
|
|
37
|
+
* evaluateModifier("state == 'done'", { state: 'done' }) // => true
|
|
38
|
+
* evaluateModifier("amount > 100", { amount: 150 }) // => true
|
|
39
|
+
*
|
|
40
|
+
* // Logical expressions
|
|
41
|
+
* evaluateModifier("state == 'draft' and amount > 100", { state: 'draft', amount: 150 }) // => true
|
|
42
|
+
* evaluateModifier("state in ['draft', 'sent']", { state: 'draft' }) // => true
|
|
43
|
+
*
|
|
44
|
+
* // Nested field access
|
|
45
|
+
* evaluateModifier("partner_id.country_id == 5", { partner_id: { country_id: 5 } }) // => true
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
export declare function evaluateModifier(expression: string | boolean | undefined, context: Record<string, unknown>): boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Check if a modifier expression is valid and can be parsed
|
|
51
|
+
*
|
|
52
|
+
* @param expression - The modifier expression to check
|
|
53
|
+
* @returns true if expression is valid, false otherwise
|
|
54
|
+
*/
|
|
55
|
+
export declare function isModifierValid(expression: string | boolean | undefined): boolean;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* evaluateModifier - Evaluate modifier expressions with form context
|
|
3
|
+
*
|
|
4
|
+
* Phase 2 implementation with full expression parser.
|
|
5
|
+
* Supports Python-like expressions used in Flectra modifiers.
|
|
6
|
+
*
|
|
7
|
+
* Structura Reference:
|
|
8
|
+
* - DynBehaviorManager.evaluateCondition() method
|
|
9
|
+
* - Supports Python-like expressions: "state == 'draft' and amount > 100"
|
|
10
|
+
*
|
|
11
|
+
* Supported features:
|
|
12
|
+
* - Comparison operators: ==, !=, <>, <, >, <=, >=
|
|
13
|
+
* - In operators: in, not in
|
|
14
|
+
* - Logical operators: and, or, not
|
|
15
|
+
* - Parentheses for precedence
|
|
16
|
+
* - Nested field access: partner_id.country_id.name
|
|
17
|
+
* - Truthiness checks: partner_id (true if partner_id has value)
|
|
18
|
+
*
|
|
19
|
+
* @param expression - The modifier expression to evaluate
|
|
20
|
+
* @param context - Current form values
|
|
21
|
+
* @returns Boolean result of evaluation
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```typescript
|
|
25
|
+
* // Simple boolean
|
|
26
|
+
* evaluateModifier(true, {}) // => true
|
|
27
|
+
*
|
|
28
|
+
* // String boolean
|
|
29
|
+
* evaluateModifier('1', {}) // => true
|
|
30
|
+
* evaluateModifier('True', {}) // => true
|
|
31
|
+
*
|
|
32
|
+
* // Field truthiness
|
|
33
|
+
* evaluateModifier('is_company', { is_company: true }) // => true
|
|
34
|
+
* evaluateModifier('partner_id', { partner_id: null }) // => false
|
|
35
|
+
*
|
|
36
|
+
* // Comparison expressions
|
|
37
|
+
* evaluateModifier("state == 'done'", { state: 'done' }) // => true
|
|
38
|
+
* evaluateModifier("amount > 100", { amount: 150 }) // => true
|
|
39
|
+
*
|
|
40
|
+
* // Logical expressions
|
|
41
|
+
* evaluateModifier("state == 'draft' and amount > 100", { state: 'draft', amount: 150 }) // => true
|
|
42
|
+
* evaluateModifier("state in ['draft', 'sent']", { state: 'draft' }) // => true
|
|
43
|
+
*
|
|
44
|
+
* // Nested field access
|
|
45
|
+
* evaluateModifier("partner_id.country_id == 5", { partner_id: { country_id: 5 } }) // => true
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
export declare function evaluateModifier(expression: string | boolean | undefined, context: Record<string, unknown>): boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Check if a modifier expression is valid and can be parsed
|
|
51
|
+
*
|
|
52
|
+
* @param expression - The modifier expression to check
|
|
53
|
+
* @returns true if expression is valid, false otherwise
|
|
54
|
+
*/
|
|
55
|
+
export declare function isModifierValid(expression: string | boolean | undefined): boolean;
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* evaluateModifier - Evaluate modifier expressions with form context
|
|
4
|
+
*
|
|
5
|
+
* Phase 2 implementation with full expression parser.
|
|
6
|
+
* Supports Python-like expressions used in Flectra modifiers.
|
|
7
|
+
*
|
|
8
|
+
* Structura Reference:
|
|
9
|
+
* - DynBehaviorManager.evaluateCondition() method
|
|
10
|
+
* - Supports Python-like expressions: "state == 'draft' and amount > 100"
|
|
11
|
+
*
|
|
12
|
+
* Supported features:
|
|
13
|
+
* - Comparison operators: ==, !=, <>, <, >, <=, >=
|
|
14
|
+
* - In operators: in, not in
|
|
15
|
+
* - Logical operators: and, or, not
|
|
16
|
+
* - Parentheses for precedence
|
|
17
|
+
* - Nested field access: partner_id.country_id.name
|
|
18
|
+
* - Truthiness checks: partner_id (true if partner_id has value)
|
|
19
|
+
*
|
|
20
|
+
* @param expression - The modifier expression to evaluate
|
|
21
|
+
* @param context - Current form values
|
|
22
|
+
* @returns Boolean result of evaluation
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```typescript
|
|
26
|
+
* // Simple boolean
|
|
27
|
+
* evaluateModifier(true, {}) // => true
|
|
28
|
+
*
|
|
29
|
+
* // String boolean
|
|
30
|
+
* evaluateModifier('1', {}) // => true
|
|
31
|
+
* evaluateModifier('True', {}) // => true
|
|
32
|
+
*
|
|
33
|
+
* // Field truthiness
|
|
34
|
+
* evaluateModifier('is_company', { is_company: true }) // => true
|
|
35
|
+
* evaluateModifier('partner_id', { partner_id: null }) // => false
|
|
36
|
+
*
|
|
37
|
+
* // Comparison expressions
|
|
38
|
+
* evaluateModifier("state == 'done'", { state: 'done' }) // => true
|
|
39
|
+
* evaluateModifier("amount > 100", { amount: 150 }) // => true
|
|
40
|
+
*
|
|
41
|
+
* // Logical expressions
|
|
42
|
+
* evaluateModifier("state == 'draft' and amount > 100", { state: 'draft', amount: 150 }) // => true
|
|
43
|
+
* evaluateModifier("state in ['draft', 'sent']", { state: 'draft' }) // => true
|
|
44
|
+
*
|
|
45
|
+
* // Nested field access
|
|
46
|
+
* evaluateModifier("partner_id.country_id == 5", { partner_id: { country_id: 5 } }) // => true
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
50
|
+
exports.evaluateModifier = evaluateModifier;
|
|
51
|
+
exports.isModifierValid = isModifierValid;
|
|
52
|
+
const tokenizer_1 = require("./tokenizer");
|
|
53
|
+
const parser_1 = require("./parser");
|
|
54
|
+
const evaluator_1 = require("./evaluator");
|
|
55
|
+
function evaluateModifier(expression, context) {
|
|
56
|
+
// Undefined modifier = false (field is not affected)
|
|
57
|
+
if (expression === undefined) {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
// Direct boolean value
|
|
61
|
+
if (typeof expression === 'boolean') {
|
|
62
|
+
return expression;
|
|
63
|
+
}
|
|
64
|
+
// String representation of boolean
|
|
65
|
+
if (expression === '1' || expression === 'True' || expression === 'true') {
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
if (expression === '0' || expression === 'False' || expression === 'false') {
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
// Empty string = false
|
|
72
|
+
if (expression === '') {
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
// Parse and evaluate complex expression
|
|
76
|
+
try {
|
|
77
|
+
const tokens = (0, tokenizer_1.tokenize)(expression);
|
|
78
|
+
// Empty token list
|
|
79
|
+
if (tokens.length === 0) {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
const parser = new parser_1.ExpressionParser(tokens);
|
|
83
|
+
const ast = parser.parse();
|
|
84
|
+
const result = (0, evaluator_1.evaluate)(ast, context);
|
|
85
|
+
// Convert result to boolean
|
|
86
|
+
return (0, evaluator_1.truthy)(result);
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
// A page is validated before it runs (validatePage reads every
|
|
90
|
+
// expression), so this only guards pages that skipped validation.
|
|
91
|
+
// Fail safely - return false so field is not hidden/disabled by broken modifier
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Check if a modifier expression is valid and can be parsed
|
|
97
|
+
*
|
|
98
|
+
* @param expression - The modifier expression to check
|
|
99
|
+
* @returns true if expression is valid, false otherwise
|
|
100
|
+
*/
|
|
101
|
+
function isModifierValid(expression) {
|
|
102
|
+
if (expression === undefined || typeof expression === 'boolean') {
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
105
|
+
if (expression === '') {
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
try {
|
|
109
|
+
const tokens = (0, tokenizer_1.tokenize)(expression);
|
|
110
|
+
if (tokens.length === 0) {
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
113
|
+
const parser = new parser_1.ExpressionParser(tokens);
|
|
114
|
+
parser.parse();
|
|
115
|
+
return true;
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=evaluateModifier.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evaluateModifier.js","sourceRoot":"","sources":["../../../../../../libs/core/src/lib/expression/evaluateModifier.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;;AAMH,4CAiDC;AAQD,0CAoBC;AAjFD,2CAAuC;AACvC,qCAA4C;AAC5C,2CAA+C;AAE/C,SAAgB,gBAAgB,CAC9B,UAAwC,EACxC,OAAgC;IAEhC,qDAAqD;IACrD,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;QAC7B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,uBAAuB;IACvB,IAAI,OAAO,UAAU,KAAK,SAAS,EAAE,CAAC;QACpC,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,mCAAmC;IACnC,IAAI,UAAU,KAAK,GAAG,IAAI,UAAU,KAAK,MAAM,IAAI,UAAU,KAAK,MAAM,EAAE,CAAC;QACzE,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,UAAU,KAAK,GAAG,IAAI,UAAU,KAAK,OAAO,IAAI,UAAU,KAAK,OAAO,EAAE,CAAC;QAC3E,OAAO,KAAK,CAAC;IACf,CAAC;IAED,uBAAuB;IACvB,IAAI,UAAU,KAAK,EAAE,EAAE,CAAC;QACtB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,wCAAwC;IACxC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAA,oBAAQ,EAAC,UAAU,CAAC,CAAC;QAEpC,mBAAmB;QACnB,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,yBAAgB,CAAC,MAAM,CAAC,CAAC;QAC5C,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,EAAE,CAAC;QAC3B,MAAM,MAAM,GAAG,IAAA,oBAAQ,EAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QAEtC,4BAA4B;QAC5B,OAAO,IAAA,kBAAM,EAAC,MAAM,CAAC,CAAC;IACxB,CAAC;IAAC,MAAM,CAAC;QACP,+DAA+D;QAC/D,kEAAkE;QAClE,gFAAgF;QAChF,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,SAAgB,eAAe,CAAC,UAAwC;IACtE,IAAI,UAAU,KAAK,SAAS,IAAI,OAAO,UAAU,KAAK,SAAS,EAAE,CAAC;QAChE,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,UAAU,KAAK,EAAE,EAAE,CAAC;QACtB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAA,oBAAQ,EAAC,UAAU,CAAC,CAAC;QACpC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,yBAAgB,CAAC,MAAM,CAAC,CAAC;QAC5C,MAAM,CAAC,KAAK,EAAE,CAAC;QACf,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* evaluateModifier - Evaluate modifier expressions with form context
|
|
3
|
+
*
|
|
4
|
+
* Phase 2 implementation with full expression parser.
|
|
5
|
+
* Supports Python-like expressions used in Flectra modifiers.
|
|
6
|
+
*
|
|
7
|
+
* Structura Reference:
|
|
8
|
+
* - DynBehaviorManager.evaluateCondition() method
|
|
9
|
+
* - Supports Python-like expressions: "state == 'draft' and amount > 100"
|
|
10
|
+
*
|
|
11
|
+
* Supported features:
|
|
12
|
+
* - Comparison operators: ==, !=, <>, <, >, <=, >=
|
|
13
|
+
* - In operators: in, not in
|
|
14
|
+
* - Logical operators: and, or, not
|
|
15
|
+
* - Parentheses for precedence
|
|
16
|
+
* - Nested field access: partner_id.country_id.name
|
|
17
|
+
* - Truthiness checks: partner_id (true if partner_id has value)
|
|
18
|
+
*
|
|
19
|
+
* @param expression - The modifier expression to evaluate
|
|
20
|
+
* @param context - Current form values
|
|
21
|
+
* @returns Boolean result of evaluation
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```typescript
|
|
25
|
+
* // Simple boolean
|
|
26
|
+
* evaluateModifier(true, {}) // => true
|
|
27
|
+
*
|
|
28
|
+
* // String boolean
|
|
29
|
+
* evaluateModifier('1', {}) // => true
|
|
30
|
+
* evaluateModifier('True', {}) // => true
|
|
31
|
+
*
|
|
32
|
+
* // Field truthiness
|
|
33
|
+
* evaluateModifier('is_company', { is_company: true }) // => true
|
|
34
|
+
* evaluateModifier('partner_id', { partner_id: null }) // => false
|
|
35
|
+
*
|
|
36
|
+
* // Comparison expressions
|
|
37
|
+
* evaluateModifier("state == 'done'", { state: 'done' }) // => true
|
|
38
|
+
* evaluateModifier("amount > 100", { amount: 150 }) // => true
|
|
39
|
+
*
|
|
40
|
+
* // Logical expressions
|
|
41
|
+
* evaluateModifier("state == 'draft' and amount > 100", { state: 'draft', amount: 150 }) // => true
|
|
42
|
+
* evaluateModifier("state in ['draft', 'sent']", { state: 'draft' }) // => true
|
|
43
|
+
*
|
|
44
|
+
* // Nested field access
|
|
45
|
+
* evaluateModifier("partner_id.country_id == 5", { partner_id: { country_id: 5 } }) // => true
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
import { tokenize } from './tokenizer.mjs';
|
|
49
|
+
import { ExpressionParser } from './parser.mjs';
|
|
50
|
+
import { evaluate, truthy } from './evaluator.mjs';
|
|
51
|
+
export function evaluateModifier(expression, context) {
|
|
52
|
+
// Undefined modifier = false (field is not affected)
|
|
53
|
+
if (expression === undefined) {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
// Direct boolean value
|
|
57
|
+
if (typeof expression === 'boolean') {
|
|
58
|
+
return expression;
|
|
59
|
+
}
|
|
60
|
+
// String representation of boolean
|
|
61
|
+
if (expression === '1' || expression === 'True' || expression === 'true') {
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
if (expression === '0' || expression === 'False' || expression === 'false') {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
// Empty string = false
|
|
68
|
+
if (expression === '') {
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
// Parse and evaluate complex expression
|
|
72
|
+
try {
|
|
73
|
+
const tokens = tokenize(expression);
|
|
74
|
+
// Empty token list
|
|
75
|
+
if (tokens.length === 0) {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
const parser = new ExpressionParser(tokens);
|
|
79
|
+
const ast = parser.parse();
|
|
80
|
+
const result = evaluate(ast, context);
|
|
81
|
+
// Convert result to boolean
|
|
82
|
+
return truthy(result);
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
// A page is validated before it runs (validatePage reads every
|
|
86
|
+
// expression), so this only guards pages that skipped validation.
|
|
87
|
+
// Fail safely - return false so field is not hidden/disabled by broken modifier
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Check if a modifier expression is valid and can be parsed
|
|
93
|
+
*
|
|
94
|
+
* @param expression - The modifier expression to check
|
|
95
|
+
* @returns true if expression is valid, false otherwise
|
|
96
|
+
*/
|
|
97
|
+
export function isModifierValid(expression) {
|
|
98
|
+
if (expression === undefined || typeof expression === 'boolean') {
|
|
99
|
+
return true;
|
|
100
|
+
}
|
|
101
|
+
if (expression === '') {
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
104
|
+
try {
|
|
105
|
+
const tokens = tokenize(expression);
|
|
106
|
+
if (tokens.length === 0) {
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
109
|
+
const parser = new ExpressionParser(tokens);
|
|
110
|
+
parser.parse();
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=evaluateModifier.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evaluateModifier.mjs","sourceRoot":"","sources":["../../../../../../libs/core/src/lib/expression/evaluateModifier.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE/C,MAAM,UAAU,gBAAgB,CAC9B,UAAwC,EACxC,OAAgC;IAEhC,qDAAqD;IACrD,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;QAC7B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,uBAAuB;IACvB,IAAI,OAAO,UAAU,KAAK,SAAS,EAAE,CAAC;QACpC,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,mCAAmC;IACnC,IAAI,UAAU,KAAK,GAAG,IAAI,UAAU,KAAK,MAAM,IAAI,UAAU,KAAK,MAAM,EAAE,CAAC;QACzE,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,UAAU,KAAK,GAAG,IAAI,UAAU,KAAK,OAAO,IAAI,UAAU,KAAK,OAAO,EAAE,CAAC;QAC3E,OAAO,KAAK,CAAC;IACf,CAAC;IAED,uBAAuB;IACvB,IAAI,UAAU,KAAK,EAAE,EAAE,CAAC;QACtB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,wCAAwC;IACxC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAC;QAEpC,mBAAmB;QACnB,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,gBAAgB,CAAC,MAAM,CAAC,CAAC;QAC5C,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,EAAE,CAAC;QAC3B,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QAEtC,4BAA4B;QAC5B,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC;IACxB,CAAC;IAAC,MAAM,CAAC;QACP,+DAA+D;QAC/D,kEAAkE;QAClE,gFAAgF;QAChF,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,UAAwC;IACtE,IAAI,UAAU,KAAK,SAAS,IAAI,OAAO,UAAU,KAAK,SAAS,EAAE,CAAC;QAChE,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,UAAU,KAAK,EAAE,EAAE,CAAC;QACtB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAC;QACpC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,gBAAgB,CAAC,MAAM,CAAC,CAAC;QAC5C,MAAM,CAAC,KAAK,EAAE,CAAC;QACf,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AST evaluator for modifiers, ported from the React form engine.
|
|
3
|
+
*
|
|
4
|
+
* Python semantics where the React version used JavaScript's: an empty list
|
|
5
|
+
* or string is false, and an empty value is never smaller or larger than
|
|
6
|
+
* anything — modifiers come from backends that think in Python.
|
|
7
|
+
*/
|
|
8
|
+
import type { ASTNode } from './parser.mjs';
|
|
9
|
+
/**
|
|
10
|
+
* Evaluate an AST node against a context object
|
|
11
|
+
*
|
|
12
|
+
* @param ast - The AST node to evaluate
|
|
13
|
+
* @param context - Object containing field values
|
|
14
|
+
* @returns The result of evaluation
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* const ast = { type: 'BinaryOp', operator: '==', left: {...}, right: {...} };
|
|
18
|
+
* const context = { state: 'draft', amount: 100 };
|
|
19
|
+
* evaluate(ast, context); // Returns boolean result
|
|
20
|
+
*/
|
|
21
|
+
export declare function evaluate(ast: ASTNode, context: Record<string, unknown>): unknown;
|
|
22
|
+
/** Python's truth test: empty lists, strings and objects, 0 and None are false. */
|
|
23
|
+
export declare function truthy(value: unknown): boolean;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AST evaluator for modifiers, ported from the React form engine.
|
|
3
|
+
*
|
|
4
|
+
* Python semantics where the React version used JavaScript's: an empty list
|
|
5
|
+
* or string is false, and an empty value is never smaller or larger than
|
|
6
|
+
* anything — modifiers come from backends that think in Python.
|
|
7
|
+
*/
|
|
8
|
+
import type { ASTNode } from './parser';
|
|
9
|
+
/**
|
|
10
|
+
* Evaluate an AST node against a context object
|
|
11
|
+
*
|
|
12
|
+
* @param ast - The AST node to evaluate
|
|
13
|
+
* @param context - Object containing field values
|
|
14
|
+
* @returns The result of evaluation
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* const ast = { type: 'BinaryOp', operator: '==', left: {...}, right: {...} };
|
|
18
|
+
* const context = { state: 'draft', amount: 100 };
|
|
19
|
+
* evaluate(ast, context); // Returns boolean result
|
|
20
|
+
*/
|
|
21
|
+
export declare function evaluate(ast: ASTNode, context: Record<string, unknown>): unknown;
|
|
22
|
+
/** Python's truth test: empty lists, strings and objects, 0 and None are false. */
|
|
23
|
+
export declare function truthy(value: unknown): boolean;
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* AST evaluator for modifiers, ported from the React form engine.
|
|
4
|
+
*
|
|
5
|
+
* Python semantics where the React version used JavaScript's: an empty list
|
|
6
|
+
* or string is false, and an empty value is never smaller or larger than
|
|
7
|
+
* anything — modifiers come from backends that think in Python.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.evaluate = evaluate;
|
|
11
|
+
exports.truthy = truthy;
|
|
12
|
+
/**
|
|
13
|
+
* Evaluate an AST node against a context object
|
|
14
|
+
*
|
|
15
|
+
* @param ast - The AST node to evaluate
|
|
16
|
+
* @param context - Object containing field values
|
|
17
|
+
* @returns The result of evaluation
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* const ast = { type: 'BinaryOp', operator: '==', left: {...}, right: {...} };
|
|
21
|
+
* const context = { state: 'draft', amount: 100 };
|
|
22
|
+
* evaluate(ast, context); // Returns boolean result
|
|
23
|
+
*/
|
|
24
|
+
function evaluate(ast, context) {
|
|
25
|
+
switch (ast.type) {
|
|
26
|
+
case 'BinaryOp':
|
|
27
|
+
return evaluateBinaryOp(ast, context);
|
|
28
|
+
case 'UnaryOp':
|
|
29
|
+
return evaluateUnaryOp(ast, context);
|
|
30
|
+
case 'Literal':
|
|
31
|
+
return ast.value;
|
|
32
|
+
case 'Identifier':
|
|
33
|
+
return getNestedValue(context, ast.name);
|
|
34
|
+
default:
|
|
35
|
+
throw new Error(`Unknown AST node type: ${ast.type}`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Evaluate binary operations
|
|
40
|
+
*/
|
|
41
|
+
function evaluateBinaryOp(node, context) {
|
|
42
|
+
const left = normalize(evaluate(node.left, context));
|
|
43
|
+
const right = normalize(evaluate(node.right, context));
|
|
44
|
+
const operator = node.operator.toLowerCase();
|
|
45
|
+
const ordered = left !== null && right !== null;
|
|
46
|
+
switch (operator) {
|
|
47
|
+
// Comparison operators
|
|
48
|
+
case '==':
|
|
49
|
+
return left === right;
|
|
50
|
+
case '!=':
|
|
51
|
+
case '<>':
|
|
52
|
+
return left !== right;
|
|
53
|
+
case '<':
|
|
54
|
+
return ordered && left < right;
|
|
55
|
+
case '>':
|
|
56
|
+
return ordered && left > right;
|
|
57
|
+
case '<=':
|
|
58
|
+
return ordered && left <= right;
|
|
59
|
+
case '>=':
|
|
60
|
+
return ordered && left >= right;
|
|
61
|
+
// In operators
|
|
62
|
+
case 'in':
|
|
63
|
+
return Array.isArray(right) && right.includes(left);
|
|
64
|
+
case 'not in':
|
|
65
|
+
return Array.isArray(right) && !right.includes(left);
|
|
66
|
+
// Logical operators (use truthiness)
|
|
67
|
+
case 'and':
|
|
68
|
+
return truthy(left) && truthy(right);
|
|
69
|
+
case 'or':
|
|
70
|
+
return truthy(left) || truthy(right);
|
|
71
|
+
default:
|
|
72
|
+
throw new Error(`Unknown binary operator: ${node.operator}`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Evaluate unary operations
|
|
77
|
+
*/
|
|
78
|
+
function evaluateUnaryOp(node, context) {
|
|
79
|
+
const operand = evaluate(node.operand, context);
|
|
80
|
+
const operator = node.operator.toLowerCase();
|
|
81
|
+
switch (operator) {
|
|
82
|
+
case 'not':
|
|
83
|
+
return !truthy(operand);
|
|
84
|
+
default:
|
|
85
|
+
throw new Error(`Unknown unary operator: ${node.operator}`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
/** A missing value compares like None. */
|
|
89
|
+
function normalize(value) {
|
|
90
|
+
return value === undefined ? null : value;
|
|
91
|
+
}
|
|
92
|
+
/** Python's truth test: empty lists, strings and objects, 0 and None are false. */
|
|
93
|
+
function truthy(value) {
|
|
94
|
+
if (Array.isArray(value))
|
|
95
|
+
return value.length > 0;
|
|
96
|
+
if (value !== null && typeof value === 'object')
|
|
97
|
+
return Object.keys(value).length > 0;
|
|
98
|
+
return Boolean(value);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Get a nested value from an object using dot notation
|
|
102
|
+
*
|
|
103
|
+
* @param obj - The object to traverse
|
|
104
|
+
* @param path - Dot-separated path (e.g., 'partner_id.country_id.name')
|
|
105
|
+
* @returns The value at the path, or undefined if not found
|
|
106
|
+
*
|
|
107
|
+
* @example
|
|
108
|
+
* getNestedValue({ a: { b: { c: 5 } } }, 'a.b.c') // Returns 5
|
|
109
|
+
* getNestedValue({ a: null }, 'a.b.c') // Returns undefined
|
|
110
|
+
*/
|
|
111
|
+
function getNestedValue(obj, path) {
|
|
112
|
+
const parts = path.split('.');
|
|
113
|
+
let current = obj;
|
|
114
|
+
for (const part of parts) {
|
|
115
|
+
if (current === null || current === undefined) {
|
|
116
|
+
return undefined;
|
|
117
|
+
}
|
|
118
|
+
current = current[part];
|
|
119
|
+
}
|
|
120
|
+
return current;
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=evaluator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evaluator.js","sourceRoot":"","sources":["../../../../../../libs/core/src/lib/expression/evaluator.ts"],"names":[],"mappings":"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"}
|