@nocobase/flow-engine 2.1.0-alpha.12 → 2.1.0-alpha.13
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/lib/FlowDefinition.d.ts +0 -4
- package/lib/index.d.ts +0 -1
- package/lib/index.js +1 -3
- package/lib/models/DisplayItemModel.d.ts +1 -1
- package/lib/models/EditableItemModel.d.ts +1 -1
- package/lib/models/FilterableItemModel.d.ts +1 -1
- package/lib/runjs-context/snippets/index.js +13 -2
- package/lib/{server.d.ts → runjs-context/snippets/scene/detail/set-field-style.snippet.d.ts} +3 -2
- package/lib/{server.js → runjs-context/snippets/scene/detail/set-field-style.snippet.js} +27 -9
- package/{src/server.ts → lib/runjs-context/snippets/scene/table/set-cell-style.snippet.d.ts} +3 -3
- package/lib/runjs-context/snippets/scene/table/set-cell-style.snippet.js +54 -0
- package/lib/types.d.ts +0 -221
- package/package.json +4 -4
- package/src/__tests__/runjsSnippets.test.ts +21 -0
- package/src/index.ts +0 -1
- package/src/models/DisplayItemModel.tsx +1 -1
- package/src/models/EditableItemModel.tsx +1 -1
- package/src/models/FilterableItemModel.tsx +1 -1
- package/src/runjs-context/snippets/index.ts +12 -1
- package/src/runjs-context/snippets/scene/detail/set-field-style.snippet.ts +30 -0
- package/src/runjs-context/snippets/scene/table/set-cell-style.snippet.ts +34 -0
- package/src/types.ts +0 -262
- package/lib/FlowSchemaRegistry.d.ts +0 -154
- package/lib/FlowSchemaRegistry.js +0 -1427
- package/lib/flow-schema-registry/fieldBinding.d.ts +0 -32
- package/lib/flow-schema-registry/fieldBinding.js +0 -165
- package/lib/flow-schema-registry/modelPatches.d.ts +0 -16
- package/lib/flow-schema-registry/modelPatches.js +0 -235
- package/lib/flow-schema-registry/schemaInference.d.ts +0 -17
- package/lib/flow-schema-registry/schemaInference.js +0 -207
- package/lib/flow-schema-registry/utils.d.ts +0 -25
- package/lib/flow-schema-registry/utils.js +0 -293
- package/server.d.ts +0 -1
- package/server.js +0 -1
- package/src/FlowSchemaRegistry.ts +0 -1799
- package/src/__tests__/FlowSchemaRegistry.test.ts +0 -1951
- package/src/flow-schema-registry/fieldBinding.ts +0 -171
- package/src/flow-schema-registry/modelPatches.ts +0 -260
- package/src/flow-schema-registry/schemaInference.ts +0 -210
- package/src/flow-schema-registry/utils.ts +0 -268
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* This file is part of the NocoBase (R) project.
|
|
3
|
-
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
-
* Authors: NocoBase Team.
|
|
5
|
-
*
|
|
6
|
-
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
-
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import _ from 'lodash';
|
|
11
|
-
import type {
|
|
12
|
-
FlowFieldBindingConditions,
|
|
13
|
-
FlowFieldBindingContextContribution,
|
|
14
|
-
FlowFieldBindingContribution,
|
|
15
|
-
FlowFieldModelCompatibility,
|
|
16
|
-
FlowSchemaCoverage,
|
|
17
|
-
} from '../types';
|
|
18
|
-
import { normalizeStringArray } from './utils';
|
|
19
|
-
|
|
20
|
-
export type RegisteredFieldBindingContext = {
|
|
21
|
-
name: string;
|
|
22
|
-
inherits: string[];
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
export type RegisteredFieldBinding = {
|
|
26
|
-
context: string;
|
|
27
|
-
use: string;
|
|
28
|
-
interfaces: string[];
|
|
29
|
-
isDefault: boolean;
|
|
30
|
-
order?: number;
|
|
31
|
-
conditions?: FlowFieldBindingConditions;
|
|
32
|
-
defaultProps?: any;
|
|
33
|
-
source: FlowSchemaCoverage['source'];
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
function normalizeFieldBindingConditions(
|
|
37
|
-
conditions?: FlowFieldBindingConditions,
|
|
38
|
-
): FlowFieldBindingConditions | undefined {
|
|
39
|
-
if (!conditions || typeof conditions !== 'object' || Array.isArray(conditions)) {
|
|
40
|
-
return undefined;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const normalized = _.pickBy(
|
|
44
|
-
{
|
|
45
|
-
association: typeof conditions.association === 'boolean' ? conditions.association : undefined,
|
|
46
|
-
fieldTypes: normalizeStringArray(conditions.fieldTypes),
|
|
47
|
-
targetCollectionTemplateIn: normalizeStringArray(conditions.targetCollectionTemplateIn),
|
|
48
|
-
targetCollectionTemplateNotIn: normalizeStringArray(conditions.targetCollectionTemplateNotIn),
|
|
49
|
-
},
|
|
50
|
-
(value) => {
|
|
51
|
-
if (Array.isArray(value)) {
|
|
52
|
-
return value.length > 0;
|
|
53
|
-
}
|
|
54
|
-
return value !== undefined;
|
|
55
|
-
},
|
|
56
|
-
) as FlowFieldBindingConditions;
|
|
57
|
-
|
|
58
|
-
return Object.keys(normalized).length > 0 ? normalized : undefined;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
export function normalizeFieldBindingContextContribution(
|
|
62
|
-
contribution?: FlowFieldBindingContextContribution,
|
|
63
|
-
fallbackName?: string,
|
|
64
|
-
): RegisteredFieldBindingContext | undefined {
|
|
65
|
-
const name = String(contribution?.name || fallbackName || '').trim();
|
|
66
|
-
if (!name) {
|
|
67
|
-
return undefined;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
return {
|
|
71
|
-
name,
|
|
72
|
-
inherits: normalizeStringArray(contribution?.inherits),
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
export function normalizeFieldBindingContribution(
|
|
77
|
-
contribution?: FlowFieldBindingContribution,
|
|
78
|
-
source: FlowSchemaCoverage['source'] = 'official',
|
|
79
|
-
): RegisteredFieldBinding | undefined {
|
|
80
|
-
const context = String(contribution?.context || '').trim();
|
|
81
|
-
const use = String(contribution?.use || '').trim();
|
|
82
|
-
const interfaces = normalizeStringArray(contribution?.interfaces);
|
|
83
|
-
if (!context || !use || interfaces.length === 0) {
|
|
84
|
-
return undefined;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
return {
|
|
88
|
-
context,
|
|
89
|
-
use,
|
|
90
|
-
interfaces,
|
|
91
|
-
isDefault: contribution?.isDefault === true,
|
|
92
|
-
order: typeof contribution?.order === 'number' ? contribution.order : undefined,
|
|
93
|
-
conditions: normalizeFieldBindingConditions(contribution?.conditions),
|
|
94
|
-
defaultProps: contribution?.defaultProps === undefined ? undefined : _.cloneDeep(contribution.defaultProps),
|
|
95
|
-
source,
|
|
96
|
-
};
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
export function matchesFieldBinding(
|
|
100
|
-
binding: RegisteredFieldBinding,
|
|
101
|
-
options: {
|
|
102
|
-
interface?: string;
|
|
103
|
-
fieldType?: string;
|
|
104
|
-
association?: boolean;
|
|
105
|
-
targetCollectionTemplate?: string;
|
|
106
|
-
},
|
|
107
|
-
) {
|
|
108
|
-
if (options.interface && !binding.interfaces.includes('*') && !binding.interfaces.includes(options.interface)) {
|
|
109
|
-
return false;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
const conditions = binding.conditions;
|
|
113
|
-
if (!conditions) {
|
|
114
|
-
return true;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
if (typeof conditions.association === 'boolean' && options.association !== undefined) {
|
|
118
|
-
if (conditions.association !== options.association) {
|
|
119
|
-
return false;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
if (conditions.fieldTypes?.length && options.fieldType) {
|
|
124
|
-
if (!conditions.fieldTypes.includes(options.fieldType)) {
|
|
125
|
-
return false;
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
if (conditions.targetCollectionTemplateIn?.length && options.targetCollectionTemplate) {
|
|
130
|
-
if (!conditions.targetCollectionTemplateIn.includes(options.targetCollectionTemplate)) {
|
|
131
|
-
return false;
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
if (conditions.targetCollectionTemplateNotIn?.length && options.targetCollectionTemplate) {
|
|
136
|
-
if (conditions.targetCollectionTemplateNotIn.includes(options.targetCollectionTemplate)) {
|
|
137
|
-
return false;
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
return true;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
export function buildFieldModelCompatibility(binding: RegisteredFieldBinding): FlowFieldModelCompatibility {
|
|
145
|
-
const compatibility: FlowFieldModelCompatibility = {
|
|
146
|
-
context: binding.context,
|
|
147
|
-
interfaces: _.cloneDeep(binding.interfaces),
|
|
148
|
-
inheritParentFieldBinding: true,
|
|
149
|
-
};
|
|
150
|
-
|
|
151
|
-
if (binding.isDefault) {
|
|
152
|
-
compatibility.isDefault = true;
|
|
153
|
-
}
|
|
154
|
-
if (typeof binding.order === 'number') {
|
|
155
|
-
compatibility.order = binding.order;
|
|
156
|
-
}
|
|
157
|
-
if (typeof binding.conditions?.association === 'boolean') {
|
|
158
|
-
compatibility.association = binding.conditions.association;
|
|
159
|
-
}
|
|
160
|
-
if (binding.conditions?.fieldTypes?.length) {
|
|
161
|
-
compatibility.fieldTypes = _.cloneDeep(binding.conditions.fieldTypes);
|
|
162
|
-
}
|
|
163
|
-
if (binding.conditions?.targetCollectionTemplateIn?.length) {
|
|
164
|
-
compatibility.targetCollectionTemplateIn = _.cloneDeep(binding.conditions.targetCollectionTemplateIn);
|
|
165
|
-
}
|
|
166
|
-
if (binding.conditions?.targetCollectionTemplateNotIn?.length) {
|
|
167
|
-
compatibility.targetCollectionTemplateNotIn = _.cloneDeep(binding.conditions.targetCollectionTemplateNotIn);
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
return compatibility;
|
|
171
|
-
}
|
|
@@ -1,260 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* This file is part of the NocoBase (R) project.
|
|
3
|
-
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
-
* Authors: NocoBase Team.
|
|
5
|
-
*
|
|
6
|
-
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
-
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import _ from 'lodash';
|
|
11
|
-
import type {
|
|
12
|
-
FlowDescendantSchemaPatch,
|
|
13
|
-
FlowJsonSchema,
|
|
14
|
-
FlowModelSchemaPatch,
|
|
15
|
-
FlowSchemaContextEdge,
|
|
16
|
-
FlowSchemaCoverage,
|
|
17
|
-
FlowSubModelContextPathStep,
|
|
18
|
-
FlowSubModelSlotSchema,
|
|
19
|
-
} from '../types';
|
|
20
|
-
import type { RegisteredModelSchema } from '../FlowSchemaRegistry';
|
|
21
|
-
import { deepMergeReplaceArrays, mergeSchemas, normalizeSchemaDocs, normalizeSchemaHints } from './utils';
|
|
22
|
-
|
|
23
|
-
export function normalizeSubModelContextPath(path?: FlowSubModelContextPathStep[]): FlowSubModelContextPathStep[] {
|
|
24
|
-
if (!Array.isArray(path)) {
|
|
25
|
-
return [];
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
return path
|
|
29
|
-
.map((step) => ({
|
|
30
|
-
slotKey: String(step?.slotKey || '').trim(),
|
|
31
|
-
...(typeof step?.use === 'string'
|
|
32
|
-
? { use: step.use.trim() }
|
|
33
|
-
: Array.isArray(step?.use)
|
|
34
|
-
? { use: step.use.map((item) => String(item || '').trim()).filter(Boolean) }
|
|
35
|
-
: {}),
|
|
36
|
-
}))
|
|
37
|
-
.filter((step) => !!step.slotKey);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export function normalizeModelSchemaPatch(patch?: FlowModelSchemaPatch): FlowModelSchemaPatch | undefined {
|
|
41
|
-
if (!patch || typeof patch !== 'object' || Array.isArray(patch)) {
|
|
42
|
-
return undefined;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const normalized = _.pickBy(
|
|
46
|
-
{
|
|
47
|
-
stepParamsSchema: patch.stepParamsSchema ? _.cloneDeep(patch.stepParamsSchema) : undefined,
|
|
48
|
-
flowRegistrySchema: patch.flowRegistrySchema ? _.cloneDeep(patch.flowRegistrySchema) : undefined,
|
|
49
|
-
flowRegistrySchemaPatch: patch.flowRegistrySchemaPatch ? _.cloneDeep(patch.flowRegistrySchemaPatch) : undefined,
|
|
50
|
-
subModelSlots: normalizeSubModelSlots(patch.subModelSlots),
|
|
51
|
-
docs: patch.docs ? normalizeSchemaDocs(patch.docs) : undefined,
|
|
52
|
-
examples: Array.isArray(patch.examples) ? _.cloneDeep(patch.examples) : undefined,
|
|
53
|
-
skeleton: patch.skeleton === undefined ? undefined : _.cloneDeep(patch.skeleton),
|
|
54
|
-
dynamicHints: Array.isArray(patch.dynamicHints) ? normalizeSchemaHints(patch.dynamicHints) : undefined,
|
|
55
|
-
},
|
|
56
|
-
(value) => value !== undefined && (!Array.isArray(value) || value.length > 0),
|
|
57
|
-
) as FlowModelSchemaPatch;
|
|
58
|
-
|
|
59
|
-
return Object.keys(normalized).length > 0 ? normalized : undefined;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
function normalizeDescendantSchemaPatches(
|
|
63
|
-
patches?: FlowDescendantSchemaPatch[],
|
|
64
|
-
): FlowDescendantSchemaPatch[] | undefined {
|
|
65
|
-
if (!Array.isArray(patches)) {
|
|
66
|
-
return undefined;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
const normalized = patches
|
|
70
|
-
.map((item) => {
|
|
71
|
-
const path = normalizeSubModelContextPath(item?.path);
|
|
72
|
-
const patch = normalizeModelSchemaPatch(item?.patch);
|
|
73
|
-
if (!patch) {
|
|
74
|
-
return undefined;
|
|
75
|
-
}
|
|
76
|
-
return { path, patch };
|
|
77
|
-
})
|
|
78
|
-
.filter(Boolean) as FlowDescendantSchemaPatch[];
|
|
79
|
-
|
|
80
|
-
return normalized.length > 0 ? normalized : undefined;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
function normalizeChildSchemaPatch(
|
|
84
|
-
patch?: FlowSubModelSlotSchema['childSchemaPatch'],
|
|
85
|
-
): FlowSubModelSlotSchema['childSchemaPatch'] | undefined {
|
|
86
|
-
if (!patch || typeof patch !== 'object' || Array.isArray(patch)) {
|
|
87
|
-
return undefined;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
const directPatch = normalizeModelSchemaPatch(patch as FlowModelSchemaPatch);
|
|
91
|
-
if (directPatch) {
|
|
92
|
-
return directPatch;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
const entries = Object.entries(patch as Record<string, FlowModelSchemaPatch>)
|
|
96
|
-
.map(([childUse, childPatch]) => [String(childUse || '').trim(), normalizeModelSchemaPatch(childPatch)] as const)
|
|
97
|
-
.filter(([childUse, childPatch]) => !!childUse && !!childPatch);
|
|
98
|
-
|
|
99
|
-
if (!entries.length) {
|
|
100
|
-
return undefined;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
return Object.fromEntries(entries);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
export function normalizeSubModelSlots(
|
|
107
|
-
slots?: Record<string, FlowSubModelSlotSchema>,
|
|
108
|
-
): Record<string, FlowSubModelSlotSchema> | undefined {
|
|
109
|
-
if (!slots || typeof slots !== 'object' || Array.isArray(slots)) {
|
|
110
|
-
return undefined;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
const normalizedEntries = Object.entries(slots)
|
|
114
|
-
.map(([slotKey, slot]) => {
|
|
115
|
-
if (!slot?.type) {
|
|
116
|
-
return undefined;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
const normalizedSlot: FlowSubModelSlotSchema = {
|
|
120
|
-
type: slot.type,
|
|
121
|
-
};
|
|
122
|
-
|
|
123
|
-
const normalizedUse = typeof slot.use === 'string' ? slot.use.trim() : undefined;
|
|
124
|
-
if (normalizedUse) {
|
|
125
|
-
normalizedSlot.use = normalizedUse;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
const normalizedUses = Array.isArray(slot.uses)
|
|
129
|
-
? slot.uses.map((item) => String(item || '').trim()).filter(Boolean)
|
|
130
|
-
: undefined;
|
|
131
|
-
if (normalizedUses?.length) {
|
|
132
|
-
normalizedSlot.uses = normalizedUses;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
if (slot.required !== undefined) {
|
|
136
|
-
normalizedSlot.required = slot.required;
|
|
137
|
-
}
|
|
138
|
-
if (slot.type === 'array' && typeof slot.minItems === 'number' && Number.isFinite(slot.minItems)) {
|
|
139
|
-
normalizedSlot.minItems = Math.max(0, Math.trunc(slot.minItems));
|
|
140
|
-
}
|
|
141
|
-
if (slot.dynamic !== undefined) {
|
|
142
|
-
normalizedSlot.dynamic = slot.dynamic;
|
|
143
|
-
}
|
|
144
|
-
if (slot.schema) {
|
|
145
|
-
normalizedSlot.schema = _.cloneDeep(slot.schema);
|
|
146
|
-
}
|
|
147
|
-
if (typeof slot.fieldBindingContext === 'string' && slot.fieldBindingContext.trim()) {
|
|
148
|
-
normalizedSlot.fieldBindingContext = slot.fieldBindingContext.trim();
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
const childSchemaPatch = normalizeChildSchemaPatch(slot.childSchemaPatch);
|
|
152
|
-
if (childSchemaPatch) {
|
|
153
|
-
normalizedSlot.childSchemaPatch = childSchemaPatch;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
const descendantSchemaPatches = normalizeDescendantSchemaPatches(slot.descendantSchemaPatches);
|
|
157
|
-
if (descendantSchemaPatches?.length) {
|
|
158
|
-
normalizedSlot.descendantSchemaPatches = descendantSchemaPatches;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
if (slot.description !== undefined) {
|
|
162
|
-
normalizedSlot.description = slot.description;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
return [slotKey, normalizedSlot] as const;
|
|
166
|
-
})
|
|
167
|
-
.filter(Boolean) as Array<readonly [string, FlowSubModelSlotSchema]>;
|
|
168
|
-
|
|
169
|
-
return normalizedEntries.length > 0 ? Object.fromEntries(normalizedEntries) : undefined;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
export function matchesDescendantSchemaPatch(
|
|
173
|
-
patch: FlowDescendantSchemaPatch,
|
|
174
|
-
remainingEdges: FlowSchemaContextEdge[],
|
|
175
|
-
): boolean {
|
|
176
|
-
const path = normalizeSubModelContextPath(patch.path);
|
|
177
|
-
if (path.length !== remainingEdges.length) {
|
|
178
|
-
return false;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
return path.every((step, index) => {
|
|
182
|
-
const edge = remainingEdges[index];
|
|
183
|
-
if (step.slotKey !== edge.slotKey) {
|
|
184
|
-
return false;
|
|
185
|
-
}
|
|
186
|
-
if (typeof step.use === 'undefined') {
|
|
187
|
-
return true;
|
|
188
|
-
}
|
|
189
|
-
if (typeof step.use === 'string') {
|
|
190
|
-
return step.use === edge.childUse;
|
|
191
|
-
}
|
|
192
|
-
return step.use.includes(edge.childUse);
|
|
193
|
-
});
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
export function resolveChildSchemaPatch(
|
|
197
|
-
slot: FlowSubModelSlotSchema,
|
|
198
|
-
childUse: string,
|
|
199
|
-
): FlowModelSchemaPatch | undefined {
|
|
200
|
-
const childSchemaPatch = slot.childSchemaPatch;
|
|
201
|
-
if (!childSchemaPatch || typeof childSchemaPatch !== 'object' || Array.isArray(childSchemaPatch)) {
|
|
202
|
-
return undefined;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
const directPatch = normalizeModelSchemaPatch(childSchemaPatch as FlowModelSchemaPatch);
|
|
206
|
-
if (directPatch) {
|
|
207
|
-
return directPatch;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
return normalizeModelSchemaPatch((childSchemaPatch as Record<string, FlowModelSchemaPatch>)[childUse]);
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
export function applyModelSchemaPatch(
|
|
214
|
-
target: RegisteredModelSchema,
|
|
215
|
-
patch: FlowModelSchemaPatch,
|
|
216
|
-
source: FlowSchemaCoverage['source'],
|
|
217
|
-
strict?: boolean,
|
|
218
|
-
) {
|
|
219
|
-
target.stepParamsSchema = mergeSchemas(target.stepParamsSchema, patch.stepParamsSchema);
|
|
220
|
-
target.flowRegistrySchema = mergeSchemas(target.flowRegistrySchema, patch.flowRegistrySchema);
|
|
221
|
-
target.flowRegistrySchemaPatch = mergeSchemas(target.flowRegistrySchemaPatch, patch.flowRegistrySchemaPatch);
|
|
222
|
-
target.subModelSlots = normalizeSubModelSlots(
|
|
223
|
-
patch.subModelSlots
|
|
224
|
-
? deepMergeReplaceArrays(target.subModelSlots || {}, patch.subModelSlots)
|
|
225
|
-
: target.subModelSlots,
|
|
226
|
-
);
|
|
227
|
-
target.docs = normalizeSchemaDocs({
|
|
228
|
-
...target.docs,
|
|
229
|
-
...patch.docs,
|
|
230
|
-
examples: patch.docs?.examples || target.docs?.examples,
|
|
231
|
-
dynamicHints: [...(target.docs?.dynamicHints || []), ...(patch.docs?.dynamicHints || [])],
|
|
232
|
-
commonPatterns: patch.docs?.commonPatterns || target.docs?.commonPatterns,
|
|
233
|
-
antiPatterns: patch.docs?.antiPatterns || target.docs?.antiPatterns,
|
|
234
|
-
minimalExample: patch.docs?.minimalExample !== undefined ? patch.docs.minimalExample : target.docs?.minimalExample,
|
|
235
|
-
});
|
|
236
|
-
target.examples = Array.isArray(patch.examples) ? _.cloneDeep(patch.examples) : target.examples;
|
|
237
|
-
target.skeleton =
|
|
238
|
-
patch.skeleton !== undefined ? deepMergeReplaceArrays(target.skeleton, patch.skeleton) : target.skeleton;
|
|
239
|
-
target.dynamicHints = normalizeSchemaHints([
|
|
240
|
-
...(target.dynamicHints || []),
|
|
241
|
-
...(patch.dynamicHints || []),
|
|
242
|
-
...(patch.docs?.dynamicHints || []),
|
|
243
|
-
]);
|
|
244
|
-
|
|
245
|
-
const hasSchemaPatch =
|
|
246
|
-
!!patch.stepParamsSchema || !!patch.flowRegistrySchema || !!patch.flowRegistrySchemaPatch || !!patch.subModelSlots;
|
|
247
|
-
if (hasSchemaPatch) {
|
|
248
|
-
target.coverage = {
|
|
249
|
-
...target.coverage,
|
|
250
|
-
status:
|
|
251
|
-
target.coverage.status === 'unresolved'
|
|
252
|
-
? 'manual'
|
|
253
|
-
: target.coverage.status === 'auto'
|
|
254
|
-
? 'mixed'
|
|
255
|
-
: target.coverage.status,
|
|
256
|
-
source: target.coverage.source === 'third-party' ? source : target.coverage.source,
|
|
257
|
-
strict: target.coverage.strict ?? strict,
|
|
258
|
-
};
|
|
259
|
-
}
|
|
260
|
-
}
|
|
@@ -1,210 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* This file is part of the NocoBase (R) project.
|
|
3
|
-
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
-
* Authors: NocoBase Team.
|
|
5
|
-
*
|
|
6
|
-
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
-
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import _ from 'lodash';
|
|
11
|
-
import type { ISchema } from '@formily/json-schema';
|
|
12
|
-
import type { FlowDynamicHint, FlowJsonSchema, FlowSchemaCoverage } from '../types';
|
|
13
|
-
import { createFlowHint } from './utils';
|
|
14
|
-
|
|
15
|
-
export type StepSchemaResolution = {
|
|
16
|
-
schema?: FlowJsonSchema;
|
|
17
|
-
hints: FlowDynamicHint[];
|
|
18
|
-
coverage: FlowSchemaCoverage['status'];
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
export type UiSchemaLike =
|
|
22
|
-
| Record<string, ISchema>
|
|
23
|
-
| ((...args: any[]) => Record<string, ISchema> | Promise<Record<string, ISchema>>)
|
|
24
|
-
| undefined;
|
|
25
|
-
|
|
26
|
-
function inferSchemaFromUiSchemaValue(
|
|
27
|
-
name: string,
|
|
28
|
-
uiSchema: ISchema,
|
|
29
|
-
path: string,
|
|
30
|
-
hints: FlowDynamicHint[],
|
|
31
|
-
): FlowJsonSchema {
|
|
32
|
-
if (!uiSchema || typeof uiSchema !== 'object' || Array.isArray(uiSchema)) {
|
|
33
|
-
return { type: 'object', additionalProperties: true };
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const xComponent = (uiSchema as any)['x-component'];
|
|
37
|
-
if (typeof xComponent === 'function') {
|
|
38
|
-
hints.push(
|
|
39
|
-
createFlowHint(
|
|
40
|
-
{
|
|
41
|
-
kind: 'custom-component',
|
|
42
|
-
path,
|
|
43
|
-
message: `${name} uses a custom component and needs manual schema review.`,
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
unresolvedReason: 'function-x-component',
|
|
47
|
-
recommendedFallback: { type: 'object', additionalProperties: true },
|
|
48
|
-
},
|
|
49
|
-
),
|
|
50
|
-
);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const reactions = (uiSchema as any)['x-reactions'];
|
|
54
|
-
if (
|
|
55
|
-
reactions &&
|
|
56
|
-
((Array.isArray(reactions) && reactions.some((item) => typeof item === 'function')) ||
|
|
57
|
-
typeof reactions === 'function')
|
|
58
|
-
) {
|
|
59
|
-
hints.push(
|
|
60
|
-
createFlowHint(
|
|
61
|
-
{
|
|
62
|
-
kind: 'x-reactions',
|
|
63
|
-
path,
|
|
64
|
-
message: `${name} contains function-based x-reactions and only static schema is generated.`,
|
|
65
|
-
},
|
|
66
|
-
{
|
|
67
|
-
unresolvedReason: 'function-x-reactions',
|
|
68
|
-
},
|
|
69
|
-
),
|
|
70
|
-
);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
const schema: FlowJsonSchema = {};
|
|
74
|
-
const type = (uiSchema as any).type;
|
|
75
|
-
if (type) {
|
|
76
|
-
schema.type = type;
|
|
77
|
-
}
|
|
78
|
-
if ((uiSchema as any).description) {
|
|
79
|
-
schema.description = (uiSchema as any).description;
|
|
80
|
-
}
|
|
81
|
-
if ((uiSchema as any).default !== undefined) {
|
|
82
|
-
schema.default = _.cloneDeep((uiSchema as any).default);
|
|
83
|
-
}
|
|
84
|
-
if ((uiSchema as any).enum) {
|
|
85
|
-
if (
|
|
86
|
-
Array.isArray((uiSchema as any).enum) &&
|
|
87
|
-
(uiSchema as any).enum.every((item) => _.isPlainObject(item) && 'value' in item)
|
|
88
|
-
) {
|
|
89
|
-
schema.enum = (uiSchema as any).enum.map((item) => item.value);
|
|
90
|
-
} else {
|
|
91
|
-
schema.enum = _.cloneDeep((uiSchema as any).enum);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
if ((uiSchema as any).const !== undefined) {
|
|
95
|
-
schema.const = _.cloneDeep((uiSchema as any).const);
|
|
96
|
-
}
|
|
97
|
-
if ((uiSchema as any).required === true) {
|
|
98
|
-
schema.__required = true;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
const validator = (uiSchema as any)['x-validator'];
|
|
102
|
-
if (_.isPlainObject(validator)) {
|
|
103
|
-
if (validator.minimum !== undefined) schema.minimum = validator.minimum;
|
|
104
|
-
if (validator.maximum !== undefined) schema.maximum = validator.maximum;
|
|
105
|
-
if (validator.minLength !== undefined) schema.minLength = validator.minLength;
|
|
106
|
-
if (validator.maxLength !== undefined) schema.maxLength = validator.maxLength;
|
|
107
|
-
if (validator.pattern !== undefined) schema.pattern = validator.pattern;
|
|
108
|
-
} else if (Array.isArray(validator)) {
|
|
109
|
-
for (const item of validator) {
|
|
110
|
-
if (_.isPlainObject(item)) {
|
|
111
|
-
Object.assign(schema, _.pick(item, ['minimum', 'maximum', 'minLength', 'maxLength', 'pattern']));
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
} else if (typeof validator === 'string') {
|
|
115
|
-
if (validator === 'integer') schema.type = 'integer';
|
|
116
|
-
if (validator === 'email') schema.format = 'email';
|
|
117
|
-
if (validator === 'url') schema.format = 'uri';
|
|
118
|
-
if (validator === 'uid') schema.pattern = '^[A-Za-z0-9_-]+$';
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
if ((uiSchema as any).properties && _.isPlainObject((uiSchema as any).properties)) {
|
|
122
|
-
schema.type = schema.type || 'object';
|
|
123
|
-
schema.properties = {};
|
|
124
|
-
const required: string[] = [];
|
|
125
|
-
for (const [propName, propValue] of Object.entries((uiSchema as any).properties)) {
|
|
126
|
-
const childSchema = inferSchemaFromUiSchemaValue(propName, propValue as ISchema, `${path}.${propName}`, hints);
|
|
127
|
-
if ((childSchema as any).__required) {
|
|
128
|
-
required.push(propName);
|
|
129
|
-
delete (childSchema as any).__required;
|
|
130
|
-
}
|
|
131
|
-
(schema.properties as any)[propName] = childSchema;
|
|
132
|
-
}
|
|
133
|
-
if (required.length) {
|
|
134
|
-
schema.required = required;
|
|
135
|
-
}
|
|
136
|
-
schema.additionalProperties = false;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
if ((uiSchema as any).items) {
|
|
140
|
-
schema.type = schema.type || 'array';
|
|
141
|
-
if (_.isPlainObject((uiSchema as any).items)) {
|
|
142
|
-
schema.items = inferSchemaFromUiSchemaValue(`${name}.items`, (uiSchema as any).items, `${path}.items`, hints);
|
|
143
|
-
} else if (Array.isArray((uiSchema as any).items)) {
|
|
144
|
-
schema.items = (uiSchema as any).items.map((item, index) =>
|
|
145
|
-
inferSchemaFromUiSchemaValue(`${name}.items[${index}]`, item, `${path}.items[${index}]`, hints),
|
|
146
|
-
);
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
if (!schema.type) {
|
|
151
|
-
schema.type = 'object';
|
|
152
|
-
schema.additionalProperties = true;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
return schema;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
export function inferParamsSchemaFromUiSchema(
|
|
159
|
-
name: string,
|
|
160
|
-
uiSchema: UiSchemaLike,
|
|
161
|
-
path: string,
|
|
162
|
-
): StepSchemaResolution {
|
|
163
|
-
const hints: FlowDynamicHint[] = [];
|
|
164
|
-
if (!uiSchema) {
|
|
165
|
-
return { schema: undefined, hints, coverage: 'unresolved' };
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
if (typeof uiSchema === 'function') {
|
|
169
|
-
hints.push(
|
|
170
|
-
createFlowHint(
|
|
171
|
-
{
|
|
172
|
-
kind: 'dynamic-ui-schema',
|
|
173
|
-
path,
|
|
174
|
-
message: `${name} uses function-based uiSchema and requires manual schema patch.`,
|
|
175
|
-
},
|
|
176
|
-
{
|
|
177
|
-
unresolvedReason: 'function-ui-schema',
|
|
178
|
-
recommendedFallback: { type: 'object', additionalProperties: true },
|
|
179
|
-
},
|
|
180
|
-
),
|
|
181
|
-
);
|
|
182
|
-
return {
|
|
183
|
-
schema: { type: 'object', additionalProperties: true },
|
|
184
|
-
hints,
|
|
185
|
-
coverage: 'unresolved',
|
|
186
|
-
};
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
const properties: Record<string, FlowJsonSchema> = {};
|
|
190
|
-
const required: string[] = [];
|
|
191
|
-
for (const [key, value] of Object.entries(uiSchema)) {
|
|
192
|
-
const childSchema = inferSchemaFromUiSchemaValue(key, value, `${path}.${key}`, hints);
|
|
193
|
-
if ((childSchema as any).__required) {
|
|
194
|
-
required.push(key);
|
|
195
|
-
delete (childSchema as any).__required;
|
|
196
|
-
}
|
|
197
|
-
properties[key] = childSchema;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
return {
|
|
201
|
-
schema: {
|
|
202
|
-
type: 'object',
|
|
203
|
-
properties,
|
|
204
|
-
...(required.length ? { required } : {}),
|
|
205
|
-
additionalProperties: false,
|
|
206
|
-
},
|
|
207
|
-
hints,
|
|
208
|
-
coverage: hints.length ? 'mixed' : 'auto',
|
|
209
|
-
};
|
|
210
|
-
}
|