@nocobase/plugin-data-source-main 2.1.0-alpha.13 → 2.1.0-alpha.15

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.
@@ -0,0 +1,543 @@
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
+ var __create = Object.create;
11
+ var __defProp = Object.defineProperty;
12
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
13
+ var __getOwnPropNames = Object.getOwnPropertyNames;
14
+ var __getProtoOf = Object.getPrototypeOf;
15
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
16
+ var __export = (target, all) => {
17
+ for (var name in all)
18
+ __defProp(target, name, { get: all[name], enumerable: true });
19
+ };
20
+ var __copyProps = (to, from, except, desc) => {
21
+ if (from && typeof from === "object" || typeof from === "function") {
22
+ for (let key of __getOwnPropNames(from))
23
+ if (!__hasOwnProp.call(to, key) && key !== except)
24
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
25
+ }
26
+ return to;
27
+ };
28
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
29
+ // If the importer is in node compatibility mode or this is not an ESM
30
+ // file that has been converted to a CommonJS file using a Babel-
31
+ // compatible transform (i.e. "__esModule" has not been set), then set
32
+ // "default" to the CommonJS "module.exports" for node compatibility.
33
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
34
+ mod
35
+ ));
36
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
37
+ var fields_exports = {};
38
+ __export(fields_exports, {
39
+ normalizeFieldInput: () => normalizeFieldInput,
40
+ normalizeFieldList: () => normalizeFieldList,
41
+ normalizeInterfaceName: () => normalizeInterfaceName
42
+ });
43
+ module.exports = __toCommonJS(fields_exports);
44
+ var import_lodash = __toESM(require("lodash"));
45
+ var import_sequelize = require("sequelize");
46
+ var import_constants = require("./constants");
47
+ function normalizeInterfaceName(value) {
48
+ if (!value) {
49
+ return value;
50
+ }
51
+ return import_constants.INTERFACE_ALIASES[value] || value;
52
+ }
53
+ const DEFAULT_FIELD_TYPES = {
54
+ input: "string",
55
+ phone: "string",
56
+ email: "string",
57
+ color: "string",
58
+ icon: "string",
59
+ url: "text",
60
+ textarea: "text",
61
+ markdown: "text",
62
+ vditor: "text",
63
+ richText: "text",
64
+ integer: "bigInt",
65
+ number: "double",
66
+ percent: "float",
67
+ password: "password",
68
+ checkbox: "boolean",
69
+ select: "string",
70
+ radioGroup: "string",
71
+ multipleSelect: "array",
72
+ checkboxGroup: "array",
73
+ json: "json",
74
+ attachment: "belongsToMany",
75
+ attachmentURL: "string",
76
+ point: "point",
77
+ lineString: "lineString",
78
+ circle: "circle",
79
+ polygon: "polygon",
80
+ datetime: "date",
81
+ createdAt: "date",
82
+ updatedAt: "date",
83
+ datetimeNoTz: "datetimeNoTz",
84
+ dateOnly: "dateOnly",
85
+ time: "time",
86
+ unixTimestamp: "unixTimestamp",
87
+ m2o: "belongsTo",
88
+ obo: "belongsTo",
89
+ createdBy: "belongsTo",
90
+ updatedBy: "belongsTo",
91
+ o2m: "hasMany",
92
+ m2m: "belongsToMany",
93
+ oho: "hasOne",
94
+ chinaRegion: "belongsToMany",
95
+ snowflakeId: "snowflakeId",
96
+ id: "bigInt",
97
+ uuid: "uuid",
98
+ nanoid: "nanoid",
99
+ formula: "formula",
100
+ sort: "sort",
101
+ code: "code",
102
+ sequence: "sequence",
103
+ encryption: "string",
104
+ tableoid: "virtual",
105
+ mbm: "belongsToArray"
106
+ };
107
+ const ALLOWED_FIELD_TYPES = {
108
+ input: ["string"],
109
+ phone: ["string"],
110
+ email: ["string"],
111
+ color: ["string"],
112
+ icon: ["string"],
113
+ url: ["text", "string"],
114
+ textarea: ["text", "string"],
115
+ markdown: ["text", "string"],
116
+ vditor: ["text", "string"],
117
+ richText: ["text", "string"],
118
+ integer: ["bigInt", "integer"],
119
+ number: ["double", "float", "decimal", "integer", "bigInt"],
120
+ percent: ["float", "double", "decimal"],
121
+ password: ["password", "string"],
122
+ checkbox: ["boolean"],
123
+ select: ["string"],
124
+ radioGroup: ["string"],
125
+ multipleSelect: ["array"],
126
+ checkboxGroup: ["array"],
127
+ json: ["json", "jsonb"],
128
+ attachment: ["belongsToMany"],
129
+ attachmentURL: ["string"],
130
+ point: ["point", "json"],
131
+ lineString: ["lineString", "json"],
132
+ circle: ["circle", "json"],
133
+ polygon: ["polygon", "json"],
134
+ datetime: ["date"],
135
+ createdAt: ["date"],
136
+ updatedAt: ["date"],
137
+ datetimeNoTz: ["datetimeNoTz"],
138
+ dateOnly: ["dateOnly"],
139
+ time: ["time"],
140
+ unixTimestamp: ["unixTimestamp"],
141
+ m2o: ["belongsTo"],
142
+ obo: ["belongsTo"],
143
+ createdBy: ["belongsTo"],
144
+ updatedBy: ["belongsTo"],
145
+ o2m: ["hasMany"],
146
+ m2m: ["belongsToMany"],
147
+ oho: ["hasOne"],
148
+ chinaRegion: ["belongsToMany"],
149
+ snowflakeId: ["snowflakeId"],
150
+ id: ["bigInt"],
151
+ uuid: ["uuid"],
152
+ nanoid: ["nanoid"],
153
+ formula: ["formula"],
154
+ sort: ["sort"],
155
+ code: ["code"],
156
+ sequence: ["sequence"],
157
+ encryption: ["encryption", "string"],
158
+ tableoid: ["virtual"],
159
+ mbm: ["belongsToArray"]
160
+ };
161
+ function buildRelationComponentProps(field) {
162
+ return {
163
+ multiple: import_constants.MULTI_COMPONENT_INTERFACES.has(field.interface),
164
+ fieldNames: {
165
+ value: field.targetKey || "id",
166
+ label: field.targetTitleField || "id"
167
+ }
168
+ };
169
+ }
170
+ function getFieldType(field) {
171
+ const defaultType = DEFAULT_FIELD_TYPES[field.interface];
172
+ if (!defaultType) {
173
+ throw new Error(`Unknown field interface ${field.interface}`);
174
+ }
175
+ return field.type || defaultType;
176
+ }
177
+ function isPrimaryKeyLikeField(field) {
178
+ return field.primaryKey === true || field.name === "id";
179
+ }
180
+ function buildUiSchema(field) {
181
+ const title = field.title || (0, import_constants.toDisplayTitle)(field.name);
182
+ switch (field.interface) {
183
+ case "input":
184
+ return { type: "string", title, "x-component": "Input" };
185
+ case "textarea":
186
+ return { type: "string", title, "x-component": "Input.TextArea" };
187
+ case "phone":
188
+ return { type: "string", title, "x-component": "Input", "x-component-props": { type: "tel" } };
189
+ case "email":
190
+ return { type: "string", title, "x-component": "Input", "x-validator": "email" };
191
+ case "url":
192
+ return { type: "string", title, "x-component": "Input.URL" };
193
+ case "integer":
194
+ return {
195
+ type: "number",
196
+ title,
197
+ "x-component": "InputNumber",
198
+ "x-component-props": { stringMode: true, step: "1" },
199
+ "x-validator": "integer"
200
+ };
201
+ case "number":
202
+ return {
203
+ type: "number",
204
+ title,
205
+ "x-component": "InputNumber",
206
+ "x-component-props": { stringMode: true, step: "1" }
207
+ };
208
+ case "percent":
209
+ return {
210
+ type: "string",
211
+ title,
212
+ "x-component": "Percent",
213
+ "x-component-props": { stringMode: true, step: "1", addonAfter: "%" }
214
+ };
215
+ case "password":
216
+ return { type: "string", title, "x-component": "Password" };
217
+ case "color":
218
+ return { type: "string", title, "x-component": "ColorSelect" };
219
+ case "icon":
220
+ return { type: "string", title, "x-component": "IconPicker" };
221
+ case "checkbox":
222
+ return { type: "boolean", title, "x-component": "Checkbox" };
223
+ case "select":
224
+ return { type: "string", title, "x-component": "Select", enum: (0, import_constants.normalizeChoiceEnum)(field.enum) };
225
+ case "multipleSelect":
226
+ return {
227
+ type: "array",
228
+ title,
229
+ "x-component": "Select",
230
+ "x-component-props": { mode: "multiple" },
231
+ enum: (0, import_constants.normalizeChoiceEnum)(field.enum)
232
+ };
233
+ case "radioGroup":
234
+ return { type: "string", title, "x-component": "Radio.Group", enum: (0, import_constants.normalizeChoiceEnum)(field.enum) };
235
+ case "checkboxGroup":
236
+ return { type: "array", title, "x-component": "Checkbox.Group", enum: (0, import_constants.normalizeChoiceEnum)(field.enum) };
237
+ case "chinaRegion":
238
+ return {
239
+ type: "array",
240
+ title,
241
+ "x-component": "Cascader",
242
+ "x-component-props": {
243
+ useDataSource: "{{ useChinaRegionDataSource }}",
244
+ useLoadData: "{{ useChinaRegionLoadData }}",
245
+ changeOnSelectLast: false,
246
+ labelInValue: true,
247
+ maxLevel: 3,
248
+ fieldNames: { label: "name", value: "code", children: "children" }
249
+ }
250
+ };
251
+ case "markdown":
252
+ return { type: "string", title, "x-component": "Markdown" };
253
+ case "vditor":
254
+ return { type: "string", title, "x-component": "MarkdownVditor" };
255
+ case "richText":
256
+ return { type: "string", title, "x-component": "RichText" };
257
+ case "attachment":
258
+ return { type: "array", title, "x-component": "Attachment" };
259
+ case "attachmentURL":
260
+ return {
261
+ type: "string",
262
+ title,
263
+ "x-component": "AttachmentUrl",
264
+ "x-use-component-props": "useAttachmentUrlFieldProps"
265
+ };
266
+ case "point":
267
+ case "lineString":
268
+ case "circle":
269
+ case "polygon":
270
+ return {
271
+ type: "void",
272
+ title,
273
+ "x-component": "Map",
274
+ "x-component-designer": "Map.Designer",
275
+ "x-component-props": {}
276
+ };
277
+ case "json":
278
+ return { type: "object", title, "x-component": "Input.JSON", "x-component-props": { autoSize: { minRows: 5 } } };
279
+ case "datetime":
280
+ return { type: "string", title, "x-component": "DatePicker", "x-component-props": { showTime: true, utc: true } };
281
+ case "datetimeNoTz":
282
+ return {
283
+ type: "string",
284
+ title,
285
+ "x-component": "DatePicker",
286
+ "x-component-props": { showTime: true, utc: false }
287
+ };
288
+ case "dateOnly":
289
+ return {
290
+ type: "string",
291
+ title,
292
+ "x-component": "DatePicker",
293
+ "x-component-props": { dateOnly: true, showTime: false }
294
+ };
295
+ case "time":
296
+ return { type: "string", title, "x-component": "TimePicker" };
297
+ case "unixTimestamp":
298
+ return {
299
+ type: "number",
300
+ title,
301
+ "x-component": "UnixTimestamp",
302
+ "x-component-props": { showTime: true },
303
+ "x-validator": "timestamp"
304
+ };
305
+ case "m2o":
306
+ case "o2m":
307
+ case "m2m":
308
+ case "obo":
309
+ case "oho":
310
+ case "mbm":
311
+ return {
312
+ type: import_constants.MULTI_COMPONENT_INTERFACES.has(field.interface) ? "array" : "object",
313
+ title,
314
+ "x-component": "AssociationField",
315
+ "x-component-props": buildRelationComponentProps(field)
316
+ };
317
+ case "createdAt":
318
+ case "updatedAt":
319
+ return { type: "datetime", title, "x-component": "DatePicker", "x-read-pretty": true };
320
+ case "createdBy":
321
+ case "updatedBy":
322
+ return {
323
+ type: "object",
324
+ title,
325
+ "x-component": "AssociationField",
326
+ "x-component-props": { fieldNames: { value: "id", label: "nickname" } },
327
+ "x-read-pretty": true
328
+ };
329
+ case "snowflakeId":
330
+ return {
331
+ type: "number",
332
+ title,
333
+ "x-component": "InputNumber",
334
+ "x-component-props": { stringMode: true, separator: "0.00", step: "1" },
335
+ "x-validator": "integer"
336
+ };
337
+ case "id":
338
+ return { type: "number", title, "x-component": "InputNumber", "x-read-pretty": true };
339
+ case "uuid":
340
+ return { type: "string", title, "x-component": "Input", "x-validator": "uuid" };
341
+ case "nanoid":
342
+ return { type: "string", title, "x-component": "NanoIDInput" };
343
+ case "formula":
344
+ return {
345
+ type: "string",
346
+ title,
347
+ "x-component": "Formula.Result",
348
+ "x-component-props": { stringMode: true, step: "1" },
349
+ "x-read-pretty": true
350
+ };
351
+ case "sort":
352
+ return { type: "number", title, "x-component": "InputNumber" };
353
+ case "code":
354
+ return { type: "string", title, "x-component": "CodeEditor" };
355
+ case "sequence":
356
+ return { type: "string", title, "x-component": "Sequence" };
357
+ case "tableoid":
358
+ return {
359
+ type: "string",
360
+ title,
361
+ "x-component": "CollectionSelect",
362
+ "x-component-props": {
363
+ isTableOid: true
364
+ },
365
+ "x-read-pretty": true
366
+ };
367
+ default:
368
+ return { type: "string", title, "x-component": "Input" };
369
+ }
370
+ }
371
+ function validateFieldType(field) {
372
+ const allowedTypes = ALLOWED_FIELD_TYPES[field.interface];
373
+ if (!allowedTypes) {
374
+ throw new Error(`Unknown field interface ${field.interface}`);
375
+ }
376
+ if (field.type && !allowedTypes.includes(field.type)) {
377
+ throw new Error(
378
+ `Field ${field.name || "(unknown)"} type ${field.type} does not match interface ${field.interface}. Allowed types: ${allowedTypes.join(", ")}`
379
+ );
380
+ }
381
+ }
382
+ function buildRelationKeyName(name, key = "id") {
383
+ return import_sequelize.Utils.camelize([import_sequelize.Utils.singularize(name || ""), key].join("_"));
384
+ }
385
+ const REVERSE_INTERFACE_MAP = {
386
+ m2o: "o2m",
387
+ o2m: "m2o",
388
+ m2m: "m2m",
389
+ obo: "oho",
390
+ oho: "obo"
391
+ };
392
+ function buildThroughName(source, target) {
393
+ return import_sequelize.Utils.camelize(
394
+ [source, target].filter(Boolean).map((name) => String(name).toLowerCase()).sort().join("_")
395
+ );
396
+ }
397
+ function applyReadableRelationDefaults(field) {
398
+ const sourceKey = field.sourceKey || "id";
399
+ const targetKey = field.targetKey || "id";
400
+ if (field.interface === "m2o" || field.interface === "obo") {
401
+ field.targetKey = field.targetKey || targetKey;
402
+ field.foreignKey = field.foreignKey || buildRelationKeyName(field.name, field.targetKey);
403
+ return;
404
+ }
405
+ if (field.interface === "o2m" || field.interface === "oho") {
406
+ field.sourceKey = field.sourceKey || sourceKey;
407
+ field.foreignKey = field.foreignKey || buildRelationKeyName(field.collectionName, field.sourceKey);
408
+ return;
409
+ }
410
+ if (field.interface === "m2m" || field.interface === "mbm") {
411
+ field.sourceKey = field.sourceKey || sourceKey;
412
+ field.targetKey = field.targetKey || targetKey;
413
+ field.foreignKey = field.foreignKey || buildRelationKeyName(field.collectionName, field.sourceKey);
414
+ field.otherKey = field.otherKey || buildRelationKeyName(field.target, field.targetKey);
415
+ field.through = field.through || buildThroughName(field.collectionName, field.target);
416
+ }
417
+ }
418
+ function buildReverseField(field) {
419
+ if (field.reverseField) {
420
+ return normalizeFieldInput(field.reverseField, { collectionName: field.target });
421
+ }
422
+ if (!field.reverseName) {
423
+ return void 0;
424
+ }
425
+ const reverseInterface = field.reverseInterface || REVERSE_INTERFACE_MAP[field.interface];
426
+ return normalizeFieldInput(
427
+ {
428
+ name: field.reverseName,
429
+ title: field.reverseTitle,
430
+ interface: reverseInterface,
431
+ target: field.collectionName,
432
+ targetTitleField: field.sourceTitleField || "id",
433
+ targetKey: field.sourceKey || "id",
434
+ through: field.through,
435
+ foreignKey: field.otherKey || field.foreignKey,
436
+ otherKey: field.foreignKey || field.otherKey
437
+ },
438
+ { collectionName: field.target }
439
+ );
440
+ }
441
+ function normalizeFieldInput(input, context = {}) {
442
+ var _a, _b;
443
+ const field = import_lodash.default.cloneDeep(input || {});
444
+ field.interface = normalizeInterfaceName(field.interface);
445
+ field.collectionName = field.collectionName || context.collectionName;
446
+ field.title = field.title || ((_a = field.uiSchema) == null ? void 0 : _a.title) || (0, import_constants.toDisplayTitle)(field.name);
447
+ field.targetTitleField = field.targetTitleField || field.titleField;
448
+ if (!field.interface) {
449
+ throw new Error(`Field ${field.name || "(unknown)"} is missing interface`);
450
+ }
451
+ validateFieldType(field);
452
+ if (import_constants.RELATION_INTERFACES.has(field.interface) && !field.target) {
453
+ throw new Error(`Relation field ${field.name} requires target`);
454
+ }
455
+ if (field.interface === "formula" && !field.expression) {
456
+ throw new Error(`Formula field ${field.name || "(unknown)"} requires expression`);
457
+ }
458
+ applyReadableRelationDefaults(field);
459
+ const normalized = {
460
+ ...field,
461
+ interface: field.interface,
462
+ type: getFieldType(field)
463
+ };
464
+ normalized.uiSchema = import_lodash.default.merge({}, buildUiSchema(normalized), field.uiSchema || {});
465
+ if (import_constants.CHOICE_INTERFACES.has(normalized.interface)) {
466
+ normalized.enum = (0, import_constants.normalizeChoiceEnum)(normalized.enum || ((_b = normalized.uiSchema) == null ? void 0 : _b.enum) || []);
467
+ normalized.uiSchema.enum = normalized.enum;
468
+ }
469
+ if (import_constants.ARRAY_DEFAULT_INTERFACES.has(normalized.interface) && normalized.defaultValue === void 0) {
470
+ normalized.defaultValue = [];
471
+ }
472
+ if (normalized.interface === "createdAt") {
473
+ normalized.field = normalized.field || "createdAt";
474
+ }
475
+ if (normalized.interface === "updatedAt") {
476
+ normalized.field = normalized.field || "updatedAt";
477
+ }
478
+ if (normalized.interface === "createdBy") {
479
+ normalized.target = normalized.target || "users";
480
+ normalized.foreignKey = normalized.foreignKey || "createdById";
481
+ }
482
+ if (normalized.interface === "updatedBy") {
483
+ normalized.target = normalized.target || "users";
484
+ normalized.foreignKey = normalized.foreignKey || "updatedById";
485
+ }
486
+ if (normalized.interface === "attachment") {
487
+ normalized.target = normalized.target || "attachments";
488
+ }
489
+ if (normalized.interface === "attachmentURL") {
490
+ normalized.target = normalized.target || "attachments";
491
+ normalized.targetKey = normalized.targetKey || "id";
492
+ }
493
+ if (normalized.interface === "chinaRegion") {
494
+ normalized.target = normalized.target || "chinaRegions";
495
+ normalized.targetKey = normalized.targetKey || "code";
496
+ normalized.sourceKey = normalized.sourceKey || "id";
497
+ normalized.sortBy = normalized.sortBy || "level";
498
+ normalized.through = normalized.through || `t_${normalized.name}_links`;
499
+ normalized.foreignKey = normalized.foreignKey || "f_record_id";
500
+ normalized.otherKey = normalized.otherKey || "f_region_code";
501
+ }
502
+ if (normalized.interface === "snowflakeId") {
503
+ normalized.primaryKey = normalized.primaryKey ?? isPrimaryKeyLikeField(normalized);
504
+ normalized.allowNull = normalized.allowNull ?? false;
505
+ normalized.autoIncrement = normalized.autoIncrement ?? false;
506
+ }
507
+ if (normalized.interface === "id") {
508
+ normalized.primaryKey = normalized.primaryKey ?? isPrimaryKeyLikeField(normalized);
509
+ normalized.allowNull = normalized.allowNull ?? false;
510
+ normalized.autoIncrement = normalized.autoIncrement ?? true;
511
+ }
512
+ if (normalized.interface === "uuid" || normalized.interface === "nanoid") {
513
+ normalized.primaryKey = normalized.primaryKey ?? isPrimaryKeyLikeField(normalized);
514
+ normalized.allowNull = normalized.allowNull ?? false;
515
+ }
516
+ if (normalized.interface === "tableoid") {
517
+ normalized.name = normalized.name || "__collection";
518
+ }
519
+ if (normalized.interface === "formula") {
520
+ normalized.engine = normalized.engine || "formula.js";
521
+ }
522
+ const reverseField = buildReverseField(normalized);
523
+ if (reverseField) {
524
+ normalized.reverseField = reverseField;
525
+ }
526
+ delete normalized.title;
527
+ delete normalized.reverseName;
528
+ delete normalized.reverseTitle;
529
+ delete normalized.reverseInterface;
530
+ delete normalized.targetTitleField;
531
+ delete normalized.sourceTitleField;
532
+ delete normalized.titleField;
533
+ return normalized;
534
+ }
535
+ function normalizeFieldList(fields = [], collectionName) {
536
+ return (0, import_constants.uniqueByName)(fields.map((field) => normalizeFieldInput(field, { collectionName })));
537
+ }
538
+ // Annotate the CommonJS export names for ESM import in node:
539
+ 0 && (module.exports = {
540
+ normalizeFieldInput,
541
+ normalizeFieldList,
542
+ normalizeInterfaceName
543
+ });
@@ -0,0 +1,36 @@
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
+ import { PlainObject } from './constants';
10
+ export declare function findCollection(ctx: any, collectionName: string): Promise<any>;
11
+ export declare function pickCollectionApplyValues(values: PlainObject): {
12
+ [x: string]: any;
13
+ };
14
+ export declare function upsertFieldDefinition(ctx: any, rawInput: PlainObject): Promise<any>;
15
+ export declare function applyFieldDefinition(ctx: any, rawInput: PlainObject, options?: {
16
+ relationOnly?: boolean;
17
+ }): Promise<any>;
18
+ export declare function applyCollectionDefinition(ctx: any, rawInput: PlainObject, syncCollectionFields: (ctx: any, collectionName: string, values: {
19
+ fields?: PlainObject[];
20
+ }) => Promise<void>): Promise<{
21
+ data: any;
22
+ verify: {
23
+ valid: boolean;
24
+ issues: string[];
25
+ data: {
26
+ name: any;
27
+ template: any;
28
+ fields: {
29
+ name: any;
30
+ interface: any;
31
+ type: any;
32
+ title: any;
33
+ }[];
34
+ };
35
+ };
36
+ }>;