@koda-sl/baker-cli 0.15.0 → 0.16.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 +167 -3
- package/dist/cli.js +5 -1
- package/dist/cli.js.map +1 -1
- package/dist/commands/ads/google/accounts.d.ts.map +1 -1
- package/dist/commands/ads/google/accounts.js +7 -4
- package/dist/commands/ads/google/accounts.js.map +1 -1
- package/dist/commands/ads/output.d.ts +1 -0
- package/dist/commands/ads/output.d.ts.map +1 -1
- package/dist/commands/ads/output.js +18 -15
- package/dist/commands/ads/output.js.map +1 -1
- package/dist/commands/ga4/audit.d.ts +13 -0
- package/dist/commands/ga4/audit.d.ts.map +1 -0
- package/dist/commands/ga4/audit.js +67 -0
- package/dist/commands/ga4/audit.js.map +1 -0
- package/dist/commands/ga4/index.d.ts +2 -0
- package/dist/commands/ga4/index.d.ts.map +1 -0
- package/dist/commands/ga4/index.js +26 -0
- package/dist/commands/ga4/index.js.map +1 -0
- package/dist/commands/ga4/presets.d.ts +8 -0
- package/dist/commands/ga4/presets.d.ts.map +1 -0
- package/dist/commands/ga4/presets.js +33 -0
- package/dist/commands/ga4/presets.js.map +1 -0
- package/dist/commands/ga4/properties.d.ts +14 -0
- package/dist/commands/ga4/properties.d.ts.map +1 -0
- package/dist/commands/ga4/properties.js +61 -0
- package/dist/commands/ga4/properties.js.map +1 -0
- package/dist/commands/ga4/query.d.ts +69 -0
- package/dist/commands/ga4/query.d.ts.map +1 -0
- package/dist/commands/ga4/query.js +184 -0
- package/dist/commands/ga4/query.js.map +1 -0
- package/dist/commands/ga4/resolve.d.ts +2 -0
- package/dist/commands/ga4/resolve.d.ts.map +1 -0
- package/dist/commands/ga4/resolve.js +57 -0
- package/dist/commands/ga4/resolve.js.map +1 -0
- package/dist/commands/gsc/index.d.ts +2 -0
- package/dist/commands/gsc/index.d.ts.map +1 -0
- package/dist/commands/gsc/index.js +26 -0
- package/dist/commands/gsc/index.js.map +1 -0
- package/dist/commands/gsc/presets.d.ts +9 -0
- package/dist/commands/gsc/presets.d.ts.map +1 -0
- package/dist/commands/gsc/presets.js +34 -0
- package/dist/commands/gsc/presets.js.map +1 -0
- package/dist/commands/gsc/query.d.ts +79 -0
- package/dist/commands/gsc/query.d.ts.map +1 -0
- package/dist/commands/gsc/query.js +196 -0
- package/dist/commands/gsc/query.js.map +1 -0
- package/dist/commands/gsc/resolve.d.ts +2 -0
- package/dist/commands/gsc/resolve.d.ts.map +1 -0
- package/dist/commands/gsc/resolve.js +57 -0
- package/dist/commands/gsc/resolve.js.map +1 -0
- package/dist/commands/gsc/sitemaps.d.ts +19 -0
- package/dist/commands/gsc/sitemaps.d.ts.map +1 -0
- package/dist/commands/gsc/sitemaps.js +65 -0
- package/dist/commands/gsc/sitemaps.js.map +1 -0
- package/dist/commands/gsc/sites.d.ts +14 -0
- package/dist/commands/gsc/sites.d.ts.map +1 -0
- package/dist/commands/gsc/sites.js +61 -0
- package/dist/commands/gsc/sites.js.map +1 -0
- package/dist/env.d.ts +2 -0
- package/dist/env.d.ts.map +1 -1
- package/dist/env.js +2 -0
- package/dist/env.js.map +1 -1
- package/dist/error-handler.d.ts +8 -0
- package/dist/error-handler.d.ts.map +1 -0
- package/dist/error-handler.js +37 -0
- package/dist/error-handler.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -20,11 +20,19 @@ export BAKER_API_URL="https://your-baker-instance.convex.site"
|
|
|
20
20
|
|
|
21
21
|
# Optional: default customer ID for Google Ads commands
|
|
22
22
|
export BAKER_GOOGLE_ADS_CUSTOMER_ID="1234567890"
|
|
23
|
+
|
|
24
|
+
# Optional: default GA4 property ID
|
|
25
|
+
export BAKER_GA4_PROPERTY_ID="properties/123456789"
|
|
26
|
+
|
|
27
|
+
# Optional: default GSC site URL
|
|
28
|
+
export BAKER_GSC_SITE_URL="https://example.com/"
|
|
23
29
|
```
|
|
24
30
|
|
|
25
31
|
- `BAKER_API_KEY` must start with `bk_`
|
|
26
32
|
- `BAKER_API_URL` is your Convex site URL
|
|
27
33
|
- `BAKER_GOOGLE_ADS_CUSTOMER_ID` — default Google Ads customer ID (10 digits). Used when `--customer-id` is not passed. If neither is set and the account has exactly one Google Ads customer, it is auto-selected.
|
|
34
|
+
- `BAKER_GA4_PROPERTY_ID` — default GA4 property ID. Used when `--property-id` is not passed. If neither is set and exactly one property is connected, it is auto-selected.
|
|
35
|
+
- `BAKER_GSC_SITE_URL` — default GSC site URL. Used when `--site-url` is not passed. If neither is set and exactly one site is verified, it is auto-selected.
|
|
28
36
|
|
|
29
37
|
## Output Format
|
|
30
38
|
|
|
@@ -421,6 +429,162 @@ All errors include a `fix` object with `action`, `correctedCommand` (when applic
|
|
|
421
429
|
|
|
422
430
|
---
|
|
423
431
|
|
|
432
|
+
### Google Analytics 4 (`baker ga4`)
|
|
433
|
+
|
|
434
|
+
GA4 commands for multi-channel audits. Playbook-aligned presets, property health audits, and free-form Data API queries.
|
|
435
|
+
|
|
436
|
+
---
|
|
437
|
+
|
|
438
|
+
### `baker ga4 properties`
|
|
439
|
+
|
|
440
|
+
List accessible GA4 properties. Run this first to find property IDs.
|
|
441
|
+
|
|
442
|
+
```bash
|
|
443
|
+
baker ga4 properties
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
---
|
|
447
|
+
|
|
448
|
+
### `baker ga4 audit`
|
|
449
|
+
|
|
450
|
+
Run all GA4 admin health checks at once. Checks data retention, Google Ads linkage, phantom conversions, audience defaults, data streams, and attribution settings.
|
|
451
|
+
|
|
452
|
+
```bash
|
|
453
|
+
baker ga4 audit
|
|
454
|
+
baker ga4 audit --property-id properties/123456789
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
Returns raw config data plus playbook-aligned warnings:
|
|
458
|
+
|
|
459
|
+
```json
|
|
460
|
+
{
|
|
461
|
+
"ok": true,
|
|
462
|
+
"data": { "property": {...}, "dataRetention": {...}, "conversionEvents": [...] },
|
|
463
|
+
"warnings": [
|
|
464
|
+
{ "code": "SHORT_RETENTION", "message": "Data retention is TWO_MONTHS — should be FOURTEEN_MONTHS" },
|
|
465
|
+
{ "code": "PHANTOM_CONVERSION", "message": "\"page_view\" is marked as a conversion event" }
|
|
466
|
+
]
|
|
467
|
+
}
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
---
|
|
471
|
+
|
|
472
|
+
### `baker ga4 query`
|
|
473
|
+
|
|
474
|
+
Run GA4 Data API reports. Presets are the primary interface; free-form dimensions/metrics is the escape hatch.
|
|
475
|
+
|
|
476
|
+
```bash
|
|
477
|
+
# Playbook presets
|
|
478
|
+
baker ga4 query --preset tracking-health
|
|
479
|
+
baker ga4 query --preset lp-performance --days 14
|
|
480
|
+
baker ga4 query --preset funnel-leakage --out funnel.csv
|
|
481
|
+
baker ga4 query --list-presets
|
|
482
|
+
|
|
483
|
+
# Free-form
|
|
484
|
+
baker ga4 query --dimensions "date,sessionSourceMedium" --metrics "sessions,conversions"
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
**Flags:**
|
|
488
|
+
|
|
489
|
+
| Flag | Description |
|
|
490
|
+
|------|-------------|
|
|
491
|
+
| `--preset` | Named preset (see below) |
|
|
492
|
+
| `--dimensions` | Comma-separated GA4 dimension names |
|
|
493
|
+
| `--metrics` | Comma-separated GA4 metric names |
|
|
494
|
+
| `--days` | Lookback window in days (default: 30) |
|
|
495
|
+
| `--start-date` | Start date (YYYY-MM-DD or GA4 relative like "30daysAgo") |
|
|
496
|
+
| `--end-date` | End date (YYYY-MM-DD or "yesterday") |
|
|
497
|
+
| `--limit` | Max rows (default: 1000) |
|
|
498
|
+
| `--property-id` | GA4 property ID (auto-resolved if not provided) |
|
|
499
|
+
| `--out` | Write to file (.csv, .jsonl, .json) |
|
|
500
|
+
| `--output` | Format: json\|csv\|jsonl\|md |
|
|
501
|
+
| `--no-cache` | Skip cache |
|
|
502
|
+
|
|
503
|
+
**Presets:**
|
|
504
|
+
|
|
505
|
+
| Preset | Playbook | What it answers |
|
|
506
|
+
|--------|----------|-----------------|
|
|
507
|
+
| `tracking-health` | [07] Discrepancy | Is GA4 tracking matching GAds? (>20% gap = broken) |
|
|
508
|
+
| `lp-performance` | [06] LP Diagnostic | Which LPs have bad UX? (<10s = message mismatch) |
|
|
509
|
+
| `traffic-quality` | [06] Warm Traffic | Is Smart Bidding cherry-picking returning users? |
|
|
510
|
+
| `funnel-leakage` | [06] Funnel Analysis | Where do users drop off in the funnel? |
|
|
511
|
+
| `first-touch` | First-Touch | What channels actually acquire new users? |
|
|
512
|
+
| `traffic-overview` | General | General traffic trends |
|
|
513
|
+
|
|
514
|
+
---
|
|
515
|
+
|
|
516
|
+
### Google Search Console (`baker gsc`)
|
|
517
|
+
|
|
518
|
+
GSC commands for PPC-SEO arbitrage, brand halo analysis, and negative keyword discovery.
|
|
519
|
+
|
|
520
|
+
---
|
|
521
|
+
|
|
522
|
+
### `baker gsc sites`
|
|
523
|
+
|
|
524
|
+
List verified Search Console sites.
|
|
525
|
+
|
|
526
|
+
```bash
|
|
527
|
+
baker gsc sites
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
---
|
|
531
|
+
|
|
532
|
+
### `baker gsc query`
|
|
533
|
+
|
|
534
|
+
Run Search Analytics queries. Presets are the primary interface.
|
|
535
|
+
|
|
536
|
+
```bash
|
|
537
|
+
# Playbook presets
|
|
538
|
+
baker gsc query --preset cannibalization
|
|
539
|
+
baker gsc query --preset brand-halo --brand "Acme" --days 90
|
|
540
|
+
baker gsc query --preset negative-keywords --out negatives.csv
|
|
541
|
+
baker gsc query --list-presets
|
|
542
|
+
|
|
543
|
+
# Free-form
|
|
544
|
+
baker gsc query --dimensions "query,page" --days 28
|
|
545
|
+
baker gsc query --dimensions "query" --row-limit 25000 --out keywords.csv
|
|
546
|
+
```
|
|
547
|
+
|
|
548
|
+
**Flags:**
|
|
549
|
+
|
|
550
|
+
| Flag | Description |
|
|
551
|
+
|------|-------------|
|
|
552
|
+
| `--preset` | Named preset (see below) |
|
|
553
|
+
| `--brand` | Brand name (required for brand-halo preset) |
|
|
554
|
+
| `--dimensions` | Comma-separated: query, page, country, device, date |
|
|
555
|
+
| `--days` | Lookback window (default: 28) |
|
|
556
|
+
| `--start-date` / `--end-date` | Explicit date range |
|
|
557
|
+
| `--row-limit` | Max rows (default: 1000, max: 25000) |
|
|
558
|
+
| `--type` | Search type: web\|image\|video\|news\|discover |
|
|
559
|
+
| `--site-url` | Site URL (auto-resolved if not provided) |
|
|
560
|
+
| `--out` | Write to file |
|
|
561
|
+
| `--output` | Format: json\|csv\|jsonl\|md |
|
|
562
|
+
| `--no-cache` | Skip cache |
|
|
563
|
+
|
|
564
|
+
**Presets:**
|
|
565
|
+
|
|
566
|
+
| Preset | Playbook | What it answers |
|
|
567
|
+
|--------|----------|-----------------|
|
|
568
|
+
| `cannibalization` | [05] PPC-SEO Arbitrage | Which queries rank #1-2 organically where you also pay? |
|
|
569
|
+
| `missed-revenue` | [05] Opportunity | High-impression queries with no PPC coverage? |
|
|
570
|
+
| `brand-halo` | [21] YouTube/DG ROI | Is upper-funnel spend driving brand searches? |
|
|
571
|
+
| `negative-keywords` | Negative Discovery | Queries to add as negative keywords |
|
|
572
|
+
| `top-pages` | General | Top performing pages |
|
|
573
|
+
| `top-queries` | General | Top search queries |
|
|
574
|
+
|
|
575
|
+
---
|
|
576
|
+
|
|
577
|
+
### `baker gsc sitemaps`
|
|
578
|
+
|
|
579
|
+
Check sitemap health for a site.
|
|
580
|
+
|
|
581
|
+
```bash
|
|
582
|
+
baker gsc sitemaps
|
|
583
|
+
baker gsc sitemaps --site-url "https://example.com/"
|
|
584
|
+
```
|
|
585
|
+
|
|
586
|
+
---
|
|
587
|
+
|
|
424
588
|
### Competitive Intelligence (`baker research`)
|
|
425
589
|
|
|
426
590
|
Market and competitor research powered by DataForSEO. Shows who's competing for keywords, search intent classification, competitor keyword strategies, keyword gaps, and landing page performance.
|
|
@@ -917,9 +1081,9 @@ For machine-readable introspection, use `baker schema` (see below).
|
|
|
917
1081
|
|
|
918
1082
|
This CLI is designed for AI agent consumption. Key patterns:
|
|
919
1083
|
|
|
920
|
-
1. **Start with `baker ads google accounts
|
|
921
|
-
2. **Use
|
|
922
|
-
3. **
|
|
1084
|
+
1. **Start with account discovery** — `baker ads google accounts`, `baker ga4 properties`, `baker gsc sites`
|
|
1085
|
+
2. **Use presets** (`--preset campaign-performance`, `--preset tracking-health`, `--preset cannibalization`) — saves tokens, answers playbook questions
|
|
1086
|
+
3. **Run `--list-presets`** on query commands to see available templates
|
|
923
1087
|
4. **Read the `fields` object** in responses to understand what each column means
|
|
924
1088
|
5. **Check `fix.correctedCommand`** on errors — copy-paste it to retry
|
|
925
1089
|
6. **Use `--all --out file.csv`** for large exports to avoid filling context window
|
package/dist/cli.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { defineCommand, runMain } from "citty";
|
|
3
3
|
import { adsCommand } from "./commands/ads/index.js";
|
|
4
|
+
import { ga4Command } from "./commands/ga4/index.js";
|
|
5
|
+
import { gscCommand } from "./commands/gsc/index.js";
|
|
4
6
|
import { imagesCommand } from "./commands/images/index.js";
|
|
5
7
|
import { researchCommand } from "./commands/research/index.js";
|
|
6
8
|
import { schemaCommand } from "./commands/schema.js";
|
|
@@ -9,7 +11,7 @@ import { videosCommand } from "./commands/videos/index.js";
|
|
|
9
11
|
const main = defineCommand({
|
|
10
12
|
meta: {
|
|
11
13
|
name: "baker",
|
|
12
|
-
version: "0.
|
|
14
|
+
version: "0.16.0",
|
|
13
15
|
description: `AI-agent CLI for finding and managing images, videos, testimonials, and ad platform data in Baker.
|
|
14
16
|
|
|
15
17
|
Auth: Set BAKER_API_KEY (starts with bk_) and BAKER_API_URL environment variables.
|
|
@@ -19,6 +21,8 @@ Introspection: Run 'baker schema <command>' to inspect argument schemas.`,
|
|
|
19
21
|
},
|
|
20
22
|
subCommands: {
|
|
21
23
|
ads: adsCommand,
|
|
24
|
+
ga4: ga4Command,
|
|
25
|
+
gsc: gscCommand,
|
|
22
26
|
research: researchCommand,
|
|
23
27
|
images: imagesCommand,
|
|
24
28
|
videos: videosCommand,
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AACvE,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAE3D,MAAM,IAAI,GAAG,aAAa,CAAC;IACzB,IAAI,EAAE;QACJ,IAAI,EAAE,OAAO;QACb,OAAO,EAAE,QAAQ;QACjB,WAAW,EAAE;;;;;yEAKwD;KACtE;IACD,WAAW,EAAE;QACX,GAAG,EAAE,UAAU;QACf,QAAQ,EAAE,eAAe;QACzB,MAAM,EAAE,aAAa;QACrB,MAAM,EAAE,aAAa;QACrB,YAAY,EAAE,mBAAmB;QACjC,MAAM,EAAE,aAAa;KACtB;CACF,CAAC,CAAC;AAEH,OAAO,CAAC,IAAI,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AACvE,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAE3D,MAAM,IAAI,GAAG,aAAa,CAAC;IACzB,IAAI,EAAE;QACJ,IAAI,EAAE,OAAO;QACb,OAAO,EAAE,QAAQ;QACjB,WAAW,EAAE;;;;;yEAKwD;KACtE;IACD,WAAW,EAAE;QACX,GAAG,EAAE,UAAU;QACf,GAAG,EAAE,UAAU;QACf,GAAG,EAAE,UAAU;QACf,QAAQ,EAAE,eAAe;QACzB,MAAM,EAAE,aAAa;QACrB,MAAM,EAAE,aAAa;QACrB,YAAY,EAAE,mBAAmB;QACjC,MAAM,EAAE,aAAa;KACtB;CACF,CAAC,CAAC;AAEH,OAAO,CAAC,IAAI,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"accounts.d.ts","sourceRoot":"","sources":["../../../../src/commands/ads/google/accounts.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"accounts.d.ts","sourceRoot":"","sources":["../../../../src/commands/ads/google/accounts.ts"],"names":[],"mappings":"AAkDA,eAAO,MAAM,eAAe;;;;;;;;;;;;EAuC1B,CAAC"}
|
|
@@ -10,17 +10,20 @@ registerSchema({
|
|
|
10
10
|
"no-cache": { type: "boolean", description: "Skip cache, hit API directly", required: false },
|
|
11
11
|
},
|
|
12
12
|
});
|
|
13
|
+
import { handleConnectionError } from "../../../error-handler.js";
|
|
13
14
|
function handleAccountsError(err) {
|
|
14
15
|
if (err instanceof ApiError) {
|
|
15
|
-
|
|
16
|
+
if (err.code === "UNAUTHORIZED" || err.code === "NOT_FOUND") {
|
|
17
|
+
handleConnectionError("google_ads", err.message);
|
|
18
|
+
}
|
|
16
19
|
const envelope = {
|
|
17
20
|
ok: false,
|
|
18
21
|
error: {
|
|
19
|
-
code:
|
|
22
|
+
code: err.code,
|
|
20
23
|
message: err.message,
|
|
21
24
|
fix: {
|
|
22
|
-
action:
|
|
23
|
-
explanation:
|
|
25
|
+
action: "reject",
|
|
26
|
+
explanation: err.message,
|
|
24
27
|
},
|
|
25
28
|
retryable: false,
|
|
26
29
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"accounts.js","sourceRoot":"","sources":["../../../../src/commands/ads/google/accounts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAG5D,cAAc,CAAC;IACb,OAAO,EAAE,qBAAqB;IAC9B,WAAW,EACT,iPAAiP;IACnP,IAAI,EAAE;QACJ,UAAU,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,8BAA8B,EAAE,QAAQ,EAAE,KAAK,EAAE;KAC9F;CACF,CAAC,CAAC;AAUH,SAAS,mBAAmB,CAAC,GAAY;IACvC,IAAI,GAAG,YAAY,QAAQ,EAAE,CAAC;QAC5B,
|
|
1
|
+
{"version":3,"file":"accounts.js","sourceRoot":"","sources":["../../../../src/commands/ads/google/accounts.ts"],"names":[],"mappings":"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"}
|
|
@@ -14,6 +14,7 @@ type AdsOutput = AdsSuccessEnvelope<unknown> | AdsErrorEnvelope | AdsFileSummary
|
|
|
14
14
|
};
|
|
15
15
|
};
|
|
16
16
|
export declare function writeAdsJson(envelope: AdsOutput): void;
|
|
17
|
+
export declare function writeJsonEnvelope(envelope: Record<string, unknown>): void;
|
|
17
18
|
export declare function toCsvRow(values: string[]): string;
|
|
18
19
|
export declare function writeAdsOutput(data: Array<Record<string, unknown>>, format: string, fields?: string[]): void;
|
|
19
20
|
export declare function resolveCustomerId(args: Record<string, unknown>): Promise<string>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../../../src/commands/ads/output.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEzD,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAEvF,KAAK,SAAS,GACV,kBAAkB,CAAC,OAAO,CAAC,GAC3B,gBAAgB,GAChB,cAAc,GACd;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,OAAO,CAAC;IAAC,aAAa,CAAC,EAAE,YAAY,CAAC;IAAC,MAAM,CAAC,EAAE,IAAI,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GACzG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAAC;AAE5D,wBAAgB,YAAY,CAAC,QAAQ,EAAE,SAAS,GAAG,IAAI,CAEtD;AAED,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CASjD;AAqCD,wBAAgB,cAAc,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAc5G;
|
|
1
|
+
{"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../../../src/commands/ads/output.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEzD,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAEvF,KAAK,SAAS,GACV,kBAAkB,CAAC,OAAO,CAAC,GAC3B,gBAAgB,GAChB,cAAc,GACd;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,OAAO,CAAC;IAAC,aAAa,CAAC,EAAE,YAAY,CAAC;IAAC,MAAM,CAAC,EAAE,IAAI,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GACzG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAAC;AAE5D,wBAAgB,YAAY,CAAC,QAAQ,EAAE,SAAS,GAAG,IAAI,CAEtD;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAEzE;AAED,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CASjD;AAqCD,wBAAgB,cAAc,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAc5G;AAyBD,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAkDtF"}
|
|
@@ -4,6 +4,9 @@ import { cacheGet, cacheSet } from "./cache.js";
|
|
|
4
4
|
export function writeAdsJson(envelope) {
|
|
5
5
|
process.stdout.write(`${JSON.stringify(envelope, null, 2)}\n`);
|
|
6
6
|
}
|
|
7
|
+
export function writeJsonEnvelope(envelope) {
|
|
8
|
+
process.stdout.write(`${JSON.stringify(envelope, null, 2)}\n`);
|
|
9
|
+
}
|
|
7
10
|
export function toCsvRow(values) {
|
|
8
11
|
return values
|
|
9
12
|
.map((v) => {
|
|
@@ -62,14 +65,20 @@ export function writeAdsOutput(data, format, fields) {
|
|
|
62
65
|
writeAdsJson({ ok: true, data });
|
|
63
66
|
}
|
|
64
67
|
}
|
|
65
|
-
async function fetchAccounts() {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
68
|
+
async function fetchAccounts(useCache = true) {
|
|
69
|
+
if (useCache) {
|
|
70
|
+
const cached = cacheGet("accounts", "list");
|
|
71
|
+
if (cached)
|
|
72
|
+
return cached.data;
|
|
73
|
+
}
|
|
74
|
+
const params = !useCache ? { "skip-cache": "true" } : undefined;
|
|
75
|
+
const data = await apiGet("/api/ads/google/accounts", params);
|
|
76
|
+
if (useCache) {
|
|
77
|
+
cacheSet("accounts", "list", data, 60 * 60 * 1000);
|
|
78
|
+
}
|
|
71
79
|
return data;
|
|
72
80
|
}
|
|
81
|
+
import { handleConnectionError } from "../../error-handler.js";
|
|
73
82
|
export async function resolveCustomerId(args) {
|
|
74
83
|
const fromArgs = args["customer-id"];
|
|
75
84
|
const customerId = fromArgs || getEnv().BAKER_GOOGLE_ADS_CUSTOMER_ID;
|
|
@@ -86,22 +95,16 @@ export async function resolveCustomerId(args) {
|
|
|
86
95
|
}
|
|
87
96
|
return customerId;
|
|
88
97
|
}
|
|
98
|
+
const useCache = !args["no-cache"];
|
|
89
99
|
try {
|
|
90
|
-
const accounts = await fetchAccounts();
|
|
100
|
+
const accounts = await fetchAccounts(useCache);
|
|
91
101
|
const [single] = accounts;
|
|
92
102
|
if (accounts.length === 1 && single) {
|
|
93
103
|
process.stderr.write(`Using account "${single.name}" (${single.id})\n`);
|
|
94
104
|
return single.id;
|
|
95
105
|
}
|
|
96
106
|
if (accounts.length === 0) {
|
|
97
|
-
|
|
98
|
-
ok: false,
|
|
99
|
-
error: {
|
|
100
|
-
code: "NO_ACCOUNTS",
|
|
101
|
-
message: "No Google Ads accounts found. Connect Google Ads in dashboard settings first.",
|
|
102
|
-
},
|
|
103
|
-
});
|
|
104
|
-
process.exit(1);
|
|
107
|
+
handleConnectionError("google_ads");
|
|
105
108
|
}
|
|
106
109
|
const list = accounts.map((a) => ` ${a.id} ${a.name}`).join("\n");
|
|
107
110
|
writeAdsJson({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"output.js","sourceRoot":"","sources":["../../../src/commands/ads/output.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"output.js","sourceRoot":"","sources":["../../../src/commands/ads/output.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare const auditCommand: import("citty").CommandDef<{
|
|
2
|
+
readonly "property-id": {
|
|
3
|
+
readonly type: "string";
|
|
4
|
+
readonly description: "GA4 property ID";
|
|
5
|
+
readonly required: false;
|
|
6
|
+
};
|
|
7
|
+
readonly "no-cache": {
|
|
8
|
+
readonly type: "boolean";
|
|
9
|
+
readonly description: "Skip cache";
|
|
10
|
+
readonly required: false;
|
|
11
|
+
};
|
|
12
|
+
}>;
|
|
13
|
+
//# sourceMappingURL=audit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../../../src/commands/ga4/audit.ts"],"names":[],"mappings":"AAiBA,eAAO,MAAM,YAAY;;;;;;;;;;;EAmDvB,CAAC"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { defineCommand } from "citty";
|
|
2
|
+
import { ApiError, apiPost } from "../../client.js";
|
|
3
|
+
import { registerSchema } from "../../schemas.js";
|
|
4
|
+
import { cacheGet, cacheSet } from "../ads/cache.js";
|
|
5
|
+
import { writeJsonEnvelope } from "../ads/output.js";
|
|
6
|
+
import { resolvePropertyId } from "./resolve.js";
|
|
7
|
+
registerSchema({
|
|
8
|
+
command: "ga4.audit",
|
|
9
|
+
description: "Run all GA4 admin health checks at once. Checks data retention, Google Ads linkage, phantom conversions, audience defaults, data streams, and attribution settings. Returns raw data plus playbook-aligned warnings.",
|
|
10
|
+
args: {
|
|
11
|
+
"property-id": { type: "string", description: "GA4 property ID (auto-resolved if not provided)", required: false },
|
|
12
|
+
"no-cache": { type: "boolean", description: "Skip cache, hit API directly", required: false },
|
|
13
|
+
},
|
|
14
|
+
});
|
|
15
|
+
export const auditCommand = defineCommand({
|
|
16
|
+
meta: {
|
|
17
|
+
name: "audit",
|
|
18
|
+
description: `Run all GA4 admin health checks. Returns property config with playbook warnings.
|
|
19
|
+
|
|
20
|
+
Checks:
|
|
21
|
+
- Data retention (should be FOURTEEN_MONTHS)
|
|
22
|
+
- Google Ads linkage (must match audited account)
|
|
23
|
+
- Phantom conversions (page_view, scroll as conversions)
|
|
24
|
+
- Audience membership defaults (30-day B2B traps)
|
|
25
|
+
- Data streams and filters
|
|
26
|
+
- Attribution settings
|
|
27
|
+
|
|
28
|
+
Examples:
|
|
29
|
+
baker ga4 audit
|
|
30
|
+
baker ga4 audit --property-id properties/123456789`,
|
|
31
|
+
},
|
|
32
|
+
args: {
|
|
33
|
+
"property-id": { type: "string", description: "GA4 property ID", required: false },
|
|
34
|
+
"no-cache": { type: "boolean", description: "Skip cache", required: false },
|
|
35
|
+
},
|
|
36
|
+
run: async ({ args }) => {
|
|
37
|
+
const propertyId = await resolvePropertyId(args);
|
|
38
|
+
const useCache = !args["no-cache"];
|
|
39
|
+
const cacheKey = `audit:${propertyId}`;
|
|
40
|
+
if (useCache) {
|
|
41
|
+
const cached = cacheGet("ga4-audit", cacheKey);
|
|
42
|
+
if (cached) {
|
|
43
|
+
writeJsonEnvelope({ ...cached.data, cached: true });
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
try {
|
|
48
|
+
const body = { propertyId };
|
|
49
|
+
if (!useCache)
|
|
50
|
+
body.skipCache = true;
|
|
51
|
+
const data = await apiPost("/api/ga4/audit", body);
|
|
52
|
+
if (useCache) {
|
|
53
|
+
cacheSet("ga4-audit", cacheKey, data, 6 * 60 * 60 * 1000);
|
|
54
|
+
}
|
|
55
|
+
writeJsonEnvelope(data);
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
if (err instanceof ApiError) {
|
|
59
|
+
writeJsonEnvelope({ ok: false, error: { code: err.code, message: err.message } });
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
writeJsonEnvelope({ ok: false, error: { code: "NETWORK_ERROR", message: "Unexpected error" } });
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
//# sourceMappingURL=audit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit.js","sourceRoot":"","sources":["../../../src/commands/ga4/audit.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/ga4/index.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,UAAU,qDAoBrB,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { defineCommand } from "citty";
|
|
2
|
+
import { auditCommand } from "./audit.js";
|
|
3
|
+
import { propertiesCommand } from "./properties.js";
|
|
4
|
+
import { queryCommand } from "./query.js";
|
|
5
|
+
export const ga4Command = defineCommand({
|
|
6
|
+
meta: {
|
|
7
|
+
name: "ga4",
|
|
8
|
+
description: `Google Analytics 4 commands. Audit property config, run playbook-aligned reports.
|
|
9
|
+
|
|
10
|
+
Start here:
|
|
11
|
+
baker ga4 properties — list accessible properties
|
|
12
|
+
baker ga4 query --list-presets — see available report presets
|
|
13
|
+
|
|
14
|
+
Examples:
|
|
15
|
+
baker ga4 audit — full property health check
|
|
16
|
+
baker ga4 query --preset tracking-health — compare GA4 vs GAds data
|
|
17
|
+
baker ga4 query --preset lp-performance --days 14 — landing page UX audit
|
|
18
|
+
baker ga4 query --dimensions "date" --metrics "sessions" --days 7 — free-form query`,
|
|
19
|
+
},
|
|
20
|
+
subCommands: {
|
|
21
|
+
properties: propertiesCommand,
|
|
22
|
+
audit: auditCommand,
|
|
23
|
+
query: queryCommand,
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/ga4/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,MAAM,CAAC,MAAM,UAAU,GAAG,aAAa,CAAC;IACtC,IAAI,EAAE;QACJ,IAAI,EAAE,KAAK;QACX,WAAW,EAAE;;;;;;;;;;uFAUsE;KACpF;IACD,WAAW,EAAE;QACX,UAAU,EAAE,iBAAiB;QAC7B,KAAK,EAAE,YAAY;QACnB,KAAK,EAAE,YAAY;KACpB;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presets.d.ts","sourceRoot":"","sources":["../../../src/commands/ga4/presets.ts"],"names":[],"mappings":"AAAA,UAAU,SAAS;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,eAAO,MAAM,WAAW,EAAE,SAAS,EA+BlC,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export const GA4_PRESETS = [
|
|
2
|
+
{
|
|
3
|
+
name: "tracking-health",
|
|
4
|
+
description: "Compare GA4 sessions to GAds clicks — flag >20% discrepancy",
|
|
5
|
+
playbook: "[07] Discrepancy Check",
|
|
6
|
+
},
|
|
7
|
+
{
|
|
8
|
+
name: "lp-performance",
|
|
9
|
+
description: "Landing page UX diagnostic — flag duration <10s as message mismatch",
|
|
10
|
+
playbook: "[06] LP Diagnostic",
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
name: "traffic-quality",
|
|
14
|
+
description: "Warm traffic trap — flag >40% returning user conversions",
|
|
15
|
+
playbook: "[06] Warm Traffic Trap",
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
name: "funnel-leakage",
|
|
19
|
+
description: "Funnel drop-off analysis between form events",
|
|
20
|
+
playbook: "[06] Funnel Analysis",
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
name: "first-touch",
|
|
24
|
+
description: "First-touch attribution — true acquisition value of channels",
|
|
25
|
+
playbook: "First-Touch Attribution",
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
name: "traffic-overview",
|
|
29
|
+
description: "General traffic trends by date and source",
|
|
30
|
+
playbook: "General",
|
|
31
|
+
},
|
|
32
|
+
];
|
|
33
|
+
//# sourceMappingURL=presets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presets.js","sourceRoot":"","sources":["../../../src/commands/ga4/presets.ts"],"names":[],"mappings":"AAMA,MAAM,CAAC,MAAM,WAAW,GAAgB;IACtC;QACE,IAAI,EAAE,iBAAiB;QACvB,WAAW,EAAE,6DAA6D;QAC1E,QAAQ,EAAE,wBAAwB;KACnC;IACD;QACE,IAAI,EAAE,gBAAgB;QACtB,WAAW,EAAE,qEAAqE;QAClF,QAAQ,EAAE,oBAAoB;KAC/B;IACD;QACE,IAAI,EAAE,iBAAiB;QACvB,WAAW,EAAE,0DAA0D;QACvE,QAAQ,EAAE,wBAAwB;KACnC;IACD;QACE,IAAI,EAAE,gBAAgB;QACtB,WAAW,EAAE,8CAA8C;QAC3D,QAAQ,EAAE,sBAAsB;KACjC;IACD;QACE,IAAI,EAAE,aAAa;QACnB,WAAW,EAAE,8DAA8D;QAC3E,QAAQ,EAAE,yBAAyB;KACpC;IACD;QACE,IAAI,EAAE,kBAAkB;QACxB,WAAW,EAAE,2CAA2C;QACxD,QAAQ,EAAE,SAAS;KACpB;CACF,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare const propertiesCommand: import("citty").CommandDef<{
|
|
2
|
+
readonly "no-cache": {
|
|
3
|
+
readonly type: "boolean";
|
|
4
|
+
readonly description: "Skip cache";
|
|
5
|
+
readonly required: false;
|
|
6
|
+
};
|
|
7
|
+
readonly output: {
|
|
8
|
+
readonly type: "string";
|
|
9
|
+
readonly description: "Format: json|csv|md";
|
|
10
|
+
readonly required: false;
|
|
11
|
+
readonly default: "json";
|
|
12
|
+
};
|
|
13
|
+
}>;
|
|
14
|
+
//# sourceMappingURL=properties.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"properties.d.ts","sourceRoot":"","sources":["../../../src/commands/ga4/properties.ts"],"names":[],"mappings":"AAsBA,eAAO,MAAM,iBAAiB;;;;;;;;;;;;EA+C5B,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { defineCommand } from "citty";
|
|
2
|
+
import { ApiError, apiGet } from "../../client.js";
|
|
3
|
+
import { registerSchema } from "../../schemas.js";
|
|
4
|
+
import { cacheGet, cacheSet } from "../ads/cache.js";
|
|
5
|
+
import { writeAdsOutput, writeJsonEnvelope } from "../ads/output.js";
|
|
6
|
+
registerSchema({
|
|
7
|
+
command: "ga4.properties",
|
|
8
|
+
description: "List all accessible GA4 properties. Returns property IDs needed for query and audit commands. Run this first to find property IDs.",
|
|
9
|
+
args: {
|
|
10
|
+
"no-cache": { type: "boolean", description: "Skip cache, hit API directly", required: false },
|
|
11
|
+
},
|
|
12
|
+
});
|
|
13
|
+
import { handleConnectionError } from "../../error-handler.js";
|
|
14
|
+
export const propertiesCommand = defineCommand({
|
|
15
|
+
meta: {
|
|
16
|
+
name: "properties",
|
|
17
|
+
description: `List accessible GA4 properties.
|
|
18
|
+
|
|
19
|
+
Examples:
|
|
20
|
+
baker ga4 properties`,
|
|
21
|
+
},
|
|
22
|
+
args: {
|
|
23
|
+
"no-cache": { type: "boolean", description: "Skip cache", required: false },
|
|
24
|
+
output: { type: "string", description: "Format: json|csv|md", required: false, default: "json" },
|
|
25
|
+
},
|
|
26
|
+
run: async ({ args }) => {
|
|
27
|
+
const useCache = !args["no-cache"];
|
|
28
|
+
if (useCache) {
|
|
29
|
+
const cached = cacheGet("ga4-properties", "list");
|
|
30
|
+
if (cached) {
|
|
31
|
+
writeJsonEnvelope({ ok: true, data: cached.data, cached: true });
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
try {
|
|
36
|
+
const params = !useCache ? { "skip-cache": "true" } : undefined;
|
|
37
|
+
const data = await apiGet("/api/ga4/properties", params);
|
|
38
|
+
if (useCache) {
|
|
39
|
+
cacheSet("ga4-properties", "list", data, 60 * 60 * 1000);
|
|
40
|
+
}
|
|
41
|
+
const format = args.output || "json";
|
|
42
|
+
if (format !== "json") {
|
|
43
|
+
writeAdsOutput(data, format);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
writeJsonEnvelope({ ok: true, data });
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
if (err instanceof ApiError) {
|
|
50
|
+
if (err.code === "UNAUTHORIZED" || err.code === "NOT_FOUND") {
|
|
51
|
+
handleConnectionError("ga4", err.message);
|
|
52
|
+
}
|
|
53
|
+
writeJsonEnvelope({ ok: false, error: { code: err.code, message: err.message } });
|
|
54
|
+
process.exit(1);
|
|
55
|
+
}
|
|
56
|
+
writeJsonEnvelope({ ok: false, error: { code: "NETWORK_ERROR", message: "Unexpected error" } });
|
|
57
|
+
process.exit(1);
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
//# sourceMappingURL=properties.js.map
|