@tiangong-lca/cli 0.0.5 → 0.0.7
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/README.md +73 -30
- package/dist/src/cli.js +913 -113
- package/dist/src/cli.js.map +1 -1
- package/dist/src/lib/dataset-local.js +231 -0
- package/dist/src/lib/dataset-local.js.map +1 -0
- package/dist/src/lib/dataset-references-rewrite.js +214 -0
- package/dist/src/lib/dataset-references-rewrite.js.map +1 -0
- package/dist/src/lib/dataset-validate.js +191 -0
- package/dist/src/lib/dataset-validate.js.map +1 -0
- package/dist/src/lib/flow-regen-product.js +2 -10
- package/dist/src/lib/flow-regen-product.js.map +1 -1
- package/dist/src/lib/flow-remediate.js +4 -8
- package/dist/src/lib/flow-remediate.js.map +1 -1
- package/dist/src/lib/lifecyclemodel-auto-build.js +11 -8
- package/dist/src/lib/lifecyclemodel-auto-build.js.map +1 -1
- package/dist/src/lib/lifecyclemodel-bundle-save.js +468 -0
- package/dist/src/lib/lifecyclemodel-bundle-save.js.map +1 -0
- package/dist/src/lib/lifecyclemodel-graph.js +248 -0
- package/dist/src/lib/lifecyclemodel-graph.js.map +1 -0
- package/dist/src/lib/lifecyclemodel-publish-build.js +3 -1
- package/dist/src/lib/lifecyclemodel-publish-build.js.map +1 -1
- package/dist/src/lib/lifecyclemodel-save-draft-run.js +245 -0
- package/dist/src/lib/lifecyclemodel-save-draft-run.js.map +1 -0
- package/dist/src/lib/lifecyclemodel-validate-build.js +1 -1
- package/dist/src/lib/lifecyclemodel-validate-build.js.map +1 -1
- package/dist/src/lib/process-auto-build.js +11 -8
- package/dist/src/lib/process-auto-build.js.map +1 -1
- package/dist/src/lib/process-batch-build.js +6 -3
- package/dist/src/lib/process-batch-build.js.map +1 -1
- package/dist/src/lib/process-dedup-review.js +870 -0
- package/dist/src/lib/process-dedup-review.js.map +1 -0
- package/dist/src/lib/process-payload-validation.js +50 -0
- package/dist/src/lib/process-payload-validation.js.map +1 -0
- package/dist/src/lib/process-publish-build.js +4 -6
- package/dist/src/lib/process-publish-build.js.map +1 -1
- package/dist/src/lib/process-refresh-references.js +1028 -0
- package/dist/src/lib/process-refresh-references.js.map +1 -0
- package/dist/src/lib/process-resume-build.js +4 -6
- package/dist/src/lib/process-resume-build.js.map +1 -1
- package/dist/src/lib/process-save-draft-run.js +31 -12
- package/dist/src/lib/process-save-draft-run.js.map +1 -1
- package/dist/src/lib/process-scope-statistics.js +859 -0
- package/dist/src/lib/process-scope-statistics.js.map +1 -0
- package/dist/src/lib/process-verify-rows.js +250 -0
- package/dist/src/lib/process-verify-rows.js.map +1 -0
- package/dist/src/lib/publish.js +54 -4
- package/dist/src/lib/publish.js.map +1 -1
- package/dist/src/lib/remote.js +4 -4
- package/dist/src/lib/remote.js.map +1 -1
- package/dist/src/lib/review-lifecyclemodel.js +2 -2
- package/dist/src/lib/review-lifecyclemodel.js.map +1 -1
- package/dist/src/lib/tidas-sdk-package-validator.js +28 -9
- package/dist/src/lib/tidas-sdk-package-validator.js.map +1 -1
- package/dist/src/lib/tidas-sdk-validation.js +96 -0
- package/dist/src/lib/tidas-sdk-validation.js.map +1 -0
- package/dist/src/lib/user-api-key.js +1 -1
- package/dist/src/lib/user-api-key.js.map +1 -1
- package/package.json +4 -4
- /package/bin/{tiangong.d.ts → tiangong-lca.d.ts} +0 -0
- /package/bin/{tiangong.js → tiangong-lca.js} +0 -0
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import * as tidasSdk from '@tiangong-lca/tidas-sdk';
|
|
3
|
+
import { writeJsonArtifact, writeJsonLinesArtifact } from './artifacts.js';
|
|
4
|
+
import { CliError } from './errors.js';
|
|
5
|
+
import { materializeDatasetRows } from './dataset-local.js';
|
|
6
|
+
import { normalizeIssuePath, validateSchemaWithDeepFallback, } from './tidas-sdk-validation.js';
|
|
7
|
+
const DEFAULT_TYPE = 'auto';
|
|
8
|
+
const SCHEMA_EXPORTS = {
|
|
9
|
+
flow: 'FlowSchema',
|
|
10
|
+
process: 'ProcessSchema',
|
|
11
|
+
lifecyclemodel: 'LifeCycleModelSchema',
|
|
12
|
+
};
|
|
13
|
+
const ENTITY_FACTORY_EXPORTS = {
|
|
14
|
+
flow: 'createFlow',
|
|
15
|
+
process: 'createProcess',
|
|
16
|
+
lifecyclemodel: 'createLifeCycleModel',
|
|
17
|
+
};
|
|
18
|
+
function normalizeType(value) {
|
|
19
|
+
const normalized = value?.trim().toLowerCase();
|
|
20
|
+
if (!normalized) {
|
|
21
|
+
return DEFAULT_TYPE;
|
|
22
|
+
}
|
|
23
|
+
if (normalized === 'auto') {
|
|
24
|
+
return 'auto';
|
|
25
|
+
}
|
|
26
|
+
if (normalized === 'flow' || normalized === 'flows') {
|
|
27
|
+
return 'flow';
|
|
28
|
+
}
|
|
29
|
+
if (normalized === 'process' || normalized === 'processes') {
|
|
30
|
+
return 'process';
|
|
31
|
+
}
|
|
32
|
+
if (normalized === 'lifecyclemodel' ||
|
|
33
|
+
normalized === 'lifecyclemodels' ||
|
|
34
|
+
normalized === 'model' ||
|
|
35
|
+
normalized === 'models') {
|
|
36
|
+
return 'lifecyclemodel';
|
|
37
|
+
}
|
|
38
|
+
throw new CliError('Expected --type to be auto, flow, process, or lifecyclemodel.', {
|
|
39
|
+
code: 'DATASET_VALIDATE_TYPE_INVALID',
|
|
40
|
+
exitCode: 2,
|
|
41
|
+
details: value,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
function schemaForKind(kind, schemas) {
|
|
45
|
+
if (schemas?.[kind]) {
|
|
46
|
+
return {
|
|
47
|
+
validator: 'injected',
|
|
48
|
+
schema: schemas[kind],
|
|
49
|
+
createEntity: null,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
const exportName = SCHEMA_EXPORTS[kind];
|
|
53
|
+
const candidate = tidasSdk[exportName];
|
|
54
|
+
if (!candidate ||
|
|
55
|
+
typeof candidate !== 'object' ||
|
|
56
|
+
typeof candidate.safeParse !== 'function') {
|
|
57
|
+
throw new CliError(`${String(exportName)} is unavailable in @tiangong-lca/tidas-sdk.`, {
|
|
58
|
+
code: 'DATASET_VALIDATE_SCHEMA_UNAVAILABLE',
|
|
59
|
+
exitCode: 2,
|
|
60
|
+
details: { type: kind },
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
const factoryName = ENTITY_FACTORY_EXPORTS[kind];
|
|
64
|
+
const createEntity = tidasSdk[factoryName];
|
|
65
|
+
return {
|
|
66
|
+
validator: `@tiangong-lca/tidas-sdk/${String(exportName)}`,
|
|
67
|
+
schema: candidate,
|
|
68
|
+
createEntity: typeof createEntity === 'function' ? createEntity : null,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
function buildUnsupportedTypeReport(row) {
|
|
72
|
+
return {
|
|
73
|
+
index: row.index,
|
|
74
|
+
id: row.id,
|
|
75
|
+
version: row.version,
|
|
76
|
+
type: row.kind,
|
|
77
|
+
status: 'invalid',
|
|
78
|
+
validator: null,
|
|
79
|
+
issue_count: 1,
|
|
80
|
+
issues: [
|
|
81
|
+
{
|
|
82
|
+
path: '<root>',
|
|
83
|
+
message: 'Could not detect dataset type. Use --type or provide a recognized TIDAS wrapper.',
|
|
84
|
+
code: 'dataset_type_unknown',
|
|
85
|
+
},
|
|
86
|
+
],
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
function validateRow(row, requestedType, schemas) {
|
|
90
|
+
const kind = requestedType === 'auto' ? row.kind : requestedType;
|
|
91
|
+
if (!kind) {
|
|
92
|
+
return buildUnsupportedTypeReport(row);
|
|
93
|
+
}
|
|
94
|
+
const { validator, schema, createEntity } = schemaForKind(kind, schemas);
|
|
95
|
+
const outcome = validateSchemaWithDeepFallback(schema, row.payload, createEntity);
|
|
96
|
+
if (outcome.success) {
|
|
97
|
+
return {
|
|
98
|
+
index: row.index,
|
|
99
|
+
id: row.id,
|
|
100
|
+
version: row.version,
|
|
101
|
+
type: kind,
|
|
102
|
+
status: 'valid',
|
|
103
|
+
validator,
|
|
104
|
+
issue_count: 0,
|
|
105
|
+
issues: [],
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
const issues = outcome.issues.map((issue) => ({
|
|
109
|
+
path: normalizeIssuePath(issue.path),
|
|
110
|
+
message: issue.message ?? 'Validation failed',
|
|
111
|
+
code: issue.code ?? 'custom',
|
|
112
|
+
}));
|
|
113
|
+
return {
|
|
114
|
+
index: row.index,
|
|
115
|
+
id: row.id,
|
|
116
|
+
version: row.version,
|
|
117
|
+
type: kind,
|
|
118
|
+
status: 'invalid',
|
|
119
|
+
validator,
|
|
120
|
+
issue_count: issues.length,
|
|
121
|
+
issues,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
function buildFiles(outDir) {
|
|
125
|
+
if (!outDir) {
|
|
126
|
+
return {
|
|
127
|
+
report: null,
|
|
128
|
+
valid_rows: null,
|
|
129
|
+
invalid_rows: null,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
const resolved = path.resolve(outDir);
|
|
133
|
+
return {
|
|
134
|
+
report: path.join(resolved, 'outputs', 'validation-report.json'),
|
|
135
|
+
valid_rows: path.join(resolved, 'outputs', 'valid-rows.jsonl'),
|
|
136
|
+
invalid_rows: path.join(resolved, 'outputs', 'invalid-rows.jsonl'),
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
function summarizeByType(rows) {
|
|
140
|
+
return {
|
|
141
|
+
flow: rows.filter((row) => row.type === 'flow').length,
|
|
142
|
+
process: rows.filter((row) => row.type === 'process').length,
|
|
143
|
+
lifecyclemodel: rows.filter((row) => row.type === 'lifecyclemodel').length,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
export async function runDatasetValidate(options) {
|
|
147
|
+
const requestedType = normalizeType(options.type);
|
|
148
|
+
const rows = materializeDatasetRows(options.inputPath, options.rawInput);
|
|
149
|
+
const reports = rows.map((row) => validateRow(row, requestedType, options.schemas));
|
|
150
|
+
const invalidRows = reports.filter((row) => row.status === 'invalid');
|
|
151
|
+
const files = buildFiles(options.outDir);
|
|
152
|
+
const report = {
|
|
153
|
+
generated_at_utc: (options.now ?? new Date()).toISOString(),
|
|
154
|
+
input_path: path.resolve(options.inputPath),
|
|
155
|
+
requested_type: requestedType,
|
|
156
|
+
status: invalidRows.length > 0 ? 'completed_with_failures' : 'completed',
|
|
157
|
+
counts: {
|
|
158
|
+
total: reports.length,
|
|
159
|
+
valid: reports.length - invalidRows.length,
|
|
160
|
+
invalid: invalidRows.length,
|
|
161
|
+
by_type: summarizeByType(reports),
|
|
162
|
+
},
|
|
163
|
+
files,
|
|
164
|
+
rows: reports,
|
|
165
|
+
};
|
|
166
|
+
if (files.report) {
|
|
167
|
+
writeJsonArtifact(files.report, report);
|
|
168
|
+
}
|
|
169
|
+
if (files.valid_rows) {
|
|
170
|
+
writeJsonLinesArtifact(files.valid_rows, rows.filter((_, index) => reports[index]?.status === 'valid').map((row) => row.row));
|
|
171
|
+
}
|
|
172
|
+
if (files.invalid_rows) {
|
|
173
|
+
writeJsonLinesArtifact(files.invalid_rows, rows.flatMap((row, index) => reports[index]?.status === 'invalid'
|
|
174
|
+
? [
|
|
175
|
+
{
|
|
176
|
+
row: row.row,
|
|
177
|
+
validation: reports[index],
|
|
178
|
+
},
|
|
179
|
+
]
|
|
180
|
+
: []));
|
|
181
|
+
}
|
|
182
|
+
return report;
|
|
183
|
+
}
|
|
184
|
+
export const __testInternals = {
|
|
185
|
+
ENTITY_FACTORY_EXPORTS,
|
|
186
|
+
SCHEMA_EXPORTS,
|
|
187
|
+
normalizeType,
|
|
188
|
+
schemaForKind,
|
|
189
|
+
validateRow,
|
|
190
|
+
};
|
|
191
|
+
//# sourceMappingURL=dataset-validate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dataset-validate.js","sourceRoot":"","sources":["../../../src/lib/dataset-validate.ts"],"names":[],"mappings":"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","sourcesContent":["import path from 'node:path';\nimport * as tidasSdk from '@tiangong-lca/tidas-sdk';\nimport { writeJsonArtifact, writeJsonLinesArtifact } from './artifacts.js';\nimport { CliError } from './errors.js';\nimport { materializeDatasetRows, type DatasetKind, type DatasetRowInput } from './dataset-local.js';\nimport {\n normalizeIssuePath,\n type SafeParseSchema,\n type SdkValidationFactory,\n validateSchemaWithDeepFallback,\n} from './tidas-sdk-validation.js';\n\ntype DatasetValidateType = 'auto' | DatasetKind;\n\nexport type DatasetValidateIssue = {\n path: string;\n message: string;\n code: string;\n};\n\nexport type DatasetValidateRowReport = {\n index: number;\n id: string | null;\n version: string | null;\n type: DatasetKind | null;\n status: 'valid' | 'invalid';\n validator: string | null;\n issue_count: number;\n issues: DatasetValidateIssue[];\n};\n\nexport type DatasetValidateReport = {\n generated_at_utc: string;\n input_path: string;\n requested_type: DatasetValidateType;\n status: 'completed' | 'completed_with_failures';\n counts: {\n total: number;\n valid: number;\n invalid: number;\n by_type: Record<DatasetKind, number>;\n };\n files: {\n report: string | null;\n valid_rows: string | null;\n invalid_rows: string | null;\n };\n rows: DatasetValidateRowReport[];\n};\n\nexport type RunDatasetValidateOptions = {\n inputPath: string;\n type?: string | null;\n outDir?: string | null;\n rawInput?: unknown;\n now?: Date;\n schemas?: Partial<Record<DatasetKind, SafeParseSchema>>;\n};\n\nconst DEFAULT_TYPE: DatasetValidateType = 'auto';\n\nconst SCHEMA_EXPORTS: Record<DatasetKind, keyof typeof tidasSdk> = {\n flow: 'FlowSchema' as keyof typeof tidasSdk,\n process: 'ProcessSchema' as keyof typeof tidasSdk,\n lifecyclemodel: 'LifeCycleModelSchema' as keyof typeof tidasSdk,\n};\n\nconst ENTITY_FACTORY_EXPORTS: Record<DatasetKind, keyof typeof tidasSdk> = {\n flow: 'createFlow' as keyof typeof tidasSdk,\n process: 'createProcess' as keyof typeof tidasSdk,\n lifecyclemodel: 'createLifeCycleModel' as keyof typeof tidasSdk,\n};\n\nfunction normalizeType(value: string | null | undefined): DatasetValidateType {\n const normalized = value?.trim().toLowerCase();\n if (!normalized) {\n return DEFAULT_TYPE;\n }\n if (normalized === 'auto') {\n return 'auto';\n }\n if (normalized === 'flow' || normalized === 'flows') {\n return 'flow';\n }\n if (normalized === 'process' || normalized === 'processes') {\n return 'process';\n }\n if (\n normalized === 'lifecyclemodel' ||\n normalized === 'lifecyclemodels' ||\n normalized === 'model' ||\n normalized === 'models'\n ) {\n return 'lifecyclemodel';\n }\n throw new CliError('Expected --type to be auto, flow, process, or lifecyclemodel.', {\n code: 'DATASET_VALIDATE_TYPE_INVALID',\n exitCode: 2,\n details: value,\n });\n}\n\nfunction schemaForKind(\n kind: DatasetKind,\n schemas: Partial<Record<DatasetKind, SafeParseSchema>> | undefined,\n): { validator: string; schema: SafeParseSchema; createEntity: SdkValidationFactory | null } {\n if (schemas?.[kind]) {\n return {\n validator: 'injected',\n schema: schemas[kind],\n createEntity: null,\n };\n }\n\n const exportName = SCHEMA_EXPORTS[kind];\n const candidate = (tidasSdk as Record<string, unknown>)[exportName];\n if (\n !candidate ||\n typeof candidate !== 'object' ||\n typeof (candidate as SafeParseSchema).safeParse !== 'function'\n ) {\n throw new CliError(`${String(exportName)} is unavailable in @tiangong-lca/tidas-sdk.`, {\n code: 'DATASET_VALIDATE_SCHEMA_UNAVAILABLE',\n exitCode: 2,\n details: { type: kind },\n });\n }\n\n const factoryName = ENTITY_FACTORY_EXPORTS[kind];\n const createEntity = (tidasSdk as Record<string, unknown>)[factoryName];\n\n return {\n validator: `@tiangong-lca/tidas-sdk/${String(exportName)}`,\n schema: candidate as SafeParseSchema,\n createEntity:\n typeof createEntity === 'function' ? (createEntity as SdkValidationFactory) : null,\n };\n}\n\nfunction buildUnsupportedTypeReport(row: DatasetRowInput): DatasetValidateRowReport {\n return {\n index: row.index,\n id: row.id,\n version: row.version,\n type: row.kind,\n status: 'invalid',\n validator: null,\n issue_count: 1,\n issues: [\n {\n path: '<root>',\n message: 'Could not detect dataset type. Use --type or provide a recognized TIDAS wrapper.',\n code: 'dataset_type_unknown',\n },\n ],\n };\n}\n\nfunction validateRow(\n row: DatasetRowInput,\n requestedType: DatasetValidateType,\n schemas: Partial<Record<DatasetKind, SafeParseSchema>> | undefined,\n): DatasetValidateRowReport {\n const kind = requestedType === 'auto' ? row.kind : requestedType;\n if (!kind) {\n return buildUnsupportedTypeReport(row);\n }\n\n const { validator, schema, createEntity } = schemaForKind(kind, schemas);\n const outcome = validateSchemaWithDeepFallback(schema, row.payload, createEntity);\n if (outcome.success) {\n return {\n index: row.index,\n id: row.id,\n version: row.version,\n type: kind,\n status: 'valid',\n validator,\n issue_count: 0,\n issues: [],\n };\n }\n\n const issues = outcome.issues.map((issue) => ({\n path: normalizeIssuePath(issue.path),\n message: issue.message ?? 'Validation failed',\n code: issue.code ?? 'custom',\n }));\n\n return {\n index: row.index,\n id: row.id,\n version: row.version,\n type: kind,\n status: 'invalid',\n validator,\n issue_count: issues.length,\n issues,\n };\n}\n\nfunction buildFiles(outDir: string | null | undefined): DatasetValidateReport['files'] {\n if (!outDir) {\n return {\n report: null,\n valid_rows: null,\n invalid_rows: null,\n };\n }\n\n const resolved = path.resolve(outDir);\n return {\n report: path.join(resolved, 'outputs', 'validation-report.json'),\n valid_rows: path.join(resolved, 'outputs', 'valid-rows.jsonl'),\n invalid_rows: path.join(resolved, 'outputs', 'invalid-rows.jsonl'),\n };\n}\n\nfunction summarizeByType(rows: DatasetValidateRowReport[]): Record<DatasetKind, number> {\n return {\n flow: rows.filter((row) => row.type === 'flow').length,\n process: rows.filter((row) => row.type === 'process').length,\n lifecyclemodel: rows.filter((row) => row.type === 'lifecyclemodel').length,\n };\n}\n\nexport async function runDatasetValidate(\n options: RunDatasetValidateOptions,\n): Promise<DatasetValidateReport> {\n const requestedType = normalizeType(options.type);\n const rows = materializeDatasetRows(options.inputPath, options.rawInput);\n const reports = rows.map((row) => validateRow(row, requestedType, options.schemas));\n const invalidRows = reports.filter((row) => row.status === 'invalid');\n const files = buildFiles(options.outDir);\n\n const report: DatasetValidateReport = {\n generated_at_utc: (options.now ?? new Date()).toISOString(),\n input_path: path.resolve(options.inputPath),\n requested_type: requestedType,\n status: invalidRows.length > 0 ? 'completed_with_failures' : 'completed',\n counts: {\n total: reports.length,\n valid: reports.length - invalidRows.length,\n invalid: invalidRows.length,\n by_type: summarizeByType(reports),\n },\n files,\n rows: reports,\n };\n\n if (files.report) {\n writeJsonArtifact(files.report, report);\n }\n if (files.valid_rows) {\n writeJsonLinesArtifact(\n files.valid_rows,\n rows.filter((_, index) => reports[index]?.status === 'valid').map((row) => row.row),\n );\n }\n if (files.invalid_rows) {\n writeJsonLinesArtifact(\n files.invalid_rows,\n rows.flatMap((row, index) =>\n reports[index]?.status === 'invalid'\n ? [\n {\n row: row.row,\n validation: reports[index],\n },\n ]\n : [],\n ),\n );\n }\n\n return report;\n}\n\nexport const __testInternals = {\n ENTITY_FACTORY_EXPORTS,\n SCHEMA_EXPORTS,\n normalizeType,\n schemaForKind,\n validateRow,\n};\n"]}
|
|
@@ -6,6 +6,7 @@ import { fileURLToPath } from 'node:url';
|
|
|
6
6
|
import { writeJsonArtifact, writeJsonLinesArtifact, writeTextArtifact } from './artifacts.js';
|
|
7
7
|
import { CliError } from './errors.js';
|
|
8
8
|
import { coerceText, deepGet, extractFlowRecord, flowDatasetFromRow, isRecord, listify, loadRowsFromFile, normalizeText, } from './flow-governance.js';
|
|
9
|
+
import { validateEntityWithDeepFallback, } from './tidas-sdk-validation.js';
|
|
9
10
|
import { resolveRepoRootFrom } from './validation.js';
|
|
10
11
|
const EMERGY_TEXT_KEYWORDS = [
|
|
11
12
|
'emergy',
|
|
@@ -787,16 +788,7 @@ function formatValidationDetails(validation) {
|
|
|
787
788
|
}
|
|
788
789
|
function evaluateProcessSdkValidation(payload, createProcess) {
|
|
789
790
|
try {
|
|
790
|
-
const
|
|
791
|
-
mode: 'strict',
|
|
792
|
-
throwOnError: false,
|
|
793
|
-
deepValidation: true,
|
|
794
|
-
});
|
|
795
|
-
const validation = typeof entity?.validateEnhanced === 'function'
|
|
796
|
-
? entity.validateEnhanced()
|
|
797
|
-
: typeof entity?.validate === 'function'
|
|
798
|
-
? entity.validate()
|
|
799
|
-
: null;
|
|
791
|
+
const validation = validateEntityWithDeepFallback(payload, createProcess);
|
|
800
792
|
if (isRecord(validation) && validation.success === true) {
|
|
801
793
|
return null;
|
|
802
794
|
}
|