@replohq/sdk 0.13.0 → 0.14.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/content.js ADDED
@@ -0,0 +1,594 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import "server-only";
3
+ import { readdir, readFile } from "node:fs/promises";
4
+ import { join } from "node:path";
5
+ import { Fragment } from "react";
6
+ import { notFound } from "next/navigation";
7
+ import ReactMarkdown from "react-markdown";
8
+ import remarkGfm from "remark-gfm";
9
+ import { parseJsonOrNull } from "./_vendor/replo-utils/lib/json.mjs";
10
+ import { isNotNullish } from "./_vendor/replo-utils/lib/misc.mjs";
11
+ import {
12
+ CONTENT_COLLECTION_SCHEMA_FILENAME,
13
+ CONTENT_DIRNAME,
14
+ CONTENT_ENTRY_FILE_EXTENSION,
15
+ CONTENT_RELATED_VALUE_STORAGE_KEY,
16
+ contentCollectionFileSchema,
17
+ getPublishedContentFields,
18
+ isContentEntryPubliclyVisible,
19
+ isSafeContentUrl,
20
+ isValidContentSlug,
21
+ parseContentEntryRef
22
+ } from "./_vendor/schemas/contentCollection.mjs";
23
+ import {
24
+ getContentEntryFieldValidationIssues,
25
+ getContentRenderableEntryValues,
26
+ parseContentEntryDocument
27
+ } from "./_vendor/schemas/contentEntry.mjs";
28
+ import {
29
+ getContentManifestCollectionSlugs,
30
+ getContentManifestEntrySlugs
31
+ } from "./_vendor/schemas/contentManifest.mjs";
32
+ import { z } from "zod";
33
+ function createContentSource({
34
+ contentDirectory = getDefaultContentDirectory(),
35
+ contentManifest
36
+ } = {}) {
37
+ if (contentManifest) {
38
+ return {
39
+ read: async (relativePath) => {
40
+ return contentManifest.files[relativePath] ?? null;
41
+ },
42
+ listCollections: async () => {
43
+ return getContentManifestCollectionSlugs(contentManifest);
44
+ },
45
+ listEntries: async (collection) => {
46
+ return getContentManifestEntrySlugs({ collection, contentManifest });
47
+ }
48
+ };
49
+ }
50
+ return {
51
+ read: (relativePath) => {
52
+ return readTextFileOrNull(join(contentDirectory, relativePath));
53
+ },
54
+ listCollections: async () => {
55
+ return (await readDirectoryOrEmpty(contentDirectory)).flatMap((entry) => {
56
+ return entry.isDirectory() ? [entry.name] : [];
57
+ });
58
+ },
59
+ listEntries: async (collection) => {
60
+ return (await readDirectoryOrEmpty(join(contentDirectory, collection))).flatMap((entry) => {
61
+ return entry.isFile() && entry.name.endsWith(CONTENT_ENTRY_FILE_EXTENSION) ? [entry.name.slice(0, -CONTENT_ENTRY_FILE_EXTENSION.length)] : [];
62
+ });
63
+ }
64
+ };
65
+ }
66
+ async function getContentEntry({
67
+ collection,
68
+ slug,
69
+ ...contentOptions
70
+ }) {
71
+ const entry = await findContentEntry({
72
+ collection,
73
+ slug,
74
+ contentSource: getContentSource(contentOptions)
75
+ });
76
+ if (!entry) {
77
+ notFound();
78
+ }
79
+ return entry;
80
+ }
81
+ async function getContentCollectionStaticParams({
82
+ collection,
83
+ ...contentOptions
84
+ }) {
85
+ const contentSource = getContentSource(contentOptions);
86
+ const collectionSchema = await readActiveCollectionSchema({
87
+ collection,
88
+ contentSource
89
+ });
90
+ if (!collectionSchema) {
91
+ return [];
92
+ }
93
+ const entries = await listVisibleEntries({
94
+ collectionSchema,
95
+ collection,
96
+ contentSource
97
+ });
98
+ return entries.map((entry) => entry.slug).sort().map((slug) => ({ slug }));
99
+ }
100
+ async function getContentCollection({
101
+ collection,
102
+ ...contentOptions
103
+ }) {
104
+ const loaded = await findContentCollection({
105
+ collection,
106
+ contentSource: getContentSource(contentOptions)
107
+ });
108
+ if (!loaded) {
109
+ notFound();
110
+ }
111
+ return loaded;
112
+ }
113
+ async function getContentEntryMetadata({
114
+ collection,
115
+ slug,
116
+ ...contentOptions
117
+ }) {
118
+ const entry = await findContentEntry({
119
+ collection,
120
+ slug,
121
+ contentSource: getContentSource(contentOptions)
122
+ });
123
+ if (!entry) {
124
+ return {};
125
+ }
126
+ const title = readNonEmptyString(entry.values.seoTitle) ?? readNonEmptyString(entry.values.title) ?? entry.collection.name;
127
+ const description = readNonEmptyString(entry.values.seoDescription) ?? readNonEmptyString(entry.values.excerpt);
128
+ const image = readSafeImageUrl(entry.values.coverImage);
129
+ return {
130
+ title,
131
+ ...description === null ? {} : { description },
132
+ openGraph: {
133
+ title,
134
+ ...description === null ? {} : { description },
135
+ type: "article",
136
+ ...image === null ? {} : { images: [image] }
137
+ },
138
+ twitter: {
139
+ card: image === null ? "summary" : "summary_large_image",
140
+ title,
141
+ ...description === null ? {} : { description },
142
+ ...image === null ? {} : { images: [image] }
143
+ }
144
+ };
145
+ }
146
+ function ContentEntryJsonLd({ entry }) {
147
+ const title = readNonEmptyString(entry.values.seoTitle) ?? readNonEmptyString(entry.values.title) ?? entry.collection.name;
148
+ const description = readNonEmptyString(entry.values.seoDescription) ?? readNonEmptyString(entry.values.excerpt);
149
+ const image = readSafeImageUrl(entry.values.coverImage);
150
+ const datePublished = readIsoDate(entry.values.publishedAt);
151
+ const dateModified = readIsoDate(entry.values.updatedAt);
152
+ const jsonLd = {
153
+ "@context": "https://schema.org",
154
+ "@type": "WebPage",
155
+ name: title,
156
+ ...description === null ? {} : { description },
157
+ ...image === null ? {} : { image },
158
+ ...datePublished === null ? {} : { datePublished },
159
+ ...dateModified === null ? {} : { dateModified }
160
+ };
161
+ return /* @__PURE__ */ jsx(
162
+ "script",
163
+ {
164
+ type: "application/ld+json",
165
+ dangerouslySetInnerHTML: { __html: serializeJsonLd(jsonLd) }
166
+ }
167
+ );
168
+ }
169
+ async function getContentSitemapEntries({
170
+ origin,
171
+ ...contentOptions
172
+ }) {
173
+ const base = origin.replace(/\/+$/u, "");
174
+ const entries = [];
175
+ const contentSource = getContentSource(contentOptions);
176
+ for (const collection of await listCollectionSlugs({ contentSource })) {
177
+ const collectionSchema = await readActiveCollectionSchema({
178
+ collection,
179
+ contentSource
180
+ });
181
+ if (!collectionSchema) {
182
+ continue;
183
+ }
184
+ if (collectionSchema.hasListingPage !== false) {
185
+ entries.push({ url: `${base}/${collection}` });
186
+ }
187
+ const visibleEntries = await listVisibleEntries({
188
+ collectionSchema,
189
+ collection,
190
+ contentSource
191
+ });
192
+ visibleEntries.sort((left, right) => left.slug.localeCompare(right.slug));
193
+ for (const entry of visibleEntries) {
194
+ const lastModified = readValidDate(entry.values.updatedAt);
195
+ entries.push({
196
+ url: `${base}/${collection}/${entry.slug}`,
197
+ ...lastModified === null ? {} : { lastModified }
198
+ });
199
+ }
200
+ }
201
+ return entries;
202
+ }
203
+ async function getContentSitemapXml({
204
+ origin,
205
+ ...contentOptions
206
+ }) {
207
+ const base = origin.replace(/\/+$/u, "");
208
+ const entries = [
209
+ { url: base },
210
+ ...await getContentSitemapEntries({
211
+ origin: base,
212
+ contentSource: getContentSource(contentOptions)
213
+ })
214
+ ];
215
+ const items = entries.map(({ url, lastModified }) => {
216
+ const lastmod = lastModified ? `<lastmod>${lastModified.toISOString()}</lastmod>` : "";
217
+ return `<url><loc>${escapeXml(url)}</loc>${lastmod}</url>`;
218
+ });
219
+ return `<?xml version="1.0" encoding="UTF-8"?>
220
+ <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">${items.join(
221
+ ""
222
+ )}</urlset>
223
+ `;
224
+ }
225
+ function getContentFields(entry) {
226
+ return getPublishedContentFields(entry.fields).map((field) => ({ field, value: entry.values[field.id] })).filter(({ value }) => {
227
+ return value !== void 0 && value !== null && value !== "";
228
+ });
229
+ }
230
+ function ContentFieldValue({
231
+ field,
232
+ value
233
+ }) {
234
+ if (field.type === "rich-text" && typeof value === "string") {
235
+ return /* @__PURE__ */ jsx(SafeMarkdown, { source: value });
236
+ }
237
+ if (field.type === "image" && typeof value === "string") {
238
+ return /* @__PURE__ */ jsx(
239
+ "img",
240
+ {
241
+ alt: field.label,
242
+ src: value,
243
+ style: { display: "block", height: "auto", maxWidth: "100%" }
244
+ }
245
+ );
246
+ }
247
+ if (field.type === "url" && typeof value === "string") {
248
+ return /* @__PURE__ */ jsx("a", { href: value, style: CONTENT_LINK_STYLE, children: value });
249
+ }
250
+ if (field.type === "date" && typeof value === "string") {
251
+ const parsed = new Date(value);
252
+ const label = Number.isNaN(parsed.getTime()) ? value : parsed.toLocaleDateString("en-US", {
253
+ year: "numeric",
254
+ month: "long",
255
+ day: "numeric"
256
+ });
257
+ return /* @__PURE__ */ jsx("time", { dateTime: value, children: label });
258
+ }
259
+ if (field.type === "boolean" && typeof value === "boolean") {
260
+ return value ? "Yes" : "No";
261
+ }
262
+ if (field.type === "related" && Array.isArray(value)) {
263
+ const items = value.filter(
264
+ (item) => isContentRelatedLink(item) || typeof item === "string"
265
+ );
266
+ if (items.length === 0) {
267
+ return null;
268
+ }
269
+ return items.map((item, index) => /* @__PURE__ */ jsxs(Fragment, { children: [
270
+ index > 0 && ", ",
271
+ isContentRelatedLink(item) ? /* @__PURE__ */ jsx("a", { href: item.href, style: CONTENT_LINK_STYLE, children: item.title }) : String(item)
272
+ ] }, isContentRelatedLink(item) ? item.href : String(item)));
273
+ }
274
+ if (field.type === "tags" && Array.isArray(value)) {
275
+ return value.join(", ");
276
+ }
277
+ return typeof value === "string" ? value : null;
278
+ }
279
+ async function findContentCollection({
280
+ collection,
281
+ contentSource
282
+ }) {
283
+ const collectionSchema = await readActiveCollectionSchema({
284
+ collection,
285
+ contentSource
286
+ });
287
+ if (!collectionSchema) {
288
+ return null;
289
+ }
290
+ const visibleEntries = await listVisibleEntries({
291
+ collectionSchema,
292
+ collection,
293
+ contentSource
294
+ });
295
+ const entries = visibleEntries.map((entry) => {
296
+ return {
297
+ slug: entry.slug,
298
+ title: readNonEmptyString(entry.values.title) ?? entry.slug,
299
+ excerpt: readNonEmptyString(entry.values.excerpt),
300
+ coverImage: readSafeImageUrl(entry.values.coverImage),
301
+ coverImageAlt: readNonEmptyString(entry.values.coverImageAlt),
302
+ publishedAt: readIsoDate(entry.values.publishedAt),
303
+ status: entry.values.status === "draft" ? "draft" : "published"
304
+ };
305
+ });
306
+ entries.sort((left, right) => {
307
+ const leftTime = left.publishedAt ? Date.parse(left.publishedAt) : 0;
308
+ const rightTime = right.publishedAt ? Date.parse(right.publishedAt) : 0;
309
+ return rightTime - leftTime || left.title.localeCompare(right.title);
310
+ });
311
+ return {
312
+ slug: collection,
313
+ name: collectionSchema.name,
314
+ description: collectionSchema.description,
315
+ entries
316
+ };
317
+ }
318
+ async function findContentEntry({
319
+ collection,
320
+ slug,
321
+ contentSource
322
+ }) {
323
+ const collectionSchema = await readActiveCollectionSchema({
324
+ collection,
325
+ contentSource
326
+ });
327
+ if (!collectionSchema) {
328
+ return null;
329
+ }
330
+ return readVisibleEntry({
331
+ collectionSchema,
332
+ collection,
333
+ slug,
334
+ contentSource
335
+ });
336
+ }
337
+ async function listCollectionSlugs({
338
+ contentSource
339
+ }) {
340
+ return (await contentSource.listCollections()).filter(isValidContentSlug).sort();
341
+ }
342
+ async function listVisibleEntries({
343
+ collectionSchema,
344
+ collection,
345
+ contentSource
346
+ }) {
347
+ const slugs = await contentSource.listEntries(collection);
348
+ const entries = await Promise.all(
349
+ slugs.map((slug) => {
350
+ return readVisibleEntry({
351
+ collectionSchema,
352
+ collection,
353
+ slug,
354
+ contentSource
355
+ });
356
+ })
357
+ );
358
+ return entries.filter(isNotNullish);
359
+ }
360
+ async function readActiveCollectionSchema({
361
+ collection,
362
+ contentSource
363
+ }) {
364
+ if (!isValidContentSlug(collection)) {
365
+ return null;
366
+ }
367
+ const rawSchema = await contentSource.read(
368
+ `${collection}/${CONTENT_COLLECTION_SCHEMA_FILENAME}`
369
+ );
370
+ if (!rawSchema) {
371
+ return null;
372
+ }
373
+ const parsedJson = parseJsonOrNull(rawSchema);
374
+ if (parsedJson === null) {
375
+ return null;
376
+ }
377
+ const result = contentCollectionFileSchema.safeParse(parsedJson);
378
+ if (!result.success || isNotNullish(result.data.archivedAt)) {
379
+ return null;
380
+ }
381
+ return result.data;
382
+ }
383
+ async function readVisibleEntryDocument({
384
+ collection,
385
+ slug,
386
+ contentSource
387
+ }) {
388
+ if (!isValidContentSlug(slug)) {
389
+ return null;
390
+ }
391
+ const rawEntry = await contentSource.read(
392
+ `${collection}/${slug}${CONTENT_ENTRY_FILE_EXTENSION}`
393
+ );
394
+ if (!rawEntry) {
395
+ return null;
396
+ }
397
+ const parsedDocument = parseContentEntryDocument(rawEntry);
398
+ if (parsedDocument.status === "invalid") {
399
+ return null;
400
+ }
401
+ const document = parsedDocument.document;
402
+ const allowDrafts = process.env.NODE_ENV === "development";
403
+ if (!isContentEntryPubliclyVisible({
404
+ status: document.values.status,
405
+ archivedAt: document.values.archivedAt,
406
+ allowDrafts
407
+ })) {
408
+ return null;
409
+ }
410
+ return document;
411
+ }
412
+ async function readVisibleEntry({
413
+ collectionSchema,
414
+ collection,
415
+ slug,
416
+ contentSource
417
+ }) {
418
+ const document = await readVisibleEntryDocument({
419
+ collection,
420
+ slug,
421
+ contentSource
422
+ });
423
+ if (!document) {
424
+ return null;
425
+ }
426
+ const values = getContentRenderableEntryValues({
427
+ document,
428
+ slug
429
+ });
430
+ if (getContentEntryFieldValidationIssues({
431
+ fields: collectionSchema.fields,
432
+ values,
433
+ requireRequiredFields: document.values.status !== "draft"
434
+ }).length > 0) {
435
+ return null;
436
+ }
437
+ const fields = [...collectionSchema.fields];
438
+ const hasRelatedField = fields.some((field) => field.type === "related");
439
+ const storedRelated = values[CONTENT_RELATED_VALUE_STORAGE_KEY];
440
+ if (!hasRelatedField && Array.isArray(storedRelated) && storedRelated.length > 0) {
441
+ fields.push({
442
+ id: CONTENT_RELATED_VALUE_STORAGE_KEY,
443
+ label: "Related content",
444
+ type: "related",
445
+ required: false,
446
+ enabled: true,
447
+ builtin: true
448
+ });
449
+ }
450
+ return {
451
+ collection: {
452
+ name: collectionSchema.name,
453
+ description: collectionSchema.description,
454
+ slug: collection
455
+ },
456
+ fields,
457
+ slug,
458
+ body: document.body,
459
+ values: await resolveRelatedFieldValues({
460
+ fields,
461
+ values,
462
+ contentSource
463
+ })
464
+ };
465
+ }
466
+ async function resolveRelatedFieldValues({
467
+ fields,
468
+ values,
469
+ contentSource
470
+ }) {
471
+ const relatedFields = fields.filter((field) => field.type === "related");
472
+ if (relatedFields.length === 0) {
473
+ return values;
474
+ }
475
+ const resolved = { ...values };
476
+ for (const field of relatedFields) {
477
+ const raw = resolved[field.id];
478
+ if (!Array.isArray(raw)) {
479
+ continue;
480
+ }
481
+ const links = [];
482
+ for (const item of raw) {
483
+ if (typeof item !== "string") {
484
+ continue;
485
+ }
486
+ const ref = parseContentEntryRef(item);
487
+ if (!ref) {
488
+ continue;
489
+ }
490
+ const { collectionSlug: targetCollection, entrySlug: targetSlug } = ref;
491
+ const collectionSchema = await readActiveCollectionSchema({
492
+ collection: targetCollection,
493
+ contentSource
494
+ });
495
+ if (!collectionSchema) {
496
+ continue;
497
+ }
498
+ const target = await readVisibleEntryDocument({
499
+ collection: targetCollection,
500
+ slug: targetSlug,
501
+ contentSource
502
+ });
503
+ if (!target) {
504
+ continue;
505
+ }
506
+ links.push({
507
+ title: readNonEmptyString(target.values.title) ?? targetSlug,
508
+ href: `/${targetCollection}/${targetSlug}`
509
+ });
510
+ }
511
+ resolved[field.id] = links;
512
+ }
513
+ return resolved;
514
+ }
515
+ const contentRelatedLinkSchema = z.object({
516
+ title: z.string(),
517
+ href: z.string()
518
+ });
519
+ function isContentRelatedLink(value) {
520
+ return contentRelatedLinkSchema.safeParse(value).success;
521
+ }
522
+ const CONTENT_LINK_STYLE = { textDecoration: "underline" };
523
+ function SafeMarkdown({ source }) {
524
+ return /* @__PURE__ */ jsx(
525
+ ReactMarkdown,
526
+ {
527
+ remarkPlugins: [remarkGfm],
528
+ skipHtml: true,
529
+ components: {
530
+ a: ({ children, ...props }) => /* @__PURE__ */ jsx("a", { ...props, style: CONTENT_LINK_STYLE, children })
531
+ },
532
+ children: source
533
+ }
534
+ );
535
+ }
536
+ function readNonEmptyString(value) {
537
+ const parsed = z.string().safeParse(value);
538
+ return parsed.success && parsed.data.trim().length > 0 ? parsed.data : null;
539
+ }
540
+ function readSafeImageUrl(value) {
541
+ const url = readNonEmptyString(value);
542
+ return url !== null && isSafeContentUrl(url, { image: true }) ? url : null;
543
+ }
544
+ function readIsoDate(value) {
545
+ const raw = readNonEmptyString(value);
546
+ return raw !== null && !Number.isNaN(Date.parse(raw)) ? raw : null;
547
+ }
548
+ function readValidDate(value) {
549
+ const iso = readIsoDate(value);
550
+ return iso === null ? null : new Date(iso);
551
+ }
552
+ function serializeJsonLd(value) {
553
+ return JSON.stringify(value).replaceAll("<", "\\u003c").replaceAll("\u2028", "\\u2028").replaceAll("\u2029", "\\u2029");
554
+ }
555
+ function escapeXml(value) {
556
+ return value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&apos;");
557
+ }
558
+ async function readTextFileOrNull(path) {
559
+ try {
560
+ return await readFile(path, "utf8");
561
+ } catch {
562
+ return null;
563
+ }
564
+ }
565
+ async function readDirectoryOrEmpty(path) {
566
+ try {
567
+ return await readdir(path, { withFileTypes: true });
568
+ } catch {
569
+ return [];
570
+ }
571
+ }
572
+ function getContentSource({
573
+ contentSource,
574
+ contentDirectory,
575
+ contentManifest
576
+ }) {
577
+ return contentSource ?? createContentSource({ contentDirectory, contentManifest });
578
+ }
579
+ function getDefaultContentDirectory() {
580
+ return join(process.cwd(), CONTENT_DIRNAME);
581
+ }
582
+ export {
583
+ ContentEntryJsonLd,
584
+ ContentFieldValue,
585
+ createContentSource,
586
+ getContentCollection,
587
+ getContentCollectionStaticParams,
588
+ getContentEntry,
589
+ getContentEntryMetadata,
590
+ getContentFields,
591
+ getContentSitemapEntries,
592
+ getContentSitemapXml
593
+ };
594
+ //# sourceMappingURL=content.js.map
package/content.js.map ADDED
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../content.tsx"],
4
+ "sourcesContent": ["/* oxlint-disable replo/consistent-component-exports -- NOTE (Ryan, 2026-07-30): The published content entrypoint exposes its server loaders and renderers together; HMR splitting doesn't apply to a published server-only package. */\nimport \"server-only\";\n\nimport { readdir, readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type { Metadata } from \"next\";\nimport type { ReactNode } from \"react\";\nimport type { ContentManifest } from \"schemas/contentManifest\";\n\nimport { Fragment } from \"react\";\n\nimport { notFound } from \"next/navigation\";\n\nimport ReactMarkdown from \"react-markdown\";\nimport remarkGfm from \"remark-gfm\";\nimport { parseJsonOrNull } from \"replo-utils/lib/json\";\nimport { isNotNullish } from \"replo-utils/lib/misc\";\nimport {\n CONTENT_COLLECTION_SCHEMA_FILENAME,\n CONTENT_DIRNAME,\n CONTENT_ENTRY_FILE_EXTENSION,\n CONTENT_RELATED_VALUE_STORAGE_KEY,\n contentCollectionFieldSchema,\n contentCollectionFileSchema,\n getPublishedContentFields,\n isContentEntryPubliclyVisible,\n isSafeContentUrl,\n isValidContentSlug,\n parseContentEntryRef,\n} from \"schemas/contentCollection\";\nimport {\n getContentEntryFieldValidationIssues,\n getContentRenderableEntryValues,\n parseContentEntryDocument,\n} from \"schemas/contentEntry\";\nimport {\n getContentManifestCollectionSlugs,\n getContentManifestEntrySlugs,\n} from \"schemas/contentManifest\";\nimport { z } from \"zod\";\n\ntype ContentCollectionFile = z.infer<typeof contentCollectionFileSchema>;\n\n/** Public name for the shared collection-field contract. */\nexport type ContentField = z.infer<typeof contentCollectionFieldSchema>;\n\nexport interface ContentEntry {\n collection: {\n name: string;\n description: string;\n slug: string;\n };\n fields: ContentField[];\n slug: string;\n body: string;\n values: Record<string, unknown>;\n}\n\n/** One entry's slot in a collection listing. */\nexport interface ContentCollectionEntry {\n slug: string;\n title: string;\n excerpt: string | null;\n coverImage: string | null;\n coverImageAlt: string | null;\n publishedAt: string | null;\n status: \"draft\" | \"published\";\n}\n\nexport interface ContentCollection {\n slug: string;\n name: string;\n description: string;\n entries: ContentCollectionEntry[];\n}\n\n/** An ordered content field paired with this entry's value for it. */\nexport interface ContentFieldWithValue {\n field: ContentField;\n value: unknown;\n}\n\nexport interface ContentSitemapEntry {\n url: string;\n lastModified?: Date;\n}\n\nexport interface ContentSource {\n read(relativePath: string): Promise<string | null>;\n listCollections(): Promise<string[]>;\n listEntries(collection: string): Promise<string[]>;\n}\n\ninterface ContentOptions {\n contentSource?: ContentSource;\n contentDirectory?: string;\n contentManifest?: ContentManifest;\n}\n\nexport function createContentSource({\n contentDirectory = getDefaultContentDirectory(),\n contentManifest,\n}: {\n contentDirectory?: string;\n contentManifest?: ContentManifest;\n} = {}): ContentSource {\n if (contentManifest) {\n return {\n read: async (relativePath) => {\n return contentManifest.files[relativePath] ?? null;\n },\n listCollections: async () => {\n return getContentManifestCollectionSlugs(contentManifest);\n },\n listEntries: async (collection) => {\n return getContentManifestEntrySlugs({ collection, contentManifest });\n },\n };\n }\n return {\n read: (relativePath) => {\n return readTextFileOrNull(join(contentDirectory, relativePath));\n },\n listCollections: async () => {\n return (await readDirectoryOrEmpty(contentDirectory)).flatMap((entry) => {\n return entry.isDirectory() ? [entry.name] : [];\n });\n },\n listEntries: async (collection) => {\n return (\n await readDirectoryOrEmpty(join(contentDirectory, collection))\n ).flatMap((entry) => {\n return entry.isFile() &&\n entry.name.endsWith(CONTENT_ENTRY_FILE_EXTENSION)\n ? [entry.name.slice(0, -CONTENT_ENTRY_FILE_EXTENSION.length)]\n : [];\n });\n },\n };\n}\n\nexport async function getContentEntry({\n collection,\n slug,\n ...contentOptions\n}: {\n collection: string;\n slug: string;\n} & ContentOptions): Promise<ContentEntry> {\n const entry = await findContentEntry({\n collection,\n slug,\n contentSource: getContentSource(contentOptions),\n });\n if (!entry) {\n notFound();\n }\n return entry;\n}\n\n/** Static params for one collection's `[slug]` detail route. */\nexport async function getContentCollectionStaticParams({\n collection,\n ...contentOptions\n}: { collection: string } & ContentOptions): Promise<{ slug: string }[]> {\n const contentSource = getContentSource(contentOptions);\n const collectionSchema = await readActiveCollectionSchema({\n collection,\n contentSource,\n });\n if (!collectionSchema) {\n return [];\n }\n const entries = await listVisibleEntries({\n collectionSchema,\n collection,\n contentSource,\n });\n return entries\n .map((entry) => entry.slug)\n .sort()\n .map((slug) => ({ slug }));\n}\n\n/**\n * A collection and its renderable entries for a listing page. Uses the\n * not-found contract when the collection is missing or archived.\n */\nexport async function getContentCollection({\n collection,\n ...contentOptions\n}: { collection: string } & ContentOptions): Promise<ContentCollection> {\n const loaded = await findContentCollection({\n collection,\n contentSource: getContentSource(contentOptions),\n });\n if (!loaded) {\n notFound();\n }\n return loaded;\n}\n\n/**\n * Per-entry head metadata (title/description/OpenGraph/Twitter) from the\n * entry's SEO fields with content fallbacks. Returns an empty object when the\n * entry is not renderable, so `generateMetadata` can call it unconditionally.\n */\nexport async function getContentEntryMetadata({\n collection,\n slug,\n ...contentOptions\n}: {\n collection: string;\n slug: string;\n} & ContentOptions): Promise<Metadata> {\n const entry = await findContentEntry({\n collection,\n slug,\n contentSource: getContentSource(contentOptions),\n });\n if (!entry) {\n return {};\n }\n\n const title =\n readNonEmptyString(entry.values.seoTitle) ??\n readNonEmptyString(entry.values.title) ??\n entry.collection.name;\n const description =\n readNonEmptyString(entry.values.seoDescription) ??\n readNonEmptyString(entry.values.excerpt);\n const image = readSafeImageUrl(entry.values.coverImage);\n\n return {\n title,\n ...(description === null ? {} : { description }),\n openGraph: {\n title,\n ...(description === null ? {} : { description }),\n type: \"article\",\n ...(image === null ? {} : { images: [image] }),\n },\n twitter: {\n card: image === null ? \"summary\" : \"summary_large_image\",\n title,\n ...(description === null ? {} : { description }),\n ...(image === null ? {} : { images: [image] }),\n },\n };\n}\n\n/**\n * Structured data for an entry as a JSON-LD script tag. Serialization is\n * script-safe (`<` escaped) so entry content can never break out of the tag.\n * The type is a deliberately neutral `WebPage`; collections have no schema\n * type of their own.\n */\nexport function ContentEntryJsonLd({ entry }: { entry: ContentEntry }) {\n const title =\n readNonEmptyString(entry.values.seoTitle) ??\n readNonEmptyString(entry.values.title) ??\n entry.collection.name;\n const description =\n readNonEmptyString(entry.values.seoDescription) ??\n readNonEmptyString(entry.values.excerpt);\n const image = readSafeImageUrl(entry.values.coverImage);\n const datePublished = readIsoDate(entry.values.publishedAt);\n const dateModified = readIsoDate(entry.values.updatedAt);\n\n const jsonLd = {\n \"@context\": \"https://schema.org\",\n \"@type\": \"WebPage\",\n name: title,\n ...(description === null ? {} : { description }),\n ...(image === null ? {} : { image }),\n ...(datePublished === null ? {} : { datePublished }),\n ...(dateModified === null ? {} : { dateModified }),\n };\n\n return (\n <script\n type=\"application/ld+json\"\n // eslint-disable-next-line react/no-danger -- NOTE (Ryan, 2026-07-30): JSON-LD must be raw script text; serializeJsonLd escapes `<` so values cannot close the tag.\n dangerouslySetInnerHTML={{ __html: serializeJsonLd(jsonLd) }}\n />\n );\n}\n\n/**\n * Absolute sitemap entries for every collection listing and renderable entry.\n * `origin` comes from the caller (e.g. the request's platform-validated Host)\n * because site origins are not fixed at build time.\n */\nexport async function getContentSitemapEntries({\n origin,\n ...contentOptions\n}: { origin: string } & ContentOptions): Promise<ContentSitemapEntry[]> {\n const base = origin.replace(/\\/+$/u, \"\");\n const entries: ContentSitemapEntry[] = [];\n const contentSource = getContentSource(contentOptions);\n\n for (const collection of await listCollectionSlugs({ contentSource })) {\n const collectionSchema = await readActiveCollectionSchema({\n collection,\n contentSource,\n });\n if (!collectionSchema) {\n continue;\n }\n\n // Collections can opt out of a public listing page; its URL would 404.\n if (collectionSchema.hasListingPage !== false) {\n entries.push({ url: `${base}/${collection}` });\n }\n const visibleEntries = await listVisibleEntries({\n collectionSchema,\n collection,\n contentSource,\n });\n visibleEntries.sort((left, right) => left.slug.localeCompare(right.slug));\n for (const entry of visibleEntries) {\n const lastModified = readValidDate(entry.values.updatedAt);\n entries.push({\n url: `${base}/${collection}/${entry.slug}`,\n ...(lastModified === null ? {} : { lastModified }),\n });\n }\n }\n\n return entries;\n}\n\n/**\n * The full sitemap XML document for a site's content (home, collection\n * listings, entries). Kept here so the generated sitemap route stays a tiny,\n * restylable-free shell around one call.\n */\nexport async function getContentSitemapXml({\n origin,\n ...contentOptions\n}: { origin: string } & ContentOptions): Promise<string> {\n const base = origin.replace(/\\/+$/u, \"\");\n const entries: ContentSitemapEntry[] = [\n { url: base },\n ...(await getContentSitemapEntries({\n origin: base,\n contentSource: getContentSource(contentOptions),\n })),\n ];\n const items = entries.map(({ url, lastModified }) => {\n const lastmod = lastModified\n ? `<lastmod>${lastModified.toISOString()}</lastmod>`\n : \"\";\n return `<url><loc>${escapeXml(url)}</loc>${lastmod}</url>`;\n });\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">${items.join(\n \"\",\n )}</urlset>\\n`;\n}\n\n/**\n * The entry's renderable content fields in collection-settings order, paired\n * with values. This is the published half of the shared ordering contract in\n * `schemas/contentCollection`; empty values are omitted so templates never render\n * bare labels.\n */\nexport function getContentFields(entry: ContentEntry): ContentFieldWithValue[] {\n return getPublishedContentFields(entry.fields)\n .map((field) => ({ field, value: entry.values[field.id] }))\n .filter(({ value }) => {\n return value !== undefined && value !== null && value !== \"\";\n });\n}\n\nexport function ContentFieldValue({\n field,\n value,\n}: {\n field: ContentField;\n value: unknown;\n}): ReactNode {\n if (field.type === \"rich-text\" && typeof value === \"string\") {\n return <SafeMarkdown source={value} />;\n }\n if (field.type === \"image\" && typeof value === \"string\") {\n return (\n <img\n alt={field.label}\n src={value}\n style={{ display: \"block\", height: \"auto\", maxWidth: \"100%\" }}\n />\n );\n }\n if (field.type === \"url\" && typeof value === \"string\") {\n return (\n <a href={value} style={CONTENT_LINK_STYLE}>\n {value}\n </a>\n );\n }\n if (field.type === \"date\" && typeof value === \"string\") {\n const parsed = new Date(value);\n // Explicit locale so the server render matches the client's hydration.\n const label = Number.isNaN(parsed.getTime())\n ? value\n : parsed.toLocaleDateString(\"en-US\", {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n });\n return <time dateTime={value}>{label}</time>;\n }\n if (field.type === \"boolean\" && typeof value === \"boolean\") {\n return value ? \"Yes\" : \"No\";\n }\n if (field.type === \"related\" && Array.isArray(value)) {\n const items = value.filter(\n (item) => isContentRelatedLink(item) || typeof item === \"string\",\n );\n if (items.length === 0) {\n return null;\n }\n return items.map((item, index) => (\n <Fragment key={isContentRelatedLink(item) ? item.href : String(item)}>\n {index > 0 && \", \"}\n {isContentRelatedLink(item) ? (\n <a href={item.href} style={CONTENT_LINK_STYLE}>\n {item.title}\n </a>\n ) : (\n String(item)\n )}\n </Fragment>\n ));\n }\n if (field.type === \"tags\" && Array.isArray(value)) {\n return value.join(\", \");\n }\n return typeof value === \"string\" ? value : null;\n}\n\nasync function findContentCollection({\n collection,\n contentSource,\n}: {\n collection: string;\n contentSource: ContentSource;\n}): Promise<ContentCollection | null> {\n const collectionSchema = await readActiveCollectionSchema({\n collection,\n contentSource,\n });\n if (!collectionSchema) {\n return null;\n }\n\n const visibleEntries = await listVisibleEntries({\n collectionSchema,\n collection,\n contentSource,\n });\n const entries = visibleEntries.map((entry): ContentCollectionEntry => {\n return {\n slug: entry.slug,\n title: readNonEmptyString(entry.values.title) ?? entry.slug,\n excerpt: readNonEmptyString(entry.values.excerpt),\n coverImage: readSafeImageUrl(entry.values.coverImage),\n coverImageAlt: readNonEmptyString(entry.values.coverImageAlt),\n publishedAt: readIsoDate(entry.values.publishedAt),\n status: entry.values.status === \"draft\" ? \"draft\" : \"published\",\n };\n });\n entries.sort((left, right) => {\n const leftTime = left.publishedAt ? Date.parse(left.publishedAt) : 0;\n const rightTime = right.publishedAt ? Date.parse(right.publishedAt) : 0;\n return rightTime - leftTime || left.title.localeCompare(right.title);\n });\n\n return {\n slug: collection,\n name: collectionSchema.name,\n description: collectionSchema.description,\n entries,\n };\n}\n\nasync function findContentEntry({\n collection,\n slug,\n contentSource,\n}: {\n collection: string;\n slug: string;\n contentSource: ContentSource;\n}): Promise<ContentEntry | null> {\n const collectionSchema = await readActiveCollectionSchema({\n collection,\n contentSource,\n });\n if (!collectionSchema) {\n return null;\n }\n return readVisibleEntry({\n collectionSchema,\n collection,\n slug,\n contentSource,\n });\n}\n\nasync function listCollectionSlugs({\n contentSource,\n}: {\n contentSource: ContentSource;\n}): Promise<string[]> {\n return (await contentSource.listCollections())\n .filter(isValidContentSlug)\n .sort();\n}\n\n/**\n * Every renderable entry of a collection, each file read and parsed exactly\n * once. Callers pass the already-read collection schema so no helper in this\n * chain ever re-reads it.\n */\nasync function listVisibleEntries({\n collectionSchema,\n collection,\n contentSource,\n}: {\n collectionSchema: ContentCollectionFile;\n collection: string;\n contentSource: ContentSource;\n}): Promise<ContentEntry[]> {\n const slugs = await contentSource.listEntries(collection);\n const entries = await Promise.all(\n slugs.map((slug) => {\n return readVisibleEntry({\n collectionSchema,\n collection,\n slug,\n contentSource,\n });\n }),\n );\n return entries.filter(isNotNullish);\n}\n\n/** The collection's parsed schema, or null when missing, invalid, or archived. */\nasync function readActiveCollectionSchema({\n collection,\n contentSource,\n}: {\n collection: string;\n contentSource: ContentSource;\n}): Promise<ContentCollectionFile | null> {\n if (!isValidContentSlug(collection)) {\n return null;\n }\n const rawSchema = await contentSource.read(\n `${collection}/${CONTENT_COLLECTION_SCHEMA_FILENAME}`,\n );\n if (!rawSchema) {\n return null;\n }\n const parsedJson = parseJsonOrNull(rawSchema);\n if (parsedJson === null) {\n return null;\n }\n const result = contentCollectionFileSchema.safeParse(parsedJson);\n if (!result.success || isNotNullish(result.data.archivedAt)) {\n return null;\n }\n return result.data;\n}\n\n// The parsed document when the entry exists and is publicly visible, else\n// null. The one visibility gate for full entry loads and shallow reads alike.\nasync function readVisibleEntryDocument({\n collection,\n slug,\n contentSource,\n}: {\n collection: string;\n slug: string;\n contentSource: ContentSource;\n}) {\n if (!isValidContentSlug(slug)) {\n return null;\n }\n const rawEntry = await contentSource.read(\n `${collection}/${slug}${CONTENT_ENTRY_FILE_EXTENSION}`,\n );\n if (!rawEntry) {\n return null;\n }\n const parsedDocument = parseContentEntryDocument(rawEntry);\n if (parsedDocument.status === \"invalid\") {\n return null;\n }\n const document = parsedDocument.document;\n // NOTE (Ryan, 2026-07-28): The sandbox preview runs `next dev`, so drafts\n // render there for Content previewing; production builds stay published-only.\n const allowDrafts = process.env.NODE_ENV === \"development\";\n if (\n !isContentEntryPubliclyVisible({\n status: document.values.status,\n archivedAt: document.values.archivedAt,\n allowDrafts,\n })\n ) {\n return null;\n }\n return document;\n}\n\nasync function readVisibleEntry({\n collectionSchema,\n collection,\n slug,\n contentSource,\n}: {\n collectionSchema: ContentCollectionFile;\n collection: string;\n slug: string;\n contentSource: ContentSource;\n}): Promise<ContentEntry | null> {\n const document = await readVisibleEntryDocument({\n collection,\n slug,\n contentSource,\n });\n if (!document) {\n return null;\n }\n\n const values = getContentRenderableEntryValues({\n document,\n slug,\n });\n // NOTE (Ryan, 2026-07-28): Drafts are work-in-progress, so the dev preview\n // renders them even when required fields are still incomplete.\n if (\n getContentEntryFieldValidationIssues({\n fields: collectionSchema.fields,\n values,\n requireRequiredFields: document.values.status !== \"draft\",\n }).length > 0\n ) {\n return null;\n }\n\n // The editor's built-in Related Content section stores refs under `related`\n // without a schema field; surface them through a synthetic trailing field so\n // related links render for every collection, not only ones whose schema\n // declares a related field.\n const fields: ContentField[] = [...collectionSchema.fields];\n const hasRelatedField = fields.some((field) => field.type === \"related\");\n const storedRelated = values[CONTENT_RELATED_VALUE_STORAGE_KEY];\n if (\n !hasRelatedField &&\n Array.isArray(storedRelated) &&\n storedRelated.length > 0\n ) {\n fields.push({\n id: CONTENT_RELATED_VALUE_STORAGE_KEY,\n label: \"Related content\",\n type: \"related\",\n required: false,\n enabled: true,\n builtin: true,\n });\n }\n return {\n collection: {\n name: collectionSchema.name,\n description: collectionSchema.description,\n slug: collection,\n },\n fields,\n slug,\n body: document.body,\n values: await resolveRelatedFieldValues({\n fields,\n values,\n contentSource,\n }),\n };\n}\n\n/** A related entry resolved to a public link; unresolvable refs stay plain text. */\nexport interface ContentRelatedLink {\n title: string;\n href: string;\n}\n\n// Resolves each `related` field's stored content paths into public links with\n// the target entry's title. Targets that aren't publicly visible (drafts in\n// production, archived, deleted) stay out entirely rather than rendering a\n// dead link.\nasync function resolveRelatedFieldValues({\n fields,\n values,\n contentSource,\n}: {\n fields: ContentField[];\n values: Record<string, unknown>;\n contentSource: ContentSource;\n}): Promise<Record<string, unknown>> {\n const relatedFields = fields.filter((field) => field.type === \"related\");\n if (relatedFields.length === 0) {\n return values;\n }\n const resolved = { ...values };\n for (const field of relatedFields) {\n const raw = resolved[field.id];\n if (!Array.isArray(raw)) {\n continue;\n }\n const links: ContentRelatedLink[] = [];\n for (const item of raw) {\n if (typeof item !== \"string\") {\n continue;\n }\n const ref = parseContentEntryRef(item);\n if (!ref) {\n continue;\n }\n const { collectionSlug: targetCollection, entrySlug: targetSlug } = ref;\n const collectionSchema = await readActiveCollectionSchema({\n collection: targetCollection,\n contentSource,\n });\n if (!collectionSchema) {\n continue;\n }\n // A shallow document read on purpose: resolving the target through the\n // full entry loader would recurse through ITS related fields, looping\n // on mutually-related entries. Only visibility and the title matter.\n const target = await readVisibleEntryDocument({\n collection: targetCollection,\n slug: targetSlug,\n contentSource,\n });\n if (!target) {\n continue;\n }\n links.push({\n title: readNonEmptyString(target.values.title) ?? targetSlug,\n href: `/${targetCollection}/${targetSlug}`,\n });\n }\n resolved[field.id] = links;\n }\n return resolved;\n}\n\nconst contentRelatedLinkSchema = z.object({\n title: z.string(),\n href: z.string(),\n});\n\nfunction isContentRelatedLink(value: unknown): value is ContentRelatedLink {\n return contentRelatedLinkSchema.safeParse(value).success;\n}\n\n// Sites commonly ship a CSS reset (Tailwind's preflight sets\n// `text-decoration: inherit`) that strips link underlines, leaving body links\n// visually indistinguishable from text. State it inline so a link reads as a\n// link on any site, the same way images carry their own layout styles.\nconst CONTENT_LINK_STYLE = { textDecoration: \"underline\" } as const;\n\nfunction SafeMarkdown({ source }: { source: string }) {\n return (\n <ReactMarkdown\n remarkPlugins={[remarkGfm]}\n skipHtml\n components={{\n a: ({ children, ...props }) => (\n <a {...props} style={CONTENT_LINK_STYLE}>\n {children}\n </a>\n ),\n }}\n >\n {source}\n </ReactMarkdown>\n );\n}\n\nfunction readNonEmptyString(value: unknown): string | null {\n const parsed = z.string().safeParse(value);\n return parsed.success && parsed.data.trim().length > 0 ? parsed.data : null;\n}\n\nfunction readSafeImageUrl(value: unknown): string | null {\n const url = readNonEmptyString(value);\n return url !== null && isSafeContentUrl(url, { image: true }) ? url : null;\n}\n\nfunction readIsoDate(value: unknown): string | null {\n const raw = readNonEmptyString(value);\n return raw !== null && !Number.isNaN(Date.parse(raw)) ? raw : null;\n}\n\nfunction readValidDate(value: unknown): Date | null {\n const iso = readIsoDate(value);\n return iso === null ? null : new Date(iso);\n}\n\nfunction serializeJsonLd(value: Record<string, unknown>): string {\n return JSON.stringify(value)\n .replaceAll(\"<\", \"\\\\u003c\")\n .replaceAll(\"\\u2028\", \"\\\\u2028\")\n .replaceAll(\"\\u2029\", \"\\\\u2029\");\n}\n\nfunction escapeXml(value: string): string {\n return value\n .replaceAll(\"&\", \"&amp;\")\n .replaceAll(\"<\", \"&lt;\")\n .replaceAll(\">\", \"&gt;\")\n .replaceAll('\"', \"&quot;\")\n .replaceAll(\"'\", \"&apos;\");\n}\n\nasync function readTextFileOrNull(path: string) {\n try {\n return await readFile(path, \"utf8\");\n } catch {\n return null;\n }\n}\n\nasync function readDirectoryOrEmpty(path: string) {\n try {\n return await readdir(path, { withFileTypes: true });\n } catch {\n return [];\n }\n}\n\nfunction getContentSource({\n contentSource,\n contentDirectory,\n contentManifest,\n}: ContentOptions): ContentSource {\n return (\n contentSource ?? createContentSource({ contentDirectory, contentManifest })\n );\n}\n\nfunction getDefaultContentDirectory() {\n return join(process.cwd(), CONTENT_DIRNAME);\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -1,7 +1,7 @@
1
1
  export const BUILD_METADATA = {
2
2
  "packageName": "@replohq/sdk",
3
- "version": "0.13.0",
3
+ "version": "0.14.0",
4
4
  "branch": "HEAD",
5
- "commit": "56e0eef69efd5e5baff88bcd4428e1b34adcc765",
6
- "builtAt": "2026-08-26T20:40:22.478Z"
5
+ "commit": "417543dc4cd3b28bb31df939f348125643aa08fa",
6
+ "builtAt": "2026-08-26T22:26:21.043Z"
7
7
  };