@tiangong-lca/cli 0.0.12 → 0.0.13

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.
@@ -266,6 +266,7 @@ export async function runProcessSaveDraft(options) {
266
266
  const now = options.now ?? new Date();
267
267
  const inputPath = path.resolve(options.inputPath);
268
268
  const commit = options.commit === true;
269
+ const targetUserId = first_non_empty(options.targetUserId);
269
270
  const rawInput = options.rawInput ?? readStructuredInput(inputPath);
270
271
  const validateProcessPayloadImpl = options.validateProcessPayloadImpl ?? validateProcessPayload;
271
272
  const prepared = prepareProcessSaveDraftInput(inputPath, rawInput, commit, now, validateProcessPayloadImpl);
@@ -307,10 +308,12 @@ export async function runProcessSaveDraft(options) {
307
308
  env: options.env,
308
309
  fetchImpl: options.fetchImpl,
309
310
  timeoutMs: options.timeoutMs,
311
+ targetUserId,
310
312
  audit: {
311
313
  command: 'tiangong-lca process save-draft',
312
314
  source: candidate.source,
313
315
  bundle_path: candidate.bundle_path,
316
+ target_user_id: targetUserId,
314
317
  },
315
318
  });
316
319
  report.status = 'executed';
@@ -331,6 +334,13 @@ export async function runProcessSaveDraft(options) {
331
334
  out_dir: outDir,
332
335
  commit,
333
336
  mode: commit ? 'commit' : 'dry_run',
337
+ target_user_id: targetUserId,
338
+ account_guard: {
339
+ target_user_id_required: Boolean(targetUserId),
340
+ target_user_id: targetUserId,
341
+ commit_account_binding: 'current_cli_auth_session',
342
+ post_write_verify_required: Boolean(targetUserId),
343
+ },
334
344
  status: failedReports.length > 0 ? 'completed_with_failures' : 'completed',
335
345
  counts: {
336
346
  selected: prepared.processes.length,
@@ -1 +1 @@
1
- {"version":3,"file":"process-save-draft-run.js","sourceRoot":"","sources":["../../../src/lib/process-save-draft-run.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readFileSync } from 'node:fs';\nimport path from 'node:path';\nimport { writeJsonArtifact, writeJsonLinesArtifact } from './artifacts.js';\nimport { CliError } from './errors.js';\nimport type { FetchLike } from './http.js';\nimport { readJsonInput } from './io.js';\nimport {\n summarizeProcessPayloadValidation,\n validateProcessPayload,\n type ProcessPayloadValidationResult,\n} from './process-payload-validation.js';\nimport {\n collectPublishInputs,\n normalizePublishRequest,\n type PublishCollectedDatasetEntry,\n type PublishCollectedOrigin,\n} from './publish.js';\nimport {\n syncStateAwareProcessRecord,\n type ProcessStateAwareWriteResult,\n} from './process-save-draft.js';\nimport { buildRunId, resolveRunLayout } from './run.js';\n\ntype JsonObject = Record<string, unknown>;\n\nfunction isRecord(value: unknown): value is JsonObject {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction first_non_empty(...values: unknown[]): string | null {\n for (const value of values) {\n if (typeof value === 'string' && value.trim()) {\n return value.trim();\n }\n }\n return null;\n}\n\nfunction resolve_path(baseDir: string, value: string): string {\n return path.resolve(baseDir, value);\n}\n\nfunction serialize_error(error: unknown): { message: string } {\n if (error instanceof Error) {\n return { message: error.message };\n }\n return { message: String(error) };\n}\n\nfunction readJsonLinesInput(inputPath: string): JsonObject[] {\n const resolved = path.resolve(inputPath);\n if (!existsSync(resolved)) {\n throw new CliError(`Input file not found: ${resolved}`, {\n code: 'INPUT_NOT_FOUND',\n exitCode: 2,\n });\n }\n\n return readFileSync(resolved, 'utf8')\n .split(/\\r?\\n/u)\n .map((line) => line.trim())\n .filter(Boolean)\n .map((line, index) => {\n try {\n const parsed = JSON.parse(line) as unknown;\n if (!isRecord(parsed)) {\n throw new CliError(\n `Expected JSON object rows in JSONL input: ${resolved} (line ${index + 1})`,\n {\n code: 'INPUT_INVALID_JSONL_ROW',\n exitCode: 2,\n },\n );\n }\n return parsed;\n } catch (error) {\n if (error instanceof CliError) {\n throw error;\n }\n throw new CliError(`Input file contains invalid JSONL at line ${index + 1}: ${resolved}`, {\n code: 'INPUT_INVALID_JSONL',\n exitCode: 2,\n details: String(error),\n });\n }\n });\n}\n\nfunction readStructuredInput(inputPath: string): unknown {\n return inputPath.toLowerCase().endsWith('.jsonl')\n ? readJsonLinesInput(inputPath)\n : readJsonInput(inputPath);\n}\n\nfunction looksLikePublishRequest(value: unknown): boolean {\n return (\n isRecord(value) &&\n ('inputs' in value || 'publish' in value || 'out_dir' in value || 'output_dir' in value)\n );\n}\n\nfunction loadProcessPayloadFromDatasetEntry(entry: unknown, baseDir: string): JsonObject {\n if (isRecord(entry)) {\n for (const key of ['json_ordered', 'jsonOrdered', 'payload', 'process'] as const) {\n const candidate = entry[key];\n if (isRecord(candidate)) {\n return candidate;\n }\n }\n\n const fileValue = first_non_empty(entry.file, entry.path);\n if (fileValue) {\n const filePath = resolve_path(baseDir, fileValue);\n const loaded = readJsonInput(filePath);\n if (!isRecord(loaded)) {\n throw new CliError(`Expected JSON object input: ${filePath}`, {\n code: 'PROCESS_SAVE_DRAFT_INPUT_NOT_OBJECT',\n exitCode: 2,\n });\n }\n return loaded;\n }\n\n return entry;\n }\n\n if (typeof entry === 'string' && entry.trim()) {\n const filePath = resolve_path(baseDir, entry);\n const loaded = readJsonInput(filePath);\n if (!isRecord(loaded)) {\n throw new CliError(`Expected JSON object input: ${filePath}`, {\n code: 'PROCESS_SAVE_DRAFT_INPUT_NOT_OBJECT',\n exitCode: 2,\n });\n }\n return loaded;\n }\n\n throw new CliError('Unsupported process save-draft dataset entry.', {\n code: 'PROCESS_SAVE_DRAFT_UNSUPPORTED_ENTRY',\n exitCode: 2,\n details: entry,\n });\n}\n\nfunction extractProcessIdentity(payload: JsonObject): [string, string] {\n const root = isRecord(payload.processDataSet) ? payload.processDataSet : payload;\n const processInformation = isRecord(root.processInformation) ? root.processInformation : {};\n const dataSetInformation = isRecord(processInformation.dataSetInformation)\n ? processInformation.dataSetInformation\n : {};\n const administrativeInformation = isRecord(root.administrativeInformation)\n ? root.administrativeInformation\n : {};\n const publicationAndOwnership = isRecord(administrativeInformation.publicationAndOwnership)\n ? administrativeInformation.publicationAndOwnership\n : {};\n const datasetId = first_non_empty(dataSetInformation['common:UUID']);\n const version = first_non_empty(publicationAndOwnership['common:dataSetVersion'], '01.01.000')!;\n\n if (!datasetId) {\n throw new CliError(\n 'Process payload missing processInformation.dataSetInformation.common:UUID.',\n {\n code: 'PUBLISH_PROCESS_ID_MISSING',\n exitCode: 2,\n },\n );\n }\n\n return [datasetId, version];\n}\n\nfunction processPayloadFromRow(row: JsonObject): JsonObject {\n if (isRecord(row.json_ordered)) {\n return row.json_ordered;\n }\n\n if (isRecord(row.json)) {\n return row.json;\n }\n\n if (isRecord(row.process)) {\n return row.process;\n }\n\n return row;\n}\n\nexport type ProcessSaveDraftSource = 'rows_file' | 'bundle' | 'input';\n\nexport type ProcessSaveDraftCandidate = {\n id: string | null;\n version: string | null;\n source: ProcessSaveDraftSource;\n bundle_path: string | null;\n payload: JsonObject;\n validation?: ProcessPayloadValidationResult;\n error?: { message: string };\n};\n\nexport type ProcessSaveDraftProcessReport = {\n id: string | null;\n version: string | null;\n source: ProcessSaveDraftSource;\n bundle_path: string | null;\n status: 'prepared' | 'executed' | 'failed';\n validation?: ProcessPayloadValidationResult;\n execution?: ProcessStateAwareWriteResult;\n error?: { message: string };\n};\n\nexport type ProcessSaveDraftReport = {\n generated_at_utc: string;\n input_path: string;\n input_kind: 'rows_file' | 'publish_request';\n out_dir: string;\n commit: boolean;\n mode: 'dry_run' | 'commit';\n status: 'completed' | 'completed_with_failures';\n counts: {\n selected: number;\n prepared: number;\n executed: number;\n failed: number;\n };\n files: {\n normalized_input: string;\n selected_processes: string;\n progress_jsonl: string;\n failures_jsonl: string;\n summary_json: string;\n };\n processes: ProcessSaveDraftProcessReport[];\n};\n\nexport type RunProcessSaveDraftOptions = {\n inputPath: string;\n outDir?: string | null;\n commit?: boolean | null;\n rawInput?: unknown;\n env?: NodeJS.ProcessEnv;\n fetchImpl?: FetchLike;\n timeoutMs?: number;\n now?: Date;\n validateProcessPayloadImpl?: (payload: JsonObject) => ProcessPayloadValidationResult;\n};\n\ntype PreparedProcessSaveDraftInput = {\n inputKind: 'rows_file' | 'publish_request';\n normalizedInput: unknown;\n processes: ProcessSaveDraftCandidate[];\n};\n\nfunction candidateFromPayload(\n payload: JsonObject,\n source: ProcessSaveDraftSource,\n bundlePath: string | null,\n validateProcessPayloadImpl: (payload: JsonObject) => ProcessPayloadValidationResult,\n): ProcessSaveDraftCandidate {\n try {\n const [id, version] = extractProcessIdentity(payload);\n const validation = validateProcessPayloadImpl(payload);\n if (!validation.ok) {\n return {\n id,\n version,\n source,\n bundle_path: bundlePath,\n payload,\n validation,\n error: {\n message: summarizeProcessPayloadValidation(validation),\n },\n };\n }\n return {\n id,\n version,\n source,\n bundle_path: bundlePath,\n payload,\n validation,\n };\n } catch (error) {\n return {\n id: first_non_empty(payload['@id'], payload.id),\n version: first_non_empty(payload['@version'], payload.version, '01.01.000'),\n source,\n bundle_path: bundlePath,\n payload,\n error:\n error instanceof CliError && error.code === 'PUBLISH_PROCESS_ID_MISSING'\n ? {\n message:\n 'Payload is not a canonical processDataSet wrapper; process save-draft only supports canonical process datasets.',\n }\n : serialize_error(error),\n };\n }\n}\n\nfunction sourceFromPublishOrigin(origin: PublishCollectedOrigin): ProcessSaveDraftSource {\n return origin.source === 'bundle' ? 'bundle' : 'input';\n}\n\nfunction candidateFromPublishEntry(\n entry: PublishCollectedDatasetEntry,\n validateProcessPayloadImpl: (payload: JsonObject) => ProcessPayloadValidationResult,\n): ProcessSaveDraftCandidate {\n return candidateFromPayload(\n loadProcessPayloadFromDatasetEntry(entry.entry, entry.origin.base_dir),\n sourceFromPublishOrigin(entry.origin),\n entry.origin.bundle_path,\n validateProcessPayloadImpl,\n );\n}\n\nfunction prepareRowsFileInput(\n inputPath: string,\n rawInput: unknown,\n validateProcessPayloadImpl: (payload: JsonObject) => ProcessPayloadValidationResult,\n): PreparedProcessSaveDraftInput {\n const rows = Array.isArray(rawInput) ? rawInput : [rawInput];\n const normalizedRows = rows.map((row, index) => {\n if (!isRecord(row)) {\n throw new CliError(\n `Expected JSON object rows in process save-draft input: ${inputPath} (index ${index})`,\n {\n code: 'PROCESS_SAVE_DRAFT_INVALID_ROW',\n exitCode: 2,\n },\n );\n }\n return row;\n });\n\n return {\n inputKind: 'rows_file',\n normalizedInput: {\n input_kind: 'rows_file',\n input_path: inputPath,\n row_count: normalizedRows.length,\n },\n processes: normalizedRows.map((row) =>\n candidateFromPayload(\n processPayloadFromRow(row),\n 'rows_file',\n null,\n validateProcessPayloadImpl,\n ),\n ),\n };\n}\n\nfunction preparePublishRequestInput(\n inputPath: string,\n rawInput: unknown,\n commit: boolean,\n now: Date,\n validateProcessPayloadImpl: (payload: JsonObject) => ProcessPayloadValidationResult,\n): PreparedProcessSaveDraftInput {\n const normalized = normalizePublishRequest(rawInput, {\n requestPath: inputPath,\n commitOverride: commit,\n now,\n });\n const collected = collectPublishInputs(normalized, path.dirname(inputPath));\n\n return {\n inputKind: 'publish_request',\n normalizedInput: normalized,\n processes: collected.processes.map((entry) =>\n candidateFromPublishEntry(entry, validateProcessPayloadImpl),\n ),\n };\n}\n\nfunction prepareProcessSaveDraftInput(\n inputPath: string,\n rawInput: unknown,\n commit: boolean,\n now: Date,\n validateProcessPayloadImpl: (payload: JsonObject) => ProcessPayloadValidationResult,\n): PreparedProcessSaveDraftInput {\n return looksLikePublishRequest(rawInput)\n ? preparePublishRequestInput(inputPath, rawInput, commit, now, validateProcessPayloadImpl)\n : prepareRowsFileInput(inputPath, rawInput, validateProcessPayloadImpl);\n}\n\nfunction defaultOutDir(inputPath: string, commit: boolean, now: Date): string {\n const runId = buildRunId({\n namespace: 'process_save_draft',\n operation: commit ? 'commit' : 'dry_run',\n now,\n });\n return resolveRunLayout(\n path.join(path.dirname(inputPath), 'artifacts'),\n 'process_save_draft',\n runId,\n ).runRoot;\n}\n\nfunction resolveOutDir(\n inputPath: string,\n outDir: string | null | undefined,\n commit: boolean,\n now: Date,\n): string {\n return outDir ? path.resolve(outDir) : defaultOutDir(inputPath, commit, now);\n}\n\nfunction buildFiles(outDir: string): ProcessSaveDraftReport['files'] {\n const outputDir = path.join(outDir, 'outputs', 'save-draft-rpc');\n return {\n normalized_input: path.join(outDir, 'inputs', 'normalized-input.json'),\n selected_processes: path.join(outputDir, 'selected-processes.jsonl'),\n progress_jsonl: path.join(outputDir, 'progress.jsonl'),\n failures_jsonl: path.join(outputDir, 'failures.jsonl'),\n summary_json: path.join(outputDir, 'summary.json'),\n };\n}\n\nfunction compactCandidate(candidate: ProcessSaveDraftCandidate): JsonObject {\n return {\n id: candidate.id,\n version: candidate.version,\n source: candidate.source,\n bundle_path: candidate.bundle_path,\n payload: candidate.payload,\n ...(candidate.validation ? { validation: candidate.validation } : {}),\n ...(candidate.error ? { error: candidate.error } : {}),\n };\n}\n\nexport async function runProcessSaveDraft(\n options: RunProcessSaveDraftOptions,\n): Promise<ProcessSaveDraftReport> {\n const now = options.now ?? new Date();\n const inputPath = path.resolve(options.inputPath);\n const commit = options.commit === true;\n const rawInput = options.rawInput ?? readStructuredInput(inputPath);\n const validateProcessPayloadImpl = options.validateProcessPayloadImpl ?? validateProcessPayload;\n const prepared = prepareProcessSaveDraftInput(\n inputPath,\n rawInput,\n commit,\n now,\n validateProcessPayloadImpl,\n );\n const outDir = resolveOutDir(inputPath, options.outDir, commit, now);\n const files = buildFiles(outDir);\n\n if (commit && (!options.env || !options.fetchImpl)) {\n throw new CliError('Process save-draft commit requires env and fetch runtime bindings.', {\n code: 'PROCESS_SAVE_DRAFT_RUNTIME_REQUIRED',\n exitCode: 2,\n });\n }\n\n writeJsonArtifact(files.normalized_input, prepared.normalizedInput);\n writeJsonLinesArtifact(files.selected_processes, prepared.processes.map(compactCandidate));\n\n const reports: ProcessSaveDraftProcessReport[] = [];\n for (const candidate of prepared.processes) {\n const report: ProcessSaveDraftProcessReport = {\n id: candidate.id,\n version: candidate.version,\n source: candidate.source,\n bundle_path: candidate.bundle_path,\n status: 'prepared',\n ...(candidate.validation ? { validation: candidate.validation } : {}),\n };\n\n if (candidate.error) {\n report.status = 'failed';\n report.error = candidate.error;\n reports.push(report);\n continue;\n }\n\n if (!commit) {\n reports.push(report);\n continue;\n }\n\n try {\n report.execution = await syncStateAwareProcessRecord({\n id: candidate.id!,\n version: candidate.version!,\n payload: candidate.payload,\n env: options.env!,\n fetchImpl: options.fetchImpl!,\n timeoutMs: options.timeoutMs,\n audit: {\n command: 'tiangong-lca process save-draft',\n source: candidate.source,\n bundle_path: candidate.bundle_path,\n },\n });\n report.status = 'executed';\n } catch (error) {\n report.status = 'failed';\n report.error = serialize_error(error);\n }\n\n reports.push(report);\n }\n\n const failedReports = reports.filter((report) => report.status === 'failed');\n writeJsonLinesArtifact(files.progress_jsonl, reports);\n writeJsonLinesArtifact(files.failures_jsonl, failedReports);\n\n const report: ProcessSaveDraftReport = {\n generated_at_utc: now.toISOString(),\n input_path: inputPath,\n input_kind: prepared.inputKind,\n out_dir: outDir,\n commit,\n mode: commit ? 'commit' : 'dry_run',\n status: failedReports.length > 0 ? 'completed_with_failures' : 'completed',\n counts: {\n selected: prepared.processes.length,\n prepared: reports.filter((entry) => entry.status === 'prepared').length,\n executed: reports.filter((entry) => entry.status === 'executed').length,\n failed: failedReports.length,\n },\n files,\n processes: reports,\n };\n\n writeJsonArtifact(files.summary_json, report);\n return report;\n}\n"]}
1
+ {"version":3,"file":"process-save-draft-run.js","sourceRoot":"","sources":["../../../src/lib/process-save-draft-run.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readFileSync } from 'node:fs';\nimport path from 'node:path';\nimport { writeJsonArtifact, writeJsonLinesArtifact } from './artifacts.js';\nimport { CliError } from './errors.js';\nimport type { FetchLike } from './http.js';\nimport { readJsonInput } from './io.js';\nimport {\n summarizeProcessPayloadValidation,\n validateProcessPayload,\n type ProcessPayloadValidationResult,\n} from './process-payload-validation.js';\nimport {\n collectPublishInputs,\n normalizePublishRequest,\n type PublishCollectedDatasetEntry,\n type PublishCollectedOrigin,\n} from './publish.js';\nimport {\n syncStateAwareProcessRecord,\n type ProcessStateAwareWriteResult,\n} from './process-save-draft.js';\nimport { buildRunId, resolveRunLayout } from './run.js';\n\ntype JsonObject = Record<string, unknown>;\n\nfunction isRecord(value: unknown): value is JsonObject {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction first_non_empty(...values: unknown[]): string | null {\n for (const value of values) {\n if (typeof value === 'string' && value.trim()) {\n return value.trim();\n }\n }\n return null;\n}\n\nfunction resolve_path(baseDir: string, value: string): string {\n return path.resolve(baseDir, value);\n}\n\nfunction serialize_error(error: unknown): { message: string } {\n if (error instanceof Error) {\n return { message: error.message };\n }\n return { message: String(error) };\n}\n\nfunction readJsonLinesInput(inputPath: string): JsonObject[] {\n const resolved = path.resolve(inputPath);\n if (!existsSync(resolved)) {\n throw new CliError(`Input file not found: ${resolved}`, {\n code: 'INPUT_NOT_FOUND',\n exitCode: 2,\n });\n }\n\n return readFileSync(resolved, 'utf8')\n .split(/\\r?\\n/u)\n .map((line) => line.trim())\n .filter(Boolean)\n .map((line, index) => {\n try {\n const parsed = JSON.parse(line) as unknown;\n if (!isRecord(parsed)) {\n throw new CliError(\n `Expected JSON object rows in JSONL input: ${resolved} (line ${index + 1})`,\n {\n code: 'INPUT_INVALID_JSONL_ROW',\n exitCode: 2,\n },\n );\n }\n return parsed;\n } catch (error) {\n if (error instanceof CliError) {\n throw error;\n }\n throw new CliError(`Input file contains invalid JSONL at line ${index + 1}: ${resolved}`, {\n code: 'INPUT_INVALID_JSONL',\n exitCode: 2,\n details: String(error),\n });\n }\n });\n}\n\nfunction readStructuredInput(inputPath: string): unknown {\n return inputPath.toLowerCase().endsWith('.jsonl')\n ? readJsonLinesInput(inputPath)\n : readJsonInput(inputPath);\n}\n\nfunction looksLikePublishRequest(value: unknown): boolean {\n return (\n isRecord(value) &&\n ('inputs' in value || 'publish' in value || 'out_dir' in value || 'output_dir' in value)\n );\n}\n\nfunction loadProcessPayloadFromDatasetEntry(entry: unknown, baseDir: string): JsonObject {\n if (isRecord(entry)) {\n for (const key of ['json_ordered', 'jsonOrdered', 'payload', 'process'] as const) {\n const candidate = entry[key];\n if (isRecord(candidate)) {\n return candidate;\n }\n }\n\n const fileValue = first_non_empty(entry.file, entry.path);\n if (fileValue) {\n const filePath = resolve_path(baseDir, fileValue);\n const loaded = readJsonInput(filePath);\n if (!isRecord(loaded)) {\n throw new CliError(`Expected JSON object input: ${filePath}`, {\n code: 'PROCESS_SAVE_DRAFT_INPUT_NOT_OBJECT',\n exitCode: 2,\n });\n }\n return loaded;\n }\n\n return entry;\n }\n\n if (typeof entry === 'string' && entry.trim()) {\n const filePath = resolve_path(baseDir, entry);\n const loaded = readJsonInput(filePath);\n if (!isRecord(loaded)) {\n throw new CliError(`Expected JSON object input: ${filePath}`, {\n code: 'PROCESS_SAVE_DRAFT_INPUT_NOT_OBJECT',\n exitCode: 2,\n });\n }\n return loaded;\n }\n\n throw new CliError('Unsupported process save-draft dataset entry.', {\n code: 'PROCESS_SAVE_DRAFT_UNSUPPORTED_ENTRY',\n exitCode: 2,\n details: entry,\n });\n}\n\nfunction extractProcessIdentity(payload: JsonObject): [string, string] {\n const root = isRecord(payload.processDataSet) ? payload.processDataSet : payload;\n const processInformation = isRecord(root.processInformation) ? root.processInformation : {};\n const dataSetInformation = isRecord(processInformation.dataSetInformation)\n ? processInformation.dataSetInformation\n : {};\n const administrativeInformation = isRecord(root.administrativeInformation)\n ? root.administrativeInformation\n : {};\n const publicationAndOwnership = isRecord(administrativeInformation.publicationAndOwnership)\n ? administrativeInformation.publicationAndOwnership\n : {};\n const datasetId = first_non_empty(dataSetInformation['common:UUID']);\n const version = first_non_empty(publicationAndOwnership['common:dataSetVersion'], '01.01.000')!;\n\n if (!datasetId) {\n throw new CliError(\n 'Process payload missing processInformation.dataSetInformation.common:UUID.',\n {\n code: 'PUBLISH_PROCESS_ID_MISSING',\n exitCode: 2,\n },\n );\n }\n\n return [datasetId, version];\n}\n\nfunction processPayloadFromRow(row: JsonObject): JsonObject {\n if (isRecord(row.json_ordered)) {\n return row.json_ordered;\n }\n\n if (isRecord(row.json)) {\n return row.json;\n }\n\n if (isRecord(row.process)) {\n return row.process;\n }\n\n return row;\n}\n\nexport type ProcessSaveDraftSource = 'rows_file' | 'bundle' | 'input';\n\nexport type ProcessSaveDraftCandidate = {\n id: string | null;\n version: string | null;\n source: ProcessSaveDraftSource;\n bundle_path: string | null;\n payload: JsonObject;\n validation?: ProcessPayloadValidationResult;\n error?: { message: string };\n};\n\nexport type ProcessSaveDraftProcessReport = {\n id: string | null;\n version: string | null;\n source: ProcessSaveDraftSource;\n bundle_path: string | null;\n status: 'prepared' | 'executed' | 'failed';\n validation?: ProcessPayloadValidationResult;\n execution?: ProcessStateAwareWriteResult;\n error?: { message: string };\n};\n\nexport type ProcessSaveDraftReport = {\n generated_at_utc: string;\n input_path: string;\n input_kind: 'rows_file' | 'publish_request';\n out_dir: string;\n commit: boolean;\n mode: 'dry_run' | 'commit';\n target_user_id: string | null;\n account_guard: {\n target_user_id_required: boolean;\n target_user_id: string | null;\n commit_account_binding: 'current_cli_auth_session';\n post_write_verify_required: boolean;\n };\n status: 'completed' | 'completed_with_failures';\n counts: {\n selected: number;\n prepared: number;\n executed: number;\n failed: number;\n };\n files: {\n normalized_input: string;\n selected_processes: string;\n progress_jsonl: string;\n failures_jsonl: string;\n summary_json: string;\n };\n processes: ProcessSaveDraftProcessReport[];\n};\n\nexport type RunProcessSaveDraftOptions = {\n inputPath: string;\n outDir?: string | null;\n commit?: boolean | null;\n rawInput?: unknown;\n env?: NodeJS.ProcessEnv;\n fetchImpl?: FetchLike;\n timeoutMs?: number;\n now?: Date;\n targetUserId?: string | null;\n validateProcessPayloadImpl?: (payload: JsonObject) => ProcessPayloadValidationResult;\n};\n\ntype PreparedProcessSaveDraftInput = {\n inputKind: 'rows_file' | 'publish_request';\n normalizedInput: unknown;\n processes: ProcessSaveDraftCandidate[];\n};\n\nfunction candidateFromPayload(\n payload: JsonObject,\n source: ProcessSaveDraftSource,\n bundlePath: string | null,\n validateProcessPayloadImpl: (payload: JsonObject) => ProcessPayloadValidationResult,\n): ProcessSaveDraftCandidate {\n try {\n const [id, version] = extractProcessIdentity(payload);\n const validation = validateProcessPayloadImpl(payload);\n if (!validation.ok) {\n return {\n id,\n version,\n source,\n bundle_path: bundlePath,\n payload,\n validation,\n error: {\n message: summarizeProcessPayloadValidation(validation),\n },\n };\n }\n return {\n id,\n version,\n source,\n bundle_path: bundlePath,\n payload,\n validation,\n };\n } catch (error) {\n return {\n id: first_non_empty(payload['@id'], payload.id),\n version: first_non_empty(payload['@version'], payload.version, '01.01.000'),\n source,\n bundle_path: bundlePath,\n payload,\n error:\n error instanceof CliError && error.code === 'PUBLISH_PROCESS_ID_MISSING'\n ? {\n message:\n 'Payload is not a canonical processDataSet wrapper; process save-draft only supports canonical process datasets.',\n }\n : serialize_error(error),\n };\n }\n}\n\nfunction sourceFromPublishOrigin(origin: PublishCollectedOrigin): ProcessSaveDraftSource {\n return origin.source === 'bundle' ? 'bundle' : 'input';\n}\n\nfunction candidateFromPublishEntry(\n entry: PublishCollectedDatasetEntry,\n validateProcessPayloadImpl: (payload: JsonObject) => ProcessPayloadValidationResult,\n): ProcessSaveDraftCandidate {\n return candidateFromPayload(\n loadProcessPayloadFromDatasetEntry(entry.entry, entry.origin.base_dir),\n sourceFromPublishOrigin(entry.origin),\n entry.origin.bundle_path,\n validateProcessPayloadImpl,\n );\n}\n\nfunction prepareRowsFileInput(\n inputPath: string,\n rawInput: unknown,\n validateProcessPayloadImpl: (payload: JsonObject) => ProcessPayloadValidationResult,\n): PreparedProcessSaveDraftInput {\n const rows = Array.isArray(rawInput) ? rawInput : [rawInput];\n const normalizedRows = rows.map((row, index) => {\n if (!isRecord(row)) {\n throw new CliError(\n `Expected JSON object rows in process save-draft input: ${inputPath} (index ${index})`,\n {\n code: 'PROCESS_SAVE_DRAFT_INVALID_ROW',\n exitCode: 2,\n },\n );\n }\n return row;\n });\n\n return {\n inputKind: 'rows_file',\n normalizedInput: {\n input_kind: 'rows_file',\n input_path: inputPath,\n row_count: normalizedRows.length,\n },\n processes: normalizedRows.map((row) =>\n candidateFromPayload(\n processPayloadFromRow(row),\n 'rows_file',\n null,\n validateProcessPayloadImpl,\n ),\n ),\n };\n}\n\nfunction preparePublishRequestInput(\n inputPath: string,\n rawInput: unknown,\n commit: boolean,\n now: Date,\n validateProcessPayloadImpl: (payload: JsonObject) => ProcessPayloadValidationResult,\n): PreparedProcessSaveDraftInput {\n const normalized = normalizePublishRequest(rawInput, {\n requestPath: inputPath,\n commitOverride: commit,\n now,\n });\n const collected = collectPublishInputs(normalized, path.dirname(inputPath));\n\n return {\n inputKind: 'publish_request',\n normalizedInput: normalized,\n processes: collected.processes.map((entry) =>\n candidateFromPublishEntry(entry, validateProcessPayloadImpl),\n ),\n };\n}\n\nfunction prepareProcessSaveDraftInput(\n inputPath: string,\n rawInput: unknown,\n commit: boolean,\n now: Date,\n validateProcessPayloadImpl: (payload: JsonObject) => ProcessPayloadValidationResult,\n): PreparedProcessSaveDraftInput {\n return looksLikePublishRequest(rawInput)\n ? preparePublishRequestInput(inputPath, rawInput, commit, now, validateProcessPayloadImpl)\n : prepareRowsFileInput(inputPath, rawInput, validateProcessPayloadImpl);\n}\n\nfunction defaultOutDir(inputPath: string, commit: boolean, now: Date): string {\n const runId = buildRunId({\n namespace: 'process_save_draft',\n operation: commit ? 'commit' : 'dry_run',\n now,\n });\n return resolveRunLayout(\n path.join(path.dirname(inputPath), 'artifacts'),\n 'process_save_draft',\n runId,\n ).runRoot;\n}\n\nfunction resolveOutDir(\n inputPath: string,\n outDir: string | null | undefined,\n commit: boolean,\n now: Date,\n): string {\n return outDir ? path.resolve(outDir) : defaultOutDir(inputPath, commit, now);\n}\n\nfunction buildFiles(outDir: string): ProcessSaveDraftReport['files'] {\n const outputDir = path.join(outDir, 'outputs', 'save-draft-rpc');\n return {\n normalized_input: path.join(outDir, 'inputs', 'normalized-input.json'),\n selected_processes: path.join(outputDir, 'selected-processes.jsonl'),\n progress_jsonl: path.join(outputDir, 'progress.jsonl'),\n failures_jsonl: path.join(outputDir, 'failures.jsonl'),\n summary_json: path.join(outputDir, 'summary.json'),\n };\n}\n\nfunction compactCandidate(candidate: ProcessSaveDraftCandidate): JsonObject {\n return {\n id: candidate.id,\n version: candidate.version,\n source: candidate.source,\n bundle_path: candidate.bundle_path,\n payload: candidate.payload,\n ...(candidate.validation ? { validation: candidate.validation } : {}),\n ...(candidate.error ? { error: candidate.error } : {}),\n };\n}\n\nexport async function runProcessSaveDraft(\n options: RunProcessSaveDraftOptions,\n): Promise<ProcessSaveDraftReport> {\n const now = options.now ?? new Date();\n const inputPath = path.resolve(options.inputPath);\n const commit = options.commit === true;\n const targetUserId = first_non_empty(options.targetUserId);\n const rawInput = options.rawInput ?? readStructuredInput(inputPath);\n const validateProcessPayloadImpl = options.validateProcessPayloadImpl ?? validateProcessPayload;\n const prepared = prepareProcessSaveDraftInput(\n inputPath,\n rawInput,\n commit,\n now,\n validateProcessPayloadImpl,\n );\n const outDir = resolveOutDir(inputPath, options.outDir, commit, now);\n const files = buildFiles(outDir);\n\n if (commit && (!options.env || !options.fetchImpl)) {\n throw new CliError('Process save-draft commit requires env and fetch runtime bindings.', {\n code: 'PROCESS_SAVE_DRAFT_RUNTIME_REQUIRED',\n exitCode: 2,\n });\n }\n\n writeJsonArtifact(files.normalized_input, prepared.normalizedInput);\n writeJsonLinesArtifact(files.selected_processes, prepared.processes.map(compactCandidate));\n\n const reports: ProcessSaveDraftProcessReport[] = [];\n for (const candidate of prepared.processes) {\n const report: ProcessSaveDraftProcessReport = {\n id: candidate.id,\n version: candidate.version,\n source: candidate.source,\n bundle_path: candidate.bundle_path,\n status: 'prepared',\n ...(candidate.validation ? { validation: candidate.validation } : {}),\n };\n\n if (candidate.error) {\n report.status = 'failed';\n report.error = candidate.error;\n reports.push(report);\n continue;\n }\n\n if (!commit) {\n reports.push(report);\n continue;\n }\n\n try {\n report.execution = await syncStateAwareProcessRecord({\n id: candidate.id!,\n version: candidate.version!,\n payload: candidate.payload,\n env: options.env!,\n fetchImpl: options.fetchImpl!,\n timeoutMs: options.timeoutMs,\n targetUserId,\n audit: {\n command: 'tiangong-lca process save-draft',\n source: candidate.source,\n bundle_path: candidate.bundle_path,\n target_user_id: targetUserId,\n },\n });\n report.status = 'executed';\n } catch (error) {\n report.status = 'failed';\n report.error = serialize_error(error);\n }\n\n reports.push(report);\n }\n\n const failedReports = reports.filter((report) => report.status === 'failed');\n writeJsonLinesArtifact(files.progress_jsonl, reports);\n writeJsonLinesArtifact(files.failures_jsonl, failedReports);\n\n const report: ProcessSaveDraftReport = {\n generated_at_utc: now.toISOString(),\n input_path: inputPath,\n input_kind: prepared.inputKind,\n out_dir: outDir,\n commit,\n mode: commit ? 'commit' : 'dry_run',\n target_user_id: targetUserId,\n account_guard: {\n target_user_id_required: Boolean(targetUserId),\n target_user_id: targetUserId,\n commit_account_binding: 'current_cli_auth_session',\n post_write_verify_required: Boolean(targetUserId),\n },\n status: failedReports.length > 0 ? 'completed_with_failures' : 'completed',\n counts: {\n selected: prepared.processes.length,\n prepared: reports.filter((entry) => entry.status === 'prepared').length,\n executed: reports.filter((entry) => entry.status === 'executed').length,\n failed: failedReports.length,\n },\n files,\n processes: reports,\n };\n\n writeJsonArtifact(files.summary_json, report);\n return report;\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  import { CliError } from './errors.js';
2
- import { postJson, requireRemoteOkPayload } from './http.js';
3
- import { buildSupabaseAuthHeaders, createSupabaseDataClient, requireSupabaseRestRuntime, runSupabaseArrayQuery, } from './supabase-client.js';
2
+ import { getJson, postJson, requireRemoteOkPayload } from './http.js';
3
+ import { buildSupabaseAuthHeaders, createSupabaseDataClient, deriveSupabaseProjectBaseUrl, requireSupabaseRestRuntime, runSupabaseArrayQuery, } from './supabase-client.js';
4
4
  import { createSupabaseDataRuntime } from './supabase-session.js';
5
5
  import { syncSupabaseJsonOrderedRecord, } from './supabase-json-ordered-write.js';
6
6
  const DEFAULT_TIMEOUT_MS = 10_000;
@@ -68,6 +68,48 @@ async function exactVisibleRows(options) {
68
68
  function visibleDraftRow(rows) {
69
69
  return rows.find((row) => row.state_code === 0) ?? null;
70
70
  }
71
+ function visibleDraftRowForTarget(rows, targetUserId) {
72
+ if (!targetUserId) {
73
+ return visibleDraftRow(rows);
74
+ }
75
+ return rows.find((row) => row.state_code === 0 && row.user_id === targetUserId) ?? null;
76
+ }
77
+ function buildCurrentUserUrl(restBaseUrl) {
78
+ return `${deriveSupabaseProjectBaseUrl(restBaseUrl)}/auth/v1/user`;
79
+ }
80
+ async function currentUserId(options) {
81
+ const url = buildCurrentUserUrl(options.restBaseUrl);
82
+ const payload = await getJson({
83
+ url,
84
+ headers: buildSupabaseAuthHeaders(options.publishableKey, options.accessToken),
85
+ timeoutMs: options.timeoutMs,
86
+ fetchImpl: options.fetchImpl,
87
+ });
88
+ const userId = isRecord(payload) ? trimToken(payload.id) : null;
89
+ if (!userId) {
90
+ throw new CliError('Supabase current-user lookup succeeded without a user id.', {
91
+ code: 'PROCESS_SAVE_DRAFT_CURRENT_USER_ID_MISSING',
92
+ exitCode: 1,
93
+ details: payload,
94
+ });
95
+ }
96
+ return userId;
97
+ }
98
+ function assertTargetUserMatchesCurrent(options) {
99
+ if (!options.targetUserId) {
100
+ return;
101
+ }
102
+ if (options.currentUserId !== options.targetUserId) {
103
+ throw new CliError(`Process save-draft target user ${options.targetUserId} does not match current CLI auth user ${options.currentUserId}.`, {
104
+ code: 'PROCESS_SAVE_DRAFT_TARGET_USER_MISMATCH',
105
+ exitCode: 1,
106
+ details: {
107
+ target_user_id: options.targetUserId,
108
+ current_user_id: options.currentUserId,
109
+ },
110
+ });
111
+ }
112
+ }
71
113
  function buildUnsupportedVisibleRowError(id, version, rows) {
72
114
  const primaryRow = rows[0] ?? null;
73
115
  const stateCode = primaryRow?.state_code === null || primaryRow?.state_code === undefined
@@ -114,6 +156,7 @@ async function saveDraft(options) {
114
156
  }
115
157
  export async function syncStateAwareProcessRecord(options) {
116
158
  const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
159
+ const targetUserId = trimToken(options.targetUserId);
117
160
  const visible = await exactVisibleRows({
118
161
  id: options.id,
119
162
  version: options.version,
@@ -121,7 +164,17 @@ export async function syncStateAwareProcessRecord(options) {
121
164
  fetchImpl: options.fetchImpl,
122
165
  timeoutMs,
123
166
  });
124
- const draftRow = visibleDraftRow(visible.rows);
167
+ if (targetUserId) {
168
+ const userId = await currentUserId({
169
+ restBaseUrl: visible.restBaseUrl,
170
+ publishableKey: visible.publishableKey,
171
+ accessToken: visible.accessToken,
172
+ timeoutMs,
173
+ fetchImpl: options.fetchImpl,
174
+ });
175
+ assertTargetUserMatchesCurrent({ targetUserId, currentUserId: userId });
176
+ }
177
+ const draftRow = visibleDraftRowForTarget(visible.rows, targetUserId);
125
178
  if (!draftRow) {
126
179
  if (visible.rows.length > 0) {
127
180
  throw buildUnsupportedVisibleRowError(options.id, options.version, visible.rows);
@@ -158,8 +211,11 @@ export async function syncStateAwareProcessRecord(options) {
158
211
  }
159
212
  export const __testInternals = {
160
213
  buildVisibleRowsUrl,
214
+ buildCurrentUserUrl,
161
215
  parseVisibleRows,
162
216
  visibleDraftRow,
217
+ visibleDraftRowForTarget,
218
+ assertTargetUserMatchesCurrent,
163
219
  buildUnsupportedVisibleRowError,
164
220
  };
165
221
  //# sourceMappingURL=process-save-draft.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"process-save-draft.js","sourceRoot":"","sources":["../../../src/lib/process-save-draft.ts"],"names":[],"mappings":"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","sourcesContent":["import { CliError } from './errors.js';\nimport type { FetchLike } from './http.js';\nimport { postJson, requireRemoteOkPayload } from './http.js';\nimport {\n buildSupabaseAuthHeaders,\n createSupabaseDataClient,\n requireSupabaseRestRuntime,\n runSupabaseArrayQuery,\n} from './supabase-client.js';\nimport { createSupabaseDataRuntime } from './supabase-session.js';\nimport {\n syncSupabaseJsonOrderedRecord,\n type SupabaseJsonOrderedWriteResult,\n} from './supabase-json-ordered-write.js';\n\ntype JsonObject = Record<string, unknown>;\n\nconst DEFAULT_TIMEOUT_MS = 10_000;\n\nfunction isRecord(value: unknown): value is JsonObject {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction trimToken(value: unknown): string | null {\n if (typeof value !== 'string') {\n return null;\n }\n\n const trimmed = value.trim();\n return trimmed ? trimmed : null;\n}\n\nexport type VisibleProcessRow = {\n id: string;\n version: string;\n user_id: string | null;\n state_code: number | null;\n};\n\nexport type ProcessSaveDraftRpcResult = {\n ok: true;\n [key: string]: unknown;\n};\n\nexport type ProcessStateAwareWriteResult =\n | SupabaseJsonOrderedWriteResult\n | {\n status: 'success';\n operation: 'save_draft';\n write_path: 'cmd_dataset_save_draft';\n rpc_result: ProcessSaveDraftRpcResult;\n visible_row: VisibleProcessRow;\n };\n\nexport type SyncStateAwareProcessRecordOptions = {\n id: string;\n version: string;\n payload: JsonObject;\n env: NodeJS.ProcessEnv;\n fetchImpl: FetchLike;\n timeoutMs?: number;\n audit?: JsonObject;\n modelId?: string | null;\n};\n\nfunction buildVisibleRowsUrl(restBaseUrl: string, id: string, version: string): string {\n const url = new URL(`${restBaseUrl.replace(/\\/+$/u, '')}/processes`);\n url.searchParams.set('select', 'id,version,user_id,state_code');\n url.searchParams.set('id', `eq.${id}`);\n url.searchParams.set('version', `eq.${version}`);\n return url.toString();\n}\n\nfunction parseVisibleRows(payload: unknown, url: string): VisibleProcessRow[] {\n if (!Array.isArray(payload)) {\n throw new CliError(`Supabase REST response was not a JSON array for ${url}`, {\n code: 'SUPABASE_REST_RESPONSE_INVALID',\n exitCode: 1,\n details: payload,\n });\n }\n\n return payload.map((item, index) => {\n if (!isRecord(item)) {\n throw new CliError(`Supabase REST row ${index} was not a JSON object for ${url}`, {\n code: 'SUPABASE_REST_RESPONSE_INVALID',\n exitCode: 1,\n details: item,\n });\n }\n\n return {\n id: trimToken(item.id) ?? '',\n version: trimToken(item.version) ?? '',\n user_id: trimToken(item.user_id),\n state_code: typeof item.state_code === 'number' ? item.state_code : null,\n };\n });\n}\n\nasync function exactVisibleRows(options: {\n id: string;\n version: string;\n env: NodeJS.ProcessEnv;\n fetchImpl: FetchLike;\n timeoutMs: number;\n}): Promise<{\n rows: VisibleProcessRow[];\n restBaseUrl: string;\n accessToken: string;\n publishableKey: string;\n}> {\n const runtime = createSupabaseDataRuntime({\n runtime: requireSupabaseRestRuntime(options.env),\n fetchImpl: options.fetchImpl,\n timeoutMs: options.timeoutMs,\n });\n const { client, restBaseUrl } = createSupabaseDataClient(\n runtime,\n options.fetchImpl,\n options.timeoutMs,\n );\n const url = buildVisibleRowsUrl(restBaseUrl, options.id, options.version);\n const payload = await runSupabaseArrayQuery(\n client\n .from('processes')\n .select('id,version,user_id,state_code')\n .eq('id', options.id)\n .eq('version', options.version),\n url,\n );\n\n return {\n rows: parseVisibleRows(payload, url),\n restBaseUrl,\n accessToken: await runtime.getAccessToken(),\n publishableKey: runtime.publishableKey,\n };\n}\n\nfunction visibleDraftRow(rows: VisibleProcessRow[]): VisibleProcessRow | null {\n return rows.find((row) => row.state_code === 0) ?? null;\n}\n\nfunction buildUnsupportedVisibleRowError(\n id: string,\n version: string,\n rows: VisibleProcessRow[],\n): CliError {\n const primaryRow = rows[0] ?? null;\n const stateCode =\n primaryRow?.state_code === null || primaryRow?.state_code === undefined\n ? 'unknown'\n : String(primaryRow.state_code);\n const visibleOwner = primaryRow?.user_id ?? 'unknown';\n\n return new CliError(\n `Process ${id}@${version} is already visible but cannot use save-draft because the visible row is not a current-user draft (state_code=${stateCode}, visible_owner=${visibleOwner}).`,\n {\n code: 'PUBLISH_PROCESS_SAVE_DRAFT_UNSUPPORTED_VISIBLE_ROW',\n exitCode: 1,\n details: {\n id,\n version,\n visible_rows: rows,\n },\n },\n );\n}\n\nasync function saveDraft(options: {\n restBaseUrl: string;\n publishableKey: string;\n accessToken: string;\n id: string;\n version: string;\n payload: JsonObject;\n timeoutMs: number;\n fetchImpl: FetchLike;\n audit?: JsonObject;\n modelId?: string | null;\n}): Promise<ProcessSaveDraftRpcResult> {\n const url = `${options.restBaseUrl.replace(/\\/+$/u, '')}/rpc/cmd_dataset_save_draft`;\n const payload = requireRemoteOkPayload(\n await postJson({\n url,\n headers: {\n ...buildSupabaseAuthHeaders(options.publishableKey, options.accessToken),\n 'Content-Type': 'application/json',\n },\n body: {\n p_table: 'processes',\n p_id: options.id,\n p_version: options.version,\n p_json_ordered: options.payload,\n p_model_id: options.modelId ?? null,\n p_audit: options.audit ?? null,\n },\n timeoutMs: options.timeoutMs,\n fetchImpl: options.fetchImpl,\n }),\n url,\n );\n\n if (!isRecord(payload) || payload.ok !== true) {\n throw new CliError(`Process save-draft RPC returned an unexpected payload for ${url}`, {\n code: 'REMOTE_RESPONSE_INVALID',\n exitCode: 1,\n details: payload,\n });\n }\n\n return payload as ProcessSaveDraftRpcResult;\n}\n\nexport async function syncStateAwareProcessRecord(\n options: SyncStateAwareProcessRecordOptions,\n): Promise<ProcessStateAwareWriteResult> {\n const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const visible = await exactVisibleRows({\n id: options.id,\n version: options.version,\n env: options.env,\n fetchImpl: options.fetchImpl,\n timeoutMs,\n });\n const draftRow = visibleDraftRow(visible.rows);\n\n if (!draftRow) {\n if (visible.rows.length > 0) {\n throw buildUnsupportedVisibleRowError(options.id, options.version, visible.rows);\n }\n\n return syncSupabaseJsonOrderedRecord({\n table: 'processes',\n id: options.id,\n version: options.version,\n payload: options.payload,\n writeMode: 'upsert_current_version',\n env: options.env,\n fetchImpl: options.fetchImpl,\n timeoutMs,\n });\n }\n\n return {\n status: 'success',\n operation: 'save_draft',\n write_path: 'cmd_dataset_save_draft',\n rpc_result: await saveDraft({\n restBaseUrl: visible.restBaseUrl,\n publishableKey: visible.publishableKey,\n accessToken: visible.accessToken,\n id: options.id,\n version: options.version,\n payload: options.payload,\n timeoutMs,\n fetchImpl: options.fetchImpl,\n audit: options.audit,\n modelId: options.modelId,\n }),\n visible_row: draftRow,\n };\n}\n\nexport const __testInternals = {\n buildVisibleRowsUrl,\n parseVisibleRows,\n visibleDraftRow,\n buildUnsupportedVisibleRowError,\n};\n"]}
1
+ {"version":3,"file":"process-save-draft.js","sourceRoot":"","sources":["../../../src/lib/process-save-draft.ts"],"names":[],"mappings":"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","sourcesContent":["import { CliError } from './errors.js';\nimport type { FetchLike } from './http.js';\nimport { getJson, postJson, requireRemoteOkPayload } from './http.js';\nimport {\n buildSupabaseAuthHeaders,\n createSupabaseDataClient,\n deriveSupabaseProjectBaseUrl,\n requireSupabaseRestRuntime,\n runSupabaseArrayQuery,\n} from './supabase-client.js';\nimport { createSupabaseDataRuntime } from './supabase-session.js';\nimport {\n syncSupabaseJsonOrderedRecord,\n type SupabaseJsonOrderedWriteResult,\n} from './supabase-json-ordered-write.js';\n\ntype JsonObject = Record<string, unknown>;\n\nconst DEFAULT_TIMEOUT_MS = 10_000;\n\nfunction isRecord(value: unknown): value is JsonObject {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction trimToken(value: unknown): string | null {\n if (typeof value !== 'string') {\n return null;\n }\n\n const trimmed = value.trim();\n return trimmed ? trimmed : null;\n}\n\nexport type VisibleProcessRow = {\n id: string;\n version: string;\n user_id: string | null;\n state_code: number | null;\n};\n\nexport type ProcessSaveDraftRpcResult = {\n ok: true;\n [key: string]: unknown;\n};\n\nexport type ProcessStateAwareWriteResult =\n | SupabaseJsonOrderedWriteResult\n | {\n status: 'success';\n operation: 'save_draft';\n write_path: 'cmd_dataset_save_draft';\n rpc_result: ProcessSaveDraftRpcResult;\n visible_row: VisibleProcessRow;\n };\n\nexport type SyncStateAwareProcessRecordOptions = {\n id: string;\n version: string;\n payload: JsonObject;\n env: NodeJS.ProcessEnv;\n fetchImpl: FetchLike;\n timeoutMs?: number;\n audit?: JsonObject;\n modelId?: string | null;\n targetUserId?: string | null;\n};\n\nfunction buildVisibleRowsUrl(restBaseUrl: string, id: string, version: string): string {\n const url = new URL(`${restBaseUrl.replace(/\\/+$/u, '')}/processes`);\n url.searchParams.set('select', 'id,version,user_id,state_code');\n url.searchParams.set('id', `eq.${id}`);\n url.searchParams.set('version', `eq.${version}`);\n return url.toString();\n}\n\nfunction parseVisibleRows(payload: unknown, url: string): VisibleProcessRow[] {\n if (!Array.isArray(payload)) {\n throw new CliError(`Supabase REST response was not a JSON array for ${url}`, {\n code: 'SUPABASE_REST_RESPONSE_INVALID',\n exitCode: 1,\n details: payload,\n });\n }\n\n return payload.map((item, index) => {\n if (!isRecord(item)) {\n throw new CliError(`Supabase REST row ${index} was not a JSON object for ${url}`, {\n code: 'SUPABASE_REST_RESPONSE_INVALID',\n exitCode: 1,\n details: item,\n });\n }\n\n return {\n id: trimToken(item.id) ?? '',\n version: trimToken(item.version) ?? '',\n user_id: trimToken(item.user_id),\n state_code: typeof item.state_code === 'number' ? item.state_code : null,\n };\n });\n}\n\nasync function exactVisibleRows(options: {\n id: string;\n version: string;\n env: NodeJS.ProcessEnv;\n fetchImpl: FetchLike;\n timeoutMs: number;\n}): Promise<{\n rows: VisibleProcessRow[];\n restBaseUrl: string;\n accessToken: string;\n publishableKey: string;\n}> {\n const runtime = createSupabaseDataRuntime({\n runtime: requireSupabaseRestRuntime(options.env),\n fetchImpl: options.fetchImpl,\n timeoutMs: options.timeoutMs,\n });\n const { client, restBaseUrl } = createSupabaseDataClient(\n runtime,\n options.fetchImpl,\n options.timeoutMs,\n );\n const url = buildVisibleRowsUrl(restBaseUrl, options.id, options.version);\n const payload = await runSupabaseArrayQuery(\n client\n .from('processes')\n .select('id,version,user_id,state_code')\n .eq('id', options.id)\n .eq('version', options.version),\n url,\n );\n\n return {\n rows: parseVisibleRows(payload, url),\n restBaseUrl,\n accessToken: await runtime.getAccessToken(),\n publishableKey: runtime.publishableKey,\n };\n}\n\nfunction visibleDraftRow(rows: VisibleProcessRow[]): VisibleProcessRow | null {\n return rows.find((row) => row.state_code === 0) ?? null;\n}\n\nfunction visibleDraftRowForTarget(\n rows: VisibleProcessRow[],\n targetUserId: string | null,\n): VisibleProcessRow | null {\n if (!targetUserId) {\n return visibleDraftRow(rows);\n }\n return rows.find((row) => row.state_code === 0 && row.user_id === targetUserId) ?? null;\n}\n\nfunction buildCurrentUserUrl(restBaseUrl: string): string {\n return `${deriveSupabaseProjectBaseUrl(restBaseUrl)}/auth/v1/user`;\n}\n\nasync function currentUserId(options: {\n restBaseUrl: string;\n publishableKey: string;\n accessToken: string;\n timeoutMs: number;\n fetchImpl: FetchLike;\n}): Promise<string> {\n const url = buildCurrentUserUrl(options.restBaseUrl);\n const payload = await getJson({\n url,\n headers: buildSupabaseAuthHeaders(options.publishableKey, options.accessToken),\n timeoutMs: options.timeoutMs,\n fetchImpl: options.fetchImpl,\n });\n const userId = isRecord(payload) ? trimToken(payload.id) : null;\n if (!userId) {\n throw new CliError('Supabase current-user lookup succeeded without a user id.', {\n code: 'PROCESS_SAVE_DRAFT_CURRENT_USER_ID_MISSING',\n exitCode: 1,\n details: payload,\n });\n }\n return userId;\n}\n\nfunction assertTargetUserMatchesCurrent(options: {\n targetUserId: string | null;\n currentUserId: string;\n}): void {\n if (!options.targetUserId) {\n return;\n }\n if (options.currentUserId !== options.targetUserId) {\n throw new CliError(\n `Process save-draft target user ${options.targetUserId} does not match current CLI auth user ${options.currentUserId}.`,\n {\n code: 'PROCESS_SAVE_DRAFT_TARGET_USER_MISMATCH',\n exitCode: 1,\n details: {\n target_user_id: options.targetUserId,\n current_user_id: options.currentUserId,\n },\n },\n );\n }\n}\n\nfunction buildUnsupportedVisibleRowError(\n id: string,\n version: string,\n rows: VisibleProcessRow[],\n): CliError {\n const primaryRow = rows[0] ?? null;\n const stateCode =\n primaryRow?.state_code === null || primaryRow?.state_code === undefined\n ? 'unknown'\n : String(primaryRow.state_code);\n const visibleOwner = primaryRow?.user_id ?? 'unknown';\n\n return new CliError(\n `Process ${id}@${version} is already visible but cannot use save-draft because the visible row is not a current-user draft (state_code=${stateCode}, visible_owner=${visibleOwner}).`,\n {\n code: 'PUBLISH_PROCESS_SAVE_DRAFT_UNSUPPORTED_VISIBLE_ROW',\n exitCode: 1,\n details: {\n id,\n version,\n visible_rows: rows,\n },\n },\n );\n}\n\nasync function saveDraft(options: {\n restBaseUrl: string;\n publishableKey: string;\n accessToken: string;\n id: string;\n version: string;\n payload: JsonObject;\n timeoutMs: number;\n fetchImpl: FetchLike;\n audit?: JsonObject;\n modelId?: string | null;\n}): Promise<ProcessSaveDraftRpcResult> {\n const url = `${options.restBaseUrl.replace(/\\/+$/u, '')}/rpc/cmd_dataset_save_draft`;\n const payload = requireRemoteOkPayload(\n await postJson({\n url,\n headers: {\n ...buildSupabaseAuthHeaders(options.publishableKey, options.accessToken),\n 'Content-Type': 'application/json',\n },\n body: {\n p_table: 'processes',\n p_id: options.id,\n p_version: options.version,\n p_json_ordered: options.payload,\n p_model_id: options.modelId ?? null,\n p_audit: options.audit ?? null,\n },\n timeoutMs: options.timeoutMs,\n fetchImpl: options.fetchImpl,\n }),\n url,\n );\n\n if (!isRecord(payload) || payload.ok !== true) {\n throw new CliError(`Process save-draft RPC returned an unexpected payload for ${url}`, {\n code: 'REMOTE_RESPONSE_INVALID',\n exitCode: 1,\n details: payload,\n });\n }\n\n return payload as ProcessSaveDraftRpcResult;\n}\n\nexport async function syncStateAwareProcessRecord(\n options: SyncStateAwareProcessRecordOptions,\n): Promise<ProcessStateAwareWriteResult> {\n const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const targetUserId = trimToken(options.targetUserId);\n const visible = await exactVisibleRows({\n id: options.id,\n version: options.version,\n env: options.env,\n fetchImpl: options.fetchImpl,\n timeoutMs,\n });\n if (targetUserId) {\n const userId = await currentUserId({\n restBaseUrl: visible.restBaseUrl,\n publishableKey: visible.publishableKey,\n accessToken: visible.accessToken,\n timeoutMs,\n fetchImpl: options.fetchImpl,\n });\n assertTargetUserMatchesCurrent({ targetUserId, currentUserId: userId });\n }\n\n const draftRow = visibleDraftRowForTarget(visible.rows, targetUserId);\n\n if (!draftRow) {\n if (visible.rows.length > 0) {\n throw buildUnsupportedVisibleRowError(options.id, options.version, visible.rows);\n }\n\n return syncSupabaseJsonOrderedRecord({\n table: 'processes',\n id: options.id,\n version: options.version,\n payload: options.payload,\n writeMode: 'upsert_current_version',\n env: options.env,\n fetchImpl: options.fetchImpl,\n timeoutMs,\n });\n }\n\n return {\n status: 'success',\n operation: 'save_draft',\n write_path: 'cmd_dataset_save_draft',\n rpc_result: await saveDraft({\n restBaseUrl: visible.restBaseUrl,\n publishableKey: visible.publishableKey,\n accessToken: visible.accessToken,\n id: options.id,\n version: options.version,\n payload: options.payload,\n timeoutMs,\n fetchImpl: options.fetchImpl,\n audit: options.audit,\n modelId: options.modelId,\n }),\n visible_row: draftRow,\n };\n}\n\nexport const __testInternals = {\n buildVisibleRowsUrl,\n buildCurrentUserUrl,\n parseVisibleRows,\n visibleDraftRow,\n visibleDraftRowForTarget,\n assertTargetUserMatchesCurrent,\n buildUnsupportedVisibleRowError,\n};\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tiangong-lca/cli",
3
- "version": "0.0.12",
3
+ "version": "0.0.13",
4
4
  "description": "Unified TianGong LCA CLI with direct REST adapters and low-entropy command surface.",
5
5
  "repository": {
6
6
  "type": "git",