@readpress/wp-blog 1.0.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/index.js ADDED
@@ -0,0 +1,1326 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __defProps = Object.defineProperties;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
10
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
11
+ var __spreadValues = (a, b) => {
12
+ for (var prop in b || (b = {}))
13
+ if (__hasOwnProp.call(b, prop))
14
+ __defNormalProp(a, prop, b[prop]);
15
+ if (__getOwnPropSymbols)
16
+ for (var prop of __getOwnPropSymbols(b)) {
17
+ if (__propIsEnum.call(b, prop))
18
+ __defNormalProp(a, prop, b[prop]);
19
+ }
20
+ return a;
21
+ };
22
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
23
+ var __export = (target, all) => {
24
+ for (var name in all)
25
+ __defProp(target, name, { get: all[name], enumerable: true });
26
+ };
27
+ var __copyProps = (to, from, except, desc) => {
28
+ if (from && typeof from === "object" || typeof from === "function") {
29
+ for (let key of __getOwnPropNames(from))
30
+ if (!__hasOwnProp.call(to, key) && key !== except)
31
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
32
+ }
33
+ return to;
34
+ };
35
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
36
+
37
+ // src/index.ts
38
+ var index_exports = {};
39
+ __export(index_exports, {
40
+ WpClientError: () => WpClientError,
41
+ createWpBlogClient: () => createWpBlogClient,
42
+ getAuthorById: () => getAuthorById,
43
+ getAuthors: () => getAuthors,
44
+ getCategories: () => getCategories,
45
+ getPostById: () => getPostById,
46
+ getPostBySlug: () => getPostBySlug,
47
+ getPosts: () => getPosts,
48
+ getTags: () => getTags,
49
+ parseContentPlaceholders: () => parseContentPlaceholders,
50
+ queryGraphql: () => queryGraphql,
51
+ queryRaw: () => queryRaw,
52
+ searchPosts: () => searchPosts
53
+ });
54
+ module.exports = __toCommonJS(index_exports);
55
+
56
+ // src/core/errors.ts
57
+ var WpClientError = class extends Error {
58
+ constructor(code, message, status, details = {}) {
59
+ super(message);
60
+ this.name = "WpClientError";
61
+ this.code = code;
62
+ this.status = status;
63
+ this.wpCode = details.wpCode;
64
+ this.wpMessage = details.wpMessage;
65
+ this.wpData = details.wpData;
66
+ }
67
+ };
68
+
69
+ // src/domain/placeholders.ts
70
+ var DEFAULT_NAMESPACE = "wpapp";
71
+ var DEFAULT_MAX_PROPS_LENGTH = 1e4;
72
+ var PLACEHOLDER_NAME_REGEX = /^[A-Za-z][A-Za-z0-9_-]*$/;
73
+ function escapeRegex(value) {
74
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
75
+ }
76
+ function normalizeNamespace(value) {
77
+ const trimmed = value == null ? void 0 : value.trim();
78
+ if (!trimmed) {
79
+ return DEFAULT_NAMESPACE;
80
+ }
81
+ return trimmed;
82
+ }
83
+ function normalizeMaxPropsLength(value) {
84
+ if (!value || !Number.isInteger(value) || value <= 0) {
85
+ return DEFAULT_MAX_PROPS_LENGTH;
86
+ }
87
+ return value;
88
+ }
89
+ function parseProps(rawProps, maxPropsLength) {
90
+ const trimmed = rawProps == null ? void 0 : rawProps.trim();
91
+ if (!trimmed) {
92
+ return {};
93
+ }
94
+ if (trimmed.length > maxPropsLength) {
95
+ return null;
96
+ }
97
+ try {
98
+ const parsed = JSON.parse(trimmed);
99
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
100
+ return null;
101
+ }
102
+ return parsed;
103
+ } catch (e) {
104
+ return null;
105
+ }
106
+ }
107
+ function parseContentPlaceholders(contentHtml, options = {}) {
108
+ if (!contentHtml) {
109
+ return [{ type: "html", html: "" }];
110
+ }
111
+ const namespace = normalizeNamespace(options.namespace);
112
+ const maxPropsLength = normalizeMaxPropsLength(options.maxPropsLength);
113
+ const markerRegex = new RegExp(
114
+ `<!--\\s*${escapeRegex(namespace)}:([A-Za-z][A-Za-z0-9_-]*)(?:\\s+([\\s\\S]*?))?\\s*-->`,
115
+ "g"
116
+ );
117
+ const parts = [];
118
+ let cursor = 0;
119
+ let match;
120
+ while ((match = markerRegex.exec(contentHtml)) !== null) {
121
+ const [fullMatch, rawName, rawProps] = match;
122
+ const matchIndex = match.index;
123
+ if (matchIndex > cursor) {
124
+ parts.push({ type: "html", html: contentHtml.slice(cursor, matchIndex) });
125
+ }
126
+ const name = rawName == null ? void 0 : rawName.trim();
127
+ const props = parseProps(rawProps, maxPropsLength);
128
+ if (!name || !PLACEHOLDER_NAME_REGEX.test(name) || !props) {
129
+ parts.push({ type: "html", html: fullMatch });
130
+ cursor = markerRegex.lastIndex;
131
+ continue;
132
+ }
133
+ parts.push({
134
+ type: "placeholder",
135
+ name,
136
+ props
137
+ });
138
+ cursor = markerRegex.lastIndex;
139
+ }
140
+ if (cursor < contentHtml.length) {
141
+ parts.push({ type: "html", html: contentHtml.slice(cursor) });
142
+ }
143
+ if (parts.length === 0) {
144
+ return [{ type: "html", html: contentHtml }];
145
+ }
146
+ return parts;
147
+ }
148
+
149
+ // src/core/config.ts
150
+ var DEFAULT_PER_PAGE = 10;
151
+ var DEFAULT_ENDPOINT = "/wp-json/wp/v2/posts";
152
+ function readEnv(name) {
153
+ var _a, _b;
154
+ const scopedGlobal = globalThis;
155
+ return (_b = (_a = scopedGlobal.process) == null ? void 0 : _a.env) == null ? void 0 : _b[name];
156
+ }
157
+ function normalizeWpUrl(rawUrl) {
158
+ const trimmed = rawUrl.trim();
159
+ if (!trimmed) {
160
+ throw new WpClientError("INVALID_CONFIG", "WP URL cannot be empty.");
161
+ }
162
+ try {
163
+ const url = new URL(trimmed);
164
+ return url.toString().replace(/\/$/, "");
165
+ } catch (e) {
166
+ throw new WpClientError("INVALID_CONFIG", `Invalid WP URL: ${rawUrl}`);
167
+ }
168
+ }
169
+ function normalizePathOrUrl(value, label) {
170
+ const trimmed = value.trim();
171
+ if (!trimmed) {
172
+ throw new WpClientError("INVALID_CONFIG", `${label} cannot be empty.`);
173
+ }
174
+ if (/^https?:\/\//i.test(trimmed)) {
175
+ return trimmed;
176
+ }
177
+ return trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
178
+ }
179
+ function parseHeadersJson(raw) {
180
+ if (!raw) {
181
+ return void 0;
182
+ }
183
+ let parsed;
184
+ try {
185
+ parsed = JSON.parse(raw);
186
+ } catch (e) {
187
+ throw new WpClientError("INVALID_CONFIG", "WP_AUTH_HEADERS_JSON must be valid JSON.");
188
+ }
189
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
190
+ throw new WpClientError("INVALID_CONFIG", "WP_AUTH_HEADERS_JSON must be a JSON object.");
191
+ }
192
+ const headers = {};
193
+ for (const [key, value] of Object.entries(parsed)) {
194
+ if (typeof value !== "string") {
195
+ throw new WpClientError("INVALID_CONFIG", "WP_AUTH_HEADERS_JSON values must be strings.");
196
+ }
197
+ headers[key] = value;
198
+ }
199
+ return headers;
200
+ }
201
+ function resolveAuthType(config) {
202
+ var _a;
203
+ const explicitType = (_a = config.type) != null ? _a : readEnv("WP_AUTH_TYPE");
204
+ if (explicitType) {
205
+ const normalized = explicitType.toLowerCase();
206
+ if (normalized === "none" || normalized === "basic" || normalized === "bearer" || normalized === "headers") {
207
+ return normalized;
208
+ }
209
+ throw new WpClientError("INVALID_CONFIG", "WP_AUTH_TYPE must be one of: none, basic, bearer, headers.");
210
+ }
211
+ if (config.headers && Object.keys(config.headers).length > 0) {
212
+ return "headers";
213
+ }
214
+ if (config.token) {
215
+ return "bearer";
216
+ }
217
+ if (config.user || config.appPassword) {
218
+ return "basic";
219
+ }
220
+ return "none";
221
+ }
222
+ function resolveAuth(options) {
223
+ var _a, _b, _c, _d, _e;
224
+ const auth = (_a = options.auth) != null ? _a : {};
225
+ const user = (_b = auth.user) != null ? _b : readEnv("WP_AUTH_USER");
226
+ const appPassword = (_c = auth.appPassword) != null ? _c : readEnv("WP_AUTH_APP_PASSWORD");
227
+ const token = (_d = auth.token) != null ? _d : readEnv("WP_AUTH_TOKEN");
228
+ const headers = (_e = auth.headers) != null ? _e : parseHeadersJson(readEnv("WP_AUTH_HEADERS_JSON"));
229
+ const resolved = {
230
+ type: auth.type,
231
+ user: user == null ? void 0 : user.trim(),
232
+ appPassword: appPassword == null ? void 0 : appPassword.trim(),
233
+ token: token == null ? void 0 : token.trim(),
234
+ headers
235
+ };
236
+ const type = resolveAuthType(resolved);
237
+ if (type === "none") {
238
+ return { type: "none" };
239
+ }
240
+ if (type === "basic") {
241
+ if (!resolved.user || !resolved.appPassword) {
242
+ throw new WpClientError(
243
+ "INVALID_CONFIG",
244
+ "Basic auth requires WP_AUTH_USER and WP_AUTH_APP_PASSWORD (or auth.user/auth.appPassword)."
245
+ );
246
+ }
247
+ return { type, user: resolved.user, appPassword: resolved.appPassword };
248
+ }
249
+ if (type === "bearer") {
250
+ if (!resolved.token) {
251
+ throw new WpClientError("INVALID_CONFIG", "Bearer auth requires WP_AUTH_TOKEN (or auth.token).");
252
+ }
253
+ return { type, token: resolved.token };
254
+ }
255
+ if (!resolved.headers || Object.keys(resolved.headers).length === 0) {
256
+ throw new WpClientError(
257
+ "INVALID_CONFIG",
258
+ "Headers auth requires WP_AUTH_HEADERS_JSON (or auth.headers) with at least one header."
259
+ );
260
+ }
261
+ return { type, headers: resolved.headers };
262
+ }
263
+ function resolveRewriteLinks(options) {
264
+ const rules = options.rewriteLinks;
265
+ if (!rules) {
266
+ return void 0;
267
+ }
268
+ if (!Array.isArray(rules)) {
269
+ throw new WpClientError("INVALID_CONFIG", "rewriteLinks must be an array.");
270
+ }
271
+ for (const [index, rule] of rules.entries()) {
272
+ if (!rule || typeof rule !== "object") {
273
+ throw new WpClientError("INVALID_CONFIG", `rewriteLinks[${index}] must be an object.`);
274
+ }
275
+ if (!rule.source || typeof rule.source !== "string") {
276
+ throw new WpClientError("INVALID_CONFIG", `rewriteLinks[${index}].source must be a non-empty string.`);
277
+ }
278
+ if (!rule.source.startsWith("/")) {
279
+ throw new WpClientError("INVALID_CONFIG", `rewriteLinks[${index}].source must start with '/'.`);
280
+ }
281
+ const hasDestination = typeof rule.destination === "string" && rule.destination.length > 0;
282
+ const isIgnore = rule.action === "ignore";
283
+ const hasTransform = typeof rule.transform === "function";
284
+ if (!hasDestination && !isIgnore && !hasTransform) {
285
+ throw new WpClientError(
286
+ "INVALID_CONFIG",
287
+ `rewriteLinks[${index}] must define destination, action: "ignore", or transform.`
288
+ );
289
+ }
290
+ if (hasDestination && !rule.destination.startsWith("/")) {
291
+ throw new WpClientError("INVALID_CONFIG", `rewriteLinks[${index}].destination must start with '/'.`);
292
+ }
293
+ }
294
+ return rules;
295
+ }
296
+ function resolveClassNameMap(options) {
297
+ const map = options.classNameMap;
298
+ if (!map) {
299
+ return void 0;
300
+ }
301
+ if (typeof map !== "object" || Array.isArray(map)) {
302
+ throw new WpClientError("INVALID_CONFIG", "classNameMap must be an object.");
303
+ }
304
+ for (const [key, value] of Object.entries(map)) {
305
+ if (!key.trim()) {
306
+ throw new WpClientError("INVALID_CONFIG", "classNameMap keys must be non-empty class names.");
307
+ }
308
+ if (typeof value === "string") {
309
+ continue;
310
+ }
311
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
312
+ throw new WpClientError("INVALID_CONFIG", `classNameMap[${key}] must be a string or object.`);
313
+ }
314
+ if (typeof value.className !== "string" || !value.className.trim()) {
315
+ throw new WpClientError("INVALID_CONFIG", `classNameMap[${key}].className must be a non-empty string.`);
316
+ }
317
+ if (value.mode !== void 0 && value.mode !== "append" && value.mode !== "replace" && value.mode !== "replace-all") {
318
+ throw new WpClientError(
319
+ "INVALID_CONFIG",
320
+ `classNameMap[${key}].mode must be "append", "replace", or "replace-all".`
321
+ );
322
+ }
323
+ }
324
+ return map;
325
+ }
326
+ function resolveClientOptions(options = {}) {
327
+ var _a, _b, _c, _d, _e;
328
+ const wpUrl = (_a = options.wpUrl) != null ? _a : readEnv("WP_URL");
329
+ if (!wpUrl) {
330
+ throw new WpClientError("INVALID_CONFIG", "Missing WordPress URL. Set WP_URL or pass wpUrl.");
331
+ }
332
+ const globalFetch = globalThis.fetch;
333
+ const fetchImpl = (_b = options.fetchImpl) != null ? _b : globalFetch;
334
+ if (!fetchImpl) {
335
+ throw new WpClientError("INVALID_CONFIG", "Global fetch is unavailable. Pass fetchImpl explicitly.");
336
+ }
337
+ const perPage = (_c = options.perPage) != null ? _c : DEFAULT_PER_PAGE;
338
+ const endpoint = normalizePathOrUrl(
339
+ (_e = (_d = options.endpoint) != null ? _d : readEnv("WP_ENDPOINT")) != null ? _e : DEFAULT_ENDPOINT,
340
+ "WP_ENDPOINT"
341
+ );
342
+ return {
343
+ wpUrl: normalizeWpUrl(wpUrl),
344
+ endpoint,
345
+ perPage,
346
+ auth: resolveAuth(options),
347
+ rewriteLinks: resolveRewriteLinks(options),
348
+ classNameMap: resolveClassNameMap(options),
349
+ fetchImpl,
350
+ requestInit: options.requestInit
351
+ };
352
+ }
353
+
354
+ // src/transport/graphql.ts
355
+ function resolveUrl(baseUrl, pathOrUrl) {
356
+ if (/^https?:\/\//i.test(pathOrUrl)) {
357
+ return pathOrUrl;
358
+ }
359
+ return `${baseUrl}${pathOrUrl}`;
360
+ }
361
+ function buildRequestInit(options) {
362
+ var _a;
363
+ return __spreadValues({}, (_a = options.requestInit) != null ? _a : {});
364
+ }
365
+ function buildAuthHeaderValue(user, appPassword) {
366
+ const plain = `${user}:${appPassword}`;
367
+ if (typeof globalThis.btoa !== "function") {
368
+ throw new WpClientError("INVALID_CONFIG", "Global btoa is unavailable for auth header encoding.");
369
+ }
370
+ return `Basic ${globalThis.btoa(plain)}`;
371
+ }
372
+ function applyAuth(requestInit, options) {
373
+ var _a, _b;
374
+ const headers = new Headers((_a = requestInit.headers) != null ? _a : void 0);
375
+ if (options.auth.type === "basic") {
376
+ headers.set("Authorization", buildAuthHeaderValue(options.auth.user, options.auth.appPassword));
377
+ } else if (options.auth.type === "bearer") {
378
+ headers.set("Authorization", `Bearer ${options.auth.token}`);
379
+ } else if (options.auth.type === "headers") {
380
+ for (const [key, value] of Object.entries((_b = options.auth.headers) != null ? _b : {})) {
381
+ headers.set(key, value);
382
+ }
383
+ }
384
+ return __spreadProps(__spreadValues({}, requestInit), {
385
+ headers
386
+ });
387
+ }
388
+ function normalizeGraphqlErrors(payload) {
389
+ const errors = payload == null ? void 0 : payload.errors;
390
+ if (!Array.isArray(errors)) {
391
+ return void 0;
392
+ }
393
+ return errors.filter((error) => !!error && typeof error === "object");
394
+ }
395
+ async function queryGraphqlFromApi(options, params) {
396
+ var _a, _b, _c;
397
+ if (!((_a = params.query) == null ? void 0 : _a.trim())) {
398
+ throw new WpClientError("INVALID_INPUT", "queryGraphql requires query.");
399
+ }
400
+ const requestInit = applyAuth(buildRequestInit(options), options);
401
+ const headers = new Headers((_b = requestInit.headers) != null ? _b : void 0);
402
+ headers.set("Content-Type", "application/json");
403
+ let response;
404
+ try {
405
+ response = await options.fetchImpl(resolveUrl(options.wpUrl, options.endpoint), __spreadProps(__spreadValues({}, requestInit), {
406
+ method: "POST",
407
+ headers,
408
+ body: JSON.stringify({
409
+ query: params.query,
410
+ variables: (_c = params.variables) != null ? _c : {}
411
+ })
412
+ }));
413
+ } catch (error) {
414
+ if (error instanceof WpClientError) {
415
+ throw error;
416
+ }
417
+ const message = error instanceof Error ? error.message : "Unknown fetch error.";
418
+ throw new WpClientError("REQUEST_FAILED", `WordPress request failed: ${message}`);
419
+ }
420
+ if (!response.ok) {
421
+ let details = "";
422
+ try {
423
+ details = await response.text();
424
+ } catch (e) {
425
+ details = "";
426
+ }
427
+ const suffix = details ? `: ${details}` : ".";
428
+ throw new WpClientError("REQUEST_FAILED", `WordPress request failed with status ${response.status}${suffix}`, response.status);
429
+ }
430
+ let payload;
431
+ try {
432
+ payload = await response.json();
433
+ } catch (e) {
434
+ throw new WpClientError("INVALID_RESPONSE", "WordPress response was not valid JSON.");
435
+ }
436
+ if (!payload || typeof payload !== "object") {
437
+ throw new WpClientError("INVALID_RESPONSE", "WordPress GraphQL response must be an object.");
438
+ }
439
+ return {
440
+ data: payload.data,
441
+ errors: normalizeGraphqlErrors(payload)
442
+ };
443
+ }
444
+
445
+ // src/transport/rest.ts
446
+ function parseHeaderInt(value, headerName) {
447
+ const parsed = Number.parseInt(value != null ? value : "", 10);
448
+ if (!Number.isFinite(parsed) || parsed < 0) {
449
+ throw new WpClientError("INVALID_RESPONSE", `Missing or invalid ${headerName} response header.`);
450
+ }
451
+ return parsed;
452
+ }
453
+ function buildRequestInit2(options) {
454
+ var _a;
455
+ return __spreadValues({}, (_a = options.requestInit) != null ? _a : {});
456
+ }
457
+ function buildAuthHeaderValue2(user, appPassword) {
458
+ const plain = `${user}:${appPassword}`;
459
+ if (typeof globalThis.btoa !== "function") {
460
+ throw new WpClientError("INVALID_CONFIG", "Global btoa is unavailable for auth header encoding.");
461
+ }
462
+ return `Basic ${globalThis.btoa(plain)}`;
463
+ }
464
+ function applyAuth2(requestInit, options, authRequired) {
465
+ var _a, _b;
466
+ if (authRequired && options.auth.type === "none") {
467
+ throw new WpClientError(
468
+ "INVALID_CONFIG",
469
+ "Missing auth for non-public request. Configure WP_AUTH_TYPE and related credentials/headers."
470
+ );
471
+ }
472
+ const headers = new Headers((_a = requestInit.headers) != null ? _a : void 0);
473
+ if (options.auth.type === "basic") {
474
+ headers.set("Authorization", buildAuthHeaderValue2(options.auth.user, options.auth.appPassword));
475
+ } else if (options.auth.type === "bearer") {
476
+ headers.set("Authorization", `Bearer ${options.auth.token}`);
477
+ } else if (options.auth.type === "headers") {
478
+ for (const [key, value] of Object.entries((_b = options.auth.headers) != null ? _b : {})) {
479
+ headers.set(key, value);
480
+ }
481
+ }
482
+ return __spreadProps(__spreadValues({}, requestInit), {
483
+ headers
484
+ });
485
+ }
486
+ function resolveUrl2(baseUrl, pathOrUrl) {
487
+ if (/^https?:\/\//i.test(pathOrUrl)) {
488
+ return pathOrUrl;
489
+ }
490
+ return `${baseUrl}${pathOrUrl}`;
491
+ }
492
+ function appendRestQueryParams(pathOrUrl, params) {
493
+ if (!params) {
494
+ return pathOrUrl;
495
+ }
496
+ const [base, query = ""] = pathOrUrl.split("?");
497
+ const search = new URLSearchParams(query);
498
+ for (const [key, value] of Object.entries(params)) {
499
+ if (value === void 0 || value === null) {
500
+ continue;
501
+ }
502
+ search.set(key, String(value));
503
+ }
504
+ const encoded = search.toString();
505
+ return encoded ? `${base}?${encoded}` : base;
506
+ }
507
+ async function throwRestRequestFailed(response) {
508
+ let wpCode;
509
+ let wpMessage;
510
+ let wpData;
511
+ try {
512
+ const payload = await response.json();
513
+ if (typeof payload.code === "string") {
514
+ wpCode = payload.code;
515
+ }
516
+ if (typeof payload.message === "string") {
517
+ wpMessage = payload.message;
518
+ }
519
+ wpData = payload.data;
520
+ } catch (e) {
521
+ }
522
+ const message = wpMessage ? `WordPress request failed with status ${response.status}: ${wpMessage}` : `WordPress request failed with status ${response.status}.`;
523
+ throw new WpClientError("REQUEST_FAILED", message, response.status, {
524
+ wpCode,
525
+ wpMessage,
526
+ wpData
527
+ });
528
+ }
529
+ function toBlogTerm(term) {
530
+ var _a, _b;
531
+ return {
532
+ id: term.id,
533
+ slug: (_a = term.slug) != null ? _a : "",
534
+ name: (_b = term.name) != null ? _b : "",
535
+ count: Number.isFinite(term.count) ? Number(term.count) : 0
536
+ };
537
+ }
538
+ function resolveRestOrder(order) {
539
+ switch (order) {
540
+ case "alphabetical":
541
+ return { orderby: "name", order: "asc" };
542
+ case "count":
543
+ return { orderby: "count", order: "desc" };
544
+ default:
545
+ return {};
546
+ }
547
+ }
548
+ async function fetchPostsFromRest(options, input) {
549
+ const params = new URLSearchParams({
550
+ page: String(input.page),
551
+ per_page: String(input.perPage),
552
+ _embed: "author,wp:featuredmedia,wp:term"
553
+ });
554
+ async function resolveTermIdBySlug(taxonomyPath, slug) {
555
+ const requestInit2 = applyAuth2(buildRequestInit2(options), options, input.authRequired);
556
+ const url2 = `${resolveUrl2(
557
+ options.wpUrl,
558
+ `/wp-json/wp/v2/${taxonomyPath}`
559
+ )}?slug=${encodeURIComponent(slug)}&per_page=1`;
560
+ let response2;
561
+ try {
562
+ response2 = await options.fetchImpl(url2, requestInit2);
563
+ } catch (error) {
564
+ if (error instanceof WpClientError) {
565
+ throw error;
566
+ }
567
+ const message = error instanceof Error ? error.message : "Unknown fetch error.";
568
+ throw new WpClientError("REQUEST_FAILED", `WordPress request failed: ${message}`);
569
+ }
570
+ if (!response2.ok) {
571
+ await throwRestRequestFailed(response2);
572
+ }
573
+ let payload2;
574
+ try {
575
+ payload2 = await response2.json();
576
+ } catch (e) {
577
+ throw new WpClientError("INVALID_RESPONSE", "WordPress response was not valid JSON.");
578
+ }
579
+ if (!Array.isArray(payload2)) {
580
+ throw new WpClientError("INVALID_RESPONSE", "WordPress terms response must be an array.");
581
+ }
582
+ const first = payload2[0];
583
+ if (!(first == null ? void 0 : first.id) || !Number.isInteger(first.id) || first.id <= 0) {
584
+ return null;
585
+ }
586
+ return first.id;
587
+ }
588
+ if (input.slug) {
589
+ params.set("slug", input.slug);
590
+ }
591
+ if (input.id !== void 0) {
592
+ params.set("include", String(input.id));
593
+ }
594
+ if (input.search) {
595
+ params.set("search", input.search);
596
+ }
597
+ if (input.status) {
598
+ params.set("status", input.status);
599
+ }
600
+ if (input.categorySlug) {
601
+ const categoryId = await resolveTermIdBySlug("categories", input.categorySlug);
602
+ if (!categoryId) {
603
+ return { posts: [], totalItems: 0, totalPages: 0 };
604
+ }
605
+ params.set("categories", String(categoryId));
606
+ }
607
+ if (input.tagSlug) {
608
+ const tagId = await resolveTermIdBySlug("tags", input.tagSlug);
609
+ if (!tagId) {
610
+ return { posts: [], totalItems: 0, totalPages: 0 };
611
+ }
612
+ params.set("tags", String(tagId));
613
+ }
614
+ if (input.context) {
615
+ params.set("context", input.context);
616
+ }
617
+ const url = `${resolveUrl2(options.wpUrl, options.endpoint)}?${params.toString()}`;
618
+ const requestInit = applyAuth2(buildRequestInit2(options), options, input.authRequired);
619
+ let response;
620
+ try {
621
+ response = await options.fetchImpl(url, requestInit);
622
+ } catch (error) {
623
+ if (error instanceof WpClientError) {
624
+ throw error;
625
+ }
626
+ const message = error instanceof Error ? error.message : "Unknown fetch error.";
627
+ throw new WpClientError("REQUEST_FAILED", `WordPress request failed: ${message}`);
628
+ }
629
+ if (!response.ok) {
630
+ await throwRestRequestFailed(response);
631
+ }
632
+ let payload;
633
+ try {
634
+ payload = await response.json();
635
+ } catch (e) {
636
+ throw new WpClientError("INVALID_RESPONSE", "WordPress response was not valid JSON.");
637
+ }
638
+ if (!Array.isArray(payload)) {
639
+ throw new WpClientError("INVALID_RESPONSE", "WordPress posts response must be an array.");
640
+ }
641
+ return {
642
+ posts: payload,
643
+ totalItems: parseHeaderInt(response.headers.get("X-WP-Total"), "X-WP-Total"),
644
+ totalPages: parseHeaderInt(response.headers.get("X-WP-TotalPages"), "X-WP-TotalPages")
645
+ };
646
+ }
647
+ async function fetchPostsFromApi(options, input) {
648
+ return fetchPostsFromRest(options, input);
649
+ }
650
+ async function fetchTermsFromRest(options, input) {
651
+ const requestInit = applyAuth2(buildRequestInit2(options), options, false);
652
+ const basePath = input.taxonomy === "categories" ? "/wp-json/wp/v2/categories" : "/wp-json/wp/v2/tags";
653
+ const { orderby, order } = resolveRestOrder(input.order);
654
+ const url = appendRestQueryParams(basePath, {
655
+ per_page: 100,
656
+ hide_empty: true,
657
+ orderby,
658
+ order
659
+ });
660
+ let response;
661
+ try {
662
+ response = await options.fetchImpl(resolveUrl2(options.wpUrl, url), requestInit);
663
+ } catch (error) {
664
+ if (error instanceof WpClientError) {
665
+ throw error;
666
+ }
667
+ const message = error instanceof Error ? error.message : "Unknown fetch error.";
668
+ throw new WpClientError("REQUEST_FAILED", `WordPress request failed: ${message}`);
669
+ }
670
+ if (!response.ok) {
671
+ await throwRestRequestFailed(response);
672
+ }
673
+ let payload;
674
+ try {
675
+ payload = await response.json();
676
+ } catch (e) {
677
+ throw new WpClientError("INVALID_RESPONSE", "WordPress response was not valid JSON.");
678
+ }
679
+ if (!Array.isArray(payload)) {
680
+ throw new WpClientError("INVALID_RESPONSE", "WordPress terms response must be an array.");
681
+ }
682
+ return payload.map((term) => {
683
+ var _a, _b, _c;
684
+ const t = term;
685
+ if (!t.id || !Number.isInteger(t.id) || t.id <= 0) {
686
+ return null;
687
+ }
688
+ return toBlogTerm({
689
+ id: t.id,
690
+ slug: (_a = t.slug) != null ? _a : "",
691
+ name: (_b = t.name) != null ? _b : "",
692
+ count: (_c = t.count) != null ? _c : 0
693
+ });
694
+ }).filter((term) => term !== null);
695
+ }
696
+ async function fetchTermsFromApi(options, input) {
697
+ return fetchTermsFromRest(options, input);
698
+ }
699
+ function toBlogAuthor(author) {
700
+ if (!(author == null ? void 0 : author.id) || !Number.isInteger(author.id) || author.id <= 0) {
701
+ return null;
702
+ }
703
+ return __spreadValues({}, author);
704
+ }
705
+ async function fetchAuthorsFromRest(options, input) {
706
+ const requestInit = applyAuth2(buildRequestInit2(options), options, false);
707
+ const url = appendRestQueryParams("/wp-json/wp/v2/users", {
708
+ page: input.page,
709
+ per_page: input.perPage
710
+ });
711
+ let response;
712
+ try {
713
+ response = await options.fetchImpl(resolveUrl2(options.wpUrl, url), requestInit);
714
+ } catch (error) {
715
+ if (error instanceof WpClientError) {
716
+ throw error;
717
+ }
718
+ const message = error instanceof Error ? error.message : "Unknown fetch error.";
719
+ throw new WpClientError("REQUEST_FAILED", `WordPress request failed: ${message}`);
720
+ }
721
+ if (!response.ok) {
722
+ await throwRestRequestFailed(response);
723
+ }
724
+ let payload;
725
+ try {
726
+ payload = await response.json();
727
+ } catch (e) {
728
+ throw new WpClientError("INVALID_RESPONSE", "WordPress response was not valid JSON.");
729
+ }
730
+ if (!Array.isArray(payload)) {
731
+ throw new WpClientError("INVALID_RESPONSE", "WordPress authors response must be an array.");
732
+ }
733
+ return payload.map((author) => toBlogAuthor(author)).filter((author) => author !== null);
734
+ }
735
+ async function fetchAuthorByIdFromRest(options, id) {
736
+ const requestInit = applyAuth2(buildRequestInit2(options), options, false);
737
+ const url = `/wp-json/wp/v2/users/${id}`;
738
+ let response;
739
+ try {
740
+ response = await options.fetchImpl(resolveUrl2(options.wpUrl, url), requestInit);
741
+ } catch (error) {
742
+ if (error instanceof WpClientError) {
743
+ throw error;
744
+ }
745
+ const message = error instanceof Error ? error.message : "Unknown fetch error.";
746
+ throw new WpClientError("REQUEST_FAILED", `WordPress request failed: ${message}`);
747
+ }
748
+ if (response.status === 404) {
749
+ return null;
750
+ }
751
+ if (!response.ok) {
752
+ await throwRestRequestFailed(response);
753
+ }
754
+ let payload;
755
+ try {
756
+ payload = await response.json();
757
+ } catch (e) {
758
+ throw new WpClientError("INVALID_RESPONSE", "WordPress response was not valid JSON.");
759
+ }
760
+ if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
761
+ throw new WpClientError("INVALID_RESPONSE", "WordPress author response must be an object.");
762
+ }
763
+ return toBlogAuthor(payload);
764
+ }
765
+ async function fetchAuthorsFromApi(options, input) {
766
+ return fetchAuthorsFromRest(options, input);
767
+ }
768
+ async function fetchAuthorByIdFromApi(options, id) {
769
+ return fetchAuthorByIdFromRest(options, id);
770
+ }
771
+ async function queryRawFromApi(options, params) {
772
+ var _a, _b, _c, _d;
773
+ if (!((_b = (_a = params.rest) == null ? void 0 : _a.path) == null ? void 0 : _b.trim())) {
774
+ throw new WpClientError("INVALID_INPUT", "queryRaw requires rest.path.");
775
+ }
776
+ const method = ((_c = params.rest.method) != null ? _c : "GET").toUpperCase();
777
+ const withParams = appendRestQueryParams(params.rest.path, params.rest.params);
778
+ const requestInit = applyAuth2(buildRequestInit2(options), options, params.authRequired);
779
+ const headers = new Headers((_d = requestInit.headers) != null ? _d : void 0);
780
+ if (params.rest.headers) {
781
+ for (const [key, value] of Object.entries(params.rest.headers)) {
782
+ headers.set(key, value);
783
+ }
784
+ }
785
+ let body;
786
+ if (params.rest.body !== void 0) {
787
+ if (typeof params.rest.body === "string") {
788
+ body = params.rest.body;
789
+ } else {
790
+ headers.set("Content-Type", "application/json");
791
+ body = JSON.stringify(params.rest.body);
792
+ }
793
+ }
794
+ let response;
795
+ try {
796
+ response = await options.fetchImpl(resolveUrl2(options.wpUrl, withParams), __spreadProps(__spreadValues({}, requestInit), {
797
+ method,
798
+ headers,
799
+ body
800
+ }));
801
+ } catch (error) {
802
+ if (error instanceof WpClientError) {
803
+ throw error;
804
+ }
805
+ const message = error instanceof Error ? error.message : "Unknown fetch error.";
806
+ throw new WpClientError("REQUEST_FAILED", `WordPress request failed: ${message}`);
807
+ }
808
+ if (!response.ok) {
809
+ await throwRestRequestFailed(response);
810
+ }
811
+ try {
812
+ return await response.json();
813
+ } catch (e) {
814
+ throw new WpClientError("INVALID_RESPONSE", "WordPress response was not valid JSON.");
815
+ }
816
+ }
817
+
818
+ // src/domain/normalize.ts
819
+ function htmlToPlainText(value) {
820
+ if (!value) {
821
+ return "";
822
+ }
823
+ return value.replace(/<[^>]*>/g, " ").replace(/\s+/g, " ").trim();
824
+ }
825
+ function getFeaturedImageUrl(post) {
826
+ var _a, _b, _c;
827
+ const media = (_a = post._embedded) == null ? void 0 : _a["wp:featuredmedia"];
828
+ if (!Array.isArray(media) || media.length === 0) {
829
+ return null;
830
+ }
831
+ return (_c = (_b = media[0]) == null ? void 0 : _b.source_url) != null ? _c : null;
832
+ }
833
+ function normalizeTerm(term) {
834
+ var _a, _b;
835
+ if (!Number.isInteger(term.id) || term.id <= 0) {
836
+ return null;
837
+ }
838
+ return {
839
+ id: term.id,
840
+ slug: (_a = term.slug) != null ? _a : "",
841
+ name: (_b = term.name) != null ? _b : "",
842
+ count: typeof term.count === "number" ? term.count : 0
843
+ };
844
+ }
845
+ function getTermsByTaxonomy(post, taxonomy) {
846
+ var _a;
847
+ const groups = (_a = post._embedded) == null ? void 0 : _a["wp:term"];
848
+ if (!Array.isArray(groups)) {
849
+ return [];
850
+ }
851
+ const terms = [];
852
+ for (const group of groups) {
853
+ if (!Array.isArray(group)) {
854
+ continue;
855
+ }
856
+ for (const rawTerm of group) {
857
+ if (!rawTerm || rawTerm.taxonomy !== taxonomy) {
858
+ continue;
859
+ }
860
+ const term = normalizeTerm(rawTerm);
861
+ if (term) {
862
+ terms.push(term);
863
+ }
864
+ }
865
+ }
866
+ return terms;
867
+ }
868
+ function normalizeText(value, textMode) {
869
+ if (textMode === "html") {
870
+ return value != null ? value : "";
871
+ }
872
+ return htmlToPlainText(value);
873
+ }
874
+ function getEmbeddedAuthor(post) {
875
+ var _a;
876
+ const authors = (_a = post._embedded) == null ? void 0 : _a.author;
877
+ if (!Array.isArray(authors) || authors.length === 0) {
878
+ return null;
879
+ }
880
+ const author = authors[0];
881
+ if (!author || !Number.isInteger(author.id) || author.id <= 0) {
882
+ return null;
883
+ }
884
+ return author;
885
+ }
886
+ function isSkippableProtocol(rawHref) {
887
+ const normalized = rawHref.trim().toLowerCase();
888
+ return normalized.startsWith("mailto:") || normalized.startsWith("tel:") || normalized.startsWith("javascript:");
889
+ }
890
+ function normalizePathForMatch(pathname) {
891
+ const collapsed = pathname.replace(/\/{2,}/g, "/");
892
+ const trimmed = collapsed.replace(/\/+$/g, "");
893
+ return trimmed || "/";
894
+ }
895
+ function toUrl(href, wpUrl) {
896
+ try {
897
+ if (/^\/\//.test(href)) {
898
+ const wpProtocol = new URL(wpUrl).protocol;
899
+ return new URL(`${wpProtocol}${href}`);
900
+ }
901
+ return new URL(href, wpUrl);
902
+ } catch (e) {
903
+ return null;
904
+ }
905
+ }
906
+ function isInternalWpUrl(url, wpUrl) {
907
+ try {
908
+ const wpHost = new URL(wpUrl).host.toLowerCase();
909
+ return url.host.toLowerCase() === wpHost;
910
+ } catch (e) {
911
+ return false;
912
+ }
913
+ }
914
+ function parsePattern(pattern) {
915
+ return normalizePathForMatch(pattern).split("/").filter(Boolean);
916
+ }
917
+ function matchPathPattern(pathname, sourcePattern) {
918
+ const pathParts = normalizePathForMatch(pathname).split("/").filter(Boolean);
919
+ const patternParts = parsePattern(sourcePattern);
920
+ if (pathParts.length !== patternParts.length) {
921
+ return null;
922
+ }
923
+ const params = {};
924
+ for (let i = 0; i < patternParts.length; i += 1) {
925
+ const patternPart = patternParts[i];
926
+ const pathPart = pathParts[i];
927
+ if (patternPart.startsWith(":")) {
928
+ const key = patternPart.slice(1);
929
+ if (!key) {
930
+ return null;
931
+ }
932
+ params[key] = pathPart;
933
+ continue;
934
+ }
935
+ if (patternPart !== pathPart) {
936
+ return null;
937
+ }
938
+ }
939
+ return params;
940
+ }
941
+ function applyDestinationPattern(destination, params) {
942
+ const output = normalizePathForMatch(destination);
943
+ return output.replace(/:([A-Za-z0-9_]+)/g, (_match, key) => {
944
+ var _a;
945
+ return (_a = params[key]) != null ? _a : "";
946
+ });
947
+ }
948
+ function applyRewriteRule(href, wpUrl, rules) {
949
+ if (isSkippableProtocol(href)) {
950
+ return href;
951
+ }
952
+ const url = toUrl(href, wpUrl);
953
+ if (!url || !isInternalWpUrl(url, wpUrl)) {
954
+ return href;
955
+ }
956
+ const originalPathname = normalizePathForMatch(url.pathname);
957
+ const context = {
958
+ href: url.toString(),
959
+ pathname: originalPathname,
960
+ search: url.search,
961
+ hash: url.hash
962
+ };
963
+ for (const rule of rules) {
964
+ const source = rule.source.trim();
965
+ if (!source) {
966
+ continue;
967
+ }
968
+ if (rule.action === "ignore") {
969
+ if (context.href.includes(source) || context.pathname.includes(normalizePathForMatch(source))) {
970
+ return href;
971
+ }
972
+ continue;
973
+ }
974
+ const params = matchPathPattern(context.pathname, source);
975
+ if (!params) {
976
+ continue;
977
+ }
978
+ if (typeof rule.transform === "function") {
979
+ const transformed = rule.transform(context);
980
+ return typeof transformed === "string" && transformed ? transformed : href;
981
+ }
982
+ if (rule.destination) {
983
+ const rewrittenPath = applyDestinationPattern(rule.destination, params);
984
+ const finalPath = rewrittenPath.startsWith("/") ? rewrittenPath : `/${rewrittenPath}`;
985
+ return `${finalPath}${context.search}${context.hash}`;
986
+ }
987
+ }
988
+ return href;
989
+ }
990
+ function rewriteContentLinks(contentHtml, options) {
991
+ const rules = options.rewriteLinks;
992
+ if (!rules || rules.length === 0 || !contentHtml.includes("<a ")) {
993
+ return contentHtml;
994
+ }
995
+ return contentHtml.replace(/(<a\b[^>]*\bhref\s*=\s*)(["'])([^"']+)(\2)/gi, (_match, prefix, quote, href, suffix) => {
996
+ const nextHref = applyRewriteRule(href, options.wpUrl, rules);
997
+ return `${prefix}${quote}${nextHref}${suffix}`;
998
+ });
999
+ }
1000
+ function splitClassNames(value) {
1001
+ return value.split(/\s+/).map((token) => token.trim()).filter(Boolean);
1002
+ }
1003
+ function resolveClassMapValue(value) {
1004
+ var _a;
1005
+ if (typeof value === "string") {
1006
+ return { className: value, mode: "append" };
1007
+ }
1008
+ return {
1009
+ className: value.className,
1010
+ mode: (_a = value.mode) != null ? _a : "append"
1011
+ };
1012
+ }
1013
+ function transformContentClasses(contentHtml, classNameMap) {
1014
+ if (!contentHtml || !contentHtml.includes("class=")) {
1015
+ return contentHtml;
1016
+ }
1017
+ return contentHtml.replace(
1018
+ /(<[a-zA-Z][^>]*\bclass\s*=\s*)(["'])([^"']*)(\2)/g,
1019
+ (_match, prefix, quote, classValue, suffix) => {
1020
+ const tokens = splitClassNames(classValue);
1021
+ if (tokens.length === 0) {
1022
+ return `${prefix}${quote}${classValue}${suffix}`;
1023
+ }
1024
+ let replaceAllTokens = null;
1025
+ for (const token of tokens) {
1026
+ const mapped = classNameMap[token];
1027
+ if (!mapped) {
1028
+ continue;
1029
+ }
1030
+ const { className, mode } = resolveClassMapValue(mapped);
1031
+ if (mode === "replace-all") {
1032
+ replaceAllTokens = splitClassNames(className);
1033
+ break;
1034
+ }
1035
+ }
1036
+ if (replaceAllTokens) {
1037
+ const deduped2 = Array.from(new Set(replaceAllTokens));
1038
+ return `${prefix}${quote}${deduped2.join(" ")}${suffix}`;
1039
+ }
1040
+ const nextClasses = [];
1041
+ for (const token of tokens) {
1042
+ const mapped = classNameMap[token];
1043
+ if (!mapped) {
1044
+ nextClasses.push(token);
1045
+ continue;
1046
+ }
1047
+ const { className, mode } = resolveClassMapValue(mapped);
1048
+ const mappedTokens = splitClassNames(className);
1049
+ if (mode === "append") {
1050
+ nextClasses.push(token, ...mappedTokens);
1051
+ } else {
1052
+ nextClasses.push(...mappedTokens);
1053
+ }
1054
+ }
1055
+ const deduped = Array.from(new Set(nextClasses));
1056
+ return `${prefix}${quote}${deduped.join(" ")}${suffix}`;
1057
+ }
1058
+ );
1059
+ }
1060
+ function normalizePost(post, textMode = "plain", options) {
1061
+ var _a, _b;
1062
+ const summary = normalizePostSummary(post, textMode);
1063
+ const rawContentHtml = (_b = (_a = post.content) == null ? void 0 : _a.rendered) != null ? _b : "";
1064
+ const rewrittenHtml = options ? rewriteContentLinks(rawContentHtml, options) : rawContentHtml;
1065
+ const contentHtml = (options == null ? void 0 : options.classNameMap) && Object.keys(options.classNameMap).length > 0 ? transformContentClasses(rewrittenHtml, options.classNameMap) : rewrittenHtml;
1066
+ return __spreadProps(__spreadValues({}, summary), {
1067
+ contentHtml
1068
+ });
1069
+ }
1070
+ function normalizePostSummary(post, textMode = "plain") {
1071
+ var _a, _b;
1072
+ return {
1073
+ id: post.id,
1074
+ slug: post.slug,
1075
+ url: post.link,
1076
+ date: post.date,
1077
+ modified: post.modified,
1078
+ publishedDate: post.date,
1079
+ updatedDate: post.modified,
1080
+ title: normalizeText((_a = post.title) == null ? void 0 : _a.rendered, textMode),
1081
+ excerpt: normalizeText((_b = post.excerpt) == null ? void 0 : _b.rendered, textMode),
1082
+ featuredImageUrl: getFeaturedImageUrl(post),
1083
+ author: getEmbeddedAuthor(post),
1084
+ categories: getTermsByTaxonomy(post, "category"),
1085
+ tags: getTermsByTaxonomy(post, "post_tag")
1086
+ };
1087
+ }
1088
+
1089
+ // src/domain/posts.ts
1090
+ function ensurePositiveInt(value, label) {
1091
+ if (!Number.isInteger(value) || value <= 0) {
1092
+ throw new WpClientError("INVALID_INPUT", `${label} must be a positive integer.`);
1093
+ }
1094
+ return value;
1095
+ }
1096
+ function resolvePage(page) {
1097
+ return ensurePositiveInt(page != null ? page : 1, "page");
1098
+ }
1099
+ function resolvePerPage(perPage, fallback) {
1100
+ return ensurePositiveInt(perPage != null ? perPage : fallback, "perPage");
1101
+ }
1102
+ function resolveOptionalSlug(value, label) {
1103
+ if (value === void 0) {
1104
+ return void 0;
1105
+ }
1106
+ const trimmed = value.trim();
1107
+ if (!trimmed) {
1108
+ throw new WpClientError("INVALID_INPUT", `${label} must be a non-empty string.`);
1109
+ }
1110
+ return trimmed;
1111
+ }
1112
+ function resolveRequiredQuery(value) {
1113
+ const trimmed = value.trim();
1114
+ if (!trimmed) {
1115
+ throw new WpClientError("INVALID_INPUT", "query must be a non-empty string.");
1116
+ }
1117
+ return trimmed;
1118
+ }
1119
+ function resolveStatus(status) {
1120
+ return status != null ? status : "publish";
1121
+ }
1122
+ function isNonPublicStatus(status) {
1123
+ return status !== "publish";
1124
+ }
1125
+ function resolvePostId(id) {
1126
+ return ensurePositiveInt(id, "id");
1127
+ }
1128
+ function resolveTermOrder(order) {
1129
+ return order != null ? order : "default";
1130
+ }
1131
+ function resolveTextMode(textMode) {
1132
+ return textMode != null ? textMode : "plain";
1133
+ }
1134
+ function resolveAuthorsPage(page) {
1135
+ return ensurePositiveInt(page != null ? page : 1, "page");
1136
+ }
1137
+ function applySelect(value, select) {
1138
+ if (!select || select.length === 0) {
1139
+ return value;
1140
+ }
1141
+ const output = {};
1142
+ for (const key of select) {
1143
+ if (key in value) {
1144
+ output[key] = value[key];
1145
+ }
1146
+ }
1147
+ return output;
1148
+ }
1149
+ function createPostsApi(options) {
1150
+ return {
1151
+ async getPosts(params = {}) {
1152
+ const page = resolvePage(params.page);
1153
+ const perPage = resolvePerPage(params.perPage, options.perPage);
1154
+ const status = resolveStatus(params.status);
1155
+ const categorySlug = resolveOptionalSlug(params.categorySlug, "categorySlug");
1156
+ const tagSlug = resolveOptionalSlug(params.tagSlug, "tagSlug");
1157
+ const textMode = resolveTextMode(params.textMode);
1158
+ const select = params.select;
1159
+ const result = await fetchPostsFromApi(options, {
1160
+ page,
1161
+ perPage,
1162
+ status,
1163
+ categorySlug,
1164
+ tagSlug,
1165
+ context: isNonPublicStatus(status) ? "edit" : void 0,
1166
+ authRequired: isNonPublicStatus(status)
1167
+ });
1168
+ const items = result.posts.map(
1169
+ (post) => applySelect(normalizePostSummary(post, textMode), select)
1170
+ );
1171
+ return {
1172
+ items,
1173
+ pagination: {
1174
+ page,
1175
+ perPage,
1176
+ totalItems: result.totalItems,
1177
+ totalPages: result.totalPages
1178
+ }
1179
+ };
1180
+ },
1181
+ async searchPosts(params) {
1182
+ const query = resolveRequiredQuery(params.query);
1183
+ const page = resolvePage(params.page);
1184
+ const perPage = resolvePerPage(params.perPage, options.perPage);
1185
+ const status = resolveStatus(params.status);
1186
+ const categorySlug = resolveOptionalSlug(params.categorySlug, "categorySlug");
1187
+ const tagSlug = resolveOptionalSlug(params.tagSlug, "tagSlug");
1188
+ const textMode = resolveTextMode(params.textMode);
1189
+ const select = params.select;
1190
+ const result = await fetchPostsFromApi(options, {
1191
+ page,
1192
+ perPage,
1193
+ search: query,
1194
+ status,
1195
+ categorySlug,
1196
+ tagSlug,
1197
+ context: isNonPublicStatus(status) ? "edit" : void 0,
1198
+ authRequired: isNonPublicStatus(status)
1199
+ });
1200
+ const items = result.posts.map(
1201
+ (post) => applySelect(normalizePostSummary(post, textMode), select)
1202
+ );
1203
+ return {
1204
+ items,
1205
+ pagination: {
1206
+ page,
1207
+ perPage,
1208
+ totalItems: result.totalItems,
1209
+ totalPages: result.totalPages
1210
+ }
1211
+ };
1212
+ },
1213
+ async getPostBySlug(slug, params = {}) {
1214
+ const trimmedSlug = slug.trim();
1215
+ if (!trimmedSlug) {
1216
+ throw new WpClientError("INVALID_INPUT", "slug must be a non-empty string.");
1217
+ }
1218
+ const status = resolveStatus(params.status);
1219
+ const textMode = resolveTextMode(params.textMode);
1220
+ const select = params.select;
1221
+ const result = await fetchPostsFromApi(options, {
1222
+ page: 1,
1223
+ perPage: 1,
1224
+ slug: trimmedSlug,
1225
+ status,
1226
+ context: isNonPublicStatus(status) ? "edit" : void 0,
1227
+ authRequired: isNonPublicStatus(status)
1228
+ });
1229
+ const post = result.posts[0];
1230
+ return post ? applySelect(normalizePost(post, textMode, options), select) : null;
1231
+ },
1232
+ async getPostById(id, params = {}) {
1233
+ const postId = resolvePostId(id);
1234
+ const status = resolveStatus(params.status);
1235
+ const textMode = resolveTextMode(params.textMode);
1236
+ const select = params.select;
1237
+ const result = await fetchPostsFromApi(options, {
1238
+ page: 1,
1239
+ perPage: 1,
1240
+ id: postId,
1241
+ status,
1242
+ context: isNonPublicStatus(status) ? "edit" : void 0,
1243
+ authRequired: isNonPublicStatus(status)
1244
+ });
1245
+ const post = result.posts[0];
1246
+ return post ? applySelect(normalizePost(post, textMode, options), select) : null;
1247
+ },
1248
+ async queryRaw(params) {
1249
+ return queryRawFromApi(options, params);
1250
+ },
1251
+ async queryGraphql(params) {
1252
+ return queryGraphqlFromApi(options, params);
1253
+ },
1254
+ async getCategories(params = {}) {
1255
+ return fetchTermsFromApi(options, { taxonomy: "categories", order: resolveTermOrder(params.order) });
1256
+ },
1257
+ async getTags(params = {}) {
1258
+ return fetchTermsFromApi(options, { taxonomy: "tags", order: resolveTermOrder(params.order) });
1259
+ },
1260
+ async getAuthors(params = {}) {
1261
+ const page = resolveAuthorsPage(params.page);
1262
+ const perPage = resolvePerPage(params.perPage, options.perPage);
1263
+ return fetchAuthorsFromApi(options, { page, perPage });
1264
+ },
1265
+ async getAuthorById(id) {
1266
+ const authorId = ensurePositiveInt(id, "id");
1267
+ return fetchAuthorByIdFromApi(options, authorId);
1268
+ }
1269
+ };
1270
+ }
1271
+ var defaultClient;
1272
+ function createWpBlogClient(clientOptions = {}) {
1273
+ return createPostsApi(resolveClientOptions(clientOptions));
1274
+ }
1275
+ function getDefaultClient() {
1276
+ if (!defaultClient) {
1277
+ defaultClient = createWpBlogClient();
1278
+ }
1279
+ return defaultClient;
1280
+ }
1281
+ async function getPosts(params = {}) {
1282
+ return getDefaultClient().getPosts(params);
1283
+ }
1284
+ async function searchPosts(params) {
1285
+ return getDefaultClient().searchPosts(params);
1286
+ }
1287
+ async function getPostBySlug(slug, params = {}) {
1288
+ return getDefaultClient().getPostBySlug(slug, params);
1289
+ }
1290
+ async function getPostById(id, params = {}) {
1291
+ return getDefaultClient().getPostById(id, params);
1292
+ }
1293
+ async function queryRaw(params) {
1294
+ return getDefaultClient().queryRaw(params);
1295
+ }
1296
+ async function queryGraphql(params) {
1297
+ return getDefaultClient().queryGraphql(params);
1298
+ }
1299
+ async function getCategories(params = {}) {
1300
+ return getDefaultClient().getCategories(params);
1301
+ }
1302
+ async function getTags(params = {}) {
1303
+ return getDefaultClient().getTags(params);
1304
+ }
1305
+ async function getAuthors(params = {}) {
1306
+ return getDefaultClient().getAuthors(params);
1307
+ }
1308
+ async function getAuthorById(id) {
1309
+ return getDefaultClient().getAuthorById(id);
1310
+ }
1311
+ // Annotate the CommonJS export names for ESM import in node:
1312
+ 0 && (module.exports = {
1313
+ WpClientError,
1314
+ createWpBlogClient,
1315
+ getAuthorById,
1316
+ getAuthors,
1317
+ getCategories,
1318
+ getPostById,
1319
+ getPostBySlug,
1320
+ getPosts,
1321
+ getTags,
1322
+ parseContentPlaceholders,
1323
+ queryGraphql,
1324
+ queryRaw,
1325
+ searchPosts
1326
+ });