@homespunapps/core 1.6.64 → 1.6.65
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/client.d.ts +50 -2
- package/dist/client.js +81 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/dist/client.d.ts
CHANGED
|
@@ -652,6 +652,34 @@ export declare class HomespunClient {
|
|
|
652
652
|
}>;
|
|
653
653
|
/** DELETE /v1/apps/:id/connections/:name: idempotent. */
|
|
654
654
|
deleteConnection(appId: string, name: string): Promise<void>;
|
|
655
|
+
/**
|
|
656
|
+
* GET /v1/apps/:id/webhooks/deliveries: the outbound delivery journal, newest
|
|
657
|
+
* first. This is a ROLLING window (the retention sweeper prunes terminal rows
|
|
658
|
+
* past WEBHOOKS_DELIVERY_RETENTION_DAYS), not the app's whole history.
|
|
659
|
+
*
|
|
660
|
+
* `payload` is the request body as it was rendered and sent, truncated
|
|
661
|
+
* server-side; `payloadTruncated` says whether it was cut. Together with
|
|
662
|
+
* `responseStatus`/`responseBody` that is what answers "why did the target
|
|
663
|
+
* reject this", which is the reason to reach for this call at all.
|
|
664
|
+
*/
|
|
665
|
+
listWebhookDeliveries(appId: string, opts?: {
|
|
666
|
+
status?: string;
|
|
667
|
+
collection?: string;
|
|
668
|
+
limit?: number;
|
|
669
|
+
}): Promise<{
|
|
670
|
+
deliveries: Record<string, unknown>[];
|
|
671
|
+
}>;
|
|
672
|
+
/**
|
|
673
|
+
* POST /v1/apps/:id/webhooks/deliveries/:deliveryId/replay: re-send a stored
|
|
674
|
+
* delivery's own rule/url/payload as a fresh row, now, without waiting out
|
|
675
|
+
* its remaining backoff. Nothing caller-supplied enters the new row.
|
|
676
|
+
*
|
|
677
|
+
* NOT idempotent in effect: the target receives the same request again, so a
|
|
678
|
+
* target without its own dedupe ends up with a duplicate record.
|
|
679
|
+
*/
|
|
680
|
+
replayWebhookDelivery(appId: string, deliveryId: string): Promise<{
|
|
681
|
+
delivery: Record<string, unknown>;
|
|
682
|
+
}>;
|
|
655
683
|
/**
|
|
656
684
|
* The browser URL that completes an oauth2 connection's consent. Build
|
|
657
685
|
* only, never fetch this yourself: it 302s the caller to the third-party
|
|
@@ -667,8 +695,10 @@ export declare class HomespunClient {
|
|
|
667
695
|
* conditions) and/or `sort` (`{field, dir}` list) to filter/order DB-side. The
|
|
668
696
|
* relay applies read permission + author scoping FIRST, then the filter, so a
|
|
669
697
|
* filtered read is always a subset of what the caller could already read. The
|
|
670
|
-
* query is serialized into the `q` param as URL-encoded JSON.
|
|
671
|
-
* `
|
|
698
|
+
* query is serialized into the `q` param as URL-encoded JSON. Cursor
|
|
699
|
+
* pagination (`since`) works with a custom `sort` too (issue #1057): pass
|
|
700
|
+
* back the same `sort` a page's `next_cursor` came from, since a cursor is
|
|
701
|
+
* only valid for the exact sort it was issued under.
|
|
672
702
|
*/
|
|
673
703
|
listAppRows(appId: string, collection: string, opts?: {
|
|
674
704
|
since?: string;
|
|
@@ -887,6 +917,24 @@ export declare class HomespunClient {
|
|
|
887
917
|
/** POST /v1/reviews/:id/unhold (operator): publish a held review. */
|
|
888
918
|
unholdReview(reviewId: string): Promise<CommunityReview>;
|
|
889
919
|
}
|
|
920
|
+
/**
|
|
921
|
+
* PUT raw bytes to a presigned upload URL returned by `presignBlob()`.
|
|
922
|
+
* Deliberately a bare function, not a `HomespunClient` method: the URL is
|
|
923
|
+
* ALREADY pre-authorized (a SAS query string on Azure, scoped to this one
|
|
924
|
+
* key), so sending `Authorization: Bearer <apiKey>` alongside it would hand
|
|
925
|
+
* the agent's relay credential to a storage host that never asked for it and
|
|
926
|
+
* has no use for it. Routing this through `this.call` / `this.fetchImpl`
|
|
927
|
+
* would attach that header unconditionally, so this stays outside the
|
|
928
|
+
* authenticated client machinery on purpose.
|
|
929
|
+
*
|
|
930
|
+
* Azure Blob's single-shot PUT additionally requires the
|
|
931
|
+
* `x-ms-blob-type: BlockBlob` header; every presign backend today is Azure
|
|
932
|
+
* SAS, and a PUT without it 400s with `MissingRequiredHeader`, so it is
|
|
933
|
+
* always sent. There is no relay error envelope to parse on failure here:
|
|
934
|
+
* this response is storage's own, so a non-2xx throws a plain `Error`
|
|
935
|
+
* carrying the status and whatever body storage returned.
|
|
936
|
+
*/
|
|
937
|
+
export declare function putPresigned(uploadUrl: string, bytes: Uint8Array | Buffer, mime: string, fetchImpl?: typeof fetch): Promise<void>;
|
|
890
938
|
/**
|
|
891
939
|
* One multi-file-deploy asset carrying its bytes inline as base64. The deployed
|
|
892
940
|
* page references it by a stable, app-relative, same-origin path (e.g.
|
package/dist/client.js
CHANGED
|
@@ -1104,6 +1104,44 @@ export class HomespunClient {
|
|
|
1104
1104
|
if (!r.ok)
|
|
1105
1105
|
this.fail(r);
|
|
1106
1106
|
}
|
|
1107
|
+
/**
|
|
1108
|
+
* GET /v1/apps/:id/webhooks/deliveries: the outbound delivery journal, newest
|
|
1109
|
+
* first. This is a ROLLING window (the retention sweeper prunes terminal rows
|
|
1110
|
+
* past WEBHOOKS_DELIVERY_RETENTION_DAYS), not the app's whole history.
|
|
1111
|
+
*
|
|
1112
|
+
* `payload` is the request body as it was rendered and sent, truncated
|
|
1113
|
+
* server-side; `payloadTruncated` says whether it was cut. Together with
|
|
1114
|
+
* `responseStatus`/`responseBody` that is what answers "why did the target
|
|
1115
|
+
* reject this", which is the reason to reach for this call at all.
|
|
1116
|
+
*/
|
|
1117
|
+
async listWebhookDeliveries(appId, opts = {}) {
|
|
1118
|
+
const q = new URLSearchParams();
|
|
1119
|
+
if (opts.status !== undefined)
|
|
1120
|
+
q.set("status", opts.status);
|
|
1121
|
+
if (opts.collection !== undefined)
|
|
1122
|
+
q.set("collection", opts.collection);
|
|
1123
|
+
if (opts.limit !== undefined)
|
|
1124
|
+
q.set("limit", String(opts.limit));
|
|
1125
|
+
const qs = q.toString();
|
|
1126
|
+
const r = await this.call("GET", `/v1/apps/${encodeURIComponent(appId)}/webhooks/deliveries${qs ? `?${qs}` : ""}`);
|
|
1127
|
+
if (!r.ok)
|
|
1128
|
+
this.fail(r);
|
|
1129
|
+
return this.asObject(r);
|
|
1130
|
+
}
|
|
1131
|
+
/**
|
|
1132
|
+
* POST /v1/apps/:id/webhooks/deliveries/:deliveryId/replay: re-send a stored
|
|
1133
|
+
* delivery's own rule/url/payload as a fresh row, now, without waiting out
|
|
1134
|
+
* its remaining backoff. Nothing caller-supplied enters the new row.
|
|
1135
|
+
*
|
|
1136
|
+
* NOT idempotent in effect: the target receives the same request again, so a
|
|
1137
|
+
* target without its own dedupe ends up with a duplicate record.
|
|
1138
|
+
*/
|
|
1139
|
+
async replayWebhookDelivery(appId, deliveryId) {
|
|
1140
|
+
const r = await this.call("POST", `/v1/apps/${encodeURIComponent(appId)}/webhooks/deliveries/${encodeURIComponent(deliveryId)}/replay`);
|
|
1141
|
+
if (!r.ok)
|
|
1142
|
+
this.fail(r);
|
|
1143
|
+
return this.asObject(r);
|
|
1144
|
+
}
|
|
1107
1145
|
/**
|
|
1108
1146
|
* The browser URL that completes an oauth2 connection's consent. Build
|
|
1109
1147
|
* only, never fetch this yourself: it 302s the caller to the third-party
|
|
@@ -1126,8 +1164,10 @@ export class HomespunClient {
|
|
|
1126
1164
|
* conditions) and/or `sort` (`{field, dir}` list) to filter/order DB-side. The
|
|
1127
1165
|
* relay applies read permission + author scoping FIRST, then the filter, so a
|
|
1128
1166
|
* filtered read is always a subset of what the caller could already read. The
|
|
1129
|
-
* query is serialized into the `q` param as URL-encoded JSON.
|
|
1130
|
-
* `
|
|
1167
|
+
* query is serialized into the `q` param as URL-encoded JSON. Cursor
|
|
1168
|
+
* pagination (`since`) works with a custom `sort` too (issue #1057): pass
|
|
1169
|
+
* back the same `sort` a page's `next_cursor` came from, since a cursor is
|
|
1170
|
+
* only valid for the exact sort it was issued under.
|
|
1131
1171
|
*/
|
|
1132
1172
|
async listAppRows(appId, collection, opts = {}) {
|
|
1133
1173
|
const q = new URLSearchParams();
|
|
@@ -1554,6 +1594,45 @@ export class HomespunClient {
|
|
|
1554
1594
|
return this.asObject(r);
|
|
1555
1595
|
}
|
|
1556
1596
|
}
|
|
1597
|
+
/**
|
|
1598
|
+
* PUT raw bytes to a presigned upload URL returned by `presignBlob()`.
|
|
1599
|
+
* Deliberately a bare function, not a `HomespunClient` method: the URL is
|
|
1600
|
+
* ALREADY pre-authorized (a SAS query string on Azure, scoped to this one
|
|
1601
|
+
* key), so sending `Authorization: Bearer <apiKey>` alongside it would hand
|
|
1602
|
+
* the agent's relay credential to a storage host that never asked for it and
|
|
1603
|
+
* has no use for it. Routing this through `this.call` / `this.fetchImpl`
|
|
1604
|
+
* would attach that header unconditionally, so this stays outside the
|
|
1605
|
+
* authenticated client machinery on purpose.
|
|
1606
|
+
*
|
|
1607
|
+
* Azure Blob's single-shot PUT additionally requires the
|
|
1608
|
+
* `x-ms-blob-type: BlockBlob` header; every presign backend today is Azure
|
|
1609
|
+
* SAS, and a PUT without it 400s with `MissingRequiredHeader`, so it is
|
|
1610
|
+
* always sent. There is no relay error envelope to parse on failure here:
|
|
1611
|
+
* this response is storage's own, so a non-2xx throws a plain `Error`
|
|
1612
|
+
* carrying the status and whatever body storage returned.
|
|
1613
|
+
*/
|
|
1614
|
+
export async function putPresigned(uploadUrl, bytes, mime, fetchImpl = fetch) {
|
|
1615
|
+
const body = bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes);
|
|
1616
|
+
let res;
|
|
1617
|
+
try {
|
|
1618
|
+
res = await fetchImpl(uploadUrl, {
|
|
1619
|
+
method: "PUT",
|
|
1620
|
+
headers: {
|
|
1621
|
+
"content-type": mime,
|
|
1622
|
+
"x-ms-blob-type": "BlockBlob",
|
|
1623
|
+
},
|
|
1624
|
+
body,
|
|
1625
|
+
});
|
|
1626
|
+
}
|
|
1627
|
+
catch (e) {
|
|
1628
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
1629
|
+
throw new Error(`presigned upload failed: ${msg}`, { cause: e });
|
|
1630
|
+
}
|
|
1631
|
+
if (!res.ok) {
|
|
1632
|
+
const text = await res.text().catch(() => "");
|
|
1633
|
+
throw new Error(`presigned upload failed: HTTP ${res.status}${text ? ` (${text.slice(0, 500)})` : ""}`);
|
|
1634
|
+
}
|
|
1635
|
+
}
|
|
1557
1636
|
/**
|
|
1558
1637
|
* Path for a community-template ref action. A namespaced `<handle>/<slug>` ref
|
|
1559
1638
|
* becomes a TWO-segment path (`/templates/<handle>/<slug>/<suffix>`) so it
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { HomespunClient, HomespunApiError } from "./client.js";
|
|
1
|
+
export { HomespunClient, HomespunApiError, putPresigned } from "./client.js";
|
|
2
2
|
export type { ClientOptions, RelayResponse, AttachmentRef, UploadBlobOptions, PresignBlobOptions, AttachmentTokenMintResponse, ListBlobsOptions, AttachmentTokenAuditEntry, AttachmentTokenListResponse, QueryResponse, AppAsset, DeployAppRequest, DeployAppResponse, RedeployAppRequest, RedeployAppResponse, DeployCheckRequest, DeployCheckResult, KeyMintResult, AppSummary, AppDetail, AppsPage, AppDomain, AppDomainDnsRecord, AppMember, AddAppMemberResult, AppRow, AppRowsPage, ListScalar, ListWhereCondition, ListSortSpec, BatchRowInput, BatchRowResult, BatchResult, BatchWriteOptions, AppFeedEntry, AppFeedPage, CommunitySetupStep, RetentionAxes, CollectionRetentionView, ServiceCredentialGrant, MintAppCredentialResult, AppCredentialSummary, RotateAppCredentialResult, ConnectionSummary, } from "./client.js";
|
|
3
3
|
export { openStream } from "./stream.js";
|
|
4
4
|
export type { OpenStreamOptions, StreamHandlers, StreamHandle, } from "./stream.js";
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// @homespunapps/core — typed client for the Homespun relay HTTP + WebSocket API.
|
|
2
2
|
// Pure and framework-free: no argv, no MCP, no server deps.
|
|
3
|
-
export { HomespunClient, HomespunApiError } from "./client.js";
|
|
3
|
+
export { HomespunClient, HomespunApiError, putPresigned } from "./client.js";
|
|
4
4
|
export { openStream } from "./stream.js";
|
|
5
5
|
export { openAppStream, appWsUrlFromAppUrl } from "./app-stream.js";
|
|
6
6
|
export { openWorkerStream, workerWsUrlFromBase } from "./app-stream.js";
|