@fonderie/client 0.17.1 → 0.19.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/brain/signatures.md +32 -1
- package/dist/index.cjs +75 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +37 -2
- package/dist/index.d.ts +37 -2
- package/dist/index.js +74 -4
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/brain/signatures.md
CHANGED
|
@@ -48,6 +48,7 @@ new FonderieClient(opts: IFonderieClientOptions): FonderieClient
|
|
|
48
48
|
.audit: AuditClient
|
|
49
49
|
.webhooks: WebhooksClient
|
|
50
50
|
.customers: CustomersClient
|
|
51
|
+
.media: MediaClient
|
|
51
52
|
.setAccessToken(token: string | undefined): void
|
|
52
53
|
.clearCache(): void
|
|
53
54
|
.setWorkspaceId(workspaceId: string | undefined): void
|
|
@@ -58,11 +59,12 @@ new FonderieClient(opts: IFonderieClientOptions): FonderieClient
|
|
|
58
59
|
.patch<T = unknown>(path: string, body?: unknown, config?: IRequestConfig | undefined): Promise<IApiResponse<T>>
|
|
59
60
|
.delete<T = unknown>(path: string, config?: IRequestConfig | undefined): Promise<IApiResponse<T>>
|
|
60
61
|
|
|
61
|
-
new FonderieApiError(reason: string, explanation: string, status: number, details?: unknown): FonderieApiError
|
|
62
|
+
new FonderieApiError(reason: string, explanation: string, status: number, details?: unknown, requestId?: string | undefined): FonderieApiError
|
|
62
63
|
.reason: string
|
|
63
64
|
.explanation: string
|
|
64
65
|
.status: number
|
|
65
66
|
.details: unknown
|
|
67
|
+
.requestId: string | undefined
|
|
66
68
|
.name: string
|
|
67
69
|
.message: string
|
|
68
70
|
.stack: string
|
|
@@ -377,6 +379,20 @@ new CustomersClient(http: HttpClient, tokens: TokenStore): CustomersClient
|
|
|
377
379
|
.listLabels(type: CustomerLabelType, opts?: IReadOptions | undefined): Promise<IApiResponse<ICustomerLabelListResult>>
|
|
378
380
|
.removeLabel(labelId: string): Promise<IApiResponse<undefined>>
|
|
379
381
|
|
|
382
|
+
interface IUploadMediaInput {
|
|
383
|
+
dataBase64: string;
|
|
384
|
+
purpose?: string;
|
|
385
|
+
ownerType?: string;
|
|
386
|
+
ownerId?: string;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
new MediaClient(http: HttpClient, tokens: TokenStore): MediaClient
|
|
390
|
+
.setAccessToken(token: string | undefined): void
|
|
391
|
+
.upload(input: IUploadMediaInput): Promise<IApiResponse<IMediaAssetResult>>
|
|
392
|
+
.delete(id: string): Promise<IApiResponse<{ id: string; }>>
|
|
393
|
+
.assetUrl(id: string): string
|
|
394
|
+
.assetIdFromUrl(url: string | null | undefined): string | null
|
|
395
|
+
|
|
380
396
|
interface ICreateWebhookEndpointInput {
|
|
381
397
|
url: string;
|
|
382
398
|
events?: string[];
|
|
@@ -800,6 +816,21 @@ interface ILoginResult {
|
|
|
800
816
|
requiresVerification?: boolean;
|
|
801
817
|
}
|
|
802
818
|
|
|
819
|
+
interface IMediaAssetDTO {
|
|
820
|
+
id: string;
|
|
821
|
+
url: string;
|
|
822
|
+
contentType: string;
|
|
823
|
+
byteSize: number;
|
|
824
|
+
ownerType: string;
|
|
825
|
+
ownerId: string;
|
|
826
|
+
purpose: string;
|
|
827
|
+
createdAt: string;
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
interface IMediaAssetResult {
|
|
831
|
+
asset: IMediaAssetDTO;
|
|
832
|
+
}
|
|
833
|
+
|
|
803
834
|
interface IMemberDTO {
|
|
804
835
|
userId: string;
|
|
805
836
|
workspaceId: string;
|
package/dist/index.cjs
CHANGED
|
@@ -28,6 +28,7 @@ __export(index_exports, {
|
|
|
28
28
|
CustomersClient: () => CustomersClient,
|
|
29
29
|
FonderieApiError: () => FonderieApiError,
|
|
30
30
|
FonderieClient: () => FonderieClient,
|
|
31
|
+
MediaClient: () => MediaClient,
|
|
31
32
|
WebhooksClient: () => WebhooksClient,
|
|
32
33
|
WorkspacesClient: () => WorkspacesClient,
|
|
33
34
|
createMemoryCache: () => createMemoryCache,
|
|
@@ -74,19 +75,26 @@ function createMemoryCache(opts = {}) {
|
|
|
74
75
|
|
|
75
76
|
// src/http.ts
|
|
76
77
|
var FonderieApiError = class extends Error {
|
|
77
|
-
constructor(reason, explanation, status, details) {
|
|
78
|
+
constructor(reason, explanation, status, details, requestId) {
|
|
78
79
|
super(explanation);
|
|
79
80
|
this.reason = reason;
|
|
80
81
|
this.explanation = explanation;
|
|
81
82
|
this.status = status;
|
|
82
83
|
this.details = details;
|
|
84
|
+
this.requestId = requestId;
|
|
83
85
|
this.name = "FonderieApiError";
|
|
84
86
|
}
|
|
85
87
|
reason;
|
|
86
88
|
explanation;
|
|
87
89
|
status;
|
|
88
90
|
details;
|
|
91
|
+
requestId;
|
|
89
92
|
};
|
|
93
|
+
function newRequestId() {
|
|
94
|
+
const c = globalThis.crypto;
|
|
95
|
+
if (c?.randomUUID) return c.randomUUID();
|
|
96
|
+
return `r-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
|
|
97
|
+
}
|
|
90
98
|
var HttpClient = class {
|
|
91
99
|
constructor(baseUrl, deps = {}) {
|
|
92
100
|
this.baseUrl = baseUrl;
|
|
@@ -98,6 +106,12 @@ var HttpClient = class {
|
|
|
98
106
|
cache;
|
|
99
107
|
defaultTtlMs;
|
|
100
108
|
refresh;
|
|
109
|
+
// Absolute URL for a path on this client's origin — for endpoints a browser
|
|
110
|
+
// navigates to or embeds (e.g. a public `<img src>`) rather than fetches
|
|
111
|
+
// through request(). Mirrors the `${baseUrl}${path}` join request() uses.
|
|
112
|
+
absolute(path) {
|
|
113
|
+
return `${this.baseUrl}${path}`;
|
|
114
|
+
}
|
|
101
115
|
// Drop all cached responses — sign-out must not leave one session's data
|
|
102
116
|
// servable to the next.
|
|
103
117
|
clearCache() {
|
|
@@ -128,7 +142,11 @@ var HttpClient = class {
|
|
|
128
142
|
return data;
|
|
129
143
|
}
|
|
130
144
|
async exec(opts, retried = false) {
|
|
131
|
-
const
|
|
145
|
+
const requestId = newRequestId();
|
|
146
|
+
const headers = {
|
|
147
|
+
"Content-Type": "application/json",
|
|
148
|
+
"X-Request-ID": requestId
|
|
149
|
+
};
|
|
132
150
|
if (opts.token) headers["Authorization"] = `Bearer ${opts.token}`;
|
|
133
151
|
if (opts.cookie) headers["Cookie"] = opts.cookie;
|
|
134
152
|
if (opts.workspaceId) headers["X-Workspace-ID"] = opts.workspaceId;
|
|
@@ -136,18 +154,19 @@ var HttpClient = class {
|
|
|
136
154
|
const fetchInit = { method: opts.method, headers, credentials: "include" };
|
|
137
155
|
if (opts.body !== void 0) fetchInit.body = JSON.stringify(opts.body);
|
|
138
156
|
const res = await fetch(`${this.baseUrl}${opts.path}`, fetchInit);
|
|
157
|
+
const rid = res.headers.get("x-request-id") ?? requestId;
|
|
139
158
|
if (res.status === 401 && this.refresh && !retried && !opts.path.startsWith("/auth/")) {
|
|
140
159
|
const newToken = await this.refresh();
|
|
141
160
|
if (newToken) return this.exec({ ...opts, token: newToken }, true);
|
|
142
161
|
}
|
|
143
162
|
if (res.status === 204) {
|
|
144
|
-
if (!res.ok) throw new FonderieApiError("unknown", res.statusText, res.status);
|
|
163
|
+
if (!res.ok) throw new FonderieApiError("unknown", res.statusText, res.status, void 0, rid);
|
|
145
164
|
return void 0;
|
|
146
165
|
}
|
|
147
166
|
const data = await res.json();
|
|
148
167
|
if (!res.ok || res.status === 202) {
|
|
149
168
|
const err = data;
|
|
150
|
-
throw new FonderieApiError(err.reason, err.explanation, res.status, err.details);
|
|
169
|
+
throw new FonderieApiError(err.reason, err.explanation, res.status, err.details, rid);
|
|
151
170
|
}
|
|
152
171
|
return data;
|
|
153
172
|
}
|
|
@@ -1020,6 +1039,55 @@ var CustomersClient = class {
|
|
|
1020
1039
|
}
|
|
1021
1040
|
};
|
|
1022
1041
|
|
|
1042
|
+
// src/modules/media.ts
|
|
1043
|
+
var MediaClient = class {
|
|
1044
|
+
constructor(http, tokens) {
|
|
1045
|
+
this.http = http;
|
|
1046
|
+
this.tokens = tokens;
|
|
1047
|
+
}
|
|
1048
|
+
http;
|
|
1049
|
+
tokens;
|
|
1050
|
+
setAccessToken(token) {
|
|
1051
|
+
this.tokens.set(token);
|
|
1052
|
+
}
|
|
1053
|
+
// POST /media — store an image; returns the asset with its monomorphic
|
|
1054
|
+
// /media/:id url. requireAuth server-side.
|
|
1055
|
+
upload(input) {
|
|
1056
|
+
return this.http.request({
|
|
1057
|
+
method: "POST",
|
|
1058
|
+
path: "/media",
|
|
1059
|
+
body: input,
|
|
1060
|
+
token: this.tokens.get()
|
|
1061
|
+
});
|
|
1062
|
+
}
|
|
1063
|
+
// DELETE /media/:id — uploader-only (403 for anyone else).
|
|
1064
|
+
delete(id) {
|
|
1065
|
+
return this.http.request({
|
|
1066
|
+
method: "DELETE",
|
|
1067
|
+
path: `/media/${encodeURIComponent(id)}`,
|
|
1068
|
+
token: this.tokens.get()
|
|
1069
|
+
});
|
|
1070
|
+
}
|
|
1071
|
+
// Absolute URL for a stored asset — an `<img src>` target. The GET /media/:id
|
|
1072
|
+
// route is public and cached (it can't carry a Bearer token), so turn an
|
|
1073
|
+
// upload's `asset.id` into a browser-loadable URL with this, and use it as
|
|
1074
|
+
// the avatarUrl handed to auth's updateProfile.
|
|
1075
|
+
assetUrl(id) {
|
|
1076
|
+
return this.http.absolute(`/media/${encodeURIComponent(id)}`);
|
|
1077
|
+
}
|
|
1078
|
+
// Inverse of assetUrl: pull the asset id out of one of THIS brick's
|
|
1079
|
+
// /media/:id URLs (absolute or relative); null for empty/external URLs. Lets
|
|
1080
|
+
// avatar cleanup delete only assets we minted (matched as a UUID), never a
|
|
1081
|
+
// placeholder or third-party avatar URL.
|
|
1082
|
+
assetIdFromUrl(url) {
|
|
1083
|
+
if (!url) return null;
|
|
1084
|
+
const m = url.match(
|
|
1085
|
+
/\/media\/([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})(?:[/?#]|$)/i
|
|
1086
|
+
);
|
|
1087
|
+
return m ? m[1] : null;
|
|
1088
|
+
}
|
|
1089
|
+
};
|
|
1090
|
+
|
|
1023
1091
|
// src/modules/webhooks.ts
|
|
1024
1092
|
var WebhooksClient = class {
|
|
1025
1093
|
constructor(http, tokens) {
|
|
@@ -1355,6 +1423,7 @@ var FonderieClient = class {
|
|
|
1355
1423
|
audit;
|
|
1356
1424
|
webhooks;
|
|
1357
1425
|
customers;
|
|
1426
|
+
media;
|
|
1358
1427
|
http;
|
|
1359
1428
|
tokens;
|
|
1360
1429
|
workspaceId;
|
|
@@ -1377,6 +1446,7 @@ var FonderieClient = class {
|
|
|
1377
1446
|
this.audit = new AuditClient(this.http, this.tokens);
|
|
1378
1447
|
this.webhooks = new WebhooksClient(this.http, this.tokens);
|
|
1379
1448
|
this.customers = new CustomersClient(this.http, this.tokens);
|
|
1449
|
+
this.media = new MediaClient(this.http, this.tokens);
|
|
1380
1450
|
if (opts.workspaceId !== void 0) this.setWorkspaceId(opts.workspaceId);
|
|
1381
1451
|
}
|
|
1382
1452
|
// Single-flight refresh: POST /auth/refresh with the app-supplied refresh
|
|
@@ -1665,6 +1735,7 @@ function isMfaRequired(result) {
|
|
|
1665
1735
|
CustomersClient,
|
|
1666
1736
|
FonderieApiError,
|
|
1667
1737
|
FonderieClient,
|
|
1738
|
+
MediaClient,
|
|
1668
1739
|
WebhooksClient,
|
|
1669
1740
|
WorkspacesClient,
|
|
1670
1741
|
createMemoryCache,
|