@koda-sl/baker-cli 0.376.0 → 0.378.0
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 +6 -1
- package/dist/{chunk-WKGKDYX3.js → chunk-VLUGGVJL.js} +6 -1
- package/dist/{chunk-WKGKDYX3.js.map → chunk-VLUGGVJL.js.map} +1 -1
- package/dist/cli.js +66 -25
- package/dist/cli.js.map +1 -1
- package/dist/{shared-VAA3SCQR.js → shared-J7DQZ2ED.js} +4 -2
- package/package.json +1 -1
- /package/dist/{shared-VAA3SCQR.js.map → shared-J7DQZ2ED.js.map} +0 -0
package/README.md
CHANGED
|
@@ -905,6 +905,9 @@ baker ads meta leads --form-id 987654321 --full # raw conta
|
|
|
905
905
|
baker ads meta campaigns --account-id act_123 # ACTIVE only by default
|
|
906
906
|
baker ads meta ads --account-id act_123 --all-statuses # widen to everything
|
|
907
907
|
|
|
908
|
+
# "Find the October ad" — Meta matches the name, so only that row is read
|
|
909
|
+
baker ads meta ads --account-id act_123 --all-statuses --name-contains octubre --fields id,name,adset_id,creative_id
|
|
910
|
+
|
|
908
911
|
# "Tell me about ad 9988"
|
|
909
912
|
baker ads meta creatives --creative-id 9988
|
|
910
913
|
baker ads meta preview --creative-id 9988 --ad-format MOBILE_FEED_STANDARD --out-file /tmp/p.html
|
|
@@ -984,6 +987,8 @@ Status changes are `pause|resume|archive` subcommands on `campaigns`/`adsets`/`a
|
|
|
984
987
|
|
|
985
988
|
**Listing rows (`campaigns`/`adsets`/`ads`/`activities`)** print a table of compact rows by default — the fields you decide with (id, name, `effective_status`, budgets, goal; for activities who/when/what and a one-line `change`). `--fields a,b.c` returns exactly those dotted paths, `--full` returns every field Meta sent (targeting, tracking specs, raw `extra_data`), and `--output json` returns the rows in the `{ ok, data }` envelope.
|
|
986
989
|
|
|
990
|
+
To find one entity by name, pass `--name-contains <text>` to `campaigns`, `adsets` or `ads`: Meta matches it server-side (case-insensitive), so only the matching rows are read instead of the whole account.
|
|
991
|
+
|
|
987
992
|
**Pagination** is auto-drained (no manual cursor handling).
|
|
988
993
|
|
|
989
994
|
#### Full command surface
|
|
@@ -5452,7 +5457,7 @@ Validate, then execute the graph. Blocks until done. Logs one line per node. Ret
|
|
|
5452
5457
|
|
|
5453
5458
|
**Run history streams live.** The run posts its plan (every node + its dependency edges) the moment validation passes, then re-posts a progress snapshot as each node starts and settles — the dashboard's creative workflow graph shows nodes flipping pending → running → done in real time, with each node's outputs attached as they land. A failed run keeps its per-node trail (what completed, what died). All best-effort: an unreachable backend never changes the run's outcome.
|
|
5454
5459
|
|
|
5455
|
-
**Failures don't abandon sibling work.** Nodes in a layer run under the concurrency cap and every one **settles** — a failed clip no longer kills its in-flight siblings, whose finished results still land in the content-addressed cache. One failure re-throws as-is; several are reported together (each failed node named). Re-running `baker canvas run` resumes from the cache and re-executes **only** the failed nodes and their descendants — never hand-orchestrate per-node renders. Long `video_generate` clips execute as **backend jobs** (the CLI polls; a CDN/proxy timeout can no longer kill a generation mid-flight).
|
|
5460
|
+
**Failures don't abandon sibling work.** Nodes in a layer run under the concurrency cap and every one **settles** — a failed clip no longer kills its in-flight siblings, whose finished results still land in the content-addressed cache. One failure re-throws as-is; several are reported together (each failed node named). Re-running `baker canvas run` resumes from the cache and re-executes **only** the failed nodes and their descendants — never hand-orchestrate per-node renders. **One render per canvas at a time:** a `run` of a canvas that another live process in the same workspace is still rendering (a backgrounded render, or a subagent's) is refused with `CONFLICT` instead of sharing its run, `--run-id` included — wait for it and use its result. Long `video_generate` clips execute as **backend jobs** (the CLI polls; a CDN/proxy timeout can no longer kill a generation mid-flight).
|
|
5456
5461
|
|
|
5457
5462
|
#### `baker canvas scaffold-video <video> [flags]`
|
|
5458
5463
|
|
|
@@ -87,6 +87,10 @@ function daysAgoIso(days) {
|
|
|
87
87
|
function csvOrJson(args) {
|
|
88
88
|
return args.output ?? "json";
|
|
89
89
|
}
|
|
90
|
+
var NAME_CONTAINS_ARG = {
|
|
91
|
+
type: "string",
|
|
92
|
+
description: "Only rows whose name contains this text, matched by Meta before anything is returned. Start here to find one entity by name: --name-contains octubre --all-statuses"
|
|
93
|
+
};
|
|
90
94
|
function resolveEffectiveStatus(args) {
|
|
91
95
|
if (args["all-statuses"]) {
|
|
92
96
|
return void 0;
|
|
@@ -117,7 +121,8 @@ export {
|
|
|
117
121
|
todayIso,
|
|
118
122
|
daysAgoIso,
|
|
119
123
|
csvOrJson,
|
|
124
|
+
NAME_CONTAINS_ARG,
|
|
120
125
|
resolveEffectiveStatus,
|
|
121
126
|
statusFilterHints
|
|
122
127
|
};
|
|
123
|
-
//# sourceMappingURL=chunk-
|
|
128
|
+
//# sourceMappingURL=chunk-VLUGGVJL.js.map
|
|
@@ -1 +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\n/**\n * An empty listing under a status filter reads exactly like \"nothing exists\":\n * a paused campaign's ad sets are CAMPAIGN_PAUSED, so the ACTIVE default hides\n * every one of them. Say which filter produced the empty list and how to widen it.\n */\nexport function statusFilterHints(\n rows: ReadonlyArray<unknown>,\n effectiveStatus: string | undefined,\n noun: string,\n): string[] {\n if (rows.length > 0 || effectiveStatus === undefined) return [];\n if (effectiveStatus === \"ACTIVE\") {\n return [\n `No ACTIVE ${noun}. The ACTIVE filter hides paused, archived and in-review ones (under a paused campaign or ad set that is all of them), so this does NOT mean none exist. Re-run with --all-statuses before concluding there are none.`,\n ];\n }\n return [\n `No ${noun} with effective_status ${effectiveStatus}. Re-run with --all-statuses to see every status before concluding there are none.`,\n ];\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;AAOO,SAAS,kBACd,MACA,iBACA,MACU;AACV,MAAI,KAAK,SAAS,KAAK,oBAAoB,OAAW,QAAO,CAAC;AAC9D,MAAI,oBAAoB,UAAU;AAChC,WAAO;AAAA,MACL,aAAa,IAAI;AAAA,IACnB;AAAA,EACF;AACA,SAAO;AAAA,IACL,MAAM,IAAI,0BAA0B,eAAe;AAAA,EACrD;AACF;","names":[]}
|
|
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 * Matched by Meta itself, so finding one entity by name reads only the rows that\n * match instead of the whole account.\n */\nexport const NAME_CONTAINS_ARG = {\n type: \"string\",\n description:\n \"Only rows whose name contains this text, matched by Meta before anything is returned. Start here to find one entity by name: --name-contains octubre --all-statuses\",\n} as const;\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\n/**\n * An empty listing under a status filter reads exactly like \"nothing exists\":\n * a paused campaign's ad sets are CAMPAIGN_PAUSED, so the ACTIVE default hides\n * every one of them. Say which filter produced the empty list and how to widen it.\n */\nexport function statusFilterHints(\n rows: ReadonlyArray<unknown>,\n effectiveStatus: string | undefined,\n noun: string,\n): string[] {\n if (rows.length > 0 || effectiveStatus === undefined) return [];\n if (effectiveStatus === \"ACTIVE\") {\n return [\n `No ACTIVE ${noun}. The ACTIVE filter hides paused, archived and in-review ones (under a paused campaign or ad set that is all of them), so this does NOT mean none exist. Re-run with --all-statuses before concluding there are none.`,\n ];\n }\n return [\n `No ${noun} with effective_status ${effectiveStatus}. Re-run with --all-statuses to see every status before concluding there are none.`,\n ];\n}\n"],"mappings":"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","names":[]}
|
package/dist/cli.js
CHANGED
|
@@ -72,6 +72,7 @@ import {
|
|
|
72
72
|
ytDlpBlockSignal
|
|
73
73
|
} from "./chunk-FGHMWBUD.js";
|
|
74
74
|
import {
|
|
75
|
+
NAME_CONTAINS_ARG,
|
|
75
76
|
csvOrJson,
|
|
76
77
|
daysAgoIso,
|
|
77
78
|
getDateRange,
|
|
@@ -80,7 +81,7 @@ import {
|
|
|
80
81
|
resolveEffectiveStatus,
|
|
81
82
|
statusFilterHints,
|
|
82
83
|
todayIso
|
|
83
|
-
} from "./chunk-
|
|
84
|
+
} from "./chunk-VLUGGVJL.js";
|
|
84
85
|
import {
|
|
85
86
|
buildQueryCacheKey,
|
|
86
87
|
cacheGet,
|
|
@@ -26835,7 +26836,7 @@ Example: baker ads meta ads retag 120252158038400247 --url-tags "utm_source={{si
|
|
|
26835
26836
|
const { apiPost: apiPost2 } = await import("./client-GR6YL3YX.js");
|
|
26836
26837
|
const { requireChatId: requireChatId2 } = await import("./env-4P5HOGNA.js");
|
|
26837
26838
|
const { writeJsonEnvelope: writeJsonEnvelope2 } = await import("./output-NMQXZF3Z.js");
|
|
26838
|
-
const { handleMetaError: handleMetaError2 } = await import("./shared-
|
|
26839
|
+
const { handleMetaError: handleMetaError2 } = await import("./shared-J7DQZ2ED.js");
|
|
26839
26840
|
try {
|
|
26840
26841
|
const accountId = bareAccountId2(args5);
|
|
26841
26842
|
const urlTags = typeof args5["url-tags"] === "string" ? args5["url-tags"] : void 0;
|
|
@@ -26983,7 +26984,7 @@ function duplicateCommand2(entity, label) {
|
|
|
26983
26984
|
const { apiPost: apiPost2 } = await import("./client-GR6YL3YX.js");
|
|
26984
26985
|
const { requireChatId: requireChatId2 } = await import("./env-4P5HOGNA.js");
|
|
26985
26986
|
const { writeJsonEnvelope: writeJsonEnvelope2 } = await import("./output-NMQXZF3Z.js");
|
|
26986
|
-
const { handleMetaError: handleMetaError2 } = await import("./shared-
|
|
26987
|
+
const { handleMetaError: handleMetaError2 } = await import("./shared-J7DQZ2ED.js");
|
|
26987
26988
|
try {
|
|
26988
26989
|
const accountId = bareAccountId2(args5);
|
|
26989
26990
|
const chatId = requireChatId2();
|
|
@@ -27022,6 +27023,7 @@ var listArgs5 = {
|
|
|
27022
27023
|
"campaign-id": { type: "string", description: "Filter to one campaign" },
|
|
27023
27024
|
"effective-status": { type: "string", description: "Comma-separated effective_status filter (overrides default)" },
|
|
27024
27025
|
"all-statuses": { type: "boolean", description: "Drop the default ACTIVE filter" },
|
|
27026
|
+
"name-contains": NAME_CONTAINS_ARG,
|
|
27025
27027
|
limit: { type: "string", description: "Max rows (default 1000)" },
|
|
27026
27028
|
"no-cache": NO_CACHE_ARG,
|
|
27027
27029
|
...META_LIST_SHAPE_ARGS
|
|
@@ -27045,6 +27047,7 @@ var listCommand4 = defineCommand58({
|
|
|
27045
27047
|
if (args5["adset-id"]) params["adset-id"] = args5["adset-id"];
|
|
27046
27048
|
if (args5["campaign-id"]) params["campaign-id"] = args5["campaign-id"];
|
|
27047
27049
|
if (effectiveStatus) params["effective-status"] = effectiveStatus;
|
|
27050
|
+
if (args5["name-contains"]) params["name-contains"] = args5["name-contains"];
|
|
27048
27051
|
if (args5.limit) params.limit = args5.limit;
|
|
27049
27052
|
if (args5["no-cache"]) params["skip-cache"] = "true";
|
|
27050
27053
|
const data = await apiGet("/api/ads/meta/ads", params);
|
|
@@ -27070,6 +27073,7 @@ preview_shareable_link); --full returns every field; --output json returns the r
|
|
|
27070
27073
|
Examples:
|
|
27071
27074
|
baker ads meta ads --account-id act_123
|
|
27072
27075
|
baker ads meta ads --adset-id 6123
|
|
27076
|
+
baker ads meta ads --account-id act_123 --all-statuses --name-contains octubre --fields id,name,adset_id,creative_id \u2014 find one ad by name
|
|
27073
27077
|
baker ads meta ads --adset-id 6123 --fields id,name,preview_shareable_link
|
|
27074
27078
|
baker ads meta ads create --name "Ad 1" --adset meta_temp_as01 --creative meta_temp_cr01
|
|
27075
27079
|
baker ads meta ads pause 6123 --account-id act_123
|
|
@@ -27100,6 +27104,7 @@ var listArgs6 = {
|
|
|
27100
27104
|
"campaign-id": { type: "string", description: "Filter to one campaign" },
|
|
27101
27105
|
"effective-status": { type: "string", description: "Comma-separated effective_status filter (overrides default)" },
|
|
27102
27106
|
"all-statuses": { type: "boolean", description: "Drop the default ACTIVE filter" },
|
|
27107
|
+
"name-contains": NAME_CONTAINS_ARG,
|
|
27103
27108
|
limit: { type: "string", description: "Max rows (default 1000)" },
|
|
27104
27109
|
"no-cache": NO_CACHE_ARG,
|
|
27105
27110
|
...META_LIST_SHAPE_ARGS
|
|
@@ -27122,6 +27127,7 @@ var listCommand5 = defineCommand59({
|
|
|
27122
27127
|
const params = { "account-id": accountId };
|
|
27123
27128
|
if (args5["campaign-id"]) params["campaign-id"] = args5["campaign-id"];
|
|
27124
27129
|
if (effectiveStatus) params["effective-status"] = effectiveStatus;
|
|
27130
|
+
if (args5["name-contains"]) params["name-contains"] = args5["name-contains"];
|
|
27125
27131
|
if (args5.limit) params.limit = args5.limit;
|
|
27126
27132
|
if (args5["no-cache"]) params["skip-cache"] = "true";
|
|
27127
27133
|
const data = await apiGet("/api/ads/meta/adsets", params);
|
|
@@ -27145,6 +27151,7 @@ is not in the compact row \u2014 ask for it with --fields (dotted paths) or --fu
|
|
|
27145
27151
|
Examples:
|
|
27146
27152
|
baker ads meta adsets --account-id act_123
|
|
27147
27153
|
baker ads meta adsets --campaign-id 6123456789
|
|
27154
|
+
baker ads meta adsets --account-id act_123 --all-statuses --name-contains retargeting \u2014 find one ad set by name
|
|
27148
27155
|
baker ads meta adsets --campaign-id 6123456789 --fields id,name,targeting.geo_locations
|
|
27149
27156
|
baker ads meta adsets create --campaign meta_temp_ab12 --name "US 25-54" --optimization-goal LINK_CLICKS --billing-event IMPRESSIONS --daily-budget 50 --targeting-file t.json`
|
|
27150
27157
|
},
|
|
@@ -27257,6 +27264,7 @@ var listArgs8 = {
|
|
|
27257
27264
|
"account-id": { type: "string", description: "Meta ad account ID" },
|
|
27258
27265
|
"effective-status": { type: "string", description: "Comma-separated effective_status filter (overrides default)" },
|
|
27259
27266
|
"all-statuses": { type: "boolean", description: "Drop the default ACTIVE filter and return everything" },
|
|
27267
|
+
"name-contains": NAME_CONTAINS_ARG,
|
|
27260
27268
|
limit: { type: "string", description: "Max rows (default 1000)" },
|
|
27261
27269
|
"no-cache": NO_CACHE_ARG,
|
|
27262
27270
|
...META_LIST_SHAPE_ARGS
|
|
@@ -27278,6 +27286,7 @@ var listCommand7 = defineCommand62({
|
|
|
27278
27286
|
try {
|
|
27279
27287
|
const params = { "account-id": accountId };
|
|
27280
27288
|
if (effectiveStatus) params["effective-status"] = effectiveStatus;
|
|
27289
|
+
if (args5["name-contains"]) params["name-contains"] = args5["name-contains"];
|
|
27281
27290
|
if (args5.limit) params.limit = args5.limit;
|
|
27282
27291
|
if (args5["no-cache"]) params["skip-cache"] = "true";
|
|
27283
27292
|
const data = await apiGet("/api/ads/meta/campaigns", params);
|
|
@@ -27305,6 +27314,7 @@ Listings print a table by default: id, name, effective_status, daily/lifetime bu
|
|
|
27305
27314
|
Examples:
|
|
27306
27315
|
baker ads meta campaigns --account-id act_123 # ACTIVE only
|
|
27307
27316
|
baker ads meta campaigns --account-id act_123 --all-statuses # everything
|
|
27317
|
+
baker ads meta campaigns --account-id act_123 --all-statuses --name-contains Q3 # find one by name
|
|
27308
27318
|
baker ads meta campaigns --account-id act_123 --fields id,name,objective,bid_strategy,special_ad_categories
|
|
27309
27319
|
baker ads meta campaigns --account-id act_123 --output json # rows as JSON
|
|
27310
27320
|
baker ads meta campaigns create --account-id act_123 --name "Q3" --objective OUTCOME_LEADS --daily-budget 50
|
|
@@ -41621,6 +41631,7 @@ async function clearCreativeDirty(slug, base) {
|
|
|
41621
41631
|
}
|
|
41622
41632
|
|
|
41623
41633
|
// src/commands/canvas/run-resume.ts
|
|
41634
|
+
import { readFileSync as readFileSync14 } from "fs";
|
|
41624
41635
|
import { mkdir as mkdir4, readFile as readFile9, rm as rm4, writeFile as writeFile6 } from "fs/promises";
|
|
41625
41636
|
import path13 from "path";
|
|
41626
41637
|
function markerKey(canvasPath) {
|
|
@@ -41642,10 +41653,13 @@ function classifyRemoteRun(run, now) {
|
|
|
41642
41653
|
return age > REMOTE_ADOPT_STALE_MS ? "adopt" : "concurrent";
|
|
41643
41654
|
}
|
|
41644
41655
|
async function resolveRunId(opts) {
|
|
41656
|
+
const existing = await readMarker(opts.outputsDir, opts.canvasPath);
|
|
41657
|
+
if (existing?.pid !== void 0 && existing.pid !== process.pid && (opts.isRendering ?? isRenderProcess)(existing.pid)) {
|
|
41658
|
+
return { runId: existing.runId, resumed: false, rendering: { runId: existing.runId, pid: existing.pid } };
|
|
41659
|
+
}
|
|
41645
41660
|
if (opts.explicitRunId) return { runId: opts.explicitRunId, resumed: false };
|
|
41646
41661
|
if (!opts.fresh) {
|
|
41647
|
-
|
|
41648
|
-
if (existing) return { runId: existing, resumed: true, source: "local" };
|
|
41662
|
+
if (existing) return { runId: existing.runId, resumed: true, source: "local" };
|
|
41649
41663
|
if (opts.remote) {
|
|
41650
41664
|
try {
|
|
41651
41665
|
const active = await opts.remote.getActiveRun(opts.remote.creativeSlug, opts.remote.canvasSha);
|
|
@@ -41665,22 +41679,31 @@ async function resolveRunId(opts) {
|
|
|
41665
41679
|
}
|
|
41666
41680
|
return { runId: `r_${ulid()}`, resumed: false };
|
|
41667
41681
|
}
|
|
41668
|
-
async function
|
|
41682
|
+
async function readMarker(outputsDir, canvasPath) {
|
|
41669
41683
|
for (const key of [markerKey(canvasPath), legacyMarkerKey(canvasPath)]) {
|
|
41670
41684
|
try {
|
|
41671
41685
|
const raw = await readFile9(markerFile(outputsDir, key), "utf8");
|
|
41672
41686
|
const parsed = JSON.parse(raw);
|
|
41673
|
-
if (typeof parsed.runId === "string" && parsed.runId.length > 0)
|
|
41687
|
+
if (typeof parsed.runId === "string" && parsed.runId.length > 0) {
|
|
41688
|
+
return { runId: parsed.runId, ...Number.isInteger(parsed.pid) ? { pid: parsed.pid } : {} };
|
|
41689
|
+
}
|
|
41674
41690
|
} catch {
|
|
41675
41691
|
}
|
|
41676
41692
|
}
|
|
41677
41693
|
return null;
|
|
41678
41694
|
}
|
|
41695
|
+
function isRenderProcess(pid) {
|
|
41696
|
+
try {
|
|
41697
|
+
return readFileSync14(`/proc/${pid}/cmdline`, "utf8").includes("canvas");
|
|
41698
|
+
} catch {
|
|
41699
|
+
return false;
|
|
41700
|
+
}
|
|
41701
|
+
}
|
|
41679
41702
|
async function markRunInFlight(outputsDir, canvasPath, runId) {
|
|
41680
41703
|
try {
|
|
41681
41704
|
const file = markerFile(outputsDir, markerKey(canvasPath));
|
|
41682
41705
|
await mkdir4(path13.dirname(file), { recursive: true });
|
|
41683
|
-
await writeFile6(file, JSON.stringify({ runId, canvasPath: path13.resolve(canvasPath), startedAt: Date.now() }));
|
|
41706
|
+
await writeFile6(file, JSON.stringify({ runId, pid: process.pid, canvasPath: path13.resolve(canvasPath), startedAt: Date.now() }));
|
|
41684
41707
|
} catch {
|
|
41685
41708
|
}
|
|
41686
41709
|
}
|
|
@@ -42636,13 +42659,31 @@ ${describeRewrites(healed.rewrites)}
|
|
|
42636
42659
|
const creativeSlug = creativeSlugFromCanvasPath(filePath) ?? void 0;
|
|
42637
42660
|
const client = opts.record === false ? null : buildBackendClient();
|
|
42638
42661
|
const outputsDir = opts.outputsDir ? path16.resolve(opts.outputsDir) : canvasRoot;
|
|
42639
|
-
const { runId, resumed, source, concurrentRunId } = await resolveRunId({
|
|
42662
|
+
const { runId, resumed, source, concurrentRunId, rendering } = await resolveRunId({
|
|
42640
42663
|
explicitRunId: opts.runId,
|
|
42641
42664
|
fresh: opts.fresh === true,
|
|
42642
42665
|
outputsDir,
|
|
42643
42666
|
canvasPath: filePath,
|
|
42644
42667
|
remote: client && creativeSlug ? { creativeSlug, canvasSha, getActiveRun: (slug, sha) => client.getActiveRun(slug, sha) } : void 0
|
|
42645
42668
|
});
|
|
42669
|
+
if (rendering) {
|
|
42670
|
+
process.stderr.write(
|
|
42671
|
+
`${JSON.stringify(
|
|
42672
|
+
{
|
|
42673
|
+
ok: false,
|
|
42674
|
+
error: {
|
|
42675
|
+
code: "CONFLICT",
|
|
42676
|
+
message: `This canvas is already rendering in another process (run ${rendering.runId}, pid ${rendering.pid}).`,
|
|
42677
|
+
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."
|
|
42678
|
+
}
|
|
42679
|
+
},
|
|
42680
|
+
null,
|
|
42681
|
+
2
|
|
42682
|
+
)}
|
|
42683
|
+
`
|
|
42684
|
+
);
|
|
42685
|
+
process.exit(2);
|
|
42686
|
+
}
|
|
42646
42687
|
if (resumed) {
|
|
42647
42688
|
process.stdout.write(
|
|
42648
42689
|
`[resume] continuing interrupted run ${runId}${source === "remote" ? " (adopted from run history)" : ""} \u2014 in-flight jobs re-attach, cached nodes skip
|
|
@@ -49102,11 +49143,11 @@ var addSideEffectCommand = defineCommand125({
|
|
|
49102
49143
|
});
|
|
49103
49144
|
|
|
49104
49145
|
// src/commands/flows/map.ts
|
|
49105
|
-
import { readFileSync as
|
|
49146
|
+
import { readFileSync as readFileSync16 } from "fs";
|
|
49106
49147
|
import { defineCommand as defineCommand126 } from "citty";
|
|
49107
49148
|
|
|
49108
49149
|
// src/commands/flows/value-expression.ts
|
|
49109
|
-
import { existsSync as existsSync6, readFileSync as
|
|
49150
|
+
import { existsSync as existsSync6, readFileSync as readFileSync15 } from "fs";
|
|
49110
49151
|
import { join as join4 } from "path";
|
|
49111
49152
|
var PREFIXES2 = ["field", "tracking", "global", "code"];
|
|
49112
49153
|
function splitParts(raw) {
|
|
@@ -49193,7 +49234,7 @@ function trackingFieldIds() {
|
|
|
49193
49234
|
const path48 = join4(flowsDir(), "..", "tracking.ts");
|
|
49194
49235
|
if (!existsSync6(path48)) return null;
|
|
49195
49236
|
try {
|
|
49196
|
-
const source =
|
|
49237
|
+
const source = readFileSync15(path48, "utf-8");
|
|
49197
49238
|
const block2 = source.match(/TRACKING_FIELD_IDS\s*=\s*\[([\s\S]*?)\]\s*as const/)?.[1];
|
|
49198
49239
|
if (!block2) return null;
|
|
49199
49240
|
const ids = [...block2.matchAll(/"(tracking\.[a-z0-9_]+)"/g)].map((match) => match[1]);
|
|
@@ -49770,7 +49811,7 @@ function specsFromFile(parsed) {
|
|
|
49770
49811
|
function readSpecFile(path48) {
|
|
49771
49812
|
let raw;
|
|
49772
49813
|
try {
|
|
49773
|
-
raw = path48 === "-" ?
|
|
49814
|
+
raw = path48 === "-" ? readFileSync16(0, "utf-8") : readFileSync16(path48, "utf-8");
|
|
49774
49815
|
} catch (error) {
|
|
49775
49816
|
refuse(
|
|
49776
49817
|
`Could not read ${path48 === "-" ? "the mapping from stdin" : `"${path48}"`}: ${error instanceof Error ? error.message : String(error)}`
|
|
@@ -50469,7 +50510,7 @@ Full guide: __tooling__/docs/tools/baker/flows.md`
|
|
|
50469
50510
|
});
|
|
50470
50511
|
|
|
50471
50512
|
// src/commands/funnel/index.ts
|
|
50472
|
-
import { readFileSync as
|
|
50513
|
+
import { readFileSync as readFileSync17 } from "fs";
|
|
50473
50514
|
import { defineCommand as defineCommand130 } from "citty";
|
|
50474
50515
|
|
|
50475
50516
|
// src/commands/funnel/formMoments.ts
|
|
@@ -51265,7 +51306,7 @@ function workspaceForms() {
|
|
|
51265
51306
|
const forms = [];
|
|
51266
51307
|
for (const slug of listFlowSlugs()) {
|
|
51267
51308
|
try {
|
|
51268
|
-
forms.push({ slug, tree: JSON.parse(
|
|
51309
|
+
forms.push({ slug, tree: JSON.parse(readFileSync17(flowDataPath(slug), "utf-8")) });
|
|
51269
51310
|
} catch {
|
|
51270
51311
|
}
|
|
51271
51312
|
}
|
|
@@ -51400,7 +51441,7 @@ Examples:
|
|
|
51400
51441
|
import { defineCommand as defineCommand132 } from "citty";
|
|
51401
51442
|
|
|
51402
51443
|
// src/commands/ga4/shared.ts
|
|
51403
|
-
import { readFileSync as
|
|
51444
|
+
import { readFileSync as readFileSync18 } from "fs";
|
|
51404
51445
|
function failValidation3(message) {
|
|
51405
51446
|
writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message } });
|
|
51406
51447
|
process.exit(1);
|
|
@@ -51416,7 +51457,7 @@ function requireTarget5(args5, entity) {
|
|
|
51416
51457
|
function readJsonSource(args5, flag) {
|
|
51417
51458
|
const inline = args5[flag];
|
|
51418
51459
|
const file = args5.file;
|
|
51419
|
-
const raw = typeof file === "string" && file.length > 0 ?
|
|
51460
|
+
const raw = typeof file === "string" && file.length > 0 ? readFileSync18(file, "utf8") : typeof inline === "string" && inline.length > 0 ? inline : void 0;
|
|
51420
51461
|
if (raw === void 0) {
|
|
51421
51462
|
failValidation3(`pass --${flag} with inline JSON or --file with a path to a JSON file`);
|
|
51422
51463
|
}
|
|
@@ -51767,7 +51808,7 @@ Examples:
|
|
|
51767
51808
|
});
|
|
51768
51809
|
|
|
51769
51810
|
// src/commands/ga4/query.ts
|
|
51770
|
-
import { appendFileSync as appendFileSync2, existsSync as existsSync7, readFileSync as
|
|
51811
|
+
import { appendFileSync as appendFileSync2, existsSync as existsSync7, readFileSync as readFileSync19, writeFileSync as writeFileSync4 } from "fs";
|
|
51771
51812
|
import { resolve as resolve2 } from "path";
|
|
51772
51813
|
import { defineCommand as defineCommand135 } from "citty";
|
|
51773
51814
|
|
|
@@ -51858,7 +51899,7 @@ function writeRowsToFile2(filePath, rows, append) {
|
|
|
51858
51899
|
writeFileSync4(filePath, content, "utf-8");
|
|
51859
51900
|
}
|
|
51860
51901
|
} else if (append && existsSync7(filePath)) {
|
|
51861
|
-
const existing = JSON.parse(
|
|
51902
|
+
const existing = JSON.parse(readFileSync19(filePath, "utf-8"));
|
|
51862
51903
|
writeFileSync4(filePath, JSON.stringify([...existing, ...rows], null, 2), "utf-8");
|
|
51863
51904
|
} else {
|
|
51864
51905
|
writeFileSync4(filePath, JSON.stringify(rows, null, 2), "utf-8");
|
|
@@ -52710,7 +52751,7 @@ Full guide: __tooling__/docs/tools/baker/ga4.md`
|
|
|
52710
52751
|
import { defineCommand as defineCommand141 } from "citty";
|
|
52711
52752
|
|
|
52712
52753
|
// src/commands/gsc/query.ts
|
|
52713
|
-
import { appendFileSync as appendFileSync3, existsSync as existsSync8, readFileSync as
|
|
52754
|
+
import { appendFileSync as appendFileSync3, existsSync as existsSync8, readFileSync as readFileSync20, writeFileSync as writeFileSync5 } from "fs";
|
|
52714
52755
|
import { resolve as resolve3 } from "path";
|
|
52715
52756
|
import { defineCommand as defineCommand138 } from "citty";
|
|
52716
52757
|
|
|
@@ -52858,7 +52899,7 @@ function writeRowsToFile3(filePath, rows, append) {
|
|
|
52858
52899
|
writeFileSync5(filePath, content, "utf-8");
|
|
52859
52900
|
}
|
|
52860
52901
|
} else if (append && existsSync8(filePath)) {
|
|
52861
|
-
const existing = JSON.parse(
|
|
52902
|
+
const existing = JSON.parse(readFileSync20(filePath, "utf-8"));
|
|
52862
52903
|
writeFileSync5(filePath, JSON.stringify([...existing, ...rows], null, 2), "utf-8");
|
|
52863
52904
|
} else {
|
|
52864
52905
|
writeFileSync5(filePath, JSON.stringify(rows, null, 2), "utf-8");
|
|
@@ -66583,7 +66624,7 @@ import { defineCommand as defineCommand221 } from "citty";
|
|
|
66583
66624
|
import { defineCommand as defineCommand218 } from "citty";
|
|
66584
66625
|
|
|
66585
66626
|
// src/commands/tag-manager/shared.ts
|
|
66586
|
-
import { readFileSync as
|
|
66627
|
+
import { readFileSync as readFileSync21 } from "fs";
|
|
66587
66628
|
function failValidation5(message) {
|
|
66588
66629
|
writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message } });
|
|
66589
66630
|
process.exit(1);
|
|
@@ -66599,7 +66640,7 @@ function requireTarget6(args5, entity) {
|
|
|
66599
66640
|
function loadJsonArg2(args5, flag = "json") {
|
|
66600
66641
|
const inline = args5[flag];
|
|
66601
66642
|
const file = args5.file;
|
|
66602
|
-
const raw = typeof file === "string" && file.length > 0 ?
|
|
66643
|
+
const raw = typeof file === "string" && file.length > 0 ? readFileSync21(file, "utf8") : typeof inline === "string" && inline.length > 0 ? inline : void 0;
|
|
66603
66644
|
if (raw === void 0) {
|
|
66604
66645
|
failValidation5(`pass --${flag} with inline JSON or --file with a path to a JSON file`);
|
|
66605
66646
|
}
|
|
@@ -69747,7 +69788,7 @@ Full guide: __tooling__/docs/tools/baker/winning-ads.md`
|
|
|
69747
69788
|
});
|
|
69748
69789
|
|
|
69749
69790
|
// src/version.ts
|
|
69750
|
-
import { readFileSync as
|
|
69791
|
+
import { readFileSync as readFileSync22 } from "fs";
|
|
69751
69792
|
function packageJsonUrl() {
|
|
69752
69793
|
return new URL("../package.json", import.meta.url);
|
|
69753
69794
|
}
|
|
@@ -69759,7 +69800,7 @@ function parsePackageVersion(raw) {
|
|
|
69759
69800
|
throw new Error("Invalid CLI package.json: missing version");
|
|
69760
69801
|
}
|
|
69761
69802
|
function getCliVersion() {
|
|
69762
|
-
return parsePackageVersion(
|
|
69803
|
+
return parsePackageVersion(readFileSync22(packageJsonUrl(), "utf8"));
|
|
69763
69804
|
}
|
|
69764
69805
|
|
|
69765
69806
|
// src/cli.ts
|