@myapihq/sdk 2.20.0 → 2.20.1
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/auth.js +5 -1
- package/dist/client.d.ts +25 -0
- package/dist/client.js +38 -0
- package/dist/container.js +4 -1
- package/dist/feedback.js +6 -4
- package/dist/function.js +4 -1
- package/dist/hq.d.ts +1 -0
- package/dist/hq.js +3 -1
- package/dist/queue.js +6 -2
- package/dist/storage.js +4 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/dist/auth.js
CHANGED
|
@@ -63,7 +63,11 @@ async function createClient(apiKey, orgId, input) {
|
|
|
63
63
|
return (0, client_1.request)('POST', `${config_1.AUTH_BASE}/auth/orgs/${encodeURIComponent(orgId)}/clients`, apiKey, input);
|
|
64
64
|
}
|
|
65
65
|
async function listClients(apiKey, orgId) {
|
|
66
|
-
|
|
66
|
+
// Follows the cursor to the end — the endpoint pages now. The {clients: […]}
|
|
67
|
+
// wrapper was kept when it started paging so no caller had to change, which
|
|
68
|
+
// is why the rows need picking out one level down.
|
|
69
|
+
const clients = await (0, client_1.requestAll)(`${config_1.AUTH_BASE}/auth/orgs/${encodeURIComponent(orgId)}/clients`, apiKey, { select: d => (d?.clients ?? []) });
|
|
70
|
+
return { clients };
|
|
67
71
|
}
|
|
68
72
|
// Change a client's redirect URIs or name, keeping the SAME client_id and
|
|
69
73
|
// secret.
|
package/dist/client.d.ts
CHANGED
|
@@ -41,4 +41,29 @@ export interface Page<T> {
|
|
|
41
41
|
next_cursor?: string;
|
|
42
42
|
has_more?: boolean;
|
|
43
43
|
}
|
|
44
|
+
/**
|
|
45
|
+
* Follow a keyset-paginated list to the end and return every row.
|
|
46
|
+
*
|
|
47
|
+
* The backend began paging these lists on 2026-08-20 (myapi-hq #17). Callers
|
|
48
|
+
* that were using `request` kept working and quietly started receiving only the
|
|
49
|
+
* first page — 50 rows where they used to get the whole collection, with
|
|
50
|
+
* nothing in the response to say so. A list that silently stops at 50 is worse
|
|
51
|
+
* than a slow one: the caller acts on a partial answer believing it is complete.
|
|
52
|
+
*
|
|
53
|
+
* So the default is unchanged behaviour — everything — and a caller who wants
|
|
54
|
+
* one page asks for it with requestPage.
|
|
55
|
+
*
|
|
56
|
+
* `maxPages` is a stop, not a limit: a server that returns has_more forever
|
|
57
|
+
* (or a cursor that does not advance) would otherwise spin here. Hitting it
|
|
58
|
+
* throws rather than returning a short list, because a truncated answer that
|
|
59
|
+
* looks complete is the failure this function exists to prevent.
|
|
60
|
+
*/
|
|
61
|
+
export declare function requestAll<T>(url: string, apiKey?: string, opts?: RequestOptions & {
|
|
62
|
+
pageSize?: number;
|
|
63
|
+
maxPages?: number;
|
|
64
|
+
/** Pulls the array out of a wrapped payload — `{queues: […]}`, `{clients:
|
|
65
|
+
* […]}`. Those wrappers were kept when the endpoints started paging so no
|
|
66
|
+
* existing caller had to change, which means the rows are one level down. */
|
|
67
|
+
select?: (data: unknown) => T[];
|
|
68
|
+
}): Promise<T[]>;
|
|
44
69
|
export declare function requestPage<T>(method: string, url: string, apiKey?: string, body?: unknown, extraHeaders?: Record<string, string>, opts?: RequestOptions): Promise<Page<T>>;
|
package/dist/client.js
CHANGED
|
@@ -4,6 +4,7 @@ exports.MyApiError = void 0;
|
|
|
4
4
|
exports.setUserAgent = setUserAgent;
|
|
5
5
|
exports.toError = toError;
|
|
6
6
|
exports.request = request;
|
|
7
|
+
exports.requestAll = requestAll;
|
|
7
8
|
exports.requestPage = requestPage;
|
|
8
9
|
const version_1 = require("./version");
|
|
9
10
|
class MyApiError extends Error {
|
|
@@ -301,6 +302,43 @@ async function request(method, url, apiKey, body, extraHeaders, opts) {
|
|
|
301
302
|
// For keyset-paginated endpoints (backend `envelope.WrapPage`): `data` is a
|
|
302
303
|
// bare array and the cursor/has_more live under `meta`. `request` would drop
|
|
303
304
|
// the cursor, so list endpoints with pagination must use this.
|
|
305
|
+
/**
|
|
306
|
+
* Follow a keyset-paginated list to the end and return every row.
|
|
307
|
+
*
|
|
308
|
+
* The backend began paging these lists on 2026-08-20 (myapi-hq #17). Callers
|
|
309
|
+
* that were using `request` kept working and quietly started receiving only the
|
|
310
|
+
* first page — 50 rows where they used to get the whole collection, with
|
|
311
|
+
* nothing in the response to say so. A list that silently stops at 50 is worse
|
|
312
|
+
* than a slow one: the caller acts on a partial answer believing it is complete.
|
|
313
|
+
*
|
|
314
|
+
* So the default is unchanged behaviour — everything — and a caller who wants
|
|
315
|
+
* one page asks for it with requestPage.
|
|
316
|
+
*
|
|
317
|
+
* `maxPages` is a stop, not a limit: a server that returns has_more forever
|
|
318
|
+
* (or a cursor that does not advance) would otherwise spin here. Hitting it
|
|
319
|
+
* throws rather than returning a short list, because a truncated answer that
|
|
320
|
+
* looks complete is the failure this function exists to prevent.
|
|
321
|
+
*/
|
|
322
|
+
async function requestAll(url, apiKey, opts) {
|
|
323
|
+
const pageSize = opts?.pageSize ?? 200;
|
|
324
|
+
const maxPages = opts?.maxPages ?? 100;
|
|
325
|
+
const out = [];
|
|
326
|
+
let cursor;
|
|
327
|
+
for (let i = 0; i < maxPages; i++) {
|
|
328
|
+
const sep = url.includes('?') ? '&' : '?';
|
|
329
|
+
const qs = `limit=${pageSize}${cursor ? `&cursor=${encodeURIComponent(cursor)}` : ''}`;
|
|
330
|
+
const page = await requestPage('GET', `${url}${sep}${qs}`, apiKey, undefined, undefined, opts);
|
|
331
|
+
out.push(...(opts?.select ? opts.select(page.data) : page.data));
|
|
332
|
+
if (!page.has_more || !page.next_cursor)
|
|
333
|
+
return out;
|
|
334
|
+
if (page.next_cursor === cursor) {
|
|
335
|
+
throw new MyApiError('pagination_stalled', 0, `${url} returned the same cursor twice — refusing to loop. Got ${out.length} rows.`);
|
|
336
|
+
}
|
|
337
|
+
cursor = page.next_cursor;
|
|
338
|
+
}
|
|
339
|
+
throw new MyApiError('pagination_runaway', 0, `${url} still reported more rows after ${maxPages} pages (${out.length} fetched). ` +
|
|
340
|
+
`Refusing to return a partial list as if it were complete.`);
|
|
341
|
+
}
|
|
304
342
|
async function requestPage(method, url, apiKey, body, extraHeaders, opts) {
|
|
305
343
|
const r = await requestFull(method, url, apiKey, body, extraHeaders, opts);
|
|
306
344
|
const meta = (r.meta ?? {});
|
package/dist/container.js
CHANGED
|
@@ -37,7 +37,10 @@ async function createContainer(apiKey, orgId, payload) {
|
|
|
37
37
|
return (0, client_1.request)('POST', `${config_1.CONTAINER_BASE}/container/orgs/${encodeURIComponent(orgId)}/containers`, apiKey, payload);
|
|
38
38
|
}
|
|
39
39
|
async function listContainers(apiKey, orgId) {
|
|
40
|
-
|
|
40
|
+
// Follows the cursor to the end: the backend began paging this list on
|
|
41
|
+
// 2026-08-20, and returning only the first page here would silently turn a
|
|
42
|
+
// complete answer into a partial one.
|
|
43
|
+
return (0, client_1.requestAll)(`${config_1.CONTAINER_BASE}/container/orgs/${encodeURIComponent(orgId)}/containers`, apiKey);
|
|
41
44
|
}
|
|
42
45
|
async function getContainer(apiKey, orgId, containerId) {
|
|
43
46
|
return (0, client_1.request)('GET', `${config_1.CONTAINER_BASE}/container/orgs/${encodeURIComponent(orgId)}/containers/${encodeURIComponent(containerId)}`, apiKey);
|
package/dist/feedback.js
CHANGED
|
@@ -87,10 +87,12 @@ async function listWidgets(apiKey, orgId) {
|
|
|
87
87
|
// CLI reported "No widgets yet" for orgs that had widgets, four times, while
|
|
88
88
|
// the HTTP API was answering correctly the whole time. Reported by ImmoPilot
|
|
89
89
|
// on 2026-08-19; verified against widgetView in the backend.
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
return
|
|
90
|
+
// Follows the cursor to the end: the endpoint pages now, and one page
|
|
91
|
+
// returned as the whole list is the same silent-partial-answer bug in a new
|
|
92
|
+
// costume.
|
|
93
|
+
return (0, client_1.requestAll)(`${orgBase(orgId)}/widgets`, apiKey, {
|
|
94
|
+
select: d => (Array.isArray(d) ? d : (d?.widgets ?? [])),
|
|
95
|
+
});
|
|
94
96
|
}
|
|
95
97
|
async function revokeWidget(apiKey, orgId, id) {
|
|
96
98
|
return (0, client_1.request)('DELETE', `${orgBase(orgId)}/widgets/${encodeURIComponent(id)}`, apiKey);
|
package/dist/function.js
CHANGED
|
@@ -29,7 +29,10 @@ async function createFunction(apiKey, orgId, payload) {
|
|
|
29
29
|
return (0, client_1.request)('POST', `${config_1.FUNCTION_BASE}/function/orgs/${encodeURIComponent(orgId)}/functions`, apiKey, payload);
|
|
30
30
|
}
|
|
31
31
|
async function listFunctions(apiKey, orgId) {
|
|
32
|
-
|
|
32
|
+
// Follows the cursor to the end: the backend began paging this list on
|
|
33
|
+
// 2026-08-20, and returning only the first page here would silently turn a
|
|
34
|
+
// complete answer into a partial one.
|
|
35
|
+
return (0, client_1.requestAll)(`${config_1.FUNCTION_BASE}/function/orgs/${encodeURIComponent(orgId)}/functions`, apiKey);
|
|
33
36
|
}
|
|
34
37
|
async function getFunction(apiKey, orgId, fnId) {
|
|
35
38
|
return (0, client_1.request)('GET', `${config_1.FUNCTION_BASE}/function/orgs/${encodeURIComponent(orgId)}/functions/${encodeURIComponent(fnId)}`, apiKey);
|
package/dist/hq.d.ts
CHANGED
|
@@ -118,6 +118,7 @@ export declare function getBalance(apiKey: string): Promise<{
|
|
|
118
118
|
has_payment_method: boolean;
|
|
119
119
|
}>;
|
|
120
120
|
export declare function getBillingHistory(apiKey: string): Promise<{
|
|
121
|
+
id: string;
|
|
121
122
|
type: string;
|
|
122
123
|
amount_display: string;
|
|
123
124
|
status: string;
|
package/dist/hq.js
CHANGED
|
@@ -164,7 +164,9 @@ async function getBalance(apiKey) {
|
|
|
164
164
|
return (0, client_1.request)('GET', `${config_1.HQ_BASE}/hq/billing/balance`, apiKey);
|
|
165
165
|
}
|
|
166
166
|
async function getBillingHistory(apiKey) {
|
|
167
|
-
|
|
167
|
+
// Follows the cursor to the end — the backend pages this list now, and one
|
|
168
|
+
// page returned as if it were the whole list is a silent partial answer.
|
|
169
|
+
return (0, client_1.requestAll)(`${config_1.HQ_BASE}/hq/billing/history`, apiKey);
|
|
168
170
|
}
|
|
169
171
|
// getBillingUsage rolls up spend by service for a window: the current
|
|
170
172
|
// calendar month (default) or the trailing 30 days ('30d').
|
package/dist/queue.js
CHANGED
|
@@ -37,8 +37,12 @@ async function createQueue(apiKey, orgId, opts) {
|
|
|
37
37
|
return (0, client_1.request)('POST', queuesBase(orgId), apiKey, body);
|
|
38
38
|
}
|
|
39
39
|
async function listQueues(apiKey, orgId) {
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
// Follows the cursor to the end: the backend began paging this list on
|
|
41
|
+
// 2026-08-20, and returning only the first page here would silently turn a
|
|
42
|
+
// complete answer into a partial one.
|
|
43
|
+
return (0, client_1.requestAll)(queuesBase(orgId), apiKey, {
|
|
44
|
+
select: d => (d?.queues ?? []),
|
|
45
|
+
});
|
|
42
46
|
}
|
|
43
47
|
async function getQueue(apiKey, orgId, name) {
|
|
44
48
|
return (0, client_1.request)('GET', `${queuesBase(orgId)}/${encodeURIComponent(name)}`, apiKey);
|
package/dist/storage.js
CHANGED
|
@@ -91,7 +91,10 @@ function signedUrlOf(res) {
|
|
|
91
91
|
return res.signed_url ?? res.url;
|
|
92
92
|
}
|
|
93
93
|
async function listAssets(apiKey, orgId) {
|
|
94
|
-
|
|
94
|
+
// Follows the cursor to the end: the backend began paging this list on
|
|
95
|
+
// 2026-08-20, and returning only the first page here would silently turn a
|
|
96
|
+
// complete answer into a partial one.
|
|
97
|
+
return (0, client_1.requestAll)(`${config_1.STORAGE_BASE}/storage/orgs/${encodeURIComponent(orgId)}/assets`, apiKey);
|
|
95
98
|
}
|
|
96
99
|
async function deleteAsset(apiKey, orgId, assetId) {
|
|
97
100
|
return (0, client_1.request)('DELETE', `${config_1.STORAGE_BASE}/storage/orgs/${encodeURIComponent(orgId)}/assets/${encodeURIComponent(assetId)}`, apiKey);
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const SDK_VERSION = "2.20.
|
|
1
|
+
export declare const SDK_VERSION = "2.20.1";
|
package/dist/version.js
CHANGED
|
@@ -8,4 +8,4 @@ exports.SDK_VERSION = void 0;
|
|
|
8
8
|
// Why a constant and not a package.json read: the SDK runs inside edge
|
|
9
9
|
// functions (Cloudflare Workers), so it must not import node:fs. A literal
|
|
10
10
|
// is the only version source that works in every runtime we ship to.
|
|
11
|
-
exports.SDK_VERSION = '2.20.
|
|
11
|
+
exports.SDK_VERSION = '2.20.1';
|