@myapihq/cli 2.31.2 → 2.31.4
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/dist/commands/pixel.js +6 -2
- package/dist/errors.js +10 -1
- package/dist/errors.test.js +26 -0
- package/dist/flags.js +16 -3
- package/dist/flags.test.js +13 -0
- package/dist/skills/my-pixel-api/SKILL.md +2 -2
- package/package.json +2 -2
package/dist/commands/pixel.js
CHANGED
|
@@ -87,7 +87,7 @@ export async function visits(flags) {
|
|
|
87
87
|
ts: v.ts,
|
|
88
88
|
})));
|
|
89
89
|
// /visits returns only {visits, total} — it does NOT echo limit/offset the
|
|
90
|
-
// way /
|
|
90
|
+
// way /interactions does, so this used to print
|
|
91
91
|
// "Showing: undefined | Offset: undefined". Report what the response
|
|
92
92
|
// actually carries.
|
|
93
93
|
info(`Total: ${res.total} | Showing: ${res.visits.length}`);
|
|
@@ -128,7 +128,11 @@ export async function events(flags) {
|
|
|
128
128
|
campaign_id: e.campaign_id ?? '',
|
|
129
129
|
ts: e.ts,
|
|
130
130
|
})));
|
|
131
|
-
|
|
131
|
+
// /events returns {events, total} — the limit/offset echo the visits comment
|
|
132
|
+
// above attributes to it is in `meta`, which the SDK does not surface, so
|
|
133
|
+
// this printed "Showing: undefined | Offset: undefined" too. Only
|
|
134
|
+
// /interactions genuinely echoes them in the body.
|
|
135
|
+
info(`Total: ${res.total} | Showing: ${res.events.length}`);
|
|
132
136
|
}
|
|
133
137
|
// Geographic distribution sample of the org's pixel audience.
|
|
134
138
|
export async function audience(flags) {
|
package/dist/errors.js
CHANGED
|
@@ -144,7 +144,16 @@ export function friendlyError(err) {
|
|
|
144
144
|
lines.push(err.requestId
|
|
145
145
|
? ` Quote this when reporting it: ${err.requestId}`
|
|
146
146
|
: ' No request id came back, so quote the exact command and the time instead.');
|
|
147
|
-
|
|
147
|
+
// Only for a request that could have changed something. A 500 can land
|
|
148
|
+
// before or after a write, so the warning is right for POST/PATCH/DELETE —
|
|
149
|
+
// but `pixel audience` is a GET, and telling someone to go and check
|
|
150
|
+
// whether their read went through sends them looking for a change that
|
|
151
|
+
// could not exist. Unknown method keeps the warning: silence about a
|
|
152
|
+
// possible half-applied write is the worse failure.
|
|
153
|
+
const read = err.method === 'GET' || err.method === 'HEAD';
|
|
154
|
+
if (!read) {
|
|
155
|
+
lines.push(' Whether the change went through is not knowable from here — check before retrying.');
|
|
156
|
+
}
|
|
148
157
|
return withOrgContext(lines.join('\n'), err);
|
|
149
158
|
}
|
|
150
159
|
const base = ERROR_MESSAGES[err.code] || err.code;
|
package/dist/errors.test.js
CHANGED
|
@@ -139,3 +139,29 @@ function looksLikeBadKey(err) {
|
|
|
139
139
|
]);
|
|
140
140
|
return err.status === 401 && (!err.code || AUTH_CODES.has(String(err.code).toLowerCase()));
|
|
141
141
|
}
|
|
142
|
+
// A 500 on a GET used to end with "Whether the change went through is not
|
|
143
|
+
// knowable from here — check before retrying." `pixel audience` is a read; it
|
|
144
|
+
// sent people to look for a change that could not exist. Found 2026-08-24 while
|
|
145
|
+
// fixing PIXEL_BASE, when the command finally reached the platform at all.
|
|
146
|
+
describe('5xx advice distinguishes a read from a write', () => {
|
|
147
|
+
function err(method) {
|
|
148
|
+
const e = new MyApiError('ANALYTICS_ERROR', 502, 'analytics query failed');
|
|
149
|
+
e.requestId = 'req_test';
|
|
150
|
+
if (method)
|
|
151
|
+
e.method = method;
|
|
152
|
+
return e;
|
|
153
|
+
}
|
|
154
|
+
it('says nothing about a change after a failed GET', () => {
|
|
155
|
+
const msg = friendlyError(err('GET'));
|
|
156
|
+
expect(msg).not.toContain('went through');
|
|
157
|
+
expect(msg).toContain('req_test');
|
|
158
|
+
expect(msg).toContain('our fault');
|
|
159
|
+
});
|
|
160
|
+
it('still warns after a failed write', () => {
|
|
161
|
+
expect(friendlyError(err('POST'))).toContain('went through');
|
|
162
|
+
expect(friendlyError(err('DELETE'))).toContain('went through');
|
|
163
|
+
});
|
|
164
|
+
it('keeps the warning when the method is unknown', () => {
|
|
165
|
+
expect(friendlyError(err())).toContain('went through');
|
|
166
|
+
});
|
|
167
|
+
});
|
package/dist/flags.js
CHANGED
|
@@ -22,6 +22,9 @@ export const GLOBAL_FLAGS = {
|
|
|
22
22
|
version: 'boolean',
|
|
23
23
|
org: 'string',
|
|
24
24
|
};
|
|
25
|
+
// Value flags that name one target rather than a list, mapped to the noun used
|
|
26
|
+
// when refusing a duplicate. Comma-separating these is not a workaround.
|
|
27
|
+
const SINGLE_VALUED = new Map([['org', 'organisation']]);
|
|
25
28
|
// Short aliases are consumed as `-h` / `-v` / `-V` before the `--flag` branch,
|
|
26
29
|
// so they never appear as keys in `merged` and need no type — but they do land
|
|
27
30
|
// in `flags` (as help/version), so the dispatcher must still tolerate them.
|
|
@@ -134,10 +137,20 @@ export function parseFlags(argv, schema = {}, quiet = false) {
|
|
|
134
137
|
// mistake when the docs say "comma-separated"; silently honouring the
|
|
135
138
|
// last is the one behaviour that can't be recovered from. Refuse, and
|
|
136
139
|
// say what to do instead.
|
|
140
|
+
//
|
|
141
|
+
// The comma-separated suggestion is right for a flag that names a list of
|
|
142
|
+
// things and wrong for one that names a single target: a command writes to
|
|
143
|
+
// one organisation, so `--org a,b` would just build an id that matches no
|
|
144
|
+
// org. Say which case this is rather than offering advice that cannot work.
|
|
137
145
|
if (seenValueFlags.has(key)) {
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
146
|
+
const previous = flags[key];
|
|
147
|
+
throw new Error(SINGLE_VALUED.has(key)
|
|
148
|
+
? `--${key} was given more than once ("${String(previous)}", then "${raw}"). ` +
|
|
149
|
+
`Only the last would be used, which silently discards the first.\n` +
|
|
150
|
+
`→ A command acts on one ${SINGLE_VALUED.get(key)}. Pass --${key} once.`
|
|
151
|
+
: `--${key} was given more than once. Only the last value would be used, ` +
|
|
152
|
+
`which silently discards the others.\n` +
|
|
153
|
+
`→ If you meant to pass several values, comma-separate them: --${key} a,b,c`);
|
|
141
154
|
}
|
|
142
155
|
seenValueFlags.add(key);
|
|
143
156
|
if (type === 'number') {
|
package/dist/flags.test.js
CHANGED
|
@@ -206,6 +206,19 @@ describe('global flag lists cannot drift', () => {
|
|
|
206
206
|
// other nineteen silently kept the last value. Parse with an empty schema
|
|
207
207
|
// to stand in for a command that declares nothing of its own.
|
|
208
208
|
expect(() => parseFlags(['--org', 'ORG_A', '--org', 'ORG_B'], {}, true)).toThrow(/--org was given more than once/);
|
|
209
|
+
// The generic advice ("comma-separate them") cannot work for org: a command
|
|
210
|
+
// writes to one organisation, and --org a,b is just an id that matches none.
|
|
211
|
+
let msg = '';
|
|
212
|
+
try {
|
|
213
|
+
parseFlags(['--org', 'ORG_A', '--org', 'ORG_B'], {}, true);
|
|
214
|
+
}
|
|
215
|
+
catch (e) {
|
|
216
|
+
msg = e.message;
|
|
217
|
+
}
|
|
218
|
+
expect(msg).not.toContain('comma-separate');
|
|
219
|
+
expect(msg).toContain('acts on one organisation');
|
|
220
|
+
expect(msg).toContain('ORG_A');
|
|
221
|
+
expect(msg).toContain('ORG_B');
|
|
209
222
|
});
|
|
210
223
|
it('a single --org still parses to its value under an empty schema', () => {
|
|
211
224
|
const { flags } = parseFlags(['--org', 'ORG_A'], {}, true);
|
|
@@ -4,7 +4,7 @@ version: 1.0.0
|
|
|
4
4
|
description: >
|
|
5
5
|
Tracking pixel + identity resolution for MyAPI funnels and email. Capture visits and events, resolve known users to anonymous sessions, stream interaction events for analytics. Pairs with mycrmapi for auto-ingest of pixel_visit events on known contacts.
|
|
6
6
|
triggers: [pixel, analytics, tracking, visit, event, identity, session, attribution, geo, open pixel]
|
|
7
|
-
checksum: sha256-
|
|
7
|
+
checksum: sha256-4be497d5db05dbca3646b76b3385c22f84de4726d1049a7d9876c054159e4a58
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# MyPixelAPI
|
|
@@ -103,7 +103,7 @@ graph across the visitor's sessions.
|
|
|
103
103
|
<!-- http:start -->
|
|
104
104
|
<!-- generated by `npm run canonical-sync` — do not edit -->
|
|
105
105
|
```
|
|
106
|
-
base https://api.
|
|
106
|
+
base https://api.myapihq.com
|
|
107
107
|
path POST /pixel/orgs/{org_id}/identify
|
|
108
108
|
auth Authorization: Bearer <key> (fn: env.__MYAPI_KEY · container: env.MYAPI_KEY)
|
|
109
109
|
reply { "success": true, "data": …, "error": null, "meta": {…} }
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@myapihq/cli",
|
|
3
3
|
"license": "Apache-2.0",
|
|
4
|
-
"version": "2.31.
|
|
4
|
+
"version": "2.31.4",
|
|
5
5
|
"description": "MyAPI command-line interface",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"lint:skills:strict": "node scripts/copy-skills.js && node scripts/lint-skills.js --strict"
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@myapihq/sdk": "^2.31.
|
|
50
|
+
"@myapihq/sdk": "^2.31.4"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"@types/node": "^25.6.0",
|