@the-smithy/hearth 0.21.0 → 0.23.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/{chunk-V47RFBJE.js → chunk-QDCU7YWV.js} +17 -0
- package/dist/{client-IImehdSM.d.ts → client-Deumm7No.d.ts} +15 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +1 -1
- package/dist/next.d.ts +9 -1
- package/dist/next.js +15 -1
- package/dist/testing.d.ts +5 -1
- package/dist/testing.js +2 -0
- package/llms.md +4 -1
- package/package.json +2 -2
|
@@ -239,6 +239,11 @@ function createCore(options) {
|
|
|
239
239
|
}
|
|
240
240
|
},
|
|
241
241
|
sitemap: (o = {}) => request("/sitemap", { ...o, resource: "sitemap" }),
|
|
242
|
+
/**
|
|
243
|
+
* The site's llms.txt (Markdown for AI tools: the organization, how to reach it, its pages with a line on each),
|
|
244
|
+
* or null while the site has no domain or is hidden from search engines, and from Hearth versions without it.
|
|
245
|
+
*/
|
|
246
|
+
llmsTxt: async (o = {}) => await maybe("/llms", { ...o, resource: "llms" }) ?? null,
|
|
242
247
|
redirects: {
|
|
243
248
|
/** Every redirect on the site (old addresses and where they go now). Empty from Hearth versions without them. */
|
|
244
249
|
list: async (o = {}) => await maybe("/redirects", { ...o, resource: "redirects.list" }) ?? []
|
|
@@ -292,6 +297,18 @@ function createCore(options) {
|
|
|
292
297
|
/** Check a preview token from a Hearth preview link. Throws (unauthorized) if it's expired or for another site. */
|
|
293
298
|
verify: (token, o = {}) => request("/preview", { ...o, preview: token, resource: "preview.verify" })
|
|
294
299
|
},
|
|
300
|
+
globalBlocks: {
|
|
301
|
+
/**
|
|
302
|
+
* The site's global blocks (Global blocks in Hearth), resolved: pop-ups (`popup` set), menu dropdowns (a menu
|
|
303
|
+
* item's `dropdown` names one) and any others the site's code places by key. Empty from Hearth versions without them.
|
|
304
|
+
*/
|
|
305
|
+
list: async (o = {}) => await maybe("/global-blocks", { ...o, resource: "globalBlocks.list" }) ?? [],
|
|
306
|
+
/** One global block by key, or null. */
|
|
307
|
+
get: async (key, o = {}) => {
|
|
308
|
+
const list = await maybe("/global-blocks", { ...o, resource: "globalBlocks.list" }) ?? [];
|
|
309
|
+
return list.find((g) => g.key === key) ?? null;
|
|
310
|
+
}
|
|
311
|
+
},
|
|
295
312
|
customBlocks: {
|
|
296
313
|
/** The site's own block types (Custom blocks in Hearth): each one's key, name and fields, for rendering `custom` blocks. */
|
|
297
314
|
list: (o = {}) => request("/custom-blocks", { ...o, resource: "customBlocks.list" })
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Collection, CollectionEntry, HearthEvent, Site, PageSummary, Page, HearthEventDetail, RegistrationInput, RegistrationResult, VolunteerInput, VolunteerResult, CategoryGroup, SitemapEntry, Redirect, AnalyticsReport, Fundraiser, FundraiserDetail, DonationInput, DonationCheckout, HearthForm } from '@the-smithy/hearth-schema';
|
|
1
|
+
import { Collection, CollectionEntry, HearthEvent, Site, PageSummary, Page, HearthEventDetail, RegistrationInput, RegistrationResult, VolunteerInput, VolunteerResult, CategoryGroup, SitemapEntry, Redirect, AnalyticsReport, Fundraiser, FundraiserDetail, DonationInput, DonationCheckout, GlobalBlock, HearthForm } from '@the-smithy/hearth-schema';
|
|
2
2
|
|
|
3
3
|
type HearthErrorCode = "unauthorized" | "not_found" | "bad_request" | "feature_disabled" | "rate_limited" | "server_error" | "network" | "timeout" | "invalid_response";
|
|
4
4
|
/** Any failure talking to Hearth. Messages never contain the API key. */
|
|
@@ -178,6 +178,11 @@ declare function createCore(options: HearthClientOptions): {
|
|
|
178
178
|
}, o?: CallOptions) => Promise<CollectionPage | EventCollectionPage | null>;
|
|
179
179
|
};
|
|
180
180
|
sitemap: (o?: CallOptions) => Promise<SitemapEntry[]>;
|
|
181
|
+
/**
|
|
182
|
+
* The site's llms.txt (Markdown for AI tools: the organization, how to reach it, its pages with a line on each),
|
|
183
|
+
* or null while the site has no domain or is hidden from search engines, and from Hearth versions without it.
|
|
184
|
+
*/
|
|
185
|
+
llmsTxt: (o?: CallOptions) => Promise<string | null>;
|
|
181
186
|
redirects: {
|
|
182
187
|
/** Every redirect on the site (old addresses and where they go now). Empty from Hearth versions without them. */
|
|
183
188
|
list: (o?: CallOptions) => Promise<Redirect[]>;
|
|
@@ -222,6 +227,15 @@ declare function createCore(options: HearthClientOptions): {
|
|
|
222
227
|
/** Check a preview token from a Hearth preview link. Throws (unauthorized) if it's expired or for another site. */
|
|
223
228
|
verify: (token: string, o?: Omit<CallOptions, "preview">) => Promise<PreviewSession>;
|
|
224
229
|
};
|
|
230
|
+
globalBlocks: {
|
|
231
|
+
/**
|
|
232
|
+
* The site's global blocks (Global blocks in Hearth), resolved: pop-ups (`popup` set), menu dropdowns (a menu
|
|
233
|
+
* item's `dropdown` names one) and any others the site's code places by key. Empty from Hearth versions without them.
|
|
234
|
+
*/
|
|
235
|
+
list: (o?: CallOptions) => Promise<GlobalBlock[]>;
|
|
236
|
+
/** One global block by key, or null. */
|
|
237
|
+
get: (key: string, o?: CallOptions) => Promise<GlobalBlock | null>;
|
|
238
|
+
};
|
|
225
239
|
customBlocks: {
|
|
226
240
|
/** The site's own block types (Custom blocks in Hearth): each one's key, name and fields, for rendering `custom` blocks. */
|
|
227
241
|
list: (o?: CallOptions) => Promise<{
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { H as HearthCore, a as HearthClientOptions } from './client-
|
|
2
|
-
export { C as CallOptions, b as CollectionPage, D as DEFAULT_BASE_URL, E as EventCollectionPage, F as FormResult, c as FormValues, d as HearthError, e as HearthErrorCode, f as HearthHooks, N as NextFetchOptions, P as PreviewSession, R as RequestContext, g as RequestOptions, h as findRedirect, i as isHearthError, n as normalizeSlug } from './client-
|
|
3
|
-
export { AnalyticsReport, AnalyticsRow, Block, BlockOf, CategoryGroup, CategoryRef, Collection, CollectionEntry, CollectionRef, DonationCheckout, DonationInput, EntryDetails, EventCustomFields, EventRegistration, EventTicket, EventVolunteerShift, EventVolunteering, Fundraiser, FundraiserDetail, HearthEvent, HearthEventDetail, ImageRef, KnownBlock, Page, PageMeta, PageSummary, Position, Redirect, RegistrationInput, RegistrationResult, ResolvedBlock, Site, SiteAnalytics, SiteSettings, SitemapEntry, UnknownBlock, VolunteerInput, VolunteerResult, WebhookPayload, directionsUrl, focalPosition, pinned, videoEmbedUrl } from '@the-smithy/hearth-schema';
|
|
1
|
+
import { H as HearthCore, a as HearthClientOptions } from './client-Deumm7No.js';
|
|
2
|
+
export { C as CallOptions, b as CollectionPage, D as DEFAULT_BASE_URL, E as EventCollectionPage, F as FormResult, c as FormValues, d as HearthError, e as HearthErrorCode, f as HearthHooks, N as NextFetchOptions, P as PreviewSession, R as RequestContext, g as RequestOptions, h as findRedirect, i as isHearthError, n as normalizeSlug } from './client-Deumm7No.js';
|
|
3
|
+
export { AnalyticsReport, AnalyticsRow, Block, BlockOf, CategoryGroup, CategoryRef, Collection, CollectionEntry, CollectionRef, DonationCheckout, DonationInput, EntryDetails, EventCustomFields, EventRegistration, EventTicket, EventVolunteerShift, EventVolunteering, Fundraiser, FundraiserDetail, GlobalBlock, GlobalPopup, HearthEvent, HearthEventDetail, ImageRef, KnownBlock, Page, PageMeta, PageSummary, Position, Redirect, RegistrationInput, RegistrationResult, ResolvedBlock, SharedFrom, Site, SiteAnalytics, SiteSettings, SitemapEntry, UnknownBlock, VolunteerInput, VolunteerResult, WebhookPayload, directionsUrl, focalPosition, pinned, videoEmbedUrl } from '@the-smithy/hearth-schema';
|
|
4
4
|
|
|
5
5
|
/** A plugin adds resources (and can use the core's `request`) under its own names. */
|
|
6
6
|
type HearthPlugin<T extends object = object> = {
|
package/dist/index.js
CHANGED
package/dist/next.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { H as HearthCore, b as CollectionPage, E as EventCollectionPage, F as FormResult, c as FormValues } from './client-
|
|
1
|
+
import { H as HearthCore, b as CollectionPage, E as EventCollectionPage, F as FormResult, c as FormValues } from './client-Deumm7No.js';
|
|
2
2
|
import * as _the_smithy_hearth_schema from '@the-smithy/hearth-schema';
|
|
3
3
|
import { Site, PageMeta } from '@the-smithy/hearth-schema';
|
|
4
4
|
import { Metadata, MetadataRoute } from 'next';
|
|
@@ -170,6 +170,8 @@ declare function createHearthNext(client: HearthCore, { tag, revalidate }?: Hear
|
|
|
170
170
|
optional?: boolean | undefined;
|
|
171
171
|
})[];
|
|
172
172
|
}[]>;
|
|
173
|
+
/** Global blocks (pop-ups, menu dropdowns, ones the site places by key); drafts while previewing. */
|
|
174
|
+
getGlobalBlocks: () => Promise<_the_smithy_hearth_schema.GlobalBlock[]>;
|
|
173
175
|
getCollections: () => Promise<_the_smithy_hearth_schema.Collection[]>;
|
|
174
176
|
getCollection: (slug: string, opts?: {
|
|
175
177
|
limit?: number;
|
|
@@ -254,6 +256,12 @@ declare function createHearthNext(client: HearthCore, { tag, revalidate }?: Hear
|
|
|
254
256
|
* export default hearthNext.sitemapWith(["/events", "/fundraisers"]);
|
|
255
257
|
*/
|
|
256
258
|
sitemapWith(paths: string[]): () => Promise<MetadataRoute.Sitemap>;
|
|
259
|
+
/**
|
|
260
|
+
* GET handler for app/llms.txt/route.ts, the summary AI tools read (https://llmstxt.org):
|
|
261
|
+
* export const GET = hearthNext.llmsTxtHandler();
|
|
262
|
+
* Not found until the site has a domain in Hearth, while it's hidden from search engines, and on preview deploys.
|
|
263
|
+
*/
|
|
264
|
+
llmsTxtHandler(): () => Promise<Response>;
|
|
257
265
|
/**
|
|
258
266
|
* POST handler for the site's revalidation webhook (app/api/revalidate/route.ts):
|
|
259
267
|
* export const POST = hearthNext.revalidateHandler();
|
package/dist/next.js
CHANGED
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
findRedirect,
|
|
3
3
|
isHearthError,
|
|
4
4
|
normalizeSlug
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-QDCU7YWV.js";
|
|
6
6
|
import {
|
|
7
7
|
parseWebhook,
|
|
8
8
|
tagsForWebhook
|
|
@@ -60,6 +60,8 @@ function createHearthNext(client, { tag = "hearth", revalidate = 3600 } = {}) {
|
|
|
60
60
|
getEvents: (opts) => client.events.list(opts, tags(`${tag}:events`)),
|
|
61
61
|
getCategories: () => client.categories.list(tags(`${tag}:site`)),
|
|
62
62
|
getCustomBlocks: () => client.customBlocks.list(tags(`${tag}:site`)),
|
|
63
|
+
/** Global blocks (pop-ups, menu dropdowns, ones the site places by key); drafts while previewing. */
|
|
64
|
+
getGlobalBlocks: async () => client.globalBlocks.list(await read(`${tag}:global`)),
|
|
63
65
|
getCollections: () => client.collections.list(tags(`${tag}:site`, `${tag}:pages`)),
|
|
64
66
|
getCollection: (slug, opts) => client.collections.get(slug, opts, tags(`${tag}:pages`, `${tag}:events`)),
|
|
65
67
|
getEvent: async (slug) => client.events.get(slug, await read(`${tag}:events`)),
|
|
@@ -284,6 +286,18 @@ function createHearthNext(client, { tag = "hearth", revalidate = 3600 } = {}) {
|
|
|
284
286
|
return [...entries.map((e) => ({ url: e.url, ...e.lastModified ? { lastModified: e.lastModified } : {}, priority: e.priority })), ...extra];
|
|
285
287
|
};
|
|
286
288
|
},
|
|
289
|
+
/**
|
|
290
|
+
* GET handler for app/llms.txt/route.ts, the summary AI tools read (https://llmstxt.org):
|
|
291
|
+
* export const GET = hearthNext.llmsTxtHandler();
|
|
292
|
+
* Not found until the site has a domain in Hearth, while it's hidden from search engines, and on preview deploys.
|
|
293
|
+
*/
|
|
294
|
+
llmsTxtHandler() {
|
|
295
|
+
return async () => {
|
|
296
|
+
const text = isNonProductionDeploy() ? null : await client.llmsTxt(tags(`${tag}:pages`, `${tag}:events`, `${tag}:site`));
|
|
297
|
+
if (!text) return new Response("Not found", { status: 404, headers: { "Content-Type": "text/plain; charset=utf-8" } });
|
|
298
|
+
return new Response(text, { headers: { "Content-Type": "text/markdown; charset=utf-8" } });
|
|
299
|
+
};
|
|
300
|
+
},
|
|
287
301
|
/**
|
|
288
302
|
* POST handler for the site's revalidation webhook (app/api/revalidate/route.ts):
|
|
289
303
|
* export const POST = hearthNext.revalidateHandler();
|
package/dist/testing.d.ts
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
|
-
import { Site, Page, HearthEvent, HearthEventDetail, SitemapEntry, Redirect, Collection, CollectionEntry, CategoryGroup, Fundraiser, FundraiserDetail, HearthForm } from '@the-smithy/hearth-schema';
|
|
1
|
+
import { Site, Page, HearthEvent, HearthEventDetail, SitemapEntry, Redirect, GlobalBlock, Collection, CollectionEntry, CategoryGroup, Fundraiser, FundraiserDetail, HearthForm } from '@the-smithy/hearth-schema';
|
|
2
2
|
|
|
3
3
|
type MockHearthData = {
|
|
4
4
|
site?: Partial<Site>;
|
|
5
5
|
pages?: Page[];
|
|
6
6
|
events?: (HearthEvent | HearthEventDetail)[];
|
|
7
7
|
sitemap?: SitemapEntry[];
|
|
8
|
+
/** The site's llms.txt; null (the default) is a site without one. */
|
|
9
|
+
llmsTxt?: string | null;
|
|
8
10
|
redirects?: Redirect[];
|
|
11
|
+
/** The site's global blocks (pop-ups, menu dropdowns). */
|
|
12
|
+
globalBlocks?: GlobalBlock[];
|
|
9
13
|
/** Collections, with their entries (page collections) keyed by collection slug. */
|
|
10
14
|
collections?: Collection[];
|
|
11
15
|
entries?: Record<string, CollectionEntry[]>;
|
package/dist/testing.js
CHANGED
|
@@ -46,7 +46,9 @@ function createMockHearth(data = {}) {
|
|
|
46
46
|
return event ? json({ data: event }) : notFound();
|
|
47
47
|
}
|
|
48
48
|
if (rest === "/sitemap") return json({ data: data.sitemap ?? [] });
|
|
49
|
+
if (rest === "/llms") return json({ data: data.llmsTxt ?? null });
|
|
49
50
|
if (rest === "/redirects") return json({ data: data.redirects ?? [] });
|
|
51
|
+
if (rest === "/global-blocks") return json({ data: data.globalBlocks ?? [] });
|
|
50
52
|
if (rest === "/fundraisers" || rest.startsWith("/fundraisers?")) {
|
|
51
53
|
const status = url.searchParams.get("status") ?? "active";
|
|
52
54
|
return json({ data: (data.fundraisers ?? []).filter((f) => status === "all" || f.status === status) });
|
package/llms.md
CHANGED
|
@@ -37,6 +37,7 @@ client components: the API key is secret.
|
|
|
37
37
|
- `events.list({ when?: "upcoming" | "past", limit? }): HearthEvent[]`
|
|
38
38
|
- `events.get(slug): HearthEventDetail | null`
|
|
39
39
|
- `sitemap(): SitemapEntry[]`
|
|
40
|
+
- `llmsTxt(): string | null`: the site's llms.txt (Markdown for AI tools), null while it has no domain or is hidden
|
|
40
41
|
- `forms.get(formKey): HearthForm | null`: the site's form (`{ key, name, fields, submitLabel, successMessage }`), to render outside a Form block, e.g. in a footer. Each site has one form, `contact`, and every Form block shows it. Fields are `{ name, label, type, required, options?, placeholder? }`; render `placeholder` in the input (for a select, as the prompt option). A Form block can instead name an Ember form (`data.emberFormId`, `frm_…`): render it with `EmberForm` from `@the-smithy/ember/react`, with the site's form as the fallback.
|
|
41
42
|
- `forms.submit(formKey, FormData | object, { ip? }): { ok: true, message } | { ok: false, message, fieldErrors }`
|
|
42
43
|
- `request<T>(path, opts)`: the raw call for anything else under `/api/v1/sites/{site}`
|
|
@@ -78,6 +79,8 @@ client components: the API key is secret.
|
|
|
78
79
|
- `generateMetadata`: `return hearthNext.generatePageMetadata((await params).slug)`
|
|
79
80
|
- Events: `metadataFromMeta(event.meta)`
|
|
80
81
|
- `app/sitemap.ts`: `export default hearthNext.sitemap`
|
|
82
|
+
- `app/llms.txt/route.ts`: `export const GET = hearthNext.llmsTxtHandler()` (the organization, contact details,
|
|
83
|
+
hours and every listed page with a line on it, for AI tools; 404 on previews and while the site is hidden)
|
|
81
84
|
- `app/api/revalidate/route.ts`: `export const POST = hearthNext.revalidateHandler()`
|
|
82
85
|
- Giving: `getFundraisers(opts)`, `getFundraiser(slug)`, and a donation form's server action:
|
|
83
86
|
`export const donate = async (prev: FormResult | null, fd: FormData) => hearthNext.donateAction()(prev, fd)`
|
|
@@ -113,5 +116,5 @@ client components: the API key is secret.
|
|
|
113
116
|
## Other entry points
|
|
114
117
|
- `@the-smithy/hearth/webhooks`: `verifyWebhook(raw, header, secret)`, `parseWebhook(request, secret)`,
|
|
115
118
|
`tagsForWebhook(payload)`
|
|
116
|
-
- `@the-smithy/hearth/testing`: `createMockHearth({ site, pages, events, sitemap, onForm })` returns
|
|
119
|
+
- `@the-smithy/hearth/testing`: `createMockHearth({ site, pages, events, sitemap, llmsTxt, onForm })` returns
|
|
117
120
|
`{ fetch, requests }`. Pass `fetch` to `createHearthClient`.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@the-smithy/hearth",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.23.0",
|
|
4
4
|
"description": "Typed client for the Hearth Delivery API: content, SEO, forms and publish webhooks.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"llms.md"
|
|
50
50
|
],
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@the-smithy/hearth-schema": "^0.
|
|
52
|
+
"@the-smithy/hearth-schema": "^0.23.0"
|
|
53
53
|
},
|
|
54
54
|
"peerDependencies": {
|
|
55
55
|
"next": ">=15",
|