@tiangong-lca/cli 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +368 -0
- package/bin/tiangong.d.ts +1 -0
- package/bin/tiangong.js +32 -0
- package/dist/scripts/assert-full-coverage.js +77 -0
- package/dist/scripts/assert-full-coverage.js.map +1 -0
- package/dist/src/cli.js +2740 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/lib/artifacts.js +86 -0
- package/dist/src/lib/artifacts.js.map +1 -0
- package/dist/src/lib/dotenv.js +36 -0
- package/dist/src/lib/dotenv.js.map +1 -0
- package/dist/src/lib/env.js +139 -0
- package/dist/src/lib/env.js.map +1 -0
- package/dist/src/lib/errors.js +38 -0
- package/dist/src/lib/errors.js.map +1 -0
- package/dist/src/lib/flow-build-alias-map.js +299 -0
- package/dist/src/lib/flow-build-alias-map.js.map +1 -0
- package/dist/src/lib/flow-get.js +81 -0
- package/dist/src/lib/flow-get.js.map +1 -0
- package/dist/src/lib/flow-governance.js +164 -0
- package/dist/src/lib/flow-governance.js.map +1 -0
- package/dist/src/lib/flow-list.js +187 -0
- package/dist/src/lib/flow-list.js.map +1 -0
- package/dist/src/lib/flow-publish-reviewed-data.js +808 -0
- package/dist/src/lib/flow-publish-reviewed-data.js.map +1 -0
- package/dist/src/lib/flow-publish-version.js +541 -0
- package/dist/src/lib/flow-publish-version.js.map +1 -0
- package/dist/src/lib/flow-read.js +310 -0
- package/dist/src/lib/flow-read.js.map +1 -0
- package/dist/src/lib/flow-regen-product.js +1396 -0
- package/dist/src/lib/flow-regen-product.js.map +1 -0
- package/dist/src/lib/flow-remediate.js +821 -0
- package/dist/src/lib/flow-remediate.js.map +1 -0
- package/dist/src/lib/http.js +45 -0
- package/dist/src/lib/http.js.map +1 -0
- package/dist/src/lib/io.js +30 -0
- package/dist/src/lib/io.js.map +1 -0
- package/dist/src/lib/kb-search.js +83 -0
- package/dist/src/lib/kb-search.js.map +1 -0
- package/dist/src/lib/lifecyclemodel-auto-build.js +1328 -0
- package/dist/src/lib/lifecyclemodel-auto-build.js.map +1 -0
- package/dist/src/lib/lifecyclemodel-orchestrate.js +1556 -0
- package/dist/src/lib/lifecyclemodel-orchestrate.js.map +1 -0
- package/dist/src/lib/lifecyclemodel-publish-build.js +296 -0
- package/dist/src/lib/lifecyclemodel-publish-build.js.map +1 -0
- package/dist/src/lib/lifecyclemodel-publish-resulting-process.js +101 -0
- package/dist/src/lib/lifecyclemodel-publish-resulting-process.js.map +1 -0
- package/dist/src/lib/lifecyclemodel-resulting-process.js +1152 -0
- package/dist/src/lib/lifecyclemodel-resulting-process.js.map +1 -0
- package/dist/src/lib/lifecyclemodel-validate-build.js +238 -0
- package/dist/src/lib/lifecyclemodel-validate-build.js.map +1 -0
- package/dist/src/lib/llm.js +383 -0
- package/dist/src/lib/llm.js.map +1 -0
- package/dist/src/lib/process-auto-build.js +717 -0
- package/dist/src/lib/process-auto-build.js.map +1 -0
- package/dist/src/lib/process-batch-build.js +409 -0
- package/dist/src/lib/process-batch-build.js.map +1 -0
- package/dist/src/lib/process-get.js +66 -0
- package/dist/src/lib/process-get.js.map +1 -0
- package/dist/src/lib/process-publish-build.js +451 -0
- package/dist/src/lib/process-publish-build.js.map +1 -0
- package/dist/src/lib/process-resume-build.js +364 -0
- package/dist/src/lib/process-resume-build.js.map +1 -0
- package/dist/src/lib/publish.js +562 -0
- package/dist/src/lib/publish.js.map +1 -0
- package/dist/src/lib/remote.js +88 -0
- package/dist/src/lib/remote.js.map +1 -0
- package/dist/src/lib/review-flow.js +1110 -0
- package/dist/src/lib/review-flow.js.map +1 -0
- package/dist/src/lib/review-lifecyclemodel.js +727 -0
- package/dist/src/lib/review-lifecyclemodel.js.map +1 -0
- package/dist/src/lib/review-process.js +702 -0
- package/dist/src/lib/review-process.js.map +1 -0
- package/dist/src/lib/run.js +106 -0
- package/dist/src/lib/run.js.map +1 -0
- package/dist/src/lib/state-lock.js +150 -0
- package/dist/src/lib/state-lock.js.map +1 -0
- package/dist/src/lib/supabase-client.js +269 -0
- package/dist/src/lib/supabase-client.js.map +1 -0
- package/dist/src/lib/supabase-json-ordered-write.js +186 -0
- package/dist/src/lib/supabase-json-ordered-write.js.map +1 -0
- package/dist/src/lib/supabase-rest.js +138 -0
- package/dist/src/lib/supabase-rest.js.map +1 -0
- package/dist/src/lib/supabase-session.js +424 -0
- package/dist/src/lib/supabase-session.js.map +1 -0
- package/dist/src/lib/tidas-sdk-package-validator.js +493 -0
- package/dist/src/lib/tidas-sdk-package-validator.js.map +1 -0
- package/dist/src/lib/unstructured.js +203 -0
- package/dist/src/lib/unstructured.js.map +1 -0
- package/dist/src/lib/user-api-key.js +75 -0
- package/dist/src/lib/user-api-key.js.map +1 -0
- package/dist/src/lib/validation.js +191 -0
- package/dist/src/lib/validation.js.map +1 -0
- package/dist/src/main.js +38 -0
- package/dist/src/main.js.map +1 -0
- package/package.json +81 -0
|
@@ -0,0 +1,541 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { writeJsonArtifact, writeJsonLinesArtifact } from './artifacts.js';
|
|
4
|
+
import { CliError } from './errors.js';
|
|
5
|
+
import { coerceText, deepGet, isRecord, loadRowsFromFile, } from './flow-governance.js';
|
|
6
|
+
import { createSupabaseDataClient, requireSupabaseRestRuntime, runSupabaseArrayQuery, runSupabaseMutation, } from './supabase-client.js';
|
|
7
|
+
import { createSupabaseDataRuntime } from './supabase-session.js';
|
|
8
|
+
const DEFAULT_TIMEOUT_MS = 10_000;
|
|
9
|
+
const DEFAULT_MAX_WORKERS = 4;
|
|
10
|
+
const LEGACY_OUTPUT_PREFIX = 'flows_tidas_sdk_plus_classification';
|
|
11
|
+
function normalize_token(value) {
|
|
12
|
+
if (typeof value !== 'string') {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
const trimmed = value.trim();
|
|
16
|
+
return trimmed ? trimmed : null;
|
|
17
|
+
}
|
|
18
|
+
function assert_input_file(inputFile) {
|
|
19
|
+
const resolved = path.resolve(inputFile);
|
|
20
|
+
if (!inputFile) {
|
|
21
|
+
throw new CliError('Missing required --input-file value.', {
|
|
22
|
+
code: 'FLOW_PUBLISH_VERSION_INPUT_REQUIRED',
|
|
23
|
+
exitCode: 2,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
if (!existsSync(resolved)) {
|
|
27
|
+
throw new CliError(`Flow publish-version input file not found: ${resolved}`, {
|
|
28
|
+
code: 'FLOW_PUBLISH_VERSION_INPUT_NOT_FOUND',
|
|
29
|
+
exitCode: 2,
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
return resolved;
|
|
33
|
+
}
|
|
34
|
+
function assert_out_dir(outDir) {
|
|
35
|
+
if (!outDir) {
|
|
36
|
+
throw new CliError('Missing required --out-dir value.', {
|
|
37
|
+
code: 'FLOW_PUBLISH_VERSION_OUT_DIR_REQUIRED',
|
|
38
|
+
exitCode: 2,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
return path.resolve(outDir);
|
|
42
|
+
}
|
|
43
|
+
function to_positive_integer(value, label, code, defaultValue) {
|
|
44
|
+
if (value === undefined) {
|
|
45
|
+
return defaultValue;
|
|
46
|
+
}
|
|
47
|
+
if (!Number.isInteger(value) || value <= 0) {
|
|
48
|
+
throw new CliError(`Expected ${label} to be a positive integer.`, {
|
|
49
|
+
code,
|
|
50
|
+
exitCode: 2,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
return value;
|
|
54
|
+
}
|
|
55
|
+
function to_non_negative_integer(value, label, code) {
|
|
56
|
+
if (value === undefined) {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
if (!Number.isInteger(value) || value < 0) {
|
|
60
|
+
throw new CliError(`Expected ${label} to be a non-negative integer.`, {
|
|
61
|
+
code,
|
|
62
|
+
exitCode: 2,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
return value;
|
|
66
|
+
}
|
|
67
|
+
function build_output_files(outDir) {
|
|
68
|
+
return {
|
|
69
|
+
successList: path.join(outDir, `${LEGACY_OUTPUT_PREFIX}_mcp_success_list.json`),
|
|
70
|
+
remoteFailed: path.join(outDir, `${LEGACY_OUTPUT_PREFIX}_remote_validation_failed.jsonl`),
|
|
71
|
+
report: path.join(outDir, `${LEGACY_OUTPUT_PREFIX}_mcp_sync_report.json`),
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
function flow_payload(row) {
|
|
75
|
+
if (isRecord(row.json_ordered)) {
|
|
76
|
+
return row.json_ordered;
|
|
77
|
+
}
|
|
78
|
+
if (isRecord(row.jsonOrdered)) {
|
|
79
|
+
return row.jsonOrdered;
|
|
80
|
+
}
|
|
81
|
+
if (isRecord(row.json)) {
|
|
82
|
+
return row.json;
|
|
83
|
+
}
|
|
84
|
+
if (isRecord(row.flowDataSet)) {
|
|
85
|
+
return row;
|
|
86
|
+
}
|
|
87
|
+
throw new CliError('Flow row is missing json_ordered/jsonOrdered/json or a top-level flowDataSet payload.', {
|
|
88
|
+
code: 'FLOW_PUBLISH_VERSION_PAYLOAD_REQUIRED',
|
|
89
|
+
exitCode: 2,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
function flow_id(row, payload) {
|
|
93
|
+
return (coerceText(row.id) ||
|
|
94
|
+
coerceText(deepGet(payload, ['flowDataSet', 'flowInformation', 'dataSetInformation', 'common:UUID'])));
|
|
95
|
+
}
|
|
96
|
+
function flow_version(payload) {
|
|
97
|
+
const version = coerceText(deepGet(payload, [
|
|
98
|
+
'flowDataSet',
|
|
99
|
+
'administrativeInformation',
|
|
100
|
+
'publicationAndOwnership',
|
|
101
|
+
'common:dataSetVersion',
|
|
102
|
+
]));
|
|
103
|
+
if (!version) {
|
|
104
|
+
throw new CliError('Flow payload is missing flowDataSet.administrativeInformation.publicationAndOwnership.common:dataSetVersion.', {
|
|
105
|
+
code: 'FLOW_PUBLISH_VERSION_MISSING_VERSION',
|
|
106
|
+
exitCode: 2,
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
return version;
|
|
110
|
+
}
|
|
111
|
+
function resolve_target_user_id(row, targetUserIdOverride) {
|
|
112
|
+
return normalize_token(coerceText(row.user_id)) ?? targetUserIdOverride;
|
|
113
|
+
}
|
|
114
|
+
function build_visible_rows_url(restBaseUrl, id, version) {
|
|
115
|
+
const url = new URL(`${restBaseUrl.replace(/\/+$/u, '')}/flows`);
|
|
116
|
+
url.searchParams.set('select', 'id,version,user_id,state_code');
|
|
117
|
+
url.searchParams.set('id', `eq.${id}`);
|
|
118
|
+
url.searchParams.set('version', `eq.${version}`);
|
|
119
|
+
return url.toString();
|
|
120
|
+
}
|
|
121
|
+
function build_update_url(restBaseUrl, id, version) {
|
|
122
|
+
const url = new URL(`${restBaseUrl.replace(/\/+$/u, '')}/flows`);
|
|
123
|
+
url.searchParams.set('id', `eq.${id}`);
|
|
124
|
+
url.searchParams.set('version', `eq.${version}`);
|
|
125
|
+
return url.toString();
|
|
126
|
+
}
|
|
127
|
+
async function parse_response(response, url) {
|
|
128
|
+
const rawText = await response.text();
|
|
129
|
+
const contentType = response.headers.get('content-type') ?? '';
|
|
130
|
+
if (!response.ok) {
|
|
131
|
+
throw new CliError(`HTTP ${response.status} returned from ${url}`, {
|
|
132
|
+
code: 'REMOTE_REQUEST_FAILED',
|
|
133
|
+
exitCode: 1,
|
|
134
|
+
details: rawText,
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
if (!rawText) {
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
140
|
+
if (contentType.includes('application/json')) {
|
|
141
|
+
try {
|
|
142
|
+
return JSON.parse(rawText);
|
|
143
|
+
}
|
|
144
|
+
catch (error) {
|
|
145
|
+
throw new CliError(`Remote response was not valid JSON for ${url}`, {
|
|
146
|
+
code: 'REMOTE_INVALID_JSON',
|
|
147
|
+
exitCode: 1,
|
|
148
|
+
details: String(error),
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return rawText;
|
|
153
|
+
}
|
|
154
|
+
function parse_visible_rows(payload, url) {
|
|
155
|
+
if (!Array.isArray(payload)) {
|
|
156
|
+
throw new CliError(`Supabase REST response was not a JSON array for ${url}`, {
|
|
157
|
+
code: 'SUPABASE_REST_RESPONSE_INVALID',
|
|
158
|
+
exitCode: 1,
|
|
159
|
+
details: payload,
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
return payload.map((item, index) => {
|
|
163
|
+
if (!isRecord(item)) {
|
|
164
|
+
throw new CliError(`Supabase REST row ${index} was not a JSON object for ${url}`, {
|
|
165
|
+
code: 'SUPABASE_REST_RESPONSE_INVALID',
|
|
166
|
+
exitCode: 1,
|
|
167
|
+
details: item,
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
return {
|
|
171
|
+
id: coerceText(item.id),
|
|
172
|
+
version: coerceText(item.version),
|
|
173
|
+
user_id: coerceText(item.user_id),
|
|
174
|
+
state_code: typeof item.state_code === 'number' ? item.state_code : null,
|
|
175
|
+
};
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
async function visible_exact_rows(options) {
|
|
179
|
+
const url = build_visible_rows_url(options.restBaseUrl, options.id, options.version);
|
|
180
|
+
const payload = await runSupabaseArrayQuery(options.client
|
|
181
|
+
.from('flows')
|
|
182
|
+
.select('id,version,user_id,state_code')
|
|
183
|
+
.eq('id', options.id)
|
|
184
|
+
.eq('version', options.version), url);
|
|
185
|
+
return parse_visible_rows(payload, url);
|
|
186
|
+
}
|
|
187
|
+
function own_visible_row(rows, targetUserId) {
|
|
188
|
+
if (!targetUserId) {
|
|
189
|
+
return null;
|
|
190
|
+
}
|
|
191
|
+
return rows.find((row) => row.user_id === targetUserId) ?? null;
|
|
192
|
+
}
|
|
193
|
+
function visible_conflict_reasons(stage, visibleRows, targetUserId) {
|
|
194
|
+
if (visibleRows.length === 0) {
|
|
195
|
+
return [];
|
|
196
|
+
}
|
|
197
|
+
if (!targetUserId) {
|
|
198
|
+
return [
|
|
199
|
+
{
|
|
200
|
+
validator: 'remote_rest',
|
|
201
|
+
stage,
|
|
202
|
+
path: '',
|
|
203
|
+
message: 'Exact UUID/version is already visible, but no target user id was available to determine whether the row is writable.',
|
|
204
|
+
code: 'target_user_id_required',
|
|
205
|
+
},
|
|
206
|
+
];
|
|
207
|
+
}
|
|
208
|
+
return visibleRows.map((row) => ({
|
|
209
|
+
validator: 'remote_rest',
|
|
210
|
+
stage,
|
|
211
|
+
path: '',
|
|
212
|
+
message: 'Exact UUID/version is already visible but not writable under the target user.',
|
|
213
|
+
code: 'exact_version_visible_not_owned',
|
|
214
|
+
visible_user_id: row.user_id,
|
|
215
|
+
visible_state_code: row.state_code === null ? '' : String(row.state_code),
|
|
216
|
+
}));
|
|
217
|
+
}
|
|
218
|
+
function failure_row(sourceRow, reasons) {
|
|
219
|
+
let payload;
|
|
220
|
+
try {
|
|
221
|
+
payload = flow_payload(sourceRow);
|
|
222
|
+
}
|
|
223
|
+
catch {
|
|
224
|
+
payload = {};
|
|
225
|
+
}
|
|
226
|
+
return {
|
|
227
|
+
id: sourceRow.id,
|
|
228
|
+
user_id: sourceRow.user_id,
|
|
229
|
+
json_ordered: payload,
|
|
230
|
+
reason: reasons,
|
|
231
|
+
state_code: sourceRow.state_code,
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
function build_error_reasons(stage, error) {
|
|
235
|
+
if (error instanceof CliError) {
|
|
236
|
+
const detailText = typeof error.details === 'string' ? error.details.trim() : error.message;
|
|
237
|
+
return [
|
|
238
|
+
{
|
|
239
|
+
validator: 'remote_rest',
|
|
240
|
+
stage,
|
|
241
|
+
path: '',
|
|
242
|
+
message: detailText || error.message,
|
|
243
|
+
code: error.code,
|
|
244
|
+
},
|
|
245
|
+
];
|
|
246
|
+
}
|
|
247
|
+
if (error instanceof Error) {
|
|
248
|
+
return [
|
|
249
|
+
{
|
|
250
|
+
validator: 'remote_rest',
|
|
251
|
+
stage,
|
|
252
|
+
path: '',
|
|
253
|
+
message: error.message,
|
|
254
|
+
code: error.name || 'Error',
|
|
255
|
+
},
|
|
256
|
+
];
|
|
257
|
+
}
|
|
258
|
+
return [
|
|
259
|
+
{
|
|
260
|
+
validator: 'remote_rest',
|
|
261
|
+
stage,
|
|
262
|
+
path: '',
|
|
263
|
+
message: String(error),
|
|
264
|
+
code: 'UnknownError',
|
|
265
|
+
},
|
|
266
|
+
];
|
|
267
|
+
}
|
|
268
|
+
async function insert_flow_version(options) {
|
|
269
|
+
const url = `${options.restBaseUrl.replace(/\/+$/u, '')}/flows`;
|
|
270
|
+
await runSupabaseMutation(options.client.from('flows').insert({
|
|
271
|
+
id: options.rowId,
|
|
272
|
+
json_ordered: options.payload,
|
|
273
|
+
}), url);
|
|
274
|
+
}
|
|
275
|
+
async function update_flow_version(options) {
|
|
276
|
+
const url = build_update_url(options.restBaseUrl, options.rowId, options.version);
|
|
277
|
+
await runSupabaseMutation(options.client
|
|
278
|
+
.from('flows')
|
|
279
|
+
.update({
|
|
280
|
+
json_ordered: options.payload,
|
|
281
|
+
})
|
|
282
|
+
.eq('id', options.rowId)
|
|
283
|
+
.eq('version', options.version), url);
|
|
284
|
+
}
|
|
285
|
+
async function sync_one_row(options) {
|
|
286
|
+
try {
|
|
287
|
+
const payload = flow_payload(options.row);
|
|
288
|
+
const rowId = flow_id(options.row, payload);
|
|
289
|
+
if (!rowId) {
|
|
290
|
+
throw new CliError('Flow row is missing a resolvable id/common:UUID value.', {
|
|
291
|
+
code: 'FLOW_PUBLISH_VERSION_ID_REQUIRED',
|
|
292
|
+
exitCode: 2,
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
const version = flow_version(payload);
|
|
296
|
+
const targetUserId = resolve_target_user_id(options.row, options.targetUserIdOverride);
|
|
297
|
+
const visibleBefore = await visible_exact_rows({
|
|
298
|
+
client: options.client,
|
|
299
|
+
restBaseUrl: options.restBaseUrl,
|
|
300
|
+
id: rowId,
|
|
301
|
+
version,
|
|
302
|
+
});
|
|
303
|
+
const ownBefore = own_visible_row(visibleBefore, targetUserId);
|
|
304
|
+
if (options.mode === 'dry_run') {
|
|
305
|
+
if (ownBefore) {
|
|
306
|
+
return {
|
|
307
|
+
status: 'success',
|
|
308
|
+
success: {
|
|
309
|
+
id: rowId,
|
|
310
|
+
version,
|
|
311
|
+
operation: 'would_update_existing',
|
|
312
|
+
},
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
if (visibleBefore.length > 0) {
|
|
316
|
+
return {
|
|
317
|
+
status: 'failure',
|
|
318
|
+
failure: failure_row(options.row, visible_conflict_reasons('dry_run_preflight', visibleBefore, targetUserId)),
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
return {
|
|
322
|
+
status: 'success',
|
|
323
|
+
success: {
|
|
324
|
+
id: rowId,
|
|
325
|
+
version,
|
|
326
|
+
operation: 'would_insert',
|
|
327
|
+
},
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
if (ownBefore) {
|
|
331
|
+
await update_flow_version({
|
|
332
|
+
client: options.client,
|
|
333
|
+
restBaseUrl: options.restBaseUrl,
|
|
334
|
+
rowId,
|
|
335
|
+
version,
|
|
336
|
+
payload,
|
|
337
|
+
});
|
|
338
|
+
return {
|
|
339
|
+
status: 'success',
|
|
340
|
+
success: {
|
|
341
|
+
id: rowId,
|
|
342
|
+
version,
|
|
343
|
+
operation: 'update_existing',
|
|
344
|
+
},
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
if (visibleBefore.length > 0) {
|
|
348
|
+
return {
|
|
349
|
+
status: 'failure',
|
|
350
|
+
failure: failure_row(options.row, visible_conflict_reasons('preflight', visibleBefore, targetUserId)),
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
try {
|
|
354
|
+
await insert_flow_version({
|
|
355
|
+
client: options.client,
|
|
356
|
+
restBaseUrl: options.restBaseUrl,
|
|
357
|
+
rowId,
|
|
358
|
+
payload,
|
|
359
|
+
});
|
|
360
|
+
return {
|
|
361
|
+
status: 'success',
|
|
362
|
+
success: {
|
|
363
|
+
id: rowId,
|
|
364
|
+
version,
|
|
365
|
+
operation: 'insert',
|
|
366
|
+
},
|
|
367
|
+
};
|
|
368
|
+
}
|
|
369
|
+
catch (error) {
|
|
370
|
+
const visibleAfter = await visible_exact_rows({
|
|
371
|
+
client: options.client,
|
|
372
|
+
restBaseUrl: options.restBaseUrl,
|
|
373
|
+
id: rowId,
|
|
374
|
+
version,
|
|
375
|
+
});
|
|
376
|
+
const ownAfter = own_visible_row(visibleAfter, targetUserId);
|
|
377
|
+
if (ownAfter) {
|
|
378
|
+
try {
|
|
379
|
+
await update_flow_version({
|
|
380
|
+
client: options.client,
|
|
381
|
+
restBaseUrl: options.restBaseUrl,
|
|
382
|
+
rowId,
|
|
383
|
+
version,
|
|
384
|
+
payload,
|
|
385
|
+
});
|
|
386
|
+
return {
|
|
387
|
+
status: 'success',
|
|
388
|
+
success: {
|
|
389
|
+
id: rowId,
|
|
390
|
+
version,
|
|
391
|
+
operation: 'update_after_insert_error',
|
|
392
|
+
},
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
catch (updateError) {
|
|
396
|
+
return {
|
|
397
|
+
status: 'failure',
|
|
398
|
+
failure: failure_row(options.row, [
|
|
399
|
+
...build_error_reasons('insert', error),
|
|
400
|
+
...build_error_reasons('update_after_insert_error', updateError),
|
|
401
|
+
]),
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
return {
|
|
406
|
+
status: 'failure',
|
|
407
|
+
failure: failure_row(options.row, [
|
|
408
|
+
...build_error_reasons('insert', error),
|
|
409
|
+
...visible_conflict_reasons('post_insert_error_preflight', visibleAfter, targetUserId),
|
|
410
|
+
]),
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
catch (error) {
|
|
415
|
+
return {
|
|
416
|
+
status: 'failure',
|
|
417
|
+
failure: failure_row(options.row, build_error_reasons('sync_one_unhandled', error)),
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
async function map_with_concurrency(items, maxWorkers, worker) {
|
|
422
|
+
const results = new Array(items.length);
|
|
423
|
+
const workerCount = Math.min(Math.max(1, maxWorkers), Math.max(items.length, 1));
|
|
424
|
+
let nextIndex = 0;
|
|
425
|
+
async function runWorker() {
|
|
426
|
+
while (true) {
|
|
427
|
+
const currentIndex = nextIndex;
|
|
428
|
+
nextIndex += 1;
|
|
429
|
+
if (currentIndex >= items.length) {
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
results[currentIndex] = await worker(items[currentIndex], currentIndex);
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
await Promise.all(Array.from({ length: workerCount }, () => runWorker()));
|
|
436
|
+
return results;
|
|
437
|
+
}
|
|
438
|
+
function status_from_mode(mode, failureCount) {
|
|
439
|
+
if (mode === 'dry_run') {
|
|
440
|
+
return 'prepared_flow_publish_version';
|
|
441
|
+
}
|
|
442
|
+
return failureCount > 0
|
|
443
|
+
? 'completed_flow_publish_version_with_failures'
|
|
444
|
+
: 'completed_flow_publish_version';
|
|
445
|
+
}
|
|
446
|
+
export async function runFlowPublishVersion(options) {
|
|
447
|
+
const inputFile = assert_input_file(options.inputFile);
|
|
448
|
+
const outDir = assert_out_dir(options.outDir);
|
|
449
|
+
const mode = options.commit ? 'commit' : 'dry_run';
|
|
450
|
+
const maxWorkers = to_positive_integer(options.maxWorkers, '--max-workers', 'FLOW_PUBLISH_VERSION_MAX_WORKERS_INVALID', DEFAULT_MAX_WORKERS);
|
|
451
|
+
const limit = to_non_negative_integer(options.limit, '--limit', 'FLOW_PUBLISH_VERSION_LIMIT_INVALID');
|
|
452
|
+
const fetchImpl = options.fetchImpl ?? fetch;
|
|
453
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
454
|
+
const now = options.now ?? new Date();
|
|
455
|
+
const runtime = createSupabaseDataRuntime({
|
|
456
|
+
runtime: requireSupabaseRestRuntime(options.env ?? process.env),
|
|
457
|
+
fetchImpl,
|
|
458
|
+
timeoutMs,
|
|
459
|
+
now,
|
|
460
|
+
});
|
|
461
|
+
const { client, restBaseUrl } = createSupabaseDataClient(runtime, fetchImpl, timeoutMs);
|
|
462
|
+
const targetUserIdOverride = normalize_token(options.targetUserId ?? null);
|
|
463
|
+
const files = build_output_files(outDir);
|
|
464
|
+
let rows = loadRowsFromFile(inputFile);
|
|
465
|
+
if (limit !== null && limit > 0) {
|
|
466
|
+
rows = rows.slice(0, limit);
|
|
467
|
+
}
|
|
468
|
+
if (rows.length === 0) {
|
|
469
|
+
throw new CliError(`No rows found in ${inputFile}`, {
|
|
470
|
+
code: 'FLOW_PUBLISH_VERSION_EMPTY_INPUT',
|
|
471
|
+
exitCode: 2,
|
|
472
|
+
});
|
|
473
|
+
}
|
|
474
|
+
const outcomes = await map_with_concurrency(rows, maxWorkers, async (row) => sync_one_row({
|
|
475
|
+
row,
|
|
476
|
+
mode,
|
|
477
|
+
client,
|
|
478
|
+
restBaseUrl,
|
|
479
|
+
targetUserIdOverride,
|
|
480
|
+
}));
|
|
481
|
+
const successes = [];
|
|
482
|
+
const failures = [];
|
|
483
|
+
const operationCounts = {};
|
|
484
|
+
for (const outcome of outcomes) {
|
|
485
|
+
if (outcome.status === 'success') {
|
|
486
|
+
successes.push(outcome.success);
|
|
487
|
+
operationCounts[outcome.success.operation] =
|
|
488
|
+
(operationCounts[outcome.success.operation] ?? 0) + 1;
|
|
489
|
+
}
|
|
490
|
+
else {
|
|
491
|
+
failures.push(outcome.failure);
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
await writeJsonArtifact(files.successList, successes);
|
|
495
|
+
await writeJsonLinesArtifact(files.remoteFailed, failures);
|
|
496
|
+
const report = {
|
|
497
|
+
schema_version: 1,
|
|
498
|
+
generated_at_utc: (options.now ?? new Date()).toISOString(),
|
|
499
|
+
status: status_from_mode(mode, failures.length),
|
|
500
|
+
mode,
|
|
501
|
+
input_file: inputFile,
|
|
502
|
+
out_dir: outDir,
|
|
503
|
+
counts: {
|
|
504
|
+
total_rows: rows.length,
|
|
505
|
+
success_count: successes.length,
|
|
506
|
+
failure_count: failures.length,
|
|
507
|
+
},
|
|
508
|
+
operation_counts: operationCounts,
|
|
509
|
+
max_workers: maxWorkers,
|
|
510
|
+
limit,
|
|
511
|
+
target_user_id_override: targetUserIdOverride,
|
|
512
|
+
files: {
|
|
513
|
+
success_list: files.successList,
|
|
514
|
+
remote_failed: files.remoteFailed,
|
|
515
|
+
report: files.report,
|
|
516
|
+
},
|
|
517
|
+
};
|
|
518
|
+
await writeJsonArtifact(files.report, report);
|
|
519
|
+
return report;
|
|
520
|
+
}
|
|
521
|
+
export const __testInternals = {
|
|
522
|
+
assert_input_file,
|
|
523
|
+
assert_out_dir,
|
|
524
|
+
to_positive_integer,
|
|
525
|
+
to_non_negative_integer,
|
|
526
|
+
build_output_files,
|
|
527
|
+
flow_payload,
|
|
528
|
+
flow_id,
|
|
529
|
+
flow_version,
|
|
530
|
+
resolve_target_user_id,
|
|
531
|
+
build_visible_rows_url,
|
|
532
|
+
build_update_url,
|
|
533
|
+
parse_response,
|
|
534
|
+
parse_visible_rows,
|
|
535
|
+
visible_conflict_reasons,
|
|
536
|
+
failure_row,
|
|
537
|
+
build_error_reasons,
|
|
538
|
+
map_with_concurrency,
|
|
539
|
+
status_from_mode,
|
|
540
|
+
};
|
|
541
|
+
//# sourceMappingURL=flow-publish-version.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flow-publish-version.js","sourceRoot":"","sources":["../../../src/lib/flow-publish-version.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAC3E,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EACL,UAAU,EACV,OAAO,EACP,QAAQ,EACR,gBAAgB,GAEjB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,wBAAwB,EACxB,0BAA0B,EAC1B,qBAAqB,EACrB,mBAAmB,GACpB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AAElE,MAAM,kBAAkB,GAAG,MAAM,CAAC;AAClC,MAAM,mBAAmB,GAAG,CAAC,CAAC;AAC9B,MAAM,oBAAoB,GAAG,qCAAqC,CAAC;AAkGnE,SAAS,eAAe,CAAC,KAAc;IACrC,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC7B,OAAO,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;AAClC,CAAC;AAED,SAAS,iBAAiB,CAAC,SAAiB;IAC1C,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACzC,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,QAAQ,CAAC,sCAAsC,EAAE;YACzD,IAAI,EAAE,qCAAqC;YAC3C,QAAQ,EAAE,CAAC;SACZ,CAAC,CAAC;IACL,CAAC;IACD,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,QAAQ,CAAC,8CAA8C,QAAQ,EAAE,EAAE;YAC3E,IAAI,EAAE,sCAAsC;YAC5C,QAAQ,EAAE,CAAC;SACZ,CAAC,CAAC;IACL,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,cAAc,CAAC,MAAc;IACpC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,QAAQ,CAAC,mCAAmC,EAAE;YACtD,IAAI,EAAE,uCAAuC;YAC7C,QAAQ,EAAE,CAAC;SACZ,CAAC,CAAC;IACL,CAAC;IACD,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;AAC9B,CAAC;AAED,SAAS,mBAAmB,CAC1B,KAAyB,EACzB,KAAa,EACb,IAAY,EACZ,YAAoB;IAEpB,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,OAAO,YAAY,CAAC;IACtB,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;QAC3C,MAAM,IAAI,QAAQ,CAAC,YAAY,KAAK,4BAA4B,EAAE;YAChE,IAAI;YACJ,QAAQ,EAAE,CAAC;SACZ,CAAC,CAAC;IACL,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,uBAAuB,CAC9B,KAAyB,EACzB,KAAa,EACb,IAAY;IAEZ,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QAC1C,MAAM,IAAI,QAAQ,CAAC,YAAY,KAAK,gCAAgC,EAAE;YACpE,IAAI;YACJ,QAAQ,EAAE,CAAC;SACZ,CAAC,CAAC;IACL,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,kBAAkB,CAAC,MAAc;IACxC,OAAO;QACL,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,oBAAoB,wBAAwB,CAAC;QAC/E,YAAY,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,oBAAoB,iCAAiC,CAAC;QACzF,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,oBAAoB,uBAAuB,CAAC;KAC1E,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CAAC,GAAe;IACnC,IAAI,QAAQ,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC;QAC/B,OAAO,GAAG,CAAC,YAAY,CAAC;IAC1B,CAAC;IACD,IAAI,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;QAC9B,OAAO,GAAG,CAAC,WAAW,CAAC;IACzB,CAAC;IACD,IAAI,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;QACvB,OAAO,GAAG,CAAC,IAAI,CAAC;IAClB,CAAC;IACD,IAAI,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;QAC9B,OAAO,GAAG,CAAC;IACb,CAAC;IACD,MAAM,IAAI,QAAQ,CAChB,uFAAuF,EACvF;QACE,IAAI,EAAE,uCAAuC;QAC7C,QAAQ,EAAE,CAAC;KACZ,CACF,CAAC;AACJ,CAAC;AAED,SAAS,OAAO,CAAC,GAAe,EAAE,OAAmB;IACnD,OAAO,CACL,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAClB,UAAU,CACR,OAAO,CAAC,OAAO,EAAE,CAAC,aAAa,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,aAAa,CAAC,CAAC,CAC1F,CACF,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CAAC,OAAmB;IACvC,MAAM,OAAO,GAAG,UAAU,CACxB,OAAO,CAAC,OAAO,EAAE;QACf,aAAa;QACb,2BAA2B;QAC3B,yBAAyB;QACzB,uBAAuB;KACxB,CAAC,CACH,CAAC;IACF,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,QAAQ,CAChB,8GAA8G,EAC9G;YACE,IAAI,EAAE,sCAAsC;YAC5C,QAAQ,EAAE,CAAC;SACZ,CACF,CAAC;IACJ,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,sBAAsB,CAC7B,GAAe,EACf,oBAAmC;IAEnC,OAAO,eAAe,CAAC,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,IAAI,oBAAoB,CAAC;AAC1E,CAAC;AAED,SAAS,sBAAsB,CAAC,WAAmB,EAAE,EAAU,EAAE,OAAe;IAC9E,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,WAAW,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC;IACjE,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,EAAE,+BAA+B,CAAC,CAAC;IAChE,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC;IACvC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,EAAE,MAAM,OAAO,EAAE,CAAC,CAAC;IACjD,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC;AACxB,CAAC;AAED,SAAS,gBAAgB,CAAC,WAAmB,EAAE,EAAU,EAAE,OAAe;IACxE,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,WAAW,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC;IACjE,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC;IACvC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,EAAE,MAAM,OAAO,EAAE,CAAC,CAAC;IACjD,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC;AACxB,CAAC;AAED,KAAK,UAAU,cAAc,CAAC,QAAsB,EAAE,GAAW;IAC/D,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IACtC,MAAM,WAAW,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;IAE/D,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,QAAQ,CAAC,QAAQ,QAAQ,CAAC,MAAM,kBAAkB,GAAG,EAAE,EAAE;YACjE,IAAI,EAAE,uBAAuB;YAC7B,QAAQ,EAAE,CAAC;YACX,OAAO,EAAE,OAAO;SACjB,CAAC,CAAC;IACL,CAAC;IAED,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,WAAW,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC;QAC7C,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC7B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,QAAQ,CAAC,0CAA0C,GAAG,EAAE,EAAE;gBAClE,IAAI,EAAE,qBAAqB;gBAC3B,QAAQ,EAAE,CAAC;gBACX,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC;aACvB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,kBAAkB,CAAC,OAAgB,EAAE,GAAW;IACvD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,QAAQ,CAAC,mDAAmD,GAAG,EAAE,EAAE;YAC3E,IAAI,EAAE,gCAAgC;YACtC,QAAQ,EAAE,CAAC;YACX,OAAO,EAAE,OAAO;SACjB,CAAC,CAAC;IACL,CAAC;IAED,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;QACjC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACpB,MAAM,IAAI,QAAQ,CAAC,qBAAqB,KAAK,8BAA8B,GAAG,EAAE,EAAE;gBAChF,IAAI,EAAE,gCAAgC;gBACtC,QAAQ,EAAE,CAAC;gBACX,OAAO,EAAE,IAAI;aACd,CAAC,CAAC;QACL,CAAC;QAED,OAAO;YACL,EAAE,EAAE,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACvB,OAAO,EAAE,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC;YACjC,OAAO,EAAE,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC;YACjC,UAAU,EAAE,OAAO,IAAI,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI;SACzE,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAED,KAAK,UAAU,kBAAkB,CAAC,OAKjC;IACC,MAAM,GAAG,GAAG,sBAAsB,CAAC,OAAO,CAAC,WAAW,EAAE,OAAO,CAAC,EAAE,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IACrF,MAAM,OAAO,GAAG,MAAM,qBAAqB,CACzC,OAAO,CAAC,MAAM;SACX,IAAI,CAAC,OAAO,CAAC;SACb,MAAM,CAAC,+BAA+B,CAAC;SACvC,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,CAAC;SACpB,EAAE,CAAC,SAAS,EAAE,OAAO,CAAC,OAAO,CAAC,EACjC,GAAG,CACJ,CAAC;IACF,OAAO,kBAAkB,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;AAC1C,CAAC;AAED,SAAS,eAAe,CACtB,IAAsB,EACtB,YAA2B;IAE3B,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,KAAK,YAAY,CAAC,IAAI,IAAI,CAAC;AAClE,CAAC;AAED,SAAS,wBAAwB,CAC/B,KAAa,EACb,WAA6B,EAC7B,YAA2B;IAE3B,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7B,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,OAAO;YACL;gBACE,SAAS,EAAE,aAAa;gBACxB,KAAK;gBACL,IAAI,EAAE,EAAE;gBACR,OAAO,EACL,sHAAsH;gBACxH,IAAI,EAAE,yBAAyB;aAChC;SACF,CAAC;IACJ,CAAC;IAED,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QAC/B,SAAS,EAAE,aAAa;QACxB,KAAK;QACL,IAAI,EAAE,EAAE;QACR,OAAO,EAAE,+EAA+E;QACxF,IAAI,EAAE,iCAAiC;QACvC,eAAe,EAAE,GAAG,CAAC,OAAO;QAC5B,kBAAkB,EAAE,GAAG,CAAC,UAAU,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC;KAC1E,CAAC,CAAC,CAAC;AACN,CAAC;AAED,SAAS,WAAW,CAClB,SAAqB,EACrB,OAAmC;IAEnC,IAAI,OAAmB,CAAC;IACxB,IAAI,CAAC;QACH,OAAO,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC;IACpC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,GAAG,EAAE,CAAC;IACf,CAAC;IACD,OAAO;QACL,EAAE,EAAE,SAAS,CAAC,EAAE;QAChB,OAAO,EAAE,SAAS,CAAC,OAAO;QAC1B,YAAY,EAAE,OAAO;QACrB,MAAM,EAAE,OAAO;QACf,UAAU,EAAE,SAAS,CAAC,UAAU;KACjC,CAAC;AACJ,CAAC;AAED,SAAS,mBAAmB,CAAC,KAAa,EAAE,KAAc;IACxD,IAAI,KAAK,YAAY,QAAQ,EAAE,CAAC;QAC9B,MAAM,UAAU,GAAG,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC;QAC5F,OAAO;YACL;gBACE,SAAS,EAAE,aAAa;gBACxB,KAAK;gBACL,IAAI,EAAE,EAAE;gBACR,OAAO,EAAE,UAAU,IAAI,KAAK,CAAC,OAAO;gBACpC,IAAI,EAAE,KAAK,CAAC,IAAI;aACjB;SACF,CAAC;IACJ,CAAC;IAED,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;QAC3B,OAAO;YACL;gBACE,SAAS,EAAE,aAAa;gBACxB,KAAK;gBACL,IAAI,EAAE,EAAE;gBACR,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,OAAO;aAC5B;SACF,CAAC;IACJ,CAAC;IAED,OAAO;QACL;YACE,SAAS,EAAE,aAAa;YACxB,KAAK;YACL,IAAI,EAAE,EAAE;YACR,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC;YACtB,IAAI,EAAE,cAAc;SACrB;KACF,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,mBAAmB,CAAC,OAKlC;IACC,MAAM,GAAG,GAAG,GAAG,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,QAAQ,CAAC;IAChE,MAAM,mBAAmB,CACvB,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC;QAClC,EAAE,EAAE,OAAO,CAAC,KAAK;QACjB,YAAY,EAAE,OAAO,CAAC,OAAO;KAC9B,CAAC,EACF,GAAG,CACJ,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,mBAAmB,CAAC,OAMlC;IACC,MAAM,GAAG,GAAG,gBAAgB,CAAC,OAAO,CAAC,WAAW,EAAE,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IAClF,MAAM,mBAAmB,CACvB,OAAO,CAAC,MAAM;SACX,IAAI,CAAC,OAAO,CAAC;SACb,MAAM,CAAC;QACN,YAAY,EAAE,OAAO,CAAC,OAAO;KAC9B,CAAC;SACD,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC;SACvB,EAAE,CAAC,SAAS,EAAE,OAAO,CAAC,OAAO,CAAC,EACjC,GAAG,CACJ,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,YAAY,CAAC,OAM3B;IACC,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC1C,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QAC5C,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,QAAQ,CAAC,wDAAwD,EAAE;gBAC3E,IAAI,EAAE,kCAAkC;gBACxC,QAAQ,EAAE,CAAC;aACZ,CAAC,CAAC;QACL,CAAC;QACD,MAAM,OAAO,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;QACtC,MAAM,YAAY,GAAG,sBAAsB,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,oBAAoB,CAAC,CAAC;QACvF,MAAM,aAAa,GAAG,MAAM,kBAAkB,CAAC;YAC7C,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,WAAW,EAAE,OAAO,CAAC,WAAW;YAChC,EAAE,EAAE,KAAK;YACT,OAAO;SACR,CAAC,CAAC;QACH,MAAM,SAAS,GAAG,eAAe,CAAC,aAAa,EAAE,YAAY,CAAC,CAAC;QAE/D,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC/B,IAAI,SAAS,EAAE,CAAC;gBACd,OAAO;oBACL,MAAM,EAAE,SAAS;oBACjB,OAAO,EAAE;wBACP,EAAE,EAAE,KAAK;wBACT,OAAO;wBACP,SAAS,EAAE,uBAAuB;qBACnC;iBACF,CAAC;YACJ,CAAC;YAED,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC7B,OAAO;oBACL,MAAM,EAAE,SAAS;oBACjB,OAAO,EAAE,WAAW,CAClB,OAAO,CAAC,GAAG,EACX,wBAAwB,CAAC,mBAAmB,EAAE,aAAa,EAAE,YAAY,CAAC,CAC3E;iBACF,CAAC;YACJ,CAAC;YAED,OAAO;gBACL,MAAM,EAAE,SAAS;gBACjB,OAAO,EAAE;oBACP,EAAE,EAAE,KAAK;oBACT,OAAO;oBACP,SAAS,EAAE,cAAc;iBAC1B;aACF,CAAC;QACJ,CAAC;QAED,IAAI,SAAS,EAAE,CAAC;YACd,MAAM,mBAAmB,CAAC;gBACxB,MAAM,EAAE,OAAO,CAAC,MAAM;gBACtB,WAAW,EAAE,OAAO,CAAC,WAAW;gBAChC,KAAK;gBACL,OAAO;gBACP,OAAO;aACR,CAAC,CAAC;YACH,OAAO;gBACL,MAAM,EAAE,SAAS;gBACjB,OAAO,EAAE;oBACP,EAAE,EAAE,KAAK;oBACT,OAAO;oBACP,SAAS,EAAE,iBAAiB;iBAC7B;aACF,CAAC;QACJ,CAAC;QAED,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7B,OAAO;gBACL,MAAM,EAAE,SAAS;gBACjB,OAAO,EAAE,WAAW,CAClB,OAAO,CAAC,GAAG,EACX,wBAAwB,CAAC,WAAW,EAAE,aAAa,EAAE,YAAY,CAAC,CACnE;aACF,CAAC;QACJ,CAAC;QAED,IAAI,CAAC;YACH,MAAM,mBAAmB,CAAC;gBACxB,MAAM,EAAE,OAAO,CAAC,MAAM;gBACtB,WAAW,EAAE,OAAO,CAAC,WAAW;gBAChC,KAAK;gBACL,OAAO;aACR,CAAC,CAAC;YACH,OAAO;gBACL,MAAM,EAAE,SAAS;gBACjB,OAAO,EAAE;oBACP,EAAE,EAAE,KAAK;oBACT,OAAO;oBACP,SAAS,EAAE,QAAQ;iBACpB;aACF,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,YAAY,GAAG,MAAM,kBAAkB,CAAC;gBAC5C,MAAM,EAAE,OAAO,CAAC,MAAM;gBACtB,WAAW,EAAE,OAAO,CAAC,WAAW;gBAChC,EAAE,EAAE,KAAK;gBACT,OAAO;aACR,CAAC,CAAC;YACH,MAAM,QAAQ,GAAG,eAAe,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;YAC7D,IAAI,QAAQ,EAAE,CAAC;gBACb,IAAI,CAAC;oBACH,MAAM,mBAAmB,CAAC;wBACxB,MAAM,EAAE,OAAO,CAAC,MAAM;wBACtB,WAAW,EAAE,OAAO,CAAC,WAAW;wBAChC,KAAK;wBACL,OAAO;wBACP,OAAO;qBACR,CAAC,CAAC;oBACH,OAAO;wBACL,MAAM,EAAE,SAAS;wBACjB,OAAO,EAAE;4BACP,EAAE,EAAE,KAAK;4BACT,OAAO;4BACP,SAAS,EAAE,2BAA2B;yBACvC;qBACF,CAAC;gBACJ,CAAC;gBAAC,OAAO,WAAW,EAAE,CAAC;oBACrB,OAAO;wBACL,MAAM,EAAE,SAAS;wBACjB,OAAO,EAAE,WAAW,CAAC,OAAO,CAAC,GAAG,EAAE;4BAChC,GAAG,mBAAmB,CAAC,QAAQ,EAAE,KAAK,CAAC;4BACvC,GAAG,mBAAmB,CAAC,2BAA2B,EAAE,WAAW,CAAC;yBACjE,CAAC;qBACH,CAAC;gBACJ,CAAC;YACH,CAAC;YAED,OAAO;gBACL,MAAM,EAAE,SAAS;gBACjB,OAAO,EAAE,WAAW,CAAC,OAAO,CAAC,GAAG,EAAE;oBAChC,GAAG,mBAAmB,CAAC,QAAQ,EAAE,KAAK,CAAC;oBACvC,GAAG,wBAAwB,CAAC,6BAA6B,EAAE,YAAY,EAAE,YAAY,CAAC;iBACvF,CAAC;aACH,CAAC;QACJ,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,MAAM,EAAE,SAAS;YACjB,OAAO,EAAE,WAAW,CAAC,OAAO,CAAC,GAAG,EAAE,mBAAmB,CAAC,oBAAoB,EAAE,KAAK,CAAC,CAAC;SACpF,CAAC;IACJ,CAAC;AACH,CAAC;AAED,KAAK,UAAU,oBAAoB,CACjC,KAAU,EACV,UAAkB,EAClB,MAA8C;IAE9C,MAAM,OAAO,GAAG,IAAI,KAAK,CAAI,KAAK,CAAC,MAAM,CAAC,CAAC;IAC3C,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;IACjF,IAAI,SAAS,GAAG,CAAC,CAAC;IAElB,KAAK,UAAU,SAAS;QACtB,OAAO,IAAI,EAAE,CAAC;YACZ,MAAM,YAAY,GAAG,SAAS,CAAC;YAC/B,SAAS,IAAI,CAAC,CAAC;YACf,IAAI,YAAY,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;gBACjC,OAAO;YACT,CAAC;YACD,OAAO,CAAC,YAAY,CAAC,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,YAAY,CAAM,EAAE,YAAY,CAAC,CAAC;QAC/E,CAAC;IACH,CAAC;IAED,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,EAAE,GAAG,EAAE,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;IAC1E,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,gBAAgB,CACvB,IAAqB,EACrB,YAAoB;IAEpB,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,OAAO,+BAA+B,CAAC;IACzC,CAAC;IACD,OAAO,YAAY,GAAG,CAAC;QACrB,CAAC,CAAC,8CAA8C;QAChD,CAAC,CAAC,gCAAgC,CAAC;AACvC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,OAAqC;IAErC,MAAM,SAAS,GAAG,iBAAiB,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACvD,MAAM,MAAM,GAAG,cAAc,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAC9C,MAAM,IAAI,GAAoB,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;IACpE,MAAM,UAAU,GAAG,mBAAmB,CACpC,OAAO,CAAC,UAAU,EAClB,eAAe,EACf,0CAA0C,EAC1C,mBAAmB,CACpB,CAAC;IACF,MAAM,KAAK,GAAG,uBAAuB,CACnC,OAAO,CAAC,KAAK,EACb,SAAS,EACT,oCAAoC,CACrC,CAAC;IACF,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAK,KAAmB,CAAC;IAC5D,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,kBAAkB,CAAC;IAC1D,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,IAAI,IAAI,EAAE,CAAC;IACtC,MAAM,OAAO,GAAG,yBAAyB,CAAC;QACxC,OAAO,EAAE,0BAA0B,CAAC,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC;QAC/D,SAAS;QACT,SAAS;QACT,GAAG;KACJ,CAAC,CAAC;IACH,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,wBAAwB,CAAC,OAAO,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;IACxF,MAAM,oBAAoB,GAAG,eAAe,CAAC,OAAO,CAAC,YAAY,IAAI,IAAI,CAAC,CAAC;IAC3E,MAAM,KAAK,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAEzC,IAAI,IAAI,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAC;IACvC,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QAChC,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IAC9B,CAAC;IACD,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,QAAQ,CAAC,oBAAoB,SAAS,EAAE,EAAE;YAClD,IAAI,EAAE,kCAAkC;YACxC,QAAQ,EAAE,CAAC;SACZ,CAAC,CAAC;IACL,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,oBAAoB,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,CAC1E,YAAY,CAAC;QACX,GAAG;QACH,IAAI;QACJ,MAAM;QACN,WAAW;QACX,oBAAoB;KACrB,CAAC,CACH,CAAC;IAEF,MAAM,SAAS,GAA4B,EAAE,CAAC;IAC9C,MAAM,QAAQ,GAA4B,EAAE,CAAC;IAC7C,MAAM,eAAe,GAA2B,EAAE,CAAC;IAEnD,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YACjC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YAChC,eAAe,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC;gBACxC,CAAC,eAAe,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;QAC1D,CAAC;aAAM,CAAC;YACN,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;IAED,MAAM,iBAAiB,CAAC,KAAK,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;IACtD,MAAM,sBAAsB,CAAC,KAAK,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;IAE3D,MAAM,MAAM,GAA6B;QACvC,cAAc,EAAE,CAAC;QACjB,gBAAgB,EAAE,CAAC,OAAO,CAAC,GAAG,IAAI,IAAI,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE;QAC3D,MAAM,EAAE,gBAAgB,CAAC,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC;QAC/C,IAAI;QACJ,UAAU,EAAE,SAAS;QACrB,OAAO,EAAE,MAAM;QACf,MAAM,EAAE;YACN,UAAU,EAAE,IAAI,CAAC,MAAM;YACvB,aAAa,EAAE,SAAS,CAAC,MAAM;YAC/B,aAAa,EAAE,QAAQ,CAAC,MAAM;SAC/B;QACD,gBAAgB,EAAE,eAAe;QACjC,WAAW,EAAE,UAAU;QACvB,KAAK;QACL,uBAAuB,EAAE,oBAAoB;QAC7C,KAAK,EAAE;YACL,YAAY,EAAE,KAAK,CAAC,WAAW;YAC/B,aAAa,EAAE,KAAK,CAAC,YAAY;YACjC,MAAM,EAAE,KAAK,CAAC,MAAM;SACrB;KACF,CAAC;IAEF,MAAM,iBAAiB,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9C,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,iBAAiB;IACjB,cAAc;IACd,mBAAmB;IACnB,uBAAuB;IACvB,kBAAkB;IAClB,YAAY;IACZ,OAAO;IACP,YAAY;IACZ,sBAAsB;IACtB,sBAAsB;IACtB,gBAAgB;IAChB,cAAc;IACd,kBAAkB;IAClB,wBAAwB;IACxB,WAAW;IACX,mBAAmB;IACnB,oBAAoB;IACpB,gBAAgB;CACjB,CAAC","sourcesContent":["import { existsSync } from 'node:fs';\nimport path from 'node:path';\nimport { writeJsonArtifact, writeJsonLinesArtifact } from './artifacts.js';\nimport { CliError } from './errors.js';\nimport {\n coerceText,\n deepGet,\n isRecord,\n loadRowsFromFile,\n type JsonRecord,\n} from './flow-governance.js';\nimport type { FetchLike, ResponseLike } from './http.js';\nimport {\n createSupabaseDataClient,\n requireSupabaseRestRuntime,\n runSupabaseArrayQuery,\n runSupabaseMutation,\n} from './supabase-client.js';\nimport { createSupabaseDataRuntime } from './supabase-session.js';\n\nconst DEFAULT_TIMEOUT_MS = 10_000;\nconst DEFAULT_MAX_WORKERS = 4;\nconst LEGACY_OUTPUT_PREFIX = 'flows_tidas_sdk_plus_classification';\n\ntype FlowPublishMode = 'dry_run' | 'commit';\ntype FlowPublishOperation =\n | 'would_insert'\n | 'would_update_existing'\n | 'insert'\n | 'update_existing'\n | 'update_after_insert_error';\n\ntype FlowPublishFailureReason = {\n validator: 'remote_rest';\n stage: string;\n path: string;\n message: string;\n code: string;\n visible_user_id?: string;\n visible_state_code?: string;\n};\n\ntype VisibleFlowRow = {\n id: string;\n version: string;\n user_id: string;\n state_code: number | null;\n};\n\ntype SupabaseDataClient = ReturnType<typeof createSupabaseDataClient>['client'];\n\ntype FlowPublishFailureRow = {\n id: unknown;\n user_id: unknown;\n json_ordered: JsonRecord;\n reason: FlowPublishFailureReason[];\n state_code: unknown;\n};\n\ntype FlowPublishSuccessRow = {\n id: string;\n version: string;\n operation: FlowPublishOperation;\n};\n\ntype FlowPublishFiles = {\n successList: string;\n remoteFailed: string;\n report: string;\n};\n\ntype FlowPublishOutcome =\n | {\n status: 'success';\n success: FlowPublishSuccessRow;\n }\n | {\n status: 'failure';\n failure: FlowPublishFailureRow;\n };\n\nexport type FlowPublishVersionReport = {\n schema_version: 1;\n generated_at_utc: string;\n status:\n | 'prepared_flow_publish_version'\n | 'completed_flow_publish_version'\n | 'completed_flow_publish_version_with_failures';\n mode: FlowPublishMode;\n input_file: string;\n out_dir: string;\n counts: {\n total_rows: number;\n success_count: number;\n failure_count: number;\n };\n operation_counts: Record<string, number>;\n max_workers: number;\n limit: number | null;\n target_user_id_override: string | null;\n files: {\n success_list: string;\n remote_failed: string;\n report: string;\n };\n};\n\nexport type RunFlowPublishVersionOptions = {\n inputFile: string;\n outDir: string;\n commit?: boolean;\n maxWorkers?: number;\n limit?: number;\n targetUserId?: string | null;\n env?: NodeJS.ProcessEnv;\n fetchImpl?: FetchLike;\n timeoutMs?: number;\n now?: Date;\n};\n\nfunction normalize_token(value: unknown): string | null {\n if (typeof value !== 'string') {\n return null;\n }\n const trimmed = value.trim();\n return trimmed ? trimmed : null;\n}\n\nfunction assert_input_file(inputFile: string): string {\n const resolved = path.resolve(inputFile);\n if (!inputFile) {\n throw new CliError('Missing required --input-file value.', {\n code: 'FLOW_PUBLISH_VERSION_INPUT_REQUIRED',\n exitCode: 2,\n });\n }\n if (!existsSync(resolved)) {\n throw new CliError(`Flow publish-version input file not found: ${resolved}`, {\n code: 'FLOW_PUBLISH_VERSION_INPUT_NOT_FOUND',\n exitCode: 2,\n });\n }\n return resolved;\n}\n\nfunction assert_out_dir(outDir: string): string {\n if (!outDir) {\n throw new CliError('Missing required --out-dir value.', {\n code: 'FLOW_PUBLISH_VERSION_OUT_DIR_REQUIRED',\n exitCode: 2,\n });\n }\n return path.resolve(outDir);\n}\n\nfunction to_positive_integer(\n value: number | undefined,\n label: string,\n code: string,\n defaultValue: number,\n): number {\n if (value === undefined) {\n return defaultValue;\n }\n if (!Number.isInteger(value) || value <= 0) {\n throw new CliError(`Expected ${label} to be a positive integer.`, {\n code,\n exitCode: 2,\n });\n }\n return value;\n}\n\nfunction to_non_negative_integer(\n value: number | undefined,\n label: string,\n code: string,\n): number | null {\n if (value === undefined) {\n return null;\n }\n if (!Number.isInteger(value) || value < 0) {\n throw new CliError(`Expected ${label} to be a non-negative integer.`, {\n code,\n exitCode: 2,\n });\n }\n return value;\n}\n\nfunction build_output_files(outDir: string): FlowPublishFiles {\n return {\n successList: path.join(outDir, `${LEGACY_OUTPUT_PREFIX}_mcp_success_list.json`),\n remoteFailed: path.join(outDir, `${LEGACY_OUTPUT_PREFIX}_remote_validation_failed.jsonl`),\n report: path.join(outDir, `${LEGACY_OUTPUT_PREFIX}_mcp_sync_report.json`),\n };\n}\n\nfunction flow_payload(row: JsonRecord): JsonRecord {\n if (isRecord(row.json_ordered)) {\n return row.json_ordered;\n }\n if (isRecord(row.jsonOrdered)) {\n return row.jsonOrdered;\n }\n if (isRecord(row.json)) {\n return row.json;\n }\n if (isRecord(row.flowDataSet)) {\n return row;\n }\n throw new CliError(\n 'Flow row is missing json_ordered/jsonOrdered/json or a top-level flowDataSet payload.',\n {\n code: 'FLOW_PUBLISH_VERSION_PAYLOAD_REQUIRED',\n exitCode: 2,\n },\n );\n}\n\nfunction flow_id(row: JsonRecord, payload: JsonRecord): string {\n return (\n coerceText(row.id) ||\n coerceText(\n deepGet(payload, ['flowDataSet', 'flowInformation', 'dataSetInformation', 'common:UUID']),\n )\n );\n}\n\nfunction flow_version(payload: JsonRecord): string {\n const version = coerceText(\n deepGet(payload, [\n 'flowDataSet',\n 'administrativeInformation',\n 'publicationAndOwnership',\n 'common:dataSetVersion',\n ]),\n );\n if (!version) {\n throw new CliError(\n 'Flow payload is missing flowDataSet.administrativeInformation.publicationAndOwnership.common:dataSetVersion.',\n {\n code: 'FLOW_PUBLISH_VERSION_MISSING_VERSION',\n exitCode: 2,\n },\n );\n }\n return version;\n}\n\nfunction resolve_target_user_id(\n row: JsonRecord,\n targetUserIdOverride: string | null,\n): string | null {\n return normalize_token(coerceText(row.user_id)) ?? targetUserIdOverride;\n}\n\nfunction build_visible_rows_url(restBaseUrl: string, id: string, version: string): string {\n const url = new URL(`${restBaseUrl.replace(/\\/+$/u, '')}/flows`);\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 build_update_url(restBaseUrl: string, id: string, version: string): string {\n const url = new URL(`${restBaseUrl.replace(/\\/+$/u, '')}/flows`);\n url.searchParams.set('id', `eq.${id}`);\n url.searchParams.set('version', `eq.${version}`);\n return url.toString();\n}\n\nasync function parse_response(response: ResponseLike, url: string): Promise<unknown> {\n const rawText = await response.text();\n const contentType = response.headers.get('content-type') ?? '';\n\n if (!response.ok) {\n throw new CliError(`HTTP ${response.status} returned from ${url}`, {\n code: 'REMOTE_REQUEST_FAILED',\n exitCode: 1,\n details: rawText,\n });\n }\n\n if (!rawText) {\n return null;\n }\n\n if (contentType.includes('application/json')) {\n try {\n return JSON.parse(rawText);\n } catch (error) {\n throw new CliError(`Remote response was not valid JSON for ${url}`, {\n code: 'REMOTE_INVALID_JSON',\n exitCode: 1,\n details: String(error),\n });\n }\n }\n\n return rawText;\n}\n\nfunction parse_visible_rows(payload: unknown, url: string): VisibleFlowRow[] {\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: coerceText(item.id),\n version: coerceText(item.version),\n user_id: coerceText(item.user_id),\n state_code: typeof item.state_code === 'number' ? item.state_code : null,\n };\n });\n}\n\nasync function visible_exact_rows(options: {\n client: SupabaseDataClient;\n restBaseUrl: string;\n id: string;\n version: string;\n}): Promise<VisibleFlowRow[]> {\n const url = build_visible_rows_url(options.restBaseUrl, options.id, options.version);\n const payload = await runSupabaseArrayQuery(\n options.client\n .from('flows')\n .select('id,version,user_id,state_code')\n .eq('id', options.id)\n .eq('version', options.version),\n url,\n );\n return parse_visible_rows(payload, url);\n}\n\nfunction own_visible_row(\n rows: VisibleFlowRow[],\n targetUserId: string | null,\n): VisibleFlowRow | null {\n if (!targetUserId) {\n return null;\n }\n return rows.find((row) => row.user_id === targetUserId) ?? null;\n}\n\nfunction visible_conflict_reasons(\n stage: string,\n visibleRows: VisibleFlowRow[],\n targetUserId: string | null,\n): FlowPublishFailureReason[] {\n if (visibleRows.length === 0) {\n return [];\n }\n\n if (!targetUserId) {\n return [\n {\n validator: 'remote_rest',\n stage,\n path: '',\n message:\n 'Exact UUID/version is already visible, but no target user id was available to determine whether the row is writable.',\n code: 'target_user_id_required',\n },\n ];\n }\n\n return visibleRows.map((row) => ({\n validator: 'remote_rest',\n stage,\n path: '',\n message: 'Exact UUID/version is already visible but not writable under the target user.',\n code: 'exact_version_visible_not_owned',\n visible_user_id: row.user_id,\n visible_state_code: row.state_code === null ? '' : String(row.state_code),\n }));\n}\n\nfunction failure_row(\n sourceRow: JsonRecord,\n reasons: FlowPublishFailureReason[],\n): FlowPublishFailureRow {\n let payload: JsonRecord;\n try {\n payload = flow_payload(sourceRow);\n } catch {\n payload = {};\n }\n return {\n id: sourceRow.id,\n user_id: sourceRow.user_id,\n json_ordered: payload,\n reason: reasons,\n state_code: sourceRow.state_code,\n };\n}\n\nfunction build_error_reasons(stage: string, error: unknown): FlowPublishFailureReason[] {\n if (error instanceof CliError) {\n const detailText = typeof error.details === 'string' ? error.details.trim() : error.message;\n return [\n {\n validator: 'remote_rest',\n stage,\n path: '',\n message: detailText || error.message,\n code: error.code,\n },\n ];\n }\n\n if (error instanceof Error) {\n return [\n {\n validator: 'remote_rest',\n stage,\n path: '',\n message: error.message,\n code: error.name || 'Error',\n },\n ];\n }\n\n return [\n {\n validator: 'remote_rest',\n stage,\n path: '',\n message: String(error),\n code: 'UnknownError',\n },\n ];\n}\n\nasync function insert_flow_version(options: {\n client: SupabaseDataClient;\n restBaseUrl: string;\n rowId: string;\n payload: JsonRecord;\n}): Promise<void> {\n const url = `${options.restBaseUrl.replace(/\\/+$/u, '')}/flows`;\n await runSupabaseMutation(\n options.client.from('flows').insert({\n id: options.rowId,\n json_ordered: options.payload,\n }),\n url,\n );\n}\n\nasync function update_flow_version(options: {\n client: SupabaseDataClient;\n restBaseUrl: string;\n rowId: string;\n version: string;\n payload: JsonRecord;\n}): Promise<void> {\n const url = build_update_url(options.restBaseUrl, options.rowId, options.version);\n await runSupabaseMutation(\n options.client\n .from('flows')\n .update({\n json_ordered: options.payload,\n })\n .eq('id', options.rowId)\n .eq('version', options.version),\n url,\n );\n}\n\nasync function sync_one_row(options: {\n row: JsonRecord;\n mode: FlowPublishMode;\n client: SupabaseDataClient;\n restBaseUrl: string;\n targetUserIdOverride: string | null;\n}): Promise<FlowPublishOutcome> {\n try {\n const payload = flow_payload(options.row);\n const rowId = flow_id(options.row, payload);\n if (!rowId) {\n throw new CliError('Flow row is missing a resolvable id/common:UUID value.', {\n code: 'FLOW_PUBLISH_VERSION_ID_REQUIRED',\n exitCode: 2,\n });\n }\n const version = flow_version(payload);\n const targetUserId = resolve_target_user_id(options.row, options.targetUserIdOverride);\n const visibleBefore = await visible_exact_rows({\n client: options.client,\n restBaseUrl: options.restBaseUrl,\n id: rowId,\n version,\n });\n const ownBefore = own_visible_row(visibleBefore, targetUserId);\n\n if (options.mode === 'dry_run') {\n if (ownBefore) {\n return {\n status: 'success',\n success: {\n id: rowId,\n version,\n operation: 'would_update_existing',\n },\n };\n }\n\n if (visibleBefore.length > 0) {\n return {\n status: 'failure',\n failure: failure_row(\n options.row,\n visible_conflict_reasons('dry_run_preflight', visibleBefore, targetUserId),\n ),\n };\n }\n\n return {\n status: 'success',\n success: {\n id: rowId,\n version,\n operation: 'would_insert',\n },\n };\n }\n\n if (ownBefore) {\n await update_flow_version({\n client: options.client,\n restBaseUrl: options.restBaseUrl,\n rowId,\n version,\n payload,\n });\n return {\n status: 'success',\n success: {\n id: rowId,\n version,\n operation: 'update_existing',\n },\n };\n }\n\n if (visibleBefore.length > 0) {\n return {\n status: 'failure',\n failure: failure_row(\n options.row,\n visible_conflict_reasons('preflight', visibleBefore, targetUserId),\n ),\n };\n }\n\n try {\n await insert_flow_version({\n client: options.client,\n restBaseUrl: options.restBaseUrl,\n rowId,\n payload,\n });\n return {\n status: 'success',\n success: {\n id: rowId,\n version,\n operation: 'insert',\n },\n };\n } catch (error) {\n const visibleAfter = await visible_exact_rows({\n client: options.client,\n restBaseUrl: options.restBaseUrl,\n id: rowId,\n version,\n });\n const ownAfter = own_visible_row(visibleAfter, targetUserId);\n if (ownAfter) {\n try {\n await update_flow_version({\n client: options.client,\n restBaseUrl: options.restBaseUrl,\n rowId,\n version,\n payload,\n });\n return {\n status: 'success',\n success: {\n id: rowId,\n version,\n operation: 'update_after_insert_error',\n },\n };\n } catch (updateError) {\n return {\n status: 'failure',\n failure: failure_row(options.row, [\n ...build_error_reasons('insert', error),\n ...build_error_reasons('update_after_insert_error', updateError),\n ]),\n };\n }\n }\n\n return {\n status: 'failure',\n failure: failure_row(options.row, [\n ...build_error_reasons('insert', error),\n ...visible_conflict_reasons('post_insert_error_preflight', visibleAfter, targetUserId),\n ]),\n };\n }\n } catch (error) {\n return {\n status: 'failure',\n failure: failure_row(options.row, build_error_reasons('sync_one_unhandled', error)),\n };\n }\n}\n\nasync function map_with_concurrency<T, R>(\n items: T[],\n maxWorkers: number,\n worker: (item: T, index: number) => Promise<R>,\n): Promise<R[]> {\n const results = new Array<R>(items.length);\n const workerCount = Math.min(Math.max(1, maxWorkers), Math.max(items.length, 1));\n let nextIndex = 0;\n\n async function runWorker(): Promise<void> {\n while (true) {\n const currentIndex = nextIndex;\n nextIndex += 1;\n if (currentIndex >= items.length) {\n return;\n }\n results[currentIndex] = await worker(items[currentIndex] as T, currentIndex);\n }\n }\n\n await Promise.all(Array.from({ length: workerCount }, () => runWorker()));\n return results;\n}\n\nfunction status_from_mode(\n mode: FlowPublishMode,\n failureCount: number,\n): FlowPublishVersionReport['status'] {\n if (mode === 'dry_run') {\n return 'prepared_flow_publish_version';\n }\n return failureCount > 0\n ? 'completed_flow_publish_version_with_failures'\n : 'completed_flow_publish_version';\n}\n\nexport async function runFlowPublishVersion(\n options: RunFlowPublishVersionOptions,\n): Promise<FlowPublishVersionReport> {\n const inputFile = assert_input_file(options.inputFile);\n const outDir = assert_out_dir(options.outDir);\n const mode: FlowPublishMode = options.commit ? 'commit' : 'dry_run';\n const maxWorkers = to_positive_integer(\n options.maxWorkers,\n '--max-workers',\n 'FLOW_PUBLISH_VERSION_MAX_WORKERS_INVALID',\n DEFAULT_MAX_WORKERS,\n );\n const limit = to_non_negative_integer(\n options.limit,\n '--limit',\n 'FLOW_PUBLISH_VERSION_LIMIT_INVALID',\n );\n const fetchImpl = options.fetchImpl ?? (fetch as FetchLike);\n const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const now = options.now ?? new Date();\n const runtime = createSupabaseDataRuntime({\n runtime: requireSupabaseRestRuntime(options.env ?? process.env),\n fetchImpl,\n timeoutMs,\n now,\n });\n const { client, restBaseUrl } = createSupabaseDataClient(runtime, fetchImpl, timeoutMs);\n const targetUserIdOverride = normalize_token(options.targetUserId ?? null);\n const files = build_output_files(outDir);\n\n let rows = loadRowsFromFile(inputFile);\n if (limit !== null && limit > 0) {\n rows = rows.slice(0, limit);\n }\n if (rows.length === 0) {\n throw new CliError(`No rows found in ${inputFile}`, {\n code: 'FLOW_PUBLISH_VERSION_EMPTY_INPUT',\n exitCode: 2,\n });\n }\n\n const outcomes = await map_with_concurrency(rows, maxWorkers, async (row) =>\n sync_one_row({\n row,\n mode,\n client,\n restBaseUrl,\n targetUserIdOverride,\n }),\n );\n\n const successes: FlowPublishSuccessRow[] = [];\n const failures: FlowPublishFailureRow[] = [];\n const operationCounts: Record<string, number> = {};\n\n for (const outcome of outcomes) {\n if (outcome.status === 'success') {\n successes.push(outcome.success);\n operationCounts[outcome.success.operation] =\n (operationCounts[outcome.success.operation] ?? 0) + 1;\n } else {\n failures.push(outcome.failure);\n }\n }\n\n await writeJsonArtifact(files.successList, successes);\n await writeJsonLinesArtifact(files.remoteFailed, failures);\n\n const report: FlowPublishVersionReport = {\n schema_version: 1,\n generated_at_utc: (options.now ?? new Date()).toISOString(),\n status: status_from_mode(mode, failures.length),\n mode,\n input_file: inputFile,\n out_dir: outDir,\n counts: {\n total_rows: rows.length,\n success_count: successes.length,\n failure_count: failures.length,\n },\n operation_counts: operationCounts,\n max_workers: maxWorkers,\n limit,\n target_user_id_override: targetUserIdOverride,\n files: {\n success_list: files.successList,\n remote_failed: files.remoteFailed,\n report: files.report,\n },\n };\n\n await writeJsonArtifact(files.report, report);\n return report;\n}\n\nexport const __testInternals = {\n assert_input_file,\n assert_out_dir,\n to_positive_integer,\n to_non_negative_integer,\n build_output_files,\n flow_payload,\n flow_id,\n flow_version,\n resolve_target_user_id,\n build_visible_rows_url,\n build_update_url,\n parse_response,\n parse_visible_rows,\n visible_conflict_reasons,\n failure_row,\n build_error_reasons,\n map_with_concurrency,\n status_from_mode,\n};\n"]}
|