@rytass/bpm-core-shared 0.20.0 → 0.21.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/CHANGELOG.md +43 -0
- package/package.json +1 -1
- package/src/index.d.ts +1 -0
- package/src/index.js +1 -0
- package/src/index.js.map +1 -1
- package/src/lib/form-filter.d.ts +166 -0
- package/src/lib/form-filter.js +388 -0
- package/src/lib/form-filter.js.map +1 -0
- package/src/lib/form.d.ts +26 -0
- package/src/lib/form.js +28 -1
- package/src/lib/form.js.map +1 -1
- package/src/lib/workflow-graph.d.ts +22 -0
- package/src/lib/workflow-graph.js +109 -20
- package/src/lib/workflow-graph.js.map +1 -1
- package/src/lib/workflow-toolset.js +3 -3
- package/src/lib/workflow-toolset.js.map +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,46 @@
|
|
|
1
|
+
## 0.21.0 (2026-11-11)
|
|
2
|
+
|
|
3
|
+
### 🚀 Features
|
|
4
|
+
|
|
5
|
+
- **bpm-core-react:** place refused fill values on their fields by path ([0f26687](https://github.com/Rytass/BPMCore/commit/0f26687))
|
|
6
|
+
- **bpm-core-client:** expose refused form values on request errors ([3a5d406](https://github.com/Rytass/BPMCore/commit/3a5d406))
|
|
7
|
+
- **shared:** add structured form data issue contract ([827e26d](https://github.com/Rytass/BPMCore/commit/827e26d))
|
|
8
|
+
- **client:** add a filterable expense example list built on field filters ([3d624fb](https://github.com/Rytass/BPMCore/commit/3d624fb))
|
|
9
|
+
- **react:** filterable toggle in the form builder and list field filters ([e8d58bf](https://github.com/Rytass/BPMCore/commit/e8d58bf))
|
|
10
|
+
- **client:** pass field filters and sort to the approval-instance list ([bbfd789](https://github.com/Rytass/BPMCore/commit/bbfd789))
|
|
11
|
+
- **workflow-engine:** filter and sort approval instances by form fields ([6e4a98f](https://github.com/Rytass/BPMCore/commit/6e4a98f))
|
|
12
|
+
- **template:** refuse to enable a filterable field over conflicting history ([42628b4](https://github.com/Rytass/BPMCore/commit/42628b4))
|
|
13
|
+
- **shared:** declare filterable form fields and the field filter contract ([166389e](https://github.com/Rytass/BPMCore/commit/166389e))
|
|
14
|
+
- **api:** add a staging notify webhook showcase pushed over SSE ([0cb3ea5](https://github.com/Rytass/BPMCore/commit/0cb3ea5))
|
|
15
|
+
|
|
16
|
+
### 🩹 Fixes
|
|
17
|
+
|
|
18
|
+
- **client:** read form data issues all or nothing ([c0e4281](https://github.com/Rytass/BPMCore/commit/c0e4281))
|
|
19
|
+
- **shared:** name the table, not a column, for a malformed filterable table ([c4b0420](https://github.com/Rytass/BPMCore/commit/c4b0420))
|
|
20
|
+
- **shared:** describe filterable value mismatches in Chinese ([afd27a7](https://github.com/Rytass/BPMCore/commit/afd27a7))
|
|
21
|
+
- **client:** name data-source values in case titles from the option snapshot ([14ade77](https://github.com/Rytass/BPMCore/commit/14ade77))
|
|
22
|
+
- **shared:** narrow the self-approval flag with typeof in the resolver fallback parser ([19497cf](https://github.com/Rytass/BPMCore/commit/19497cf))
|
|
23
|
+
|
|
24
|
+
### 🔥 Performance
|
|
25
|
+
|
|
26
|
+
- **template:** scan instances only for fields a publish newly makes filterable ([b18dda2](https://github.com/Rytass/BPMCore/commit/b18dda2))
|
|
27
|
+
|
|
28
|
+
### ❤️ Thank You
|
|
29
|
+
|
|
30
|
+
- Chia Yu Pai @fantasywind
|
|
31
|
+
|
|
32
|
+
## 0.20.1 (2026-11-10)
|
|
33
|
+
|
|
34
|
+
### 🩹 Fixes
|
|
35
|
+
|
|
36
|
+
- **workflow-graph:** read a multiple-selection "" as unfilled ([298753a](https://github.com/Rytass/BPMCore/commit/298753a))
|
|
37
|
+
- **workflow-graph:** guard designer conditions against absent form keys ([a3d2cb6](https://github.com/Rytass/BPMCore/commit/a3d2cb6))
|
|
38
|
+
|
|
39
|
+
### ❤️ Thank You
|
|
40
|
+
|
|
41
|
+
- Chia Yu Pai @fantasywind
|
|
42
|
+
- Kai-Chieh Yang
|
|
43
|
+
|
|
1
44
|
## 0.20.0 (2026-11-08)
|
|
2
45
|
|
|
3
46
|
### 🚀 Features
|
package/package.json
CHANGED
package/src/index.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ export * from './lib/field-access';
|
|
|
5
5
|
export * from './lib/field-access-lint';
|
|
6
6
|
export * from './lib/field-access-matrix';
|
|
7
7
|
export * from './lib/form';
|
|
8
|
+
export * from './lib/form-filter';
|
|
8
9
|
export * from './lib/identity';
|
|
9
10
|
export * from './lib/organization';
|
|
10
11
|
export * from './lib/status';
|
package/src/index.js
CHANGED
|
@@ -8,6 +8,7 @@ tslib_1.__exportStar(require("./lib/field-access"), exports);
|
|
|
8
8
|
tslib_1.__exportStar(require("./lib/field-access-lint"), exports);
|
|
9
9
|
tslib_1.__exportStar(require("./lib/field-access-matrix"), exports);
|
|
10
10
|
tslib_1.__exportStar(require("./lib/form"), exports);
|
|
11
|
+
tslib_1.__exportStar(require("./lib/form-filter"), exports);
|
|
11
12
|
tslib_1.__exportStar(require("./lib/identity"), exports);
|
|
12
13
|
tslib_1.__exportStar(require("./lib/organization"), exports);
|
|
13
14
|
tslib_1.__exportStar(require("./lib/status"), exports);
|
package/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../libs/shared/src/index.ts"],"names":[],"mappings":";;;AAAA,0DAAgC;AAChC,oEAA0C;AAC1C,uEAA6C;AAC7C,6DAAmC;AACnC,kEAAwC;AACxC,oEAA0C;AAC1C,qDAA2B;AAC3B,yDAA+B;AAC/B,6DAAmC;AACnC,uDAA6B;AAC7B,yDAA+B;AAC/B,+DAAqC;AACrC,iEAAuC;AACvC,iEAAuC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../libs/shared/src/index.ts"],"names":[],"mappings":";;;AAAA,0DAAgC;AAChC,oEAA0C;AAC1C,uEAA6C;AAC7C,6DAAmC;AACnC,kEAAwC;AACxC,oEAA0C;AAC1C,qDAA2B;AAC3B,4DAAkC;AAClC,yDAA+B;AAC/B,6DAAmC;AACnC,uDAA6B;AAC7B,yDAA+B;AAC/B,+DAAqC;AACrC,iEAAuC;AACvC,iEAAuC"}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { type FormDefinitionSchema, type FormFieldDefinition, type FormFieldOption, type TableColumnDefinition } from './form';
|
|
2
|
+
/**
|
|
3
|
+
* Filtering and sorting the approval-instance list by form fields (ADR 25).
|
|
4
|
+
*
|
|
5
|
+
* Everything that decides "is this value right for a filterable field" lives
|
|
6
|
+
* here so the write-time check, the enable-time scan of old instances, the
|
|
7
|
+
* query compiler and the designer all answer the same way.
|
|
8
|
+
*/
|
|
9
|
+
/** Top-level field types a form designer may mark `filterable` (ADR 25 §5.2). */
|
|
10
|
+
export declare const FILTERABLE_FIELD_TYPES: readonly ["autocomplete", "boolean", "checkbox", "date", "datetime", "member", "money", "number", "org_unit", "radio", "select", "text", "textarea"];
|
|
11
|
+
export type FilterableFieldType = (typeof FILTERABLE_FIELD_TYPES)[number];
|
|
12
|
+
/** Table column types a form designer may mark `filterable`: every column type. */
|
|
13
|
+
export declare const FILTERABLE_TABLE_COLUMN_TYPES: readonly TableColumnDefinition['type'][];
|
|
14
|
+
/**
|
|
15
|
+
* Sort keys that are not form fields. A filterable field must not use one of
|
|
16
|
+
* these as its `fieldKey`, or a sort request would be ambiguous.
|
|
17
|
+
*/
|
|
18
|
+
export declare const APPROVAL_INSTANCE_SORT_TIME_FIELDS: readonly ["submittedAt", "updatedAt", "completedAt"];
|
|
19
|
+
export type ApprovalInstanceSortTimeField = (typeof APPROVAL_INSTANCE_SORT_TIME_FIELDS)[number];
|
|
20
|
+
export declare function isApprovalInstanceSortTimeField(value: string): value is ApprovalInstanceSortTimeField;
|
|
21
|
+
export declare function isFilterableFieldType(type: FormFieldDefinition['type'], placement?: 'column' | 'top-level'): boolean;
|
|
22
|
+
export type ApprovalInstanceFieldFilterOperator = 'CONTAINS' | 'EQUALS' | 'IN' | 'NOT_EQUALS' | 'RANGE';
|
|
23
|
+
export declare const APPROVAL_INSTANCE_FIELD_FILTER_OPERATORS: readonly ApprovalInstanceFieldFilterOperator[];
|
|
24
|
+
export interface ApprovalInstanceFieldFilter {
|
|
25
|
+
/** A top-level fieldKey, or `<tableKey>.<columnKey>` for a table column. */
|
|
26
|
+
readonly fieldKey: string;
|
|
27
|
+
readonly operator: ApprovalInstanceFieldFilterOperator;
|
|
28
|
+
/** EQUALS, NOT_EQUALS and CONTAINS read the first value; IN reads them all. */
|
|
29
|
+
readonly values?: readonly string[];
|
|
30
|
+
/** RANGE lower bound, inclusive. Decimal string, `YYYY-MM-DD` or ISO 8601. */
|
|
31
|
+
readonly from?: string;
|
|
32
|
+
/** RANGE upper bound, inclusive. */
|
|
33
|
+
readonly to?: string;
|
|
34
|
+
}
|
|
35
|
+
export type ApprovalInstanceSortDirection = 'ASC' | 'DESC';
|
|
36
|
+
export interface ApprovalInstanceSort {
|
|
37
|
+
/** A top-level filterable fieldKey, or one of {@link APPROVAL_INSTANCE_SORT_TIME_FIELDS}. */
|
|
38
|
+
readonly field: string;
|
|
39
|
+
readonly direction?: ApprovalInstanceSortDirection;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* How a filterable value is stored and compared. Several field types share a
|
|
43
|
+
* kind: `money` compares like `number`, and every option-like field compares
|
|
44
|
+
* by its stored value.
|
|
45
|
+
*/
|
|
46
|
+
export type FilterableValueKind = 'boolean' | 'date' | 'datetime' | 'member' | 'number' | 'option' | 'org_unit' | 'text';
|
|
47
|
+
export declare function readFilterableValueKind(type: FormFieldDefinition['type']): FilterableValueKind | null;
|
|
48
|
+
/** Operators a field type accepts (ADR 25 §7.2). */
|
|
49
|
+
export declare function readFilterOperatorsForFieldType(type: FormFieldDefinition['type']): readonly ApprovalInstanceFieldFilterOperator[];
|
|
50
|
+
/** A filterable top-level field can be sorted on; a table column cannot (ADR 25 §7.5). */
|
|
51
|
+
export declare function isFilterableFieldSortable(path: FilterableFieldPath): boolean;
|
|
52
|
+
/** One filterable field, top-level or table column, as the list query sees it. */
|
|
53
|
+
export interface FilterableFieldPath {
|
|
54
|
+
/** `fieldKey`, or `<tableKey>.<columnKey>`. */
|
|
55
|
+
readonly path: string;
|
|
56
|
+
readonly tableKey: string | null;
|
|
57
|
+
/** The key inside a row for a column; the fieldKey for a top-level field. */
|
|
58
|
+
readonly key: string;
|
|
59
|
+
readonly field: FormFieldDefinition | TableColumnDefinition;
|
|
60
|
+
readonly kind: FilterableValueKind;
|
|
61
|
+
readonly label: string;
|
|
62
|
+
/** Static options and their labels; `null` for a data-source or non-option field. */
|
|
63
|
+
readonly staticOptions: readonly FormFieldOption[] | null;
|
|
64
|
+
/** Labels live in the instance's option snapshot (a top-level data-source field). */
|
|
65
|
+
readonly usesOptionSnapshot: boolean;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* The fields of `schema` a list query may filter on: every field (or table
|
|
69
|
+
* column) marked `filterable` whose type allows it. A field marked filterable
|
|
70
|
+
* with a type that does not allow it is skipped here; the schema lint reports
|
|
71
|
+
* it.
|
|
72
|
+
*/
|
|
73
|
+
export declare function readFilterableFieldPaths(schema: FormDefinitionSchema | null | undefined): readonly FilterableFieldPath[];
|
|
74
|
+
export declare function findFilterableFieldPath(schema: FormDefinitionSchema | null | undefined, path: string): FilterableFieldPath | null;
|
|
75
|
+
/**
|
|
76
|
+
* Every field and column of a schema by path, filterable or not. The enable
|
|
77
|
+
* check compares a new filterable field against what older versions stored
|
|
78
|
+
* at the same path, whether or not they were filterable then.
|
|
79
|
+
*/
|
|
80
|
+
export declare function readFormFieldTypesByPath(schema: FormDefinitionSchema | null | undefined): ReadonlyMap<string, FormFieldDefinition['type']>;
|
|
81
|
+
export type FilterableValueCheck = {
|
|
82
|
+
readonly status: 'empty';
|
|
83
|
+
} | {
|
|
84
|
+
readonly status: 'valid';
|
|
85
|
+
} | {
|
|
86
|
+
readonly status: 'invalid';
|
|
87
|
+
readonly expected: string;
|
|
88
|
+
};
|
|
89
|
+
/**
|
|
90
|
+
* Whether one stored value fits a filterable field (ADR 25 §5.4, §6).
|
|
91
|
+
*
|
|
92
|
+
* - Missing and `null` are "no value". So is `""` for a number, money, date,
|
|
93
|
+
* datetime or boolean field (a cleared input), and `[]` for a multi-value
|
|
94
|
+
* field.
|
|
95
|
+
* - An option or member field accepts a string or an array of strings either
|
|
96
|
+
* way: its `mode` / `multiple` may change between versions without changing
|
|
97
|
+
* its type, and the query matches both shapes.
|
|
98
|
+
*/
|
|
99
|
+
export declare function checkFilterableFieldValue(field: FormFieldDefinition | TableColumnDefinition, value: unknown): FilterableValueCheck;
|
|
100
|
+
export declare function isCanonicalDate(value: unknown): value is string;
|
|
101
|
+
export declare function isCanonicalDateTime(value: unknown): value is string;
|
|
102
|
+
/**
|
|
103
|
+
* A value inside a filterable path that does not fit its field. `path` is the
|
|
104
|
+
* top-level fieldKey, `<tableKey>.<columnKey>` for a bad cell, or the bare
|
|
105
|
+
* `tableKey` when the table itself (or one of its rows) is malformed.
|
|
106
|
+
*/
|
|
107
|
+
export interface FilterableValueProblem {
|
|
108
|
+
readonly path: string;
|
|
109
|
+
/** Index of the table row, or `null` for a top-level field. */
|
|
110
|
+
readonly rowIndex: number | null;
|
|
111
|
+
readonly value: unknown;
|
|
112
|
+
readonly expected: string;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Every value in `formData` that does not fit one of `paths`. Used both when
|
|
116
|
+
* writing (refuse the write) and when enabling a field (refuse to enable while
|
|
117
|
+
* old instances hold such values). A table that is not an array, or a row that
|
|
118
|
+
* is not an object, is a problem of every filterable column in it.
|
|
119
|
+
*/
|
|
120
|
+
export declare function readFilterableValueProblems(paths: readonly FilterableFieldPath[], formData: Readonly<Record<string, unknown>> | null | undefined): readonly FilterableValueProblem[];
|
|
121
|
+
/** A field that would become filterable but whose history forbids it. */
|
|
122
|
+
export type FilterableFieldIssue = {
|
|
123
|
+
readonly kind: 'TYPE_CHANGED';
|
|
124
|
+
readonly path: string;
|
|
125
|
+
readonly label: string;
|
|
126
|
+
readonly type: FormFieldDefinition['type'];
|
|
127
|
+
/** Older versions, still holding instances, that stored another type here. */
|
|
128
|
+
readonly conflicts: readonly {
|
|
129
|
+
readonly versionNumber: number;
|
|
130
|
+
readonly type: FormFieldDefinition['type'];
|
|
131
|
+
}[];
|
|
132
|
+
} | {
|
|
133
|
+
readonly kind: 'INVALID_VALUES';
|
|
134
|
+
readonly path: string;
|
|
135
|
+
readonly label: string;
|
|
136
|
+
readonly type: FormFieldDefinition['type'];
|
|
137
|
+
readonly invalidInstanceCount: number;
|
|
138
|
+
/**
|
|
139
|
+
* The first few, for the message. The stored value is deliberately not
|
|
140
|
+
* carried: the issue reaches designers who may not read the instance.
|
|
141
|
+
*/
|
|
142
|
+
readonly samples: readonly {
|
|
143
|
+
readonly instanceId: string;
|
|
144
|
+
readonly rowIndex: number | null;
|
|
145
|
+
readonly expected: string;
|
|
146
|
+
}[];
|
|
147
|
+
};
|
|
148
|
+
export declare const FILTERABLE_FIELD_ISSUE_SAMPLE_LIMIT = 5;
|
|
149
|
+
/**
|
|
150
|
+
* The enable check (ADR 25 §5.4), pure: given the schema about to take effect,
|
|
151
|
+
* the schemas of older versions that hold instances, and those instances'
|
|
152
|
+
* form data, report every filterable field that may not be enabled.
|
|
153
|
+
*/
|
|
154
|
+
export declare function readFilterableFieldIssues(input: {
|
|
155
|
+
readonly schema: FormDefinitionSchema | null | undefined;
|
|
156
|
+
readonly history: readonly {
|
|
157
|
+
readonly versionNumber: number;
|
|
158
|
+
readonly schema: FormDefinitionSchema | null | undefined;
|
|
159
|
+
}[];
|
|
160
|
+
readonly instances: readonly {
|
|
161
|
+
readonly id: string;
|
|
162
|
+
readonly formData: Readonly<Record<string, unknown>> | null | undefined;
|
|
163
|
+
}[];
|
|
164
|
+
}): readonly FilterableFieldIssue[];
|
|
165
|
+
/** One line per issue, in the words the designer and the publish error use. */
|
|
166
|
+
export declare function describeFilterableFieldIssue(issue: FilterableFieldIssue): string;
|
|
@@ -0,0 +1,388 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FILTERABLE_FIELD_ISSUE_SAMPLE_LIMIT = exports.APPROVAL_INSTANCE_FIELD_FILTER_OPERATORS = exports.APPROVAL_INSTANCE_SORT_TIME_FIELDS = exports.FILTERABLE_TABLE_COLUMN_TYPES = exports.FILTERABLE_FIELD_TYPES = void 0;
|
|
4
|
+
exports.isApprovalInstanceSortTimeField = isApprovalInstanceSortTimeField;
|
|
5
|
+
exports.isFilterableFieldType = isFilterableFieldType;
|
|
6
|
+
exports.readFilterableValueKind = readFilterableValueKind;
|
|
7
|
+
exports.readFilterOperatorsForFieldType = readFilterOperatorsForFieldType;
|
|
8
|
+
exports.isFilterableFieldSortable = isFilterableFieldSortable;
|
|
9
|
+
exports.readFilterableFieldPaths = readFilterableFieldPaths;
|
|
10
|
+
exports.findFilterableFieldPath = findFilterableFieldPath;
|
|
11
|
+
exports.readFormFieldTypesByPath = readFormFieldTypesByPath;
|
|
12
|
+
exports.checkFilterableFieldValue = checkFilterableFieldValue;
|
|
13
|
+
exports.isCanonicalDate = isCanonicalDate;
|
|
14
|
+
exports.isCanonicalDateTime = isCanonicalDateTime;
|
|
15
|
+
exports.readFilterableValueProblems = readFilterableValueProblems;
|
|
16
|
+
exports.readFilterableFieldIssues = readFilterableFieldIssues;
|
|
17
|
+
exports.describeFilterableFieldIssue = describeFilterableFieldIssue;
|
|
18
|
+
const form_1 = require("./form");
|
|
19
|
+
/**
|
|
20
|
+
* Filtering and sorting the approval-instance list by form fields (ADR 25).
|
|
21
|
+
*
|
|
22
|
+
* Everything that decides "is this value right for a filterable field" lives
|
|
23
|
+
* here so the write-time check, the enable-time scan of old instances, the
|
|
24
|
+
* query compiler and the designer all answer the same way.
|
|
25
|
+
*/
|
|
26
|
+
/** Top-level field types a form designer may mark `filterable` (ADR 25 §5.2). */
|
|
27
|
+
exports.FILTERABLE_FIELD_TYPES = [
|
|
28
|
+
'autocomplete',
|
|
29
|
+
'boolean',
|
|
30
|
+
'checkbox',
|
|
31
|
+
'date',
|
|
32
|
+
'datetime',
|
|
33
|
+
'member',
|
|
34
|
+
'money',
|
|
35
|
+
'number',
|
|
36
|
+
'org_unit',
|
|
37
|
+
'radio',
|
|
38
|
+
'select',
|
|
39
|
+
'text',
|
|
40
|
+
'textarea',
|
|
41
|
+
];
|
|
42
|
+
/** Table column types a form designer may mark `filterable`: every column type. */
|
|
43
|
+
exports.FILTERABLE_TABLE_COLUMN_TYPES = form_1.TABLE_COLUMN_FIELD_TYPES;
|
|
44
|
+
/**
|
|
45
|
+
* Sort keys that are not form fields. A filterable field must not use one of
|
|
46
|
+
* these as its `fieldKey`, or a sort request would be ambiguous.
|
|
47
|
+
*/
|
|
48
|
+
exports.APPROVAL_INSTANCE_SORT_TIME_FIELDS = [
|
|
49
|
+
'submittedAt',
|
|
50
|
+
'updatedAt',
|
|
51
|
+
'completedAt',
|
|
52
|
+
];
|
|
53
|
+
function isApprovalInstanceSortTimeField(value) {
|
|
54
|
+
return exports.APPROVAL_INSTANCE_SORT_TIME_FIELDS.includes(value);
|
|
55
|
+
}
|
|
56
|
+
function isFilterableFieldType(type, placement = 'top-level') {
|
|
57
|
+
return placement === 'column'
|
|
58
|
+
? exports.FILTERABLE_TABLE_COLUMN_TYPES.includes(type)
|
|
59
|
+
: exports.FILTERABLE_FIELD_TYPES.includes(type);
|
|
60
|
+
}
|
|
61
|
+
exports.APPROVAL_INSTANCE_FIELD_FILTER_OPERATORS = ['EQUALS', 'NOT_EQUALS', 'IN', 'RANGE', 'CONTAINS'];
|
|
62
|
+
function readFilterableValueKind(type) {
|
|
63
|
+
switch (type) {
|
|
64
|
+
case 'text':
|
|
65
|
+
case 'textarea':
|
|
66
|
+
return 'text';
|
|
67
|
+
case 'number':
|
|
68
|
+
case 'money':
|
|
69
|
+
return 'number';
|
|
70
|
+
case 'date':
|
|
71
|
+
return 'date';
|
|
72
|
+
case 'datetime':
|
|
73
|
+
return 'datetime';
|
|
74
|
+
case 'boolean':
|
|
75
|
+
return 'boolean';
|
|
76
|
+
case 'select':
|
|
77
|
+
case 'autocomplete':
|
|
78
|
+
case 'radio':
|
|
79
|
+
case 'checkbox':
|
|
80
|
+
return 'option';
|
|
81
|
+
case 'member':
|
|
82
|
+
return 'member';
|
|
83
|
+
case 'org_unit':
|
|
84
|
+
return 'org_unit';
|
|
85
|
+
default:
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/** Operators a field type accepts (ADR 25 §7.2). */
|
|
90
|
+
function readFilterOperatorsForFieldType(type) {
|
|
91
|
+
if (type === 'textarea') {
|
|
92
|
+
return ['CONTAINS'];
|
|
93
|
+
}
|
|
94
|
+
if (type === 'boolean') {
|
|
95
|
+
return ['EQUALS'];
|
|
96
|
+
}
|
|
97
|
+
switch (readFilterableValueKind(type)) {
|
|
98
|
+
case 'text':
|
|
99
|
+
return ['EQUALS', 'NOT_EQUALS', 'IN', 'CONTAINS'];
|
|
100
|
+
case 'number':
|
|
101
|
+
return ['EQUALS', 'NOT_EQUALS', 'IN', 'RANGE'];
|
|
102
|
+
case 'date':
|
|
103
|
+
case 'datetime':
|
|
104
|
+
return ['EQUALS', 'NOT_EQUALS', 'RANGE'];
|
|
105
|
+
case 'option':
|
|
106
|
+
return ['EQUALS', 'NOT_EQUALS', 'IN', 'CONTAINS'];
|
|
107
|
+
case 'member':
|
|
108
|
+
case 'org_unit':
|
|
109
|
+
return ['EQUALS', 'NOT_EQUALS', 'IN'];
|
|
110
|
+
default:
|
|
111
|
+
return [];
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/** A filterable top-level field can be sorted on; a table column cannot (ADR 25 §7.5). */
|
|
115
|
+
function isFilterableFieldSortable(path) {
|
|
116
|
+
return path.tableKey === null && path.field.type !== 'textarea';
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* The fields of `schema` a list query may filter on: every field (or table
|
|
120
|
+
* column) marked `filterable` whose type allows it. A field marked filterable
|
|
121
|
+
* with a type that does not allow it is skipped here; the schema lint reports
|
|
122
|
+
* it.
|
|
123
|
+
*/
|
|
124
|
+
function readFilterableFieldPaths(schema) {
|
|
125
|
+
if (!schema || !Array.isArray(schema.fields)) {
|
|
126
|
+
return [];
|
|
127
|
+
}
|
|
128
|
+
return schema.fields.flatMap((field) => {
|
|
129
|
+
if ((0, form_1.isTableFieldDefinition)(field)) {
|
|
130
|
+
const table = field;
|
|
131
|
+
return table.columns
|
|
132
|
+
.filter((column) => column.filterable === true &&
|
|
133
|
+
isFilterableFieldType(column.type, 'column'))
|
|
134
|
+
.map((column) => toFilterableFieldPath(column, table.fieldKey, table.label));
|
|
135
|
+
}
|
|
136
|
+
return field.filterable === true && isFilterableFieldType(field.type)
|
|
137
|
+
? [toFilterableFieldPath(field, null, null)]
|
|
138
|
+
: [];
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
function findFilterableFieldPath(schema, path) {
|
|
142
|
+
var _a;
|
|
143
|
+
return (_a = readFilterableFieldPaths(schema).find((item) => item.path === path)) !== null && _a !== void 0 ? _a : null;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Every field and column of a schema by path, filterable or not. The enable
|
|
147
|
+
* check compares a new filterable field against what older versions stored
|
|
148
|
+
* at the same path, whether or not they were filterable then.
|
|
149
|
+
*/
|
|
150
|
+
function readFormFieldTypesByPath(schema) {
|
|
151
|
+
if (!schema || !Array.isArray(schema.fields)) {
|
|
152
|
+
return new Map();
|
|
153
|
+
}
|
|
154
|
+
return new Map(schema.fields.flatMap((field) => (0, form_1.isTableFieldDefinition)(field)
|
|
155
|
+
? [
|
|
156
|
+
[field.fieldKey, field.type],
|
|
157
|
+
...field.columns.map((column) => [
|
|
158
|
+
`${field.fieldKey}.${column.fieldKey}`,
|
|
159
|
+
column.type,
|
|
160
|
+
]),
|
|
161
|
+
]
|
|
162
|
+
: [[field.fieldKey, field.type]]));
|
|
163
|
+
}
|
|
164
|
+
function toFilterableFieldPath(field, tableKey, tableLabel) {
|
|
165
|
+
var _a;
|
|
166
|
+
const asField = field;
|
|
167
|
+
const staticOptions = (0, form_1.isFormStaticOptionFieldDefinition)(asField)
|
|
168
|
+
? asField.options
|
|
169
|
+
: null;
|
|
170
|
+
return {
|
|
171
|
+
field,
|
|
172
|
+
key: field.fieldKey,
|
|
173
|
+
kind: (_a = readFilterableValueKind(field.type)) !== null && _a !== void 0 ? _a : 'text',
|
|
174
|
+
label: tableLabel
|
|
175
|
+
? `${tableLabel}/${field.label || field.fieldKey}`
|
|
176
|
+
: field.label || field.fieldKey,
|
|
177
|
+
path: tableKey ? `${tableKey}.${field.fieldKey}` : field.fieldKey,
|
|
178
|
+
staticOptions,
|
|
179
|
+
tableKey,
|
|
180
|
+
usesOptionSnapshot: tableKey === null && (0, form_1.isFormDataSourceFieldDefinition)(asField),
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* The canonical stored formats (ADR 25 §6), matching what the form renderer
|
|
185
|
+
* writes: `formatDatePickerValue` for a date, `Date#toISOString` for a
|
|
186
|
+
* datetime, `Number(...)` for a number.
|
|
187
|
+
*/
|
|
188
|
+
const DATE_PATTERN = /^\d{4}-\d{2}-\d{2}$/u;
|
|
189
|
+
const DATETIME_PATTERN = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/u;
|
|
190
|
+
const EMPTY = { status: 'empty' };
|
|
191
|
+
const VALID = { status: 'valid' };
|
|
192
|
+
function invalid(expected) {
|
|
193
|
+
return { expected, status: 'invalid' };
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Whether one stored value fits a filterable field (ADR 25 §5.4, §6).
|
|
197
|
+
*
|
|
198
|
+
* - Missing and `null` are "no value". So is `""` for a number, money, date,
|
|
199
|
+
* datetime or boolean field (a cleared input), and `[]` for a multi-value
|
|
200
|
+
* field.
|
|
201
|
+
* - An option or member field accepts a string or an array of strings either
|
|
202
|
+
* way: its `mode` / `multiple` may change between versions without changing
|
|
203
|
+
* its type, and the query matches both shapes.
|
|
204
|
+
*/
|
|
205
|
+
function checkFilterableFieldValue(field, value) {
|
|
206
|
+
if (value === undefined || value === null) {
|
|
207
|
+
return EMPTY;
|
|
208
|
+
}
|
|
209
|
+
switch (readFilterableValueKind(field.type)) {
|
|
210
|
+
case 'text':
|
|
211
|
+
return typeof value === 'string' ? VALID : invalid('文字');
|
|
212
|
+
case 'number':
|
|
213
|
+
if (value === '') {
|
|
214
|
+
return EMPTY;
|
|
215
|
+
}
|
|
216
|
+
return typeof value === 'number' && Number.isFinite(value)
|
|
217
|
+
? VALID
|
|
218
|
+
: invalid('數字');
|
|
219
|
+
case 'date':
|
|
220
|
+
if (value === '') {
|
|
221
|
+
return EMPTY;
|
|
222
|
+
}
|
|
223
|
+
return isCanonicalDate(value) ? VALID : invalid('日期(YYYY-MM-DD)');
|
|
224
|
+
case 'datetime':
|
|
225
|
+
if (value === '') {
|
|
226
|
+
return EMPTY;
|
|
227
|
+
}
|
|
228
|
+
return isCanonicalDateTime(value)
|
|
229
|
+
? VALID
|
|
230
|
+
: invalid('日期時間(ISO 8601 UTC,例如 2026-11-03T08:30:00.000Z)');
|
|
231
|
+
case 'boolean':
|
|
232
|
+
if (value === '') {
|
|
233
|
+
return EMPTY;
|
|
234
|
+
}
|
|
235
|
+
return typeof value === 'boolean' ? VALID : invalid('布林值(true 或 false)');
|
|
236
|
+
case 'option':
|
|
237
|
+
case 'member':
|
|
238
|
+
return checkStringOrStringArray(value);
|
|
239
|
+
case 'org_unit':
|
|
240
|
+
return typeof value === 'string' ? VALID : invalid('組織單位 ID(文字)');
|
|
241
|
+
default:
|
|
242
|
+
return VALID;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
function checkStringOrStringArray(value) {
|
|
246
|
+
if (typeof value === 'string') {
|
|
247
|
+
return VALID;
|
|
248
|
+
}
|
|
249
|
+
if (Array.isArray(value) && value.every((item) => typeof item === 'string')) {
|
|
250
|
+
return value.length === 0 ? EMPTY : VALID;
|
|
251
|
+
}
|
|
252
|
+
return invalid('文字或文字清單');
|
|
253
|
+
}
|
|
254
|
+
function isCanonicalDate(value) {
|
|
255
|
+
if (typeof value !== 'string' || !DATE_PATTERN.test(value)) {
|
|
256
|
+
return false;
|
|
257
|
+
}
|
|
258
|
+
const [year, month, day] = value.split('-').map(Number);
|
|
259
|
+
const date = new Date(Date.UTC(year, month - 1, day));
|
|
260
|
+
return (date.getUTCFullYear() === year &&
|
|
261
|
+
date.getUTCMonth() === month - 1 &&
|
|
262
|
+
date.getUTCDate() === day);
|
|
263
|
+
}
|
|
264
|
+
function isCanonicalDateTime(value) {
|
|
265
|
+
if (typeof value !== 'string' || !DATETIME_PATTERN.test(value)) {
|
|
266
|
+
return false;
|
|
267
|
+
}
|
|
268
|
+
const time = Date.parse(value);
|
|
269
|
+
return Number.isFinite(time) && new Date(time).toISOString() === value;
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Every value in `formData` that does not fit one of `paths`. Used both when
|
|
273
|
+
* writing (refuse the write) and when enabling a field (refuse to enable while
|
|
274
|
+
* old instances hold such values). A table that is not an array, or a row that
|
|
275
|
+
* is not an object, is a problem of every filterable column in it.
|
|
276
|
+
*/
|
|
277
|
+
function readFilterableValueProblems(paths, formData) {
|
|
278
|
+
const data = formData !== null && formData !== void 0 ? formData : {};
|
|
279
|
+
return paths.flatMap((item) => {
|
|
280
|
+
if (item.tableKey === null) {
|
|
281
|
+
const value = ownValue(data, item.key);
|
|
282
|
+
const check = checkFilterableFieldValue(item.field, value);
|
|
283
|
+
return check.status === 'invalid'
|
|
284
|
+
? [{ expected: check.expected, path: item.path, rowIndex: null, value }]
|
|
285
|
+
: [];
|
|
286
|
+
}
|
|
287
|
+
const tableKey = item.tableKey;
|
|
288
|
+
// A malformed table or row is one problem however many of its columns are
|
|
289
|
+
// filterable, so only the table's first filterable column reports it.
|
|
290
|
+
const reportsTable = paths.find((candidate) => candidate.tableKey === tableKey) === item;
|
|
291
|
+
const rows = ownValue(data, tableKey);
|
|
292
|
+
if (rows === undefined || rows === null) {
|
|
293
|
+
return [];
|
|
294
|
+
}
|
|
295
|
+
if (!Array.isArray(rows)) {
|
|
296
|
+
return reportsTable
|
|
297
|
+
? [{ expected: '表格列的清單', path: tableKey, rowIndex: null, value: rows }]
|
|
298
|
+
: [];
|
|
299
|
+
}
|
|
300
|
+
return rows.flatMap((row, rowIndex) => {
|
|
301
|
+
if (typeof row !== 'object' || row === null || Array.isArray(row)) {
|
|
302
|
+
return reportsTable
|
|
303
|
+
? [{ expected: '物件', path: tableKey, rowIndex, value: row }]
|
|
304
|
+
: [];
|
|
305
|
+
}
|
|
306
|
+
const value = ownValue(row, item.key);
|
|
307
|
+
const check = checkFilterableFieldValue(item.field, value);
|
|
308
|
+
return check.status === 'invalid'
|
|
309
|
+
? [{ expected: check.expected, path: item.path, rowIndex, value }]
|
|
310
|
+
: [];
|
|
311
|
+
});
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
function ownValue(record, key) {
|
|
315
|
+
return Object.prototype.hasOwnProperty.call(record, key)
|
|
316
|
+
? record[key]
|
|
317
|
+
: undefined;
|
|
318
|
+
}
|
|
319
|
+
exports.FILTERABLE_FIELD_ISSUE_SAMPLE_LIMIT = 5;
|
|
320
|
+
/**
|
|
321
|
+
* The enable check (ADR 25 §5.4), pure: given the schema about to take effect,
|
|
322
|
+
* the schemas of older versions that hold instances, and those instances'
|
|
323
|
+
* form data, report every filterable field that may not be enabled.
|
|
324
|
+
*/
|
|
325
|
+
function readFilterableFieldIssues(input) {
|
|
326
|
+
const paths = readFilterableFieldPaths(input.schema);
|
|
327
|
+
const historyTypes = input.history.map((version) => ({
|
|
328
|
+
types: readFormFieldTypesByPath(version.schema),
|
|
329
|
+
versionNumber: version.versionNumber,
|
|
330
|
+
}));
|
|
331
|
+
return paths.flatMap((item) => {
|
|
332
|
+
const conflicts = historyTypes
|
|
333
|
+
.map((version) => ({
|
|
334
|
+
type: version.types.get(item.path),
|
|
335
|
+
versionNumber: version.versionNumber,
|
|
336
|
+
}))
|
|
337
|
+
.filter((version) => version.type !== undefined && version.type !== item.field.type)
|
|
338
|
+
.sort((left, right) => left.versionNumber - right.versionNumber);
|
|
339
|
+
if (conflicts.length > 0) {
|
|
340
|
+
return [
|
|
341
|
+
{
|
|
342
|
+
conflicts,
|
|
343
|
+
kind: 'TYPE_CHANGED',
|
|
344
|
+
label: item.label,
|
|
345
|
+
path: item.path,
|
|
346
|
+
type: item.field.type,
|
|
347
|
+
},
|
|
348
|
+
];
|
|
349
|
+
}
|
|
350
|
+
const problems = input.instances.flatMap((instance) => readFilterableValueProblems([item], instance.formData).map((problem) => ({
|
|
351
|
+
expected: problem.expected,
|
|
352
|
+
instanceId: instance.id,
|
|
353
|
+
rowIndex: problem.rowIndex,
|
|
354
|
+
})));
|
|
355
|
+
if (problems.length === 0) {
|
|
356
|
+
return [];
|
|
357
|
+
}
|
|
358
|
+
return [
|
|
359
|
+
{
|
|
360
|
+
invalidInstanceCount: new Set(problems.map((problem) => problem.instanceId)).size,
|
|
361
|
+
kind: 'INVALID_VALUES',
|
|
362
|
+
label: item.label,
|
|
363
|
+
path: item.path,
|
|
364
|
+
samples: problems.slice(0, exports.FILTERABLE_FIELD_ISSUE_SAMPLE_LIMIT),
|
|
365
|
+
type: item.field.type,
|
|
366
|
+
},
|
|
367
|
+
];
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
/** One line per issue, in the words the designer and the publish error use. */
|
|
371
|
+
function describeFilterableFieldIssue(issue) {
|
|
372
|
+
if (issue.kind === 'TYPE_CHANGED') {
|
|
373
|
+
const versions = issue.conflicts
|
|
374
|
+
.map((conflict) => `v${conflict.versionNumber}(${conflict.type})`)
|
|
375
|
+
.join('、');
|
|
376
|
+
return (`欄位「${issue.label}」(${issue.path})無法啟用篩選:已有案件的舊版本 ${versions} ` +
|
|
377
|
+
`在這個欄位存的是不同型別,現在是 ${issue.type}。請改用新的欄位 key 再勾選可篩選。`);
|
|
378
|
+
}
|
|
379
|
+
// The stored values are deliberately left out: a designer need not be able
|
|
380
|
+
// to read the instances, and could otherwise read any key's values by
|
|
381
|
+
// declaring it filterable. Instance ids and row numbers locate the problem.
|
|
382
|
+
const samples = issue.samples
|
|
383
|
+
.map((sample) => `${sample.instanceId}${sample.rowIndex === null ? '' : `(第 ${sample.rowIndex + 1} 列)`}`)
|
|
384
|
+
.join('、');
|
|
385
|
+
return (`欄位「${issue.label}」(${issue.path})無法啟用篩選:有 ${issue.invalidInstanceCount} 筆舊案件` +
|
|
386
|
+
`的值不符合 ${issue.type} 型別(例如 ${samples})。舊案件的值無法修改,請改用新的欄位 key 再勾選可篩選。`);
|
|
387
|
+
}
|
|
388
|
+
//# sourceMappingURL=form-filter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"form-filter.js","sourceRoot":"","sources":["../../../../../libs/shared/src/lib/form-filter.ts"],"names":[],"mappings":"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"}
|