@tiangong-lca/cli 0.1.9 → 0.1.10

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 (70) hide show
  1. package/README.md +8 -5
  2. package/assets/runtime/cli-runtime-descriptor.schema.json +138 -0
  3. package/assets/runtime/cli-runtime-expectation.schema.json +38 -0
  4. package/assets/runtime/runtime-bootstrap-lock.schema.json +254 -0
  5. package/assets/runtime/runtime-command-result.schema.json +95 -0
  6. package/assets/runtime/runtime-manifest.schema.json +380 -0
  7. package/dist/src/cli.js +5 -1
  8. package/dist/src/cli.js.map +1 -1
  9. package/dist/src/lib/dataset-import-lca.js +2 -2
  10. package/dist/src/lib/dataset-import-lca.js.map +1 -1
  11. package/dist/src/lib/runtime/archive-writer.d.ts +7 -0
  12. package/dist/src/lib/runtime/archive-writer.js +89 -0
  13. package/dist/src/lib/runtime/archive-writer.js.map +1 -0
  14. package/dist/src/lib/runtime/archive.d.ts +2 -0
  15. package/dist/src/lib/runtime/archive.js +122 -0
  16. package/dist/src/lib/runtime/archive.js.map +1 -0
  17. package/dist/src/lib/runtime/command.d.ts +8 -0
  18. package/dist/src/lib/runtime/command.js +57 -0
  19. package/dist/src/lib/runtime/command.js.map +1 -0
  20. package/dist/src/lib/runtime/descriptor.d.ts +11 -0
  21. package/dist/src/lib/runtime/descriptor.js +126 -0
  22. package/dist/src/lib/runtime/descriptor.js.map +1 -0
  23. package/dist/src/lib/runtime/download.d.ts +9 -0
  24. package/dist/src/lib/runtime/download.js +118 -0
  25. package/dist/src/lib/runtime/download.js.map +1 -0
  26. package/dist/src/lib/runtime/exec-command.d.ts +7 -0
  27. package/dist/src/lib/runtime/exec-command.js +83 -0
  28. package/dist/src/lib/runtime/exec-command.js.map +1 -0
  29. package/dist/src/lib/runtime/execute.d.ts +11 -0
  30. package/dist/src/lib/runtime/execute.js +125 -0
  31. package/dist/src/lib/runtime/execute.js.map +1 -0
  32. package/dist/src/lib/runtime/files.d.ts +7 -0
  33. package/dist/src/lib/runtime/files.js +91 -0
  34. package/dist/src/lib/runtime/files.js.map +1 -0
  35. package/dist/src/lib/runtime/host.d.ts +8 -0
  36. package/dist/src/lib/runtime/host.js +37 -0
  37. package/dist/src/lib/runtime/host.js.map +1 -0
  38. package/dist/src/lib/runtime/leases.d.ts +12 -0
  39. package/dist/src/lib/runtime/leases.js +72 -0
  40. package/dist/src/lib/runtime/leases.js.map +1 -0
  41. package/dist/src/lib/runtime/managed-command.d.ts +6 -0
  42. package/dist/src/lib/runtime/managed-command.js +99 -0
  43. package/dist/src/lib/runtime/managed-command.js.map +1 -0
  44. package/dist/src/lib/runtime/manager.d.ts +33 -0
  45. package/dist/src/lib/runtime/manager.js +196 -0
  46. package/dist/src/lib/runtime/manager.js.map +1 -0
  47. package/dist/src/lib/runtime/manifest-types.d.ts +73 -0
  48. package/dist/src/lib/runtime/manifest-types.js +4 -0
  49. package/dist/src/lib/runtime/manifest-types.js.map +1 -0
  50. package/dist/src/lib/runtime/manifest-values.d.ts +15 -0
  51. package/dist/src/lib/runtime/manifest-values.js +124 -0
  52. package/dist/src/lib/runtime/manifest-values.js.map +1 -0
  53. package/dist/src/lib/runtime/manifest.d.ts +7 -0
  54. package/dist/src/lib/runtime/manifest.js +220 -0
  55. package/dist/src/lib/runtime/manifest.js.map +1 -0
  56. package/dist/src/lib/runtime/process.d.ts +3 -0
  57. package/dist/src/lib/runtime/process.js +55 -0
  58. package/dist/src/lib/runtime/process.js.map +1 -0
  59. package/dist/src/lib/runtime/storage.d.ts +8 -0
  60. package/dist/src/lib/runtime/storage.js +142 -0
  61. package/dist/src/lib/runtime/storage.js.map +1 -0
  62. package/dist/src/lib/runtime/types.d.ts +45 -0
  63. package/dist/src/lib/runtime/types.js +9 -0
  64. package/dist/src/lib/runtime/types.js.map +1 -0
  65. package/dist/src/main.js +13 -1
  66. package/dist/src/main.js.map +1 -1
  67. package/dist/src/runtime.d.ts +15 -0
  68. package/dist/src/runtime.js +22 -0
  69. package/dist/src/runtime.js.map +1 -0
  70. package/package.json +5 -1
@@ -328,14 +328,14 @@ function resolveTidasBinary(explicitValue, env) {
328
328
  }
