@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.
Files changed (59) hide show
  1. package/README.md +97 -16
  2. package/dist/src/cli.js +1429 -131
  3. package/dist/src/cli.js.map +1 -1
  4. package/dist/src/lib/dataset-author.js +100 -0
  5. package/dist/src/lib/dataset-author.js.map +1 -0
  6. package/dist/src/lib/dataset-bilingual.js +545 -0
  7. package/dist/src/lib/dataset-bilingual.js.map +1 -0
  8. package/dist/src/lib/dataset-contract.js +350 -0
  9. package/dist/src/lib/dataset-contract.js.map +1 -0
  10. package/dist/src/lib/dataset-evidence-search.js +636 -0
  11. package/dist/src/lib/dataset-evidence-search.js.map +1 -0
  12. package/dist/src/lib/dataset-import-lca.js +171 -0
  13. package/dist/src/lib/dataset-import-lca.js.map +1 -0
  14. package/dist/src/lib/dataset-remote-refresh.js +166 -0
  15. package/dist/src/lib/dataset-remote-refresh.js.map +1 -0
  16. package/dist/src/lib/dataset-remote-verify.js +543 -0
  17. package/dist/src/lib/dataset-remote-verify.js.map +1 -0
  18. package/dist/src/lib/dataset-validate.js +63 -7
  19. package/dist/src/lib/dataset-validate.js.map +1 -1
  20. package/dist/src/lib/flow-fetch-rows.js +12 -12
  21. package/dist/src/lib/flow-fetch-rows.js.map +1 -1
  22. package/dist/src/lib/flow-payload-validation.js +51 -0
  23. package/dist/src/lib/flow-payload-validation.js.map +1 -0
  24. package/dist/src/lib/flow-publish-reviewed-data.js +16 -0
  25. package/dist/src/lib/flow-publish-reviewed-data.js.map +1 -1
  26. package/dist/src/lib/flow-publish-version.js +182 -12
  27. package/dist/src/lib/flow-publish-version.js.map +1 -1
  28. package/dist/src/lib/{review-flow.js → flow-qa.js} +86 -28
  29. package/dist/src/lib/flow-qa.js.map +1 -0
  30. package/dist/src/lib/identity-preflight.js +1021 -0
  31. package/dist/src/lib/identity-preflight.js.map +1 -0
  32. package/dist/src/lib/{review-lifecyclemodel.js → lifecyclemodel-qa.js} +54 -54
  33. package/dist/src/lib/lifecyclemodel-qa.js.map +1 -0
  34. package/dist/src/lib/process-auto-build.js +147 -0
  35. package/dist/src/lib/process-auto-build.js.map +1 -1
  36. package/dist/src/lib/process-dedup-review.js +51 -0
  37. package/dist/src/lib/process-dedup-review.js.map +1 -1
  38. package/dist/src/lib/process-flow-build-plan.js +1071 -0
  39. package/dist/src/lib/process-flow-build-plan.js.map +1 -0
  40. package/dist/src/lib/process-payload-validation.js +14 -7
  41. package/dist/src/lib/process-payload-validation.js.map +1 -1
  42. package/dist/src/lib/process-publish-build.js +122 -4
  43. package/dist/src/lib/process-publish-build.js.map +1 -1
  44. package/dist/src/lib/{review-process.js → process-qa.js} +259 -117
  45. package/dist/src/lib/process-qa.js.map +1 -0
  46. package/dist/src/lib/process-refresh-references.js +19 -10
  47. package/dist/src/lib/process-refresh-references.js.map +1 -1
  48. package/dist/src/lib/process-required-fields.js +810 -0
  49. package/dist/src/lib/process-required-fields.js.map +1 -0
  50. package/dist/src/lib/process-save-draft-run.js +4 -1
  51. package/dist/src/lib/process-save-draft-run.js.map +1 -1
  52. package/dist/src/lib/publish.js +100 -0
  53. package/dist/src/lib/publish.js.map +1 -1
  54. package/dist/src/lib/runtime-rulesets.js +283 -0
  55. package/dist/src/lib/runtime-rulesets.js.map +1 -0
  56. package/package.json +2 -2
  57. package/dist/src/lib/review-flow.js.map +0 -1
  58. package/dist/src/lib/review-lifecyclemodel.js.map +0 -1
  59. 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
- if (outcome.success) {
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 = outcome.issues.map((issue) => ({
109
- path: normalizeIssuePath(issue.path),
110
- message: issue.message ?? 'Validation failed',
111
- code: issue.code ?? 'custom',
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 buildReviewInputRow(row, flowKey, contexts) {
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 reviewInputByKey = new Map();
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 = reviewInputByKey.get(flowKey);
176
+ const existing = qaInputByKey.get(flowKey);
177
177
  if (existing) {
178
178
  existing.contexts.push(context);
179
179
  }
180
180
  else {
181
- reviewInputByKey.set(flowKey, {
181
+ qaInputByKey.set(flowKey, {
182
182
  row: materializedRow,
183
183
  contexts: [context],
184
184
  });
185
185
  }
186
186
  }
187
- const reviewInputRows = [...reviewInputByKey.entries()]
187
+ const qaInputRows = [...qaInputByKey.entries()]
188
188
  .sort(([left], [right]) => left.localeCompare(right))
189
- .map(([flowKey, entry]) => buildReviewInputRow(entry.row, flowKey, entry.contexts));
190
- const duplicateReviewInputRowsCollapsed = resolvedRowArtifacts.length - reviewInputRows.length;
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 reviewInputRowsPath = path.join(resolvedOutDir, 'review-input-rows.jsonl');
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(reviewInputRowsPath, reviewInputRows);
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
- review_input_row_count: reviewInputRows.length,
214
- duplicate_review_input_rows_collapsed: duplicateReviewInputRowsCollapsed,
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
- review_input_rows: reviewInputRowsPath,
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);