canopycms 0.0.62 → 0.0.63
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/ai/index.d.ts +9 -0
- package/dist/ai/index.d.ts.map +1 -1
- package/dist/ai/index.js +9 -0
- package/dist/ai/index.js.map +1 -1
- package/dist/ai/to-plain-text.d.ts +57 -0
- package/dist/ai/to-plain-text.d.ts.map +1 -0
- package/dist/ai/to-plain-text.js +255 -0
- package/dist/ai/to-plain-text.js.map +1 -0
- package/dist/ai/transform-components.d.ts.map +1 -1
- package/dist/ai/transform-components.js +70 -5
- package/dist/ai/transform-components.js.map +1 -1
- package/dist/api/comments.d.ts +2 -2
- package/dist/authorization/branch.d.ts +55 -3
- package/dist/authorization/branch.d.ts.map +1 -1
- package/dist/authorization/branch.js +55 -9
- package/dist/authorization/branch.js.map +1 -1
- package/dist/authorization/types.d.ts +1 -1
- package/dist/authorization/types.d.ts.map +1 -1
- package/dist/build-canopy.d.ts +49 -0
- package/dist/build-canopy.d.ts.map +1 -0
- package/dist/build-canopy.js +51 -0
- package/dist/build-canopy.js.map +1 -0
- package/dist/cli/cli.js +78 -26
- package/dist/cli/generate-ai-content.js +77 -25
- package/dist/cli/template-files/canopycms.config.ts.template +18 -1
- package/dist/content-listing.d.ts +110 -5
- package/dist/content-listing.d.ts.map +1 -1
- package/dist/content-listing.js +164 -23
- package/dist/content-listing.js.map +1 -1
- package/dist/content-reader.d.ts +41 -4
- package/dist/content-reader.d.ts.map +1 -1
- package/dist/content-reader.js +17 -4
- package/dist/content-reader.js.map +1 -1
- package/dist/content-store.d.ts +10 -1
- package/dist/content-store.d.ts.map +1 -1
- package/dist/content-store.js.map +1 -1
- package/dist/content-tree.d.ts +31 -2
- package/dist/content-tree.d.ts.map +1 -1
- package/dist/content-tree.js +22 -5
- package/dist/content-tree.js.map +1 -1
- package/dist/context.d.ts +30 -10
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +55 -4
- package/dist/context.js.map +1 -1
- package/dist/entry-schema.d.ts +228 -8
- package/dist/entry-schema.d.ts.map +1 -1
- package/dist/entry-schema.js +124 -0
- package/dist/entry-schema.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/server.d.ts +51 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +49 -0
- package/dist/server.js.map +1 -1
- package/dist/services.d.ts +1 -2
- package/dist/services.d.ts.map +1 -1
- package/dist/services.js +2 -6
- package/dist/services.js.map +1 -1
- package/dist/static/index.d.ts +65 -5
- package/dist/static/index.d.ts.map +1 -1
- package/dist/static/index.js +65 -12
- package/dist/static/index.js.map +1 -1
- package/dist/static/seo.d.ts +150 -0
- package/dist/static/seo.d.ts.map +1 -0
- package/dist/static/seo.js +189 -0
- package/dist/static/seo.js.map +1 -0
- package/dist/utils/sanitize-href.d.ts +46 -0
- package/dist/utils/sanitize-href.d.ts.map +1 -1
- package/dist/utils/sanitize-href.js +63 -2
- package/dist/utils/sanitize-href.js.map +1 -1
- package/package.json +1 -1
|
@@ -31,10 +31,55 @@ export interface CollectionListItem {
|
|
|
31
31
|
*/
|
|
32
32
|
export declare const readEntryData: (filePath: string, format: ContentFormat, bodyFieldName?: string) => Promise<Record<string, unknown>>;
|
|
33
33
|
/**
|
|
34
|
-
* Parse a filename
|
|
35
|
-
*
|
|
34
|
+
* Parse a Canopy content filename into its `{type}.{slug}.{id}.{ext}` parts.
|
|
35
|
+
*
|
|
36
|
+
* ## Filename grammar
|
|
37
|
+
*
|
|
38
|
+
* Every entry file on disk is named `{type}.{slug}.{id}.{ext}`:
|
|
39
|
+
* - `type` — the entry type name (a key in the collection's `entries` config).
|
|
40
|
+
* - `slug` — the entry's URL slug. May itself contain dots (e.g. a slug of
|
|
41
|
+
* `getting.started.guide`), so the type and ID anchor the split: the ID is
|
|
42
|
+
* always the second-to-last dot-separated segment, and the slug is
|
|
43
|
+
* everything between the type and the ID. The returned `slug` is
|
|
44
|
+
* lowercased.
|
|
45
|
+
* - `id` — a 12-character Base58 content ID (`generateId()`/`isValidId()`).
|
|
46
|
+
* Base58 excludes the ambiguous characters `0`, `O`, `I`, `l` so IDs are
|
|
47
|
+
* unambiguous when read aloud or hand-transcribed. A filename whose
|
|
48
|
+
* would-be ID segment doesn't pass `isValidId` is rejected — the whole
|
|
49
|
+
* parse returns `null`, even if the rest of the shape looks right.
|
|
50
|
+
* - `ext` — the format extension (`.md`, `.mdx`, `.json`, `.yaml`), stripped
|
|
51
|
+
* before parsing and not part of the returned result.
|
|
52
|
+
*
|
|
53
|
+
* @param filename - The bare filename (no directory component). **This precondition is
|
|
54
|
+
* not enforced.** The parser splits purely on `.`, so a `/` or `\` you pass in is not
|
|
55
|
+
* rejected and is not treated as special — it becomes part of whichever segment it
|
|
56
|
+
* falls in, most often the `type` segment (e.g. `'foo/bar.slug.<validId>.md'` parses
|
|
57
|
+
* to `type: 'foo/bar'`). Strip any directory component yourself (e.g.
|
|
58
|
+
* `path.basename(filePath)`) before calling this — every internal caller already does.
|
|
59
|
+
* @param entryTypes - When provided, the parsed `type` segment must match one
|
|
60
|
+
* of these entry types by name, or the parse is rejected (this is how
|
|
61
|
+
* `listCollectionEntries` filters out files that don't belong to the
|
|
62
|
+
* collection's configured entry types). Omit this argument to parse
|
|
63
|
+
* structurally without validating the type against a known list — useful
|
|
64
|
+
* for adopter code that needs to recover `{type, slug, id}` from a
|
|
65
|
+
* filename without having a schema/entry-types list on hand (e.g. a
|
|
66
|
+
* filesystem walk over content for tooling or diagnostics). Even without
|
|
67
|
+
* `entryTypes`, a leading-dot filename (dotfile, editor swap/backup file)
|
|
68
|
+
* is always rejected — an empty string is never a legal type, matching the
|
|
69
|
+
* `filename.startsWith('.')` guard `extractEntryTypeFromFilename` in
|
|
70
|
+
* `content-id-index.ts` already applies.
|
|
71
|
+
* @returns `{ type, slug, id }`, or `null` if `filename` doesn't match the
|
|
72
|
+
* `{type}.{slug}.{id}.{ext}` shape (too few segments, no extension, a
|
|
73
|
+
* leading dot, an invalid ID, or — when `entryTypes` is given — an
|
|
74
|
+
* unrecognized type). `id` is validated (`isValidId`) and safe to trust. **`slug` is
|
|
75
|
+
* not** — it is the raw dot-joined middle segment(s), lowercased, cast to the branded
|
|
76
|
+
* `Slug` type without running `parseSlug`'s validation. A filename with an
|
|
77
|
+
* unconventional slug segment (e.g. containing a space) still parses and still
|
|
78
|
+
* receives the `Slug` brand. Callers that need a validated slug must run the result
|
|
79
|
+
* through `parseSlug` themselves; this function's contract is "split the filename
|
|
80
|
+
* grammar apart," not "validate every part."
|
|
36
81
|
*/
|
|
37
|
-
export declare const parseTypedFilename: (filename: string, entryTypes
|
|
82
|
+
export declare const parseTypedFilename: (filename: string, entryTypes?: readonly EntryTypeConfig[]) => {
|
|
38
83
|
type: string;
|
|
39
84
|
slug: Slug;
|
|
40
85
|
id: ContentId;
|
|
@@ -76,6 +121,15 @@ export interface ListEntriesItem<T = Record<string, unknown>> {
|
|
|
76
121
|
data: T;
|
|
77
122
|
/** Field definitions for this entry's type, when resolvable. */
|
|
78
123
|
schema?: EntrySchema;
|
|
124
|
+
/**
|
|
125
|
+
* Filesystem mtime (ISO 8601) of the entry file, from an unconditional `fs.stat`
|
|
126
|
+
* done while listing. Caveat: this is a checkout-time timestamp, not an editorial
|
|
127
|
+
* one — a fresh CI clone resets every file's mtime to checkout time, so treat this
|
|
128
|
+
* as "changed since last build" at best, not an authoritative last-edited date for
|
|
129
|
+
* a public-facing `<lastmod>`. Sourcing mtime from git commit history is a
|
|
130
|
+
* separate, not-yet-built improvement.
|
|
131
|
+
*/
|
|
132
|
+
updatedAt?: string;
|
|
79
133
|
}
|
|
80
134
|
export interface ListEntriesOptions<T = Record<string, unknown>> {
|
|
81
135
|
/**
|
|
@@ -99,18 +153,53 @@ export interface ListEntriesOptions<T = Record<string, unknown>> {
|
|
|
99
153
|
/** Custom sort. */
|
|
100
154
|
sort?: (a: ListEntriesItem<T>, b: ListEntriesItem<T>) => number;
|
|
101
155
|
}
|
|
156
|
+
/**
|
|
157
|
+
* Server-only path-ACL predicate, applied to raw entries before any of their data
|
|
158
|
+
* reaches a caller.
|
|
159
|
+
*
|
|
160
|
+
* Deliberately NOT part of `ListEntriesOptions`/`BuildContentTreeOptions`: those are
|
|
161
|
+
* adopter-facing, and adopter code must not be able to supply, widen, or override the
|
|
162
|
+
* access check. `context.ts` is the only intended producer — it builds the predicate
|
|
163
|
+
* from `services.createContentAccessChecker` for the request-scoped user, and omits it
|
|
164
|
+
* entirely at build time / on static deployments (synthetic admin, no ACLs).
|
|
165
|
+
*
|
|
166
|
+
* Omitting it preserves the pre-existing unfiltered behavior exactly, which is what
|
|
167
|
+
* build-time callers want.
|
|
168
|
+
*/
|
|
169
|
+
export interface ContentVisibilityOptions {
|
|
170
|
+
/** Return false to drop an entry. Receives the entry's branch-root-relative physical path. */
|
|
171
|
+
shouldInclude?: (physicalPath: PhysicalPath) => boolean;
|
|
172
|
+
}
|
|
102
173
|
/**
|
|
103
174
|
* List all content entries as a flat array.
|
|
104
175
|
*
|
|
105
176
|
* Walks the schema to discover collections, reads entries from each,
|
|
106
177
|
* and returns a flat list suitable for generateStaticParams, search indexing, sitemaps, etc.
|
|
107
178
|
*
|
|
179
|
+
* Build-time-only failure: a file with a recognized content extension (`.md`/`.mdx`/`.json`/
|
|
180
|
+
* `.yaml`) sitting in a collection directory that *looks like an attempted entry* (see
|
|
181
|
+
* `looksLikeMalformedEntry` below) but doesn't match `{type}.{slug}.{id}.{ext}` is, by default,
|
|
182
|
+
* silently dropped (see `listCollectionEntries`'s debug-gated warning). That is exactly the
|
|
183
|
+
* silent-page-loss failure mode static generation must not have — a schema rename without a
|
|
184
|
+
* matching file rename, or an entry type declared in one collection but not another, would
|
|
185
|
+
* otherwise vanish a page with zero build output. So when `isBuildMode()` is true, any such file
|
|
186
|
+
* turns the listing into a thrown error instead (see `findInvalidEntries`/`assertBuildEntriesValid`
|
|
187
|
+
* in `static/index.ts` for the sibling schema-validity guard this mirrors). Outside build mode
|
|
188
|
+
* (admin UI, content tree, `next dev`) the file is still just skipped, since a fresh scaffold or
|
|
189
|
+
* mid-rename file legitimately exists there.
|
|
190
|
+
*
|
|
191
|
+
* A file that was never entry-shaped to begin with — a `README.md`, or a colocated sibling
|
|
192
|
+
* artifact named `{contentId}.suffix.ext` per the `entryTransforms`/`readSibling` convention
|
|
193
|
+
* documented in the README — is not this guard's failure mode and never throws, in or out of
|
|
194
|
+
* build mode. See `looksLikeMalformedEntry` for the exact shape test.
|
|
195
|
+
*
|
|
108
196
|
* @param branchRoot - Absolute path to the branch workspace root
|
|
109
197
|
* @param flatSchema - Flattened schema items (from flattenSchema)
|
|
110
198
|
* @param contentRootName - The content root name (e.g. "content")
|
|
111
199
|
* @param options - Listing options (extract, filter, rootPath, sort)
|
|
200
|
+
* @param visibility - Internal path-ACL predicate; see `ContentVisibilityOptions`
|
|
112
201
|
*/
|
|
113
|
-
export declare function listEntries<T = Record<string, unknown>>(branchRoot: string, flatSchema: FlatSchemaItem[], contentRootName: string, options?: ListEntriesOptions<T
|
|
202
|
+
export declare function listEntries<T = Record<string, unknown>>(branchRoot: string, flatSchema: FlatSchemaItem[], contentRootName: string, options?: ListEntriesOptions<T>, visibility?: ContentVisibilityOptions): Promise<ListEntriesItem<T>[]>;
|
|
114
203
|
/**
|
|
115
204
|
* Sort items by a content ID order array.
|
|
116
205
|
* Items in the order array come first (in order), items not in the array come at the end
|
|
@@ -121,9 +210,25 @@ export declare function listEntries<T = Record<string, unknown>>(branchRoot: str
|
|
|
121
210
|
export declare const sortByOrder: <T extends {
|
|
122
211
|
contentId?: ContentId;
|
|
123
212
|
}>(items: T[], order: readonly string[] | undefined, fallbackKey: (item: T) => string) => T[];
|
|
213
|
+
/** A content-extension file inside a collection directory whose filename didn't parse. */
|
|
214
|
+
export interface SkippedListingFile {
|
|
215
|
+
/** The bare filename, e.g. `article.lost-page.4fBqT78gcaLd.md`. */
|
|
216
|
+
filename: string;
|
|
217
|
+
/** The collection's logical path. */
|
|
218
|
+
collectionPath: LogicalPath;
|
|
219
|
+
}
|
|
124
220
|
/**
|
|
125
221
|
* List all entries in a collection directory.
|
|
126
222
|
* Reads each entry's data (frontmatter or JSON).
|
|
223
|
+
*
|
|
224
|
+
* @param onSkip - Called for every file that has a recognized content extension, doesn't match
|
|
225
|
+
* the `{type}.{slug}.{id}.{ext}` grammar (see `parseTypedFilename`), AND structurally looks
|
|
226
|
+
* like an attempted entry (see `looksLikeMalformedEntry`). A file that was never entry-shaped
|
|
227
|
+
* (too few dot-separated segments to ever be a valid entry — a `README.md`, a colocated
|
|
228
|
+
* sibling artifact) is always silently dropped with a debug-gated `log.warn`, never passed to
|
|
229
|
+
* `onSkip`. Optional and purely a diagnostic hook — existing callers that omit it keep the
|
|
230
|
+
* exact prior behavior. `listEntries` below uses this to turn the skip into a hard build-time
|
|
231
|
+
* failure instead of a silent one.
|
|
127
232
|
*/
|
|
128
|
-
export declare const listCollectionEntries: (root: string, collection: FlatSchemaItem) => Promise<CollectionListItem[]>;
|
|
233
|
+
export declare const listCollectionEntries: (root: string, collection: FlatSchemaItem, onSkip?: (file: SkippedListingFile) => void) => Promise<CollectionListItem[]>;
|
|
129
234
|
//# sourceMappingURL=content-listing.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"content-listing.d.ts","sourceRoot":"","sources":["../src/content-listing.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AASH,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAQ3F,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"content-listing.d.ts","sourceRoot":"","sources":["../src/content-listing.ts"],"names":[],"mappings":"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"}
|
package/dist/content-listing.js
CHANGED
|
@@ -15,6 +15,7 @@ import { isNotFoundError, getErrorMessage } from './utils/error.js';
|
|
|
15
15
|
import { createDebugLogger } from './utils/debug.js';
|
|
16
16
|
import { isValidId } from './id.js';
|
|
17
17
|
import { ContentStoreError } from './content-store.js';
|
|
18
|
+
import { isBuildMode } from './build-mode.js';
|
|
18
19
|
const log = createDebugLogger({ prefix: 'ContentListing' });
|
|
19
20
|
/**
|
|
20
21
|
* Validate and normalize a path relative to root.
|
|
@@ -58,10 +59,61 @@ export const readEntryData = async (filePath, format, bodyFieldName = 'body') =>
|
|
|
58
59
|
}
|
|
59
60
|
};
|
|
60
61
|
/**
|
|
61
|
-
* Parse a filename
|
|
62
|
-
*
|
|
62
|
+
* Parse a Canopy content filename into its `{type}.{slug}.{id}.{ext}` parts.
|
|
63
|
+
*
|
|
64
|
+
* ## Filename grammar
|
|
65
|
+
*
|
|
66
|
+
* Every entry file on disk is named `{type}.{slug}.{id}.{ext}`:
|
|
67
|
+
* - `type` — the entry type name (a key in the collection's `entries` config).
|
|
68
|
+
* - `slug` — the entry's URL slug. May itself contain dots (e.g. a slug of
|
|
69
|
+
* `getting.started.guide`), so the type and ID anchor the split: the ID is
|
|
70
|
+
* always the second-to-last dot-separated segment, and the slug is
|
|
71
|
+
* everything between the type and the ID. The returned `slug` is
|
|
72
|
+
* lowercased.
|
|
73
|
+
* - `id` — a 12-character Base58 content ID (`generateId()`/`isValidId()`).
|
|
74
|
+
* Base58 excludes the ambiguous characters `0`, `O`, `I`, `l` so IDs are
|
|
75
|
+
* unambiguous when read aloud or hand-transcribed. A filename whose
|
|
76
|
+
* would-be ID segment doesn't pass `isValidId` is rejected — the whole
|
|
77
|
+
* parse returns `null`, even if the rest of the shape looks right.
|
|
78
|
+
* - `ext` — the format extension (`.md`, `.mdx`, `.json`, `.yaml`), stripped
|
|
79
|
+
* before parsing and not part of the returned result.
|
|
80
|
+
*
|
|
81
|
+
* @param filename - The bare filename (no directory component). **This precondition is
|
|
82
|
+
* not enforced.** The parser splits purely on `.`, so a `/` or `\` you pass in is not
|
|
83
|
+
* rejected and is not treated as special — it becomes part of whichever segment it
|
|
84
|
+
* falls in, most often the `type` segment (e.g. `'foo/bar.slug.<validId>.md'` parses
|
|
85
|
+
* to `type: 'foo/bar'`). Strip any directory component yourself (e.g.
|
|
86
|
+
* `path.basename(filePath)`) before calling this — every internal caller already does.
|
|
87
|
+
* @param entryTypes - When provided, the parsed `type` segment must match one
|
|
88
|
+
* of these entry types by name, or the parse is rejected (this is how
|
|
89
|
+
* `listCollectionEntries` filters out files that don't belong to the
|
|
90
|
+
* collection's configured entry types). Omit this argument to parse
|
|
91
|
+
* structurally without validating the type against a known list — useful
|
|
92
|
+
* for adopter code that needs to recover `{type, slug, id}` from a
|
|
93
|
+
* filename without having a schema/entry-types list on hand (e.g. a
|
|
94
|
+
* filesystem walk over content for tooling or diagnostics). Even without
|
|
95
|
+
* `entryTypes`, a leading-dot filename (dotfile, editor swap/backup file)
|
|
96
|
+
* is always rejected — an empty string is never a legal type, matching the
|
|
97
|
+
* `filename.startsWith('.')` guard `extractEntryTypeFromFilename` in
|
|
98
|
+
* `content-id-index.ts` already applies.
|
|
99
|
+
* @returns `{ type, slug, id }`, or `null` if `filename` doesn't match the
|
|
100
|
+
* `{type}.{slug}.{id}.{ext}` shape (too few segments, no extension, a
|
|
101
|
+
* leading dot, an invalid ID, or — when `entryTypes` is given — an
|
|
102
|
+
* unrecognized type). `id` is validated (`isValidId`) and safe to trust. **`slug` is
|
|
103
|
+
* not** — it is the raw dot-joined middle segment(s), lowercased, cast to the branded
|
|
104
|
+
* `Slug` type without running `parseSlug`'s validation. A filename with an
|
|
105
|
+
* unconventional slug segment (e.g. containing a space) still parses and still
|
|
106
|
+
* receives the `Slug` brand. Callers that need a validated slug must run the result
|
|
107
|
+
* through `parseSlug` themselves; this function's contract is "split the filename
|
|
108
|
+
* grammar apart," not "validate every part."
|
|
63
109
|
*/
|
|
64
110
|
export const parseTypedFilename = (filename, entryTypes) => {
|
|
111
|
+
// Reject dotfiles outright (matching extractEntryTypeFromFilename's guard in
|
|
112
|
+
// content-id-index.ts): a leading dot can never be a legal entry type, and this
|
|
113
|
+
// is exactly the shape of the files a structural (no-entryTypes) parse would
|
|
114
|
+
// otherwise misparse -- e.g. '.hidden.file.aB3cD4eF5gH6.md' -> potentialType ''.
|
|
115
|
+
if (filename.startsWith('.'))
|
|
116
|
+
return null;
|
|
65
117
|
// Remove extension
|
|
66
118
|
const lastDot = filename.lastIndexOf('.');
|
|
67
119
|
if (lastDot === -1)
|
|
@@ -69,23 +121,23 @@ export const parseTypedFilename = (filename, entryTypes) => {
|
|
|
69
121
|
const nameWithoutExt = filename.slice(0, lastDot);
|
|
70
122
|
// Parse: {type}.{slug}.{id}
|
|
71
123
|
const parts = nameWithoutExt.split('.');
|
|
72
|
-
if (parts.length
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
return null;
|
|
80
|
-
const slug = parts.slice(1, -1).join('.').toLowerCase();
|
|
81
|
-
return {
|
|
82
|
-
type: potentialType,
|
|
83
|
-
slug: slug,
|
|
84
|
-
id: id,
|
|
85
|
-
};
|
|
86
|
-
}
|
|
124
|
+
if (parts.length < 3)
|
|
125
|
+
return null;
|
|
126
|
+
const potentialType = parts[0];
|
|
127
|
+
// When a known-types list is supplied, the first segment must match one of
|
|
128
|
+
// them. Without it, any non-empty first segment is accepted as the type.
|
|
129
|
+
if (entryTypes && !entryTypes.some((e) => e.name === potentialType)) {
|
|
130
|
+
return null;
|
|
87
131
|
}
|
|
88
|
-
|
|
132
|
+
const id = parts[parts.length - 1];
|
|
133
|
+
if (!isValidId(id))
|
|
134
|
+
return null;
|
|
135
|
+
const slug = parts.slice(1, -1).join('.').toLowerCase();
|
|
136
|
+
return {
|
|
137
|
+
type: potentialType,
|
|
138
|
+
slug: slug,
|
|
139
|
+
id: id,
|
|
140
|
+
};
|
|
89
141
|
};
|
|
90
142
|
/**
|
|
91
143
|
* List all content entries as a flat array.
|
|
@@ -93,12 +145,30 @@ export const parseTypedFilename = (filename, entryTypes) => {
|
|
|
93
145
|
* Walks the schema to discover collections, reads entries from each,
|
|
94
146
|
* and returns a flat list suitable for generateStaticParams, search indexing, sitemaps, etc.
|
|
95
147
|
*
|
|
148
|
+
* Build-time-only failure: a file with a recognized content extension (`.md`/`.mdx`/`.json`/
|
|
149
|
+
* `.yaml`) sitting in a collection directory that *looks like an attempted entry* (see
|
|
150
|
+
* `looksLikeMalformedEntry` below) but doesn't match `{type}.{slug}.{id}.{ext}` is, by default,
|
|
151
|
+
* silently dropped (see `listCollectionEntries`'s debug-gated warning). That is exactly the
|
|
152
|
+
* silent-page-loss failure mode static generation must not have — a schema rename without a
|
|
153
|
+
* matching file rename, or an entry type declared in one collection but not another, would
|
|
154
|
+
* otherwise vanish a page with zero build output. So when `isBuildMode()` is true, any such file
|
|
155
|
+
* turns the listing into a thrown error instead (see `findInvalidEntries`/`assertBuildEntriesValid`
|
|
156
|
+
* in `static/index.ts` for the sibling schema-validity guard this mirrors). Outside build mode
|
|
157
|
+
* (admin UI, content tree, `next dev`) the file is still just skipped, since a fresh scaffold or
|
|
158
|
+
* mid-rename file legitimately exists there.
|
|
159
|
+
*
|
|
160
|
+
* A file that was never entry-shaped to begin with — a `README.md`, or a colocated sibling
|
|
161
|
+
* artifact named `{contentId}.suffix.ext` per the `entryTransforms`/`readSibling` convention
|
|
162
|
+
* documented in the README — is not this guard's failure mode and never throws, in or out of
|
|
163
|
+
* build mode. See `looksLikeMalformedEntry` for the exact shape test.
|
|
164
|
+
*
|
|
96
165
|
* @param branchRoot - Absolute path to the branch workspace root
|
|
97
166
|
* @param flatSchema - Flattened schema items (from flattenSchema)
|
|
98
167
|
* @param contentRootName - The content root name (e.g. "content")
|
|
99
168
|
* @param options - Listing options (extract, filter, rootPath, sort)
|
|
169
|
+
* @param visibility - Internal path-ACL predicate; see `ContentVisibilityOptions`
|
|
100
170
|
*/
|
|
101
|
-
export async function listEntries(branchRoot, flatSchema, contentRootName, options) {
|
|
171
|
+
export async function listEntries(branchRoot, flatSchema, contentRootName, options, visibility) {
|
|
102
172
|
const rootPath = options?.rootPath ?? contentRootName;
|
|
103
173
|
const extract = options?.extract;
|
|
104
174
|
const filter = options?.filter;
|
|
@@ -107,11 +177,33 @@ export async function listEntries(branchRoot, flatSchema, contentRootName, optio
|
|
|
107
177
|
const collections = flatSchema.filter((item) => item.type === 'collection' &&
|
|
108
178
|
item.entries !== undefined &&
|
|
109
179
|
(item.logicalPath === rootPath || item.logicalPath.startsWith(`${rootPath}/`)));
|
|
110
|
-
// List entries from all collections in parallel
|
|
180
|
+
// List entries from all collections in parallel.
|
|
181
|
+
// The visibility predicate is applied here, before the map below, so a denied entry's
|
|
182
|
+
// data never reaches `extract` (let alone the returned items).
|
|
183
|
+
const shouldInclude = visibility?.shouldInclude;
|
|
184
|
+
const skippedFiles = [];
|
|
111
185
|
const collectionResults = await Promise.all(collections.map(async (collection) => {
|
|
112
|
-
const entries = await listCollectionEntries(branchRoot, collection);
|
|
113
|
-
|
|
186
|
+
const entries = await listCollectionEntries(branchRoot, collection, (file) => skippedFiles.push(file));
|
|
187
|
+
const visible = shouldInclude ? entries.filter((e) => shouldInclude(e.physicalPath)) : entries;
|
|
188
|
+
return visible.map((entry) => ({ entry, collection }));
|
|
114
189
|
}));
|
|
190
|
+
// Build-time only: fail loudly rather than silently shipping a build with a page missing. See
|
|
191
|
+
// the build-time-only-failure note in this function's own doc comment above. Only files that
|
|
192
|
+
// structurally look like a malformed entry reach `skippedFiles` at all -- see
|
|
193
|
+
// `looksLikeMalformedEntry` and `listCollectionEntries`.
|
|
194
|
+
if (isBuildMode() && skippedFiles.length > 0) {
|
|
195
|
+
const lines = skippedFiles.map(({ filename, collectionPath }) => ` - ${collectionPath}/${filename}`);
|
|
196
|
+
throw new Error(`CanopyCMS static build: found ${skippedFiles.length} file(s) that look like malformed ` +
|
|
197
|
+
`content entries inside a content collection:\n${lines.join('\n')}\n` +
|
|
198
|
+
'Expected {type}.{slug}.{id}.{ext} with a known entry type (a name declared in that ' +
|
|
199
|
+
"collection's entries config) and a valid 12-char Base58 ID. This usually means a schema " +
|
|
200
|
+
'rename without a matching file rename, an entry type declared in one collection but not ' +
|
|
201
|
+
'another, or a stray file placed directly in a collection directory. If this is meant to ' +
|
|
202
|
+
"be a colocated sibling artifact (e.g. an entry's contentId-prefixed data file read via " +
|
|
203
|
+
'an entryTransforms readSibling call), keep its name to three or fewer dot-separated ' +
|
|
204
|
+
'segments (id.suffix.ext) so it is never mistaken for an entry attempt. Otherwise rename ' +
|
|
205
|
+
'or move the file, or fix the schema, then rebuild.');
|
|
206
|
+
}
|
|
115
207
|
// Flatten and map to ListEntriesItem
|
|
116
208
|
const contentPrefix = contentRootName ? `${contentRootName}/` : '';
|
|
117
209
|
const items = [];
|
|
@@ -144,6 +236,7 @@ export async function listEntries(branchRoot, flatSchema, contentRootName, optio
|
|
|
144
236
|
format: entry.format,
|
|
145
237
|
data,
|
|
146
238
|
schema: collection.entries?.find((e) => e.name === entry.entryType)?.schema,
|
|
239
|
+
updatedAt: entry.updatedAt,
|
|
147
240
|
};
|
|
148
241
|
if (filter && !filter(item))
|
|
149
242
|
continue;
|
|
@@ -187,11 +280,56 @@ export const sortByOrder = (items, order, fallbackKey) => {
|
|
|
187
280
|
return fallbackKey(a).localeCompare(fallbackKey(b));
|
|
188
281
|
});
|
|
189
282
|
};
|
|
283
|
+
/**
|
|
284
|
+
* True when a content-extension filename structurally resembles an attempted entry — as opposed
|
|
285
|
+
* to a file that was never entry-shaped to begin with.
|
|
286
|
+
*
|
|
287
|
+
* A successfully-parsed entry always has at least 4 dot-separated segments: `type` (1+),
|
|
288
|
+
* `slug` (1+, since `parseTypedFilename` always takes at least the one segment between type and
|
|
289
|
+
* id), `id` (1), `ext` (1). So a file with 4+ segments that still failed to parse is malformed
|
|
290
|
+
* on its face — a wrong-length or invalid-Base58 ID, most often (`post.hello-world.BADID.md`).
|
|
291
|
+
*
|
|
292
|
+
* That segment-count test alone missed the MORE common accident: losing the ID segment
|
|
293
|
+
* entirely. `post.hello-world.md` (3 segments) fails `parseTypedFilename` exactly like the
|
|
294
|
+
* 4-segment case does, but a bare 3-or-fewer-segment cutoff would treat it as never having been
|
|
295
|
+
* entry-shaped and drop it silently — the page just vanishes with a green build. So a 3-segment
|
|
296
|
+
* file whose FIRST segment matches a real entry type name in this collection is ALSO treated as
|
|
297
|
+
* malformed: `parseTypedFilename` requires type+slug+id (3 segments) after stripping the
|
|
298
|
+
* extension, so a 3-total-segment filename already has only 2 left over — it could only have
|
|
299
|
+
* been attempting `type.slug` with no id, or `type.id` with no slug, either way a lost segment,
|
|
300
|
+
* not a coincidence. This still leaves the two motivating "was never an entry" cases alone: a
|
|
301
|
+
* bare `README.md` (2 segments, and "README" is essentially never a configured entry type name)
|
|
302
|
+
* and an entry's colocated sibling artifact named `{contentId}.suffix.ext` per the
|
|
303
|
+
* `entryTransforms`/`readSibling` convention documented in the README (3 segments, e.g.
|
|
304
|
+
* `5NVkkrB1MJUv.profile.json` — a content ID is never itself an entry type name, so the same
|
|
305
|
+
* "first segment matches a known type" test correctly leaves it unflagged).
|
|
306
|
+
*
|
|
307
|
+
* Dot-prefixed (hidden files, editor swap/backup files) and underscore-prefixed (a common
|
|
308
|
+
* adopter convention for "not an entry") names are excluded outright regardless of segment
|
|
309
|
+
* count, matching `parseTypedFilename`'s own dotfile rejection.
|
|
310
|
+
*/
|
|
311
|
+
const looksLikeMalformedEntry = (filename, entryTypes) => {
|
|
312
|
+
if (filename.startsWith('.') || filename.startsWith('_'))
|
|
313
|
+
return false;
|
|
314
|
+
const segments = filename.split('.');
|
|
315
|
+
if (segments.length >= 4)
|
|
316
|
+
return true;
|
|
317
|
+
return segments.length === 3 && entryTypes.some((e) => e.name === segments[0]);
|
|
318
|
+
};
|
|
190
319
|
/**
|
|
191
320
|
* List all entries in a collection directory.
|
|
192
321
|
* Reads each entry's data (frontmatter or JSON).
|
|
322
|
+
*
|
|
323
|
+
* @param onSkip - Called for every file that has a recognized content extension, doesn't match
|
|
324
|
+
* the `{type}.{slug}.{id}.{ext}` grammar (see `parseTypedFilename`), AND structurally looks
|
|
325
|
+
* like an attempted entry (see `looksLikeMalformedEntry`). A file that was never entry-shaped
|
|
326
|
+
* (too few dot-separated segments to ever be a valid entry — a `README.md`, a colocated
|
|
327
|
+
* sibling artifact) is always silently dropped with a debug-gated `log.warn`, never passed to
|
|
328
|
+
* `onSkip`. Optional and purely a diagnostic hook — existing callers that omit it keep the
|
|
329
|
+
* exact prior behavior. `listEntries` below uses this to turn the skip into a hard build-time
|
|
330
|
+
* failure instead of a silent one.
|
|
193
331
|
*/
|
|
194
|
-
export const listCollectionEntries = async (root, collection) => {
|
|
332
|
+
export const listCollectionEntries = async (root, collection, onSkip) => {
|
|
195
333
|
if (collection.type !== 'collection' || !collection.entries) {
|
|
196
334
|
return [];
|
|
197
335
|
}
|
|
@@ -231,6 +369,9 @@ export const listCollectionEntries = async (root, collection) => {
|
|
|
231
369
|
const parsed = parseTypedFilename(file.name, entryTypes);
|
|
232
370
|
if (!parsed) {
|
|
233
371
|
log.warn('listCollectionEntries', `Skipping file with unrecognized filename format: ${file.name} (expected {type}.{slug}.{id}.{ext} with a known entry type and valid 12-char Base58 ID)`);
|
|
372
|
+
if (looksLikeMalformedEntry(file.name, entryTypes)) {
|
|
373
|
+
onSkip?.({ filename: file.name, collectionPath: collection.logicalPath });
|
|
374
|
+
}
|
|
234
375
|
return null;
|
|
235
376
|
}
|
|
236
377
|
const { type: entryTypeName, slug, id: contentId } = parsed;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"content-listing.js","sourceRoot":"","sources":["../src/content-listing.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"content-listing.js","sourceRoot":"","sources":["../src/content-listing.ts"],"names":[],"mappings":"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"}
|
package/dist/content-reader.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type LogicalPath, type PhysicalPath, type Slug } from './paths';
|
|
1
|
+
import { type ContentId, type LogicalPath, type PhysicalPath, type Slug } from './paths';
|
|
2
2
|
import type { CanopyServices } from './services';
|
|
3
3
|
import type { BranchContext } from './types';
|
|
4
4
|
import type { CanopyUser } from './user';
|
|
@@ -22,13 +22,50 @@ export interface ReadContentInput {
|
|
|
22
22
|
/** Whether to resolve entry:ID links in body/markdown fields. Defaults to true. */
|
|
23
23
|
resolveEntryLinks?: boolean;
|
|
24
24
|
}
|
|
25
|
+
/**
|
|
26
|
+
* Structural metadata surfaced alongside a resolved content read. Shared by
|
|
27
|
+
* `ContentReader['read']` here and by `CanopyBuildContext`'s `read`/`readByUrlPath`
|
|
28
|
+
* (context.ts), which both wrap this same reader.
|
|
29
|
+
*/
|
|
30
|
+
export interface ContentReadMeta {
|
|
31
|
+
/**
|
|
32
|
+
* Absolute filesystem path to the resolved entry file. It is **server-only**
|
|
33
|
+
* -- do not serialize it to the client or embed it in public output, as it
|
|
34
|
+
* reveals the deployment's filesystem layout (home dir / EFS mount / branch
|
|
35
|
+
* name).
|
|
36
|
+
*/
|
|
37
|
+
physicalPath: PhysicalPath;
|
|
38
|
+
/**
|
|
39
|
+
* The resolved entry type name, read from the entry's own filename
|
|
40
|
+
* (`{type}.{slug}.{id}.{ext}`) -- immutable once the file is created, and
|
|
41
|
+
* NOT re-validated against the collection's current `entries` config on
|
|
42
|
+
* every read. It is therefore usually, but not guaranteed to be, a key in
|
|
43
|
+
* the collection's `entries` config: it can diverge if an entry type was
|
|
44
|
+
* renamed or removed from the schema after files using the old name were
|
|
45
|
+
* created, or if the file was hand-authored with an unrecognized type
|
|
46
|
+
* token.
|
|
47
|
+
*
|
|
48
|
+
* For a legacy entry file predating embedded-type filenames (`{slug}.{ext}`),
|
|
49
|
+
* there is no type recorded on disk at all -- `entryType` silently falls
|
|
50
|
+
* back to the collection's DEFAULT entry type, which may or may not be what
|
|
51
|
+
* the file actually is. `entryId` being `undefined` (below) is the signal
|
|
52
|
+
* that this happened: when `entryId` is `undefined`, `entryType` is
|
|
53
|
+
* inferred rather than read.
|
|
54
|
+
*/
|
|
55
|
+
entryType: string;
|
|
56
|
+
/**
|
|
57
|
+
* The entry's 12-char Base58 content ID, when the resolved file carries one.
|
|
58
|
+
* Undefined only for legacy entry files predating embedded-ID filenames
|
|
59
|
+
* (`{slug}.{ext}` rather than `{type}.{slug}.{id}.{ext}`) -- see the
|
|
60
|
+
* `entryType` caveat above for what that implies about it.
|
|
61
|
+
*/
|
|
62
|
+
entryId?: ContentId;
|
|
63
|
+
}
|
|
25
64
|
export interface ContentReader {
|
|
26
65
|
read: <T = unknown>(input: ReadContentInput, message?: string) => Promise<{
|
|
27
66
|
data: T;
|
|
28
67
|
path: string;
|
|
29
|
-
meta:
|
|
30
|
-
physicalPath: PhysicalPath;
|
|
31
|
-
};
|
|
68
|
+
meta: ContentReadMeta;
|
|
32
69
|
}>;
|
|
33
70
|
}
|
|
34
71
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"content-reader.d.ts","sourceRoot":"","sources":["../src/content-reader.ts"],"names":[],"mappings":"AAEA,OAAO,
|
|
1
|
+
{"version":3,"file":"content-reader.d.ts","sourceRoot":"","sources":["../src/content-reader.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,SAAS,EACd,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,IAAI,EACV,MAAM,SAAS,CAAA;AAGhB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAChD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAC5C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AAKxC,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,cAAc,CAAA;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,gBAAgB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAAA;CACrE;AAED,MAAM,WAAW,gBAAgB;IAC/B,kEAAkE;IAClE,SAAS,EAAE,WAAW,CAAA;IACtB,IAAI,CAAC,EAAE,IAAI,CAAA;IACX,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,gFAAgF;IAChF,IAAI,EAAE,UAAU,CAAA;IAChB,2EAA2E;IAC3E,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,mFAAmF;IACnF,iBAAiB,CAAC,EAAE,OAAO,CAAA;CAC5B;AAED;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B;;;;;OAKG;IACH,YAAY,EAAE,YAAY,CAAA;IAC1B;;;;;;;;;;;;;;;;OAgBG;IACH,SAAS,EAAE,MAAM,CAAA;IACjB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,SAAS,CAAA;CACpB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,CAAC,CAAC,GAAG,OAAO,EAChB,KAAK,EAAE,gBAAgB,EACvB,OAAO,CAAC,EAAE,MAAM,KACb,OAAO,CAAC;QACX,IAAI,EAAE,CAAC,CAAA;QACP,IAAI,EAAE,MAAM,CAAA;QACZ,IAAI,EAAE,eAAe,CAAA;KACtB,CAAC,CAAA;CACH;AAED;;;GAGG;AACH,eAAO,MAAM,mBAAmB,GAAI,SAAS,oBAAoB,KAAG,aAgOnE,CAAA"}
|
package/dist/content-reader.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { loadBranchContext, loadOrCreateBranchContext } from './branch-workspace.js';
|
|
2
2
|
import { ContentStore, ContentStoreError } from './content-store.js';
|
|
3
|
-
import { resolveBranchPaths } from './paths/index.js';
|
|
3
|
+
import { resolveBranchPaths, } from './paths/index.js';
|
|
4
4
|
import { trimSlashes } from './paths/normalize.js';
|
|
5
5
|
import { isDeployedStatic, isBuildMode } from './build-mode.js';
|
|
6
6
|
import { isNotFoundError } from './utils/error.js';
|
|
@@ -108,10 +108,23 @@ export const createContentReader = (options) => {
|
|
|
108
108
|
// for server-side colocated-artifact reads (e.g. a sibling profile.json). Already
|
|
109
109
|
// computed here for permission checks; just carried through.
|
|
110
110
|
let physicalPath;
|
|
111
|
+
// Entry type + content ID are already resolved as part of path resolution
|
|
112
|
+
// (buildPaths() derives both from the schema item / filename) — surfaced on
|
|
113
|
+
// read() / readByUrlPath() so callers can route or key by them without a
|
|
114
|
+
// separate listEntries lookup or filename parse.
|
|
115
|
+
let entryType;
|
|
116
|
+
let entryId;
|
|
111
117
|
try {
|
|
112
118
|
const resolved = await store.resolveDocumentPath(entryPath, slug ?? '');
|
|
113
119
|
relativePath = resolved.relativePath;
|
|
114
120
|
physicalPath = resolved.absolutePath;
|
|
121
|
+
// resolveDocumentPath() always sets entryTypeName for a valid schema item
|
|
122
|
+
// (collection entries fall back to 'entry'; entry-type items delegate to
|
|
123
|
+
// their parent collection with their own name), so no further fallback
|
|
124
|
+
// is needed here — id is the one field that can be legitimately absent,
|
|
125
|
+
// for legacy entry files without an embedded ID (see ContentReadMeta).
|
|
126
|
+
entryType = resolved.entryTypeName;
|
|
127
|
+
entryId = resolved.id;
|
|
115
128
|
}
|
|
116
129
|
catch (err) {
|
|
117
130
|
const message = err instanceof ContentStoreError ? err.message : 'Invalid content request';
|
|
@@ -145,7 +158,7 @@ export const createContentReader = (options) => {
|
|
|
145
158
|
const doc = await store.read(entryPath, slug ?? '', {
|
|
146
159
|
resolveReferences: input.resolveReferences ?? true,
|
|
147
160
|
});
|
|
148
|
-
return { doc, store, physicalPath };
|
|
161
|
+
return { doc, store, physicalPath, entryType, entryId };
|
|
149
162
|
}
|
|
150
163
|
catch (err) {
|
|
151
164
|
if (isNotFoundError(err))
|
|
@@ -160,7 +173,7 @@ export const createContentReader = (options) => {
|
|
|
160
173
|
const defaultMessage = `Content not found for ${entryPath}${slug ? `/${slug}` : ''} on branch ${branchName}`;
|
|
161
174
|
throw new ContentStoreError(message ?? defaultMessage, 'NOT_FOUND');
|
|
162
175
|
}
|
|
163
|
-
const { doc, store, physicalPath } = result;
|
|
176
|
+
const { doc, store, physicalPath, entryType, entryId } = result;
|
|
164
177
|
// For md/mdx format, merge the body into the data so callers get a complete object.
|
|
165
178
|
// The field name comes from the schema's isBody flag (defaults to 'body').
|
|
166
179
|
const docRecord = doc;
|
|
@@ -179,7 +192,7 @@ export const createContentReader = (options) => {
|
|
|
179
192
|
slug,
|
|
180
193
|
branch: branchName,
|
|
181
194
|
});
|
|
182
|
-
return { data, path, meta: { physicalPath } };
|
|
195
|
+
return { data, path, meta: { physicalPath, entryType, entryId } };
|
|
183
196
|
};
|
|
184
197
|
return { read };
|
|
185
198
|
};
|