329
329
  function assertSupportedPlatform(platform, arch) {
330
330
  const supported = (platform === 'linux' && (arch === 'x64' || arch === 'arm64')) ||
331
- (platform === 'darwin' && (arch === 'x64' || arch === 'arm64')) ||
331
+ (platform === 'darwin' && arch === 'arm64') ||
332
332
  (platform === 'win32' && arch === 'x64');
333
333
  if (!supported) {
334
334
  throw new CliError(`No supported Rust tidas artifact exists for ${platform}/${arch}.`, {
335
335
  code: 'DATASET_IMPORT_LCA_PLATFORM_UNSUPPORTED',
336
336
  exitCode: 69,
337
337
  details: {
338
- supported: ['linux/x64', 'linux/arm64', 'darwin/x64', 'darwin/arm64', 'win32/x64'],
338
+ supported: ['linux/x64', 'linux/arm64', 'darwin/arm64', 'win32/x64'],
339
339
  },
340
340
  });
341
341
  }
@@ -1 +1 @@
1
- {"version":3,"file":"dataset-import-lca.js","sourceRoot":"","sources":["../../../src/lib/dataset-import-lca.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readFileSync } from 'node:fs';\nimport path from 'node:path';\nimport { spawnSync, type SpawnSyncReturns } from 'node:child_process';\nimport { CliError } from './errors.js';\n\nconst OPERATION_REPORT_SCHEMA = 'tidas.operation-report.v1';\nconst INVOCATION_CONTEXT_SCHEMA = 'tidas.invocation-context.v1';\nconst IMPORT_REPORT_SCHEMA = 'tidas.import-execution-report.v1';\nconst SUPPORTED_TIDAS_VERSION = /^0\\.2\\.\\d+$/u;\n\nconst EXIT_CODES = {\n success: 0,\n 'data-issues': 2,\n usage: 64,\n unavailable: 69,\n internal: 70,\n io: 74,\n cancelled: 130,\n} as const;\n\nconst OPERATION_STATUSES = ['succeeded', 'completed-with-issues', 'failed', 'cancelled'] as const;\nconst COMPLETENESS_VALUES = ['complete', 'partial', 'not-started'] as const;\nconst SOURCE_FORMATS = [\n 'ecospold1',\n 'ecospold2',\n 'simapro-csv',\n 'openlca-jsonld',\n 'openlca-process-xlsx',\n 'ilcd',\n] as const;\n\ntype TidasExitClass = keyof typeof EXIT_CODES;\ntype TidasOperationStatus = (typeof OPERATION_STATUSES)[number];\ntype TidasCompleteness = (typeof COMPLETENESS_VALUES)[number];\nexport type DatasetImportLcaTarget = 'tidas' | 'ilcd' | 'both';\nexport type DatasetImportLcaSourceFormat = (typeof SOURCE_FORMATS)[number];\n\ntype TidasOperationReport = {\n schema_version: typeof OPERATION_REPORT_SCHEMA;\n command: 'version' | 'import';\n status: TidasOperationStatus;\n exit_class: TidasExitClass;\n completeness: TidasCompleteness;\n invocation: {\n schema_version: typeof INVOCATION_CONTEXT_SCHEMA;\n input_policy: 'explicit-path-or-dash';\n report_destination: 'stdout' | 'file';\n diagnostic_destination: 'stderr';\n [key: string]: unknown;\n };\n summary: Record<string, unknown>;\n diagnostics: unknown[];\n artifacts: unknown[];\n next_actions: unknown[];\n};\n\nexport type DatasetImportLcaReport = {\n schema_version: 'tiangong-lca.dataset-import-lca-report.v2';\n status: TidasOperationStatus;\n exit_class: TidasExitClass;\n exit_code: number;\n generated_at_utc: string;\n input_path: string;\n output_dir: string;\n from_format: DatasetImportLcaSourceFormat | 'auto';\n target: DatasetImportLcaTarget;\n tidas: {\n executable: string;\n version: string;\n operation_report_schema: typeof OPERATION_REPORT_SCHEMA;\n import_report_schema: typeof IMPORT_REPORT_SCHEMA;\n };\n command: {\n args: string[];\n cwd: string;\n stderr: string;\n };\n operation_report: TidasOperationReport;\n files: {\n report: string | null;\n native_import_report: string;\n issues: string;\n tidas_dir: string | null;\n ilcd_dir: string | null;\n mapping_csv: string | null;\n process_bundles_dir: string | null;\n };\n};\n\nexport type TidasProcessResult = {\n status: number | null;\n signal: NodeJS.Signals | null;\n stdout: string;\n stderr: string;\n error?: Error | undefined;\n};\n\nexport type RunDatasetImportLcaConvertOptions = {\n inputPath: string;\n outputDir: string;\n fromFormat?: string | undefined;\n target?: string | undefined;\n reportPath?: string | undefined;\n writeMapping?: boolean | undefined;\n processBundles?: boolean | undefined;\n failOnWarning?: boolean | undefined;\n maxEntryMib?: number | undefined;\n memoryBudgetMib?: number | undefined;\n queueCapacity?: number | undefined;\n tidasBin?: string | undefined;\n tidasConfig?: string | undefined;\n env?: NodeJS.ProcessEnv | undefined;\n cwd?: string | undefined;\n platform?: NodeJS.Platform | undefined;\n arch?: string | undefined;\n now?: Date | undefined;\n spawnImpl?: typeof spawnSync | undefined;\n};\n\nexport async function runDatasetImportLcaConvert(\n options: RunDatasetImportLcaConvertOptions,\n): Promise<DatasetImportLcaReport> {\n const inputPath = requireInputPath(options.inputPath);\n const outputDir = requireOutputDir(options.outputDir);\n const fromFormat = normalizeSourceFormat(options.fromFormat);\n const target = normalizeTarget(options.target);\n const env = options.env ?? process.env;\n const executable = resolveTidasBinary(options.tidasBin, env);\n const cwd = path.resolve(options.cwd ?? process.cwd());\n const reportPath = options.reportPath?.trim() ? path.resolve(options.reportPath) : null;\n const configPath = options.tidasConfig?.trim() ? path.resolve(options.tidasConfig) : null;\n const spawnImpl = [spawnSync, options.spawnImpl].filter(Boolean).at(-1) as typeof spawnSync;\n\n assertSupportedPlatform(options.platform ?? process.platform, options.arch ?? process.arch);\n requirePositiveInteger('--max-entry-mib', options.maxEntryMib);\n requirePositiveInteger('--memory-budget-mib', options.memoryBudgetMib);\n requirePositiveInteger('--queue-capacity', options.queueCapacity);\n\n const versionArgs = ['version', '--format', 'json', '--progress', 'never'];\n const versionRun = runTidas(spawnImpl, executable, versionArgs, cwd, env);\n const versionReport = parseOperationReport(readProcessReport(versionRun, null), 'version');\n assertExitContract(versionRun, versionReport);\n const version = readCompatibleVersion(versionReport);\n\n const commandArgs = buildImportArgs({\n inputPath,\n outputDir,\n fromFormat,\n target,\n reportPath,\n configPath,\n writeMapping: Boolean(options.writeMapping),\n processBundles: options.processBundles !== false,\n failOnWarning: Boolean(options.failOnWarning),\n maxEntryMib: options.maxEntryMib,\n memoryBudgetMib: options.memoryBudgetMib,\n queueCapacity: options.queueCapacity,\n });\n const importRun = runTidas(spawnImpl, executable, commandArgs, cwd, env);\n const operationReport = parseOperationReport(readProcessReport(importRun, reportPath), 'import');\n assertExitContract(importRun, operationReport);\n assertImportContract(operationReport);\n\n return {\n schema_version: 'tiangong-lca.dataset-import-lca-report.v2',\n status: operationReport.status,\n exit_class: operationReport.exit_class,\n exit_code: EXIT_CODES[operationReport.exit_class],\n generated_at_utc: (options.now ?? new Date()).toISOString(),\n input_path: inputPath,\n output_dir: outputDir,\n from_format: fromFormat,\n target,\n tidas: {\n executable,\n version,\n operation_report_schema: OPERATION_REPORT_SCHEMA,\n import_report_schema: IMPORT_REPORT_SCHEMA,\n },\n command: {\n args: commandArgs,\n cwd,\n stderr: importRun.stderr,\n },\n operation_report: operationReport,\n files: {\n report: reportPath,\n native_import_report: path.join(outputDir, 'import-report.json'),\n issues: path.join(outputDir, 'issues.jsonl'),\n tidas_dir:\n operationReport.completeness === 'complete' && (target === 'tidas' || target === 'both')\n ? path.join(outputDir, 'tidas')\n : null,\n ilcd_dir:\n operationReport.completeness === 'complete' && (target === 'ilcd' || target === 'both')\n ? path.join(outputDir, 'ilcd')\n : null,\n mapping_csv:\n operationReport.completeness === 'complete' && options.writeMapping\n ? path.join(outputDir, 'mapping.csv.gz')\n : null,\n process_bundles_dir:\n operationReport.completeness === 'complete' && options.processBundles !== false\n ? path.join(outputDir, 'process-bundles')\n : null,\n },\n };\n}\n\nfunction buildImportArgs(options: {\n inputPath: string;\n outputDir: string;\n fromFormat: DatasetImportLcaSourceFormat | 'auto';\n target: DatasetImportLcaTarget;\n reportPath: string | null;\n configPath: string | null;\n writeMapping: boolean;\n processBundles: boolean;\n failOnWarning: boolean;\n maxEntryMib: number | undefined;\n memoryBudgetMib: number | undefined;\n queueCapacity: number | undefined;\n}): string[] {\n const args = [\n 'import',\n options.inputPath,\n '--output',\n options.outputDir,\n '--target',\n options.target,\n '--format',\n 'json',\n '--progress',\n 'never',\n ];\n if (options.fromFormat !== 'auto') {\n args.push('--from-format', options.fromFormat);\n }\n if (options.reportPath) {\n args.push('--report', options.reportPath);\n }\n if (options.configPath) {\n args.push('--config', options.configPath);\n }\n if (options.writeMapping) {\n args.push('--write-mapping');\n }\n if (!options.processBundles) {\n args.push('--no-process-bundles');\n }\n if (options.failOnWarning) {\n args.push('--fail-on-warning');\n }\n if (options.maxEntryMib !== undefined) {\n args.push('--max-entry-mib', String(options.maxEntryMib));\n }\n if (options.memoryBudgetMib !== undefined) {\n args.push('--memory-budget-mib', String(options.memoryBudgetMib));\n }\n if (options.queueCapacity !== undefined) {\n args.push('--queue-capacity', String(options.queueCapacity));\n }\n return args;\n}\n\nfunction runTidas(\n spawnImpl: typeof spawnSync,\n executable: string,\n args: string[],\n cwd: string,\n env: NodeJS.ProcessEnv,\n): TidasProcessResult {\n const run = spawnImpl(executable, args, {\n cwd,\n env,\n encoding: 'utf8',\n windowsHide: true,\n }) as SpawnSyncReturns<string>;\n if (run.error) {\n throw new CliError(`Could not execute the Rust tidas binary: ${run.error.message}`, {\n code: 'DATASET_IMPORT_LCA_TIDAS_EXEC_FAILED',\n exitCode: 69,\n details: { executable },\n });\n }\n return {\n status: run.status,\n signal: run.signal,\n stdout: run.stdout ?? '',\n stderr: run.stderr ?? '',\n };\n}\n\nfunction readProcessReport(run: TidasProcessResult, reportPath: string | null): string {\n const cancelled = run.status === 130 || run.signal === 'SIGINT';\n if (reportPath) {\n if (!existsSync(reportPath)) {\n if (cancelled) {\n throw new CliError(\n 'tidas import was cancelled before a complete machine report was available.',\n {\n code: 'DATASET_IMPORT_LCA_CANCELLED',\n exitCode: 130,\n details: { signal: run.signal, stderr: run.stderr },\n },\n );\n }\n throw new CliError(`tidas did not write the requested machine report: ${reportPath}`, {\n code: 'DATASET_IMPORT_LCA_TIDAS_REPORT_MISSING',\n exitCode: 70,\n });\n }\n return readFileSync(reportPath, 'utf8');\n }\n if (!run.stdout.trim()) {\n throw new CliError(\n cancelled\n ? 'tidas import was cancelled before a complete machine report was available.'\n : 'tidas did not emit a machine-readable operation report.',\n {\n code: cancelled\n ? 'DATASET_IMPORT_LCA_CANCELLED'\n : 'DATASET_IMPORT_LCA_TIDAS_REPORT_MISSING',\n exitCode: cancelled ? 130 : 70,\n details: { signal: run.signal, stderr: run.stderr },\n },\n );\n }\n return run.stdout;\n}\n\nfunction parseOperationReport(text: string, command: 'version' | 'import'): TidasOperationReport {\n let value: unknown;\n try {\n value = JSON.parse(text);\n } catch (error) {\n throw new CliError('tidas emitted invalid JSON instead of its machine operation report.', {\n code: 'DATASET_IMPORT_LCA_TIDAS_REPORT_INVALID',\n exitCode: 70,\n details: String(error),\n });\n }\n if (\n !isRecord(value) ||\n value.schema_version !== OPERATION_REPORT_SCHEMA ||\n value.command !== command ||\n !includesValue(OPERATION_STATUSES, value.status) ||\n !isExitClass(value.exit_class) ||\n !includesValue(COMPLETENESS_VALUES, value.completeness) ||\n !isRecord(value.invocation) ||\n value.invocation.schema_version !== INVOCATION_CONTEXT_SCHEMA ||\n value.invocation.input_policy !== 'explicit-path-or-dash' ||\n !['stdout', 'file'].includes(String(value.invocation.report_destination)) ||\n value.invocation.diagnostic_destination !== 'stderr' ||\n !isRecord(value.summary) ||\n !Array.isArray(value.diagnostics) ||\n !Array.isArray(value.artifacts) ||\n !Array.isArray(value.next_actions)\n ) {\n throw new CliError(\n `Incompatible tidas ${command} machine contract; expected ${OPERATION_REPORT_SCHEMA}.`,\n {\n code: 'DATASET_IMPORT_LCA_TIDAS_CONTRACT_INCOMPATIBLE',\n exitCode: 69,\n },\n );\n }\n return value as TidasOperationReport;\n}\n\nfunction assertExitContract(run: TidasProcessResult, report: TidasOperationReport): void {\n const expected = EXIT_CODES[report.exit_class];\n if (run.status !== expected) {\n throw new CliError(\n `tidas exit status ${String(run.status)} disagrees with report exit class ${report.exit_class} (${expected}).`,\n {\n code: 'DATASET_IMPORT_LCA_TIDAS_EXIT_MISMATCH',\n exitCode: 70,\n },\n );\n }\n}\n\nfunction readCompatibleVersion(report: TidasOperationReport): string {\n if (\n report.status !== 'succeeded' ||\n report.exit_class !== 'success' ||\n report.completeness !== 'complete' ||\n report.summary.operation_report_schema !== OPERATION_REPORT_SCHEMA ||\n typeof report.summary.binary_version !== 'string' ||\n !SUPPORTED_TIDAS_VERSION.test(report.summary.binary_version)\n ) {\n throw new CliError(\n 'Incompatible tidas binary: dataset import requires a stable contract-compatible 0.2.x release.',\n {\n code: 'DATASET_IMPORT_LCA_TIDAS_VERSION_INCOMPATIBLE',\n exitCode: 69,\n details: { binary_version: report.summary.binary_version ?? null },\n },\n );\n }\n return report.summary.binary_version;\n}\n\nfunction assertImportContract(report: TidasOperationReport): void {\n if (report.status === 'succeeded' || report.status === 'completed-with-issues') {\n const importSummary = report.summary.import;\n if (!isRecord(importSummary) || importSummary.schema_version !== IMPORT_REPORT_SCHEMA) {\n throw new CliError(`Incompatible tidas import summary; expected ${IMPORT_REPORT_SCHEMA}.`, {\n code: 'DATASET_IMPORT_LCA_TIDAS_IMPORT_CONTRACT_INCOMPATIBLE',\n exitCode: 69,\n });\n }\n }\n}\n\nfunction requireInputPath(value: string): string {\n if (!value?.trim()) {\n throw new CliError('Missing required --input value.', {\n code: 'DATASET_IMPORT_LCA_INPUT_REQUIRED',\n exitCode: 2,\n });\n }\n const resolved = path.resolve(value);\n if (!existsSync(resolved)) {\n throw new CliError(`Input path not found: ${resolved}`, {\n code: 'DATASET_IMPORT_LCA_INPUT_NOT_FOUND',\n exitCode: 2,\n });\n }\n return resolved;\n}\n\nfunction requireOutputDir(value: string): string {\n if (!value?.trim()) {\n throw new CliError('Missing required --output-dir value.', {\n code: 'DATASET_IMPORT_LCA_OUTPUT_DIR_REQUIRED',\n exitCode: 2,\n });\n }\n return path.resolve(value);\n}\n\nfunction normalizeSourceFormat(value: string | undefined): DatasetImportLcaSourceFormat | 'auto' {\n const format = value?.trim() || 'auto';\n if (format === 'auto' || includesValue(SOURCE_FORMATS, format)) {\n return format;\n }\n throw new CliError(`--from-format must be auto or one of: ${SOURCE_FORMATS.join(', ')}.`, {\n code: 'DATASET_IMPORT_LCA_SOURCE_FORMAT_INVALID',\n exitCode: 2,\n });\n}\n\nfunction normalizeTarget(value: string | undefined): DatasetImportLcaTarget {\n const target = value?.trim() || 'tidas';\n if (target === 'tidas' || target === 'ilcd' || target === 'both') {\n return target;\n }\n throw new CliError(\"--target must be 'tidas', 'ilcd', or 'both'.\", {\n code: 'DATASET_IMPORT_LCA_TARGET_INVALID',\n exitCode: 2,\n });\n}\n\nfunction resolveTidasBinary(explicitValue: string | undefined, env: NodeJS.ProcessEnv): string {\n const candidate = explicitValue?.trim() || env.TIDAS_BIN?.trim() || 'tidas';\n if (path.isAbsolute(candidate) || candidate.includes('/') || candidate.includes('\\\\')) {\n const resolved = path.resolve(candidate);\n if (!existsSync(resolved)) {\n throw new CliError(`Rust tidas binary not found: ${resolved}`, {\n code: 'DATASET_IMPORT_LCA_TIDAS_NOT_FOUND',\n exitCode: 69,\n });\n }\n return resolved;\n }\n return candidate;\n}\n\nfunction assertSupportedPlatform(platform: NodeJS.Platform, arch: string): void {\n const supported =\n (platform === 'linux' && (arch === 'x64' || arch === 'arm64')) ||\n (platform === 'darwin' && (arch === 'x64' || arch === 'arm64')) ||\n (platform === 'win32' && arch === 'x64');\n if (!supported) {\n throw new CliError(`No supported Rust tidas artifact exists for ${platform}/${arch}.`, {\n code: 'DATASET_IMPORT_LCA_PLATFORM_UNSUPPORTED',\n exitCode: 69,\n details: {\n supported: ['linux/x64', 'linux/arm64', 'darwin/x64', 'darwin/arm64', 'win32/x64'],\n },\n });\n }\n}\n\nfunction requirePositiveInteger(flag: string, value: number | undefined): void {\n if (value !== undefined && (!Number.isSafeInteger(value) || value <= 0)) {\n throw new CliError(`${flag} must be a positive integer.`, {\n code: 'DATASET_IMPORT_LCA_RUNTIME_BOUND_INVALID',\n exitCode: 2,\n });\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value) && typeof value === 'object' && !Array.isArray(value);\n}\n\nfunction includesValue<T extends readonly string[]>(values: T, value: unknown): value is T[number] {\n return typeof value === 'string' && values.includes(value);\n}\n\nfunction isExitClass(value: unknown): value is TidasExitClass {\n return typeof value === 'string' && Object.hasOwn(EXIT_CODES, value);\n}\n\nexport const __testInternals = {\n assertImportContract,\n assertSupportedPlatform,\n buildImportArgs,\n normalizeSourceFormat,\n normalizeTarget,\n parseOperationReport,\n readCompatibleVersion,\n readProcessReport,\n requirePositiveInteger,\n resolveTidasBinary,\n};\n"]}
1
+ {"version":3,"file":"dataset-import-lca.js","sourceRoot":"","sources":["../../../src/lib/dataset-import-lca.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readFileSync } from 'node:fs';\nimport path from 'node:path';\nimport { spawnSync, type SpawnSyncReturns } from 'node:child_process';\nimport { CliError } from './errors.js';\n\nconst OPERATION_REPORT_SCHEMA = 'tidas.operation-report.v1';\nconst INVOCATION_CONTEXT_SCHEMA = 'tidas.invocation-context.v1';\nconst IMPORT_REPORT_SCHEMA = 'tidas.import-execution-report.v1';\nconst SUPPORTED_TIDAS_VERSION = /^0\\.2\\.\\d+$/u;\n\nconst EXIT_CODES = {\n success: 0,\n 'data-issues': 2,\n usage: 64,\n unavailable: 69,\n internal: 70,\n io: 74,\n cancelled: 130,\n} as const;\n\nconst OPERATION_STATUSES = ['succeeded', 'completed-with-issues', 'failed', 'cancelled'] as const;\nconst COMPLETENESS_VALUES = ['complete', 'partial', 'not-started'] as const;\nconst SOURCE_FORMATS = [\n 'ecospold1',\n 'ecospold2',\n 'simapro-csv',\n 'openlca-jsonld',\n 'openlca-process-xlsx',\n 'ilcd',\n] as const;\n\ntype TidasExitClass = keyof typeof EXIT_CODES;\ntype TidasOperationStatus = (typeof OPERATION_STATUSES)[number];\ntype TidasCompleteness = (typeof COMPLETENESS_VALUES)[number];\nexport type DatasetImportLcaTarget = 'tidas' | 'ilcd' | 'both';\nexport type DatasetImportLcaSourceFormat = (typeof SOURCE_FORMATS)[number];\n\ntype TidasOperationReport = {\n schema_version: typeof OPERATION_REPORT_SCHEMA;\n command: 'version' | 'import';\n status: TidasOperationStatus;\n exit_class: TidasExitClass;\n completeness: TidasCompleteness;\n invocation: {\n schema_version: typeof INVOCATION_CONTEXT_SCHEMA;\n input_policy: 'explicit-path-or-dash';\n report_destination: 'stdout' | 'file';\n diagnostic_destination: 'stderr';\n [key: string]: unknown;\n };\n summary: Record<string, unknown>;\n diagnostics: unknown[];\n artifacts: unknown[];\n next_actions: unknown[];\n};\n\nexport type DatasetImportLcaReport = {\n schema_version: 'tiangong-lca.dataset-import-lca-report.v2';\n status: TidasOperationStatus;\n exit_class: TidasExitClass;\n exit_code: number;\n generated_at_utc: string;\n input_path: string;\n output_dir: string;\n from_format: DatasetImportLcaSourceFormat | 'auto';\n target: DatasetImportLcaTarget;\n tidas: {\n executable: string;\n version: string;\n operation_report_schema: typeof OPERATION_REPORT_SCHEMA;\n import_report_schema: typeof IMPORT_REPORT_SCHEMA;\n };\n command: {\n args: string[];\n cwd: string;\n stderr: string;\n };\n operation_report: TidasOperationReport;\n files: {\n report: string | null;\n native_import_report: string;\n issues: string;\n tidas_dir: string | null;\n ilcd_dir: string | null;\n mapping_csv: string | null;\n process_bundles_dir: string | null;\n };\n};\n\nexport type TidasProcessResult = {\n status: number | null;\n signal: NodeJS.Signals | null;\n stdout: string;\n stderr: string;\n error?: Error | undefined;\n};\n\nexport type RunDatasetImportLcaConvertOptions = {\n inputPath: string;\n outputDir: string;\n fromFormat?: string | undefined;\n target?: string | undefined;\n reportPath?: string | undefined;\n writeMapping?: boolean | undefined;\n processBundles?: boolean | undefined;\n failOnWarning?: boolean | undefined;\n maxEntryMib?: number | undefined;\n memoryBudgetMib?: number | undefined;\n queueCapacity?: number | undefined;\n tidasBin?: string | undefined;\n tidasConfig?: string | undefined;\n env?: NodeJS.ProcessEnv | undefined;\n cwd?: string | undefined;\n platform?: NodeJS.Platform | undefined;\n arch?: string | undefined;\n now?: Date | undefined;\n spawnImpl?: typeof spawnSync | undefined;\n};\n\nexport async function runDatasetImportLcaConvert(\n options: RunDatasetImportLcaConvertOptions,\n): Promise<DatasetImportLcaReport> {\n const inputPath = requireInputPath(options.inputPath);\n const outputDir = requireOutputDir(options.outputDir);\n const fromFormat = normalizeSourceFormat(options.fromFormat);\n const target = normalizeTarget(options.target);\n const env = options.env ?? process.env;\n const executable = resolveTidasBinary(options.tidasBin, env);\n const cwd = path.resolve(options.cwd ?? process.cwd());\n const reportPath = options.reportPath?.trim() ? path.resolve(options.reportPath) : null;\n const configPath = options.tidasConfig?.trim() ? path.resolve(options.tidasConfig) : null;\n const spawnImpl = [spawnSync, options.spawnImpl].filter(Boolean).at(-1) as typeof spawnSync;\n\n assertSupportedPlatform(options.platform ?? process.platform, options.arch ?? process.arch);\n requirePositiveInteger('--max-entry-mib', options.maxEntryMib);\n requirePositiveInteger('--memory-budget-mib', options.memoryBudgetMib);\n requirePositiveInteger('--queue-capacity', options.queueCapacity);\n\n const versionArgs = ['version', '--format', 'json', '--progress', 'never'];\n const versionRun = runTidas(spawnImpl, executable, versionArgs, cwd, env);\n const versionReport = parseOperationReport(readProcessReport(versionRun, null), 'version');\n assertExitContract(versionRun, versionReport);\n const version = readCompatibleVersion(versionReport);\n\n const commandArgs = buildImportArgs({\n inputPath,\n outputDir,\n fromFormat,\n target,\n reportPath,\n configPath,\n writeMapping: Boolean(options.writeMapping),\n processBundles: options.processBundles !== false,\n failOnWarning: Boolean(options.failOnWarning),\n maxEntryMib: options.maxEntryMib,\n memoryBudgetMib: options.memoryBudgetMib,\n queueCapacity: options.queueCapacity,\n });\n const importRun = runTidas(spawnImpl, executable, commandArgs, cwd, env);\n const operationReport = parseOperationReport(readProcessReport(importRun, reportPath), 'import');\n assertExitContract(importRun, operationReport);\n assertImportContract(operationReport);\n\n return {\n schema_version: 'tiangong-lca.dataset-import-lca-report.v2',\n status: operationReport.status,\n exit_class: operationReport.exit_class,\n exit_code: EXIT_CODES[operationReport.exit_class],\n generated_at_utc: (options.now ?? new Date()).toISOString(),\n input_path: inputPath,\n output_dir: outputDir,\n from_format: fromFormat,\n target,\n tidas: {\n executable,\n version,\n operation_report_schema: OPERATION_REPORT_SCHEMA,\n import_report_schema: IMPORT_REPORT_SCHEMA,\n },\n command: {\n args: commandArgs,\n cwd,\n stderr: importRun.stderr,\n },\n operation_report: operationReport,\n files: {\n report: reportPath,\n native_import_report: path.join(outputDir, 'import-report.json'),\n issues: path.join(outputDir, 'issues.jsonl'),\n tidas_dir:\n operationReport.completeness === 'complete' && (target === 'tidas' || target === 'both')\n ? path.join(outputDir, 'tidas')\n : null,\n ilcd_dir:\n operationReport.completeness === 'complete' && (target === 'ilcd' || target === 'both')\n ? path.join(outputDir, 'ilcd')\n : null,\n mapping_csv:\n operationReport.completeness === 'complete' && options.writeMapping\n ? path.join(outputDir, 'mapping.csv.gz')\n : null,\n process_bundles_dir:\n operationReport.completeness === 'complete' && options.processBundles !== false\n ? path.join(outputDir, 'process-bundles')\n : null,\n },\n };\n}\n\nfunction buildImportArgs(options: {\n inputPath: string;\n outputDir: string;\n fromFormat: DatasetImportLcaSourceFormat | 'auto';\n target: DatasetImportLcaTarget;\n reportPath: string | null;\n configPath: string | null;\n writeMapping: boolean;\n processBundles: boolean;\n failOnWarning: boolean;\n maxEntryMib: number | undefined;\n memoryBudgetMib: number | undefined;\n queueCapacity: number | undefined;\n}): string[] {\n const args = [\n 'import',\n options.inputPath,\n '--output',\n options.outputDir,\n '--target',\n options.target,\n '--format',\n 'json',\n '--progress',\n 'never',\n ];\n if (options.fromFormat !== 'auto') {\n args.push('--from-format', options.fromFormat);\n }\n if (options.reportPath) {\n args.push('--report', options.reportPath);\n }\n if (options.configPath) {\n args.push('--config', options.configPath);\n }\n if (options.writeMapping) {\n args.push('--write-mapping');\n }\n if (!options.processBundles) {\n args.push('--no-process-bundles');\n }\n if (options.failOnWarning) {\n args.push('--fail-on-warning');\n }\n if (options.maxEntryMib !== undefined) {\n args.push('--max-entry-mib', String(options.maxEntryMib));\n }\n if (options.memoryBudgetMib !== undefined) {\n args.push('--memory-budget-mib', String(options.memoryBudgetMib));\n }\n if (options.queueCapacity !== undefined) {\n args.push('--queue-capacity', String(options.queueCapacity));\n }\n return args;\n}\n\nfunction runTidas(\n spawnImpl: typeof spawnSync,\n executable: string,\n args: string[],\n cwd: string,\n env: NodeJS.ProcessEnv,\n): TidasProcessResult {\n const run = spawnImpl(executable, args, {\n cwd,\n env,\n encoding: 'utf8',\n windowsHide: true,\n }) as SpawnSyncReturns<string>;\n if (run.error) {\n throw new CliError(`Could not execute the Rust tidas binary: ${run.error.message}`, {\n code: 'DATASET_IMPORT_LCA_TIDAS_EXEC_FAILED',\n exitCode: 69,\n details: { executable },\n });\n }\n return {\n status: run.status,\n signal: run.signal,\n stdout: run.stdout ?? '',\n stderr: run.stderr ?? '',\n };\n}\n\nfunction readProcessReport(run: TidasProcessResult, reportPath: string | null): string {\n const cancelled = run.status === 130 || run.signal === 'SIGINT';\n if (reportPath) {\n if (!existsSync(reportPath)) {\n if (cancelled) {\n throw new CliError(\n 'tidas import was cancelled before a complete machine report was available.',\n {\n code: 'DATASET_IMPORT_LCA_CANCELLED',\n exitCode: 130,\n details: { signal: run.signal, stderr: run.stderr },\n },\n );\n }\n throw new CliError(`tidas did not write the requested machine report: ${reportPath}`, {\n code: 'DATASET_IMPORT_LCA_TIDAS_REPORT_MISSING',\n exitCode: 70,\n });\n }\n return readFileSync(reportPath, 'utf8');\n }\n if (!run.stdout.trim()) {\n throw new CliError(\n cancelled\n ? 'tidas import was cancelled before a complete machine report was available.'\n : 'tidas did not emit a machine-readable operation report.',\n {\n code: cancelled\n ? 'DATASET_IMPORT_LCA_CANCELLED'\n : 'DATASET_IMPORT_LCA_TIDAS_REPORT_MISSING',\n exitCode: cancelled ? 130 : 70,\n details: { signal: run.signal, stderr: run.stderr },\n },\n );\n }\n return run.stdout;\n}\n\nfunction parseOperationReport(text: string, command: 'version' | 'import'): TidasOperationReport {\n let value: unknown;\n try {\n value = JSON.parse(text);\n } catch (error) {\n throw new CliError('tidas emitted invalid JSON instead of its machine operation report.', {\n code: 'DATASET_IMPORT_LCA_TIDAS_REPORT_INVALID',\n exitCode: 70,\n details: String(error),\n });\n }\n if (\n !isRecord(value) ||\n value.schema_version !== OPERATION_REPORT_SCHEMA ||\n value.command !== command ||\n !includesValue(OPERATION_STATUSES, value.status) ||\n !isExitClass(value.exit_class) ||\n !includesValue(COMPLETENESS_VALUES, value.completeness) ||\n !isRecord(value.invocation) ||\n value.invocation.schema_version !== INVOCATION_CONTEXT_SCHEMA ||\n value.invocation.input_policy !== 'explicit-path-or-dash' ||\n !['stdout', 'file'].includes(String(value.invocation.report_destination)) ||\n value.invocation.diagnostic_destination !== 'stderr' ||\n !isRecord(value.summary) ||\n !Array.isArray(value.diagnostics) ||\n !Array.isArray(value.artifacts) ||\n !Array.isArray(value.next_actions)\n ) {\n throw new CliError(\n `Incompatible tidas ${command} machine contract; expected ${OPERATION_REPORT_SCHEMA}.`,\n {\n code: 'DATASET_IMPORT_LCA_TIDAS_CONTRACT_INCOMPATIBLE',\n exitCode: 69,\n },\n );\n }\n return value as TidasOperationReport;\n}\n\nfunction assertExitContract(run: TidasProcessResult, report: TidasOperationReport): void {\n const expected = EXIT_CODES[report.exit_class];\n if (run.status !== expected) {\n throw new CliError(\n `tidas exit status ${String(run.status)} disagrees with report exit class ${report.exit_class} (${expected}).`,\n {\n code: 'DATASET_IMPORT_LCA_TIDAS_EXIT_MISMATCH',\n exitCode: 70,\n },\n );\n }\n}\n\nfunction readCompatibleVersion(report: TidasOperationReport): string {\n if (\n report.status !== 'succeeded' ||\n report.exit_class !== 'success' ||\n report.completeness !== 'complete' ||\n report.summary.operation_report_schema !== OPERATION_REPORT_SCHEMA ||\n typeof report.summary.binary_version !== 'string' ||\n !SUPPORTED_TIDAS_VERSION.test(report.summary.binary_version)\n ) {\n throw new CliError(\n 'Incompatible tidas binary: dataset import requires a stable contract-compatible 0.2.x release.',\n {\n code: 'DATASET_IMPORT_LCA_TIDAS_VERSION_INCOMPATIBLE',\n exitCode: 69,\n details: { binary_version: report.summary.binary_version ?? null },\n },\n );\n }\n return report.summary.binary_version;\n}\n\nfunction assertImportContract(report: TidasOperationReport): void {\n if (report.status === 'succeeded' || report.status === 'completed-with-issues') {\n const importSummary = report.summary.import;\n if (!isRecord(importSummary) || importSummary.schema_version !== IMPORT_REPORT_SCHEMA) {\n throw new CliError(`Incompatible tidas import summary; expected ${IMPORT_REPORT_SCHEMA}.`, {\n code: 'DATASET_IMPORT_LCA_TIDAS_IMPORT_CONTRACT_INCOMPATIBLE',\n exitCode: 69,\n });\n }\n }\n}\n\nfunction requireInputPath(value: string): string {\n if (!value?.trim()) {\n throw new CliError('Missing required --input value.', {\n code: 'DATASET_IMPORT_LCA_INPUT_REQUIRED',\n exitCode: 2,\n });\n }\n const resolved = path.resolve(value);\n if (!existsSync(resolved)) {\n throw new CliError(`Input path not found: ${resolved}`, {\n code: 'DATASET_IMPORT_LCA_INPUT_NOT_FOUND',\n exitCode: 2,\n });\n }\n return resolved;\n}\n\nfunction requireOutputDir(value: string): string {\n if (!value?.trim()) {\n throw new CliError('Missing required --output-dir value.', {\n code: 'DATASET_IMPORT_LCA_OUTPUT_DIR_REQUIRED',\n exitCode: 2,\n });\n }\n return path.resolve(value);\n}\n\nfunction normalizeSourceFormat(value: string | undefined): DatasetImportLcaSourceFormat | 'auto' {\n const format = value?.trim() || 'auto';\n if (format === 'auto' || includesValue(SOURCE_FORMATS, format)) {\n return format;\n }\n throw new CliError(`--from-format must be auto or one of: ${SOURCE_FORMATS.join(', ')}.`, {\n code: 'DATASET_IMPORT_LCA_SOURCE_FORMAT_INVALID',\n exitCode: 2,\n });\n}\n\nfunction normalizeTarget(value: string | undefined): DatasetImportLcaTarget {\n const target = value?.trim() || 'tidas';\n if (target === 'tidas' || target === 'ilcd' || target === 'both') {\n return target;\n }\n throw new CliError(\"--target must be 'tidas', 'ilcd', or 'both'.\", {\n code: 'DATASET_IMPORT_LCA_TARGET_INVALID',\n exitCode: 2,\n });\n}\n\nfunction resolveTidasBinary(explicitValue: string | undefined, env: NodeJS.ProcessEnv): string {\n const candidate = explicitValue?.trim() || env.TIDAS_BIN?.trim() || 'tidas';\n if (path.isAbsolute(candidate) || candidate.includes('/') || candidate.includes('\\\\')) {\n const resolved = path.resolve(candidate);\n if (!existsSync(resolved)) {\n throw new CliError(`Rust tidas binary not found: ${resolved}`, {\n code: 'DATASET_IMPORT_LCA_TIDAS_NOT_FOUND',\n exitCode: 69,\n });\n }\n return resolved;\n }\n return candidate;\n}\n\nfunction assertSupportedPlatform(platform: NodeJS.Platform, arch: string): void {\n const supported =\n (platform === 'linux' && (arch === 'x64' || arch === 'arm64')) ||\n (platform === 'darwin' && arch === 'arm64') ||\n (platform === 'win32' && arch === 'x64');\n if (!supported) {\n throw new CliError(`No supported Rust tidas artifact exists for ${platform}/${arch}.`, {\n code: 'DATASET_IMPORT_LCA_PLATFORM_UNSUPPORTED',\n exitCode: 69,\n details: {\n supported: ['linux/x64', 'linux/arm64', 'darwin/arm64', 'win32/x64'],\n },\n });\n }\n}\n\nfunction requirePositiveInteger(flag: string, value: number | undefined): void {\n if (value !== undefined && (!Number.isSafeInteger(value) || value <= 0)) {\n throw new CliError(`${flag} must be a positive integer.`, {\n code: 'DATASET_IMPORT_LCA_RUNTIME_BOUND_INVALID',\n exitCode: 2,\n });\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value) && typeof value === 'object' && !Array.isArray(value);\n}\n\nfunction includesValue<T extends readonly string[]>(values: T, value: unknown): value is T[number] {\n return typeof value === 'string' && values.includes(value);\n}\n\nfunction isExitClass(value: unknown): value is TidasExitClass {\n return typeof value === 'string' && Object.hasOwn(EXIT_CODES, value);\n}\n\nexport const __testInternals = {\n assertImportContract,\n assertSupportedPlatform,\n buildImportArgs,\n normalizeSourceFormat,\n normalizeTarget,\n parseOperationReport,\n readCompatibleVersion,\n readProcessReport,\n requirePositiveInteger,\n resolveTidasBinary,\n};\n"]}
@@ -0,0 +1,7 @@
1
+ import type { ComponentFile } from './manifest-types.js';
2
+ export declare function runtimeTarHeader(file: ComponentFile): Buffer;
3
+ /** Release-side writer. The producer supplies an explicit, already materialized production file inventory. */
4
+ export declare function writeRuntimeComponentArchive(root: string, files: readonly ComponentFile[], target: string): Promise<{
5
+ bytes: number;
6
+ sha256: string;
7
+ }>;
@@ -0,0 +1,89 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { createGzip } from 'node:zlib';
4
+ import { pipeline } from 'node:stream/promises';
5
+ import { createHash } from 'node:crypto';
6
+ import { cachePath } from './storage.js';
7
+ import { hashRuntimeFile, runtimeError } from './files.js';
8
+ import { array, integer, relativeFile, sha, unique } from './manifest-values.js';
9
+ export function runtimeTarHeader(file) {
10
+ const parts = file.path.split('/');
11
+ let name = file.path, prefix = '';
12
+ if (Buffer.byteLength(name) > 100) {
13
+ for (let split = parts.length - 1; split > 0; split--) {
14
+ const head = parts.slice(0, split).join('/'), tail = parts.slice(split).join('/');
15
+ if (Buffer.byteLength(head) <= 155 && Buffer.byteLength(tail) <= 100) {
16
+ prefix = head;
17
+ name = tail;
18
+ break;
19
+ }
20
+ }
21
+ }
22
+ const header = Buffer.alloc(512);
23
+ header.write(name, 0, 100, 'utf8');
24
+ header.write(prefix, 345, 155, 'utf8');
25
+ for (const [offset, length, value] of [
26
+ [100, 8, file.mode],
27
+ [108, 8, 0],
28
+ [116, 8, 0],
29
+ [124, 12, file.bytes],
30
+ [136, 12, 0],
31
+ ])
32
+ header.write(value.toString(8).padStart(length - 1, '0') + '\0', offset, length, 'ascii');
33
+ header.fill(32, 148, 156);
34
+ header[156] = 48;
35
+ header.write('ustar\0', 257, 6, 'ascii');
36
+ header.write('00', 263, 2, 'ascii');
37
+ const checksum = header.reduce((sum, value) => sum + value, 0);
38
+ header.write(checksum.toString(8).padStart(6, '0') + '\0 ', 148, 8, 'ascii');
39
+ return header;
40
+ }
41
+ /** Release-side writer. The producer supplies an explicit, already materialized production file inventory. */
42
+ export async function writeRuntimeComponentArchive(root, files, target) {
43
+ array(files, 50_000, 1);
44
+ unique(files.map((file) => relativeFile(file.path).toLowerCase()), 'archive file');
45
+ if (JSON.stringify(files.map((file) => file.path)) !==
46
+ JSON.stringify(files.map((file) => file.path).sort()))
47
+ runtimeError('RUNTIME_ARCHIVE_ORDER', 'Component archive files must be sorted by portable path.');
48
+ let total = 0;
49
+ for (const file of files) {
50
+ integer(file.bytes, 512 * 1024 * 1024);
51
+ sha(file.sha256);
52
+ if (file.mode !== 420 && file.mode !== 493)
53
+ runtimeError('RUNTIME_ARCHIVE_MODE', 'Component file modes must be 0644 or 0755.');
54
+ total += file.bytes;
55
+ if (total > 2 * 1024 * 1024 * 1024)
56
+ runtimeError('RUNTIME_ARCHIVE_SIZE', 'Component files exceed the unpacked size limit.');
57
+ }
58
+ for (const file of files) {
59
+ const actual = hashRuntimeFile(cachePath(root, file.path), file.path);
60
+ if (actual.bytes !== file.bytes || actual.sha256 !== file.sha256)
61
+ runtimeError('RUNTIME_ARCHIVE_SOURCE_CHANGED', 'Component source changed before packaging.');
62
+ }
63
+ async function* records() {
64
+ for (const file of files) {
65
+ yield runtimeTarHeader(file);
66
+ const hash = createHash('sha256');
67
+ let bytes = 0;
68
+ for await (const chunk of fs.createReadStream(cachePath(root, file.path))) {
69
+ const buffer = chunk;
70
+ bytes += buffer.length;
71
+ if (bytes > file.bytes)
72
+ runtimeError('RUNTIME_ARCHIVE_SOURCE_CHANGED', 'Component source grew while packaging.');
73
+ hash.update(buffer);
74
+ yield buffer;
75
+ }
76
+ if (bytes !== file.bytes || hash.digest('hex') !== file.sha256)
77
+ runtimeError('RUNTIME_ARCHIVE_SOURCE_CHANGED', 'Component source bytes changed while packaging.');
78
+ const padding = (512 - (file.bytes % 512)) % 512;
79
+ if (padding)
80
+ yield Buffer.alloc(padding);
81
+ }
82
+ yield Buffer.alloc(1024);
83
+ }
84
+ fs.mkdirSync(path.dirname(target), { recursive: true, mode: 0o700 });
85
+ await pipeline(records(), createGzip({ level: 9 }), fs.createWriteStream(target, { flags: 'wx', mode: 0o600 }));
86
+ const fact = hashRuntimeFile(target, 'archive');
87
+ return { bytes: fact.bytes, sha256: fact.sha256 };
88
+ }
89
+ //# sourceMappingURL=archive-writer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"archive-writer.js","sourceRoot":"","sources":["../../../../src/lib/runtime/archive-writer.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport { createGzip } from 'node:zlib';\nimport { pipeline } from 'node:stream/promises';\nimport { createHash } from 'node:crypto';\nimport { cachePath } from './storage.js';\nimport { hashRuntimeFile, runtimeError } from './files.js';\nimport { array, integer, relativeFile, sha, unique } from './manifest-values.js';\nimport type { ComponentFile } from './manifest-types.js';\n\nexport function runtimeTarHeader(file: ComponentFile): Buffer {\n const parts = file.path.split('/');\n let name = file.path,\n prefix = '';\n if (Buffer.byteLength(name) > 100) {\n for (let split = parts.length - 1; split > 0; split--) {\n const head = parts.slice(0, split).join('/'),\n tail = parts.slice(split).join('/');\n if (Buffer.byteLength(head) <= 155 && Buffer.byteLength(tail) <= 100) {\n prefix = head;\n name = tail;\n break;\n }\n }\n }\n const header = Buffer.alloc(512);\n header.write(name, 0, 100, 'utf8');\n header.write(prefix, 345, 155, 'utf8');\n for (const [offset, length, value] of [\n [100, 8, file.mode],\n [108, 8, 0],\n [116, 8, 0],\n [124, 12, file.bytes],\n [136, 12, 0],\n ] as const)\n header.write(value.toString(8).padStart(length - 1, '0') + '\\0', offset, length, 'ascii');\n header.fill(32, 148, 156);\n header[156] = 48;\n header.write('ustar\\0', 257, 6, 'ascii');\n header.write('00', 263, 2, 'ascii');\n const checksum = header.reduce((sum, value) => sum + value, 0);\n header.write(checksum.toString(8).padStart(6, '0') + '\\0 ', 148, 8, 'ascii');\n return header;\n}\n/** Release-side writer. The producer supplies an explicit, already materialized production file inventory. */\nexport async function writeRuntimeComponentArchive(\n root: string,\n files: readonly ComponentFile[],\n target: string,\n): Promise<{ bytes: number; sha256: string }> {\n array(files, 50_000, 1);\n unique(\n files.map((file) => relativeFile(file.path).toLowerCase()),\n 'archive file',\n );\n if (\n JSON.stringify(files.map((file) => file.path)) !==\n JSON.stringify(files.map((file) => file.path).sort())\n )\n runtimeError(\n 'RUNTIME_ARCHIVE_ORDER',\n 'Component archive files must be sorted by portable path.',\n );\n let total = 0;\n for (const file of files) {\n integer(file.bytes, 512 * 1024 * 1024);\n sha(file.sha256);\n if (file.mode !== 420 && file.mode !== 493)\n runtimeError('RUNTIME_ARCHIVE_MODE', 'Component file modes must be 0644 or 0755.');\n total += file.bytes;\n if (total > 2 * 1024 * 1024 * 1024)\n runtimeError('RUNTIME_ARCHIVE_SIZE', 'Component files exceed the unpacked size limit.');\n }\n for (const file of files) {\n const actual = hashRuntimeFile(cachePath(root, file.path), file.path);\n if (actual.bytes !== file.bytes || actual.sha256 !== file.sha256)\n runtimeError('RUNTIME_ARCHIVE_SOURCE_CHANGED', 'Component source changed before packaging.');\n }\n async function* records() {\n for (const file of files) {\n yield runtimeTarHeader(file);\n const hash = createHash('sha256');\n let bytes = 0;\n for await (const chunk of fs.createReadStream(cachePath(root, file.path))) {\n const buffer = chunk as Buffer;\n bytes += buffer.length;\n if (bytes > file.bytes)\n runtimeError('RUNTIME_ARCHIVE_SOURCE_CHANGED', 'Component source grew while packaging.');\n hash.update(buffer);\n yield buffer;\n }\n if (bytes !== file.bytes || hash.digest('hex') !== file.sha256)\n runtimeError(\n 'RUNTIME_ARCHIVE_SOURCE_CHANGED',\n 'Component source bytes changed while packaging.',\n );\n const padding = (512 - (file.bytes % 512)) % 512;\n if (padding) yield Buffer.alloc(padding);\n }\n yield Buffer.alloc(1024);\n }\n fs.mkdirSync(path.dirname(target), { recursive: true, mode: 0o700 });\n await pipeline(\n records(),\n createGzip({ level: 9 }),\n fs.createWriteStream(target, { flags: 'wx', mode: 0o600 }),\n );\n const fact = hashRuntimeFile(target, 'archive');\n return { bytes: fact.bytes, sha256: fact.sha256 };\n}\n"]}
@@ -0,0 +1,2 @@
1
+ import type { RuntimeComponent } from './manifest-types.js';
2
+ export declare function extractRuntimeArchive(archive: string, root: string, component: RuntimeComponent, signal?: AbortSignal): Promise<void>;
@@ -0,0 +1,122 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { createHash } from 'node:crypto';
4
+ import { createGunzip } from 'node:zlib';
5
+ import { pipeline } from 'node:stream/promises';
6
+ import { cachePath, writeAll } from './storage.js';
7
+ import { runtimeError } from './files.js';
8
+ function field(header, start, length) {
9
+ const bytes = header.subarray(start, start + length);
10
+ const zero = bytes.indexOf(0);
11
+ if (zero >= 0 && bytes.subarray(zero).some((value) => value !== 0))
12
+ runtimeError('RUNTIME_ARCHIVE_HEADER', 'USTAR text padding is invalid.');
13
+ try {
14
+ return new TextDecoder('utf-8', { fatal: true, ignoreBOM: true }).decode(zero < 0 ? bytes : bytes.subarray(0, zero));
15
+ }
16
+ catch {
17
+ runtimeError('RUNTIME_ARCHIVE_HEADER', 'USTAR paths must be valid UTF-8.');
18
+ }
19
+ }
20
+ function octal(bytes) {
21
+ const raw = bytes.toString('ascii');
22
+ let end = raw.length;
23
+ while (end > 0 && (raw[end - 1] === '\0' || raw[end - 1] === ' '))
24
+ end--;
25
+ const digits = raw.slice(0, end);
26
+ if (!/^[0-7]+$/u.test(digits))
27
+ runtimeError('RUNTIME_ARCHIVE_HEADER', 'USTAR numeric fields must use bounded octal.');
28
+ // All callers supply at most twelve octets; the value is within exact integer range.
29
+ return Number.parseInt(digits, 8);
30
+ }
31
+ function readExact(fd, buffer, position) {
32
+ let offset = 0;
33
+ while (offset < buffer.length) {
34
+ const count = fs.readSync(fd, buffer, offset, buffer.length - offset, position + offset);
35
+ if (count === 0)
36
+ runtimeError('RUNTIME_ARCHIVE_TRUNCATED', 'Runtime archive ended before its declared content.');
37
+ offset += count;
38
+ }
39
+ }
40
+ export async function extractRuntimeArchive(archive, root, component, signal) {
41
+ const decoded = `${root}.tar`;
42
+ const expectedBytes = 1024 + component.files.reduce((sum, file) => sum + 512 + Math.ceil(file.bytes / 512) * 512, 0);
43
+ let decodedBytes = 0;
44
+ await pipeline(fs.createReadStream(archive), createGunzip(), async function* (source) {
45
+ for await (const chunk of source) {
46
+ decodedBytes += chunk.length;
47
+ if (decodedBytes > expectedBytes)
48
+ runtimeError('RUNTIME_ARCHIVE_SIZE', 'Decoded archive exceeds its exact inventory size.');
49
+ yield chunk;
50
+ }
51
+ }, fs.createWriteStream(decoded, { flags: 'wx', mode: 0o600 }), { signal });
52
+ if (decodedBytes !== expectedBytes)
53
+ runtimeError('RUNTIME_ARCHIVE_SIZE', 'Decoded archive size does not match its inventory.');
54
+ fs.mkdirSync(root, { mode: 0o700 });
55
+ const fd = fs.openSync(decoded, 'r');
56
+ let position = 0;
57
+ try {
58
+ for (const file of component.files) {
59
+ signal?.throwIfAborted();
60
+ const header = Buffer.alloc(512);
61
+ readExact(fd, header, position);
62
+ position += 512;
63
+ const checksum = octal(header.subarray(148, 156));
64
+ const unsigned = Buffer.from(header);
65
+ unsigned.fill(32, 148, 156);
66
+ if (unsigned.reduce((sum, value) => sum + value, 0) !== checksum ||
67
+ header.toString('ascii', 257, 263) !== 'ustar\0' ||
68
+ header.toString('ascii', 263, 265) !== '00' ||
69
+ ![0, 48].includes(header[156]))
70
+ runtimeError('RUNTIME_ARCHIVE_HEADER', 'Runtime archives require regular-file USTAR entries only.');
71
+ const prefix = field(header, 345, 155), name = field(header, 0, 100);
72
+ const relative = prefix ? `${prefix}/${name}` : name;
73
+ if (relative !== file.path ||
74
+ octal(header.subarray(100, 108)) !== file.mode ||
75
+ octal(header.subarray(124, 136)) !== file.bytes ||
76
+ field(header, 157, 100) !== '')
77
+ runtimeError('RUNTIME_ARCHIVE_ENTRY', 'Archive path, mode or size differs from its trusted inventory.');
78
+ const output = cachePath(root, file.path);
79
+ fs.mkdirSync(path.dirname(output), { recursive: true, mode: 0o700 });
80
+ cachePath(root, file.path);
81
+ const out = fs.openSync(output, 'wx', 0o600);
82
+ const hash = createHash('sha256');
83
+ let remaining = file.bytes;
84
+ const buffer = Buffer.alloc(1024 * 1024);
85
+ try {
86
+ while (remaining > 0) {
87
+ signal?.throwIfAborted();
88
+ const chunk = buffer.subarray(0, Math.min(buffer.length, remaining));
89
+ readExact(fd, chunk, position);
90
+ position += chunk.length;
91
+ remaining -= chunk.length;
92
+ hash.update(chunk);
93
+ writeAll(out, chunk);
94
+ }
95
+ fs.fsyncSync(out);
96
+ }
97
+ finally {
98
+ fs.closeSync(out);
99
+ }
100
+ if (hash.digest('hex') !== file.sha256)
101
+ runtimeError('RUNTIME_ARCHIVE_INTEGRITY', 'An extracted file does not match its trusted SHA-256.');
102
+ fs.chmodSync(output, file.mode);
103
+ const padding = (512 - (file.bytes % 512)) % 512;
104
+ if (padding) {
105
+ const bytes = Buffer.alloc(padding);
106
+ readExact(fd, bytes, position);
107
+ if (bytes.some((value) => value !== 0))
108
+ runtimeError('RUNTIME_ARCHIVE_PADDING', 'USTAR file padding must be empty.');
109
+ position += padding;
110
+ }
111
+ }
112
+ const end = Buffer.alloc(1024);
113
+ readExact(fd, end, position);
114
+ if (end.some((value) => value !== 0))
115
+ runtimeError('RUNTIME_ARCHIVE_TRAILING', 'Runtime archive has unexpected entries or trailing content.');
116
+ }
117
+ finally {
118
+ fs.closeSync(fd);
119
+ fs.unlinkSync(decoded);
120
+ }
121
+ }
122
+ //# sourceMappingURL=archive.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"archive.js","sourceRoot":"","sources":["../../../../src/lib/runtime/archive.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport { createHash } from 'node:crypto';\nimport { createGunzip } from 'node:zlib';\nimport { pipeline } from 'node:stream/promises';\nimport { cachePath, writeAll } from './storage.js';\nimport { runtimeError } from './files.js';\nimport type { RuntimeComponent } from './manifest-types.js';\n\nfunction field(header: Buffer, start: number, length: number): string {\n const bytes = header.subarray(start, start + length);\n const zero = bytes.indexOf(0);\n if (zero >= 0 && bytes.subarray(zero).some((value) => value !== 0))\n runtimeError('RUNTIME_ARCHIVE_HEADER', 'USTAR text padding is invalid.');\n try {\n return new TextDecoder('utf-8', { fatal: true, ignoreBOM: true }).decode(\n zero < 0 ? bytes : bytes.subarray(0, zero),\n );\n } catch {\n runtimeError('RUNTIME_ARCHIVE_HEADER', 'USTAR paths must be valid UTF-8.');\n }\n}\nfunction octal(bytes: Buffer): number {\n const raw = bytes.toString('ascii');\n let end = raw.length;\n while (end > 0 && (raw[end - 1] === '\\0' || raw[end - 1] === ' ')) end--;\n const digits = raw.slice(0, end);\n if (!/^[0-7]+$/u.test(digits))\n runtimeError('RUNTIME_ARCHIVE_HEADER', 'USTAR numeric fields must use bounded octal.');\n // All callers supply at most twelve octets; the value is within exact integer range.\n return Number.parseInt(digits, 8);\n}\nfunction readExact(fd: number, buffer: Buffer, position: number): void {\n let offset = 0;\n while (offset < buffer.length) {\n const count = fs.readSync(fd, buffer, offset, buffer.length - offset, position + offset);\n if (count === 0)\n runtimeError(\n 'RUNTIME_ARCHIVE_TRUNCATED',\n 'Runtime archive ended before its declared content.',\n );\n offset += count;\n }\n}\nexport async function extractRuntimeArchive(\n archive: string,\n root: string,\n component: RuntimeComponent,\n signal?: AbortSignal,\n): Promise<void> {\n const decoded = `${root}.tar`;\n const expectedBytes =\n 1024 + component.files.reduce((sum, file) => sum + 512 + Math.ceil(file.bytes / 512) * 512, 0);\n let decodedBytes = 0;\n await pipeline(\n fs.createReadStream(archive),\n createGunzip(),\n async function* (source: AsyncIterable<Buffer>) {\n for await (const chunk of source) {\n decodedBytes += chunk.length;\n if (decodedBytes > expectedBytes)\n runtimeError('RUNTIME_ARCHIVE_SIZE', 'Decoded archive exceeds its exact inventory size.');\n yield chunk;\n }\n },\n fs.createWriteStream(decoded, { flags: 'wx', mode: 0o600 }),\n { signal },\n );\n if (decodedBytes !== expectedBytes)\n runtimeError('RUNTIME_ARCHIVE_SIZE', 'Decoded archive size does not match its inventory.');\n fs.mkdirSync(root, { mode: 0o700 });\n const fd = fs.openSync(decoded, 'r');\n let position = 0;\n try {\n for (const file of component.files) {\n signal?.throwIfAborted();\n const header = Buffer.alloc(512);\n readExact(fd, header, position);\n position += 512;\n const checksum = octal(header.subarray(148, 156));\n const unsigned = Buffer.from(header);\n unsigned.fill(32, 148, 156);\n if (\n unsigned.reduce((sum, value) => sum + value, 0) !== checksum ||\n header.toString('ascii', 257, 263) !== 'ustar\\0' ||\n header.toString('ascii', 263, 265) !== '00' ||\n ![0, 48].includes(header[156]!)\n )\n runtimeError(\n 'RUNTIME_ARCHIVE_HEADER',\n 'Runtime archives require regular-file USTAR entries only.',\n );\n const prefix = field(header, 345, 155),\n name = field(header, 0, 100);\n const relative = prefix ? `${prefix}/${name}` : name;\n if (\n relative !== file.path ||\n octal(header.subarray(100, 108)) !== file.mode ||\n octal(header.subarray(124, 136)) !== file.bytes ||\n field(header, 157, 100) !== ''\n )\n runtimeError(\n 'RUNTIME_ARCHIVE_ENTRY',\n 'Archive path, mode or size differs from its trusted inventory.',\n );\n const output = cachePath(root, file.path);\n fs.mkdirSync(path.dirname(output), { recursive: true, mode: 0o700 });\n cachePath(root, file.path);\n const out = fs.openSync(output, 'wx', 0o600);\n const hash = createHash('sha256');\n let remaining = file.bytes;\n const buffer = Buffer.alloc(1024 * 1024);\n try {\n while (remaining > 0) {\n signal?.throwIfAborted();\n const chunk = buffer.subarray(0, Math.min(buffer.length, remaining));\n readExact(fd, chunk, position);\n position += chunk.length;\n remaining -= chunk.length;\n hash.update(chunk);\n writeAll(out, chunk);\n }\n fs.fsyncSync(out);\n } finally {\n fs.closeSync(out);\n }\n if (hash.digest('hex') !== file.sha256)\n runtimeError(\n 'RUNTIME_ARCHIVE_INTEGRITY',\n 'An extracted file does not match its trusted SHA-256.',\n );\n fs.chmodSync(output, file.mode);\n const padding = (512 - (file.bytes % 512)) % 512;\n if (padding) {\n const bytes = Buffer.alloc(padding);\n readExact(fd, bytes, position);\n if (bytes.some((value) => value !== 0))\n runtimeError('RUNTIME_ARCHIVE_PADDING', 'USTAR file padding must be empty.');\n position += padding;\n }\n }\n const end = Buffer.alloc(1024);\n readExact(fd, end, position);\n if (end.some((value) => value !== 0))\n runtimeError(\n 'RUNTIME_ARCHIVE_TRAILING',\n 'Runtime archive has unexpected entries or trailing content.',\n );\n } finally {\n fs.closeSync(fd);\n fs.unlinkSync(decoded);\n }\n}\n"]}
@@ -0,0 +1,8 @@
1
+ import type { FetchLike } from '../http.js';
2
+ import type { CliRuntimeDescriptor } from './types.js';
3
+ export declare function isRuntimeCommand(argv: readonly string[]): boolean;
4
+ export declare function runRuntimeCommand(subcommand: string | null, args: string[], describe?: () => CliRuntimeDescriptor, fetchImpl?: FetchLike, env?: NodeJS.ProcessEnv): Promise<{
5
+ exitCode: number;
6
+ stdout: string;
7
+ stderr: string;
8
+ }>;
@@ -0,0 +1,57 @@
1
+ import { parseArgs } from 'node:util';
2
+ import { runRuntimeExecCommand } from './exec-command.js';
3
+ import { runManagedRuntimeCommand } from './managed-command.js';
4
+ import { CliError } from '../errors.js';
5
+ import { describeCliRuntime } from '../../runtime.js';
6
+ export function isRuntimeCommand(argv) {
7
+ let index = 0;
8
+ while (['--help', '-h', '--version', '-v'].includes(argv[index] ?? ''))
9
+ index += 1;
10
+ if (argv[index] === '--')
11
+ index += 1;
12
+ return argv[index] === 'runtime';
13
+ }
14
+ export async function runRuntimeCommand(subcommand, args, describe = describeCliRuntime, fetchImpl, env) {
15
+ if (subcommand === 'exec')
16
+ return runRuntimeExecCommand(args, fetchImpl, env);
17
+ if (subcommand && ['ensure', 'status', 'prune', 'lease-release'].includes(subcommand))
18
+ return runManagedRuntimeCommand(subcommand, args, fetchImpl);
19
+ let flags;
20
+ try {
21
+ flags = parseArgs({
22
+ args,
23
+ strict: true,
24
+ allowPositionals: false,
25
+ options: {
26
+ help: { type: 'boolean', short: 'h' },
27
+ json: { type: 'boolean' },
28
+ },
29
+ }).values;
30
+ }
31
+ catch {
32
+ throw new CliError('Runtime commands accept only their declared flags.', {
33
+ code: 'RUNTIME_ARGUMENT_INVALID',
34
+ exitCode: 2,
35
+ });
36
+ }
37
+ if (!subcommand || flags.help)
38
+ return {
39
+ exitCode: 0,
40
+ stdout: 'Usage: tiangong-lca runtime describe [--json] | ensure | status | prune | lease-release | exec\n\nDescribe the installed CLI package, assets and Node executable. No authentication, user env file or download.\n',
41
+ stderr: '',
42
+ };
43
+ if (subcommand !== 'describe')
44
+ throw new CliError('Unknown runtime operation.', {
45
+ code: 'RUNTIME_OPERATION_UNKNOWN',
46
+ exitCode: 2,
47
+ });
48
+ const descriptor = describe();
49
+ return {
50
+ exitCode: 0,
51
+ stdout: flags.json
52
+ ? `${JSON.stringify(descriptor)}\n`
53
+ : `CLI ${descriptor.package.version} (${descriptor.platform})\nNode ${descriptor.node.version}\nContent ${descriptor.content_sha256}\n`,
54
+ stderr: '',
55
+ };
56
+ }
57
+ //# sourceMappingURL=command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command.js","sourceRoot":"","sources":["../../../../src/lib/runtime/command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAChE,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAGtD,MAAM,UAAU,gBAAgB,CAAC,IAAuB;IACtD,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,OAAO,CAAC,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QAAE,KAAK,IAAI,CAAC,CAAC;IACnF,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,IAAI;QAAE,KAAK,IAAI,CAAC,CAAC;IACrC,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,SAAS,CAAC;AACnC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,UAAyB,EACzB,IAAc,EACd,QAAQ,GAA+B,kBAAkB,EACzD,SAAqB,EACrB,GAAuB;IAEvB,IAAI,UAAU,KAAK,MAAM;QAAE,OAAO,qBAAqB,CAAC,IAAI,EAAE,SAAS,EAAE,GAAG,CAAC,CAAC;IAC9E,IAAI,UAAU,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,eAAe,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC;QACnF,OAAO,wBAAwB,CAAC,UAAU,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;IAC/D,IAAI,KAAyC,CAAC;IAC9C,IAAI,CAAC;QACH,KAAK,GAAG,SAAS,CAAC;YAChB,IAAI;YACJ,MAAM,EAAE,IAAI;YACZ,gBAAgB,EAAE,KAAK;YACvB,OAAO,EAAE;gBACP,IAAI,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE;gBACrC,IAAI,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;aAC1B;SACF,CAAC,CAAC,MAAM,CAAC;IACZ,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,QAAQ,CAAC,oDAAoD,EAAE;YACvE,IAAI,EAAE,0BAA0B;YAChC,QAAQ,EAAE,CAAC;SACZ,CAAC,CAAC;IACL,CAAC;IACD,IAAI,CAAC,UAAU,IAAI,KAAK,CAAC,IAAI;QAC3B,OAAO;YACL,QAAQ,EAAE,CAAC;YACX,MAAM,EACJ,mNAAmN;YACrN,MAAM,EAAE,EAAE;SACX,CAAC;IACJ,IAAI,UAAU,KAAK,UAAU;QAC3B,MAAM,IAAI,QAAQ,CAAC,4BAA4B,EAAE;YAC/C,IAAI,EAAE,2BAA2B;YACjC,QAAQ,EAAE,CAAC;SACZ,CAAC,CAAC;IACL,MAAM,UAAU,GAAG,QAAQ,EAAE,CAAC;IAC9B,OAAO;QACL,QAAQ,EAAE,CAAC;QACX,MAAM,EAAE,KAAK,CAAC,IAAI;YAChB,CAAC,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI;YACnC,CAAC,CAAC,OAAO,UAAU,CAAC,OAAO,CAAC,OAAO,KAAK,UAAU,CAAC,QAAQ,WAAW,UAAU,CAAC,IAAI,CAAC,OAAO,aAAa,UAAU,CAAC,cAAc,IAAI;QACzI,MAAM,EAAE,EAAE;KACX,CAAC;AACJ,CAAC","sourcesContent":["import { parseArgs } from 'node:util';\nimport type { FetchLike } from '../http.js';\nimport { runRuntimeExecCommand } from './exec-command.js';\nimport { runManagedRuntimeCommand } from './managed-command.js';\nimport { CliError } from '../errors.js';\nimport { describeCliRuntime } from '../../runtime.js';\nimport type { CliRuntimeDescriptor } from './types.js';\n\nexport function isRuntimeCommand(argv: readonly string[]): boolean {\n let index = 0;\n while (['--help', '-h', '--version', '-v'].includes(argv[index] ?? '')) index += 1;\n if (argv[index] === '--') index += 1;\n return argv[index] === 'runtime';\n}\n\nexport async function runRuntimeCommand(\n subcommand: string | null,\n args: string[],\n describe: () => CliRuntimeDescriptor = describeCliRuntime,\n fetchImpl?: FetchLike,\n env?: NodeJS.ProcessEnv,\n): Promise<{ exitCode: number; stdout: string; stderr: string }> {\n if (subcommand === 'exec') return runRuntimeExecCommand(args, fetchImpl, env);\n if (subcommand && ['ensure', 'status', 'prune', 'lease-release'].includes(subcommand))\n return runManagedRuntimeCommand(subcommand, args, fetchImpl);\n let flags: { help?: boolean; json?: boolean };\n try {\n flags = parseArgs({\n args,\n strict: true,\n allowPositionals: false,\n options: {\n help: { type: 'boolean', short: 'h' },\n json: { type: 'boolean' },\n },\n }).values;\n } catch {\n throw new CliError('Runtime commands accept only their declared flags.', {\n code: 'RUNTIME_ARGUMENT_INVALID',\n exitCode: 2,\n });\n }\n if (!subcommand || flags.help)\n return {\n exitCode: 0,\n stdout:\n 'Usage: tiangong-lca runtime describe [--json] | ensure | status | prune | lease-release | exec\\n\\nDescribe the installed CLI package, assets and Node executable. No authentication, user env file or download.\\n',\n stderr: '',\n };\n if (subcommand !== 'describe')\n throw new CliError('Unknown runtime operation.', {\n code: 'RUNTIME_OPERATION_UNKNOWN',\n exitCode: 2,\n });\n const descriptor = describe();\n return {\n exitCode: 0,\n stdout: flags.json\n ? `${JSON.stringify(descriptor)}\\n`\n : `CLI ${descriptor.package.version} (${descriptor.platform})\\nNode ${descriptor.node.version}\\nContent ${descriptor.content_sha256}\\n`,\n stderr: '',\n };\n}\n"]}
@@ -0,0 +1,11 @@
1
+ import type { CliRuntimeDescriptor, CliRuntimeExpectation, RuntimePlatform } from './types.js';
2
+ export declare function runtimePlatform(platform: string, arch: string): RuntimePlatform;
3
+ export declare function runtimePackageRoot(moduleUrl: string): string;
4
+ export declare function inspectCliRuntime(root: string, node: {
5
+ executable: string;
6
+ version: string;
7
+ platform: string;
8
+ arch: string;
9
+ }): CliRuntimeDescriptor;
10
+ export declare function validateRuntimeExpectation(value: unknown): asserts value is CliRuntimeExpectation;
11
+ export declare function assertRuntimeObservationMatches(actual: CliRuntimeDescriptor, expected: unknown): CliRuntimeDescriptor;