@atomic-solutions/wordpress-api-client 0.1.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/LICENSE +21 -0
- package/README.md +295 -0
- package/dist/calculatePagination-WUlN3OdM.d.cts +19 -0
- package/dist/calculatePagination-WUlN3OdM.d.ts +19 -0
- package/dist/client/index.cjs +1143 -0
- package/dist/client/index.cjs.map +1 -0
- package/dist/client/index.d.cts +10 -0
- package/dist/client/index.d.ts +10 -0
- package/dist/client/index.js +1137 -0
- package/dist/client/index.js.map +1 -0
- package/dist/http/index.cjs +674 -0
- package/dist/http/index.cjs.map +1 -0
- package/dist/http/index.d.cts +12 -0
- package/dist/http/index.d.ts +12 -0
- package/dist/http/index.js +667 -0
- package/dist/http/index.js.map +1 -0
- package/dist/index.cjs +1251 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +51 -0
- package/dist/index.d.ts +51 -0
- package/dist/index.js +1205 -0
- package/dist/index.js.map +1 -0
- package/dist/schemas/index.cjs +414 -0
- package/dist/schemas/index.cjs.map +1 -0
- package/dist/schemas/index.d.cts +1339 -0
- package/dist/schemas/index.d.ts +1339 -0
- package/dist/schemas/index.js +376 -0
- package/dist/schemas/index.js.map +1 -0
- package/dist/testing/index.cjs +1435 -0
- package/dist/testing/index.cjs.map +1 -0
- package/dist/testing/index.d.cts +50 -0
- package/dist/testing/index.d.ts +50 -0
- package/dist/testing/index.js +1426 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/types-8pbwmNdu.d.ts +154 -0
- package/dist/types-BTo088EY.d.cts +154 -0
- package/dist/user.schema-eeUHQ4sI.d.cts +10614 -0
- package/dist/user.schema-eeUHQ4sI.d.ts +10614 -0
- package/dist/utils/index.cjs +47 -0
- package/dist/utils/index.cjs.map +1 -0
- package/dist/utils/index.d.cts +10 -0
- package/dist/utils/index.d.ts +10 -0
- package/dist/utils/index.js +44 -0
- package/dist/utils/index.js.map +1 -0
- package/package.json +103 -0
|
@@ -0,0 +1,1137 @@
|
|
|
1
|
+
import axios, { isAxiosError } from 'axios';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
|
|
4
|
+
// src/client/createClient.ts
|
|
5
|
+
|
|
6
|
+
// src/constants/endpoints.ts
|
|
7
|
+
var ENDPOINTS = {
|
|
8
|
+
// Posts
|
|
9
|
+
POSTS: "/wp/v2/posts",
|
|
10
|
+
POST: (id) => `/wp/v2/posts/${id}`,
|
|
11
|
+
// Categories
|
|
12
|
+
CATEGORIES: "/wp/v2/categories",
|
|
13
|
+
CATEGORY: (id) => `/wp/v2/categories/${id}`,
|
|
14
|
+
// Tags
|
|
15
|
+
TAGS: "/wp/v2/tags",
|
|
16
|
+
TAG: (id) => `/wp/v2/tags/${id}`,
|
|
17
|
+
// Media
|
|
18
|
+
MEDIA: "/wp/v2/media",
|
|
19
|
+
MEDIA_ITEM: (id) => `/wp/v2/media/${id}`,
|
|
20
|
+
// Users
|
|
21
|
+
USERS: "/wp/v2/users",
|
|
22
|
+
USER: (id) => `/wp/v2/users/${id}`,
|
|
23
|
+
USERS_ME: "/wp/v2/users/me",
|
|
24
|
+
// JWT Auth (requires JWT Authentication plugin)
|
|
25
|
+
JWT_TOKEN: "/jwt-auth/v1/token",
|
|
26
|
+
JWT_VALIDATE: "/jwt-auth/v1/token/validate",
|
|
27
|
+
// Pages
|
|
28
|
+
PAGES: "/wp/v2/pages",
|
|
29
|
+
PAGE: (id) => `/wp/v2/pages/${id}`,
|
|
30
|
+
// Comments
|
|
31
|
+
COMMENTS: "/wp/v2/comments",
|
|
32
|
+
COMMENT: (id) => `/wp/v2/comments/${id}`,
|
|
33
|
+
// Search
|
|
34
|
+
SEARCH: "/wp/v2/search"
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
// src/errors/classes/BaseError.ts
|
|
38
|
+
var BaseError = class extends Error {
|
|
39
|
+
constructor(options) {
|
|
40
|
+
super(options.message);
|
|
41
|
+
this.options = options;
|
|
42
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
43
|
+
this.name = this.constructor.name;
|
|
44
|
+
if (Error.captureStackTrace) {
|
|
45
|
+
Error.captureStackTrace(this, this.constructor);
|
|
46
|
+
}
|
|
47
|
+
if (this.options.cause instanceof Error && this.options.cause.stack) {
|
|
48
|
+
this.stack = `${this.stack}
|
|
49
|
+
Caused by: ${this.options.cause.stack}`;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Get reportable data for error tracking/logging
|
|
54
|
+
* Subclasses should override this to add their own reportable fields
|
|
55
|
+
*/
|
|
56
|
+
getReportableData() {
|
|
57
|
+
const { code, operation, userMessage, retryable } = this.options;
|
|
58
|
+
return {
|
|
59
|
+
code,
|
|
60
|
+
operation,
|
|
61
|
+
userMessage,
|
|
62
|
+
retryable
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Custom JSON serialization
|
|
67
|
+
* Makes the error properly serializable for logging/reporting
|
|
68
|
+
*/
|
|
69
|
+
toJSON() {
|
|
70
|
+
return {
|
|
71
|
+
...this.getReportableData(),
|
|
72
|
+
name: this.name,
|
|
73
|
+
message: this.message,
|
|
74
|
+
stack: this.stack
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
// src/errors/mapping/auth.ts
|
|
80
|
+
var AUTH_CODE_TRANSFORMATIONS = {
|
|
81
|
+
// Authentication
|
|
82
|
+
jwt_auth_failed: "auth_failed",
|
|
83
|
+
jwt_auth_invalid_token: "token_expired",
|
|
84
|
+
jwt_auth_bad_request: "invalid_auth_request",
|
|
85
|
+
// Authorization
|
|
86
|
+
rest_forbidden: "forbidden",
|
|
87
|
+
rest_cannot_read: "cannot_read",
|
|
88
|
+
rest_cannot_edit: "cannot_edit",
|
|
89
|
+
rest_cannot_create: "cannot_create",
|
|
90
|
+
rest_cannot_delete: "cannot_delete"
|
|
91
|
+
};
|
|
92
|
+
var AUTH_ERROR_METADATA = {
|
|
93
|
+
// Authentication
|
|
94
|
+
auth_failed: {
|
|
95
|
+
operation: "authenticate",
|
|
96
|
+
retryable: false,
|
|
97
|
+
userMessage: "Invalid username or password"
|
|
98
|
+
},
|
|
99
|
+
token_expired: {
|
|
100
|
+
operation: "validate_token",
|
|
101
|
+
retryable: false,
|
|
102
|
+
userMessage: "Your session has expired. Please sign in again."
|
|
103
|
+
},
|
|
104
|
+
invalid_auth_request: {
|
|
105
|
+
operation: "authenticate",
|
|
106
|
+
retryable: false,
|
|
107
|
+
userMessage: "Invalid login request"
|
|
108
|
+
},
|
|
109
|
+
// Authorization
|
|
110
|
+
forbidden: {
|
|
111
|
+
operation: "authorize",
|
|
112
|
+
retryable: false,
|
|
113
|
+
userMessage: "You do not have permission to access this resource"
|
|
114
|
+
},
|
|
115
|
+
cannot_read: {
|
|
116
|
+
operation: "read_resource",
|
|
117
|
+
retryable: false,
|
|
118
|
+
userMessage: "You do not have permission to view this content"
|
|
119
|
+
},
|
|
120
|
+
cannot_edit: {
|
|
121
|
+
operation: "edit_resource",
|
|
122
|
+
retryable: false,
|
|
123
|
+
userMessage: "You do not have permission to edit this content"
|
|
124
|
+
},
|
|
125
|
+
cannot_create: {
|
|
126
|
+
operation: "create_resource",
|
|
127
|
+
retryable: false,
|
|
128
|
+
userMessage: "You do not have permission to create content"
|
|
129
|
+
},
|
|
130
|
+
cannot_delete: {
|
|
131
|
+
operation: "delete_resource",
|
|
132
|
+
retryable: false,
|
|
133
|
+
userMessage: "You do not have permission to delete this content"
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
// src/errors/mapping/resources.ts
|
|
138
|
+
var RESOURCE_CODE_TRANSFORMATIONS = {
|
|
139
|
+
rest_post_invalid_id: "post_not_found",
|
|
140
|
+
rest_term_invalid: "term_not_found",
|
|
141
|
+
rest_user_invalid_id: "user_not_found",
|
|
142
|
+
rest_no_route: "route_not_found"
|
|
143
|
+
};
|
|
144
|
+
var RESOURCE_ERROR_METADATA = {
|
|
145
|
+
post_not_found: {
|
|
146
|
+
operation: "get_post",
|
|
147
|
+
retryable: false,
|
|
148
|
+
userMessage: "Post not found"
|
|
149
|
+
},
|
|
150
|
+
term_not_found: {
|
|
151
|
+
operation: "get_term",
|
|
152
|
+
retryable: false,
|
|
153
|
+
userMessage: "Category or tag not found"
|
|
154
|
+
},
|
|
155
|
+
user_not_found: {
|
|
156
|
+
operation: "get_user",
|
|
157
|
+
retryable: false,
|
|
158
|
+
userMessage: "User not found"
|
|
159
|
+
},
|
|
160
|
+
route_not_found: {
|
|
161
|
+
operation: "api_request",
|
|
162
|
+
retryable: false,
|
|
163
|
+
userMessage: "The requested resource was not found"
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
// src/errors/mapping/server.ts
|
|
168
|
+
var SERVER_CODE_TRANSFORMATIONS = {
|
|
169
|
+
rest_cookie_invalid_nonce: "invalid_nonce",
|
|
170
|
+
internal_error: "server_error"
|
|
171
|
+
};
|
|
172
|
+
var SERVER_ERROR_METADATA = {
|
|
173
|
+
invalid_nonce: {
|
|
174
|
+
operation: "api_request",
|
|
175
|
+
retryable: true,
|
|
176
|
+
userMessage: "Session expired. Please try again."
|
|
177
|
+
},
|
|
178
|
+
server_error: {
|
|
179
|
+
operation: "api_request",
|
|
180
|
+
retryable: true,
|
|
181
|
+
userMessage: "An unexpected error occurred. Please try again."
|
|
182
|
+
},
|
|
183
|
+
unknown_error: {
|
|
184
|
+
operation: "api_request",
|
|
185
|
+
retryable: false,
|
|
186
|
+
userMessage: "An error occurred"
|
|
187
|
+
}
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
// src/errors/mapping/constants.ts
|
|
191
|
+
var VALIDATION_CODE_TRANSFORMATIONS = {
|
|
192
|
+
rest_invalid_param: "invalid_params",
|
|
193
|
+
rest_missing_callback_param: "missing_params"
|
|
194
|
+
};
|
|
195
|
+
var VALIDATION_ERROR_METADATA = {
|
|
196
|
+
invalid_params: {
|
|
197
|
+
operation: "api_request",
|
|
198
|
+
retryable: false,
|
|
199
|
+
userMessage: "Invalid request parameters"
|
|
200
|
+
},
|
|
201
|
+
missing_params: {
|
|
202
|
+
operation: "api_request",
|
|
203
|
+
retryable: false,
|
|
204
|
+
userMessage: "Missing required parameters"
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
var WORDPRESS_ERROR_METADATA = {
|
|
208
|
+
...AUTH_ERROR_METADATA,
|
|
209
|
+
...RESOURCE_ERROR_METADATA,
|
|
210
|
+
...VALIDATION_ERROR_METADATA,
|
|
211
|
+
...SERVER_ERROR_METADATA
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
// src/errors/mapping/index.ts
|
|
215
|
+
var CODE_TRANSFORMATIONS = {
|
|
216
|
+
...AUTH_CODE_TRANSFORMATIONS,
|
|
217
|
+
...RESOURCE_CODE_TRANSFORMATIONS,
|
|
218
|
+
...VALIDATION_CODE_TRANSFORMATIONS,
|
|
219
|
+
...SERVER_CODE_TRANSFORMATIONS
|
|
220
|
+
};
|
|
221
|
+
var ERROR_METADATA = {
|
|
222
|
+
...AUTH_ERROR_METADATA,
|
|
223
|
+
...RESOURCE_ERROR_METADATA,
|
|
224
|
+
...VALIDATION_ERROR_METADATA,
|
|
225
|
+
...SERVER_ERROR_METADATA
|
|
226
|
+
};
|
|
227
|
+
var mapWordPressCode = (apiCode, status) => {
|
|
228
|
+
const appCode = CODE_TRANSFORMATIONS[apiCode];
|
|
229
|
+
if (appCode) {
|
|
230
|
+
const metadata = ERROR_METADATA[appCode];
|
|
231
|
+
return {
|
|
232
|
+
code: appCode,
|
|
233
|
+
...metadata
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
if (apiCode.includes("invalid_id") || apiCode.includes("not_found")) {
|
|
237
|
+
return {
|
|
238
|
+
code: "route_not_found",
|
|
239
|
+
...ERROR_METADATA.route_not_found
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
if (apiCode.includes("cannot_") || apiCode.includes("forbidden")) {
|
|
243
|
+
return {
|
|
244
|
+
code: "forbidden",
|
|
245
|
+
...ERROR_METADATA.forbidden
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
if (apiCode.includes("invalid_param") || apiCode.includes("missing_")) {
|
|
249
|
+
return {
|
|
250
|
+
code: "invalid_params",
|
|
251
|
+
...ERROR_METADATA.invalid_params
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
if (apiCode.includes("nonce")) {
|
|
255
|
+
return {
|
|
256
|
+
code: "invalid_nonce",
|
|
257
|
+
...ERROR_METADATA.invalid_nonce
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
if (status === 401) {
|
|
261
|
+
return {
|
|
262
|
+
code: "auth_failed",
|
|
263
|
+
retryable: false,
|
|
264
|
+
userMessage: "Authentication required"
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
if (status === 403) {
|
|
268
|
+
return {
|
|
269
|
+
code: "forbidden",
|
|
270
|
+
...ERROR_METADATA.forbidden
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
if (status === 404) {
|
|
274
|
+
return {
|
|
275
|
+
code: "route_not_found",
|
|
276
|
+
...ERROR_METADATA.route_not_found
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
if (status >= 500) {
|
|
280
|
+
return {
|
|
281
|
+
code: "server_error",
|
|
282
|
+
...ERROR_METADATA.server_error
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
return {
|
|
286
|
+
code: "unknown_error",
|
|
287
|
+
...ERROR_METADATA.unknown_error
|
|
288
|
+
};
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
// src/errors/classes/WordPressApiError.ts
|
|
292
|
+
var WordPressApiError = class extends BaseError {
|
|
293
|
+
constructor(options) {
|
|
294
|
+
const metadata = WORDPRESS_ERROR_METADATA[options.code] ?? {
|
|
295
|
+
operation: "wordpress_api_request",
|
|
296
|
+
retryable: false
|
|
297
|
+
};
|
|
298
|
+
const enrichedOptions = {
|
|
299
|
+
...options,
|
|
300
|
+
operation: options.operation || metadata.operation,
|
|
301
|
+
userMessage: options.userMessage || metadata.userMessage,
|
|
302
|
+
retryable: options.retryable ?? metadata.retryable
|
|
303
|
+
};
|
|
304
|
+
super(enrichedOptions);
|
|
305
|
+
}
|
|
306
|
+
// Convenient getters for frequently accessed fields (no duplication)
|
|
307
|
+
get wpCode() {
|
|
308
|
+
return this.options.code;
|
|
309
|
+
}
|
|
310
|
+
get originalCode() {
|
|
311
|
+
return this.options.originalCode;
|
|
312
|
+
}
|
|
313
|
+
get statusCode() {
|
|
314
|
+
return this.options.statusCode;
|
|
315
|
+
}
|
|
316
|
+
get url() {
|
|
317
|
+
return this.options.url;
|
|
318
|
+
}
|
|
319
|
+
get method() {
|
|
320
|
+
return this.options.method;
|
|
321
|
+
}
|
|
322
|
+
get requestBody() {
|
|
323
|
+
return this.options.requestBody;
|
|
324
|
+
}
|
|
325
|
+
get responseBody() {
|
|
326
|
+
return this.options.responseBody;
|
|
327
|
+
}
|
|
328
|
+
get data() {
|
|
329
|
+
return this.options.data;
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Check if error is an authentication error
|
|
333
|
+
*/
|
|
334
|
+
get isAuthError() {
|
|
335
|
+
return this.statusCode === 401 || this.wpCode === "auth_failed" || this.wpCode === "token_expired" || this.wpCode === "invalid_auth_request";
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Check if error is a not found error
|
|
339
|
+
*/
|
|
340
|
+
get isNotFoundError() {
|
|
341
|
+
return this.statusCode === 404 || this.wpCode === "route_not_found" || this.wpCode === "post_not_found" || this.wpCode === "term_not_found" || this.wpCode === "user_not_found";
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Get reportable data for error tracking/logging
|
|
345
|
+
* Includes HTTP context and WordPress-specific fields
|
|
346
|
+
*/
|
|
347
|
+
getReportableData() {
|
|
348
|
+
return {
|
|
349
|
+
code: this.options.code,
|
|
350
|
+
operation: this.options.operation,
|
|
351
|
+
userMessage: this.options.userMessage,
|
|
352
|
+
retryable: this.options.retryable,
|
|
353
|
+
statusCode: this.options.statusCode,
|
|
354
|
+
url: this.options.url,
|
|
355
|
+
method: this.options.method,
|
|
356
|
+
wpCode: this.options.code,
|
|
357
|
+
originalCode: this.options.originalCode
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
};
|
|
361
|
+
|
|
362
|
+
// src/errors/classes/WordPressDataValidationError.ts
|
|
363
|
+
var WordPressDataValidationError = class _WordPressDataValidationError extends BaseError {
|
|
364
|
+
constructor(options) {
|
|
365
|
+
const fieldErrors = options.zodError ? _WordPressDataValidationError.extractFieldErrorsFromZod(options.zodError) : void 0;
|
|
366
|
+
super({
|
|
367
|
+
code: "validation_error",
|
|
368
|
+
message: options.message,
|
|
369
|
+
operation: options.operation,
|
|
370
|
+
userMessage: options.userMessage || "Received unexpected data from WordPress",
|
|
371
|
+
retryable: false,
|
|
372
|
+
cause: options.cause,
|
|
373
|
+
url: options.url,
|
|
374
|
+
zodError: options.zodError,
|
|
375
|
+
value: options.value,
|
|
376
|
+
fieldErrors
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
// Convenient getters for validation-specific fields (no duplication)
|
|
380
|
+
get url() {
|
|
381
|
+
return this.options.url;
|
|
382
|
+
}
|
|
383
|
+
get zodError() {
|
|
384
|
+
return this.options.zodError;
|
|
385
|
+
}
|
|
386
|
+
get invalidValue() {
|
|
387
|
+
return this.options.value;
|
|
388
|
+
}
|
|
389
|
+
get fieldErrors() {
|
|
390
|
+
return this.options.fieldErrors;
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* Get reportable data for error tracking/logging
|
|
394
|
+
* Includes validation-specific fields
|
|
395
|
+
*/
|
|
396
|
+
getReportableData() {
|
|
397
|
+
return {
|
|
398
|
+
code: this.options.code,
|
|
399
|
+
operation: this.options.operation,
|
|
400
|
+
userMessage: this.options.userMessage,
|
|
401
|
+
retryable: false,
|
|
402
|
+
fieldErrors: this.options.fieldErrors,
|
|
403
|
+
url: this.options.url
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
/**
|
|
407
|
+
* Extract field errors from Zod error
|
|
408
|
+
*/
|
|
409
|
+
static extractFieldErrorsFromZod(zodError) {
|
|
410
|
+
if (!zodError?.errors) {
|
|
411
|
+
return void 0;
|
|
412
|
+
}
|
|
413
|
+
const fieldErrors = {};
|
|
414
|
+
for (const issue of zodError.errors) {
|
|
415
|
+
const path = issue.path.join(".");
|
|
416
|
+
if (!fieldErrors[path]) {
|
|
417
|
+
fieldErrors[path] = [];
|
|
418
|
+
}
|
|
419
|
+
fieldErrors[path].push(issue.message);
|
|
420
|
+
}
|
|
421
|
+
return fieldErrors;
|
|
422
|
+
}
|
|
423
|
+
/**
|
|
424
|
+
* Get all error messages as a flat array
|
|
425
|
+
*/
|
|
426
|
+
getMessages() {
|
|
427
|
+
if (!this.fieldErrors) {
|
|
428
|
+
return [this.message];
|
|
429
|
+
}
|
|
430
|
+
const messages = [];
|
|
431
|
+
for (const fieldMessages of Object.values(this.fieldErrors)) {
|
|
432
|
+
messages.push(...fieldMessages);
|
|
433
|
+
}
|
|
434
|
+
return messages;
|
|
435
|
+
}
|
|
436
|
+
/**
|
|
437
|
+
* Check if a specific field has errors
|
|
438
|
+
*/
|
|
439
|
+
hasFieldError(field) {
|
|
440
|
+
return this.fieldErrors ? field in this.fieldErrors : false;
|
|
441
|
+
}
|
|
442
|
+
/**
|
|
443
|
+
* Get error messages for a specific field
|
|
444
|
+
*/
|
|
445
|
+
getFieldError(field) {
|
|
446
|
+
return this.fieldErrors?.[field];
|
|
447
|
+
}
|
|
448
|
+
};
|
|
449
|
+
|
|
450
|
+
// src/http/handleApiResponse.ts
|
|
451
|
+
var handleApiResponse = (response, schema, options) => {
|
|
452
|
+
const validationMode = options?.validationMode ?? "strict";
|
|
453
|
+
if (validationMode === "warn") {
|
|
454
|
+
const result = schema.safeParse(response.data);
|
|
455
|
+
if (!result.success) {
|
|
456
|
+
const validationError = new WordPressDataValidationError({
|
|
457
|
+
message: `WordPress API response validation failed for ${response.config.url || "unknown endpoint"}`,
|
|
458
|
+
url: response.config.url,
|
|
459
|
+
zodError: result.error,
|
|
460
|
+
value: response.data,
|
|
461
|
+
userMessage: "Received unexpected data from WordPress"
|
|
462
|
+
});
|
|
463
|
+
options?.onValidationError?.(validationError);
|
|
464
|
+
options?.errorReporter?.(validationError);
|
|
465
|
+
console.warn("[wordpress-utils] Validation warning:", validationError.message);
|
|
466
|
+
return response.data;
|
|
467
|
+
}
|
|
468
|
+
return result.data;
|
|
469
|
+
}
|
|
470
|
+
try {
|
|
471
|
+
return schema.parse(response.data);
|
|
472
|
+
} catch (error2) {
|
|
473
|
+
if (error2 && typeof error2 === "object" && "issues" in error2) {
|
|
474
|
+
const validationError = new WordPressDataValidationError({
|
|
475
|
+
message: `WordPress API response validation failed for ${response.config.url || "unknown endpoint"}`,
|
|
476
|
+
url: response.config.url,
|
|
477
|
+
zodError: error2,
|
|
478
|
+
value: response.data,
|
|
479
|
+
userMessage: "Received unexpected data from WordPress"
|
|
480
|
+
});
|
|
481
|
+
options?.onValidationError?.(validationError);
|
|
482
|
+
options?.errorReporter?.(validationError);
|
|
483
|
+
throw validationError;
|
|
484
|
+
}
|
|
485
|
+
throw error2;
|
|
486
|
+
}
|
|
487
|
+
};
|
|
488
|
+
|
|
489
|
+
// src/utils/calculatePagination.ts
|
|
490
|
+
var calculatePagination = (input) => {
|
|
491
|
+
const { page, perPage, total, totalPages } = input;
|
|
492
|
+
const hasNextPage = page < totalPages;
|
|
493
|
+
const hasPrevPage = page > 1;
|
|
494
|
+
return {
|
|
495
|
+
page,
|
|
496
|
+
perPage,
|
|
497
|
+
total,
|
|
498
|
+
totalPages,
|
|
499
|
+
hasNextPage,
|
|
500
|
+
hasPrevPage,
|
|
501
|
+
nextPage: hasNextPage ? page + 1 : null,
|
|
502
|
+
prevPage: hasPrevPage ? page - 1 : null
|
|
503
|
+
};
|
|
504
|
+
};
|
|
505
|
+
|
|
506
|
+
// src/utils/getPaginationMeta.ts
|
|
507
|
+
var getPaginationMeta = (headers) => {
|
|
508
|
+
if (!headers) {
|
|
509
|
+
return {
|
|
510
|
+
total: 0,
|
|
511
|
+
totalPages: 0
|
|
512
|
+
};
|
|
513
|
+
}
|
|
514
|
+
const wpTotal = headers["x-wp-total"];
|
|
515
|
+
const wpTotalPages = headers["x-wp-totalpages"];
|
|
516
|
+
if (!wpTotal || !wpTotalPages) {
|
|
517
|
+
return {
|
|
518
|
+
total: 0,
|
|
519
|
+
totalPages: 0
|
|
520
|
+
};
|
|
521
|
+
}
|
|
522
|
+
const total = parseInt(wpTotal, 10);
|
|
523
|
+
const totalPages = parseInt(wpTotalPages, 10);
|
|
524
|
+
return {
|
|
525
|
+
total,
|
|
526
|
+
totalPages
|
|
527
|
+
};
|
|
528
|
+
};
|
|
529
|
+
|
|
530
|
+
// src/http/handlePaginatedApiResponse.ts
|
|
531
|
+
var handlePaginatedApiResponse = (response, schema, params = {}, options) => {
|
|
532
|
+
const validationMode = options?.validationMode ?? "strict";
|
|
533
|
+
let data;
|
|
534
|
+
if (validationMode === "warn") {
|
|
535
|
+
const result = schema.safeParse(response.data);
|
|
536
|
+
if (!result.success) {
|
|
537
|
+
const validationError = new WordPressDataValidationError({
|
|
538
|
+
message: `WordPress API response validation failed for ${response.config.url || "unknown endpoint"}`,
|
|
539
|
+
url: response.config.url,
|
|
540
|
+
zodError: result.error,
|
|
541
|
+
value: response.data,
|
|
542
|
+
userMessage: "Received unexpected data from WordPress"
|
|
543
|
+
});
|
|
544
|
+
options?.onValidationError?.(validationError);
|
|
545
|
+
options?.errorReporter?.(validationError);
|
|
546
|
+
console.warn("[wordpress-utils] Validation warning:", validationError.message);
|
|
547
|
+
data = Array.isArray(response.data) ? response.data : [];
|
|
548
|
+
} else {
|
|
549
|
+
data = result.data;
|
|
550
|
+
}
|
|
551
|
+
} else {
|
|
552
|
+
try {
|
|
553
|
+
data = schema.parse(response.data);
|
|
554
|
+
} catch (error2) {
|
|
555
|
+
if (error2 && typeof error2 === "object" && "issues" in error2) {
|
|
556
|
+
const validationError = new WordPressDataValidationError({
|
|
557
|
+
message: `WordPress API response validation failed for ${response.config.url || "unknown endpoint"}`,
|
|
558
|
+
url: response.config.url,
|
|
559
|
+
zodError: error2,
|
|
560
|
+
value: response.data,
|
|
561
|
+
userMessage: "Received unexpected data from WordPress"
|
|
562
|
+
});
|
|
563
|
+
options?.onValidationError?.(validationError);
|
|
564
|
+
options?.errorReporter?.(validationError);
|
|
565
|
+
throw validationError;
|
|
566
|
+
}
|
|
567
|
+
throw error2;
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
const { total, totalPages } = getPaginationMeta(response.headers);
|
|
571
|
+
const page = params.page || 1;
|
|
572
|
+
const perPage = params.per_page || 10;
|
|
573
|
+
const pagination = calculatePagination({
|
|
574
|
+
page,
|
|
575
|
+
perPage,
|
|
576
|
+
total,
|
|
577
|
+
totalPages
|
|
578
|
+
});
|
|
579
|
+
return {
|
|
580
|
+
data,
|
|
581
|
+
pagination
|
|
582
|
+
};
|
|
583
|
+
};
|
|
584
|
+
|
|
585
|
+
// src/logging/logger.ts
|
|
586
|
+
var DEBUG_PREFIX = "[wordpress-utils]";
|
|
587
|
+
var isDebugEnabled = () => {
|
|
588
|
+
if (typeof process !== "undefined" && process.env) {
|
|
589
|
+
return process.env.DEBUG === "true" || process.env.DEBUG === "1";
|
|
590
|
+
}
|
|
591
|
+
return false;
|
|
592
|
+
};
|
|
593
|
+
var debug = (...args) => {
|
|
594
|
+
if (isDebugEnabled()) {
|
|
595
|
+
console.log(DEBUG_PREFIX, ...args);
|
|
596
|
+
}
|
|
597
|
+
};
|
|
598
|
+
var error = (...args) => {
|
|
599
|
+
console.error(DEBUG_PREFIX, ...args);
|
|
600
|
+
};
|
|
601
|
+
|
|
602
|
+
// src/http/interceptors/request.ts
|
|
603
|
+
var setupRequestInterceptor = (axiosInstance, config, client) => {
|
|
604
|
+
axiosInstance.interceptors.request.use(
|
|
605
|
+
async (requestConfig) => {
|
|
606
|
+
if (config.jwtToken) {
|
|
607
|
+
const token = await config.jwtToken.get();
|
|
608
|
+
if (token) {
|
|
609
|
+
requestConfig.headers.Authorization = `Bearer ${token}`;
|
|
610
|
+
debug("JWT token injected");
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
if (config.onRequest) {
|
|
614
|
+
return config.onRequest(requestConfig, client);
|
|
615
|
+
}
|
|
616
|
+
return requestConfig;
|
|
617
|
+
},
|
|
618
|
+
(error2) => {
|
|
619
|
+
return Promise.reject(error2);
|
|
620
|
+
}
|
|
621
|
+
);
|
|
622
|
+
};
|
|
623
|
+
|
|
624
|
+
// src/http/interceptors/response.ts
|
|
625
|
+
var setupResponseInterceptor = (axiosInstance, config, client) => {
|
|
626
|
+
axiosInstance.interceptors.response.use(
|
|
627
|
+
async (response) => {
|
|
628
|
+
debug("Response:", response.config.url, response.status);
|
|
629
|
+
if (config.onResponse) {
|
|
630
|
+
return config.onResponse(response, client);
|
|
631
|
+
}
|
|
632
|
+
return response;
|
|
633
|
+
},
|
|
634
|
+
(error2) => {
|
|
635
|
+
return Promise.reject(error2);
|
|
636
|
+
}
|
|
637
|
+
);
|
|
638
|
+
};
|
|
639
|
+
var setupErrorInterceptor = (axiosInstance, config, client) => {
|
|
640
|
+
axiosInstance.interceptors.response.use(
|
|
641
|
+
(response) => response,
|
|
642
|
+
async (axiosError) => {
|
|
643
|
+
const status = axiosError.response?.status || 500;
|
|
644
|
+
const errorData = axiosError.response?.data;
|
|
645
|
+
const apiCode = errorData?.code || "unknown_error";
|
|
646
|
+
const wpMessage = errorData?.message || axiosError.message || "Unknown error";
|
|
647
|
+
const mappedError = mapWordPressCode(apiCode, status);
|
|
648
|
+
const wpError = new WordPressApiError({
|
|
649
|
+
message: wpMessage,
|
|
650
|
+
statusCode: status,
|
|
651
|
+
code: mappedError.code,
|
|
652
|
+
// Transformed app-level code
|
|
653
|
+
originalCode: apiCode,
|
|
654
|
+
// Original WordPress API code
|
|
655
|
+
retryable: mappedError.retryable,
|
|
656
|
+
userMessage: mappedError.userMessage,
|
|
657
|
+
operation: axiosError.config?.url || "wordpress_api_request",
|
|
658
|
+
url: axiosError.config?.url || "",
|
|
659
|
+
method: axiosError.config?.method?.toUpperCase() || "GET",
|
|
660
|
+
requestBody: axiosError.config?.data,
|
|
661
|
+
responseBody: errorData,
|
|
662
|
+
cause: axiosError
|
|
663
|
+
});
|
|
664
|
+
if (config.debug) {
|
|
665
|
+
debug("WordPress error:", apiCode, status, wpMessage);
|
|
666
|
+
error(wpError);
|
|
667
|
+
}
|
|
668
|
+
if ((status === 401 || status === 403) && config.onAuthError && isAxiosError(axiosError) && !axiosError.config?._retry) {
|
|
669
|
+
if (config.debug) {
|
|
670
|
+
debug("Auth error detected, calling onAuthError handler");
|
|
671
|
+
}
|
|
672
|
+
try {
|
|
673
|
+
const shouldRetry = await config.onAuthError(wpError, client);
|
|
674
|
+
if (shouldRetry) {
|
|
675
|
+
if (config.debug) {
|
|
676
|
+
debug("Retrying request after auth error");
|
|
677
|
+
}
|
|
678
|
+
axiosError.config._retry = true;
|
|
679
|
+
return axiosInstance.request(axiosError.config);
|
|
680
|
+
}
|
|
681
|
+
} catch (authErrorHandlerError) {
|
|
682
|
+
if (config.debug) {
|
|
683
|
+
debug("onAuthError handler threw error", authErrorHandlerError);
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
if (config.onError) {
|
|
688
|
+
config.onError(wpError, client);
|
|
689
|
+
}
|
|
690
|
+
config.errorReporter?.report(wpError);
|
|
691
|
+
return Promise.reject(wpError);
|
|
692
|
+
}
|
|
693
|
+
);
|
|
694
|
+
};
|
|
695
|
+
var paginationParamsSchema = z.object({
|
|
696
|
+
/** Current page number */
|
|
697
|
+
page: z.number().int().positive().optional(),
|
|
698
|
+
/** Items per page */
|
|
699
|
+
per_page: z.number().int().positive().max(100).optional(),
|
|
700
|
+
/** Offset for pagination */
|
|
701
|
+
offset: z.number().int().nonnegative().optional(),
|
|
702
|
+
/** Sort order */
|
|
703
|
+
order: z.enum(["asc", "desc"]).optional(),
|
|
704
|
+
/** Field to sort by */
|
|
705
|
+
orderby: z.string().optional()
|
|
706
|
+
});
|
|
707
|
+
z.object({
|
|
708
|
+
/** Total number of items */
|
|
709
|
+
total: z.number(),
|
|
710
|
+
/** Total number of pages */
|
|
711
|
+
totalPages: z.number(),
|
|
712
|
+
/** Current page */
|
|
713
|
+
currentPage: z.number(),
|
|
714
|
+
/** Items per page */
|
|
715
|
+
perPage: z.number()
|
|
716
|
+
});
|
|
717
|
+
z.object({
|
|
718
|
+
username: z.string(),
|
|
719
|
+
password: z.string()
|
|
720
|
+
});
|
|
721
|
+
var JwtTokenResponseSchema = z.object({
|
|
722
|
+
token: z.string(),
|
|
723
|
+
user_email: z.string(),
|
|
724
|
+
user_nicename: z.string(),
|
|
725
|
+
user_display_name: z.string()
|
|
726
|
+
});
|
|
727
|
+
z.object({
|
|
728
|
+
code: z.string(),
|
|
729
|
+
data: z.object({
|
|
730
|
+
status: z.number()
|
|
731
|
+
})
|
|
732
|
+
});
|
|
733
|
+
z.object({
|
|
734
|
+
code: z.string(),
|
|
735
|
+
message: z.string(),
|
|
736
|
+
data: z.object({
|
|
737
|
+
status: z.number()
|
|
738
|
+
}).optional()
|
|
739
|
+
});
|
|
740
|
+
var RenderedContentSchema = z.object({
|
|
741
|
+
rendered: z.string(),
|
|
742
|
+
protected: z.boolean().optional()
|
|
743
|
+
});
|
|
744
|
+
var GuidSchema = z.object({
|
|
745
|
+
rendered: z.string()
|
|
746
|
+
});
|
|
747
|
+
z.enum([
|
|
748
|
+
"publish",
|
|
749
|
+
"future",
|
|
750
|
+
"draft",
|
|
751
|
+
"pending",
|
|
752
|
+
"private",
|
|
753
|
+
"trash",
|
|
754
|
+
"auto-draft",
|
|
755
|
+
"inherit"
|
|
756
|
+
]);
|
|
757
|
+
var HalLinkItemSchema = z.object({
|
|
758
|
+
href: z.string(),
|
|
759
|
+
embeddable: z.boolean().optional(),
|
|
760
|
+
templated: z.boolean().optional()
|
|
761
|
+
});
|
|
762
|
+
var HalLinksSchema = z.object({
|
|
763
|
+
self: z.array(HalLinkItemSchema).optional(),
|
|
764
|
+
collection: z.array(HalLinkItemSchema).optional(),
|
|
765
|
+
about: z.array(HalLinkItemSchema).optional(),
|
|
766
|
+
author: z.array(HalLinkItemSchema).optional(),
|
|
767
|
+
replies: z.array(HalLinkItemSchema).optional(),
|
|
768
|
+
"wp:featuredmedia": z.array(HalLinkItemSchema).optional(),
|
|
769
|
+
"wp:attachment": z.array(HalLinkItemSchema).optional(),
|
|
770
|
+
"wp:term": z.array(HalLinkItemSchema).optional(),
|
|
771
|
+
"wp:post_type": z.array(HalLinkItemSchema).optional(),
|
|
772
|
+
curies: z.array(
|
|
773
|
+
z.object({
|
|
774
|
+
name: z.string(),
|
|
775
|
+
href: z.string(),
|
|
776
|
+
templated: z.boolean()
|
|
777
|
+
})
|
|
778
|
+
).optional()
|
|
779
|
+
}).passthrough();
|
|
780
|
+
z.object({
|
|
781
|
+
id: z.number(),
|
|
782
|
+
date: z.string(),
|
|
783
|
+
date_gmt: z.string(),
|
|
784
|
+
modified: z.string(),
|
|
785
|
+
modified_gmt: z.string(),
|
|
786
|
+
slug: z.string(),
|
|
787
|
+
status: z.string(),
|
|
788
|
+
type: z.string(),
|
|
789
|
+
link: z.string(),
|
|
790
|
+
_links: HalLinksSchema.optional()
|
|
791
|
+
});
|
|
792
|
+
var CategorySchema = z.object({
|
|
793
|
+
id: z.number(),
|
|
794
|
+
count: z.number(),
|
|
795
|
+
description: z.string().optional(),
|
|
796
|
+
link: z.string(),
|
|
797
|
+
name: z.string(),
|
|
798
|
+
slug: z.string(),
|
|
799
|
+
taxonomy: z.string(),
|
|
800
|
+
parent: z.number(),
|
|
801
|
+
meta: z.any().optional(),
|
|
802
|
+
_links: HalLinksSchema.optional()
|
|
803
|
+
});
|
|
804
|
+
var CategoriesListSchema = z.array(CategorySchema);
|
|
805
|
+
paginationParamsSchema.extend({
|
|
806
|
+
context: z.enum(["view", "embed", "edit"]).optional(),
|
|
807
|
+
search: z.string().optional(),
|
|
808
|
+
exclude: z.array(z.number()).optional(),
|
|
809
|
+
include: z.array(z.number()).optional(),
|
|
810
|
+
hide_empty: z.boolean().optional(),
|
|
811
|
+
parent: z.number().optional(),
|
|
812
|
+
post: z.number().optional(),
|
|
813
|
+
slug: z.string().optional()
|
|
814
|
+
});
|
|
815
|
+
var TagSchema = z.object({
|
|
816
|
+
id: z.number(),
|
|
817
|
+
count: z.number(),
|
|
818
|
+
description: z.string().optional(),
|
|
819
|
+
link: z.string(),
|
|
820
|
+
name: z.string(),
|
|
821
|
+
slug: z.string(),
|
|
822
|
+
taxonomy: z.string(),
|
|
823
|
+
meta: z.any().optional(),
|
|
824
|
+
_links: HalLinksSchema.optional()
|
|
825
|
+
});
|
|
826
|
+
z.array(TagSchema);
|
|
827
|
+
var MediaSizeSchema = z.object({
|
|
828
|
+
file: z.string(),
|
|
829
|
+
width: z.number(),
|
|
830
|
+
height: z.number(),
|
|
831
|
+
filesize: z.number().optional(),
|
|
832
|
+
mime_type: z.string(),
|
|
833
|
+
source_url: z.string()
|
|
834
|
+
});
|
|
835
|
+
var MediaSizesSchema = z.object({
|
|
836
|
+
thumbnail: MediaSizeSchema.optional(),
|
|
837
|
+
medium: MediaSizeSchema.optional(),
|
|
838
|
+
medium_large: MediaSizeSchema.optional(),
|
|
839
|
+
large: MediaSizeSchema.optional(),
|
|
840
|
+
full: MediaSizeSchema.optional()
|
|
841
|
+
}).passthrough();
|
|
842
|
+
var ImageMetaSchema = z.object({
|
|
843
|
+
aperture: z.string().optional(),
|
|
844
|
+
credit: z.string().optional(),
|
|
845
|
+
camera: z.string().optional(),
|
|
846
|
+
caption: z.string().optional(),
|
|
847
|
+
created_timestamp: z.string().optional(),
|
|
848
|
+
copyright: z.string().optional(),
|
|
849
|
+
focal_length: z.string().optional(),
|
|
850
|
+
iso: z.string().optional(),
|
|
851
|
+
shutter_speed: z.string().optional(),
|
|
852
|
+
title: z.string().optional(),
|
|
853
|
+
orientation: z.string().optional(),
|
|
854
|
+
keywords: z.array(z.string()).optional()
|
|
855
|
+
});
|
|
856
|
+
var MediaDetailsSchema = z.object({
|
|
857
|
+
width: z.number(),
|
|
858
|
+
height: z.number(),
|
|
859
|
+
file: z.string(),
|
|
860
|
+
filesize: z.number().optional(),
|
|
861
|
+
sizes: MediaSizesSchema,
|
|
862
|
+
image_meta: ImageMetaSchema.optional()
|
|
863
|
+
});
|
|
864
|
+
var MediaSchema = z.object({
|
|
865
|
+
id: z.number(),
|
|
866
|
+
date: z.string(),
|
|
867
|
+
date_gmt: z.string(),
|
|
868
|
+
guid: GuidSchema,
|
|
869
|
+
modified: z.string(),
|
|
870
|
+
modified_gmt: z.string(),
|
|
871
|
+
slug: z.string(),
|
|
872
|
+
status: z.string(),
|
|
873
|
+
type: z.string(),
|
|
874
|
+
link: z.string(),
|
|
875
|
+
title: RenderedContentSchema,
|
|
876
|
+
author: z.number(),
|
|
877
|
+
comment_status: z.string(),
|
|
878
|
+
ping_status: z.string(),
|
|
879
|
+
template: z.string().optional(),
|
|
880
|
+
meta: z.any().optional(),
|
|
881
|
+
description: RenderedContentSchema,
|
|
882
|
+
caption: RenderedContentSchema,
|
|
883
|
+
alt_text: z.string(),
|
|
884
|
+
media_type: z.string(),
|
|
885
|
+
mime_type: z.string(),
|
|
886
|
+
media_details: MediaDetailsSchema,
|
|
887
|
+
post: z.number().nullable(),
|
|
888
|
+
source_url: z.string(),
|
|
889
|
+
_links: HalLinksSchema.optional()
|
|
890
|
+
});
|
|
891
|
+
z.array(MediaSchema);
|
|
892
|
+
var PostSchema = z.object({
|
|
893
|
+
id: z.number(),
|
|
894
|
+
date: z.string(),
|
|
895
|
+
date_gmt: z.string(),
|
|
896
|
+
guid: GuidSchema,
|
|
897
|
+
modified: z.string(),
|
|
898
|
+
modified_gmt: z.string(),
|
|
899
|
+
slug: z.string(),
|
|
900
|
+
status: z.string(),
|
|
901
|
+
type: z.string(),
|
|
902
|
+
link: z.string(),
|
|
903
|
+
title: RenderedContentSchema,
|
|
904
|
+
content: RenderedContentSchema,
|
|
905
|
+
excerpt: RenderedContentSchema,
|
|
906
|
+
author: z.number(),
|
|
907
|
+
featured_media: z.number(),
|
|
908
|
+
comment_status: z.string(),
|
|
909
|
+
ping_status: z.string(),
|
|
910
|
+
sticky: z.boolean(),
|
|
911
|
+
template: z.string(),
|
|
912
|
+
format: z.string(),
|
|
913
|
+
meta: z.any().optional(),
|
|
914
|
+
categories: z.array(z.number()),
|
|
915
|
+
tags: z.array(z.number()).optional(),
|
|
916
|
+
_links: HalLinksSchema.optional()
|
|
917
|
+
});
|
|
918
|
+
var PostsListSchema = z.array(PostSchema);
|
|
919
|
+
paginationParamsSchema.extend({
|
|
920
|
+
context: z.enum(["view", "embed", "edit"]).optional(),
|
|
921
|
+
search: z.string().optional(),
|
|
922
|
+
after: z.string().optional(),
|
|
923
|
+
before: z.string().optional(),
|
|
924
|
+
author: z.union([z.number(), z.array(z.number())]).optional(),
|
|
925
|
+
author_exclude: z.array(z.number()).optional(),
|
|
926
|
+
exclude: z.array(z.number()).optional(),
|
|
927
|
+
include: z.array(z.number()).optional(),
|
|
928
|
+
categories: z.union([z.number(), z.array(z.number())]).optional(),
|
|
929
|
+
categories_exclude: z.array(z.number()).optional(),
|
|
930
|
+
tags: z.union([z.number(), z.array(z.number())]).optional(),
|
|
931
|
+
tags_exclude: z.array(z.number()).optional(),
|
|
932
|
+
sticky: z.boolean().optional()
|
|
933
|
+
});
|
|
934
|
+
var EmbeddedPostSchema = z.object({
|
|
935
|
+
id: z.number(),
|
|
936
|
+
title: z.string(),
|
|
937
|
+
content: z.string(),
|
|
938
|
+
featured_image: z.string().optional(),
|
|
939
|
+
published_date: z.string(),
|
|
940
|
+
categories: z.array(
|
|
941
|
+
z.object({
|
|
942
|
+
id: z.number(),
|
|
943
|
+
name: z.string(),
|
|
944
|
+
slug: z.string(),
|
|
945
|
+
taxonomy: z.string().optional(),
|
|
946
|
+
description: z.string().optional(),
|
|
947
|
+
parent: z.number().optional(),
|
|
948
|
+
count: z.number().optional()
|
|
949
|
+
})
|
|
950
|
+
).optional()
|
|
951
|
+
});
|
|
952
|
+
z.array(EmbeddedPostSchema);
|
|
953
|
+
var AvatarUrlsSchema = z.object({
|
|
954
|
+
"24": z.string().optional(),
|
|
955
|
+
"48": z.string().optional(),
|
|
956
|
+
"96": z.string().optional()
|
|
957
|
+
});
|
|
958
|
+
var UserSchema = z.object({
|
|
959
|
+
id: z.number(),
|
|
960
|
+
username: z.string().optional(),
|
|
961
|
+
// Only in edit context
|
|
962
|
+
name: z.string(),
|
|
963
|
+
first_name: z.string().optional(),
|
|
964
|
+
last_name: z.string().optional(),
|
|
965
|
+
email: z.string().optional(),
|
|
966
|
+
// Only for current user or admin
|
|
967
|
+
url: z.string(),
|
|
968
|
+
description: z.string(),
|
|
969
|
+
link: z.string(),
|
|
970
|
+
locale: z.string().optional(),
|
|
971
|
+
// Only for current user
|
|
972
|
+
nickname: z.string().optional(),
|
|
973
|
+
// Only in edit context
|
|
974
|
+
slug: z.string(),
|
|
975
|
+
registered_date: z.string().optional(),
|
|
976
|
+
// Only in edit context
|
|
977
|
+
roles: z.array(z.string()).optional(),
|
|
978
|
+
// Only in edit context
|
|
979
|
+
capabilities: z.record(z.boolean()).optional(),
|
|
980
|
+
// Only in edit context
|
|
981
|
+
extra_capabilities: z.record(z.boolean()).optional(),
|
|
982
|
+
// Only in edit context
|
|
983
|
+
avatar_urls: AvatarUrlsSchema.optional(),
|
|
984
|
+
meta: z.any().optional(),
|
|
985
|
+
_links: HalLinksSchema.optional()
|
|
986
|
+
});
|
|
987
|
+
z.array(UserSchema);
|
|
988
|
+
var CurrentUserSchema = UserSchema.extend({
|
|
989
|
+
username: z.string(),
|
|
990
|
+
email: z.string(),
|
|
991
|
+
locale: z.string(),
|
|
992
|
+
nickname: z.string(),
|
|
993
|
+
registered_date: z.string(),
|
|
994
|
+
roles: z.array(z.string())
|
|
995
|
+
});
|
|
996
|
+
|
|
997
|
+
// src/api/auth.ts
|
|
998
|
+
var createAuthAPI = (axios2, options) => ({
|
|
999
|
+
/**
|
|
1000
|
+
* Login with username/password and get JWT token
|
|
1001
|
+
*/
|
|
1002
|
+
async login(input) {
|
|
1003
|
+
const response = await axios2.post(ENDPOINTS.JWT_TOKEN, input);
|
|
1004
|
+
return handleApiResponse(response, JwtTokenResponseSchema, options);
|
|
1005
|
+
},
|
|
1006
|
+
/**
|
|
1007
|
+
* Validate current JWT token
|
|
1008
|
+
*
|
|
1009
|
+
* Requires Authorization header to be set
|
|
1010
|
+
*/
|
|
1011
|
+
async validateToken() {
|
|
1012
|
+
try {
|
|
1013
|
+
const response = await axios2.post(ENDPOINTS.JWT_VALIDATE);
|
|
1014
|
+
return response.data?.code === "jwt_auth_valid_token";
|
|
1015
|
+
} catch {
|
|
1016
|
+
return false;
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
});
|
|
1020
|
+
|
|
1021
|
+
// src/api/categories.ts
|
|
1022
|
+
var createCategoriesAPI = (axios2, options) => ({
|
|
1023
|
+
/**
|
|
1024
|
+
* Get list of categories with pagination
|
|
1025
|
+
*/
|
|
1026
|
+
async list(params) {
|
|
1027
|
+
const response = await axios2.get(ENDPOINTS.CATEGORIES, { params });
|
|
1028
|
+
return handlePaginatedApiResponse(response, CategoriesListSchema, params, options);
|
|
1029
|
+
},
|
|
1030
|
+
/**
|
|
1031
|
+
* Get single category by ID
|
|
1032
|
+
*/
|
|
1033
|
+
async get(id) {
|
|
1034
|
+
const response = await axios2.get(ENDPOINTS.CATEGORY(id));
|
|
1035
|
+
return handleApiResponse(response, CategorySchema, options);
|
|
1036
|
+
}
|
|
1037
|
+
});
|
|
1038
|
+
|
|
1039
|
+
// src/api/media.ts
|
|
1040
|
+
var createMediaAPI = (axios2, options) => ({
|
|
1041
|
+
/**
|
|
1042
|
+
* Get single media item by ID
|
|
1043
|
+
*/
|
|
1044
|
+
async get(id) {
|
|
1045
|
+
const response = await axios2.get(ENDPOINTS.MEDIA_ITEM(id));
|
|
1046
|
+
return handleApiResponse(response, MediaSchema, options);
|
|
1047
|
+
}
|
|
1048
|
+
});
|
|
1049
|
+
|
|
1050
|
+
// src/api/posts.ts
|
|
1051
|
+
var createPostsAPI = (axios2, options) => ({
|
|
1052
|
+
/**
|
|
1053
|
+
* Get list of posts with pagination
|
|
1054
|
+
*/
|
|
1055
|
+
async list(params) {
|
|
1056
|
+
const response = await axios2.get(ENDPOINTS.POSTS, { params });
|
|
1057
|
+
return handlePaginatedApiResponse(response, PostsListSchema, params, options);
|
|
1058
|
+
},
|
|
1059
|
+
/**
|
|
1060
|
+
* Get single post by ID
|
|
1061
|
+
*/
|
|
1062
|
+
async get(id) {
|
|
1063
|
+
const response = await axios2.get(ENDPOINTS.POST(id));
|
|
1064
|
+
return handleApiResponse(response, PostSchema, options);
|
|
1065
|
+
},
|
|
1066
|
+
/**
|
|
1067
|
+
* Get single post by slug
|
|
1068
|
+
*/
|
|
1069
|
+
async getBySlug(slug) {
|
|
1070
|
+
const response = await axios2.get(ENDPOINTS.POSTS, {
|
|
1071
|
+
params: { slug, per_page: 1 }
|
|
1072
|
+
});
|
|
1073
|
+
const posts = handleApiResponse(response, PostsListSchema, options);
|
|
1074
|
+
return posts[0] || null;
|
|
1075
|
+
}
|
|
1076
|
+
});
|
|
1077
|
+
|
|
1078
|
+
// src/api/users.ts
|
|
1079
|
+
var createUsersAPI = (axios2, options) => ({
|
|
1080
|
+
/**
|
|
1081
|
+
* Get current authenticated user
|
|
1082
|
+
*/
|
|
1083
|
+
async me() {
|
|
1084
|
+
const response = await axios2.get(ENDPOINTS.USERS_ME);
|
|
1085
|
+
return handleApiResponse(response, CurrentUserSchema, options);
|
|
1086
|
+
},
|
|
1087
|
+
/**
|
|
1088
|
+
* Get user by ID
|
|
1089
|
+
*/
|
|
1090
|
+
async get(id) {
|
|
1091
|
+
const response = await axios2.get(ENDPOINTS.USER(id));
|
|
1092
|
+
return handleApiResponse(response, UserSchema, options);
|
|
1093
|
+
}
|
|
1094
|
+
});
|
|
1095
|
+
|
|
1096
|
+
// src/client/createClient.ts
|
|
1097
|
+
var DEFAULT_ERROR_REPORTER = {
|
|
1098
|
+
report: (error2) => {
|
|
1099
|
+
console.error("[wordpress-utils]", error2);
|
|
1100
|
+
}
|
|
1101
|
+
};
|
|
1102
|
+
var createClient = (config) => {
|
|
1103
|
+
const fullConfig = {
|
|
1104
|
+
...config,
|
|
1105
|
+
errorReporter: config.errorReporter ?? DEFAULT_ERROR_REPORTER
|
|
1106
|
+
};
|
|
1107
|
+
const axiosInstance = axios.create({
|
|
1108
|
+
baseURL: fullConfig.baseURL,
|
|
1109
|
+
timeout: fullConfig.timeout || 3e4,
|
|
1110
|
+
headers: {
|
|
1111
|
+
"Content-Type": "application/json",
|
|
1112
|
+
...fullConfig.headers
|
|
1113
|
+
}
|
|
1114
|
+
});
|
|
1115
|
+
const responseOptions = {
|
|
1116
|
+
errorReporter: fullConfig.errorReporter?.report,
|
|
1117
|
+
onValidationError: fullConfig.onValidationError,
|
|
1118
|
+
validationMode: fullConfig.validationMode
|
|
1119
|
+
};
|
|
1120
|
+
const client = {
|
|
1121
|
+
config: fullConfig,
|
|
1122
|
+
axios: axiosInstance,
|
|
1123
|
+
posts: createPostsAPI(axiosInstance, responseOptions),
|
|
1124
|
+
categories: createCategoriesAPI(axiosInstance, responseOptions),
|
|
1125
|
+
media: createMediaAPI(axiosInstance, responseOptions),
|
|
1126
|
+
users: createUsersAPI(axiosInstance, responseOptions),
|
|
1127
|
+
auth: createAuthAPI(axiosInstance, responseOptions)
|
|
1128
|
+
};
|
|
1129
|
+
setupRequestInterceptor(axiosInstance, fullConfig, client);
|
|
1130
|
+
setupResponseInterceptor(axiosInstance, fullConfig, client);
|
|
1131
|
+
setupErrorInterceptor(axiosInstance, fullConfig, client);
|
|
1132
|
+
return client;
|
|
1133
|
+
};
|
|
1134
|
+
|
|
1135
|
+
export { createClient };
|
|
1136
|
+
//# sourceMappingURL=index.js.map
|
|
1137
|
+
//# sourceMappingURL=index.js.map
|