@homespunapps/core 1.6.38 → 1.6.40
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 +55 -0
- package/dist/client.js +46 -0
- package/dist/icons.js +2 -2
- package/package.json +3 -3
package/dist/client.d.ts
CHANGED
|
@@ -613,6 +613,26 @@ export declare class HomespunClient {
|
|
|
613
613
|
* is a 404 (HomespunApiError `row_not_found`), matching a normal delete.
|
|
614
614
|
*/
|
|
615
615
|
purgeAppRow(appId: string, collection: string, key: string): Promise<void>;
|
|
616
|
+
/**
|
|
617
|
+
* POST /v1/apps/:id/collections/:name/:key/restore: undo a soft delete.
|
|
618
|
+
*
|
|
619
|
+
* Owner/agent only, independent of the collection's permission lists. A row
|
|
620
|
+
* that was PURGED is not restorable (410 `restore_expired`), and a restore
|
|
621
|
+
* can legitimately fail on quota or on a unique value another live row took
|
|
622
|
+
* while this one was deleted (409 `restore_conflict`).
|
|
623
|
+
*/
|
|
624
|
+
restoreAppRow(appId: string, collection: string, key: string): Promise<{
|
|
625
|
+
row: AppRow;
|
|
626
|
+
}>;
|
|
627
|
+
/**
|
|
628
|
+
* GET /v1/apps/:id/collections/:name/deleted: the recovery bin, newest
|
|
629
|
+
* deletion first. Owner/agent only. Page with `before`, passing back the
|
|
630
|
+
* previous page's `next_before`.
|
|
631
|
+
*/
|
|
632
|
+
listDeletedAppRows(appId: string, collection: string, opts?: {
|
|
633
|
+
limit?: number;
|
|
634
|
+
before?: string;
|
|
635
|
+
}): Promise<DeletedAppRowsPage>;
|
|
616
636
|
/** PATCH /v1/apps/:id/collections/:name/:key — optimistic-locked update. */
|
|
617
637
|
updateAppRow(appId: string, collection: string, key: string, body: {
|
|
618
638
|
data: unknown;
|
|
@@ -666,6 +686,15 @@ export declare class HomespunClient {
|
|
|
666
686
|
decision: "approve" | "reject";
|
|
667
687
|
note?: string;
|
|
668
688
|
}): Promise<CommunitySubmissionDetail>;
|
|
689
|
+
/**
|
|
690
|
+
* POST /v1/community/submissions/:id/unpublish (publisher): take your own
|
|
691
|
+
* live listing down. It leaves the public gallery, search, and the direct
|
|
692
|
+
* snapshot install link; existing installs are untouched, because an install
|
|
693
|
+
* is a fresh private copy rather than a live reference. Idempotent, and 404
|
|
694
|
+
* when the snapshot does not exist OR is not yours (indistinguishable on
|
|
695
|
+
* purpose). Republish a new version to undo it.
|
|
696
|
+
*/
|
|
697
|
+
unpublishCommunityTemplate(snapshotId: string): Promise<CommunitySubmissionDetail>;
|
|
669
698
|
/**
|
|
670
699
|
* GET the install-time config contract for an installable template (its
|
|
671
700
|
* settings collection + the ordered keyed config/upload steps). Use it to
|
|
@@ -1100,6 +1129,32 @@ export interface AppRow {
|
|
|
1100
1129
|
updated_at: string;
|
|
1101
1130
|
deleted_at: string | null;
|
|
1102
1131
|
}
|
|
1132
|
+
/** One tombstoned row as the recovery bin reports it. */
|
|
1133
|
+
export interface DeletedAppRow {
|
|
1134
|
+
key: string;
|
|
1135
|
+
data: unknown;
|
|
1136
|
+
version: number;
|
|
1137
|
+
/** Who removed it. */
|
|
1138
|
+
author: {
|
|
1139
|
+
kind: string;
|
|
1140
|
+
id: string;
|
|
1141
|
+
};
|
|
1142
|
+
/** Who created it; null on rows predating the creator columns. */
|
|
1143
|
+
creator: {
|
|
1144
|
+
kind: string;
|
|
1145
|
+
id: string;
|
|
1146
|
+
} | null;
|
|
1147
|
+
created_at: string;
|
|
1148
|
+
deleted_at: string;
|
|
1149
|
+
/** When this row stops being recoverable. */
|
|
1150
|
+
recoverable_until: string;
|
|
1151
|
+
/** True once purged: contents already scrubbed, and restore refuses it. */
|
|
1152
|
+
purged: boolean;
|
|
1153
|
+
}
|
|
1154
|
+
export interface DeletedAppRowsPage {
|
|
1155
|
+
rows: DeletedAppRow[];
|
|
1156
|
+
next_before: string | null;
|
|
1157
|
+
}
|
|
1103
1158
|
export interface AppRowsPage {
|
|
1104
1159
|
rows: AppRow[];
|
|
1105
1160
|
next_cursor: string | null;
|
package/dist/client.js
CHANGED
|
@@ -1045,6 +1045,37 @@ export class HomespunClient {
|
|
|
1045
1045
|
if (!r.ok)
|
|
1046
1046
|
this.fail(r);
|
|
1047
1047
|
}
|
|
1048
|
+
/**
|
|
1049
|
+
* POST /v1/apps/:id/collections/:name/:key/restore: undo a soft delete.
|
|
1050
|
+
*
|
|
1051
|
+
* Owner/agent only, independent of the collection's permission lists. A row
|
|
1052
|
+
* that was PURGED is not restorable (410 `restore_expired`), and a restore
|
|
1053
|
+
* can legitimately fail on quota or on a unique value another live row took
|
|
1054
|
+
* while this one was deleted (409 `restore_conflict`).
|
|
1055
|
+
*/
|
|
1056
|
+
async restoreAppRow(appId, collection, key) {
|
|
1057
|
+
const r = await this.call("POST", `/v1/apps/${encodeURIComponent(appId)}/collections/${encodeURIComponent(collection)}/${encodeURIComponent(key)}/restore`);
|
|
1058
|
+
if (!r.ok)
|
|
1059
|
+
this.fail(r);
|
|
1060
|
+
return this.asObject(r);
|
|
1061
|
+
}
|
|
1062
|
+
/**
|
|
1063
|
+
* GET /v1/apps/:id/collections/:name/deleted: the recovery bin, newest
|
|
1064
|
+
* deletion first. Owner/agent only. Page with `before`, passing back the
|
|
1065
|
+
* previous page's `next_before`.
|
|
1066
|
+
*/
|
|
1067
|
+
async listDeletedAppRows(appId, collection, opts = {}) {
|
|
1068
|
+
const q = new URLSearchParams();
|
|
1069
|
+
if (opts.limit !== undefined)
|
|
1070
|
+
q.set("limit", String(opts.limit));
|
|
1071
|
+
if (opts.before !== undefined)
|
|
1072
|
+
q.set("before", opts.before);
|
|
1073
|
+
const qs = q.toString();
|
|
1074
|
+
const r = await this.call("GET", `/v1/apps/${encodeURIComponent(appId)}/collections/${encodeURIComponent(collection)}/deleted${qs ? `?${qs}` : ""}`);
|
|
1075
|
+
if (!r.ok)
|
|
1076
|
+
this.fail(r);
|
|
1077
|
+
return this.asObject(r);
|
|
1078
|
+
}
|
|
1048
1079
|
/** PATCH /v1/apps/:id/collections/:name/:key — optimistic-locked update. */
|
|
1049
1080
|
async updateAppRow(appId, collection, key, body) {
|
|
1050
1081
|
const r = await this.call("PATCH", `/v1/apps/${encodeURIComponent(appId)}/collections/${encodeURIComponent(collection)}/${encodeURIComponent(key)}`, body);
|
|
@@ -1164,6 +1195,21 @@ export class HomespunClient {
|
|
|
1164
1195
|
this.fail(r);
|
|
1165
1196
|
return this.asObject(r);
|
|
1166
1197
|
}
|
|
1198
|
+
/**
|
|
1199
|
+
* POST /v1/community/submissions/:id/unpublish (publisher): take your own
|
|
1200
|
+
* live listing down. It leaves the public gallery, search, and the direct
|
|
1201
|
+
* snapshot install link; existing installs are untouched, because an install
|
|
1202
|
+
* is a fresh private copy rather than a live reference. Idempotent, and 404
|
|
1203
|
+
* when the snapshot does not exist OR is not yours (indistinguishable on
|
|
1204
|
+
* purpose). Republish a new version to undo it.
|
|
1205
|
+
*/
|
|
1206
|
+
async unpublishCommunityTemplate(snapshotId) {
|
|
1207
|
+
const path = `/v1/community/submissions/${encodeURIComponent(snapshotId)}/unpublish`;
|
|
1208
|
+
const r = await this.call("POST", path);
|
|
1209
|
+
if (!r.ok)
|
|
1210
|
+
this.fail(r);
|
|
1211
|
+
return this.asObject(r);
|
|
1212
|
+
}
|
|
1167
1213
|
// -------------------------------------------------------------------------
|
|
1168
1214
|
// Agent-key community install (install-config programme, PR 4). Both act AS
|
|
1169
1215
|
// the calling agent's owning human, who becomes the installed app's owner. A
|
package/dist/icons.js
CHANGED
|
@@ -65,8 +65,8 @@ export function validateIconEmoji(raw) {
|
|
|
65
65
|
error: "icon_emoji must not contain control characters",
|
|
66
66
|
};
|
|
67
67
|
}
|
|
68
|
-
// Count grapheme clusters. Intl.Segmenter is available in
|
|
69
|
-
// evergreen browsers (our targets); guard defensively anyway.
|
|
68
|
+
// Count grapheme clusters. Intl.Segmenter is available in every supported
|
|
69
|
+
// Node and all evergreen browsers (our targets); guard defensively anyway.
|
|
70
70
|
let graphemeCount;
|
|
71
71
|
if (typeof Intl !== "undefined" && typeof Intl.Segmenter === "function") {
|
|
72
72
|
const seg = new Intl.Segmenter("en", { granularity: "grapheme" });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@homespunapps/core",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.40",
|
|
4
4
|
"description": "Homespun relay client: typed HTTP + WebSocket operations against a Homespun relay. Framework-free.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -45,10 +45,10 @@
|
|
|
45
45
|
"zod": "^4.4.3"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
|
-
"@types/node": "^26.1.
|
|
48
|
+
"@types/node": "^26.1.2",
|
|
49
49
|
"@types/ws": "^8.18.1",
|
|
50
50
|
"typescript": "^7.0.2",
|
|
51
|
-
"vitest": "^4.1.
|
|
51
|
+
"vitest": "^4.1.10"
|
|
52
52
|
},
|
|
53
53
|
"repository": {
|
|
54
54
|
"type": "git",
|