@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 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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rytass/bpm-core-shared",
3
- "version": "0.20.0",
3
+ "version": "0.21.0",
4
4
  "description": "Shared TypeScript contracts for the Rytass BPM approval workflow stack (workflow, form, condition, identity, organization, status types).",
5
5
  "keywords": [
6
6
  "bpm",
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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"}