@inverted-tech/fragments 0.10.9 → 0.11.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/dist/esm/api.js +292 -0
- package/dist/protos/api.d.ts +491 -0
- package/package.json +7 -6
- package/dist/esm/client.js +0 -297
- package/dist/protos/client.d.ts +0 -185
package/dist/esm/api.js
ADDED
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-platform API client utilities
|
|
3
|
+
*
|
|
4
|
+
* Framework-agnostic: works in Next.js (SSR/SSG), browser SPAs, and Node.js.
|
|
5
|
+
* The caller is responsible for resolving the base URL from their environment.
|
|
6
|
+
*
|
|
7
|
+
* @example Next.js
|
|
8
|
+
* ```ts
|
|
9
|
+
* const isServer = typeof window === 'undefined';
|
|
10
|
+
* const baseUrl = isServer
|
|
11
|
+
* ? (process.env.API_BASE_URL ?? process.env.NEXT_PUBLIC_API_BASE_URL ?? '')
|
|
12
|
+
* : (process.env.NEXT_PUBLIC_API_BASE_URL ?? '');
|
|
13
|
+
* export const api = createApiClient(baseUrl);
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* @example Vite SPA
|
|
17
|
+
* ```ts
|
|
18
|
+
* export const api = createApiClient(import.meta.env.VITE_API_BASE_URL ?? '');
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
const DEFAULT_HEADERS = {
|
|
22
|
+
'Content-Type': 'application/json',
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Cross-platform fetch wrapper with error handling.
|
|
26
|
+
*
|
|
27
|
+
* - Merges caller headers on top of the default Content-Type header.
|
|
28
|
+
* - Defaults cache to `no-store` unless `cache` or `next` is explicitly provided
|
|
29
|
+
* (avoids the Next.js 2 MB data-cache write limit).
|
|
30
|
+
* - Passes `next` through transparently for Next.js ISR tag/revalidation support.
|
|
31
|
+
*/
|
|
32
|
+
export async function apiCall(url, options = {}) {
|
|
33
|
+
const { next, cache, headers: callerHeaders, ...restOptions } = options;
|
|
34
|
+
const mergedHeaders = {
|
|
35
|
+
...DEFAULT_HEADERS,
|
|
36
|
+
...callerHeaders,
|
|
37
|
+
};
|
|
38
|
+
const finalOptions = {
|
|
39
|
+
...restOptions,
|
|
40
|
+
headers: mergedHeaders,
|
|
41
|
+
};
|
|
42
|
+
// Respect an explicit cache option; otherwise default to no-store to avoid
|
|
43
|
+
// the Next.js 2 MB data-cache limit. Skip the default when `next` is set,
|
|
44
|
+
// since that implies the caller wants ISR caching behaviour.
|
|
45
|
+
if (cache !== undefined) {
|
|
46
|
+
finalOptions['cache'] = cache;
|
|
47
|
+
}
|
|
48
|
+
else if (!next) {
|
|
49
|
+
finalOptions['cache'] = 'no-store';
|
|
50
|
+
}
|
|
51
|
+
if (next !== undefined) {
|
|
52
|
+
finalOptions['next'] = next;
|
|
53
|
+
}
|
|
54
|
+
const response = await fetch(url, finalOptions);
|
|
55
|
+
if (!response.ok) {
|
|
56
|
+
throw new Error(`API call failed: ${response.status} ${response.statusText}`);
|
|
57
|
+
}
|
|
58
|
+
return response.json();
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Build the endpoint map for a given base URL.
|
|
62
|
+
* Call once during app initialization with your resolved base URL.
|
|
63
|
+
*/
|
|
64
|
+
export function createApiEndpoints(baseUrl) {
|
|
65
|
+
return {
|
|
66
|
+
auth: {
|
|
67
|
+
login: `${baseUrl}/auth/login`,
|
|
68
|
+
logout: `${baseUrl}/auth/logout`,
|
|
69
|
+
createUser: `${baseUrl}/auth/createuser`,
|
|
70
|
+
adminCreateUser: `${baseUrl}/auth/admin/createuser`,
|
|
71
|
+
refresh: `${baseUrl}/auth/renewtoken`,
|
|
72
|
+
changePassword: `${baseUrl}/auth/password`,
|
|
73
|
+
adminChangePassword: `${baseUrl}/auth/admin/password`,
|
|
74
|
+
getCurrentUser: `${baseUrl}/auth/user`,
|
|
75
|
+
editOwnUser: `${baseUrl}/auth/user`,
|
|
76
|
+
getUserById: (userId) => `${baseUrl}/auth/user/${userId}`,
|
|
77
|
+
getUserByName: (userName) => `${baseUrl}/auth/username/${userName}`,
|
|
78
|
+
getUserIds: `${baseUrl}/auth/user/ids`,
|
|
79
|
+
getProfileImage: `${baseUrl}/auth/profileimage`,
|
|
80
|
+
getUserProfileImage: (userId) => `${baseUrl}/auth/user/${userId}/profileimage`,
|
|
81
|
+
uploadProfileImage: `${baseUrl}/auth/profileimage`,
|
|
82
|
+
adminUploadProfileImage: `${baseUrl}/auth/admin/profileimage`,
|
|
83
|
+
totp: `${baseUrl}/auth/totp`,
|
|
84
|
+
disableTotp: (id) => `${baseUrl}/auth/totp/${id}/disable/`,
|
|
85
|
+
verifyTotp: (id) => `${baseUrl}/auth/totp/${id}/verify/`,
|
|
86
|
+
adminGetUsers: `${baseUrl}/auth/admin/user`,
|
|
87
|
+
adminAddUser: `${baseUrl}/auth/admin/user`,
|
|
88
|
+
adminGetUser: (userId) => `${baseUrl}/auth/admin/user/${userId}`,
|
|
89
|
+
adminDisableUser: (userId) => `${baseUrl}/auth/admin/user/${userId}/disable`,
|
|
90
|
+
adminEnableUser: (userId) => `${baseUrl}/auth/admin/user/${userId}/enable`,
|
|
91
|
+
adminSetRoles: `${baseUrl}/auth/admin/user/roles`,
|
|
92
|
+
adminSearch: `${baseUrl}/auth/admin/search`,
|
|
93
|
+
adminGetTotp: (userId) => `${baseUrl}/auth/admin/totp/${userId}`,
|
|
94
|
+
adminCreateTotp: (userId) => `${baseUrl}/auth/admin/totp/${userId}`,
|
|
95
|
+
adminDisableTotp: (userId, totpId) => `${baseUrl}/auth/admin/totp/${userId}/${totpId}/disable`,
|
|
96
|
+
adminVerifyTotp: (userId, totpId) => `${baseUrl}/auth/admin/totp/${userId}/${totpId}/verify`,
|
|
97
|
+
},
|
|
98
|
+
asset: {
|
|
99
|
+
getAssetData: (id) => `${baseUrl}/cms/asset/${id}/data`,
|
|
100
|
+
createAudioAsset: `${baseUrl}/cms/asset/audio`,
|
|
101
|
+
createAsset: `${baseUrl}/cms/admin/asset`,
|
|
102
|
+
getAsset: (id) => `${baseUrl}/cms/asset/${id}`,
|
|
103
|
+
adminGetAsset: (id) => `${baseUrl}/cms/admin/asset/${id}`,
|
|
104
|
+
adminGetAssetByOldId: (id) => `${baseUrl}/cms/admin/asset/old/${id}`,
|
|
105
|
+
adminGetImageAssets: `${baseUrl}/cms/admin/asset/image`,
|
|
106
|
+
searchAssets: `${baseUrl}/cms/admin/asset/search`,
|
|
107
|
+
},
|
|
108
|
+
auditLog: {
|
|
109
|
+
adminGetAuditLog: `${baseUrl}/admin/audit-log`,
|
|
110
|
+
},
|
|
111
|
+
careers: {
|
|
112
|
+
createCareer: `${baseUrl}/admin/careers`,
|
|
113
|
+
getCareersAdmin: `${baseUrl}/admin/careers`,
|
|
114
|
+
getCareer: (id) => `${baseUrl}/careers/${id}`,
|
|
115
|
+
getCareers: `${baseUrl}/careers`,
|
|
116
|
+
adminUpdateCareer: (id) => `${baseUrl}/admin/careers/${id}`,
|
|
117
|
+
adminDeleteCareer: (id) => `${baseUrl}/admin/careers/${id}`,
|
|
118
|
+
},
|
|
119
|
+
category: {
|
|
120
|
+
createCategory: `${baseUrl}/settings/category/create`,
|
|
121
|
+
deleteCategory: (id) => `${baseUrl}/settings/category/delete/${id}`,
|
|
122
|
+
},
|
|
123
|
+
channel: {
|
|
124
|
+
getChannels: `${baseUrl}/settings/channel`,
|
|
125
|
+
createChannel: `${baseUrl}/settings/channel/create`,
|
|
126
|
+
deleteChannel: (id) => `${baseUrl}/settings/channel/delete/${id}`,
|
|
127
|
+
getChannelDetails: (id) => `${baseUrl}/settings/channel/details/${id}`,
|
|
128
|
+
},
|
|
129
|
+
comment: {
|
|
130
|
+
adminDeleteComment: (id) => `${baseUrl}/comment/admin/${id}/delete`,
|
|
131
|
+
adminPinComment: (id) => `${baseUrl}/comment/admin/${id}/pin`,
|
|
132
|
+
adminUndeleteComment: (id) => `${baseUrl}/comment/admin/${id}/undelete`,
|
|
133
|
+
adminUnpinComment: (id) => `${baseUrl}/comment/admin/${id}/unpin`,
|
|
134
|
+
createCommentForContent: (id) => `${baseUrl}/comment/content/${id}/create`,
|
|
135
|
+
createCommentForComment: (id) => `${baseUrl}/comment/${id}/create`,
|
|
136
|
+
deleteOwnComment: (id) => `${baseUrl}/comment/${id}/delete`,
|
|
137
|
+
editOwnComment: (id) => `${baseUrl}/comment/${id}/edit`,
|
|
138
|
+
getCommentForContent: (id) => `${baseUrl}/comment/content/${id}`,
|
|
139
|
+
getCommentsForComment: (id) => `${baseUrl}/comment/${id}`,
|
|
140
|
+
likeComment: (id) => `${baseUrl}/comment/${id}/like`,
|
|
141
|
+
unlikeComment: (id) => `${baseUrl}/comment/${id}/unlike`,
|
|
142
|
+
},
|
|
143
|
+
cms: {
|
|
144
|
+
// Content
|
|
145
|
+
announceContent: (id) => `${baseUrl}/cms/admin/content/${id}/announce`,
|
|
146
|
+
createContent: `${baseUrl}/cms/admin/content`,
|
|
147
|
+
adminListContent: `${baseUrl}/cms/admin/content`,
|
|
148
|
+
deleteContent: (id) => `${baseUrl}/cms/admin/content/${id}`,
|
|
149
|
+
adminGetContentById: (id) => `${baseUrl}/cms/admin/content/${id}`,
|
|
150
|
+
adminUpdateContent: (id) => `${baseUrl}/cms/admin/content/${id}`,
|
|
151
|
+
listContent: `${baseUrl}/cms/content`,
|
|
152
|
+
getContentById: (id) => `${baseUrl}/cms/content/${id}`,
|
|
153
|
+
getContentByUrl: (url) => `${baseUrl}/cms/content/url?ContentUrl=${url}`,
|
|
154
|
+
getRecentCategories: `${baseUrl}/cms/categories/recent`,
|
|
155
|
+
getRecentTags: `${baseUrl}/cms/tags/recent`,
|
|
156
|
+
getContentByChannel: (channelId, pageSize = 10) => `${baseUrl}/cms/content?ChannelIds=[${channelId}]&PageSize=${pageSize}`,
|
|
157
|
+
getRelated: (contentId, pageSize = 5) => `${baseUrl}/cms/content/${contentId}/related/?PageSize=${pageSize}`,
|
|
158
|
+
publishContent: (id) => `${baseUrl}/cms/admin/content/${id}/publish`,
|
|
159
|
+
searchContent: `${baseUrl}/cms/search`,
|
|
160
|
+
unannounceContent: (id) => `${baseUrl}/cms/admin/content/${id}/unannounce`,
|
|
161
|
+
undeleteContent: (id) => `${baseUrl}/cms/admin/content/${id}/undelete`,
|
|
162
|
+
unpublishContent: (id) => `${baseUrl}/cms/admin/content/${id}/unpublish`,
|
|
163
|
+
// Pages
|
|
164
|
+
createPage: `${baseUrl}/cms/admin/page`,
|
|
165
|
+
adminListPages: `${baseUrl}/cms/admin/page`,
|
|
166
|
+
deletePage: (id) => `${baseUrl}/cms/admin/page/${id}`,
|
|
167
|
+
adminGetPageById: (id) => `${baseUrl}/cms/admin/page/${id}`,
|
|
168
|
+
adminUpdatePage: (id) => `${baseUrl}/cms/admin/page/${id}`,
|
|
169
|
+
listPages: `${baseUrl}/cms/page`,
|
|
170
|
+
getPageById: (id) => `${baseUrl}/cms/page/${id}`,
|
|
171
|
+
getPageByUrl: `${baseUrl}/cms/page/url`,
|
|
172
|
+
publishPage: (id) => `${baseUrl}/cms/admin/page/${id}/publish`,
|
|
173
|
+
searchPages: `${baseUrl}/cms/page/search`,
|
|
174
|
+
undeletePage: (id) => `${baseUrl}/cms/admin/page/${id}/undelete`,
|
|
175
|
+
unpublishPage: (id) => `${baseUrl}/cms/admin/page/${id}/unpublish`,
|
|
176
|
+
},
|
|
177
|
+
settings: {
|
|
178
|
+
publicSettings: `${baseUrl}/settings/public`,
|
|
179
|
+
publicSettingsNewer: (version) => `${baseUrl}/settings/public/newer/${version}`,
|
|
180
|
+
adminSettings: `${baseUrl}/settings/admin`,
|
|
181
|
+
adminSettingsNewer: (version) => `${baseUrl}/settings/admin/newer/${version}`,
|
|
182
|
+
ownerSettings: `${baseUrl}/settings/owner`,
|
|
183
|
+
ownerSettingsNewer: (version) => `${baseUrl}/settings/owner/newer/${version}`,
|
|
184
|
+
channels: `${baseUrl}/settings/channel`,
|
|
185
|
+
channelById: (channelId) => `${baseUrl}/settings/channels/details/${channelId}`,
|
|
186
|
+
saveCmsPublic: `${baseUrl}/settings/cms/public`,
|
|
187
|
+
saveCmsPrivate: `${baseUrl}/settings/cms/private`,
|
|
188
|
+
saveCmsOwner: `${baseUrl}/settings/cms/owner`,
|
|
189
|
+
savePersonalizationPublic: `${baseUrl}/settings/personalization/public`,
|
|
190
|
+
savePersonalizationPrivate: `${baseUrl}/settings/personalization/private`,
|
|
191
|
+
savePersonalizationOwner: `${baseUrl}/settings/personalization/owner`,
|
|
192
|
+
saveSubscriptionPublic: `${baseUrl}/settings/subscription/public`,
|
|
193
|
+
saveSubscriptionPrivate: `${baseUrl}/settings/subscription/private`,
|
|
194
|
+
saveSubscriptionOwner: `${baseUrl}/settings/subscription/owner`,
|
|
195
|
+
saveCommentsPublic: `${baseUrl}/settings/comments/public`,
|
|
196
|
+
saveCommentsPrivate: `${baseUrl}/settings/comments/private`,
|
|
197
|
+
saveCommentsOwner: `${baseUrl}/settings/comments/owner`,
|
|
198
|
+
saveNotificationPublic: `${baseUrl}/settings/notification/public`,
|
|
199
|
+
saveNotificationPrivate: `${baseUrl}/settings/notification/private`,
|
|
200
|
+
saveNotificationOwner: `${baseUrl}/settings/notification/owner`,
|
|
201
|
+
saveEventsPublic: `${baseUrl}/settings/events/public`,
|
|
202
|
+
saveEventsPrivate: `${baseUrl}/settings/events/private`,
|
|
203
|
+
saveEventsOwner: `${baseUrl}/settings/events/owner`,
|
|
204
|
+
},
|
|
205
|
+
dashboard: {
|
|
206
|
+
getDashboard: `${baseUrl}/admin/dashboard`,
|
|
207
|
+
},
|
|
208
|
+
events: {
|
|
209
|
+
getEvent: (eventId) => `${baseUrl}/events/${eventId}`,
|
|
210
|
+
getEvents: `${baseUrl}/events`,
|
|
211
|
+
getTicket: (eventId, ticketId) => `${baseUrl}/events/${eventId}/tickets/${ticketId}`,
|
|
212
|
+
getTickets: (eventId) => `${baseUrl}/events/${eventId}/tickets`,
|
|
213
|
+
cancelTicket: (eventId, ticketId) => `${baseUrl}/events/${eventId}/tickets/${ticketId}/cancel`,
|
|
214
|
+
reserveTicket: (eventId) => `${baseUrl}/events/${eventId}/tickets/reserve`,
|
|
215
|
+
useTicket: `${baseUrl}/events/tickets/use`,
|
|
216
|
+
},
|
|
217
|
+
adminEvents: {
|
|
218
|
+
createEvent: `${baseUrl}/admin/events/create`,
|
|
219
|
+
createRecurringEvent: `${baseUrl}/admin/events/create-recurring`,
|
|
220
|
+
getEvent: (eventId) => `${baseUrl}/admin/events/${eventId}`,
|
|
221
|
+
getEvents: `${baseUrl}/admin/events`,
|
|
222
|
+
modifyEvent: `${baseUrl}/admin/events/modify`,
|
|
223
|
+
cancelEvent: `${baseUrl}/admin/events/cancel`,
|
|
224
|
+
cancelAllRecurring: `${baseUrl}/admin/events/cancel-all-recurring`,
|
|
225
|
+
getTicket: (eventId, ticketId) => `${baseUrl}/admin/events/${eventId}/tickets/${ticketId}`,
|
|
226
|
+
getTickets: (eventId) => `${baseUrl}/admin/events/${eventId}/tickets`,
|
|
227
|
+
cancelTicket: (eventId, ticketId) => `${baseUrl}/admin/events/${eventId}/tickets/${ticketId}/cancel`,
|
|
228
|
+
reserveTicket: (eventId) => `${baseUrl}/admin/events/${eventId}/tickets/reserve`,
|
|
229
|
+
},
|
|
230
|
+
payments: {
|
|
231
|
+
getSubscriptions: `${baseUrl}/payment/subscription`,
|
|
232
|
+
getSubscriptionById: (id) => `${baseUrl}/payment/subscription/${id}`,
|
|
233
|
+
reconcileSubscription: `${baseUrl}/payment/subscription/reconcile`,
|
|
234
|
+
newSubscription: (level, postalCode, successUrl, cancelUrl) => `${baseUrl}/payment/new/${level}?PostalCode=${postalCode}&SuccessUrl=${successUrl}&CancelUrl=${cancelUrl}`,
|
|
235
|
+
cancelSubscription: `${baseUrl}/payment/subscription/cancel`,
|
|
236
|
+
getSinglePayments: `${baseUrl}/payment/single`,
|
|
237
|
+
getSinglePayment: (id) => `${baseUrl}/payment/single/${id}`,
|
|
238
|
+
newSinglePayment: `${baseUrl}/payment/single/new`,
|
|
239
|
+
finishStripe: `${baseUrl}/payment/stripe/subscription/finish`,
|
|
240
|
+
finishFortis: `${baseUrl}/payment/fortis/subscription/finish`,
|
|
241
|
+
newPaypal: `${baseUrl}/payment/paypal/subscription/new`,
|
|
242
|
+
},
|
|
243
|
+
adminPayments: {
|
|
244
|
+
bulkCancel: `${baseUrl}/payment/admin/bulk/cancel`,
|
|
245
|
+
bulkStart: `${baseUrl}/payment/admin/bulk/start`,
|
|
246
|
+
getBulk: `${baseUrl}/payment/admin/bulk`,
|
|
247
|
+
cancelUserSubscription: (userId, subscriptionId) => `${baseUrl}/payment/admin/user/${userId}/subscription/${subscriptionId}/cancel`,
|
|
248
|
+
getUserSubscription: (userId, subscriptionId) => `${baseUrl}/payment/admin/user/${userId}/subscription/${subscriptionId}`,
|
|
249
|
+
getUserSubscriptions: (userId) => `${baseUrl}/payment/admin/user/${userId}/subscription`,
|
|
250
|
+
getUserSinglePayment: (userId, paymentId) => `${baseUrl}/payment/admin/user/${userId}/single/${paymentId}`,
|
|
251
|
+
getUserSinglePayments: (userId) => `${baseUrl}/payment/admin/user/${userId}/single`,
|
|
252
|
+
reconcileUserSubscription: (userId, subscriptionId) => `${baseUrl}/payment/admin/user/${userId}/subscription/${subscriptionId}/reconcile`,
|
|
253
|
+
getSubscriptions: `${baseUrl}/payment/admin/subscriptions`,
|
|
254
|
+
},
|
|
255
|
+
manualPayments: {
|
|
256
|
+
adminCancelSubscription: (userId, subscriptionId) => `${baseUrl}/payment/manual/admin/user/${userId}/subscription/${subscriptionId}/cancel`,
|
|
257
|
+
cancelSubscription: (subscriptionId) => `${baseUrl}/payment/manual/subscription/${subscriptionId}/cancel`,
|
|
258
|
+
adminGetSubscription: (userId, subscriptionId) => `${baseUrl}/payment/manual/admin/user/${userId}/subscription/${subscriptionId}`,
|
|
259
|
+
adminGetSubscriptions: (userId) => `${baseUrl}/payment/manual/admin/user/${userId}/subscription`,
|
|
260
|
+
getSubscriptions: `${baseUrl}/payment/manual/subscription`,
|
|
261
|
+
getSubscription: (subscriptionId) => `${baseUrl}/payment/manual/subscription/${subscriptionId}`,
|
|
262
|
+
adminNewSubscription: (userId) => `${baseUrl}/payment/manual/admin/user/${userId}/subscription/new`,
|
|
263
|
+
newSubscription: `${baseUrl}/payment/manual/subscription/new`,
|
|
264
|
+
},
|
|
265
|
+
stats: {
|
|
266
|
+
like: (contentId) => `${baseUrl}/stats/${contentId}/like`,
|
|
267
|
+
unlike: (contentId) => `${baseUrl}/stats/${contentId}/unlike`,
|
|
268
|
+
progress: (contentId) => `${baseUrl}/stats/${contentId}/progress`,
|
|
269
|
+
save: (contentId) => `${baseUrl}/stats/${contentId}/save`,
|
|
270
|
+
unSave: (contentId) => `${baseUrl}/stats/${contentId}/unsave`,
|
|
271
|
+
logShare: (contentId) => `${baseUrl}/stats/${contentId}/logshare`,
|
|
272
|
+
getContentStats: (contentId) => `${baseUrl}/stats/${contentId}`,
|
|
273
|
+
getUserStats: (userId) => `${baseUrl}/stats/user/${userId}`,
|
|
274
|
+
getCurrentUserStats: `${baseUrl}/stats/user`,
|
|
275
|
+
getUserLikes: `${baseUrl}/stats/user/likes`,
|
|
276
|
+
getUserProgress: `${baseUrl}/stats/user/progress`,
|
|
277
|
+
getUserSaves: `${baseUrl}/stats/user/saves`,
|
|
278
|
+
},
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Create a complete API client bound to a base URL.
|
|
283
|
+
*
|
|
284
|
+
* Returns `endpoints` (the full URL map) and `call` (the fetch wrapper),
|
|
285
|
+
* both pre-bound to the provided base URL.
|
|
286
|
+
*/
|
|
287
|
+
export function createApiClient(baseUrl) {
|
|
288
|
+
return {
|
|
289
|
+
endpoints: createApiEndpoints(baseUrl),
|
|
290
|
+
call: (url, options) => apiCall(url, options),
|
|
291
|
+
};
|
|
292
|
+
}
|
|
@@ -0,0 +1,491 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-platform API client utilities
|
|
3
|
+
*
|
|
4
|
+
* Framework-agnostic: works in Next.js (SSR/SSG), browser SPAs, and Node.js.
|
|
5
|
+
* The caller is responsible for resolving the base URL from their environment.
|
|
6
|
+
*
|
|
7
|
+
* @example Next.js
|
|
8
|
+
* ```ts
|
|
9
|
+
* const isServer = typeof window === 'undefined';
|
|
10
|
+
* const baseUrl = isServer
|
|
11
|
+
* ? (process.env.API_BASE_URL ?? process.env.NEXT_PUBLIC_API_BASE_URL ?? '')
|
|
12
|
+
* : (process.env.NEXT_PUBLIC_API_BASE_URL ?? '');
|
|
13
|
+
* export const api = createApiClient(baseUrl);
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* @example Vite SPA
|
|
17
|
+
* ```ts
|
|
18
|
+
* export const api = createApiClient(import.meta.env.VITE_API_BASE_URL ?? '');
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
type FetchCacheMode = 'default' | 'force-cache' | 'no-cache' | 'no-store' | 'only-if-cached' | 'reload';
|
|
22
|
+
/** Subset of fetch init options we care about, plus an escape hatch for anything else. */
|
|
23
|
+
export interface FetchInit {
|
|
24
|
+
method?: string;
|
|
25
|
+
headers?: Record<string, string>;
|
|
26
|
+
body?: string | null;
|
|
27
|
+
cache?: FetchCacheMode;
|
|
28
|
+
mode?: string;
|
|
29
|
+
credentials?: string;
|
|
30
|
+
signal?: unknown;
|
|
31
|
+
[key: string]: unknown;
|
|
32
|
+
}
|
|
33
|
+
/** Next.js extended fetch options — passed through as-is; non-Next runtimes ignore them. */
|
|
34
|
+
export interface NextFetchExtensions {
|
|
35
|
+
next?: {
|
|
36
|
+
tags?: string[];
|
|
37
|
+
revalidate?: number | false;
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
export type ApiCallOptions = FetchInit & NextFetchExtensions;
|
|
41
|
+
/**
|
|
42
|
+
* Cross-platform fetch wrapper with error handling.
|
|
43
|
+
*
|
|
44
|
+
* - Merges caller headers on top of the default Content-Type header.
|
|
45
|
+
* - Defaults cache to `no-store` unless `cache` or `next` is explicitly provided
|
|
46
|
+
* (avoids the Next.js 2 MB data-cache write limit).
|
|
47
|
+
* - Passes `next` through transparently for Next.js ISR tag/revalidation support.
|
|
48
|
+
*/
|
|
49
|
+
export declare function apiCall<T>(url: string, options?: ApiCallOptions): Promise<T>;
|
|
50
|
+
/**
|
|
51
|
+
* Build the endpoint map for a given base URL.
|
|
52
|
+
* Call once during app initialization with your resolved base URL.
|
|
53
|
+
*/
|
|
54
|
+
export declare function createApiEndpoints(baseUrl: string): {
|
|
55
|
+
readonly auth: {
|
|
56
|
+
readonly login: `${string}/auth/login`;
|
|
57
|
+
readonly logout: `${string}/auth/logout`;
|
|
58
|
+
readonly createUser: `${string}/auth/createuser`;
|
|
59
|
+
readonly adminCreateUser: `${string}/auth/admin/createuser`;
|
|
60
|
+
readonly refresh: `${string}/auth/renewtoken`;
|
|
61
|
+
readonly changePassword: `${string}/auth/password`;
|
|
62
|
+
readonly adminChangePassword: `${string}/auth/admin/password`;
|
|
63
|
+
readonly getCurrentUser: `${string}/auth/user`;
|
|
64
|
+
readonly editOwnUser: `${string}/auth/user`;
|
|
65
|
+
readonly getUserById: (userId: string) => string;
|
|
66
|
+
readonly getUserByName: (userName: string) => string;
|
|
67
|
+
readonly getUserIds: `${string}/auth/user/ids`;
|
|
68
|
+
readonly getProfileImage: `${string}/auth/profileimage`;
|
|
69
|
+
readonly getUserProfileImage: (userId: string) => string;
|
|
70
|
+
readonly uploadProfileImage: `${string}/auth/profileimage`;
|
|
71
|
+
readonly adminUploadProfileImage: `${string}/auth/admin/profileimage`;
|
|
72
|
+
readonly totp: `${string}/auth/totp`;
|
|
73
|
+
readonly disableTotp: (id: string) => string;
|
|
74
|
+
readonly verifyTotp: (id: string) => string;
|
|
75
|
+
readonly adminGetUsers: `${string}/auth/admin/user`;
|
|
76
|
+
readonly adminAddUser: `${string}/auth/admin/user`;
|
|
77
|
+
readonly adminGetUser: (userId: string) => string;
|
|
78
|
+
readonly adminDisableUser: (userId: string) => string;
|
|
79
|
+
readonly adminEnableUser: (userId: string) => string;
|
|
80
|
+
readonly adminSetRoles: `${string}/auth/admin/user/roles`;
|
|
81
|
+
readonly adminSearch: `${string}/auth/admin/search`;
|
|
82
|
+
readonly adminGetTotp: (userId: string) => string;
|
|
83
|
+
readonly adminCreateTotp: (userId: string) => string;
|
|
84
|
+
readonly adminDisableTotp: (userId: string, totpId: string) => string;
|
|
85
|
+
readonly adminVerifyTotp: (userId: string, totpId: string) => string;
|
|
86
|
+
};
|
|
87
|
+
readonly asset: {
|
|
88
|
+
readonly getAssetData: (id: string) => string;
|
|
89
|
+
readonly createAudioAsset: `${string}/cms/asset/audio`;
|
|
90
|
+
readonly createAsset: `${string}/cms/admin/asset`;
|
|
91
|
+
readonly getAsset: (id: string) => string;
|
|
92
|
+
readonly adminGetAsset: (id: string) => string;
|
|
93
|
+
readonly adminGetAssetByOldId: (id: string) => string;
|
|
94
|
+
readonly adminGetImageAssets: `${string}/cms/admin/asset/image`;
|
|
95
|
+
readonly searchAssets: `${string}/cms/admin/asset/search`;
|
|
96
|
+
};
|
|
97
|
+
readonly auditLog: {
|
|
98
|
+
readonly adminGetAuditLog: `${string}/admin/audit-log`;
|
|
99
|
+
};
|
|
100
|
+
readonly careers: {
|
|
101
|
+
readonly createCareer: `${string}/admin/careers`;
|
|
102
|
+
readonly getCareersAdmin: `${string}/admin/careers`;
|
|
103
|
+
readonly getCareer: (id: string) => string;
|
|
104
|
+
readonly getCareers: `${string}/careers`;
|
|
105
|
+
readonly adminUpdateCareer: (id: string) => string;
|
|
106
|
+
readonly adminDeleteCareer: (id: string) => string;
|
|
107
|
+
};
|
|
108
|
+
readonly category: {
|
|
109
|
+
readonly createCategory: `${string}/settings/category/create`;
|
|
110
|
+
readonly deleteCategory: (id: string) => string;
|
|
111
|
+
};
|
|
112
|
+
readonly channel: {
|
|
113
|
+
readonly getChannels: `${string}/settings/channel`;
|
|
114
|
+
readonly createChannel: `${string}/settings/channel/create`;
|
|
115
|
+
readonly deleteChannel: (id: string) => string;
|
|
116
|
+
readonly getChannelDetails: (id: string) => string;
|
|
117
|
+
};
|
|
118
|
+
readonly comment: {
|
|
119
|
+
readonly adminDeleteComment: (id: string) => string;
|
|
120
|
+
readonly adminPinComment: (id: string) => string;
|
|
121
|
+
readonly adminUndeleteComment: (id: string) => string;
|
|
122
|
+
readonly adminUnpinComment: (id: string) => string;
|
|
123
|
+
readonly createCommentForContent: (id: string) => string;
|
|
124
|
+
readonly createCommentForComment: (id: string) => string;
|
|
125
|
+
readonly deleteOwnComment: (id: string) => string;
|
|
126
|
+
readonly editOwnComment: (id: string) => string;
|
|
127
|
+
readonly getCommentForContent: (id: string) => string;
|
|
128
|
+
readonly getCommentsForComment: (id: string) => string;
|
|
129
|
+
readonly likeComment: (id: string) => string;
|
|
130
|
+
readonly unlikeComment: (id: string) => string;
|
|
131
|
+
};
|
|
132
|
+
readonly cms: {
|
|
133
|
+
readonly announceContent: (id: string) => string;
|
|
134
|
+
readonly createContent: `${string}/cms/admin/content`;
|
|
135
|
+
readonly adminListContent: `${string}/cms/admin/content`;
|
|
136
|
+
readonly deleteContent: (id: string) => string;
|
|
137
|
+
readonly adminGetContentById: (id: string) => string;
|
|
138
|
+
readonly adminUpdateContent: (id: string) => string;
|
|
139
|
+
readonly listContent: `${string}/cms/content`;
|
|
140
|
+
readonly getContentById: (id: string) => string;
|
|
141
|
+
readonly getContentByUrl: (url: string) => string;
|
|
142
|
+
readonly getRecentCategories: `${string}/cms/categories/recent`;
|
|
143
|
+
readonly getRecentTags: `${string}/cms/tags/recent`;
|
|
144
|
+
readonly getContentByChannel: (channelId: string, pageSize?: number) => string;
|
|
145
|
+
readonly getRelated: (contentId: string, pageSize?: number) => string;
|
|
146
|
+
readonly publishContent: (id: string) => string;
|
|
147
|
+
readonly searchContent: `${string}/cms/search`;
|
|
148
|
+
readonly unannounceContent: (id: string) => string;
|
|
149
|
+
readonly undeleteContent: (id: string) => string;
|
|
150
|
+
readonly unpublishContent: (id: string) => string;
|
|
151
|
+
readonly createPage: `${string}/cms/admin/page`;
|
|
152
|
+
readonly adminListPages: `${string}/cms/admin/page`;
|
|
153
|
+
readonly deletePage: (id: string) => string;
|
|
154
|
+
readonly adminGetPageById: (id: string) => string;
|
|
155
|
+
readonly adminUpdatePage: (id: string) => string;
|
|
156
|
+
readonly listPages: `${string}/cms/page`;
|
|
157
|
+
readonly getPageById: (id: string) => string;
|
|
158
|
+
readonly getPageByUrl: `${string}/cms/page/url`;
|
|
159
|
+
readonly publishPage: (id: string) => string;
|
|
160
|
+
readonly searchPages: `${string}/cms/page/search`;
|
|
161
|
+
readonly undeletePage: (id: string) => string;
|
|
162
|
+
readonly unpublishPage: (id: string) => string;
|
|
163
|
+
};
|
|
164
|
+
readonly settings: {
|
|
165
|
+
readonly publicSettings: `${string}/settings/public`;
|
|
166
|
+
readonly publicSettingsNewer: (version: string) => string;
|
|
167
|
+
readonly adminSettings: `${string}/settings/admin`;
|
|
168
|
+
readonly adminSettingsNewer: (version: string) => string;
|
|
169
|
+
readonly ownerSettings: `${string}/settings/owner`;
|
|
170
|
+
readonly ownerSettingsNewer: (version: string) => string;
|
|
171
|
+
readonly channels: `${string}/settings/channel`;
|
|
172
|
+
readonly channelById: (channelId: string) => string;
|
|
173
|
+
readonly saveCmsPublic: `${string}/settings/cms/public`;
|
|
174
|
+
readonly saveCmsPrivate: `${string}/settings/cms/private`;
|
|
175
|
+
readonly saveCmsOwner: `${string}/settings/cms/owner`;
|
|
176
|
+
readonly savePersonalizationPublic: `${string}/settings/personalization/public`;
|
|
177
|
+
readonly savePersonalizationPrivate: `${string}/settings/personalization/private`;
|
|
178
|
+
readonly savePersonalizationOwner: `${string}/settings/personalization/owner`;
|
|
179
|
+
readonly saveSubscriptionPublic: `${string}/settings/subscription/public`;
|
|
180
|
+
readonly saveSubscriptionPrivate: `${string}/settings/subscription/private`;
|
|
181
|
+
readonly saveSubscriptionOwner: `${string}/settings/subscription/owner`;
|
|
182
|
+
readonly saveCommentsPublic: `${string}/settings/comments/public`;
|
|
183
|
+
readonly saveCommentsPrivate: `${string}/settings/comments/private`;
|
|
184
|
+
readonly saveCommentsOwner: `${string}/settings/comments/owner`;
|
|
185
|
+
readonly saveNotificationPublic: `${string}/settings/notification/public`;
|
|
186
|
+
readonly saveNotificationPrivate: `${string}/settings/notification/private`;
|
|
187
|
+
readonly saveNotificationOwner: `${string}/settings/notification/owner`;
|
|
188
|
+
readonly saveEventsPublic: `${string}/settings/events/public`;
|
|
189
|
+
readonly saveEventsPrivate: `${string}/settings/events/private`;
|
|
190
|
+
readonly saveEventsOwner: `${string}/settings/events/owner`;
|
|
191
|
+
};
|
|
192
|
+
readonly dashboard: {
|
|
193
|
+
readonly getDashboard: `${string}/admin/dashboard`;
|
|
194
|
+
};
|
|
195
|
+
readonly events: {
|
|
196
|
+
readonly getEvent: (eventId: string) => string;
|
|
197
|
+
readonly getEvents: `${string}/events`;
|
|
198
|
+
readonly getTicket: (eventId: string, ticketId: string) => string;
|
|
199
|
+
readonly getTickets: (eventId: string) => string;
|
|
200
|
+
readonly cancelTicket: (eventId: string, ticketId: string) => string;
|
|
201
|
+
readonly reserveTicket: (eventId: string) => string;
|
|
202
|
+
readonly useTicket: `${string}/events/tickets/use`;
|
|
203
|
+
};
|
|
204
|
+
readonly adminEvents: {
|
|
205
|
+
readonly createEvent: `${string}/admin/events/create`;
|
|
206
|
+
readonly createRecurringEvent: `${string}/admin/events/create-recurring`;
|
|
207
|
+
readonly getEvent: (eventId: string) => string;
|
|
208
|
+
readonly getEvents: `${string}/admin/events`;
|
|
209
|
+
readonly modifyEvent: `${string}/admin/events/modify`;
|
|
210
|
+
readonly cancelEvent: `${string}/admin/events/cancel`;
|
|
211
|
+
readonly cancelAllRecurring: `${string}/admin/events/cancel-all-recurring`;
|
|
212
|
+
readonly getTicket: (eventId: string, ticketId: string) => string;
|
|
213
|
+
readonly getTickets: (eventId: string) => string;
|
|
214
|
+
readonly cancelTicket: (eventId: string, ticketId: string) => string;
|
|
215
|
+
readonly reserveTicket: (eventId: string) => string;
|
|
216
|
+
};
|
|
217
|
+
readonly payments: {
|
|
218
|
+
readonly getSubscriptions: `${string}/payment/subscription`;
|
|
219
|
+
readonly getSubscriptionById: (id: string) => string;
|
|
220
|
+
readonly reconcileSubscription: `${string}/payment/subscription/reconcile`;
|
|
221
|
+
readonly newSubscription: (level: number, postalCode: string, successUrl: string, cancelUrl: string) => string;
|
|
222
|
+
readonly cancelSubscription: `${string}/payment/subscription/cancel`;
|
|
223
|
+
readonly getSinglePayments: `${string}/payment/single`;
|
|
224
|
+
readonly getSinglePayment: (id: string) => string;
|
|
225
|
+
readonly newSinglePayment: `${string}/payment/single/new`;
|
|
226
|
+
readonly finishStripe: `${string}/payment/stripe/subscription/finish`;
|
|
227
|
+
readonly finishFortis: `${string}/payment/fortis/subscription/finish`;
|
|
228
|
+
readonly newPaypal: `${string}/payment/paypal/subscription/new`;
|
|
229
|
+
};
|
|
230
|
+
readonly adminPayments: {
|
|
231
|
+
readonly bulkCancel: `${string}/payment/admin/bulk/cancel`;
|
|
232
|
+
readonly bulkStart: `${string}/payment/admin/bulk/start`;
|
|
233
|
+
readonly getBulk: `${string}/payment/admin/bulk`;
|
|
234
|
+
readonly cancelUserSubscription: (userId: string, subscriptionId: string) => string;
|
|
235
|
+
readonly getUserSubscription: (userId: string, subscriptionId: string) => string;
|
|
236
|
+
readonly getUserSubscriptions: (userId: string) => string;
|
|
237
|
+
readonly getUserSinglePayment: (userId: string, paymentId: string) => string;
|
|
238
|
+
readonly getUserSinglePayments: (userId: string) => string;
|
|
239
|
+
readonly reconcileUserSubscription: (userId: string, subscriptionId: string) => string;
|
|
240
|
+
readonly getSubscriptions: `${string}/payment/admin/subscriptions`;
|
|
241
|
+
};
|
|
242
|
+
readonly manualPayments: {
|
|
243
|
+
readonly adminCancelSubscription: (userId: string, subscriptionId: string) => string;
|
|
244
|
+
readonly cancelSubscription: (subscriptionId: string) => string;
|
|
245
|
+
readonly adminGetSubscription: (userId: string, subscriptionId: string) => string;
|
|
246
|
+
readonly adminGetSubscriptions: (userId: string) => string;
|
|
247
|
+
readonly getSubscriptions: `${string}/payment/manual/subscription`;
|
|
248
|
+
readonly getSubscription: (subscriptionId: string) => string;
|
|
249
|
+
readonly adminNewSubscription: (userId: string) => string;
|
|
250
|
+
readonly newSubscription: `${string}/payment/manual/subscription/new`;
|
|
251
|
+
};
|
|
252
|
+
readonly stats: {
|
|
253
|
+
readonly like: (contentId: string) => string;
|
|
254
|
+
readonly unlike: (contentId: string) => string;
|
|
255
|
+
readonly progress: (contentId: string) => string;
|
|
256
|
+
readonly save: (contentId: string) => string;
|
|
257
|
+
readonly unSave: (contentId: string) => string;
|
|
258
|
+
readonly logShare: (contentId: string) => string;
|
|
259
|
+
readonly getContentStats: (contentId: string) => string;
|
|
260
|
+
readonly getUserStats: (userId: string) => string;
|
|
261
|
+
readonly getCurrentUserStats: `${string}/stats/user`;
|
|
262
|
+
readonly getUserLikes: `${string}/stats/user/likes`;
|
|
263
|
+
readonly getUserProgress: `${string}/stats/user/progress`;
|
|
264
|
+
readonly getUserSaves: `${string}/stats/user/saves`;
|
|
265
|
+
};
|
|
266
|
+
};
|
|
267
|
+
export type ApiEndpoints = ReturnType<typeof createApiEndpoints>;
|
|
268
|
+
/**
|
|
269
|
+
* Create a complete API client bound to a base URL.
|
|
270
|
+
*
|
|
271
|
+
* Returns `endpoints` (the full URL map) and `call` (the fetch wrapper),
|
|
272
|
+
* both pre-bound to the provided base URL.
|
|
273
|
+
*/
|
|
274
|
+
export declare function createApiClient(baseUrl: string): {
|
|
275
|
+
endpoints: {
|
|
276
|
+
readonly auth: {
|
|
277
|
+
readonly login: `${string}/auth/login`;
|
|
278
|
+
readonly logout: `${string}/auth/logout`;
|
|
279
|
+
readonly createUser: `${string}/auth/createuser`;
|
|
280
|
+
readonly adminCreateUser: `${string}/auth/admin/createuser`;
|
|
281
|
+
readonly refresh: `${string}/auth/renewtoken`;
|
|
282
|
+
readonly changePassword: `${string}/auth/password`;
|
|
283
|
+
readonly adminChangePassword: `${string}/auth/admin/password`;
|
|
284
|
+
readonly getCurrentUser: `${string}/auth/user`;
|
|
285
|
+
readonly editOwnUser: `${string}/auth/user`;
|
|
286
|
+
readonly getUserById: (userId: string) => string;
|
|
287
|
+
readonly getUserByName: (userName: string) => string;
|
|
288
|
+
readonly getUserIds: `${string}/auth/user/ids`;
|
|
289
|
+
readonly getProfileImage: `${string}/auth/profileimage`;
|
|
290
|
+
readonly getUserProfileImage: (userId: string) => string;
|
|
291
|
+
readonly uploadProfileImage: `${string}/auth/profileimage`;
|
|
292
|
+
readonly adminUploadProfileImage: `${string}/auth/admin/profileimage`;
|
|
293
|
+
readonly totp: `${string}/auth/totp`;
|
|
294
|
+
readonly disableTotp: (id: string) => string;
|
|
295
|
+
readonly verifyTotp: (id: string) => string;
|
|
296
|
+
readonly adminGetUsers: `${string}/auth/admin/user`;
|
|
297
|
+
readonly adminAddUser: `${string}/auth/admin/user`;
|
|
298
|
+
readonly adminGetUser: (userId: string) => string;
|
|
299
|
+
readonly adminDisableUser: (userId: string) => string;
|
|
300
|
+
readonly adminEnableUser: (userId: string) => string;
|
|
301
|
+
readonly adminSetRoles: `${string}/auth/admin/user/roles`;
|
|
302
|
+
readonly adminSearch: `${string}/auth/admin/search`;
|
|
303
|
+
readonly adminGetTotp: (userId: string) => string;
|
|
304
|
+
readonly adminCreateTotp: (userId: string) => string;
|
|
305
|
+
readonly adminDisableTotp: (userId: string, totpId: string) => string;
|
|
306
|
+
readonly adminVerifyTotp: (userId: string, totpId: string) => string;
|
|
307
|
+
};
|
|
308
|
+
readonly asset: {
|
|
309
|
+
readonly getAssetData: (id: string) => string;
|
|
310
|
+
readonly createAudioAsset: `${string}/cms/asset/audio`;
|
|
311
|
+
readonly createAsset: `${string}/cms/admin/asset`;
|
|
312
|
+
readonly getAsset: (id: string) => string;
|
|
313
|
+
readonly adminGetAsset: (id: string) => string;
|
|
314
|
+
readonly adminGetAssetByOldId: (id: string) => string;
|
|
315
|
+
readonly adminGetImageAssets: `${string}/cms/admin/asset/image`;
|
|
316
|
+
readonly searchAssets: `${string}/cms/admin/asset/search`;
|
|
317
|
+
};
|
|
318
|
+
readonly auditLog: {
|
|
319
|
+
readonly adminGetAuditLog: `${string}/admin/audit-log`;
|
|
320
|
+
};
|
|
321
|
+
readonly careers: {
|
|
322
|
+
readonly createCareer: `${string}/admin/careers`;
|
|
323
|
+
readonly getCareersAdmin: `${string}/admin/careers`;
|
|
324
|
+
readonly getCareer: (id: string) => string;
|
|
325
|
+
readonly getCareers: `${string}/careers`;
|
|
326
|
+
readonly adminUpdateCareer: (id: string) => string;
|
|
327
|
+
readonly adminDeleteCareer: (id: string) => string;
|
|
328
|
+
};
|
|
329
|
+
readonly category: {
|
|
330
|
+
readonly createCategory: `${string}/settings/category/create`;
|
|
331
|
+
readonly deleteCategory: (id: string) => string;
|
|
332
|
+
};
|
|
333
|
+
readonly channel: {
|
|
334
|
+
readonly getChannels: `${string}/settings/channel`;
|
|
335
|
+
readonly createChannel: `${string}/settings/channel/create`;
|
|
336
|
+
readonly deleteChannel: (id: string) => string;
|
|
337
|
+
readonly getChannelDetails: (id: string) => string;
|
|
338
|
+
};
|
|
339
|
+
readonly comment: {
|
|
340
|
+
readonly adminDeleteComment: (id: string) => string;
|
|
341
|
+
readonly adminPinComment: (id: string) => string;
|
|
342
|
+
readonly adminUndeleteComment: (id: string) => string;
|
|
343
|
+
readonly adminUnpinComment: (id: string) => string;
|
|
344
|
+
readonly createCommentForContent: (id: string) => string;
|
|
345
|
+
readonly createCommentForComment: (id: string) => string;
|
|
346
|
+
readonly deleteOwnComment: (id: string) => string;
|
|
347
|
+
readonly editOwnComment: (id: string) => string;
|
|
348
|
+
readonly getCommentForContent: (id: string) => string;
|
|
349
|
+
readonly getCommentsForComment: (id: string) => string;
|
|
350
|
+
readonly likeComment: (id: string) => string;
|
|
351
|
+
readonly unlikeComment: (id: string) => string;
|
|
352
|
+
};
|
|
353
|
+
readonly cms: {
|
|
354
|
+
readonly announceContent: (id: string) => string;
|
|
355
|
+
readonly createContent: `${string}/cms/admin/content`;
|
|
356
|
+
readonly adminListContent: `${string}/cms/admin/content`;
|
|
357
|
+
readonly deleteContent: (id: string) => string;
|
|
358
|
+
readonly adminGetContentById: (id: string) => string;
|
|
359
|
+
readonly adminUpdateContent: (id: string) => string;
|
|
360
|
+
readonly listContent: `${string}/cms/content`;
|
|
361
|
+
readonly getContentById: (id: string) => string;
|
|
362
|
+
readonly getContentByUrl: (url: string) => string;
|
|
363
|
+
readonly getRecentCategories: `${string}/cms/categories/recent`;
|
|
364
|
+
readonly getRecentTags: `${string}/cms/tags/recent`;
|
|
365
|
+
readonly getContentByChannel: (channelId: string, pageSize?: number) => string;
|
|
366
|
+
readonly getRelated: (contentId: string, pageSize?: number) => string;
|
|
367
|
+
readonly publishContent: (id: string) => string;
|
|
368
|
+
readonly searchContent: `${string}/cms/search`;
|
|
369
|
+
readonly unannounceContent: (id: string) => string;
|
|
370
|
+
readonly undeleteContent: (id: string) => string;
|
|
371
|
+
readonly unpublishContent: (id: string) => string;
|
|
372
|
+
readonly createPage: `${string}/cms/admin/page`;
|
|
373
|
+
readonly adminListPages: `${string}/cms/admin/page`;
|
|
374
|
+
readonly deletePage: (id: string) => string;
|
|
375
|
+
readonly adminGetPageById: (id: string) => string;
|
|
376
|
+
readonly adminUpdatePage: (id: string) => string;
|
|
377
|
+
readonly listPages: `${string}/cms/page`;
|
|
378
|
+
readonly getPageById: (id: string) => string;
|
|
379
|
+
readonly getPageByUrl: `${string}/cms/page/url`;
|
|
380
|
+
readonly publishPage: (id: string) => string;
|
|
381
|
+
readonly searchPages: `${string}/cms/page/search`;
|
|
382
|
+
readonly undeletePage: (id: string) => string;
|
|
383
|
+
readonly unpublishPage: (id: string) => string;
|
|
384
|
+
};
|
|
385
|
+
readonly settings: {
|
|
386
|
+
readonly publicSettings: `${string}/settings/public`;
|
|
387
|
+
readonly publicSettingsNewer: (version: string) => string;
|
|
388
|
+
readonly adminSettings: `${string}/settings/admin`;
|
|
389
|
+
readonly adminSettingsNewer: (version: string) => string;
|
|
390
|
+
readonly ownerSettings: `${string}/settings/owner`;
|
|
391
|
+
readonly ownerSettingsNewer: (version: string) => string;
|
|
392
|
+
readonly channels: `${string}/settings/channel`;
|
|
393
|
+
readonly channelById: (channelId: string) => string;
|
|
394
|
+
readonly saveCmsPublic: `${string}/settings/cms/public`;
|
|
395
|
+
readonly saveCmsPrivate: `${string}/settings/cms/private`;
|
|
396
|
+
readonly saveCmsOwner: `${string}/settings/cms/owner`;
|
|
397
|
+
readonly savePersonalizationPublic: `${string}/settings/personalization/public`;
|
|
398
|
+
readonly savePersonalizationPrivate: `${string}/settings/personalization/private`;
|
|
399
|
+
readonly savePersonalizationOwner: `${string}/settings/personalization/owner`;
|
|
400
|
+
readonly saveSubscriptionPublic: `${string}/settings/subscription/public`;
|
|
401
|
+
readonly saveSubscriptionPrivate: `${string}/settings/subscription/private`;
|
|
402
|
+
readonly saveSubscriptionOwner: `${string}/settings/subscription/owner`;
|
|
403
|
+
readonly saveCommentsPublic: `${string}/settings/comments/public`;
|
|
404
|
+
readonly saveCommentsPrivate: `${string}/settings/comments/private`;
|
|
405
|
+
readonly saveCommentsOwner: `${string}/settings/comments/owner`;
|
|
406
|
+
readonly saveNotificationPublic: `${string}/settings/notification/public`;
|
|
407
|
+
readonly saveNotificationPrivate: `${string}/settings/notification/private`;
|
|
408
|
+
readonly saveNotificationOwner: `${string}/settings/notification/owner`;
|
|
409
|
+
readonly saveEventsPublic: `${string}/settings/events/public`;
|
|
410
|
+
readonly saveEventsPrivate: `${string}/settings/events/private`;
|
|
411
|
+
readonly saveEventsOwner: `${string}/settings/events/owner`;
|
|
412
|
+
};
|
|
413
|
+
readonly dashboard: {
|
|
414
|
+
readonly getDashboard: `${string}/admin/dashboard`;
|
|
415
|
+
};
|
|
416
|
+
readonly events: {
|
|
417
|
+
readonly getEvent: (eventId: string) => string;
|
|
418
|
+
readonly getEvents: `${string}/events`;
|
|
419
|
+
readonly getTicket: (eventId: string, ticketId: string) => string;
|
|
420
|
+
readonly getTickets: (eventId: string) => string;
|
|
421
|
+
readonly cancelTicket: (eventId: string, ticketId: string) => string;
|
|
422
|
+
readonly reserveTicket: (eventId: string) => string;
|
|
423
|
+
readonly useTicket: `${string}/events/tickets/use`;
|
|
424
|
+
};
|
|
425
|
+
readonly adminEvents: {
|
|
426
|
+
readonly createEvent: `${string}/admin/events/create`;
|
|
427
|
+
readonly createRecurringEvent: `${string}/admin/events/create-recurring`;
|
|
428
|
+
readonly getEvent: (eventId: string) => string;
|
|
429
|
+
readonly getEvents: `${string}/admin/events`;
|
|
430
|
+
readonly modifyEvent: `${string}/admin/events/modify`;
|
|
431
|
+
readonly cancelEvent: `${string}/admin/events/cancel`;
|
|
432
|
+
readonly cancelAllRecurring: `${string}/admin/events/cancel-all-recurring`;
|
|
433
|
+
readonly getTicket: (eventId: string, ticketId: string) => string;
|
|
434
|
+
readonly getTickets: (eventId: string) => string;
|
|
435
|
+
readonly cancelTicket: (eventId: string, ticketId: string) => string;
|
|
436
|
+
readonly reserveTicket: (eventId: string) => string;
|
|
437
|
+
};
|
|
438
|
+
readonly payments: {
|
|
439
|
+
readonly getSubscriptions: `${string}/payment/subscription`;
|
|
440
|
+
readonly getSubscriptionById: (id: string) => string;
|
|
441
|
+
readonly reconcileSubscription: `${string}/payment/subscription/reconcile`;
|
|
442
|
+
readonly newSubscription: (level: number, postalCode: string, successUrl: string, cancelUrl: string) => string;
|
|
443
|
+
readonly cancelSubscription: `${string}/payment/subscription/cancel`;
|
|
444
|
+
readonly getSinglePayments: `${string}/payment/single`;
|
|
445
|
+
readonly getSinglePayment: (id: string) => string;
|
|
446
|
+
readonly newSinglePayment: `${string}/payment/single/new`;
|
|
447
|
+
readonly finishStripe: `${string}/payment/stripe/subscription/finish`;
|
|
448
|
+
readonly finishFortis: `${string}/payment/fortis/subscription/finish`;
|
|
449
|
+
readonly newPaypal: `${string}/payment/paypal/subscription/new`;
|
|
450
|
+
};
|
|
451
|
+
readonly adminPayments: {
|
|
452
|
+
readonly bulkCancel: `${string}/payment/admin/bulk/cancel`;
|
|
453
|
+
readonly bulkStart: `${string}/payment/admin/bulk/start`;
|
|
454
|
+
readonly getBulk: `${string}/payment/admin/bulk`;
|
|
455
|
+
readonly cancelUserSubscription: (userId: string, subscriptionId: string) => string;
|
|
456
|
+
readonly getUserSubscription: (userId: string, subscriptionId: string) => string;
|
|
457
|
+
readonly getUserSubscriptions: (userId: string) => string;
|
|
458
|
+
readonly getUserSinglePayment: (userId: string, paymentId: string) => string;
|
|
459
|
+
readonly getUserSinglePayments: (userId: string) => string;
|
|
460
|
+
readonly reconcileUserSubscription: (userId: string, subscriptionId: string) => string;
|
|
461
|
+
readonly getSubscriptions: `${string}/payment/admin/subscriptions`;
|
|
462
|
+
};
|
|
463
|
+
readonly manualPayments: {
|
|
464
|
+
readonly adminCancelSubscription: (userId: string, subscriptionId: string) => string;
|
|
465
|
+
readonly cancelSubscription: (subscriptionId: string) => string;
|
|
466
|
+
readonly adminGetSubscription: (userId: string, subscriptionId: string) => string;
|
|
467
|
+
readonly adminGetSubscriptions: (userId: string) => string;
|
|
468
|
+
readonly getSubscriptions: `${string}/payment/manual/subscription`;
|
|
469
|
+
readonly getSubscription: (subscriptionId: string) => string;
|
|
470
|
+
readonly adminNewSubscription: (userId: string) => string;
|
|
471
|
+
readonly newSubscription: `${string}/payment/manual/subscription/new`;
|
|
472
|
+
};
|
|
473
|
+
readonly stats: {
|
|
474
|
+
readonly like: (contentId: string) => string;
|
|
475
|
+
readonly unlike: (contentId: string) => string;
|
|
476
|
+
readonly progress: (contentId: string) => string;
|
|
477
|
+
readonly save: (contentId: string) => string;
|
|
478
|
+
readonly unSave: (contentId: string) => string;
|
|
479
|
+
readonly logShare: (contentId: string) => string;
|
|
480
|
+
readonly getContentStats: (contentId: string) => string;
|
|
481
|
+
readonly getUserStats: (userId: string) => string;
|
|
482
|
+
readonly getCurrentUserStats: `${string}/stats/user`;
|
|
483
|
+
readonly getUserLikes: `${string}/stats/user/likes`;
|
|
484
|
+
readonly getUserProgress: `${string}/stats/user/progress`;
|
|
485
|
+
readonly getUserSaves: `${string}/stats/user/saves`;
|
|
486
|
+
};
|
|
487
|
+
};
|
|
488
|
+
call: <T>(url: string, options?: ApiCallOptions) => Promise<T>;
|
|
489
|
+
};
|
|
490
|
+
export type ApiClient = ReturnType<typeof createApiClient>;
|
|
491
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inverted-tech/fragments",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"description": "Types and JS runtime for Inverted protocol buffers (Fragments)",
|
|
5
5
|
"types": "dist/protos/index.d.ts",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
@@ -297,9 +297,9 @@
|
|
|
297
297
|
"types": "./dist/protos/validation.d.ts",
|
|
298
298
|
"import": "./dist/esm/validation.js"
|
|
299
299
|
},
|
|
300
|
-
"./
|
|
301
|
-
"types": "./dist/protos/
|
|
302
|
-
"import": "./dist/esm/
|
|
300
|
+
"./api": {
|
|
301
|
+
"types": "./dist/protos/api.d.ts",
|
|
302
|
+
"import": "./dist/esm/api.js"
|
|
303
303
|
},
|
|
304
304
|
"./*": {
|
|
305
305
|
"types": "./dist/*",
|
|
@@ -330,7 +330,8 @@
|
|
|
330
330
|
"dependencies": {
|
|
331
331
|
"@bufbuild/protobuf": "^2.10.0",
|
|
332
332
|
"@bufbuild/protovalidate": "^1.0.0",
|
|
333
|
-
"@connectrpc/connect": "^1.7.0"
|
|
333
|
+
"@connectrpc/connect": "^1.7.0",
|
|
334
|
+
"pino": "^10.3.1"
|
|
334
335
|
},
|
|
335
336
|
"scripts": {
|
|
336
337
|
"gen": "node ./generate-ts.mjs && node ./scripts/fix-empty-indexes.mjs",
|
|
@@ -347,7 +348,7 @@
|
|
|
347
348
|
"lint": "eslint . --ext .ts",
|
|
348
349
|
"lint:gen": "eslint ts-gen --ext .ts",
|
|
349
350
|
"lint:gen:fix": "eslint ts-gen --ext .ts --fix",
|
|
350
|
-
"clean": "node -e \"const fs=require('fs'),path=require('path'); const rm=(p)=>fs.rmSync(p,{recursive:true,force:true}); if(fs.existsSync('dist')) rm('dist'); const base='ts-gen'; if(fs.existsSync(base)){ for(const ent of fs.readdirSync(base,{withFileTypes:true})) { if(ent.name==='validation.ts' || ent.name==='
|
|
351
|
+
"clean": "node -e \"const fs=require('fs'),path=require('path'); const rm=(p)=>fs.rmSync(p,{recursive:true,force:true}); if(fs.existsSync('dist')) rm('dist'); const base='ts-gen'; if(fs.existsSync(base)){ for(const ent of fs.readdirSync(base,{withFileTypes:true})) { if(ent.name==='validation.ts' || ent.name==='api.ts') continue; rm(path.join(base, ent.name)); } }\"",
|
|
351
352
|
"clean:pack": "node -e \"const fs=require('fs'); const path=require('path'); fs.rmSync('__pack_extract__',{recursive:true,force:true}); fs.readdirSync('.').filter(f=>f.endsWith('.tgz')).forEach(f=>fs.rmSync(path.join('.',f),{force:true})); console.log('Removed __pack_extract__ and *.tgz');\"",
|
|
352
353
|
"clean:dist": "node -e \"const fs=require('fs'); fs.rmSync('dist',{recursive:true,force:true});\"",
|
|
353
354
|
"rebuild": "npm run clean:dist && node ./scripts/ensure-gen.mjs && npm run build",
|
package/dist/esm/client.js
DELETED
|
@@ -1,297 +0,0 @@
|
|
|
1
|
-
import { create, toJsonString } from '@bufbuild/protobuf';
|
|
2
|
-
import { getValidator } from './validation.js';
|
|
3
|
-
// Safe logging function that works in all environments
|
|
4
|
-
const safeLog = {
|
|
5
|
-
error: (...args) => {
|
|
6
|
-
// Use globalThis to safely access console in all environments
|
|
7
|
-
const globalConsole = globalThis?.console;
|
|
8
|
-
if (globalConsole && globalConsole.error) {
|
|
9
|
-
globalConsole.error(...args);
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
};
|
|
13
|
-
/**
|
|
14
|
-
* Shared client class for standardized API communication with protobuf serialization
|
|
15
|
-
*
|
|
16
|
-
* This client encapsulates common patterns found in action functions like:
|
|
17
|
-
* - Token retrieval and authentication headers
|
|
18
|
-
* - Protobuf serialization using create() and toJsonString()
|
|
19
|
-
* - Consistent error handling with protobuf error responses
|
|
20
|
-
* - Next.js cache invalidation support (framework-agnostic)
|
|
21
|
-
* - Pre-request validation using protovalidate
|
|
22
|
-
*/
|
|
23
|
-
export class FragmentsClient {
|
|
24
|
-
config;
|
|
25
|
-
validator;
|
|
26
|
-
// Expose config for testing purposes
|
|
27
|
-
get _config() {
|
|
28
|
-
return this.config;
|
|
29
|
-
}
|
|
30
|
-
constructor(config = {}) {
|
|
31
|
-
this.config = {
|
|
32
|
-
baseUrl: config.baseUrl ?? 'http://localhost:8001',
|
|
33
|
-
getToken: config.getToken ?? (() => undefined),
|
|
34
|
-
onCacheInvalidate: config.onCacheInvalidate ?? (() => { }),
|
|
35
|
-
validateRequests: config.validateRequests ?? false,
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* Create a new client instance with modified configuration
|
|
40
|
-
* @param config Partial configuration to override
|
|
41
|
-
* @returns New FragmentsClient instance
|
|
42
|
-
*/
|
|
43
|
-
withConfig(config) {
|
|
44
|
-
return new FragmentsClient({
|
|
45
|
-
...this.config,
|
|
46
|
-
...config,
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Generic request method that handles all HTTP operations
|
|
51
|
-
* @param endpoint API endpoint (relative to baseUrl)
|
|
52
|
-
* @param reqSchema Request protobuf schema
|
|
53
|
-
* @param resSchema Response protobuf schema
|
|
54
|
-
* @param data Request data (optional for GET requests)
|
|
55
|
-
* @param options Request options
|
|
56
|
-
* @returns Promise resolving to typed response
|
|
57
|
-
*/
|
|
58
|
-
async request(endpoint, reqSchema, resSchema, data, options = {}) {
|
|
59
|
-
const method = options.method ?? 'POST';
|
|
60
|
-
const shouldValidate = options.validate ?? this.config.validateRequests;
|
|
61
|
-
// Get authentication token
|
|
62
|
-
const token = await this.config.getToken();
|
|
63
|
-
// Create request message if data is provided
|
|
64
|
-
let requestMessage;
|
|
65
|
-
let requestBody;
|
|
66
|
-
if (data && method !== 'GET') {
|
|
67
|
-
requestMessage = create(reqSchema, data);
|
|
68
|
-
// Validate request if enabled
|
|
69
|
-
if (shouldValidate) {
|
|
70
|
-
const validationResult = await this.validateMessage(reqSchema, requestMessage);
|
|
71
|
-
if (!validationResult.success) {
|
|
72
|
-
// Return error response instead of making HTTP request
|
|
73
|
-
return this.createValidationErrorResponse(resSchema, validationResult.violations);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
requestBody = toJsonString(reqSchema, requestMessage);
|
|
77
|
-
}
|
|
78
|
-
// Prepare fetch options
|
|
79
|
-
const fetchOptions = {
|
|
80
|
-
method,
|
|
81
|
-
headers: {
|
|
82
|
-
'Content-Type': 'application/json',
|
|
83
|
-
...(token && { Authorization: `Bearer ${token}` }),
|
|
84
|
-
},
|
|
85
|
-
...(requestBody && { body: requestBody }),
|
|
86
|
-
};
|
|
87
|
-
// Add Next.js cache options if provided
|
|
88
|
-
if (options.cacheTags || options.revalidate !== undefined) {
|
|
89
|
-
fetchOptions.next = {
|
|
90
|
-
...(options.cacheTags && { tags: options.cacheTags }),
|
|
91
|
-
...(options.revalidate !== undefined && { revalidate: options.revalidate }),
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
try {
|
|
95
|
-
const url = `${this.config.baseUrl}${endpoint}`;
|
|
96
|
-
const response = await fetch(url, fetchOptions);
|
|
97
|
-
// Handle null response like existing action functions
|
|
98
|
-
if (!response) {
|
|
99
|
-
safeLog.error('FragmentsClient: Network request failed - no response received');
|
|
100
|
-
return this.createNetworkErrorResponse(resSchema);
|
|
101
|
-
}
|
|
102
|
-
// Handle HTTP errors like existing action functions
|
|
103
|
-
if (!response.ok) {
|
|
104
|
-
safeLog.error(`FragmentsClient: HTTP error ${response.status}: ${response.statusText}`);
|
|
105
|
-
return this.createHttpErrorResponse(resSchema, response.status, response.statusText);
|
|
106
|
-
}
|
|
107
|
-
const responseData = await response.json();
|
|
108
|
-
// Handle cache invalidation for successful mutations
|
|
109
|
-
if (method !== 'GET' && (options.cacheTags || options.revalidatePaths)) {
|
|
110
|
-
this.config.onCacheInvalidate(options.cacheTags ?? [], options.revalidatePaths ?? []);
|
|
111
|
-
}
|
|
112
|
-
return responseData;
|
|
113
|
-
}
|
|
114
|
-
catch (error) {
|
|
115
|
-
// Log errors like existing action functions using console.error
|
|
116
|
-
safeLog.error('FragmentsClient request failed:', error);
|
|
117
|
-
// Return error response instead of throwing, matching existing patterns
|
|
118
|
-
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
119
|
-
return this.createErrorResponse(resSchema, errorMessage);
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
/**
|
|
123
|
-
* Convenience method for GET requests
|
|
124
|
-
* @param endpoint API endpoint
|
|
125
|
-
* @param resSchema Response protobuf schema
|
|
126
|
-
* @param options Request options
|
|
127
|
-
* @returns Promise resolving to typed response
|
|
128
|
-
*/
|
|
129
|
-
async get(endpoint, resSchema, options = {}) {
|
|
130
|
-
return this.request(endpoint, {}, resSchema, undefined, {
|
|
131
|
-
...options,
|
|
132
|
-
method: 'GET',
|
|
133
|
-
});
|
|
134
|
-
}
|
|
135
|
-
/**
|
|
136
|
-
* Convenience method for POST requests
|
|
137
|
-
* @param endpoint API endpoint
|
|
138
|
-
* @param reqSchema Request protobuf schema
|
|
139
|
-
* @param resSchema Response protobuf schema
|
|
140
|
-
* @param data Request data
|
|
141
|
-
* @param options Request options
|
|
142
|
-
* @returns Promise resolving to typed response
|
|
143
|
-
*/
|
|
144
|
-
async post(endpoint, reqSchema, resSchema, data, options = {}) {
|
|
145
|
-
return this.request(endpoint, reqSchema, resSchema, data, {
|
|
146
|
-
...options,
|
|
147
|
-
method: 'POST',
|
|
148
|
-
});
|
|
149
|
-
}
|
|
150
|
-
/**
|
|
151
|
-
* Static utility method to create protobuf request messages
|
|
152
|
-
* @param schema Protobuf message schema
|
|
153
|
-
* @param data Optional partial data to initialize the message
|
|
154
|
-
* @returns Created message instance
|
|
155
|
-
*/
|
|
156
|
-
static createRequest(schema, data) {
|
|
157
|
-
return create(schema, data);
|
|
158
|
-
}
|
|
159
|
-
/**
|
|
160
|
-
* Static utility method to create protobuf response messages
|
|
161
|
-
* @param schema Protobuf message schema
|
|
162
|
-
* @param data Optional partial data to initialize the message
|
|
163
|
-
* @returns Created message instance
|
|
164
|
-
*/
|
|
165
|
-
static createResponse(schema, data) {
|
|
166
|
-
return create(schema, data);
|
|
167
|
-
}
|
|
168
|
-
/**
|
|
169
|
-
* Static utility method to serialize protobuf messages to JSON strings
|
|
170
|
-
* @param schema Protobuf message schema
|
|
171
|
-
* @param data Message data to serialize
|
|
172
|
-
* @returns JSON string representation
|
|
173
|
-
*/
|
|
174
|
-
static serialize(schema, data) {
|
|
175
|
-
return toJsonString(schema, data);
|
|
176
|
-
}
|
|
177
|
-
/**
|
|
178
|
-
* Static utility method to validate protobuf messages using protovalidate
|
|
179
|
-
* @param schema Protobuf message schema
|
|
180
|
-
* @param data Message data to validate
|
|
181
|
-
* @returns Promise resolving to validation result
|
|
182
|
-
*/
|
|
183
|
-
static async validate(schema, data) {
|
|
184
|
-
try {
|
|
185
|
-
const validator = await getValidator();
|
|
186
|
-
const result = validator.validate(schema, data);
|
|
187
|
-
return {
|
|
188
|
-
success: result.kind === 'valid',
|
|
189
|
-
violations: result.kind === 'invalid' ? result.violations : undefined,
|
|
190
|
-
};
|
|
191
|
-
}
|
|
192
|
-
catch (error) {
|
|
193
|
-
safeLog.error('Validation error:', error);
|
|
194
|
-
return {
|
|
195
|
-
success: false,
|
|
196
|
-
violations: [{ message: 'Validation system error' }],
|
|
197
|
-
};
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
/**
|
|
201
|
-
* Private method to validate messages using the instance validator
|
|
202
|
-
*/
|
|
203
|
-
async validateMessage(schema, data) {
|
|
204
|
-
if (!this.validator) {
|
|
205
|
-
this.validator = await getValidator();
|
|
206
|
-
}
|
|
207
|
-
try {
|
|
208
|
-
const result = this.validator.validate(schema, data);
|
|
209
|
-
return {
|
|
210
|
-
success: result.kind === 'valid',
|
|
211
|
-
violations: result.kind === 'invalid' ? result.violations : undefined,
|
|
212
|
-
};
|
|
213
|
-
}
|
|
214
|
-
catch (error) {
|
|
215
|
-
safeLog.error('Validation error:', error);
|
|
216
|
-
return {
|
|
217
|
-
success: false,
|
|
218
|
-
violations: [{ message: 'Validation system error' }],
|
|
219
|
-
};
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
/**
|
|
223
|
-
* Private method to create error responses matching existing action function patterns
|
|
224
|
-
* This creates a generic error response structure that matches the patterns used in
|
|
225
|
-
* existing action functions like modifyPublicSubscriptionSettings
|
|
226
|
-
*/
|
|
227
|
-
createErrorResponse(schema, message) {
|
|
228
|
-
// Create error response matching existing action function patterns
|
|
229
|
-
// The structure matches what's used in functions like modifyPublicSubscriptionSettings
|
|
230
|
-
return create(schema, {
|
|
231
|
-
Error: {
|
|
232
|
-
Message: message,
|
|
233
|
-
Type: 'SETTINGS_ERROR_UNKNOWN', // Matches SettingsErrorReason.SETTINGS_ERROR_UNKNOWN
|
|
234
|
-
},
|
|
235
|
-
});
|
|
236
|
-
}
|
|
237
|
-
/**
|
|
238
|
-
* Private method to create validation error responses
|
|
239
|
-
* This preserves ValidationIssue[] arrays in error responses as required
|
|
240
|
-
*/
|
|
241
|
-
createValidationErrorResponse(schema, violations) {
|
|
242
|
-
return create(schema, {
|
|
243
|
-
Error: {
|
|
244
|
-
Message: 'Request validation failed',
|
|
245
|
-
Type: 'SETTINGS_ERROR_VALIDATION_FAILED', // Matches validation error type
|
|
246
|
-
Validation: violations ?? [], // Preserve ValidationIssue[] arrays
|
|
247
|
-
},
|
|
248
|
-
});
|
|
249
|
-
}
|
|
250
|
-
/**
|
|
251
|
-
* Private method to create HTTP error responses
|
|
252
|
-
* Handles HTTP errors uniformly like existing action functions
|
|
253
|
-
*/
|
|
254
|
-
createHttpErrorResponse(schema, status, statusText) {
|
|
255
|
-
const message = `HTTP ${status}: ${statusText}`;
|
|
256
|
-
return create(schema, {
|
|
257
|
-
Error: {
|
|
258
|
-
Message: message,
|
|
259
|
-
Type: 'SETTINGS_ERROR_UNKNOWN',
|
|
260
|
-
},
|
|
261
|
-
});
|
|
262
|
-
}
|
|
263
|
-
/**
|
|
264
|
-
* Private method to create network error responses
|
|
265
|
-
* Handles network failures like existing action functions
|
|
266
|
-
*/
|
|
267
|
-
createNetworkErrorResponse(schema) {
|
|
268
|
-
return create(schema, {
|
|
269
|
-
Error: {
|
|
270
|
-
Message: 'Network request failed',
|
|
271
|
-
Type: 'SETTINGS_ERROR_UNKNOWN',
|
|
272
|
-
},
|
|
273
|
-
});
|
|
274
|
-
}
|
|
275
|
-
/**
|
|
276
|
-
* Static method to create error responses for use in action functions
|
|
277
|
-
* This allows consumers to create consistent error responses outside of the client
|
|
278
|
-
* @param schema Response schema to create error for
|
|
279
|
-
* @param message Error message
|
|
280
|
-
* @param errorType Error type (defaults to SETTINGS_ERROR_UNKNOWN)
|
|
281
|
-
* @param validationIssues Optional validation issues array
|
|
282
|
-
* @returns Error response matching existing action function patterns
|
|
283
|
-
*/
|
|
284
|
-
static createErrorResponse(schema, message, errorType = 'SETTINGS_ERROR_UNKNOWN', validationIssues) {
|
|
285
|
-
const errorData = {
|
|
286
|
-
Message: message,
|
|
287
|
-
Type: errorType,
|
|
288
|
-
};
|
|
289
|
-
// Include validation issues if provided (preserves ValidationIssue[] arrays)
|
|
290
|
-
if (validationIssues && validationIssues.length > 0) {
|
|
291
|
-
errorData.Validation = validationIssues;
|
|
292
|
-
}
|
|
293
|
-
return create(schema, {
|
|
294
|
-
Error: errorData,
|
|
295
|
-
});
|
|
296
|
-
}
|
|
297
|
-
}
|
package/dist/protos/client.d.ts
DELETED
|
@@ -1,185 +0,0 @@
|
|
|
1
|
-
import { type Message } from '@bufbuild/protobuf';
|
|
2
|
-
import { type GenMessage } from '@bufbuild/protobuf/codegenv2';
|
|
3
|
-
declare global {
|
|
4
|
-
function fetch(input: string, init?: any): Promise<any>;
|
|
5
|
-
}
|
|
6
|
-
/**
|
|
7
|
-
* HTTP methods supported by the client
|
|
8
|
-
*/
|
|
9
|
-
export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
10
|
-
/**
|
|
11
|
-
* Token getter function type - can be sync or async
|
|
12
|
-
*/
|
|
13
|
-
export type TokenGetter = () => Promise<string | undefined> | string | undefined;
|
|
14
|
-
/**
|
|
15
|
-
* Cache invalidation callback function type
|
|
16
|
-
*/
|
|
17
|
-
export type CacheInvalidator = (tags: string[], paths: string[]) => void;
|
|
18
|
-
/**
|
|
19
|
-
* Simplified validation result interface
|
|
20
|
-
*/
|
|
21
|
-
export interface SimpleValidationResult {
|
|
22
|
-
success: boolean;
|
|
23
|
-
violations?: any[];
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* Configuration interface for the FragmentsClient
|
|
27
|
-
*/
|
|
28
|
-
export interface ClientConfig {
|
|
29
|
-
/**
|
|
30
|
-
* Base URL for API requests
|
|
31
|
-
* @default 'http://localhost:8001'
|
|
32
|
-
*/
|
|
33
|
-
baseUrl?: string;
|
|
34
|
-
/**
|
|
35
|
-
* Function to retrieve authentication tokens (sync or async)
|
|
36
|
-
*/
|
|
37
|
-
getToken?: TokenGetter;
|
|
38
|
-
/**
|
|
39
|
-
* Callback for cache invalidation (Next.js can pass revalidateTag/revalidatePath)
|
|
40
|
-
*/
|
|
41
|
-
onCacheInvalidate?: CacheInvalidator;
|
|
42
|
-
/**
|
|
43
|
-
* Enable pre-request validation using protovalidate
|
|
44
|
-
* @default false
|
|
45
|
-
*/
|
|
46
|
-
validateRequests?: boolean;
|
|
47
|
-
}
|
|
48
|
-
/**
|
|
49
|
-
* Per-request options that can override client configuration
|
|
50
|
-
*/
|
|
51
|
-
export interface RequestOptions {
|
|
52
|
-
/**
|
|
53
|
-
* HTTP method for the request
|
|
54
|
-
*/
|
|
55
|
-
method?: HttpMethod;
|
|
56
|
-
/**
|
|
57
|
-
* Cache tags for Next.js caching
|
|
58
|
-
*/
|
|
59
|
-
cacheTags?: string[];
|
|
60
|
-
/**
|
|
61
|
-
* Paths to revalidate after mutations
|
|
62
|
-
*/
|
|
63
|
-
revalidatePaths?: string[];
|
|
64
|
-
/**
|
|
65
|
-
* Cache revalidation time in seconds
|
|
66
|
-
*/
|
|
67
|
-
revalidate?: number;
|
|
68
|
-
/**
|
|
69
|
-
* Override client-level validation setting for this request
|
|
70
|
-
*/
|
|
71
|
-
validate?: boolean;
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* Shared client class for standardized API communication with protobuf serialization
|
|
75
|
-
*
|
|
76
|
-
* This client encapsulates common patterns found in action functions like:
|
|
77
|
-
* - Token retrieval and authentication headers
|
|
78
|
-
* - Protobuf serialization using create() and toJsonString()
|
|
79
|
-
* - Consistent error handling with protobuf error responses
|
|
80
|
-
* - Next.js cache invalidation support (framework-agnostic)
|
|
81
|
-
* - Pre-request validation using protovalidate
|
|
82
|
-
*/
|
|
83
|
-
export declare class FragmentsClient {
|
|
84
|
-
private readonly config;
|
|
85
|
-
private validator?;
|
|
86
|
-
get _config(): Required<ClientConfig>;
|
|
87
|
-
constructor(config?: ClientConfig);
|
|
88
|
-
/**
|
|
89
|
-
* Create a new client instance with modified configuration
|
|
90
|
-
* @param config Partial configuration to override
|
|
91
|
-
* @returns New FragmentsClient instance
|
|
92
|
-
*/
|
|
93
|
-
withConfig(config: Partial<ClientConfig>): FragmentsClient;
|
|
94
|
-
/**
|
|
95
|
-
* Generic request method that handles all HTTP operations
|
|
96
|
-
* @param endpoint API endpoint (relative to baseUrl)
|
|
97
|
-
* @param reqSchema Request protobuf schema
|
|
98
|
-
* @param resSchema Response protobuf schema
|
|
99
|
-
* @param data Request data (optional for GET requests)
|
|
100
|
-
* @param options Request options
|
|
101
|
-
* @returns Promise resolving to typed response
|
|
102
|
-
*/
|
|
103
|
-
request<TReq extends Message, TRes extends Message>(endpoint: string, reqSchema: GenMessage<TReq>, resSchema: GenMessage<TRes>, data?: Partial<TReq>, options?: RequestOptions): Promise<TRes>;
|
|
104
|
-
/**
|
|
105
|
-
* Convenience method for GET requests
|
|
106
|
-
* @param endpoint API endpoint
|
|
107
|
-
* @param resSchema Response protobuf schema
|
|
108
|
-
* @param options Request options
|
|
109
|
-
* @returns Promise resolving to typed response
|
|
110
|
-
*/
|
|
111
|
-
get<TRes extends Message>(endpoint: string, resSchema: GenMessage<TRes>, options?: Omit<RequestOptions, 'method'>): Promise<TRes>;
|
|
112
|
-
/**
|
|
113
|
-
* Convenience method for POST requests
|
|
114
|
-
* @param endpoint API endpoint
|
|
115
|
-
* @param reqSchema Request protobuf schema
|
|
116
|
-
* @param resSchema Response protobuf schema
|
|
117
|
-
* @param data Request data
|
|
118
|
-
* @param options Request options
|
|
119
|
-
* @returns Promise resolving to typed response
|
|
120
|
-
*/
|
|
121
|
-
post<TReq extends Message, TRes extends Message>(endpoint: string, reqSchema: GenMessage<TReq>, resSchema: GenMessage<TRes>, data: Partial<TReq>, options?: Omit<RequestOptions, 'method'>): Promise<TRes>;
|
|
122
|
-
/**
|
|
123
|
-
* Static utility method to create protobuf request messages
|
|
124
|
-
* @param schema Protobuf message schema
|
|
125
|
-
* @param data Optional partial data to initialize the message
|
|
126
|
-
* @returns Created message instance
|
|
127
|
-
*/
|
|
128
|
-
static createRequest<T extends Message>(schema: GenMessage<T>, data?: Partial<T>): T;
|
|
129
|
-
/**
|
|
130
|
-
* Static utility method to create protobuf response messages
|
|
131
|
-
* @param schema Protobuf message schema
|
|
132
|
-
* @param data Optional partial data to initialize the message
|
|
133
|
-
* @returns Created message instance
|
|
134
|
-
*/
|
|
135
|
-
static createResponse<T extends Message>(schema: GenMessage<T>, data?: Partial<T>): T;
|
|
136
|
-
/**
|
|
137
|
-
* Static utility method to serialize protobuf messages to JSON strings
|
|
138
|
-
* @param schema Protobuf message schema
|
|
139
|
-
* @param data Message data to serialize
|
|
140
|
-
* @returns JSON string representation
|
|
141
|
-
*/
|
|
142
|
-
static serialize<T extends Message>(schema: GenMessage<T>, data: T): string;
|
|
143
|
-
/**
|
|
144
|
-
* Static utility method to validate protobuf messages using protovalidate
|
|
145
|
-
* @param schema Protobuf message schema
|
|
146
|
-
* @param data Message data to validate
|
|
147
|
-
* @returns Promise resolving to validation result
|
|
148
|
-
*/
|
|
149
|
-
static validate<T extends Message>(schema: GenMessage<T>, data: T): Promise<SimpleValidationResult>;
|
|
150
|
-
/**
|
|
151
|
-
* Private method to validate messages using the instance validator
|
|
152
|
-
*/
|
|
153
|
-
private validateMessage;
|
|
154
|
-
/**
|
|
155
|
-
* Private method to create error responses matching existing action function patterns
|
|
156
|
-
* This creates a generic error response structure that matches the patterns used in
|
|
157
|
-
* existing action functions like modifyPublicSubscriptionSettings
|
|
158
|
-
*/
|
|
159
|
-
private createErrorResponse;
|
|
160
|
-
/**
|
|
161
|
-
* Private method to create validation error responses
|
|
162
|
-
* This preserves ValidationIssue[] arrays in error responses as required
|
|
163
|
-
*/
|
|
164
|
-
private createValidationErrorResponse;
|
|
165
|
-
/**
|
|
166
|
-
* Private method to create HTTP error responses
|
|
167
|
-
* Handles HTTP errors uniformly like existing action functions
|
|
168
|
-
*/
|
|
169
|
-
private createHttpErrorResponse;
|
|
170
|
-
/**
|
|
171
|
-
* Private method to create network error responses
|
|
172
|
-
* Handles network failures like existing action functions
|
|
173
|
-
*/
|
|
174
|
-
private createNetworkErrorResponse;
|
|
175
|
-
/**
|
|
176
|
-
* Static method to create error responses for use in action functions
|
|
177
|
-
* This allows consumers to create consistent error responses outside of the client
|
|
178
|
-
* @param schema Response schema to create error for
|
|
179
|
-
* @param message Error message
|
|
180
|
-
* @param errorType Error type (defaults to SETTINGS_ERROR_UNKNOWN)
|
|
181
|
-
* @param validationIssues Optional validation issues array
|
|
182
|
-
* @returns Error response matching existing action function patterns
|
|
183
|
-
*/
|
|
184
|
-
static createErrorResponse<T extends Message>(schema: GenMessage<T>, message: string, errorType?: string, validationIssues?: any[]): T;
|
|
185
|
-
}
|