@hollware/client 0.1.0 → 0.2.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.d.mts CHANGED
@@ -1,3 +1,53 @@
1
+ import { WebhookCheck, describeSite, getEntry, getTranslations, listEntries, signWebhook, verifyWebhook } from "@hollware/core";
2
+ import * as z from "zod";
1
3
  //#region src/index.d.ts
2
4
  export declare const name = "@hollware/client";
3
- //#endregion
5
+ type Output<Spec extends {
6
+ output: z.ZodType;
7
+ }> = z.output<Spec['output']>;
8
+ export type Format = 'markdown' | 'document' | 'html';
9
+ /**
10
+ * What a site reads from Hollware: the published content, through the four read methods. A
11
+ * service binding to a Hollware Worker already has this shape; `createClient` gives the same over
12
+ * HTTP, so a site can move from one transport to the other without changing a call.
13
+ */
14
+ export interface HollwareReader {
15
+ getEntry(site: string, collection: string, slug: string, locale: string, options?: {
16
+ readonly formats?: readonly Format[];
17
+ }): Promise<Output<typeof getEntry>>;
18
+ listEntries(site: string, collection: string, options?: {
19
+ readonly locale?: string;
20
+ readonly tag?: string;
21
+ readonly limit?: number;
22
+ readonly cursor?: string;
23
+ }): Promise<Output<typeof listEntries>>;
24
+ getTranslations(site: string, collection: string, translationGroup: string): Promise<Output<typeof getTranslations>>;
25
+ describeSite(site: string): Promise<Output<typeof describeSite>>;
26
+ }
27
+ export type ClientOptions =
28
+ /** A service binding to the `Hollware` entrypoint of a Hollware Worker. */
29
+ {
30
+ readonly binding: HollwareReader;
31
+ } |
32
+ /** The public URL of a Hollware, and a personal token with `content:read`. */
33
+ {
34
+ readonly url: string;
35
+ readonly token: string;
36
+ /** `fetch`, when not the global one. */
37
+ readonly fetch?: (request: Request) => Promise<Response>;
38
+ };
39
+ /** An answer of the HTTP read API that is no result: its code, message and fix. */
40
+ export declare class HollwareClientError extends Error {
41
+ readonly status: number;
42
+ readonly code: string;
43
+ readonly fix: string | null;
44
+ constructor(status: number, code: string, message: string, fix: string | null);
45
+ }
46
+ /**
47
+ * A reader of a Hollware: over a service binding, which needs no network and no token, or over
48
+ * HTTP, through the read API at `<url>/v1`. A deployment serves one site, so the `site` argument
49
+ * of the HTTP reader only has to be that site's key.
50
+ */
51
+ export declare function createClient(options: ClientOptions): HollwareReader;
52
+ //#endregion
53
+ export { type WebhookCheck, signWebhook, verifyWebhook };
package/dist/index.mjs CHANGED
@@ -1,4 +1,71 @@
1
+ import { signWebhook, verifyWebhook } from "@hollware/core";
1
2
  //#region src/index.ts
2
3
  const name = "@hollware/client";
4
+ /** An answer of the HTTP read API that is no result: its code, message and fix. */
5
+ var HollwareClientError = class extends Error {
6
+ status;
7
+ code;
8
+ fix;
9
+ constructor(status, code, message, fix) {
10
+ super(message);
11
+ this.name = "HollwareClientError";
12
+ this.status = status;
13
+ this.code = code;
14
+ this.fix = fix;
15
+ }
16
+ };
17
+ function isRecord(value) {
18
+ return typeof value === "object" && value !== null && !Array.isArray(value);
19
+ }
20
+ function httpReader(url, token, send) {
21
+ const base = url.replace(/\/+$/, "");
22
+ async function get(path, query = {}) {
23
+ const params = new URLSearchParams();
24
+ for (const [key, value] of Object.entries(query)) if (value !== void 0) params.set(key, value);
25
+ const search = params.toString();
26
+ const response = await send(new Request(`${base}/v1/${path}${search === "" ? "" : `?${search}`}`, { headers: {
27
+ authorization: `Bearer ${token}`,
28
+ accept: "application/json"
29
+ } }));
30
+ const body = await response.json().catch(() => null);
31
+ if (response.status === 200 || response.status === 404) {
32
+ if (isRecord(body) && typeof body["outcome"] === "string") return body;
33
+ }
34
+ const field = (key) => isRecord(body) && typeof body[key] === "string" ? body[key] : null;
35
+ throw new HollwareClientError(response.status, field("code") ?? "http_error", field("message") ?? `Hollware answered ${response.status}`, field("fix"));
36
+ }
37
+ const segment = encodeURIComponent;
38
+ return {
39
+ getEntry: (_site, collection, slug, locale, options) => get(`${segment(collection)}/${segment(locale)}/${segment(slug)}`, { formats: options?.formats?.join(",") }),
40
+ listEntries: (_site, collection, options = {}) => get(segment(collection), {
41
+ locale: options.locale,
42
+ tag: options.tag,
43
+ limit: options.limit === void 0 ? void 0 : String(options.limit),
44
+ cursor: options.cursor
45
+ }),
46
+ getTranslations: (_site, collection, group) => get(`${segment(collection)}/translations/${segment(group)}`),
47
+ describeSite: (_site) => get("site")
48
+ };
49
+ }
50
+ /**
51
+ * A reader of a Hollware: over a service binding, which needs no network and no token, or over
52
+ * HTTP, through the read API at `<url>/v1`. A deployment serves one site, so the `site` argument
53
+ * of the HTTP reader only has to be that site's key.
54
+ */
55
+ function createClient(options) {
56
+ if ("binding" in options) return options.binding;
57
+ const send = options.fetch ?? ((request) => fetch(request));
58
+ const reader = httpReader(options.url, options.token, send);
59
+ return {
60
+ getEntry: async (...args) => narrow(await reader.getEntry(...args)),
61
+ listEntries: async (...args) => narrow(await reader.listEntries(...args)),
62
+ getTranslations: async (...args) => narrow(await reader.getTranslations(...args)),
63
+ describeSite: async (...args) => narrow(await reader.describeSite(...args))
64
+ };
65
+ }
66
+ /** The body of an answer, which the read API builds from the output schema of its operation. */
67
+ function narrow(body) {
68
+ return body;
69
+ }
3
70
  //#endregion
4
- export { name };
71
+ export { HollwareClientError, createClient, name, signWebhook, verifyWebhook };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hollware/client",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Typed Hollware client over a service binding or HTTP.",
5
5
  "homepage": "https://hollware.com",
6
6
  "bugs": {
@@ -27,11 +27,18 @@
27
27
  "access": "public",
28
28
  "provenance": true
29
29
  },
30
+ "dependencies": {
31
+ "@hollware/core": "0.2.0"
32
+ },
30
33
  "devDependencies": {
31
34
  "@types/node": "24.19.2",
32
35
  "publint": "0.3.25",
33
36
  "typescript": "7.0.2",
34
- "vite-plus": "1.1.0"
37
+ "vite-plus": "1.1.0",
38
+ "zod": "4.6.5"
39
+ },
40
+ "peerDependencies": {
41
+ "zod": "^4.2.0"
35
42
  },
36
43
  "engines": {
37
44
  "node": ">=24.11.0"