@koda-sl/baker-cli 0.359.0 → 0.361.0-dev.0306d9ad9
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 +11 -1
- package/dist/{chunk-AI4HWQVN.js → chunk-K2IKLMCM.js} +4 -4
- package/dist/chunk-K2IKLMCM.js.map +1 -0
- package/dist/{chunk-4QXKWIFC.js → chunk-MZQC4LII.js} +4 -1
- package/dist/chunk-MZQC4LII.js.map +1 -0
- package/dist/{chunk-NA5CPMUA.js → chunk-SR56QQTD.js} +4 -4
- package/dist/chunk-SR56QQTD.js.map +1 -0
- package/dist/{chunk-2IC3CGQO.js → chunk-VVQLRFCI.js} +2 -2
- package/dist/cli.js +83 -36
- package/dist/cli.js.map +1 -1
- package/dist/{client-ODCNYCP4.js → client-3DGBQ2H3.js} +2 -2
- package/dist/engine/index.js +1 -1
- package/dist/{output-2XBCYF7L.js → output-OSSBUGT7.js} +3 -3
- package/dist/{shared-RYAF7Y7H.js → shared-MSI4UMZ3.js} +4 -4
- package/package.json +1 -1
- package/dist/chunk-4QXKWIFC.js.map +0 -1
- package/dist/chunk-AI4HWQVN.js.map +0 -1
- package/dist/chunk-NA5CPMUA.js.map +0 -1
- /package/dist/{chunk-2IC3CGQO.js.map → chunk-VVQLRFCI.js.map} +0 -0
- /package/dist/{client-ODCNYCP4.js.map → client-3DGBQ2H3.js.map} +0 -0
- /package/dist/{output-2XBCYF7L.js.map → output-OSSBUGT7.js.map} +0 -0
- /package/dist/{shared-RYAF7Y7H.js.map → shared-MSI4UMZ3.js.map} +0 -0
|
@@ -85,6 +85,9 @@ function mapHttpError(status) {
|
|
|
85
85
|
if (status === 429) {
|
|
86
86
|
return "RATE_LIMITED";
|
|
87
87
|
}
|
|
88
|
+
if (status === 503) {
|
|
89
|
+
return "UNAVAILABLE";
|
|
90
|
+
}
|
|
88
91
|
return "INTERNAL_ERROR";
|
|
89
92
|
}
|
|
90
93
|
async function handleResponse(response) {
|
|
@@ -205,4 +208,4 @@ export {
|
|
|
205
208
|
apiGet,
|
|
206
209
|
apiPost
|
|
207
210
|
};
|
|
208
|
-
//# sourceMappingURL=chunk-
|
|
211
|
+
//# sourceMappingURL=chunk-MZQC4LII.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/client.ts"],"sourcesContent":["import { debugLogHttp, readBodyForLog } from \"./debugLog.ts\";\nimport { getEnv } from \"./env.ts\";\n\nconst MAX_RATE_LIMIT_RETRIES = 3;\nconst MAX_TOTAL_WAIT_MS = 2 * 60 * 1000;\n\nasync function fetchWithRateLimitRetry(url: string, init: RequestInit): Promise<Response> {\n let totalWaited = 0;\n\n for (let attempt = 0; attempt <= MAX_RATE_LIMIT_RETRIES; attempt++) {\n const response = await fetch(url, init);\n\n if (response.status !== 429 || attempt >= MAX_RATE_LIMIT_RETRIES) {\n return response;\n }\n\n const retryAfterHeader = response.headers.get(\"Retry-After\");\n const waitMs = retryAfterHeader ? Number(retryAfterHeader) * 1000 : 2000 * 2 ** attempt;\n\n if (totalWaited + waitMs > MAX_TOTAL_WAIT_MS) {\n return response;\n }\n\n totalWaited += waitMs;\n await new Promise((resolve) => setTimeout(resolve, waitMs));\n }\n\n return fetch(url, init);\n}\n\nexport type ErrorCode =\n | \"UNAUTHORIZED\"\n | \"FORBIDDEN\"\n | \"NOT_FOUND\"\n | \"CONFLICT\"\n | \"VALIDATION_ERROR\"\n | \"RATE_LIMITED\"\n | \"UNAVAILABLE\"\n | \"INTERNAL_ERROR\"\n | \"NETWORK_ERROR\"\n | \"TIMEOUT\"\n | \"IMAGE_PROCESSING_ERROR\";\n\nexport class ApiError extends Error {\n code: ErrorCode;\n\n constructor(code: ErrorCode, message: string) {\n super(message);\n this.name = \"ApiError\";\n this.code = code;\n }\n}\n\nconst CONVEX_ID_RE = /^[a-zA-Z0-9_]+$/;\n\nfunction hasControlCharacters(value: string): boolean {\n for (let i = 0; i < value.length; i++) {\n const code = value.charCodeAt(i);\n // Allow tab (9), newline (10), carriage return (13)\n if (code < 32 && code !== 9 && code !== 10 && code !== 13) {\n return true;\n }\n }\n return false;\n}\n\nfunction validateStringValue(value: string): void {\n if (hasControlCharacters(value)) {\n throw new ApiError(\"VALIDATION_ERROR\", \"String value contains invalid control characters\");\n }\n}\n\nexport function validateConvexId(id: string): void {\n if (!CONVEX_ID_RE.test(id)) {\n throw new ApiError(\"VALIDATION_ERROR\", `Invalid ID format: \"${id}\". Expected alphanumeric string.`);\n }\n}\n\nfunction sanitizeParams(params: Record<string, string>): Record<string, string> {\n const sanitized: Record<string, string> = {};\n for (const [key, value] of Object.entries(params)) {\n validateStringValue(value);\n sanitized[key] = value;\n }\n return sanitized;\n}\n\n/**\n * Sent on every call so the backend can attribute immediately-applied writes\n * (library images and videos, followed advertisers) to the Session they were\n * made from. Absent outside a chat-attached environment.\n */\nfunction chatHeader(): Record<string, string> {\n const chatId = getEnv().BAKER_CHAT_ID;\n return chatId ? { \"x-baker-chat-id\": chatId } : {};\n}\n\nfunction mapHttpError(status: number): ErrorCode {\n if (status === 401) {\n return \"UNAUTHORIZED\";\n }\n // 403 is never \"not connected\" — every backend `FORBIDDEN` means connected but\n // not allowed (an asset outside the granted scope, a capability the account\n // lacks). Folding it into UNAUTHORIZED sent agents down the reconnect path,\n // which cannot fix a permission gap and wastes the user's time.\n if (status === 403) {\n return \"FORBIDDEN\";\n }\n if (status === 404) {\n return \"NOT_FOUND\";\n }\n if (status === 422 || status === 400) {\n return \"VALIDATION_ERROR\";\n }\n // 409 is a state the caller has to change, never a fault to sit out. It is\n // what the backend returns for \"this workspace has not switched analytics on\n // yet\" and its siblings — folded into INTERNAL_ERROR, that reaches an agent\n // as a transient failure worth retrying, which it never is.\n if (status === 409) {\n return \"CONFLICT\";\n }\n if (status === 429) {\n return \"RATE_LIMITED\";\n }\n // 503 is the backend's `UNAVAILABLE`: a system it depends on did not answer\n // just now, and asking again is the fix. Folded into INTERNAL_ERROR, it reads\n // exactly like a fault of ours, and the agent cannot tell which one waits out.\n if (status === 503) {\n return \"UNAVAILABLE\";\n }\n return \"INTERNAL_ERROR\";\n}\n\nasync function handleResponse<T>(response: Response): Promise<T> {\n const body = await response.text();\n\n if (!response.ok) {\n let message = `HTTP ${response.status}: ${response.statusText}`;\n try {\n const parsed = JSON.parse(body) as { error?: string | { message?: string }; message?: string };\n if (typeof parsed.error === \"string\") {\n message = parsed.error;\n } else if (parsed.error?.message) {\n message = parsed.error.message;\n } else if (parsed.message) {\n message = parsed.message;\n }\n } catch {\n // Use default message\n }\n throw new ApiError(mapHttpError(response.status), message);\n }\n\n try {\n return JSON.parse(body) as T;\n } catch {\n throw new ApiError(\"INTERNAL_ERROR\", \"Failed to parse API response as JSON\");\n }\n}\n\n/**\n * A GET that also hands back the response headers.\n *\n * Some endpoints have to say something *about* the answer that the answer has\n * no room for — `GET /api/testimonials` returns a bare array and sets\n * `X-Baker-Next-Cursor` when rows past this page remain unexamined, so the rows\n * alone cannot tell one page of a library from the whole of it.\n */\nexport async function apiGetWithHeaders<T>(\n path: string,\n params?: Record<string, string>,\n): Promise<{ data: T; headers: Headers }> {\n const env = getEnv();\n const url = new URL(path, env.BAKER_API_URL);\n if (params) {\n const clean = sanitizeParams(params);\n for (const [key, value] of Object.entries(clean)) {\n url.searchParams.set(key, value);\n }\n }\n\n const urlStr = url.toString();\n const startedAt = Date.now();\n let response: Response;\n try {\n response = await fetchWithRateLimitRetry(urlStr, {\n method: \"GET\",\n headers: {\n Authorization: `Bearer ${env.BAKER_API_KEY}`,\n Accept: \"application/json\",\n ...chatHeader(),\n },\n signal: AbortSignal.timeout(60_000),\n });\n } catch (err) {\n debugLogHttp({ source: \"cli\", method: \"GET\", url: urlStr, durationMs: Date.now() - startedAt, error: err });\n if (err instanceof Error && (err.name === \"TimeoutError\" || err.name === \"AbortError\")) {\n throw new ApiError(\"TIMEOUT\", \"Request timed out after 60 seconds\");\n }\n throw new ApiError(\"NETWORK_ERROR\", `Request failed: ${err instanceof Error ? err.message : \"Unknown error\"}`);\n }\n\n debugLogHttp({\n source: \"cli\",\n method: \"GET\",\n url: urlStr,\n status: response.status,\n ok: response.ok,\n responseBody: await readBodyForLog(response),\n durationMs: Date.now() - startedAt,\n });\n return { data: await handleResponse<T>(response), headers: response.headers };\n}\n\nexport async function apiGet<T>(path: string, params?: Record<string, string>): Promise<T> {\n return (await apiGetWithHeaders<T>(path, params)).data;\n}\n\nexport async function apiPost<T>(path: string, body: unknown, opts?: { timeoutMs?: number }): Promise<T> {\n const env = getEnv();\n const timeoutMs = opts?.timeoutMs ?? 60_000;\n const urlStr = new URL(path, env.BAKER_API_URL).toString();\n const startedAt = Date.now();\n let response: Response;\n try {\n response = await fetchWithRateLimitRetry(urlStr, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${env.BAKER_API_KEY}`,\n \"Content-Type\": \"application/json\",\n Accept: \"application/json\",\n ...chatHeader(),\n },\n body: JSON.stringify(body),\n signal: AbortSignal.timeout(timeoutMs),\n });\n } catch (err) {\n debugLogHttp({\n source: \"cli\",\n method: \"POST\",\n url: urlStr,\n requestBody: body,\n durationMs: Date.now() - startedAt,\n error: err,\n });\n if (err instanceof Error && (err.name === \"TimeoutError\" || err.name === \"AbortError\")) {\n throw new ApiError(\"TIMEOUT\", `Request timed out after ${Math.round(timeoutMs / 1000)} seconds`);\n }\n throw new ApiError(\"NETWORK_ERROR\", `Request failed: ${err instanceof Error ? err.message : \"Unknown error\"}`);\n }\n\n debugLogHttp({\n source: \"cli\",\n method: \"POST\",\n url: urlStr,\n requestBody: body,\n status: response.status,\n ok: response.ok,\n responseBody: await readBodyForLog(response),\n durationMs: Date.now() - startedAt,\n });\n return handleResponse<T>(response);\n}\n"],"mappings":"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","names":[]}
|
|
@@ -2,10 +2,10 @@ import {
|
|
|
2
2
|
handleConnectionError,
|
|
3
3
|
needsConnectionFix,
|
|
4
4
|
writeAdsJson
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-VVQLRFCI.js";
|
|
6
6
|
import {
|
|
7
7
|
ApiError
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-MZQC4LII.js";
|
|
9
9
|
import {
|
|
10
10
|
getEnv
|
|
11
11
|
} from "./chunk-2OKSJNLA.js";
|
|
@@ -35,7 +35,7 @@ function handleMetaError(err) {
|
|
|
35
35
|
code: err.code,
|
|
36
36
|
message: err.message,
|
|
37
37
|
fix: err.code === "FORBIDDEN" ? metaForbiddenFix(err.message) : { action: "reject", explanation: err.message },
|
|
38
|
-
retryable: err.code === "RATE_LIMITED" || err.code === "INTERNAL_ERROR"
|
|
38
|
+
retryable: err.code === "RATE_LIMITED" || err.code === "UNAVAILABLE" || err.code === "INTERNAL_ERROR"
|
|
39
39
|
}
|
|
40
40
|
};
|
|
41
41
|
writeAdsJson(envelope);
|
|
@@ -108,4 +108,4 @@ export {
|
|
|
108
108
|
csvOrJson,
|
|
109
109
|
resolveEffectiveStatus
|
|
110
110
|
};
|
|
111
|
-
//# sourceMappingURL=chunk-
|
|
111
|
+
//# sourceMappingURL=chunk-SR56QQTD.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/ads/meta/shared.ts"],"sourcesContent":["import { ApiError } from \"../../../client.ts\";\nimport { getEnv } from \"../../../env.ts\";\nimport { handleConnectionError, needsConnectionFix } from \"../../../error-handler.ts\";\nimport { writeAdsJson } from \"../output.ts\";\nimport type { AdsErrorEnvelope, QueryFix } from \"../types.ts\";\n\nconst DAY_MS = 86_400_000;\n\n/**\n * Meta answers a permission refusal (Graph codes 200/10/294) with a bare\n * \"Permissions error\" that covers two causes needing opposite remedies: a\n * consent grant the connection never got — nothing validates Meta's granted\n * scopes after connect, unlike HubSpot's `requireCapability` — or a role the\n * user lacks on one asset, since a Pixel/Dataset, Page or catalog lives in a\n * Business and is assigned separately from the ad account. Only the blast radius\n * separates them, so hand the agent that test rather than a verdict: guessing\n * \"reconnect\" wastes the user's time on an unassigned asset, and ruling it out\n * strands a connection that really is short a scope.\n */\nexport function metaForbiddenFix(message: string): QueryFix {\n return {\n action: \"reject\",\n explanation: [\n message,\n \"This is a permission refusal, not a dead connection, and Meta returns the same code for two causes with opposite remedies. Tell them apart by how much else works before you answer.\",\n \"If other reads on this account are ALSO refused (campaigns, ad sets, insights), the connection is short a permission it was never granted. Only the user can widen it, by reconnecting Meta from the dashboard.\",\n \"If those reads work and only this object is refused, the asset (pixel/dataset, Page, or catalog) belongs to a Business the connected user holds no role in. Ad-account access does not carry asset access and reconnecting cannot grant it — the client assigns that asset to the connected user or partner in Meta Business settings, under the asset's own section (Data sources → Datasets for a pixel).\",\n \"Either way do not retry the same call, and do not abort the wider job. Continue with what you can read, and state in your answer that this specific check could not run and why — never present the task as verified when this step was skipped.\",\n ].join(\"\\n\\n\"),\n };\n}\n\nexport function handleMetaError(err: unknown): never {\n if (err instanceof ApiError) {\n if (needsConnectionFix(err.code, err.message)) {\n handleConnectionError(\"meta_ads\", err.message);\n }\n const envelope: AdsErrorEnvelope = {\n ok: false,\n error: {\n code: err.code,\n message: err.message,\n fix: err.code === \"FORBIDDEN\" ? metaForbiddenFix(err.message) : { action: \"reject\", explanation: err.message },\n retryable: err.code === \"RATE_LIMITED\" || err.code === \"UNAVAILABLE\" || err.code === \"INTERNAL_ERROR\",\n },\n };\n writeAdsJson(envelope);\n process.exit(1);\n }\n const message = err instanceof Error ? err.message : \"Unexpected error\";\n writeAdsJson({ ok: false, error: { code: \"NETWORK_ERROR\", message } });\n process.exit(1);\n}\n\nconst ACCOUNT_ID_RE = /^(act_)?[0-9]+$/;\n\n/** Pull the default Meta ad account ID from `--account-id` arg or `BAKER_META_AD_ACCOUNT_ID` env. */\nexport function resolveAccountIdArg(args: Record<string, unknown>): string {\n const fromArgs = args[\"account-id\"] as string | undefined;\n const id = fromArgs || getEnv().BAKER_META_AD_ACCOUNT_ID;\n if (!id) {\n writeAdsJson({\n ok: false,\n error: {\n code: \"MISSING_ACCOUNT_ID\",\n message: \"Pass --account-id or set BAKER_META_AD_ACCOUNT_ID. Run `baker ads meta accounts` to find IDs.\",\n },\n });\n process.exit(1);\n }\n if (!ACCOUNT_ID_RE.test(id)) {\n writeAdsJson({\n ok: false,\n error: {\n code: \"INVALID_ACCOUNT_ID\",\n message: `Invalid account ID \"${id}\". Expected numeric ID, optionally prefixed with \"act_\".`,\n },\n });\n process.exit(1);\n }\n return id.startsWith(\"act_\") ? id : `act_${id}`;\n}\n\nexport function getDateRange(args: Record<string, unknown>): { datePreset?: string; since?: string; until?: string } {\n const datePreset = args[\"date-preset\"] as string | undefined;\n const since = args.since as string | undefined;\n const until = args.until as string | undefined;\n if (since && until) return { since, until };\n return { datePreset: datePreset ?? \"last_7d\" };\n}\n\nexport function todayIso(): string {\n return new Date().toISOString().slice(0, 10);\n}\n\nexport function daysAgoIso(days: number): string {\n return new Date(Date.now() - days * DAY_MS).toISOString().slice(0, 10);\n}\n\nexport function csvOrJson(args: Record<string, unknown>): string {\n return (args.output as string | undefined) ?? \"json\";\n}\n\n/**\n * Default to ACTIVE-only on listings — that's almost always what an AI agent or\n * a human glance wants. Pass `--effective-status ACTIVE,PAUSED` to override, or\n * `--all-statuses` to drop the filter entirely.\n */\nexport function resolveEffectiveStatus(args: Record<string, unknown>): string | undefined {\n if (args[\"all-statuses\"]) {\n return undefined;\n }\n const explicit = args[\"effective-status\"] as string | undefined;\n if (explicit) {\n return explicit;\n }\n return \"ACTIVE\";\n}\n"],"mappings":";;;;;;;;;;;;;AAMA,IAAM,SAAS;AAaR,SAAS,iBAAiB,SAA2B;AAC1D,SAAO;AAAA,IACL,QAAQ;AAAA,IACR,aAAa;AAAA,MACX;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,EAAE,KAAK,MAAM;AAAA,EACf;AACF;AAEO,SAAS,gBAAgB,KAAqB;AACnD,MAAI,eAAe,UAAU;AAC3B,QAAI,mBAAmB,IAAI,MAAM,IAAI,OAAO,GAAG;AAC7C,4BAAsB,YAAY,IAAI,OAAO;AAAA,IAC/C;AACA,UAAM,WAA6B;AAAA,MACjC,IAAI;AAAA,MACJ,OAAO;AAAA,QACL,MAAM,IAAI;AAAA,QACV,SAAS,IAAI;AAAA,QACb,KAAK,IAAI,SAAS,cAAc,iBAAiB,IAAI,OAAO,IAAI,EAAE,QAAQ,UAAU,aAAa,IAAI,QAAQ;AAAA,QAC7G,WAAW,IAAI,SAAS,kBAAkB,IAAI,SAAS,iBAAiB,IAAI,SAAS;AAAA,MACvF;AAAA,IACF;AACA,iBAAa,QAAQ;AACrB,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,QAAM,UAAU,eAAe,QAAQ,IAAI,UAAU;AACrD,eAAa,EAAE,IAAI,OAAO,OAAO,EAAE,MAAM,iBAAiB,QAAQ,EAAE,CAAC;AACrE,UAAQ,KAAK,CAAC;AAChB;AAEA,IAAM,gBAAgB;AAGf,SAAS,oBAAoB,MAAuC;AACzE,QAAM,WAAW,KAAK,YAAY;AAClC,QAAM,KAAK,YAAY,OAAO,EAAE;AAChC,MAAI,CAAC,IAAI;AACP,iBAAa;AAAA,MACX,IAAI;AAAA,MACJ,OAAO;AAAA,QACL,MAAM;AAAA,QACN,SAAS;AAAA,MACX;AAAA,IACF,CAAC;AACD,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,MAAI,CAAC,cAAc,KAAK,EAAE,GAAG;AAC3B,iBAAa;AAAA,MACX,IAAI;AAAA,MACJ,OAAO;AAAA,QACL,MAAM;AAAA,QACN,SAAS,uBAAuB,EAAE;AAAA,MACpC;AAAA,IACF,CAAC;AACD,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,SAAO,GAAG,WAAW,MAAM,IAAI,KAAK,OAAO,EAAE;AAC/C;AAEO,SAAS,aAAa,MAAwF;AACnH,QAAM,aAAa,KAAK,aAAa;AACrC,QAAM,QAAQ,KAAK;AACnB,QAAM,QAAQ,KAAK;AACnB,MAAI,SAAS,MAAO,QAAO,EAAE,OAAO,MAAM;AAC1C,SAAO,EAAE,YAAY,cAAc,UAAU;AAC/C;AAEO,SAAS,WAAmB;AACjC,UAAO,oBAAI,KAAK,GAAE,YAAY,EAAE,MAAM,GAAG,EAAE;AAC7C;AAEO,SAAS,WAAW,MAAsB;AAC/C,SAAO,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,EAAE;AACvE;AAEO,SAAS,UAAU,MAAuC;AAC/D,SAAQ,KAAK,UAAiC;AAChD;AAOO,SAAS,uBAAuB,MAAmD;AACxF,MAAI,KAAK,cAAc,GAAG;AACxB,WAAO;AAAA,EACT;AACA,QAAM,WAAW,KAAK,kBAAkB;AACxC,MAAI,UAAU;AACZ,WAAO;AAAA,EACT;AACA,SAAO;AACT;","names":[]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ApiError,
|
|
3
3
|
apiGet
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-MZQC4LII.js";
|
|
5
5
|
import {
|
|
6
6
|
getEnv
|
|
7
7
|
} from "./chunk-2OKSJNLA.js";
|
|
@@ -294,4 +294,4 @@ export {
|
|
|
294
294
|
writeAdsOutput,
|
|
295
295
|
resolveCustomerId
|
|
296
296
|
};
|
|
297
|
-
//# sourceMappingURL=chunk-
|
|
297
|
+
//# sourceMappingURL=chunk-VVQLRFCI.js.map
|
package/dist/cli.js
CHANGED
|
@@ -69,7 +69,7 @@ import {
|
|
|
69
69
|
validateCanvasDeep,
|
|
70
70
|
withoutCastName,
|
|
71
71
|
ytDlpBlockSignal
|
|
72
|
-
} from "./chunk-
|
|
72
|
+
} from "./chunk-K2IKLMCM.js";
|
|
73
73
|
import {
|
|
74
74
|
csvOrJson,
|
|
75
75
|
daysAgoIso,
|
|
@@ -78,7 +78,7 @@ import {
|
|
|
78
78
|
resolveAccountIdArg,
|
|
79
79
|
resolveEffectiveStatus,
|
|
80
80
|
todayIso
|
|
81
|
-
} from "./chunk-
|
|
81
|
+
} from "./chunk-SR56QQTD.js";
|
|
82
82
|
import {
|
|
83
83
|
buildQueryCacheKey,
|
|
84
84
|
cacheGet,
|
|
@@ -94,14 +94,14 @@ import {
|
|
|
94
94
|
writeAdsJson,
|
|
95
95
|
writeAdsOutput,
|
|
96
96
|
writeJsonEnvelope
|
|
97
|
-
} from "./chunk-
|
|
97
|
+
} from "./chunk-VVQLRFCI.js";
|
|
98
98
|
import {
|
|
99
99
|
ApiError,
|
|
100
100
|
apiGet,
|
|
101
101
|
apiGetWithHeaders,
|
|
102
102
|
apiPost,
|
|
103
103
|
validateConvexId
|
|
104
|
-
} from "./chunk-
|
|
104
|
+
} from "./chunk-MZQC4LII.js";
|
|
105
105
|
import {
|
|
106
106
|
installExitRecord,
|
|
107
107
|
installStreamTaps,
|
|
@@ -19818,7 +19818,7 @@ function handleLinkedinError(err) {
|
|
|
19818
19818
|
explanation: explanation.message,
|
|
19819
19819
|
correctedCommand: explanation.correctedCommand
|
|
19820
19820
|
},
|
|
19821
|
-
retryable: err.code === "RATE_LIMITED" || err.code === "INTERNAL_ERROR"
|
|
19821
|
+
retryable: err.code === "RATE_LIMITED" || err.code === "UNAVAILABLE" || err.code === "INTERNAL_ERROR"
|
|
19822
19822
|
}
|
|
19823
19823
|
};
|
|
19824
19824
|
writeAdsJson(envelope);
|
|
@@ -26357,10 +26357,10 @@ Example: baker ads meta ads retag 120252158038400247 --url-tags "utm_source={{si
|
|
|
26357
26357
|
}
|
|
26358
26358
|
},
|
|
26359
26359
|
run: async ({ args: args5 }) => {
|
|
26360
|
-
const { apiPost: apiPost2 } = await import("./client-
|
|
26360
|
+
const { apiPost: apiPost2 } = await import("./client-3DGBQ2H3.js");
|
|
26361
26361
|
const { requireChatId: requireChatId2 } = await import("./env-BSG7TY5Y.js");
|
|
26362
|
-
const { writeJsonEnvelope: writeJsonEnvelope2 } = await import("./output-
|
|
26363
|
-
const { handleMetaError: handleMetaError2 } = await import("./shared-
|
|
26362
|
+
const { writeJsonEnvelope: writeJsonEnvelope2 } = await import("./output-OSSBUGT7.js");
|
|
26363
|
+
const { handleMetaError: handleMetaError2 } = await import("./shared-MSI4UMZ3.js");
|
|
26364
26364
|
try {
|
|
26365
26365
|
const accountId = bareAccountId2(args5);
|
|
26366
26366
|
const urlTags = typeof args5["url-tags"] === "string" ? args5["url-tags"] : void 0;
|
|
@@ -26505,10 +26505,10 @@ function duplicateCommand2(entity, label) {
|
|
|
26505
26505
|
replace: { type: "boolean", description: "Pause the original once the copy publishes" }
|
|
26506
26506
|
},
|
|
26507
26507
|
run: async ({ args: args5 }) => {
|
|
26508
|
-
const { apiPost: apiPost2 } = await import("./client-
|
|
26508
|
+
const { apiPost: apiPost2 } = await import("./client-3DGBQ2H3.js");
|
|
26509
26509
|
const { requireChatId: requireChatId2 } = await import("./env-BSG7TY5Y.js");
|
|
26510
|
-
const { writeJsonEnvelope: writeJsonEnvelope2 } = await import("./output-
|
|
26511
|
-
const { handleMetaError: handleMetaError2 } = await import("./shared-
|
|
26510
|
+
const { writeJsonEnvelope: writeJsonEnvelope2 } = await import("./output-OSSBUGT7.js");
|
|
26511
|
+
const { handleMetaError: handleMetaError2 } = await import("./shared-MSI4UMZ3.js");
|
|
26512
26512
|
try {
|
|
26513
26513
|
const accountId = bareAccountId2(args5);
|
|
26514
26514
|
const chatId = requireChatId2();
|
|
@@ -40880,6 +40880,7 @@ async function clearCreativeDirty(slug, base) {
|
|
|
40880
40880
|
}
|
|
40881
40881
|
|
|
40882
40882
|
// src/commands/canvas/run-resume.ts
|
|
40883
|
+
import { readFileSync as readFileSync14 } from "fs";
|
|
40883
40884
|
import { mkdir as mkdir4, readFile as readFile9, rm as rm4, writeFile as writeFile6 } from "fs/promises";
|
|
40884
40885
|
import path13 from "path";
|
|
40885
40886
|
function markerKey(canvasPath) {
|
|
@@ -40902,9 +40903,12 @@ function classifyRemoteRun(run, now) {
|
|
|
40902
40903
|
}
|
|
40903
40904
|
async function resolveRunId(opts) {
|
|
40904
40905
|
if (opts.explicitRunId) return { runId: opts.explicitRunId, resumed: false };
|
|
40906
|
+
const existing = await readMarker(opts.outputsDir, opts.canvasPath);
|
|
40907
|
+
if (existing?.pid !== void 0 && existing.pid !== process.pid && (opts.isRendering ?? isRenderProcess)(existing.pid)) {
|
|
40908
|
+
return { runId: existing.runId, resumed: false, rendering: { runId: existing.runId, pid: existing.pid } };
|
|
40909
|
+
}
|
|
40905
40910
|
if (!opts.fresh) {
|
|
40906
|
-
|
|
40907
|
-
if (existing) return { runId: existing, resumed: true, source: "local" };
|
|
40911
|
+
if (existing) return { runId: existing.runId, resumed: true, source: "local" };
|
|
40908
40912
|
if (opts.remote) {
|
|
40909
40913
|
try {
|
|
40910
40914
|
const active = await opts.remote.getActiveRun(opts.remote.creativeSlug, opts.remote.canvasSha);
|
|
@@ -40924,22 +40928,31 @@ async function resolveRunId(opts) {
|
|
|
40924
40928
|
}
|
|
40925
40929
|
return { runId: `r_${ulid()}`, resumed: false };
|
|
40926
40930
|
}
|
|
40927
|
-
async function
|
|
40931
|
+
async function readMarker(outputsDir, canvasPath) {
|
|
40928
40932
|
for (const key of [markerKey(canvasPath), legacyMarkerKey(canvasPath)]) {
|
|
40929
40933
|
try {
|
|
40930
40934
|
const raw = await readFile9(markerFile(outputsDir, key), "utf8");
|
|
40931
40935
|
const parsed = JSON.parse(raw);
|
|
40932
|
-
if (typeof parsed.runId === "string" && parsed.runId.length > 0)
|
|
40936
|
+
if (typeof parsed.runId === "string" && parsed.runId.length > 0) {
|
|
40937
|
+
return { runId: parsed.runId, ...Number.isInteger(parsed.pid) ? { pid: parsed.pid } : {} };
|
|
40938
|
+
}
|
|
40933
40939
|
} catch {
|
|
40934
40940
|
}
|
|
40935
40941
|
}
|
|
40936
40942
|
return null;
|
|
40937
40943
|
}
|
|
40944
|
+
function isRenderProcess(pid) {
|
|
40945
|
+
try {
|
|
40946
|
+
return readFileSync14(`/proc/${pid}/cmdline`, "utf8").includes("canvas");
|
|
40947
|
+
} catch {
|
|
40948
|
+
return false;
|
|
40949
|
+
}
|
|
40950
|
+
}
|
|
40938
40951
|
async function markRunInFlight(outputsDir, canvasPath, runId) {
|
|
40939
40952
|
try {
|
|
40940
40953
|
const file = markerFile(outputsDir, markerKey(canvasPath));
|
|
40941
40954
|
await mkdir4(path13.dirname(file), { recursive: true });
|
|
40942
|
-
await writeFile6(file, JSON.stringify({ runId, canvasPath: path13.resolve(canvasPath), startedAt: Date.now() }));
|
|
40955
|
+
await writeFile6(file, JSON.stringify({ runId, pid: process.pid, canvasPath: path13.resolve(canvasPath), startedAt: Date.now() }));
|
|
40943
40956
|
} catch {
|
|
40944
40957
|
}
|
|
40945
40958
|
}
|
|
@@ -41897,13 +41910,31 @@ ${describeRewrites(healed.rewrites)}
|
|
|
41897
41910
|
const creativeSlug = creativeSlugFromCanvasPath(filePath) ?? void 0;
|
|
41898
41911
|
const client = opts.record === false ? null : buildBackendClient();
|
|
41899
41912
|
const outputsDir = opts.outputsDir ? path16.resolve(opts.outputsDir) : path16.resolve("canvas");
|
|
41900
|
-
const { runId, resumed, source, concurrentRunId } = await resolveRunId({
|
|
41913
|
+
const { runId, resumed, source, concurrentRunId, rendering } = await resolveRunId({
|
|
41901
41914
|
explicitRunId: opts.runId,
|
|
41902
41915
|
fresh: opts.fresh === true,
|
|
41903
41916
|
outputsDir,
|
|
41904
41917
|
canvasPath: filePath,
|
|
41905
41918
|
remote: client && creativeSlug ? { creativeSlug, canvasSha, getActiveRun: (slug, sha) => client.getActiveRun(slug, sha) } : void 0
|
|
41906
41919
|
});
|
|
41920
|
+
if (rendering) {
|
|
41921
|
+
process.stderr.write(
|
|
41922
|
+
`${JSON.stringify(
|
|
41923
|
+
{
|
|
41924
|
+
ok: false,
|
|
41925
|
+
error: {
|
|
41926
|
+
code: "CONFLICT",
|
|
41927
|
+
message: `This canvas is already rendering in another process (run ${rendering.runId}, pid ${rendering.pid}).`,
|
|
41928
|
+
fix: "Wait for that render to finish and use its result instead of starting a second one: two renders of one canvas share a run and overwrite each other. If you started it in the background, read its output when it completes."
|
|
41929
|
+
}
|
|
41930
|
+
},
|
|
41931
|
+
null,
|
|
41932
|
+
2
|
|
41933
|
+
)}
|
|
41934
|
+
`
|
|
41935
|
+
);
|
|
41936
|
+
process.exit(2);
|
|
41937
|
+
}
|
|
41907
41938
|
if (resumed) {
|
|
41908
41939
|
process.stdout.write(
|
|
41909
41940
|
`[resume] continuing interrupted run ${runId}${source === "remote" ? " (adopted from run history)" : ""} \u2014 in-flight jobs re-attach, cached nodes skip
|
|
@@ -48257,11 +48288,11 @@ var addSideEffectCommand = defineCommand125({
|
|
|
48257
48288
|
});
|
|
48258
48289
|
|
|
48259
48290
|
// src/commands/flows/map.ts
|
|
48260
|
-
import { readFileSync as
|
|
48291
|
+
import { readFileSync as readFileSync16 } from "fs";
|
|
48261
48292
|
import { defineCommand as defineCommand126 } from "citty";
|
|
48262
48293
|
|
|
48263
48294
|
// src/commands/flows/value-expression.ts
|
|
48264
|
-
import { existsSync as existsSync6, readFileSync as
|
|
48295
|
+
import { existsSync as existsSync6, readFileSync as readFileSync15 } from "fs";
|
|
48265
48296
|
import { join as join4 } from "path";
|
|
48266
48297
|
var PREFIXES2 = ["field", "tracking", "global", "code"];
|
|
48267
48298
|
function splitParts(raw) {
|
|
@@ -48348,7 +48379,7 @@ function trackingFieldIds() {
|
|
|
48348
48379
|
const path48 = join4(flowsDir(), "..", "tracking.ts");
|
|
48349
48380
|
if (!existsSync6(path48)) return null;
|
|
48350
48381
|
try {
|
|
48351
|
-
const source =
|
|
48382
|
+
const source = readFileSync15(path48, "utf-8");
|
|
48352
48383
|
const block2 = source.match(/TRACKING_FIELD_IDS\s*=\s*\[([\s\S]*?)\]\s*as const/)?.[1];
|
|
48353
48384
|
if (!block2) return null;
|
|
48354
48385
|
const ids = [...block2.matchAll(/"(tracking\.[a-z0-9_]+)"/g)].map((match) => match[1]);
|
|
@@ -48925,7 +48956,7 @@ function specsFromFile(parsed) {
|
|
|
48925
48956
|
function readSpecFile(path48) {
|
|
48926
48957
|
let raw;
|
|
48927
48958
|
try {
|
|
48928
|
-
raw = path48 === "-" ?
|
|
48959
|
+
raw = path48 === "-" ? readFileSync16(0, "utf-8") : readFileSync16(path48, "utf-8");
|
|
48929
48960
|
} catch (error) {
|
|
48930
48961
|
refuse(
|
|
48931
48962
|
`Could not read ${path48 === "-" ? "the mapping from stdin" : `"${path48}"`}: ${error instanceof Error ? error.message : String(error)}`
|
|
@@ -49624,7 +49655,7 @@ Full guide: __tooling__/docs/tools/baker/flows.md`
|
|
|
49624
49655
|
});
|
|
49625
49656
|
|
|
49626
49657
|
// src/commands/funnel/index.ts
|
|
49627
|
-
import { readFileSync as
|
|
49658
|
+
import { readFileSync as readFileSync17 } from "fs";
|
|
49628
49659
|
import { defineCommand as defineCommand130 } from "citty";
|
|
49629
49660
|
|
|
49630
49661
|
// src/commands/funnel/formMoments.ts
|
|
@@ -50420,7 +50451,7 @@ function workspaceForms() {
|
|
|
50420
50451
|
const forms = [];
|
|
50421
50452
|
for (const slug of listFlowSlugs()) {
|
|
50422
50453
|
try {
|
|
50423
|
-
forms.push({ slug, tree: JSON.parse(
|
|
50454
|
+
forms.push({ slug, tree: JSON.parse(readFileSync17(flowDataPath(slug), "utf-8")) });
|
|
50424
50455
|
} catch {
|
|
50425
50456
|
}
|
|
50426
50457
|
}
|
|
@@ -50555,7 +50586,7 @@ Examples:
|
|
|
50555
50586
|
import { defineCommand as defineCommand132 } from "citty";
|
|
50556
50587
|
|
|
50557
50588
|
// src/commands/ga4/shared.ts
|
|
50558
|
-
import { readFileSync as
|
|
50589
|
+
import { readFileSync as readFileSync18 } from "fs";
|
|
50559
50590
|
function failValidation3(message) {
|
|
50560
50591
|
writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message } });
|
|
50561
50592
|
process.exit(1);
|
|
@@ -50571,7 +50602,7 @@ function requireTarget5(args5, entity) {
|
|
|
50571
50602
|
function readJsonSource(args5, flag) {
|
|
50572
50603
|
const inline = args5[flag];
|
|
50573
50604
|
const file = args5.file;
|
|
50574
|
-
const raw = typeof file === "string" && file.length > 0 ?
|
|
50605
|
+
const raw = typeof file === "string" && file.length > 0 ? readFileSync18(file, "utf8") : typeof inline === "string" && inline.length > 0 ? inline : void 0;
|
|
50575
50606
|
if (raw === void 0) {
|
|
50576
50607
|
failValidation3(`pass --${flag} with inline JSON or --file with a path to a JSON file`);
|
|
50577
50608
|
}
|
|
@@ -50602,7 +50633,7 @@ function loadJsonPayloads(args5) {
|
|
|
50602
50633
|
}
|
|
50603
50634
|
return parsed.map((entry, index) => asObject(entry, "json", index));
|
|
50604
50635
|
}
|
|
50605
|
-
var RETRYABLE_CODES = /* @__PURE__ */ new Set(["RATE_LIMITED", "INTERNAL_ERROR", "NETWORK_ERROR", "TIMEOUT"]);
|
|
50636
|
+
var RETRYABLE_CODES = /* @__PURE__ */ new Set(["RATE_LIMITED", "UNAVAILABLE", "INTERNAL_ERROR", "NETWORK_ERROR", "TIMEOUT"]);
|
|
50606
50637
|
function handleError5(err) {
|
|
50607
50638
|
if (err instanceof ApiError) {
|
|
50608
50639
|
const readOnly = err.code === "FORBIDDEN" && /read the property but not change it/i.test(err.message);
|
|
@@ -50922,7 +50953,7 @@ Examples:
|
|
|
50922
50953
|
});
|
|
50923
50954
|
|
|
50924
50955
|
// src/commands/ga4/query.ts
|
|
50925
|
-
import { appendFileSync as appendFileSync2, existsSync as existsSync7, readFileSync as
|
|
50956
|
+
import { appendFileSync as appendFileSync2, existsSync as existsSync7, readFileSync as readFileSync19, writeFileSync as writeFileSync4 } from "fs";
|
|
50926
50957
|
import { resolve as resolve2 } from "path";
|
|
50927
50958
|
import { defineCommand as defineCommand135 } from "citty";
|
|
50928
50959
|
|
|
@@ -51013,7 +51044,7 @@ function writeRowsToFile2(filePath, rows, append) {
|
|
|
51013
51044
|
writeFileSync4(filePath, content, "utf-8");
|
|
51014
51045
|
}
|
|
51015
51046
|
} else if (append && existsSync7(filePath)) {
|
|
51016
|
-
const existing = JSON.parse(
|
|
51047
|
+
const existing = JSON.parse(readFileSync19(filePath, "utf-8"));
|
|
51017
51048
|
writeFileSync4(filePath, JSON.stringify([...existing, ...rows], null, 2), "utf-8");
|
|
51018
51049
|
} else {
|
|
51019
51050
|
writeFileSync4(filePath, JSON.stringify(rows, null, 2), "utf-8");
|
|
@@ -51865,7 +51896,7 @@ Full guide: __tooling__/docs/tools/baker/ga4.md`
|
|
|
51865
51896
|
import { defineCommand as defineCommand141 } from "citty";
|
|
51866
51897
|
|
|
51867
51898
|
// src/commands/gsc/query.ts
|
|
51868
|
-
import { appendFileSync as appendFileSync3, existsSync as existsSync8, readFileSync as
|
|
51899
|
+
import { appendFileSync as appendFileSync3, existsSync as existsSync8, readFileSync as readFileSync20, writeFileSync as writeFileSync5 } from "fs";
|
|
51869
51900
|
import { resolve as resolve3 } from "path";
|
|
51870
51901
|
import { defineCommand as defineCommand138 } from "citty";
|
|
51871
51902
|
|
|
@@ -52013,7 +52044,7 @@ function writeRowsToFile3(filePath, rows, append) {
|
|
|
52013
52044
|
writeFileSync5(filePath, content, "utf-8");
|
|
52014
52045
|
}
|
|
52015
52046
|
} else if (append && existsSync8(filePath)) {
|
|
52016
|
-
const existing = JSON.parse(
|
|
52047
|
+
const existing = JSON.parse(readFileSync20(filePath, "utf-8"));
|
|
52017
52048
|
writeFileSync5(filePath, JSON.stringify([...existing, ...rows], null, 2), "utf-8");
|
|
52018
52049
|
} else {
|
|
52019
52050
|
writeFileSync5(filePath, JSON.stringify(rows, null, 2), "utf-8");
|
|
@@ -53854,6 +53885,22 @@ function parseAutoIngest(raw, max) {
|
|
|
53854
53885
|
return { ok: true, value };
|
|
53855
53886
|
}
|
|
53856
53887
|
|
|
53888
|
+
// src/commands/images/extractErrors.ts
|
|
53889
|
+
var RETRYABLE = /* @__PURE__ */ new Set(["UNAVAILABLE", "RATE_LIMITED", "TIMEOUT", "NETWORK_ERROR"]);
|
|
53890
|
+
function extractErrorEnvelope(err, url) {
|
|
53891
|
+
const retryable = RETRYABLE.has(err.code);
|
|
53892
|
+
const fallback = `use \`baker images screenshot ${url}\` to capture the page as one image, or \`baker images logo <domain>\` for the brand's mark, and carry on with the rest of the job.`;
|
|
53893
|
+
return {
|
|
53894
|
+
ok: false,
|
|
53895
|
+
error: {
|
|
53896
|
+
code: err.code,
|
|
53897
|
+
message: err.message,
|
|
53898
|
+
retryable,
|
|
53899
|
+
fix: retryable ? { action: "retry_once", explanation: `Run the same command once more. If it fails again, ${fallback}` } : { action: "use_fallback", explanation: `Retrying the same address will fail the same way \u2014 ${fallback}` }
|
|
53900
|
+
}
|
|
53901
|
+
};
|
|
53902
|
+
}
|
|
53903
|
+
|
|
53857
53904
|
// src/commands/images/extract.ts
|
|
53858
53905
|
registerSchema({
|
|
53859
53906
|
command: "images.extract",
|
|
@@ -53920,7 +53967,7 @@ var extractCommand = defineCommand149({
|
|
|
53920
53967
|
writeJson({ ok: true, data });
|
|
53921
53968
|
} catch (err) {
|
|
53922
53969
|
if (err instanceof ApiError) {
|
|
53923
|
-
writeJson(
|
|
53970
|
+
writeJson(extractErrorEnvelope(err, String(args5.url)));
|
|
53924
53971
|
process.exit(1);
|
|
53925
53972
|
}
|
|
53926
53973
|
writeJson({ ok: false, error: { code: "INTERNAL_ERROR", message: "Unexpected error" } });
|
|
@@ -65631,7 +65678,7 @@ import { defineCommand as defineCommand221 } from "citty";
|
|
|
65631
65678
|
import { defineCommand as defineCommand218 } from "citty";
|
|
65632
65679
|
|
|
65633
65680
|
// src/commands/tag-manager/shared.ts
|
|
65634
|
-
import { readFileSync as
|
|
65681
|
+
import { readFileSync as readFileSync21 } from "fs";
|
|
65635
65682
|
function failValidation5(message) {
|
|
65636
65683
|
writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message } });
|
|
65637
65684
|
process.exit(1);
|
|
@@ -65647,7 +65694,7 @@ function requireTarget6(args5, entity) {
|
|
|
65647
65694
|
function loadJsonArg2(args5, flag = "json") {
|
|
65648
65695
|
const inline = args5[flag];
|
|
65649
65696
|
const file = args5.file;
|
|
65650
|
-
const raw = typeof file === "string" && file.length > 0 ?
|
|
65697
|
+
const raw = typeof file === "string" && file.length > 0 ? readFileSync21(file, "utf8") : typeof inline === "string" && inline.length > 0 ? inline : void 0;
|
|
65651
65698
|
if (raw === void 0) {
|
|
65652
65699
|
failValidation5(`pass --${flag} with inline JSON or --file with a path to a JSON file`);
|
|
65653
65700
|
}
|
|
@@ -65661,7 +65708,7 @@ function loadJsonArg2(args5, flag = "json") {
|
|
|
65661
65708
|
return failValidation5(`--${flag} is not valid JSON`);
|
|
65662
65709
|
}
|
|
65663
65710
|
}
|
|
65664
|
-
var RETRYABLE_CODES2 = /* @__PURE__ */ new Set(["RATE_LIMITED", "INTERNAL_ERROR", "NETWORK_ERROR", "TIMEOUT"]);
|
|
65711
|
+
var RETRYABLE_CODES2 = /* @__PURE__ */ new Set(["RATE_LIMITED", "UNAVAILABLE", "INTERNAL_ERROR", "NETWORK_ERROR", "TIMEOUT"]);
|
|
65665
65712
|
function handleError8(err) {
|
|
65666
65713
|
if (err instanceof ApiError) {
|
|
65667
65714
|
writeJsonEnvelope({
|
|
@@ -69050,7 +69097,7 @@ function outputFlagForCommand(root, argv) {
|
|
|
69050
69097
|
}
|
|
69051
69098
|
|
|
69052
69099
|
// src/version.ts
|
|
69053
|
-
import { readFileSync as
|
|
69100
|
+
import { readFileSync as readFileSync22 } from "fs";
|
|
69054
69101
|
function packageJsonUrl() {
|
|
69055
69102
|
return new URL("../package.json", import.meta.url);
|
|
69056
69103
|
}
|
|
@@ -69062,7 +69109,7 @@ function parsePackageVersion(raw) {
|
|
|
69062
69109
|
throw new Error("Invalid CLI package.json: missing version");
|
|
69063
69110
|
}
|
|
69064
69111
|
function getCliVersion() {
|
|
69065
|
-
return parsePackageVersion(
|
|
69112
|
+
return parsePackageVersion(readFileSync22(packageJsonUrl(), "utf8"));
|
|
69066
69113
|
}
|
|
69067
69114
|
|
|
69068
69115
|
// src/cli.ts
|