@tiangong-lca/cli 0.0.7 → 0.0.9
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 +97 -16
- package/dist/src/cli.js +1429 -131
- package/dist/src/cli.js.map +1 -1
- package/dist/src/lib/dataset-author.js +100 -0
- package/dist/src/lib/dataset-author.js.map +1 -0
- package/dist/src/lib/dataset-bilingual.js +545 -0
- package/dist/src/lib/dataset-bilingual.js.map +1 -0
- package/dist/src/lib/dataset-contract.js +350 -0
- package/dist/src/lib/dataset-contract.js.map +1 -0
- package/dist/src/lib/dataset-evidence-search.js +636 -0
- package/dist/src/lib/dataset-evidence-search.js.map +1 -0
- package/dist/src/lib/dataset-import-lca.js +171 -0
- package/dist/src/lib/dataset-import-lca.js.map +1 -0
- package/dist/src/lib/dataset-remote-refresh.js +166 -0
- package/dist/src/lib/dataset-remote-refresh.js.map +1 -0
- package/dist/src/lib/dataset-remote-verify.js +543 -0
- package/dist/src/lib/dataset-remote-verify.js.map +1 -0
- package/dist/src/lib/dataset-validate.js +63 -7
- package/dist/src/lib/dataset-validate.js.map +1 -1
- package/dist/src/lib/flow-fetch-rows.js +12 -12
- package/dist/src/lib/flow-fetch-rows.js.map +1 -1
- package/dist/src/lib/flow-payload-validation.js +51 -0
- package/dist/src/lib/flow-payload-validation.js.map +1 -0
- package/dist/src/lib/flow-publish-reviewed-data.js +16 -0
- package/dist/src/lib/flow-publish-reviewed-data.js.map +1 -1
- package/dist/src/lib/flow-publish-version.js +182 -12
- package/dist/src/lib/flow-publish-version.js.map +1 -1
- package/dist/src/lib/{review-flow.js → flow-qa.js} +86 -28
- package/dist/src/lib/flow-qa.js.map +1 -0
- package/dist/src/lib/identity-preflight.js +1021 -0
- package/dist/src/lib/identity-preflight.js.map +1 -0
- package/dist/src/lib/{review-lifecyclemodel.js → lifecyclemodel-qa.js} +54 -54
- package/dist/src/lib/lifecyclemodel-qa.js.map +1 -0
- package/dist/src/lib/process-auto-build.js +147 -0
- package/dist/src/lib/process-auto-build.js.map +1 -1
- package/dist/src/lib/process-dedup-review.js +51 -0
- package/dist/src/lib/process-dedup-review.js.map +1 -1
- package/dist/src/lib/process-flow-build-plan.js +1071 -0
- package/dist/src/lib/process-flow-build-plan.js.map +1 -0
- package/dist/src/lib/process-payload-validation.js +14 -7
- package/dist/src/lib/process-payload-validation.js.map +1 -1
- package/dist/src/lib/process-publish-build.js +122 -4
- package/dist/src/lib/process-publish-build.js.map +1 -1
- package/dist/src/lib/{review-process.js → process-qa.js} +259 -117
- package/dist/src/lib/process-qa.js.map +1 -0
- package/dist/src/lib/process-refresh-references.js +19 -10
- package/dist/src/lib/process-refresh-references.js.map +1 -1
- package/dist/src/lib/process-required-fields.js +810 -0
- package/dist/src/lib/process-required-fields.js.map +1 -0
- package/dist/src/lib/process-save-draft-run.js +4 -1
- package/dist/src/lib/process-save-draft-run.js.map +1 -1
- package/dist/src/lib/publish.js +100 -0
- package/dist/src/lib/publish.js.map +1 -1
- package/dist/src/lib/runtime-rulesets.js +283 -0
- package/dist/src/lib/runtime-rulesets.js.map +1 -0
- package/package.json +2 -2
- package/dist/src/lib/review-flow.js.map +0 -1
- package/dist/src/lib/review-lifecyclemodel.js.map +0 -1
- package/dist/src/lib/review-process.js.map +0 -1
|
@@ -2,8 +2,9 @@ import path from 'node:path';
|
|
|
2
2
|
import * as tidasSdk from '@tiangong-lca/tidas-sdk';
|
|
3
3
|
import { writeJsonArtifact, writeJsonLinesArtifact } from './artifacts.js';
|
|
4
4
|
import { CliError } from './errors.js';
|
|
5
|
-
import { materializeDatasetRows } from './dataset-local.js';
|
|
5
|
+
import { isRecord, materializeDatasetRows, } from './dataset-local.js';
|
|
6
6
|
import { normalizeIssuePath, validateSchemaWithDeepFallback, } from './tidas-sdk-validation.js';
|
|
7
|
+
import { collectProcessPlaceholderIssues, collectProcessRequiredFieldIssues, } from './process-required-fields.js';
|
|
7
8
|
const DEFAULT_TYPE = 'auto';
|
|
8
9
|
const SCHEMA_EXPORTS = {
|
|
9
10
|
flow: 'FlowSchema',
|
|
@@ -15,6 +16,52 @@ const ENTITY_FACTORY_EXPORTS = {
|
|
|
15
16
|
process: 'createProcess',
|
|
16
17
|
lifecyclemodel: 'createLifeCycleModel',
|
|
17
18
|
};
|
|
19
|
+
function issuePath(pathSegments) {
|
|
20
|
+
return pathSegments.length > 0 ? pathSegments.map(String).join('.') : '<root>';
|
|
21
|
+
}
|
|
22
|
+
function collectImportContentIssuesFromValue(value, pathSegments, issues) {
|
|
23
|
+
if (typeof value === 'string') {
|
|
24
|
+
const normalized = value.trim().toLowerCase();
|
|
25
|
+
if ((pathSegments.at(-1) === 'common:referenceYear' && normalized === '9999') ||
|
|
26
|
+
normalized.includes('tidas_import_placeholder') ||
|
|
27
|
+
normalized.includes('tidas_import_trace_v1') ||
|
|
28
|
+
normalized.includes('not declared in source package') ||
|
|
29
|
+
normalized.includes('source package metadata not declared') ||
|
|
30
|
+
normalized === '<null>' ||
|
|
31
|
+
/(^|[\s"'`])(?:\/users\/|\/home\/|[a-z]:\\)/iu.test(value)) {
|
|
32
|
+
issues.push({
|
|
33
|
+
path: issuePath(pathSegments),
|
|
34
|
+
message: 'Dataset payload contains import placeholder, trace, local path, or sentinel content that must be repaired before import.',
|
|
35
|
+
code: 'dataset_import_placeholder_content',
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
if (typeof value === 'number') {
|
|
41
|
+
if (pathSegments.at(-1) === 'common:referenceYear' && value === 9999) {
|
|
42
|
+
issues.push({
|
|
43
|
+
path: issuePath(pathSegments),
|
|
44
|
+
message: 'Dataset payload contains import placeholder, trace, local path, or sentinel content that must be repaired before import.',
|
|
45
|
+
code: 'dataset_import_placeholder_content',
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (Array.isArray(value)) {
|
|
51
|
+
value.forEach((item, index) => collectImportContentIssuesFromValue(item, [...pathSegments, index], issues));
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
if (isRecord(value)) {
|
|
55
|
+
for (const [key, child] of Object.entries(value)) {
|
|
56
|
+
collectImportContentIssuesFromValue(child, [...pathSegments, key], issues);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function collectImportContentIssues(payload) {
|
|
61
|
+
const issues = [];
|
|
62
|
+
collectImportContentIssuesFromValue(payload, [], issues);
|
|
63
|
+
return issues;
|
|
64
|
+
}
|
|
18
65
|
function normalizeType(value) {
|
|
19
66
|
const normalized = value?.trim().toLowerCase();
|
|
20
67
|
if (!normalized) {
|
|
@@ -93,7 +140,11 @@ function validateRow(row, requestedType, schemas) {
|
|
|
93
140
|
}
|
|
94
141
|
const { validator, schema, createEntity } = schemaForKind(kind, schemas);
|
|
95
142
|
const outcome = validateSchemaWithDeepFallback(schema, row.payload, createEntity);
|
|
96
|
-
|
|
143
|
+
const requiredFieldIssues = kind === 'process' ? collectProcessRequiredFieldIssues(row.payload) : [];
|
|
144
|
+
const placeholderIssues = kind === 'process'
|
|
145
|
+
? collectProcessPlaceholderIssues(row.payload)
|
|
146
|
+
: collectImportContentIssues(row.payload);
|
|
147
|
+
if (outcome.success && requiredFieldIssues.length === 0 && placeholderIssues.length === 0) {
|
|
97
148
|
return {
|
|
98
149
|
index: row.index,
|
|
99
150
|
id: row.id,
|
|
@@ -105,11 +156,15 @@ function validateRow(row, requestedType, schemas) {
|
|
|
105
156
|
issues: [],
|
|
106
157
|
};
|
|
107
158
|
}
|
|
108
|
-
const issues =
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
159
|
+
const issues = [
|
|
160
|
+
...outcome.issues.map((issue) => ({
|
|
161
|
+
path: normalizeIssuePath(issue.path),
|
|
162
|
+
message: issue.message ?? 'Validation failed',
|
|
163
|
+
code: issue.code ?? 'custom',
|
|
164
|
+
})),
|
|
165
|
+
...requiredFieldIssues,
|
|
166
|
+
...placeholderIssues,
|
|
167
|
+
];
|
|
113
168
|
return {
|
|
114
169
|
index: row.index,
|
|
115
170
|
id: row.id,
|
|
@@ -184,6 +239,7 @@ export async function runDatasetValidate(options) {
|
|
|
184
239
|
export const __testInternals = {
|
|
185
240
|
ENTITY_FACTORY_EXPORTS,
|
|
186
241
|
SCHEMA_EXPORTS,
|
|
242
|
+
collectImportContentIssues,
|
|
187
243
|
normalizeType,
|
|
188
244
|
schemaForKind,
|
|
189
245
|
validateRow,
|
|
@@ -1 +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"]}
|
|
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 {\n isRecord,\n materializeDatasetRows,\n type DatasetKind,\n type DatasetRowInput,\n} from './dataset-local.js';\nimport {\n normalizeIssuePath,\n type SafeParseSchema,\n type SdkValidationFactory,\n validateSchemaWithDeepFallback,\n} from './tidas-sdk-validation.js';\nimport {\n collectProcessPlaceholderIssues,\n collectProcessRequiredFieldIssues,\n} from './process-required-fields.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 issuePath(pathSegments: Array<string | number>): string {\n return pathSegments.length > 0 ? pathSegments.map(String).join('.') : '<root>';\n}\n\nfunction collectImportContentIssuesFromValue(\n value: unknown,\n pathSegments: Array<string | number>,\n issues: DatasetValidateIssue[],\n): void {\n if (typeof value === 'string') {\n const normalized = value.trim().toLowerCase();\n if (\n (pathSegments.at(-1) === 'common:referenceYear' && normalized === '9999') ||\n normalized.includes('tidas_import_placeholder') ||\n normalized.includes('tidas_import_trace_v1') ||\n normalized.includes('not declared in source package') ||\n normalized.includes('source package metadata not declared') ||\n normalized === '<null>' ||\n /(^|[\\s\"'`])(?:\\/users\\/|\\/home\\/|[a-z]:\\\\)/iu.test(value)\n ) {\n issues.push({\n path: issuePath(pathSegments),\n message:\n 'Dataset payload contains import placeholder, trace, local path, or sentinel content that must be repaired before import.',\n code: 'dataset_import_placeholder_content',\n });\n }\n return;\n }\n\n if (typeof value === 'number') {\n if (pathSegments.at(-1) === 'common:referenceYear' && value === 9999) {\n issues.push({\n path: issuePath(pathSegments),\n message:\n 'Dataset payload contains import placeholder, trace, local path, or sentinel content that must be repaired before import.',\n code: 'dataset_import_placeholder_content',\n });\n }\n return;\n }\n\n if (Array.isArray(value)) {\n value.forEach((item, index) =>\n collectImportContentIssuesFromValue(item, [...pathSegments, index], issues),\n );\n return;\n }\n\n if (isRecord(value)) {\n for (const [key, child] of Object.entries(value)) {\n collectImportContentIssuesFromValue(child, [...pathSegments, key], issues);\n }\n }\n}\n\nfunction collectImportContentIssues(payload: unknown): DatasetValidateIssue[] {\n const issues: DatasetValidateIssue[] = [];\n collectImportContentIssuesFromValue(payload, [], issues);\n return issues;\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 const requiredFieldIssues =\n kind === 'process' ? collectProcessRequiredFieldIssues(row.payload) : [];\n const placeholderIssues =\n kind === 'process'\n ? collectProcessPlaceholderIssues(row.payload)\n : collectImportContentIssues(row.payload);\n if (outcome.success && requiredFieldIssues.length === 0 && placeholderIssues.length === 0) {\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 = [\n ...outcome.issues.map((issue) => ({\n path: normalizeIssuePath(issue.path),\n message: issue.message ?? 'Validation failed',\n code: issue.code ?? 'custom',\n })),\n ...requiredFieldIssues,\n ...placeholderIssues,\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 collectImportContentIssues,\n normalizeType,\n schemaForKind,\n validateRow,\n};\n"]}
|
|
@@ -70,7 +70,7 @@ function buildMaterializedRow(lookup, context) {
|
|
|
70
70
|
_materialization: context,
|
|
71
71
|
};
|
|
72
72
|
}
|
|
73
|
-
function
|
|
73
|
+
function buildQaInputRow(row, flowKey, contexts) {
|
|
74
74
|
return {
|
|
75
75
|
...row,
|
|
76
76
|
_materialization: {
|
|
@@ -113,7 +113,7 @@ export async function runFlowFetchRows(options) {
|
|
|
113
113
|
const resolvedRowArtifacts = [];
|
|
114
114
|
const missingRefs = [];
|
|
115
115
|
const ambiguousRefs = [];
|
|
116
|
-
const
|
|
116
|
+
const qaInputByKey = new Map();
|
|
117
117
|
const resolutionCounts = {
|
|
118
118
|
remote_supabase_exact: 0,
|
|
119
119
|
remote_supabase_latest: 0,
|
|
@@ -173,32 +173,32 @@ export async function runFlowFetchRows(options) {
|
|
|
173
173
|
const materializedRow = buildMaterializedRow(lookup, context);
|
|
174
174
|
resolvedRowArtifacts.push(materializedRow);
|
|
175
175
|
const flowKey = `${resolvedFlowId}@${resolvedVersion}`;
|
|
176
|
-
const existing =
|
|
176
|
+
const existing = qaInputByKey.get(flowKey);
|
|
177
177
|
if (existing) {
|
|
178
178
|
existing.contexts.push(context);
|
|
179
179
|
}
|
|
180
180
|
else {
|
|
181
|
-
|
|
181
|
+
qaInputByKey.set(flowKey, {
|
|
182
182
|
row: materializedRow,
|
|
183
183
|
contexts: [context],
|
|
184
184
|
});
|
|
185
185
|
}
|
|
186
186
|
}
|
|
187
|
-
const
|
|
187
|
+
const qaInputRows = [...qaInputByKey.entries()]
|
|
188
188
|
.sort(([left], [right]) => left.localeCompare(right))
|
|
189
|
-
.map(([flowKey, entry]) =>
|
|
190
|
-
const
|
|
189
|
+
.map(([flowKey, entry]) => buildQaInputRow(entry.row, flowKey, entry.contexts));
|
|
190
|
+
const duplicateQaInputRowsCollapsed = resolvedRowArtifacts.length - qaInputRows.length;
|
|
191
191
|
const unresolvedRefCount = missingRefs.length + ambiguousRefs.length;
|
|
192
192
|
const status = unresolvedRefCount > 0
|
|
193
193
|
? 'completed_flow_row_materialization_with_gaps'
|
|
194
194
|
: 'completed_flow_row_materialization';
|
|
195
195
|
const resolvedRowsPath = path.join(resolvedOutDir, 'resolved-flow-rows.jsonl');
|
|
196
|
-
const
|
|
196
|
+
const qaInputRowsPath = path.join(resolvedOutDir, 'qa-input-rows.jsonl');
|
|
197
197
|
const missingRefsPath = path.join(resolvedOutDir, 'missing-flow-refs.jsonl');
|
|
198
198
|
const ambiguousRefsPath = path.join(resolvedOutDir, 'ambiguous-flow-refs.jsonl');
|
|
199
199
|
const summaryPath = path.join(resolvedOutDir, 'fetch-summary.json');
|
|
200
200
|
writeJsonLinesArtifact(resolvedRowsPath, resolvedRowArtifacts);
|
|
201
|
-
writeJsonLinesArtifact(
|
|
201
|
+
writeJsonLinesArtifact(qaInputRowsPath, qaInputRows);
|
|
202
202
|
writeJsonLinesArtifact(missingRefsPath, missingRefs);
|
|
203
203
|
writeJsonLinesArtifact(ambiguousRefsPath, ambiguousRefs);
|
|
204
204
|
const report = {
|
|
@@ -210,14 +210,14 @@ export async function runFlowFetchRows(options) {
|
|
|
210
210
|
allow_latest_fallback: allowLatestFallback,
|
|
211
211
|
requested_ref_count: rows.length,
|
|
212
212
|
resolved_ref_count: resolvedRowArtifacts.length,
|
|
213
|
-
|
|
214
|
-
|
|
213
|
+
qa_input_row_count: qaInputRows.length,
|
|
214
|
+
duplicate_qa_input_rows_collapsed: duplicateQaInputRowsCollapsed,
|
|
215
215
|
missing_ref_count: missingRefs.length,
|
|
216
216
|
ambiguous_ref_count: ambiguousRefs.length,
|
|
217
217
|
resolution_counts: resolutionCounts,
|
|
218
218
|
files: {
|
|
219
219
|
resolved_flow_rows: resolvedRowsPath,
|
|
220
|
-
|
|
220
|
+
qa_input_rows: qaInputRowsPath,
|
|
221
221
|
fetch_summary: summaryPath,
|
|
222
222
|
missing_flow_refs: missingRefsPath,
|
|
223
223
|
ambiguous_flow_refs: ambiguousRefsPath,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flow-fetch-rows.js","sourceRoot":"","sources":["../../../src/lib/flow-fetch-rows.ts"],"names":[],"mappings":"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","sourcesContent":["import path from 'node:path';\nimport { writeJsonArtifact, writeJsonLinesArtifact } from './artifacts.js';\nimport { CliError } from './errors.js';\nimport { loadRowsFromFile, type JsonRecord } from './flow-governance.js';\nimport type { FetchLike } from './http.js';\nimport {\n fetchOneFlowRow,\n normalizeSupabaseFlowPayload,\n type SupabaseFlowLookup,\n} from './flow-read.js';\nimport { requireSupabaseRestRuntime } from './supabase-rest.js';\nimport { createSupabaseDataRuntime } from './supabase-session.js';\n\nconst FLOW_FETCH_ROWS_TIMEOUT_MS = 10_000;\n\ntype FlowFetchRef = {\n id: string;\n version: string | null;\n userId: string | null;\n stateCode: number | null;\n clusterId: string | null;\n source: string | null;\n};\n\ntype FlowFetchMaterializationContext = {\n input_index: number;\n requested_ref: {\n id: string;\n version: string | null;\n user_id: string | null;\n state_code: number | null;\n cluster_id: string | null;\n source: string | null;\n };\n resolution: SupabaseFlowLookup['resolution'];\n source_url: string;\n resolved_flow_id: string;\n resolved_version: string;\n};\n\ntype FlowFetchSummaryStatus =\n | 'completed_flow_row_materialization'\n | 'completed_flow_row_materialization_with_gaps';\n\nexport type RunFlowFetchRowsOptions = {\n refsFile: string;\n outDir: string;\n allowLatestFallback?: boolean;\n env?: NodeJS.ProcessEnv;\n fetchImpl?: FetchLike;\n timeoutMs?: number;\n now?: Date;\n};\n\nexport type FlowFetchRowsReport = {\n schema_version: 1;\n generated_at_utc: string;\n status: FlowFetchSummaryStatus;\n refs_file: string;\n out_dir: string;\n allow_latest_fallback: boolean;\n requested_ref_count: number;\n resolved_ref_count: number;\n review_input_row_count: number;\n duplicate_review_input_rows_collapsed: number;\n missing_ref_count: number;\n ambiguous_ref_count: number;\n resolution_counts: Record<SupabaseFlowLookup['resolution'], number>;\n files: {\n resolved_flow_rows: string;\n review_input_rows: string;\n fetch_summary: string;\n missing_flow_refs: string;\n ambiguous_flow_refs: string;\n };\n};\n\nfunction normalizeToken(value: unknown): string | null {\n if (value === undefined || value === null) {\n return null;\n }\n\n const trimmed = String(value).trim();\n return trimmed ? trimmed : null;\n}\n\nfunction normalizeOptionalNonNegativeInteger(\n value: unknown,\n label: string,\n code: string,\n): number | null {\n if (value === undefined || value === null || value === '') {\n return null;\n }\n\n const parsed =\n typeof value === 'number' && Number.isInteger(value)\n ? value\n : Number.parseInt(String(value), 10);\n if (!Number.isInteger(parsed) || parsed < 0) {\n throw new CliError(`Expected ${label} to be a non-negative integer.`, {\n code,\n exitCode: 2,\n details: value,\n });\n }\n return parsed;\n}\n\nfunction normalizeFlowFetchRef(row: JsonRecord, index: number): FlowFetchRef {\n const id = normalizeToken(row.id);\n if (!id) {\n throw new CliError(`Flow ref row ${index + 1} is missing required id.`, {\n code: 'FLOW_FETCH_ROWS_REF_ID_REQUIRED',\n exitCode: 2,\n details: row,\n });\n }\n\n return {\n id,\n version: normalizeToken(row.version),\n userId: normalizeToken(row.user_id ?? row.userId),\n stateCode: normalizeOptionalNonNegativeInteger(\n row.state_code ?? row.stateCode,\n 'flow ref state_code',\n 'FLOW_FETCH_ROWS_INVALID_STATE_CODE',\n ),\n clusterId: normalizeToken(row.cluster_id ?? row.clusterId),\n source: normalizeToken(row.source),\n };\n}\n\nfunction toRequestedRefSummary(\n ref: FlowFetchRef,\n): FlowFetchMaterializationContext['requested_ref'] {\n return {\n id: ref.id,\n version: ref.version,\n user_id: ref.userId,\n state_code: ref.stateCode,\n cluster_id: ref.clusterId,\n source: ref.source,\n };\n}\n\nfunction buildMaterializedRow(\n lookup: SupabaseFlowLookup,\n context: FlowFetchMaterializationContext,\n): JsonRecord {\n const resolvedFlowId = lookup.row.id || context.requested_ref.id;\n const resolvedVersion = lookup.row.version || context.requested_ref.version || '';\n\n return {\n id: resolvedFlowId,\n version: resolvedVersion,\n user_id: lookup.row.user_id,\n state_code: lookup.row.state_code,\n modified_at: lookup.row.modified_at,\n json: normalizeSupabaseFlowPayload(lookup.row.json, `${resolvedFlowId}@${resolvedVersion}`),\n _materialization: context,\n };\n}\n\nfunction buildReviewInputRow(\n row: JsonRecord,\n flowKey: string,\n contexts: FlowFetchMaterializationContext[],\n): JsonRecord {\n return {\n ...row,\n _materialization: {\n flow_key: flowKey,\n materialized_ref_count: contexts.length,\n materialized_from_refs: contexts,\n },\n };\n}\n\nfunction nowIso(now: Date = new Date()): string {\n return now.toISOString();\n}\n\nexport async function runFlowFetchRows(\n options: RunFlowFetchRowsOptions,\n): Promise<FlowFetchRowsReport> {\n const refsFile = normalizeToken(options.refsFile);\n if (!refsFile) {\n throw new CliError('Missing required --refs-file value.', {\n code: 'FLOW_FETCH_ROWS_REFS_FILE_REQUIRED',\n exitCode: 2,\n });\n }\n\n const outDir = normalizeToken(options.outDir);\n if (!outDir) {\n throw new CliError('Missing required --out-dir value.', {\n code: 'FLOW_FETCH_ROWS_OUT_DIR_REQUIRED',\n exitCode: 2,\n });\n }\n\n const resolvedRefsFile = path.resolve(refsFile);\n const resolvedOutDir = path.resolve(outDir);\n const allowLatestFallback = options.allowLatestFallback !== false;\n const rows = loadRowsFromFile(resolvedRefsFile);\n\n const fetchImpl = options.fetchImpl ?? (fetch as FetchLike);\n const timeoutMs = options.timeoutMs ?? FLOW_FETCH_ROWS_TIMEOUT_MS;\n const runtime = createSupabaseDataRuntime({\n runtime: requireSupabaseRestRuntime(options.env ?? process.env),\n fetchImpl,\n timeoutMs,\n now: options.now,\n });\n\n const resolvedRowArtifacts: JsonRecord[] = [];\n const missingRefs: JsonRecord[] = [];\n const ambiguousRefs: JsonRecord[] = [];\n const reviewInputByKey = new Map<\n string,\n { row: JsonRecord; contexts: FlowFetchMaterializationContext[] }\n >();\n const resolutionCounts: FlowFetchRowsReport['resolution_counts'] = {\n remote_supabase_exact: 0,\n remote_supabase_latest: 0,\n remote_supabase_latest_fallback: 0,\n };\n\n for (let index = 0; index < rows.length; index += 1) {\n const ref = normalizeFlowFetchRef(rows[index] as JsonRecord, index);\n const requestedRef = toRequestedRefSummary(ref);\n\n let lookup: SupabaseFlowLookup | null;\n try {\n lookup = await fetchOneFlowRow({\n runtime,\n id: ref.id,\n version: ref.version,\n userId: ref.userId,\n stateCode: ref.stateCode,\n timeoutMs,\n fetchImpl,\n fallbackToLatest: allowLatestFallback && ref.version !== null,\n });\n } catch (error) {\n if (error instanceof CliError && error.code === 'FLOW_GET_AMBIGUOUS') {\n ambiguousRefs.push({\n input_index: index,\n requested_ref: requestedRef,\n code: error.code,\n message: error.message,\n details: error.details,\n });\n continue;\n }\n throw error;\n }\n\n if (!lookup) {\n missingRefs.push({\n input_index: index,\n requested_ref: requestedRef,\n code: 'FLOW_GET_NOT_FOUND',\n message: ref.version\n ? `Could not resolve flow dataset for ${ref.id}@${ref.version}.`\n : `Could not resolve flow dataset for ${ref.id}.`,\n });\n continue;\n }\n\n resolutionCounts[lookup.resolution] += 1;\n const resolvedFlowId = lookup.row.id || ref.id;\n const resolvedVersion = lookup.row.version || ref.version || '';\n const context: FlowFetchMaterializationContext = {\n input_index: index,\n requested_ref: requestedRef,\n resolution: lookup.resolution,\n source_url: lookup.sourceUrl,\n resolved_flow_id: resolvedFlowId,\n resolved_version: resolvedVersion,\n };\n const materializedRow = buildMaterializedRow(lookup, context);\n resolvedRowArtifacts.push(materializedRow);\n\n const flowKey = `${resolvedFlowId}@${resolvedVersion}`;\n const existing = reviewInputByKey.get(flowKey);\n if (existing) {\n existing.contexts.push(context);\n } else {\n reviewInputByKey.set(flowKey, {\n row: materializedRow,\n contexts: [context],\n });\n }\n }\n\n const reviewInputRows = [...reviewInputByKey.entries()]\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([flowKey, entry]) => buildReviewInputRow(entry.row, flowKey, entry.contexts));\n\n const duplicateReviewInputRowsCollapsed = resolvedRowArtifacts.length - reviewInputRows.length;\n const unresolvedRefCount = missingRefs.length + ambiguousRefs.length;\n const status: FlowFetchSummaryStatus =\n unresolvedRefCount > 0\n ? 'completed_flow_row_materialization_with_gaps'\n : 'completed_flow_row_materialization';\n\n const resolvedRowsPath = path.join(resolvedOutDir, 'resolved-flow-rows.jsonl');\n const reviewInputRowsPath = path.join(resolvedOutDir, 'review-input-rows.jsonl');\n const missingRefsPath = path.join(resolvedOutDir, 'missing-flow-refs.jsonl');\n const ambiguousRefsPath = path.join(resolvedOutDir, 'ambiguous-flow-refs.jsonl');\n const summaryPath = path.join(resolvedOutDir, 'fetch-summary.json');\n\n writeJsonLinesArtifact(resolvedRowsPath, resolvedRowArtifacts);\n writeJsonLinesArtifact(reviewInputRowsPath, reviewInputRows);\n writeJsonLinesArtifact(missingRefsPath, missingRefs);\n writeJsonLinesArtifact(ambiguousRefsPath, ambiguousRefs);\n\n const report: FlowFetchRowsReport = {\n schema_version: 1,\n generated_at_utc: nowIso(options.now),\n status,\n refs_file: resolvedRefsFile,\n out_dir: resolvedOutDir,\n allow_latest_fallback: allowLatestFallback,\n requested_ref_count: rows.length,\n resolved_ref_count: resolvedRowArtifacts.length,\n review_input_row_count: reviewInputRows.length,\n duplicate_review_input_rows_collapsed: duplicateReviewInputRowsCollapsed,\n missing_ref_count: missingRefs.length,\n ambiguous_ref_count: ambiguousRefs.length,\n resolution_counts: resolutionCounts,\n files: {\n resolved_flow_rows: resolvedRowsPath,\n review_input_rows: reviewInputRowsPath,\n fetch_summary: summaryPath,\n missing_flow_refs: missingRefsPath,\n ambiguous_flow_refs: ambiguousRefsPath,\n },\n };\n\n writeJsonArtifact(summaryPath, report);\n return report;\n}\n\nexport const __testInternals = {\n normalizeFlowFetchRef,\n normalizeOptionalNonNegativeInteger,\n normalizeToken,\n toRequestedRefSummary,\n};\n"]}
|
|
1
|
+
{"version":3,"file":"flow-fetch-rows.js","sourceRoot":"","sources":["../../../src/lib/flow-fetch-rows.ts"],"names":[],"mappings":"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","sourcesContent":["import path from 'node:path';\nimport { writeJsonArtifact, writeJsonLinesArtifact } from './artifacts.js';\nimport { CliError } from './errors.js';\nimport { loadRowsFromFile, type JsonRecord } from './flow-governance.js';\nimport type { FetchLike } from './http.js';\nimport {\n fetchOneFlowRow,\n normalizeSupabaseFlowPayload,\n type SupabaseFlowLookup,\n} from './flow-read.js';\nimport { requireSupabaseRestRuntime } from './supabase-rest.js';\nimport { createSupabaseDataRuntime } from './supabase-session.js';\n\nconst FLOW_FETCH_ROWS_TIMEOUT_MS = 10_000;\n\ntype FlowFetchRef = {\n id: string;\n version: string | null;\n userId: string | null;\n stateCode: number | null;\n clusterId: string | null;\n source: string | null;\n};\n\ntype FlowFetchMaterializationContext = {\n input_index: number;\n requested_ref: {\n id: string;\n version: string | null;\n user_id: string | null;\n state_code: number | null;\n cluster_id: string | null;\n source: string | null;\n };\n resolution: SupabaseFlowLookup['resolution'];\n source_url: string;\n resolved_flow_id: string;\n resolved_version: string;\n};\n\ntype FlowFetchSummaryStatus =\n | 'completed_flow_row_materialization'\n | 'completed_flow_row_materialization_with_gaps';\n\nexport type RunFlowFetchRowsOptions = {\n refsFile: string;\n outDir: string;\n allowLatestFallback?: boolean;\n env?: NodeJS.ProcessEnv;\n fetchImpl?: FetchLike;\n timeoutMs?: number;\n now?: Date;\n};\n\nexport type FlowFetchRowsReport = {\n schema_version: 1;\n generated_at_utc: string;\n status: FlowFetchSummaryStatus;\n refs_file: string;\n out_dir: string;\n allow_latest_fallback: boolean;\n requested_ref_count: number;\n resolved_ref_count: number;\n qa_input_row_count: number;\n duplicate_qa_input_rows_collapsed: number;\n missing_ref_count: number;\n ambiguous_ref_count: number;\n resolution_counts: Record<SupabaseFlowLookup['resolution'], number>;\n files: {\n resolved_flow_rows: string;\n qa_input_rows: string;\n fetch_summary: string;\n missing_flow_refs: string;\n ambiguous_flow_refs: string;\n };\n};\n\nfunction normalizeToken(value: unknown): string | null {\n if (value === undefined || value === null) {\n return null;\n }\n\n const trimmed = String(value).trim();\n return trimmed ? trimmed : null;\n}\n\nfunction normalizeOptionalNonNegativeInteger(\n value: unknown,\n label: string,\n code: string,\n): number | null {\n if (value === undefined || value === null || value === '') {\n return null;\n }\n\n const parsed =\n typeof value === 'number' && Number.isInteger(value)\n ? value\n : Number.parseInt(String(value), 10);\n if (!Number.isInteger(parsed) || parsed < 0) {\n throw new CliError(`Expected ${label} to be a non-negative integer.`, {\n code,\n exitCode: 2,\n details: value,\n });\n }\n return parsed;\n}\n\nfunction normalizeFlowFetchRef(row: JsonRecord, index: number): FlowFetchRef {\n const id = normalizeToken(row.id);\n if (!id) {\n throw new CliError(`Flow ref row ${index + 1} is missing required id.`, {\n code: 'FLOW_FETCH_ROWS_REF_ID_REQUIRED',\n exitCode: 2,\n details: row,\n });\n }\n\n return {\n id,\n version: normalizeToken(row.version),\n userId: normalizeToken(row.user_id ?? row.userId),\n stateCode: normalizeOptionalNonNegativeInteger(\n row.state_code ?? row.stateCode,\n 'flow ref state_code',\n 'FLOW_FETCH_ROWS_INVALID_STATE_CODE',\n ),\n clusterId: normalizeToken(row.cluster_id ?? row.clusterId),\n source: normalizeToken(row.source),\n };\n}\n\nfunction toRequestedRefSummary(\n ref: FlowFetchRef,\n): FlowFetchMaterializationContext['requested_ref'] {\n return {\n id: ref.id,\n version: ref.version,\n user_id: ref.userId,\n state_code: ref.stateCode,\n cluster_id: ref.clusterId,\n source: ref.source,\n };\n}\n\nfunction buildMaterializedRow(\n lookup: SupabaseFlowLookup,\n context: FlowFetchMaterializationContext,\n): JsonRecord {\n const resolvedFlowId = lookup.row.id || context.requested_ref.id;\n const resolvedVersion = lookup.row.version || context.requested_ref.version || '';\n\n return {\n id: resolvedFlowId,\n version: resolvedVersion,\n user_id: lookup.row.user_id,\n state_code: lookup.row.state_code,\n modified_at: lookup.row.modified_at,\n json: normalizeSupabaseFlowPayload(lookup.row.json, `${resolvedFlowId}@${resolvedVersion}`),\n _materialization: context,\n };\n}\n\nfunction buildQaInputRow(\n row: JsonRecord,\n flowKey: string,\n contexts: FlowFetchMaterializationContext[],\n): JsonRecord {\n return {\n ...row,\n _materialization: {\n flow_key: flowKey,\n materialized_ref_count: contexts.length,\n materialized_from_refs: contexts,\n },\n };\n}\n\nfunction nowIso(now: Date = new Date()): string {\n return now.toISOString();\n}\n\nexport async function runFlowFetchRows(\n options: RunFlowFetchRowsOptions,\n): Promise<FlowFetchRowsReport> {\n const refsFile = normalizeToken(options.refsFile);\n if (!refsFile) {\n throw new CliError('Missing required --refs-file value.', {\n code: 'FLOW_FETCH_ROWS_REFS_FILE_REQUIRED',\n exitCode: 2,\n });\n }\n\n const outDir = normalizeToken(options.outDir);\n if (!outDir) {\n throw new CliError('Missing required --out-dir value.', {\n code: 'FLOW_FETCH_ROWS_OUT_DIR_REQUIRED',\n exitCode: 2,\n });\n }\n\n const resolvedRefsFile = path.resolve(refsFile);\n const resolvedOutDir = path.resolve(outDir);\n const allowLatestFallback = options.allowLatestFallback !== false;\n const rows = loadRowsFromFile(resolvedRefsFile);\n\n const fetchImpl = options.fetchImpl ?? (fetch as FetchLike);\n const timeoutMs = options.timeoutMs ?? FLOW_FETCH_ROWS_TIMEOUT_MS;\n const runtime = createSupabaseDataRuntime({\n runtime: requireSupabaseRestRuntime(options.env ?? process.env),\n fetchImpl,\n timeoutMs,\n now: options.now,\n });\n\n const resolvedRowArtifacts: JsonRecord[] = [];\n const missingRefs: JsonRecord[] = [];\n const ambiguousRefs: JsonRecord[] = [];\n const qaInputByKey = new Map<\n string,\n { row: JsonRecord; contexts: FlowFetchMaterializationContext[] }\n >();\n const resolutionCounts: FlowFetchRowsReport['resolution_counts'] = {\n remote_supabase_exact: 0,\n remote_supabase_latest: 0,\n remote_supabase_latest_fallback: 0,\n };\n\n for (let index = 0; index < rows.length; index += 1) {\n const ref = normalizeFlowFetchRef(rows[index] as JsonRecord, index);\n const requestedRef = toRequestedRefSummary(ref);\n\n let lookup: SupabaseFlowLookup | null;\n try {\n lookup = await fetchOneFlowRow({\n runtime,\n id: ref.id,\n version: ref.version,\n userId: ref.userId,\n stateCode: ref.stateCode,\n timeoutMs,\n fetchImpl,\n fallbackToLatest: allowLatestFallback && ref.version !== null,\n });\n } catch (error) {\n if (error instanceof CliError && error.code === 'FLOW_GET_AMBIGUOUS') {\n ambiguousRefs.push({\n input_index: index,\n requested_ref: requestedRef,\n code: error.code,\n message: error.message,\n details: error.details,\n });\n continue;\n }\n throw error;\n }\n\n if (!lookup) {\n missingRefs.push({\n input_index: index,\n requested_ref: requestedRef,\n code: 'FLOW_GET_NOT_FOUND',\n message: ref.version\n ? `Could not resolve flow dataset for ${ref.id}@${ref.version}.`\n : `Could not resolve flow dataset for ${ref.id}.`,\n });\n continue;\n }\n\n resolutionCounts[lookup.resolution] += 1;\n const resolvedFlowId = lookup.row.id || ref.id;\n const resolvedVersion = lookup.row.version || ref.version || '';\n const context: FlowFetchMaterializationContext = {\n input_index: index,\n requested_ref: requestedRef,\n resolution: lookup.resolution,\n source_url: lookup.sourceUrl,\n resolved_flow_id: resolvedFlowId,\n resolved_version: resolvedVersion,\n };\n const materializedRow = buildMaterializedRow(lookup, context);\n resolvedRowArtifacts.push(materializedRow);\n\n const flowKey = `${resolvedFlowId}@${resolvedVersion}`;\n const existing = qaInputByKey.get(flowKey);\n if (existing) {\n existing.contexts.push(context);\n } else {\n qaInputByKey.set(flowKey, {\n row: materializedRow,\n contexts: [context],\n });\n }\n }\n\n const qaInputRows = [...qaInputByKey.entries()]\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([flowKey, entry]) => buildQaInputRow(entry.row, flowKey, entry.contexts));\n\n const duplicateQaInputRowsCollapsed = resolvedRowArtifacts.length - qaInputRows.length;\n const unresolvedRefCount = missingRefs.length + ambiguousRefs.length;\n const status: FlowFetchSummaryStatus =\n unresolvedRefCount > 0\n ? 'completed_flow_row_materialization_with_gaps'\n : 'completed_flow_row_materialization';\n\n const resolvedRowsPath = path.join(resolvedOutDir, 'resolved-flow-rows.jsonl');\n const qaInputRowsPath = path.join(resolvedOutDir, 'qa-input-rows.jsonl');\n const missingRefsPath = path.join(resolvedOutDir, 'missing-flow-refs.jsonl');\n const ambiguousRefsPath = path.join(resolvedOutDir, 'ambiguous-flow-refs.jsonl');\n const summaryPath = path.join(resolvedOutDir, 'fetch-summary.json');\n\n writeJsonLinesArtifact(resolvedRowsPath, resolvedRowArtifacts);\n writeJsonLinesArtifact(qaInputRowsPath, qaInputRows);\n writeJsonLinesArtifact(missingRefsPath, missingRefs);\n writeJsonLinesArtifact(ambiguousRefsPath, ambiguousRefs);\n\n const report: FlowFetchRowsReport = {\n schema_version: 1,\n generated_at_utc: nowIso(options.now),\n status,\n refs_file: resolvedRefsFile,\n out_dir: resolvedOutDir,\n allow_latest_fallback: allowLatestFallback,\n requested_ref_count: rows.length,\n resolved_ref_count: resolvedRowArtifacts.length,\n qa_input_row_count: qaInputRows.length,\n duplicate_qa_input_rows_collapsed: duplicateQaInputRowsCollapsed,\n missing_ref_count: missingRefs.length,\n ambiguous_ref_count: ambiguousRefs.length,\n resolution_counts: resolutionCounts,\n files: {\n resolved_flow_rows: resolvedRowsPath,\n qa_input_rows: qaInputRowsPath,\n fetch_summary: summaryPath,\n missing_flow_refs: missingRefsPath,\n ambiguous_flow_refs: ambiguousRefsPath,\n },\n };\n\n writeJsonArtifact(summaryPath, report);\n return report;\n}\n\nexport const __testInternals = {\n normalizeFlowFetchRef,\n normalizeOptionalNonNegativeInteger,\n normalizeToken,\n toRequestedRefSummary,\n};\n"]}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import * as tidasSdk from '@tiangong-lca/tidas-sdk';
|
|
2
|
+
import { normalizeIssuePath, validateSchemaWithDeepFallback, } from './tidas-sdk-validation.js';
|
|
3
|
+
export const FLOW_SCHEMA_VALIDATOR = '@tiangong-lca/tidas-sdk/FlowSchema';
|
|
4
|
+
function getFlowSchema(sdk = tidasSdk) {
|
|
5
|
+
const schema = sdk.FlowSchema;
|
|
6
|
+
if (!schema?.safeParse) {
|
|
7
|
+
throw new Error(`${FLOW_SCHEMA_VALIDATOR} is unavailable in the published CLI runtime.`);
|
|
8
|
+
}
|
|
9
|
+
return schema;
|
|
10
|
+
}
|
|
11
|
+
function getFlowFactory(sdk = tidasSdk) {
|
|
12
|
+
const createFlow = sdk.createFlow;
|
|
13
|
+
return typeof createFlow === 'function' ? createFlow : null;
|
|
14
|
+
}
|
|
15
|
+
export function summarizeFlowPayloadValidation(result) {
|
|
16
|
+
if (result.ok) {
|
|
17
|
+
return 'local FlowSchema validation passed';
|
|
18
|
+
}
|
|
19
|
+
const preview = result.issues
|
|
20
|
+
.slice(0, 3)
|
|
21
|
+
.map((issue) => `${issue.path}: ${issue.message}`)
|
|
22
|
+
.join('; ');
|
|
23
|
+
return `local FlowSchema validation failed with ${result.issue_count} issue(s)${preview ? ` (${preview})` : ''}`;
|
|
24
|
+
}
|
|
25
|
+
export function validateFlowPayload(payload, schema = getFlowSchema(), createEntity = getFlowFactory()) {
|
|
26
|
+
const outcome = validateSchemaWithDeepFallback(schema, payload, createEntity);
|
|
27
|
+
if (outcome.success) {
|
|
28
|
+
return {
|
|
29
|
+
ok: true,
|
|
30
|
+
validator: FLOW_SCHEMA_VALIDATOR,
|
|
31
|
+
issue_count: 0,
|
|
32
|
+
issues: [],
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
const issues = outcome.issues.map((issue) => ({
|
|
36
|
+
path: normalizeIssuePath(issue.path),
|
|
37
|
+
message: issue.message ?? 'Validation failed',
|
|
38
|
+
code: issue.code ?? 'custom',
|
|
39
|
+
}));
|
|
40
|
+
return {
|
|
41
|
+
ok: false,
|
|
42
|
+
validator: FLOW_SCHEMA_VALIDATOR,
|
|
43
|
+
issue_count: issues.length,
|
|
44
|
+
issues,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
export const __testInternals = {
|
|
48
|
+
getFlowSchema,
|
|
49
|
+
getFlowFactory,
|
|
50
|
+
};
|
|
51
|
+
//# sourceMappingURL=flow-payload-validation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flow-payload-validation.js","sourceRoot":"","sources":["../../../src/lib/flow-payload-validation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,yBAAyB,CAAC;AACpD,OAAO,EACL,kBAAkB,EAGlB,8BAA8B,GAC/B,MAAM,2BAA2B,CAAC;AAInC,MAAM,CAAC,MAAM,qBAAqB,GAAG,oCAAoC,CAAC;AAsB1E,SAAS,aAAa,CACpB,MAAwC,QAA4C;IAEpF,MAAM,MAAM,GAAG,GAAG,CAAC,UAAU,CAAC;IAC9B,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,GAAG,qBAAqB,+CAA+C,CAAC,CAAC;IAC3F,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,cAAc,CAAC,MAAgC,QAAQ;IAC9D,MAAM,UAAU,GAAG,GAAG,CAAC,UAAU,CAAC;IAClC,OAAO,OAAO,UAAU,KAAK,UAAU,CAAC,CAAC,CAAE,UAAmC,CAAC,CAAC,CAAC,IAAI,CAAC;AACxF,CAAC;AAED,MAAM,UAAU,8BAA8B,CAAC,MAAmC;IAChF,IAAI,MAAM,CAAC,EAAE,EAAE,CAAC;QACd,OAAO,oCAAoC,CAAC;IAC9C,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM;SAC1B,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;SACX,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC;SACjD,IAAI,CAAC,IAAI,CAAC,CAAC;IACd,OAAO,2CAA2C,MAAM,CAAC,WAAW,YAAY,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;AACnH,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,OAAmB,EACnB,SAA0B,aAAa,EAAE,EACzC,eAA4C,cAAc,EAAE;IAE5D,MAAM,OAAO,GAAG,8BAA8B,CAAC,MAAM,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC;IAC9E,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QACpB,OAAO;YACL,EAAE,EAAE,IAAI;YACR,SAAS,EAAE,qBAAqB;YAChC,WAAW,EAAE,CAAC;YACd,MAAM,EAAE,EAAE;SACX,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAC5C,IAAI,EAAE,kBAAkB,CAAC,KAAK,CAAC,IAAI,CAAC;QACpC,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,mBAAmB;QAC7C,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,QAAQ;KAC7B,CAAC,CAAC,CAAC;IAEJ,OAAO;QACL,EAAE,EAAE,KAAK;QACT,SAAS,EAAE,qBAAqB;QAChC,WAAW,EAAE,MAAM,CAAC,MAAM;QAC1B,MAAM;KACP,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,aAAa;IACb,cAAc;CACf,CAAC","sourcesContent":["import * as tidasSdk from '@tiangong-lca/tidas-sdk';\nimport {\n normalizeIssuePath,\n type SafeParseSchema,\n type SdkValidationFactory,\n validateSchemaWithDeepFallback,\n} from './tidas-sdk-validation.js';\n\ntype JsonObject = Record<string, unknown>;\n\nexport const FLOW_SCHEMA_VALIDATOR = '@tiangong-lca/tidas-sdk/FlowSchema';\n\nexport type FlowPayloadValidationIssue = {\n path: string;\n message: string;\n code: string;\n};\n\nexport type FlowPayloadValidationResult =\n | {\n ok: true;\n validator: string;\n issue_count: 0;\n issues: [];\n }\n | {\n ok: false;\n validator: string;\n issue_count: number;\n issues: FlowPayloadValidationIssue[];\n };\n\nfunction getFlowSchema(\n sdk: { FlowSchema?: SafeParseSchema } = tidasSdk as { FlowSchema?: SafeParseSchema },\n): SafeParseSchema {\n const schema = sdk.FlowSchema;\n if (!schema?.safeParse) {\n throw new Error(`${FLOW_SCHEMA_VALIDATOR} is unavailable in the published CLI runtime.`);\n }\n return schema;\n}\n\nfunction getFlowFactory(sdk: { createFlow?: unknown } = tidasSdk): SdkValidationFactory | null {\n const createFlow = sdk.createFlow;\n return typeof createFlow === 'function' ? (createFlow as SdkValidationFactory) : null;\n}\n\nexport function summarizeFlowPayloadValidation(result: FlowPayloadValidationResult): string {\n if (result.ok) {\n return 'local FlowSchema validation passed';\n }\n\n const preview = result.issues\n .slice(0, 3)\n .map((issue) => `${issue.path}: ${issue.message}`)\n .join('; ');\n return `local FlowSchema validation failed with ${result.issue_count} issue(s)${preview ? ` (${preview})` : ''}`;\n}\n\nexport function validateFlowPayload(\n payload: JsonObject,\n schema: SafeParseSchema = getFlowSchema(),\n createEntity: SdkValidationFactory | null = getFlowFactory(),\n): FlowPayloadValidationResult {\n const outcome = validateSchemaWithDeepFallback(schema, payload, createEntity);\n if (outcome.success) {\n return {\n ok: true,\n validator: FLOW_SCHEMA_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 ok: false,\n validator: FLOW_SCHEMA_VALIDATOR,\n issue_count: issues.length,\n issues,\n };\n}\n\nexport const __testInternals = {\n getFlowSchema,\n getFlowFactory,\n};\n"]}
|
|
@@ -4,6 +4,7 @@ import { writeJsonArtifact, writeJsonLinesArtifact } from './artifacts.js';
|
|
|
4
4
|
import { CliError } from './errors.js';
|
|
5
5
|
import { coerceText, datasetPayloadFromRow, deepGet, extractFlowRecord, isRecord, listify, loadRowsFromFile, } from './flow-governance.js';
|
|
6
6
|
import { runFlowPublishVersion, } from './flow-publish-version.js';
|
|
7
|
+
import { getRuntimeRuleset } from './runtime-rulesets.js';
|
|
7
8
|
import { hasSupabaseRestRuntime, syncSupabaseJsonOrderedRecord, } from './supabase-json-ordered-write.js';
|
|
8
9
|
const DEFAULT_MAX_WORKERS = 4;
|
|
9
10
|
const LEGACY_OUTPUT_PREFIX = 'flows_tidas_sdk_plus_classification';
|
|
@@ -579,6 +580,7 @@ function map_commit_reports(plans, successes, failures) {
|
|
|
579
580
|
});
|
|
580
581
|
}
|
|
581
582
|
function build_compat_report(options) {
|
|
583
|
+
const ruleset = getRuntimeRuleset('flow-publish/default');
|
|
582
584
|
let status;
|
|
583
585
|
if (options.mode === 'dry_run') {
|
|
584
586
|
status = 'prepared_flow_publish_version';
|
|
@@ -601,6 +603,18 @@ function build_compat_report(options) {
|
|
|
601
603
|
success_count: options.successCount,
|
|
602
604
|
failure_count: options.failureCount,
|
|
603
605
|
},
|
|
606
|
+
flow_gate: {
|
|
607
|
+
status: 'passed',
|
|
608
|
+
ruleset_id: ruleset.id,
|
|
609
|
+
ruleset_version: ruleset.version,
|
|
610
|
+
counts: {
|
|
611
|
+
total: options.preparedRows,
|
|
612
|
+
valid: options.preparedRows,
|
|
613
|
+
invalid: 0,
|
|
614
|
+
},
|
|
615
|
+
blocker_count: 0,
|
|
616
|
+
next_action: 'query_remote_write_plan',
|
|
617
|
+
},
|
|
604
618
|
operation_counts: {},
|
|
605
619
|
max_workers: options.maxWorkers,
|
|
606
620
|
limit: null,
|
|
@@ -608,6 +622,7 @@ function build_compat_report(options) {
|
|
|
608
622
|
files: {
|
|
609
623
|
success_list: options.files.success_list,
|
|
610
624
|
remote_failed: options.files.remote_failed,
|
|
625
|
+
gate_report: options.files.flow_publish_version_report,
|
|
611
626
|
report: options.files.flow_publish_version_report,
|
|
612
627
|
},
|
|
613
628
|
};
|
|
@@ -689,6 +704,7 @@ export async function runFlowReviewedPublishData(options) {
|
|
|
689
704
|
fetchImpl: options.fetchImpl,
|
|
690
705
|
timeoutMs: options.timeoutMs,
|
|
691
706
|
now,
|
|
707
|
+
validateFlowPayloadImpl: options.validateFlowPayloadImpl,
|
|
692
708
|
});
|
|
693
709
|
const successRows = loadRowsFromFile(files.success_list);
|
|
694
710
|
const failureRows = loadRowsFromFile(files.remote_failed);
|