@walkeros/cli 4.2.0 → 4.3.0-next-1781171238534
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/CHANGELOG.md +32 -0
- package/dist/cli.js +193 -64
- package/dist/index.d.ts +86 -7
- package/dist/index.js +207 -69
- package/dist/index.js.map +1 -1
- package/package.json +8 -8
package/dist/index.js
CHANGED
|
@@ -2755,6 +2755,9 @@ ${firstError.text}`
|
|
|
2755
2755
|
` + (location ? ` at ${location.file}:${location.line}:${location.column}` : "")
|
|
2756
2756
|
);
|
|
2757
2757
|
}
|
|
2758
|
+
function buildDataPayload(flowSettings) {
|
|
2759
|
+
return buildSplitConfigObject(flowSettings, detectNamedImports(flowSettings)).dataPayloadObj;
|
|
2760
|
+
}
|
|
2758
2761
|
function buildSplitConfigObject(flowSettings, namedImports) {
|
|
2759
2762
|
const sources = flowSettings.sources || {};
|
|
2760
2763
|
const destinations = flowSettings.destinations || {};
|
|
@@ -2777,7 +2780,7 @@ function buildSplitConfigObject(flowSettings, namedImports) {
|
|
|
2777
2780
|
}
|
|
2778
2781
|
return props;
|
|
2779
2782
|
}
|
|
2780
|
-
function buildSplitStepEntry(section,
|
|
2783
|
+
function buildSplitStepEntry(section, stepId2, step) {
|
|
2781
2784
|
const codeVar = resolveCodeVar(step);
|
|
2782
2785
|
const stepProps = getStepProps(step);
|
|
2783
2786
|
const { codeProps, dataProps } = classifyStepProperties(stepProps);
|
|
@@ -2788,13 +2791,13 @@ function buildSplitConfigObject(flowSettings, namedImports) {
|
|
|
2788
2791
|
codeEntries.push(`${key}: ${processConfigValue(value)}`);
|
|
2789
2792
|
}
|
|
2790
2793
|
for (const key of Object.keys(dataProps)) {
|
|
2791
|
-
codeEntries.push(`${key}: __data.${section}.${
|
|
2794
|
+
codeEntries.push(`${key}: __data.${section}.${stepId2}.${key}`);
|
|
2792
2795
|
}
|
|
2793
2796
|
if (Object.keys(dataProps).length > 0) {
|
|
2794
2797
|
if (!dataPayloadObj[section]) dataPayloadObj[section] = {};
|
|
2795
|
-
dataPayloadObj[section][
|
|
2798
|
+
dataPayloadObj[section][stepId2] = dataProps;
|
|
2796
2799
|
}
|
|
2797
|
-
return ` ${
|
|
2800
|
+
return ` ${stepId2}: {
|
|
2798
2801
|
${codeEntries.join(",\n ")}
|
|
2799
2802
|
}`;
|
|
2800
2803
|
}
|
|
@@ -2904,7 +2907,7 @@ ${destinationsEntries.join(",\n")}
|
|
|
2904
2907
|
stores${collectorStr}
|
|
2905
2908
|
}`;
|
|
2906
2909
|
const dataPayload = JSON.stringify(dataPayloadObj, null, 2);
|
|
2907
|
-
return { storesDeclaration, codeConfigObject, dataPayload };
|
|
2910
|
+
return { storesDeclaration, codeConfigObject, dataPayloadObj, dataPayload };
|
|
2908
2911
|
}
|
|
2909
2912
|
function generateSplitWireConfigModule(storesDeclaration, codeConfigObject, userCode) {
|
|
2910
2913
|
const codeSection = userCode ? `
|
|
@@ -3848,7 +3851,8 @@ import {
|
|
|
3848
3851
|
createIngest,
|
|
3849
3852
|
getPlatform as getPlatform3,
|
|
3850
3853
|
getNextSteps,
|
|
3851
|
-
buildCacheContext
|
|
3854
|
+
buildCacheContext,
|
|
3855
|
+
stepId
|
|
3852
3856
|
} from "@walkeros/core";
|
|
3853
3857
|
import {
|
|
3854
3858
|
enrichEvent,
|
|
@@ -4354,7 +4358,7 @@ function toError(error) {
|
|
|
4354
4358
|
return error instanceof Error ? error : new Error(getErrorMessage(error));
|
|
4355
4359
|
}
|
|
4356
4360
|
function buildSimulationResult(args) {
|
|
4357
|
-
const { step, name, startTime, captured, usage, error } = args;
|
|
4361
|
+
const { step, name, startTime, captured, usage, mappingKey, error } = args;
|
|
4358
4362
|
const events = (captured ?? []).filter(hasEvent).map((entry) => entry.event);
|
|
4359
4363
|
const calls = usage ? Object.values(usage).flat().map((call) => ({ fn: call.fn, args: call.args, ts: call.ts })) : [];
|
|
4360
4364
|
return {
|
|
@@ -4363,6 +4367,7 @@ function buildSimulationResult(args) {
|
|
|
4363
4367
|
events,
|
|
4364
4368
|
calls,
|
|
4365
4369
|
duration: Date.now() - startTime,
|
|
4370
|
+
...mappingKey !== void 0 ? { mappingKey } : {},
|
|
4366
4371
|
...error !== void 0 ? { error: toError(error) } : {}
|
|
4367
4372
|
};
|
|
4368
4373
|
}
|
|
@@ -4956,7 +4961,9 @@ async function simulateSource(configOrPath, input, options) {
|
|
|
4956
4961
|
`Source package "${sourceConfig.package}" has no createTrigger in /dev export`
|
|
4957
4962
|
);
|
|
4958
4963
|
}
|
|
4959
|
-
const flowConfig = module.wireConfig(
|
|
4964
|
+
const flowConfig = module.wireConfig(
|
|
4965
|
+
options.data ?? module.__configData ?? void 0
|
|
4966
|
+
);
|
|
4960
4967
|
applyOverrides(flowConfig, prepared.overrides);
|
|
4961
4968
|
const captured = [];
|
|
4962
4969
|
flowConfig.hooks = {
|
|
@@ -5061,7 +5068,9 @@ async function simulateTransformer(configOrPath, event, options) {
|
|
|
5061
5068
|
networkCalls
|
|
5062
5069
|
},
|
|
5063
5070
|
async (module) => {
|
|
5064
|
-
const flowConfig = module.wireConfig(
|
|
5071
|
+
const flowConfig = module.wireConfig(
|
|
5072
|
+
options.data ?? module.__configData ?? void 0
|
|
5073
|
+
);
|
|
5065
5074
|
applyOverrides(flowConfig, prepared.overrides);
|
|
5066
5075
|
if (flowConfig.sources) flowConfig.sources = {};
|
|
5067
5076
|
if (flowConfig.destinations) flowConfig.destinations = {};
|
|
@@ -5227,7 +5236,9 @@ async function simulateCollector(configOrPath, event, options) {
|
|
|
5227
5236
|
networkCalls
|
|
5228
5237
|
},
|
|
5229
5238
|
async (module) => {
|
|
5230
|
-
const flowConfig = module.wireConfig(
|
|
5239
|
+
const flowConfig = module.wireConfig(
|
|
5240
|
+
options.data ?? module.__configData ?? void 0
|
|
5241
|
+
);
|
|
5231
5242
|
applyOverrides(flowConfig, prepared.overrides);
|
|
5232
5243
|
if (flowConfig.sources) flowConfig.sources = {};
|
|
5233
5244
|
if (flowConfig.destinations) flowConfig.destinations = {};
|
|
@@ -5330,7 +5341,9 @@ async function simulateDestination(configOrPath, event, options) {
|
|
|
5330
5341
|
networkCalls
|
|
5331
5342
|
},
|
|
5332
5343
|
async (module) => {
|
|
5333
|
-
const flowConfig = module.wireConfig(
|
|
5344
|
+
const flowConfig = module.wireConfig(
|
|
5345
|
+
options.data ?? module.__configData ?? void 0
|
|
5346
|
+
);
|
|
5334
5347
|
applyOverrides(flowConfig, prepared.overrides);
|
|
5335
5348
|
const destPkg = (prepared.flowSettings.destinations ?? {})[options.destinationId];
|
|
5336
5349
|
let trackedCalls = [];
|
|
@@ -5366,6 +5379,16 @@ async function simulateDestination(configOrPath, event, options) {
|
|
|
5366
5379
|
);
|
|
5367
5380
|
}
|
|
5368
5381
|
logger.info(`Simulating destination: ${options.destinationId}`);
|
|
5382
|
+
let mappingKey;
|
|
5383
|
+
const targetStepId = stepId("destination", options.destinationId);
|
|
5384
|
+
const captureMappingKey = (state) => {
|
|
5385
|
+
if (state.stepId === targetStepId && state.mappingKey) {
|
|
5386
|
+
mappingKey = state.mappingKey;
|
|
5387
|
+
}
|
|
5388
|
+
};
|
|
5389
|
+
if (collector.observers instanceof Set) {
|
|
5390
|
+
collector.observers.add(captureMappingKey);
|
|
5391
|
+
}
|
|
5369
5392
|
await collector.push(event, {
|
|
5370
5393
|
include: [options.destinationId]
|
|
5371
5394
|
});
|
|
@@ -5374,7 +5397,8 @@ async function simulateDestination(configOrPath, event, options) {
|
|
|
5374
5397
|
step: "destination",
|
|
5375
5398
|
name: options.destinationId,
|
|
5376
5399
|
startTime,
|
|
5377
|
-
usage: trackedCalls.length ? { [options.destinationId]: trackedCalls } : void 0
|
|
5400
|
+
usage: trackedCalls.length ? { [options.destinationId]: trackedCalls } : void 0,
|
|
5401
|
+
mappingKey
|
|
5378
5402
|
});
|
|
5379
5403
|
},
|
|
5380
5404
|
(error) => buildSimulationResult({
|
|
@@ -6129,13 +6153,21 @@ init_cache();
|
|
|
6129
6153
|
async function runPipeline(options) {
|
|
6130
6154
|
const { bundlePath, port, logger, loggerConfig, api } = options;
|
|
6131
6155
|
let configVersion;
|
|
6156
|
+
const configFrozen = readConfigFrozen();
|
|
6132
6157
|
if (api) {
|
|
6133
6158
|
await injectSecrets(api, logger);
|
|
6134
6159
|
}
|
|
6135
6160
|
logger.info(`walkeros/flow v${VERSION}`);
|
|
6136
6161
|
logger.info(`Instance: ${getInstanceId()}`);
|
|
6162
|
+
if (configFrozen) {
|
|
6163
|
+
logger.info("Config frozen: hot-swap and heartbeat disabled");
|
|
6164
|
+
}
|
|
6137
6165
|
const healthServer = await createHealthServer(port, logger);
|
|
6138
|
-
const
|
|
6166
|
+
const observeLevel = readObserveLevel(logger);
|
|
6167
|
+
const telemetryObservers = buildTelemetryObservers(
|
|
6168
|
+
api?.flowId ?? "flow",
|
|
6169
|
+
observeLevel
|
|
6170
|
+
);
|
|
6139
6171
|
const runtimeConfig = { port };
|
|
6140
6172
|
let handle;
|
|
6141
6173
|
try {
|
|
@@ -6164,20 +6196,24 @@ async function runPipeline(options) {
|
|
|
6164
6196
|
const ingestToken = process.env.WALKEROS_INGEST_TOKEN;
|
|
6165
6197
|
const deploymentId = process.env.WALKEROS_DEPLOYMENT_ID;
|
|
6166
6198
|
if (observerBase && ingestToken && deploymentId) {
|
|
6167
|
-
|
|
6168
|
-
|
|
6169
|
-
|
|
6170
|
-
|
|
6171
|
-
|
|
6172
|
-
|
|
6173
|
-
|
|
6174
|
-
|
|
6175
|
-
|
|
6176
|
-
|
|
6199
|
+
if (observeLevel === "trace") {
|
|
6200
|
+
logger.info("Trace poller: skipped (observe level is trace)");
|
|
6201
|
+
} else {
|
|
6202
|
+
tracePoller = createTracePoller(
|
|
6203
|
+
{
|
|
6204
|
+
url: `${observerBase}/trace/${deploymentId}`,
|
|
6205
|
+
token: ingestToken,
|
|
6206
|
+
intervalMs: 15e3
|
|
6207
|
+
},
|
|
6208
|
+
logger
|
|
6209
|
+
);
|
|
6210
|
+
tracePoller.start();
|
|
6211
|
+
logger.info("Trace poller: active (every 15s)");
|
|
6212
|
+
}
|
|
6177
6213
|
}
|
|
6178
6214
|
let currentBundleCleanup;
|
|
6179
6215
|
let currentConfigPath;
|
|
6180
|
-
if (api) {
|
|
6216
|
+
if (api && !configFrozen) {
|
|
6181
6217
|
heartbeat = createHeartbeat(
|
|
6182
6218
|
{
|
|
6183
6219
|
appUrl: api.appUrl,
|
|
@@ -6294,17 +6330,39 @@ async function runPipeline(options) {
|
|
|
6294
6330
|
await new Promise(() => {
|
|
6295
6331
|
});
|
|
6296
6332
|
}
|
|
6297
|
-
|
|
6333
|
+
var OBSERVE_LEVELS = [
|
|
6334
|
+
"off",
|
|
6335
|
+
"standard",
|
|
6336
|
+
"trace"
|
|
6337
|
+
];
|
|
6338
|
+
function readConfigFrozen() {
|
|
6339
|
+
const raw = process.env.WALKEROS_CONFIG_FROZEN;
|
|
6340
|
+
return raw === "1" || raw === "true";
|
|
6341
|
+
}
|
|
6342
|
+
function readObserveLevel(logger) {
|
|
6343
|
+
const raw = process.env.WALKEROS_OBSERVE_LEVEL;
|
|
6344
|
+
if (raw === void 0 || raw === "") return void 0;
|
|
6345
|
+
const level = OBSERVE_LEVELS.find((candidate) => candidate === raw);
|
|
6346
|
+
if (!level) {
|
|
6347
|
+
logger.warn(
|
|
6348
|
+
`Ignoring invalid WALKEROS_OBSERVE_LEVEL "${raw}" (expected off, standard, or trace)`
|
|
6349
|
+
);
|
|
6350
|
+
return void 0;
|
|
6351
|
+
}
|
|
6352
|
+
return level;
|
|
6353
|
+
}
|
|
6354
|
+
function buildTelemetryObservers(flowId, observeLevel) {
|
|
6298
6355
|
const base = process.env.WALKEROS_OBSERVER_URL;
|
|
6299
6356
|
const token = process.env.WALKEROS_INGEST_TOKEN;
|
|
6300
6357
|
const deploymentId = process.env.WALKEROS_DEPLOYMENT_ID;
|
|
6301
6358
|
if (!base || !token || !deploymentId) return void 0;
|
|
6302
6359
|
const url = `${base}/ingest/${deploymentId}`;
|
|
6303
6360
|
const emit = createBatchedPoster({ url, token });
|
|
6361
|
+
const observe = observeLevel !== void 0 ? { level: observeLevel } : void 0;
|
|
6304
6362
|
return [
|
|
6305
6363
|
createTelemetryObserver(
|
|
6306
6364
|
emit,
|
|
6307
|
-
() => resolveTelemetryOptions({ flowId, traceUntil: getTraceUntil() })
|
|
6365
|
+
() => resolveTelemetryOptions({ flowId, observe, traceUntil: getTraceUntil() })
|
|
6308
6366
|
)
|
|
6309
6367
|
];
|
|
6310
6368
|
}
|
|
@@ -7235,7 +7293,7 @@ function validateMapping(input) {
|
|
|
7235
7293
|
// src/commands/validate/validators/entry.ts
|
|
7236
7294
|
import Ajv from "ajv";
|
|
7237
7295
|
import { fetchPackageSchema } from "@walkeros/core";
|
|
7238
|
-
var CLIENT_HEADER = "walkeros-cli/4.
|
|
7296
|
+
var CLIENT_HEADER = "walkeros-cli/4.3.0-next-1781171238534";
|
|
7239
7297
|
var SECTIONS = ["destinations", "sources", "transformers"];
|
|
7240
7298
|
function resolveEntry(path20, flowConfig) {
|
|
7241
7299
|
const flows = flowConfig.flows;
|
|
@@ -7932,9 +7990,13 @@ function createApiClient() {
|
|
|
7932
7990
|
}
|
|
7933
7991
|
|
|
7934
7992
|
// src/core/api-error.ts
|
|
7993
|
+
var EXIT_RETRYABLE = 75;
|
|
7935
7994
|
var ApiError = class extends Error {
|
|
7936
7995
|
code;
|
|
7937
7996
|
details;
|
|
7997
|
+
status;
|
|
7998
|
+
retryable;
|
|
7999
|
+
retryAfterSeconds;
|
|
7938
8000
|
// Populated only for CLIENT_OUTDATED responses (HTTP 426).
|
|
7939
8001
|
minVersion;
|
|
7940
8002
|
clientVersion;
|
|
@@ -7946,6 +8008,9 @@ var ApiError = class extends Error {
|
|
|
7946
8008
|
this.name = "ApiError";
|
|
7947
8009
|
this.code = options?.code;
|
|
7948
8010
|
this.details = options?.details;
|
|
8011
|
+
this.status = options?.status;
|
|
8012
|
+
this.retryable = options?.retryable;
|
|
8013
|
+
this.retryAfterSeconds = options?.retryAfterSeconds;
|
|
7949
8014
|
this.minVersion = options?.minVersion;
|
|
7950
8015
|
this.clientVersion = options?.clientVersion;
|
|
7951
8016
|
this.client = options?.client;
|
|
@@ -7953,25 +8018,62 @@ var ApiError = class extends Error {
|
|
|
7953
8018
|
this.docs = options?.docs;
|
|
7954
8019
|
}
|
|
7955
8020
|
};
|
|
7956
|
-
function
|
|
7957
|
-
if (error
|
|
7958
|
-
|
|
7959
|
-
|
|
7960
|
-
|
|
7961
|
-
|
|
7962
|
-
|
|
7963
|
-
|
|
7964
|
-
|
|
7965
|
-
|
|
7966
|
-
|
|
7967
|
-
|
|
7968
|
-
|
|
7969
|
-
|
|
7970
|
-
|
|
8021
|
+
function extractApiErrorOptions(error, fallbackMessage) {
|
|
8022
|
+
if (!error || typeof error !== "object" || !("error" in error) || typeof error.error !== "object") {
|
|
8023
|
+
return null;
|
|
8024
|
+
}
|
|
8025
|
+
const inner = error.error;
|
|
8026
|
+
const message = inner.message || fallbackMessage;
|
|
8027
|
+
const code = inner.code;
|
|
8028
|
+
const details = inner.details?.errors;
|
|
8029
|
+
const options = { code, details };
|
|
8030
|
+
if (code === "CLIENT_OUTDATED") {
|
|
8031
|
+
options.minVersion = inner.minVersion;
|
|
8032
|
+
options.clientVersion = inner.clientVersion;
|
|
8033
|
+
options.client = inner.client;
|
|
8034
|
+
options.upgrade = inner.upgrade;
|
|
8035
|
+
options.docs = inner.docs;
|
|
7971
8036
|
}
|
|
8037
|
+
return { message, options };
|
|
8038
|
+
}
|
|
8039
|
+
function throwApiError(error, fallbackMessage) {
|
|
8040
|
+
const extracted = extractApiErrorOptions(error, fallbackMessage);
|
|
8041
|
+
if (extracted) throw new ApiError(extracted.message, extracted.options);
|
|
7972
8042
|
throw new ApiError(fallbackMessage);
|
|
7973
8043
|
}
|
|
8044
|
+
function parseRetryAfter(value) {
|
|
8045
|
+
if (!value) return void 0;
|
|
8046
|
+
const trimmed = value.trim();
|
|
8047
|
+
if (/^\d+$/.test(trimmed)) return parseInt(trimmed, 10);
|
|
8048
|
+
const when = Date.parse(trimmed);
|
|
8049
|
+
if (Number.isNaN(when)) return void 0;
|
|
8050
|
+
return Math.max(0, Math.round((when - Date.now()) / 1e3));
|
|
8051
|
+
}
|
|
8052
|
+
function throwApiResponseError(response, body, fallbackMessage) {
|
|
8053
|
+
const status = response.status;
|
|
8054
|
+
const retryAfterSeconds = parseRetryAfter(
|
|
8055
|
+
response.headers.get("retry-after")
|
|
8056
|
+
);
|
|
8057
|
+
const retryable = status === 429 || status === 503 && retryAfterSeconds !== void 0;
|
|
8058
|
+
const extracted = extractApiErrorOptions(body, fallbackMessage);
|
|
8059
|
+
const message = extracted?.message ?? fallbackMessage;
|
|
8060
|
+
const options = {
|
|
8061
|
+
...extracted?.options ?? {},
|
|
8062
|
+
status,
|
|
8063
|
+
retryable,
|
|
8064
|
+
retryAfterSeconds
|
|
8065
|
+
};
|
|
8066
|
+
throw new ApiError(message, options);
|
|
8067
|
+
}
|
|
8068
|
+
function machineReadableErrorLine(err) {
|
|
8069
|
+
const code = err instanceof ApiError ? err.code ?? "UNKNOWN" : "UNKNOWN";
|
|
8070
|
+
const retryable = err instanceof ApiError ? err.retryable === true : false;
|
|
8071
|
+
const retryAfter = err instanceof ApiError && err.retryAfterSeconds !== void 0 ? ` retryAfter=${err.retryAfterSeconds}` : "";
|
|
8072
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
8073
|
+
return `error: code=${code} retryable=${retryable}${retryAfter} message=${message}`;
|
|
8074
|
+
}
|
|
7974
8075
|
function handleCliError(err) {
|
|
8076
|
+
console.error(machineReadableErrorLine(err));
|
|
7975
8077
|
if (err instanceof ApiError && err.code === "CLIENT_OUTDATED") {
|
|
7976
8078
|
console.error(`
|
|
7977
8079
|
${err.message}
|
|
@@ -7981,8 +8083,12 @@ ${err.message}
|
|
|
7981
8083
|
`);
|
|
7982
8084
|
process.exit(2);
|
|
7983
8085
|
}
|
|
7984
|
-
|
|
7985
|
-
|
|
8086
|
+
if (err instanceof ApiError && err.retryable) {
|
|
8087
|
+
const hint = err.retryAfterSeconds !== void 0 ? ` Retry after ${err.retryAfterSeconds}s.` : " This is temporary, retry shortly.";
|
|
8088
|
+
console.error(`${err.message}${hint}`);
|
|
8089
|
+
process.exit(EXIT_RETRYABLE);
|
|
8090
|
+
}
|
|
8091
|
+
console.error(err instanceof Error ? err.message : String(err));
|
|
7986
8092
|
process.exit(1);
|
|
7987
8093
|
}
|
|
7988
8094
|
|
|
@@ -8278,6 +8384,7 @@ async function readFlowStdin() {
|
|
|
8278
8384
|
}
|
|
8279
8385
|
|
|
8280
8386
|
// src/commands/deploy/index.ts
|
|
8387
|
+
import { randomUUID } from "crypto";
|
|
8281
8388
|
init_auth();
|
|
8282
8389
|
init_http();
|
|
8283
8390
|
init_sse();
|
|
@@ -8308,8 +8415,9 @@ async function getAvailableFlowNames(options) {
|
|
|
8308
8415
|
const settings = flow.settings;
|
|
8309
8416
|
return settings?.map((c) => c.name) ?? [];
|
|
8310
8417
|
}
|
|
8418
|
+
var DEFAULT_DEPLOY_WAIT_MS = 12 * 60 * 1e3;
|
|
8311
8419
|
async function streamDeploymentStatus(projectId, deploymentId, options) {
|
|
8312
|
-
const timeoutMs = options.timeout ??
|
|
8420
|
+
const timeoutMs = options.timeout ?? DEFAULT_DEPLOY_WAIT_MS;
|
|
8313
8421
|
const response = await apiFetch(
|
|
8314
8422
|
`/api/projects/${projectId}/deployments/${deploymentId}/stream`,
|
|
8315
8423
|
{
|
|
@@ -8368,7 +8476,10 @@ async function deploy(options) {
|
|
|
8368
8476
|
}
|
|
8369
8477
|
const { data, error } = await client.POST(
|
|
8370
8478
|
"/api/projects/{projectId}/flows/{flowId}/deploy",
|
|
8371
|
-
{
|
|
8479
|
+
{
|
|
8480
|
+
params: { path: { projectId, flowId: options.flowId } },
|
|
8481
|
+
headers: { "Idempotency-Key": randomUUID() }
|
|
8482
|
+
}
|
|
8372
8483
|
);
|
|
8373
8484
|
if (error) {
|
|
8374
8485
|
try {
|
|
@@ -8398,13 +8509,38 @@ Available: ${names.join(", ")}`,
|
|
|
8398
8509
|
}
|
|
8399
8510
|
async function deploySettings(options) {
|
|
8400
8511
|
const { flowId, projectId, settingsId } = options;
|
|
8401
|
-
const
|
|
8512
|
+
const triggerDeploy = () => apiFetch(
|
|
8402
8513
|
`/api/projects/${projectId}/flows/${flowId}/settings/${settingsId}/deploy`,
|
|
8403
|
-
{ method: "POST" }
|
|
8514
|
+
{ method: "POST", headers: { "Idempotency-Key": randomUUID() } }
|
|
8404
8515
|
);
|
|
8516
|
+
let response = await triggerDeploy();
|
|
8517
|
+
if (!response.ok && options.wait) {
|
|
8518
|
+
let retryBody = {};
|
|
8519
|
+
try {
|
|
8520
|
+
retryBody = await response.clone().json();
|
|
8521
|
+
} catch {
|
|
8522
|
+
retryBody = {};
|
|
8523
|
+
}
|
|
8524
|
+
try {
|
|
8525
|
+
throwApiResponseError(
|
|
8526
|
+
response,
|
|
8527
|
+
retryBody,
|
|
8528
|
+
`Deploy failed (${response.status})`
|
|
8529
|
+
);
|
|
8530
|
+
} catch (e) {
|
|
8531
|
+
if (e instanceof ApiError && e.retryable) {
|
|
8532
|
+
const waitSeconds = Math.min(e.retryAfterSeconds ?? 5, 60);
|
|
8533
|
+
options.onStatus?.("rate_limited", `retrying in ${waitSeconds}s`);
|
|
8534
|
+
await new Promise((resolve5) => setTimeout(resolve5, waitSeconds * 1e3));
|
|
8535
|
+
response = await triggerDeploy();
|
|
8536
|
+
} else {
|
|
8537
|
+
throw e;
|
|
8538
|
+
}
|
|
8539
|
+
}
|
|
8540
|
+
}
|
|
8405
8541
|
if (!response.ok) {
|
|
8406
8542
|
const body = await response.json().catch(() => ({}));
|
|
8407
|
-
|
|
8543
|
+
throwApiResponseError(response, body, `Deploy failed (${response.status})`);
|
|
8408
8544
|
}
|
|
8409
8545
|
const data = await response.json();
|
|
8410
8546
|
if (!options.wait) return data;
|
|
@@ -8428,7 +8564,7 @@ async function getDeployment(options) {
|
|
|
8428
8564
|
);
|
|
8429
8565
|
if (!response.ok) {
|
|
8430
8566
|
const body = await response.json().catch(() => ({}));
|
|
8431
|
-
|
|
8567
|
+
throwApiResponseError(response, body, "Failed to get deployment");
|
|
8432
8568
|
}
|
|
8433
8569
|
return response.json();
|
|
8434
8570
|
}
|
|
@@ -8441,16 +8577,20 @@ async function getDeployment(options) {
|
|
|
8441
8577
|
return data;
|
|
8442
8578
|
}
|
|
8443
8579
|
var statusLabels = {
|
|
8444
|
-
|
|
8445
|
-
"
|
|
8446
|
-
"bundling:publishing": "Publishing to web...",
|
|
8447
|
-
deploying: "Deploying container...",
|
|
8580
|
+
"deploying:building": "Building bundle...",
|
|
8581
|
+
"deploying:publishing": "Publishing to web...",
|
|
8448
8582
|
"deploying:provisioning": "Provisioning container...",
|
|
8449
8583
|
"deploying:starting": "Starting container...",
|
|
8584
|
+
deploying: "Deploying...",
|
|
8450
8585
|
active: "Container is live",
|
|
8451
8586
|
published: "Published",
|
|
8587
|
+
stopped: "Stopped",
|
|
8452
8588
|
failed: "Deployment failed"
|
|
8453
8589
|
};
|
|
8590
|
+
function renderStatusLabel(status, substatus) {
|
|
8591
|
+
const key = substatus ? `${status}:${substatus}` : status;
|
|
8592
|
+
return statusLabels[key] || statusLabels[status] || `Status: ${status}`;
|
|
8593
|
+
}
|
|
8454
8594
|
async function deployCommand(flowId, options) {
|
|
8455
8595
|
const log = createCLILogger(options);
|
|
8456
8596
|
const timeoutMs = options.timeout ? parseInt(options.timeout, 10) * 1e3 : void 0;
|
|
@@ -8462,10 +8602,7 @@ async function deployCommand(flowId, options) {
|
|
|
8462
8602
|
wait: options.wait !== false,
|
|
8463
8603
|
timeout: timeoutMs,
|
|
8464
8604
|
onStatus: options.json ? void 0 : (status, substatus) => {
|
|
8465
|
-
|
|
8466
|
-
log.info(
|
|
8467
|
-
statusLabels[key] || statusLabels[status] || `Status: ${status}`
|
|
8468
|
-
);
|
|
8605
|
+
log.info(renderStatusLabel(status, substatus));
|
|
8469
8606
|
}
|
|
8470
8607
|
});
|
|
8471
8608
|
if (options.json) {
|
|
@@ -8480,7 +8617,7 @@ async function deployCommand(flowId, options) {
|
|
|
8480
8617
|
} else if (r.status === "failed") {
|
|
8481
8618
|
log.error(`Failed: ${r.errorMessage || "Unknown error"}`);
|
|
8482
8619
|
process.exit(1);
|
|
8483
|
-
} else if (r.status === "
|
|
8620
|
+
} else if (r.status === "deploying") {
|
|
8484
8621
|
log.info(`Deployment started: ${r.deploymentId} (${r.type})`);
|
|
8485
8622
|
} else {
|
|
8486
8623
|
log.info(`Status: ${r.status}`);
|
|
@@ -8708,20 +8845,16 @@ async function createDeployCommand(config, options) {
|
|
|
8708
8845
|
log.info(`Deployment created: ${result.id}`);
|
|
8709
8846
|
log.info(` Slug: ${result.slug}`);
|
|
8710
8847
|
log.info(` Type: ${result.type}`);
|
|
8711
|
-
if (result.deployToken) {
|
|
8712
|
-
log.info(` Token: ${result.deployToken}`);
|
|
8713
|
-
log.warn(" Save this token \u2014 it will not be shown again.");
|
|
8714
|
-
}
|
|
8715
8848
|
log.info("");
|
|
8716
8849
|
log.info("Run locally:");
|
|
8717
8850
|
log.info(
|
|
8718
8851
|
` walkeros run ${isRemoteFlow ? "flow.json" : config} --deploy ${result.id}`
|
|
8719
8852
|
);
|
|
8720
8853
|
log.info("");
|
|
8721
|
-
log.info("
|
|
8722
|
-
log.info(
|
|
8723
|
-
|
|
8724
|
-
);
|
|
8854
|
+
log.info("Create a deploy token for this flow in the app");
|
|
8855
|
+
log.info("(Settings, Self-hosted deploy token) and set it as");
|
|
8856
|
+
log.info("WALKEROS_DEPLOY_TOKEN, then run with Docker:");
|
|
8857
|
+
log.info(" docker run -e WALKEROS_DEPLOY_TOKEN \\");
|
|
8725
8858
|
log.info(" -e WALKEROS_APP_URL=https://app.walkeros.io \\");
|
|
8726
8859
|
log.info(" walkeros/flow:latest");
|
|
8727
8860
|
} catch (err) {
|
|
@@ -8807,14 +8940,14 @@ init_config_file();
|
|
|
8807
8940
|
|
|
8808
8941
|
// src/telemetry/install-id.ts
|
|
8809
8942
|
init_config_file();
|
|
8810
|
-
import { randomUUID } from "crypto";
|
|
8943
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
8811
8944
|
function getInstallationId() {
|
|
8812
8945
|
return readConfig()?.installationId;
|
|
8813
8946
|
}
|
|
8814
8947
|
function createInstallationId() {
|
|
8815
8948
|
const existing = readConfig()?.installationId;
|
|
8816
8949
|
if (existing) return existing;
|
|
8817
|
-
const id =
|
|
8950
|
+
const id = randomUUID2();
|
|
8818
8951
|
writeTelemetryOnlyConfig({ installationId: id });
|
|
8819
8952
|
return id;
|
|
8820
8953
|
}
|
|
@@ -8875,6 +9008,8 @@ function telemetryDisableCommand() {
|
|
|
8875
9008
|
|
|
8876
9009
|
// src/index.ts
|
|
8877
9010
|
init_bundle();
|
|
9011
|
+
init_bundler();
|
|
9012
|
+
init_config_classifier();
|
|
8878
9013
|
|
|
8879
9014
|
// src/commands/bundle/validate-structure.ts
|
|
8880
9015
|
init_structural_validators();
|
|
@@ -9560,12 +9695,15 @@ export {
|
|
|
9560
9695
|
apiFetch,
|
|
9561
9696
|
bakedContractHash,
|
|
9562
9697
|
bakedContractVersion,
|
|
9698
|
+
buildDataPayload,
|
|
9563
9699
|
bundle,
|
|
9564
9700
|
bundleCommand,
|
|
9565
9701
|
canonicalContractHash,
|
|
9702
|
+
classifyStepProperties,
|
|
9566
9703
|
clientContextHeaders,
|
|
9567
9704
|
compareContract,
|
|
9568
9705
|
compareOutput,
|
|
9706
|
+
containsCodeMarkers,
|
|
9569
9707
|
createApiClient,
|
|
9570
9708
|
createDeployCommand,
|
|
9571
9709
|
createDeployment,
|