canopycms-next 0.0.62 → 0.0.64
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/adapter.d.ts +1 -2
- package/dist/adapter.js +1 -2
- package/dist/client.d.ts +1 -2
- package/dist/client.js +1 -2
- package/dist/config.d.ts +1 -2
- package/dist/config.js +1 -2
- package/dist/context-wrapper.d.ts +75 -4
- package/dist/context-wrapper.js +57 -3
- package/dist/index.d.ts +4 -5
- package/dist/index.js +4 -5
- package/dist/static.d.ts +210 -6
- package/dist/static.js +231 -4
- package/dist/test-utils.d.ts +0 -1
- package/dist/test-utils.js +0 -1
- package/dist/with-canopy.d.ts +0 -1
- package/dist/with-canopy.js +0 -1
- package/package.json +4 -4
- package/dist/adapter.d.ts.map +0 -1
- package/dist/adapter.js.map +0 -1
- package/dist/client.d.ts.map +0 -1
- package/dist/client.js.map +0 -1
- package/dist/client.test.d.ts +0 -2
- package/dist/client.test.d.ts.map +0 -1
- package/dist/client.test.js +0 -29
- package/dist/client.test.js.map +0 -1
- package/dist/config.d.ts.map +0 -1
- package/dist/config.js.map +0 -1
- package/dist/context-wrapper.d.ts.map +0 -1
- package/dist/context-wrapper.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/static.d.ts.map +0 -1
- package/dist/static.js.map +0 -1
- package/dist/test-utils.d.ts.map +0 -1
- package/dist/test-utils.js.map +0 -1
- package/dist/with-canopy.d.ts.map +0 -1
- package/dist/with-canopy.js.map +0 -1
package/dist/adapter.d.ts
CHANGED
|
@@ -23,7 +23,7 @@ export declare function wrapNextRequest(req: Request): CanopyRequest;
|
|
|
23
23
|
* // app/api/canopycms/[...canopycms]/route.ts
|
|
24
24
|
* import { createCanopyCatchAllHandler } from 'canopycms-next'
|
|
25
25
|
* import { createClerkAuthPlugin } from 'canopycms-auth-clerk'
|
|
26
|
-
* import config from '../../../../canopycms.config'
|
|
26
|
+
* import config from '../../../../canopycms.config.js'
|
|
27
27
|
*
|
|
28
28
|
* const handler = createCanopyCatchAllHandler({
|
|
29
29
|
* config: config.server,
|
|
@@ -46,4 +46,3 @@ export declare const createCanopyCatchAllHandler: (options: CanopyNextOptions) =
|
|
|
46
46
|
[key: string]: unknown;
|
|
47
47
|
};
|
|
48
48
|
}) => Promise<Response>;
|
|
49
|
-
//# sourceMappingURL=adapter.d.ts.map
|
package/dist/adapter.js
CHANGED
|
@@ -92,7 +92,7 @@ async function extractPathSegments(ctx) {
|
|
|
92
92
|
* // app/api/canopycms/[...canopycms]/route.ts
|
|
93
93
|
* import { createCanopyCatchAllHandler } from 'canopycms-next'
|
|
94
94
|
* import { createClerkAuthPlugin } from 'canopycms-auth-clerk'
|
|
95
|
-
* import config from '../../../../canopycms.config'
|
|
95
|
+
* import config from '../../../../canopycms.config.js'
|
|
96
96
|
*
|
|
97
97
|
* const handler = createCanopyCatchAllHandler({
|
|
98
98
|
* config: config.server,
|
|
@@ -130,4 +130,3 @@ export const createCanopyCatchAllHandler = (options) => {
|
|
|
130
130
|
}
|
|
131
131
|
};
|
|
132
132
|
};
|
|
133
|
-
//# sourceMappingURL=adapter.js.map
|
package/dist/client.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ import type { CanopyClientConfig, CustomFieldRenderers } from 'canopycms/client'
|
|
|
16
16
|
* // app/edit/page.tsx
|
|
17
17
|
* 'use client'
|
|
18
18
|
* import { NextCanopyEditorPage } from 'canopycms-next/client'
|
|
19
|
-
* import config from '../../canopycms.config'
|
|
19
|
+
* import config from '../../canopycms.config.js'
|
|
20
20
|
*
|
|
21
21
|
* export default function EditPage() {
|
|
22
22
|
* const clientConfig = config.client()
|
|
@@ -26,4 +26,3 @@ import type { CanopyClientConfig, CustomFieldRenderers } from 'canopycms/client'
|
|
|
26
26
|
* ```
|
|
27
27
|
*/
|
|
28
28
|
export declare const NextCanopyEditorPage: (config: CanopyClientConfig, customRenderers?: CustomFieldRenderers) => () => import("react/jsx-runtime").JSX.Element;
|
|
29
|
-
//# sourceMappingURL=client.d.ts.map
|
package/dist/client.js
CHANGED
|
@@ -20,7 +20,7 @@ import { CanopyEditorPage } from 'canopycms/client';
|
|
|
20
20
|
* // app/edit/page.tsx
|
|
21
21
|
* 'use client'
|
|
22
22
|
* import { NextCanopyEditorPage } from 'canopycms-next/client'
|
|
23
|
-
* import config from '../../canopycms.config'
|
|
23
|
+
* import config from '../../canopycms.config.js'
|
|
24
24
|
*
|
|
25
25
|
* export default function EditPage() {
|
|
26
26
|
* const clientConfig = config.client()
|
|
@@ -47,4 +47,3 @@ export const NextCanopyEditorPage = (config, customRenderers) => {
|
|
|
47
47
|
return (_jsx(Suspense, { fallback: null, children: _jsx(EditorWithSearchParams, {}) }));
|
|
48
48
|
};
|
|
49
49
|
};
|
|
50
|
-
//# sourceMappingURL=client.js.map
|
package/dist/config.d.ts
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
export { withCanopy, type WithCanopyOptions } from './with-canopy';
|
|
2
|
-
//# sourceMappingURL=config.d.ts.map
|
|
1
|
+
export { withCanopy, type WithCanopyOptions } from './with-canopy.js';
|
package/dist/config.js
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
export { withCanopy } from './with-canopy';
|
|
2
|
-
//# sourceMappingURL=config.js.map
|
|
1
|
+
export { withCanopy } from './with-canopy.js';
|
|
@@ -1,12 +1,43 @@
|
|
|
1
|
-
import { type CanopyContext, type CanopyBuildContext, type CanopyServices } from 'canopycms/server';
|
|
1
|
+
import { type CanopyContext, type CanopyBuildContext, type CanopyServices, type SeoFieldLocation } from 'canopycms/server';
|
|
2
2
|
import type { CanopyConfig, AuthPlugin, FieldConfig } from 'canopycms';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import type { Metadata, MetadataRoute } from 'next';
|
|
4
|
+
import { createCanopyCatchAllHandler } from './adapter.js';
|
|
5
|
+
import { type EntryToMetadataOptions, type GenerateContentSitemapOptions, type GenerateContentStaticParamsOptions } from './static.js';
|
|
6
|
+
/**
|
|
7
|
+
* Merge a context-wide default SEO field location (`createNextCanopyContext({ seo })`) with a
|
|
8
|
+
* per-call override.
|
|
9
|
+
*
|
|
10
|
+
* `generateContentSitemap`'s `noindex` exclusion and `entryToMetadata`'s field extraction/`noindex`
|
|
11
|
+
* read must agree on where the SEO fields live, or the two surfaces drift: an entry can end up
|
|
12
|
+
* `noindex` on the page while the sitemap still advertises its URL (or the reverse), because each
|
|
13
|
+
* call site independently forgot (or mis-set) `group`/`fields`. Both bound helpers below call this
|
|
14
|
+
* SAME function with the SAME context-wide default, which is what makes agreement structural
|
|
15
|
+
* rather than a matter of adopter discipline.
|
|
16
|
+
*
|
|
17
|
+
* Only keys the caller actually supplies override the default — an omitted (or explicitly
|
|
18
|
+
* `undefined`) `fields`/`group` falls through to the context-wide value, so setting a default once
|
|
19
|
+
* and never repeating it per call is the common case. A plain `{ ...contextDefault, ...callOverride
|
|
20
|
+
* }` would NOT have this property: `entryToMetadata`'s options type always has `fields`/`group`
|
|
21
|
+
* keys, so a caller who omits them still produces an object whose `fields`/`group` are present but
|
|
22
|
+
* `undefined`, and spreading that would silently clobber the default. Checking each key explicitly
|
|
23
|
+
* avoids that trap. Exported for direct unit testing.
|
|
24
|
+
*/
|
|
25
|
+
export declare function mergeSeoFieldLocation(contextDefault: SeoFieldLocation | undefined, callOverride: SeoFieldLocation | undefined): SeoFieldLocation;
|
|
5
26
|
export interface NextCanopyOptions {
|
|
6
27
|
config: CanopyConfig;
|
|
7
28
|
/** Auth plugin for user authentication. Optional for static deployments (deployedAs: 'static'). */
|
|
8
29
|
authPlugin?: AuthPlugin;
|
|
9
30
|
entrySchemaRegistry: Record<string, readonly FieldConfig[]>;
|
|
31
|
+
/**
|
|
32
|
+
* Where the SEO fields live (`fields` name overrides, and/or a nested `group`). Set once here
|
|
33
|
+
* and it is shared by BOTH the returned `generateContentSitemap`'s `noindex` exclusion and the
|
|
34
|
+
* returned `entryToMetadata`'s field extraction, so the two surfaces cannot independently forget
|
|
35
|
+
* or mis-set it and drift apart — see `mergeSeoFieldLocation`. Omit for the flat (inline-group)
|
|
36
|
+
* convention, which is the default on both the schema side (`defineSeoFieldGroup()`) and here.
|
|
37
|
+
* A per-call `seo`/`fields`/`group` option on either helper still overrides this default for
|
|
38
|
+
* that one call.
|
|
39
|
+
*/
|
|
40
|
+
seo?: SeoFieldLocation;
|
|
10
41
|
}
|
|
11
42
|
/**
|
|
12
43
|
* Wrap a build context so its operations throw if misused at request time on a production server.
|
|
@@ -55,6 +86,25 @@ export interface NextCanopyContextResult {
|
|
|
55
86
|
readByUrlPath: CanopyContext['readByUrlPath'];
|
|
56
87
|
/** Phase-selecting `read` (build context at build, runtime context at request) — counterpart to readByUrlPath. */
|
|
57
88
|
read: CanopyContext['read'];
|
|
89
|
+
/**
|
|
90
|
+
* Phase-selecting `listEntries` — every entry under `rootPath` in a single filesystem
|
|
91
|
+
* pass, each with its `urlPath`, `slug`, `entryType`, `data` and `schema`. Use it instead
|
|
92
|
+
* of "enumerate paths, then read each one", which is an N+1 over the content tree and
|
|
93
|
+
* invites URL-reconstruction bugs; the returned `urlPath` round-trips through
|
|
94
|
+
* `readByUrlPath` by construction, including for multi-segment paths.
|
|
95
|
+
*
|
|
96
|
+
* ```ts
|
|
97
|
+
* const articles = await listEntries<ArticleContent>({
|
|
98
|
+
* filter: (e) => e.entryType === 'article',
|
|
99
|
+
* })
|
|
100
|
+
* ```
|
|
101
|
+
*
|
|
102
|
+
* At build time this reads filesystem-direct; at request time it uses the branch-aware,
|
|
103
|
+
* **ACL-enforced** runtime context, so entries the current user cannot read are omitted.
|
|
104
|
+
* Note it takes no `branch` option — see `CanopyContext['listEntries']` for the
|
|
105
|
+
* base-branch pinning caveat in prod.
|
|
106
|
+
*/
|
|
107
|
+
listEntries: CanopyContext['listEntries'];
|
|
58
108
|
/**
|
|
59
109
|
* Build the array Next's `generateStaticParams` expects from CanopyCMS content. Enumeration-only
|
|
60
110
|
* (reads the set of routable paths, never entry content) and closes over the build context, so your
|
|
@@ -62,6 +112,28 @@ export interface NextCanopyContextResult {
|
|
|
62
112
|
* `[slug]` route, or the default catch-all for `[...slug]`.
|
|
63
113
|
*/
|
|
64
114
|
generateContentStaticParams: (options?: GenerateContentStaticParamsOptions) => Promise<Array<Record<string, string | string[]>>>;
|
|
115
|
+
/**
|
|
116
|
+
* Build `app/sitemap.ts`'s `MetadataRoute.Sitemap` from CanopyCMS content. Includes EVERY
|
|
117
|
+
* routable entry type by default and excludes `noindex` entries through the same predicate
|
|
118
|
+
* `entryToMetadata` uses for `robots`. Bound to the build context, so your `sitemap.ts` never
|
|
119
|
+
* imports the admin `getCanopyForBuild`.
|
|
120
|
+
*
|
|
121
|
+
* Reads the SEO field location from `createNextCanopyContext({ seo })` by default (shared with
|
|
122
|
+
* `entryToMetadata` below via `mergeSeoFieldLocation` — see that function's doc). Pass `seo` on a
|
|
123
|
+
* given call to override just that call.
|
|
124
|
+
*/
|
|
125
|
+
generateContentSitemap: (options: GenerateContentSitemapOptions) => Promise<MetadataRoute.Sitemap>;
|
|
126
|
+
/**
|
|
127
|
+
* Map an entry's SEO fields onto a Next `Metadata` for `generateMetadata`. Re-exposed here so a
|
|
128
|
+
* page module has one CanopyCMS import (your `lib/canopy.ts`) rather than two.
|
|
129
|
+
*
|
|
130
|
+
* Reads the SAME SEO field location as `generateContentSitemap` above by default (the
|
|
131
|
+
* `createNextCanopyContext({ seo })` value); the two are bound from one context-wide default so
|
|
132
|
+
* they cannot silently disagree about where `noindex` (or a renamed field) lives. Pass
|
|
133
|
+
* `fields`/`group` on a given call to override just that call. This is a pure
|
|
134
|
+
* mapping and touches no context.
|
|
135
|
+
*/
|
|
136
|
+
entryToMetadata: (entryData: unknown, options?: EntryToMetadataOptions) => Metadata;
|
|
65
137
|
/** API catch-all route handler */
|
|
66
138
|
handler: ReturnType<typeof createCanopyCatchAllHandler>;
|
|
67
139
|
/** Underlying services (rarely needed directly) */
|
|
@@ -77,4 +149,3 @@ export interface NextCanopyContextResult {
|
|
|
77
149
|
* auth works without network access (Lambda in prod, local in dev). The cache is populated by the worker daemon.
|
|
78
150
|
*/
|
|
79
151
|
export declare function createNextCanopyContext(options: NextCanopyOptions): Promise<NextCanopyContextResult>;
|
|
80
|
-
//# sourceMappingURL=context-wrapper.d.ts.map
|
package/dist/context-wrapper.js
CHANGED
|
@@ -4,8 +4,35 @@ import { headers } from 'next/headers';
|
|
|
4
4
|
import { createCanopyContext, isBuildMode, startDevContentWatcher, createCanopyServices, createAssetStore, operatingStrategy, resolveCanopyUser, STATIC_DEPLOY_USER, } from 'canopycms/server';
|
|
5
5
|
import { assertAuthPluginAllowedForMode } from 'canopycms/auth';
|
|
6
6
|
import { CachingAuthPlugin, FileBasedAuthCache } from 'canopycms/auth/cache';
|
|
7
|
-
import { createCanopyCatchAllHandler } from './adapter';
|
|
8
|
-
import { collectStaticParams } from './static';
|
|
7
|
+
import { createCanopyCatchAllHandler } from './adapter.js';
|
|
8
|
+
import { collectStaticParams, entryToMetadata as entryToMetadataCore, generateContentSitemap, } from './static.js';
|
|
9
|
+
/**
|
|
10
|
+
* Merge a context-wide default SEO field location (`createNextCanopyContext({ seo })`) with a
|
|
11
|
+
* per-call override.
|
|
12
|
+
*
|
|
13
|
+
* `generateContentSitemap`'s `noindex` exclusion and `entryToMetadata`'s field extraction/`noindex`
|
|
14
|
+
* read must agree on where the SEO fields live, or the two surfaces drift: an entry can end up
|
|
15
|
+
* `noindex` on the page while the sitemap still advertises its URL (or the reverse), because each
|
|
16
|
+
* call site independently forgot (or mis-set) `group`/`fields`. Both bound helpers below call this
|
|
17
|
+
* SAME function with the SAME context-wide default, which is what makes agreement structural
|
|
18
|
+
* rather than a matter of adopter discipline.
|
|
19
|
+
*
|
|
20
|
+
* Only keys the caller actually supplies override the default — an omitted (or explicitly
|
|
21
|
+
* `undefined`) `fields`/`group` falls through to the context-wide value, so setting a default once
|
|
22
|
+
* and never repeating it per call is the common case. A plain `{ ...contextDefault, ...callOverride
|
|
23
|
+
* }` would NOT have this property: `entryToMetadata`'s options type always has `fields`/`group`
|
|
24
|
+
* keys, so a caller who omits them still produces an object whose `fields`/`group` are present but
|
|
25
|
+
* `undefined`, and spreading that would silently clobber the default. Checking each key explicitly
|
|
26
|
+
* avoids that trap. Exported for direct unit testing.
|
|
27
|
+
*/
|
|
28
|
+
export function mergeSeoFieldLocation(contextDefault, callOverride) {
|
|
29
|
+
const merged = { ...contextDefault };
|
|
30
|
+
if (callOverride?.fields !== undefined)
|
|
31
|
+
merged.fields = callOverride.fields;
|
|
32
|
+
if (callOverride?.group !== undefined)
|
|
33
|
+
merged.group = callOverride.group;
|
|
34
|
+
return merged;
|
|
35
|
+
}
|
|
9
36
|
let warnedStaticMode = false;
|
|
10
37
|
/**
|
|
11
38
|
* Stub auth plugin for static deployments where no real auth is needed.
|
|
@@ -209,11 +236,36 @@ export async function createNextCanopyContext(options) {
|
|
|
209
236
|
const ctx = isBuildMode() ? await getCanopyForBuild() : await getCanopy();
|
|
210
237
|
return ctx.read(input);
|
|
211
238
|
};
|
|
239
|
+
const listEntries = async (opts) => {
|
|
240
|
+
const ctx = isBuildMode() ? await getCanopyForBuild() : await getCanopy();
|
|
241
|
+
return ctx.listEntries(opts);
|
|
242
|
+
};
|
|
212
243
|
// Enumeration-only static-params helper, bound to the (guarded) build context so page modules don't
|
|
213
244
|
// import the admin context just to list paths. generateStaticParams is build-only, so this is safe.
|
|
214
245
|
const generateContentStaticParams = async (options = {}) => {
|
|
215
246
|
return collectStaticParams(await getCanopyForBuild(), options);
|
|
216
247
|
};
|
|
248
|
+
// Sitemap generation reads entry CONTENT (to apply the noindex predicate), so unlike
|
|
249
|
+
// generateContentStaticParams it is not enumeration-only — but sitemap.ts is build-only in a
|
|
250
|
+
// static export, and on a prod `server` deployment guardBuildContext throws if it is reached at
|
|
251
|
+
// request time. Binding it here keeps the admin context out of the route module either way.
|
|
252
|
+
//
|
|
253
|
+
// Both this and boundEntryToMetadata below feed options.seo (the context-wide default set on
|
|
254
|
+
// createNextCanopyContext) through the SAME mergeSeoFieldLocation call, so the noindex exclusion
|
|
255
|
+
// here and entryToMetadata's noindex/field read cannot independently drift out of sync.
|
|
256
|
+
const boundGenerateContentSitemap = async (callOptions) => {
|
|
257
|
+
return generateContentSitemap(await getCanopyForBuild(), {
|
|
258
|
+
...callOptions,
|
|
259
|
+
seo: mergeSeoFieldLocation(options.seo, callOptions.seo),
|
|
260
|
+
});
|
|
261
|
+
};
|
|
262
|
+
const boundEntryToMetadata = (entryData, callOptions = {}) => {
|
|
263
|
+
const seoLocation = mergeSeoFieldLocation(options.seo, {
|
|
264
|
+
fields: callOptions.fields,
|
|
265
|
+
group: callOptions.group,
|
|
266
|
+
});
|
|
267
|
+
return entryToMetadataCore(entryData, { ...callOptions, ...seoLocation });
|
|
268
|
+
};
|
|
217
269
|
// Create API handler using same services
|
|
218
270
|
const handler = createCanopyCatchAllHandler({
|
|
219
271
|
...options,
|
|
@@ -226,9 +278,11 @@ export async function createNextCanopyContext(options) {
|
|
|
226
278
|
getCanopyForBuild,
|
|
227
279
|
readByUrlPath,
|
|
228
280
|
read,
|
|
281
|
+
listEntries,
|
|
229
282
|
generateContentStaticParams,
|
|
283
|
+
generateContentSitemap: boundGenerateContentSitemap,
|
|
284
|
+
entryToMetadata: boundEntryToMetadata,
|
|
230
285
|
handler,
|
|
231
286
|
services,
|
|
232
287
|
};
|
|
233
288
|
}
|
|
234
|
-
//# sourceMappingURL=context-wrapper.js.map
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
export { createCanopyCatchAllHandler, wrapNextRequest, type CanopyNextOptions } from './adapter';
|
|
2
|
-
export { createNextCanopyContext, type NextCanopyOptions, type NextCanopyContextResult, } from './context-wrapper';
|
|
3
|
-
export { collectStaticParams, type GenerateContentStaticParamsOptions } from './static';
|
|
4
|
-
export { createMockAuthPlugin, createRejectingAuthPlugin } from './test-utils';
|
|
5
|
-
//# sourceMappingURL=index.d.ts.map
|
|
1
|
+
export { createCanopyCatchAllHandler, wrapNextRequest, type CanopyNextOptions } from './adapter.js';
|
|
2
|
+
export { createNextCanopyContext, type NextCanopyOptions, type NextCanopyContextResult, } from './context-wrapper.js';
|
|
3
|
+
export { collectStaticParams, generateContentSitemap, entryToMetadata, type GenerateContentStaticParamsOptions, type GenerateContentSitemapOptions, type EntryToMetadataOptions, type SitemapExtraUrl, } from './static.js';
|
|
4
|
+
export { createMockAuthPlugin, createRejectingAuthPlugin } from './test-utils.js';
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
export { createCanopyCatchAllHandler, wrapNextRequest } from './adapter';
|
|
2
|
-
export { createNextCanopyContext, } from './context-wrapper';
|
|
3
|
-
export { collectStaticParams } from './static';
|
|
4
|
-
export { createMockAuthPlugin, createRejectingAuthPlugin } from './test-utils';
|
|
5
|
-
//# sourceMappingURL=index.js.map
|
|
1
|
+
export { createCanopyCatchAllHandler, wrapNextRequest } from './adapter.js';
|
|
2
|
+
export { createNextCanopyContext, } from './context-wrapper.js';
|
|
3
|
+
export { collectStaticParams, generateContentSitemap, entryToMetadata, } from './static.js';
|
|
4
|
+
export { createMockAuthPlugin, createRejectingAuthPlugin } from './test-utils.js';
|
package/dist/static.d.ts
CHANGED
|
@@ -1,10 +1,17 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { Metadata, MetadataRoute } from 'next';
|
|
2
|
+
import { type CanopyBuildContext, type CollectStaticPathsOptions, type ExtractSeoFieldsOptions, type RoutableEntry, type SeoFieldLocation, type SeoOgType } from 'canopycms/server';
|
|
2
3
|
/**
|
|
3
|
-
* Next.js static-export helpers built on the framework-agnostic core in `canopycms/server
|
|
4
|
+
* Next.js static-export helpers built on the framework-agnostic core in `canopycms/server`:
|
|
5
|
+
* static params (`collectStaticParams`), the content sitemap (`generateContentSitemap`), and
|
|
6
|
+
* per-entry metadata (`entryToMetadata`).
|
|
4
7
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
+
* The last two ship together on purpose. `noindex` has to suppress a page in BOTH surfaces —
|
|
9
|
+
* `robots: { index: false }` on the page and absence from the sitemap — and both read it through
|
|
10
|
+
* the same core `isNoindexEntry` predicate, so they cannot disagree about which pages are
|
|
11
|
+
* advertised.
|
|
12
|
+
*
|
|
13
|
+
* `robots.txt` is out of scope: it is a handful of static lines with no CanopyCMS content behind
|
|
14
|
+
* it. Write `app/robots.ts` yourself, and point its `sitemap` at the route below.
|
|
8
15
|
*/
|
|
9
16
|
export interface GenerateContentStaticParamsOptions extends CollectStaticPathsOptions {
|
|
10
17
|
/** Route param name. Default 'slug'. */
|
|
@@ -20,6 +27,10 @@ export interface GenerateContentStaticParamsOptions extends CollectStaticPathsOp
|
|
|
20
27
|
* route's base (e.g. `'/docs'`). Entries are scoped to that prefix and `segments` are made relative
|
|
21
28
|
* to it, so the params match the route. Without it, segments are the full URL path. Applies to
|
|
22
29
|
* catch-all shapes (it rewrites `segments`); it has no effect with `shape: 'single'`.
|
|
30
|
+
*
|
|
31
|
+
* Note that `shape: 'single'` also SKIPS collection index entries, whose URL is the
|
|
32
|
+
* collection's own path rather than a single slug segment. Render those from the collection's
|
|
33
|
+
* route (e.g. `app/posts/page.tsx`), not from `[slug]`.
|
|
23
34
|
*/
|
|
24
35
|
basePath?: string;
|
|
25
36
|
}
|
|
@@ -36,4 +47,197 @@ export interface GenerateContentStaticParamsOptions extends CollectStaticPathsOp
|
|
|
36
47
|
* `[[...slug]]`, otherwise exclude it via `options.filter` (e.g. `(e) => e.segments.length > 0`).
|
|
37
48
|
*/
|
|
38
49
|
export declare function collectStaticParams(buildCtx: Pick<CanopyBuildContext, 'listEntries'>, options?: GenerateContentStaticParamsOptions): Promise<Array<Record<string, string | string[]>>>;
|
|
39
|
-
|
|
50
|
+
type SitemapItem = MetadataRoute.Sitemap[number];
|
|
51
|
+
/**
|
|
52
|
+
* A URL with no CanopyCMS entry behind it (a hand-written app route, a feed).
|
|
53
|
+
*
|
|
54
|
+
* **An extra URL is entirely hand-managed — it inherits nothing from the entry pipeline.**
|
|
55
|
+
* `generateContentSitemap` applies `isNoindexEntry` and a default `lastModified` only while
|
|
56
|
+
* walking real entries; this list is appended afterwards and passes through both:
|
|
57
|
+
*
|
|
58
|
+
* - **No `noindex` gate.** Nothing checks the SEO flag for an extra URL, because there is no
|
|
59
|
+
* entry data to check. If you are using `extraUrls` to re-advertise a real entry under a
|
|
60
|
+
* different path (the usual reason — an entry whose structural `urlPath` no route serves),
|
|
61
|
+
* you are responsible for not listing it when that entry is marked `noindex`. Marking the
|
|
62
|
+
* entry does not remove the extra URL.
|
|
63
|
+
* - **No `lastModified` fallback.** The per-entry branch defaults to `entry.updatedAt`; here,
|
|
64
|
+
* omitting `lastModified` means the URL simply ships without a date.
|
|
65
|
+
*
|
|
66
|
+
* Both are easy to get wrong in exactly the same direction, and both used to be unavoidable:
|
|
67
|
+
* `extraUrls` was once the only way to advertise a real entry at a different URL, so every such
|
|
68
|
+
* use re-derived `noindex` and `lastModified` by hand — this repo's own reference app among them,
|
|
69
|
+
* and it got `lastModified` wrong.
|
|
70
|
+
*
|
|
71
|
+
* It is no longer the only way, so it should no longer be that way:
|
|
72
|
+
*
|
|
73
|
+
* 1. **Model the entry so its natural `urlPath` IS the URL you serve.** An `index` entry collapses
|
|
74
|
+
* onto its collection's path, and a root `index` entry onto `/`. Nothing to keep in sync. This
|
|
75
|
+
* is what the reference app does now, which is why its sitemap passes neither option.
|
|
76
|
+
* 2. **Failing that, use `pathFor`** (see `GenerateContentSitemapOptions`), which overrides the
|
|
77
|
+
* URL while keeping the entry inside the walk — so the `noindex` gate, the `lastModified`
|
|
78
|
+
* default and `priority` all still apply.
|
|
79
|
+
* 3. **Keep `extraUrls` for what its name says:** URLs with no entry behind them at all.
|
|
80
|
+
*/
|
|
81
|
+
export interface SitemapExtraUrl {
|
|
82
|
+
/** Site-relative path ('/blog') or an absolute URL. Trailing-slash rules apply to the former. */
|
|
83
|
+
path: string;
|
|
84
|
+
/** No fallback: omit this and the URL ships with no date at all (entries default to `updatedAt`). */
|
|
85
|
+
lastModified?: Date | string;
|
|
86
|
+
changeFrequency?: SitemapItem['changeFrequency'];
|
|
87
|
+
priority?: number;
|
|
88
|
+
}
|
|
89
|
+
export interface GenerateContentSitemapOptions {
|
|
90
|
+
/**
|
|
91
|
+
* Site origin, e.g. `https://example.com`. Required: a sitemap must carry absolute URLs, or
|
|
92
|
+
* search engines reject the whole file. Enforced — `generateContentSitemap` throws if this
|
|
93
|
+
* isn't an absolute URL (no scheme, or empty).
|
|
94
|
+
*/
|
|
95
|
+
siteUrl: string;
|
|
96
|
+
/**
|
|
97
|
+
* Emit site-relative URLs with a trailing slash (`/contact/` rather than `/contact`).
|
|
98
|
+
*
|
|
99
|
+
* **Explicit on purpose.** CanopyCMS cannot see your `next.config.ts`, so it cannot know
|
|
100
|
+
* whether your site serves `trailingSlash: true`. Set this to match, or the sitemap advertises
|
|
101
|
+
* URLs that redirect — a real adopter shipped exactly that mismatch.
|
|
102
|
+
*/
|
|
103
|
+
trailingSlash?: boolean;
|
|
104
|
+
/** Scope to a collection logical path (e.g. 'content/posts'). Defaults to the whole content root. */
|
|
105
|
+
rootPath?: string;
|
|
106
|
+
/** Where the SEO fields live, when they aren't the flat defaults. Drives the `noindex` read. */
|
|
107
|
+
seo?: SeoFieldLocation;
|
|
108
|
+
/**
|
|
109
|
+
* Drop entries from the sitemap. Applied ON TOP of the `noindex` exclusion, which is not
|
|
110
|
+
* optional. Use for structural URLs that shouldn't be advertised (e.g. a bare collection index).
|
|
111
|
+
*/
|
|
112
|
+
exclude?: (entry: RoutableEntry) => boolean;
|
|
113
|
+
/**
|
|
114
|
+
* `<lastmod>` per entry. Defaults to the entry's `updatedAt`.
|
|
115
|
+
*
|
|
116
|
+
* **`updatedAt` is filesystem mtime, not an editorial timestamp.** A fresh CI clone resets every
|
|
117
|
+
* file's mtime to checkout time, so on a clean build agent the default dates every URL to the
|
|
118
|
+
* moment the tree was cloned. Treat the default as "changed since the last build" at best; if
|
|
119
|
+
* you need a truthful `<lastmod>`, supply one here (a content date field, or git commit time)
|
|
120
|
+
* or return `undefined` to omit the element entirely, which is better than asserting a date you
|
|
121
|
+
* cannot stand behind.
|
|
122
|
+
*/
|
|
123
|
+
lastModified?: (entry: RoutableEntry) => Date | string | undefined;
|
|
124
|
+
/** `<priority>` per entry. Omitted from the URL when this returns undefined (the default). */
|
|
125
|
+
priority?: (entry: RoutableEntry) => number | undefined;
|
|
126
|
+
/**
|
|
127
|
+
* Override the URL an entry is advertised at, keeping it INSIDE the entry walk.
|
|
128
|
+
*
|
|
129
|
+
* Return a path to advertise the entry at instead of its structural `urlPath`; return `null`
|
|
130
|
+
* (or `undefined`) to leave it alone.
|
|
131
|
+
*
|
|
132
|
+
* **`null` means "no opinion", not "drop it".** So the obvious shape — handle the one entry
|
|
133
|
+
* type you care about, return `null` for the rest — advertises every other entry at its own
|
|
134
|
+
* path rather than silently emitting a one-URL sitemap. Dropping an entry stays `exclude`'s
|
|
135
|
+
* job, and keeping the two separate is the whole reason for this choice: a `pathFor` whose
|
|
136
|
+
* natural-looking callback silently omitted everything else would re-introduce exactly the
|
|
137
|
+
* quietly-short sitemap this module exists to prevent.
|
|
138
|
+
*
|
|
139
|
+
* This is the principled alternative to reaching for `extraUrls` to reroute a REAL entry.
|
|
140
|
+
* Because the entry stays in the walk, it keeps the `isNoindexEntry` gate, the `updatedAt`
|
|
141
|
+
* `lastModified` default and its `priority` automatically — all three of which an `extraUrls`
|
|
142
|
+
* entry makes you re-derive by hand, and get wrong independently (see {@link SitemapExtraUrl}).
|
|
143
|
+
*
|
|
144
|
+
* **It changes what is ADVERTISED, not what is BUILT.** `generateContentStaticParams` still
|
|
145
|
+
* enumerates the entry at its structural path, so the URL returned here must be one your app
|
|
146
|
+
* actually routes — otherwise you have advertised a 404, the same hazard `extraUrls` carries.
|
|
147
|
+
*
|
|
148
|
+
* Return a **site-relative path**. The value is trimmed, and an empty or off-site return (an
|
|
149
|
+
* absolute `https://…` or a protocol-relative `//host/…`) throws rather than being emitted:
|
|
150
|
+
* the first silently claims `/`, and the second lands in the sitemap as a non-absolute `<loc>`,
|
|
151
|
+
* which invalidates the whole file. `extraUrls` is where an off-origin URL is legitimate.
|
|
152
|
+
*
|
|
153
|
+
* Reach for it only when the URL is fixed by something OUTSIDE the content tree: published URLs
|
|
154
|
+
* you cannot change, or a route prefix that deliberately differs from the content layout. When
|
|
155
|
+
* you control the modelling, model the entry so its natural `urlPath` is already the URL you
|
|
156
|
+
* serve — an `index` entry collapses onto its collection's path, and a root `index` entry onto
|
|
157
|
+
* `/` — which needs no option at all. That ordering is not advice we only give: it is what the
|
|
158
|
+
* reference app in this repo does, which is why its sitemap passes neither this nor `extraUrls`.
|
|
159
|
+
*
|
|
160
|
+
* Runs AFTER the `noindex` and `exclude` gates (a dropped entry needs no URL). `exclude`,
|
|
161
|
+
* `lastModified` and `priority` receive the entry as ENUMERATED, so `entry.urlPath` there is
|
|
162
|
+
* always the structural path and never your override — branch on the entry, not on the URL.
|
|
163
|
+
*
|
|
164
|
+
* Two entries rewritten onto one URL are NOT caught by the build's `assertNoDuplicateUrlPaths`
|
|
165
|
+
* guard, which runs on the raw listing and never sees these rewrites; `dedupeSitemapItems`
|
|
166
|
+
* warns and keeps the first.
|
|
167
|
+
*
|
|
168
|
+
* @example
|
|
169
|
+
* // Content lives under content/articles/*, but this site has always published /blog/*.
|
|
170
|
+
* pathFor: (entry) =>
|
|
171
|
+
* entry.entryType === 'article' ? entry.urlPath.replace(/^\/articles\//, '/blog/') : null,
|
|
172
|
+
*/
|
|
173
|
+
pathFor?: (entry: RoutableEntry) => string | null | undefined;
|
|
174
|
+
/**
|
|
175
|
+
* URLs with NO entry behind them — hand-written app routes, feeds — appended to the result.
|
|
176
|
+
*
|
|
177
|
+
* Appended after the entry walk, so these bypass BOTH the `isNoindexEntry` gate and the
|
|
178
|
+
* `lastModified` default. To point a REAL entry at a different URL, use `pathFor` above, which
|
|
179
|
+
* keeps both. See {@link SitemapExtraUrl}.
|
|
180
|
+
*/
|
|
181
|
+
extraUrls?: SitemapExtraUrl[];
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Build Next's `MetadataRoute.Sitemap` from CanopyCMS content.
|
|
185
|
+
*
|
|
186
|
+
* **Every routable entry type is included by default.** There is no list of "sitemap-able" entry
|
|
187
|
+
* types to keep in sync, and that is the whole design: a hand-rolled sitemap that enumerates a
|
|
188
|
+
* remembered list of entry types omits whichever type nobody added, ships green, and takes the
|
|
189
|
+
* missing pages out of search results silently. Omitting a URL here requires an explicit
|
|
190
|
+
* `exclude` predicate or a `noindex` flag on the entry.
|
|
191
|
+
*
|
|
192
|
+
* `noindex` entries are excluded, via the same core `isNoindexEntry` predicate that drives
|
|
193
|
+
* `robots: { index: false }` in `entryToMetadata`. They are still BUILT — enumeration
|
|
194
|
+
* (`generateContentStaticParams`) does not filter them, so the page exists for anyone holding
|
|
195
|
+
* the link; it just isn't advertised.
|
|
196
|
+
*
|
|
197
|
+
* `changeFrequency` is not emitted for entries: a blanket value asserted for every URL carries no
|
|
198
|
+
* information, and search engines say they ignore it. Set it per-URL via `extraUrls` if you want it.
|
|
199
|
+
*
|
|
200
|
+
* Output is stably ordered ('/' first, then alphabetical) so a rebuild doesn't reshuffle the file.
|
|
201
|
+
*
|
|
202
|
+
* @example
|
|
203
|
+
* // app/sitemap.ts
|
|
204
|
+
* export const dynamic = 'force-static' // required for output: 'export'
|
|
205
|
+
* export default () => contentSitemap({ siteUrl: 'https://example.com', trailingSlash: true })
|
|
206
|
+
*/
|
|
207
|
+
export declare function generateContentSitemap(buildCtx: Pick<CanopyBuildContext, 'listEntries'>, options: GenerateContentSitemapOptions): Promise<MetadataRoute.Sitemap>;
|
|
208
|
+
export interface EntryToMetadataOptions extends ExtractSeoFieldsOptions {
|
|
209
|
+
/** Route path for this entry — the canonical URL when the entry sets none. */
|
|
210
|
+
path?: string;
|
|
211
|
+
/**
|
|
212
|
+
* Site origin for resolving relative canonical / OG image URLs. Omit to leave them relative and
|
|
213
|
+
* let Next's `metadataBase` resolve them.
|
|
214
|
+
*/
|
|
215
|
+
siteUrl?: string;
|
|
216
|
+
/** Emit site-relative URLs with a trailing slash. Match your sitemap and your routing config. */
|
|
217
|
+
trailingSlash?: boolean;
|
|
218
|
+
/** Site name (openGraph.siteName, and the social-card title fallback). */
|
|
219
|
+
siteName?: string;
|
|
220
|
+
/** Root-layout mode: emit `title: { template, default }` (e.g. `'%s | Example'`). */
|
|
221
|
+
titleTemplate?: string;
|
|
222
|
+
/** og:type when the entry sets none. Defaults to 'website'. */
|
|
223
|
+
defaultOgType?: SeoOgType;
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Map an entry's SEO fields onto a Next `Metadata` object.
|
|
227
|
+
*
|
|
228
|
+
* Title and description follow ONE convention everywhere: the entry's meta field, else the
|
|
229
|
+
* fallback you pass, else unset (so the root layout's default applies). An empty CMS field counts
|
|
230
|
+
* as unset — see `extractSeoFields`.
|
|
231
|
+
*
|
|
232
|
+
* `noindex` goes through the same core predicate the sitemap uses, so a page marked noindex is
|
|
233
|
+
* suppressed in both surfaces or neither.
|
|
234
|
+
*
|
|
235
|
+
* @example
|
|
236
|
+
* export async function generateMetadata({ params }): Promise<Metadata> {
|
|
237
|
+
* const { slug } = await params
|
|
238
|
+
* const result = await readByUrlPath(`/posts/${slug}`)
|
|
239
|
+
* return entryToMetadata(result?.data, { path: `/posts/${slug}`, fallbackTitle: result?.data.title })
|
|
240
|
+
* }
|
|
241
|
+
*/
|
|
242
|
+
export declare function entryToMetadata(entryData: unknown, opts?: EntryToMetadataOptions): Metadata;
|
|
243
|
+
export {};
|
package/dist/static.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { collectStaticPaths, } from 'canopycms/server';
|
|
1
|
+
import { collectRoutableEntries, collectStaticPaths, extractSeoFields, isAbsoluteUrl, isIndexSlug, isNoindexEntry, resolveSeoUrl, } from 'canopycms/server';
|
|
2
2
|
/**
|
|
3
3
|
* Shape CanopyCMS content paths into the array Next's `generateStaticParams` expects.
|
|
4
4
|
*
|
|
@@ -14,7 +14,13 @@ import { collectStaticPaths, } from 'canopycms/server';
|
|
|
14
14
|
export async function collectStaticParams(buildCtx, options = {}) {
|
|
15
15
|
const { paramName = 'slug', shape = 'catch-all', basePath, ...collectOptions } = options;
|
|
16
16
|
let entries = await collectStaticPaths(buildCtx, collectOptions);
|
|
17
|
-
|
|
17
|
+
// basePath only means something for the catch-all shape: it rewrites `segments` relative to the
|
|
18
|
+
// route's URL prefix, and 'single' shape never reads `segments` (it emits `entry.slug`). Applying
|
|
19
|
+
// the prefix FILTER unconditionally — as this once did — silently dropped every entry outside the
|
|
20
|
+
// prefix for 'single' too, contradicting this option's own doc above ("no effect with shape:
|
|
21
|
+
// 'single'") and meaning unbuilt pages for anyone who set basePath alongside 'single'. Scope with
|
|
22
|
+
// `rootPath` for 'single' instead.
|
|
23
|
+
if (basePath && shape !== 'single') {
|
|
18
24
|
// Make segments relative to a nested route's base prefix (e.g. '/docs' for app/docs/[[...slug]]).
|
|
19
25
|
// urlPath is always lowercased (see content-listing), so lowercase the prefix to match.
|
|
20
26
|
const prefix = (basePath.endsWith('/') ? basePath.slice(0, -1) : basePath).toLowerCase();
|
|
@@ -25,6 +31,227 @@ export async function collectStaticParams(buildCtx, options = {}) {
|
|
|
25
31
|
return { ...entry, segments: rel ? rel.split('/') : [] };
|
|
26
32
|
});
|
|
27
33
|
}
|
|
28
|
-
|
|
34
|
+
if (shape === 'single') {
|
|
35
|
+
// Drop index entries. Their URL is the COLLECTION's path (`/posts`, not `/posts/index`), a
|
|
36
|
+
// shape a single-segment `[slug]` route cannot represent — that page belongs to the
|
|
37
|
+
// collection's own route. Emitting one produced a param whose URL `readByUrlPath` refuses to
|
|
38
|
+
// resolve, so Next prerendered a guaranteed notFound (and an `output: export` build can fail
|
|
39
|
+
// outright). Catch-all is unaffected: it reads the already-collapsed `segments`, which for an
|
|
40
|
+
// index entry are the collection's.
|
|
41
|
+
return entries
|
|
42
|
+
.filter((entry) => !isIndexSlug(entry.slug))
|
|
43
|
+
.map((entry) => ({ [paramName]: entry.slug }));
|
|
44
|
+
}
|
|
45
|
+
return entries.map((entry) => ({ [paramName]: entry.segments }));
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Build Next's `MetadataRoute.Sitemap` from CanopyCMS content.
|
|
49
|
+
*
|
|
50
|
+
* **Every routable entry type is included by default.** There is no list of "sitemap-able" entry
|
|
51
|
+
* types to keep in sync, and that is the whole design: a hand-rolled sitemap that enumerates a
|
|
52
|
+
* remembered list of entry types omits whichever type nobody added, ships green, and takes the
|
|
53
|
+
* missing pages out of search results silently. Omitting a URL here requires an explicit
|
|
54
|
+
* `exclude` predicate or a `noindex` flag on the entry.
|
|
55
|
+
*
|
|
56
|
+
* `noindex` entries are excluded, via the same core `isNoindexEntry` predicate that drives
|
|
57
|
+
* `robots: { index: false }` in `entryToMetadata`. They are still BUILT — enumeration
|
|
58
|
+
* (`generateContentStaticParams`) does not filter them, so the page exists for anyone holding
|
|
59
|
+
* the link; it just isn't advertised.
|
|
60
|
+
*
|
|
61
|
+
* `changeFrequency` is not emitted for entries: a blanket value asserted for every URL carries no
|
|
62
|
+
* information, and search engines say they ignore it. Set it per-URL via `extraUrls` if you want it.
|
|
63
|
+
*
|
|
64
|
+
* Output is stably ordered ('/' first, then alphabetical) so a rebuild doesn't reshuffle the file.
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* // app/sitemap.ts
|
|
68
|
+
* export const dynamic = 'force-static' // required for output: 'export'
|
|
69
|
+
* export default () => contentSitemap({ siteUrl: 'https://example.com', trailingSlash: true })
|
|
70
|
+
*/
|
|
71
|
+
export async function generateContentSitemap(buildCtx, options) {
|
|
72
|
+
const { siteUrl, trailingSlash, rootPath, seo, exclude, lastModified, priority, pathFor } = options;
|
|
73
|
+
// A sitemap with a non-absolute <loc> is invalid — search engines reject the WHOLE file, not
|
|
74
|
+
// just the bad entry, and the build stays green because nothing here threw. 'example.com' (no
|
|
75
|
+
// scheme) and '' both pass through resolveSeoUrl unmodified today; catch them here instead.
|
|
76
|
+
if (!isAbsoluteUrl(siteUrl)) {
|
|
77
|
+
throw new Error(`CanopyCMS: generateContentSitemap requires an absolute siteUrl (e.g. "https://example.com"), ` +
|
|
78
|
+
`got ${JSON.stringify(siteUrl)}. A sitemap whose <loc> values aren't absolute URLs is invalid ` +
|
|
79
|
+
'and search engines silently reject the entire file.');
|
|
80
|
+
}
|
|
81
|
+
const urlOpts = { siteUrl, trailingSlash };
|
|
82
|
+
const entries = await collectRoutableEntries(buildCtx, { rootPath });
|
|
83
|
+
const items = [];
|
|
84
|
+
for (const entry of entries) {
|
|
85
|
+
if (isNoindexEntry(entry.data, seo))
|
|
86
|
+
continue;
|
|
87
|
+
if (exclude?.(entry))
|
|
88
|
+
continue;
|
|
89
|
+
const modified = lastModified ? lastModified(entry) : entry.updatedAt;
|
|
90
|
+
const entryPriority = priority?.(entry);
|
|
91
|
+
items.push({
|
|
92
|
+
url: resolveSeoUrl(resolveEntrySitemapPath(entry, pathFor), urlOpts),
|
|
93
|
+
...(modified ? { lastModified: modified } : {}),
|
|
94
|
+
...(entryPriority === undefined ? {} : { priority: entryPriority }),
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
// Deliberately outside the entry loop above, and therefore outside its `isNoindexEntry` gate
|
|
98
|
+
// and its `entry.updatedAt` fallback — an extra URL has no entry to derive either from. This is
|
|
99
|
+
// the behaviour documented on SitemapExtraUrl; if that ever changes, change the doc with it.
|
|
100
|
+
for (const extra of options.extraUrls ?? []) {
|
|
101
|
+
items.push({
|
|
102
|
+
url: resolveSeoUrl(extra.path, urlOpts),
|
|
103
|
+
...(extra.lastModified ? { lastModified: extra.lastModified } : {}),
|
|
104
|
+
...(extra.changeFrequency ? { changeFrequency: extra.changeFrequency } : {}),
|
|
105
|
+
...(extra.priority === undefined ? {} : { priority: extra.priority }),
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
const root = resolveSeoUrl('/', urlOpts);
|
|
109
|
+
return dedupeSitemapItems(items).sort((a, b) => a.url === root ? -1 : b.url === root ? 1 : a.url.localeCompare(b.url));
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Resolve the path an entry is advertised at, applying the caller's `pathFor` override.
|
|
113
|
+
*
|
|
114
|
+
* `null`/`undefined` mean "no opinion" and keep the entry's own `urlPath` — see the `pathFor`
|
|
115
|
+
* doc for why that is not "drop it".
|
|
116
|
+
*
|
|
117
|
+
* Two shapes are rejected rather than passed through, because each produces a WRONG SITEMAP THAT
|
|
118
|
+
* SHIPS GREEN — the failure mode every other guard in this file exists to convert into a red
|
|
119
|
+
* build. (A third, the WHATWG-backslash spellings like `/\evil.com/x`, is not thrown but
|
|
120
|
+
* neutralized downstream by `resolveSeoUrl`'s `neutralizeImplicitOffOrigin`.)
|
|
121
|
+
*
|
|
122
|
+
* - **Empty or whitespace-only.** `resolveSeoUrl('')` resolves to the site root, so an empty
|
|
123
|
+
* return would quietly advertise this entry at `/` and collide with whatever really lives there.
|
|
124
|
+
* - **Absolute (scheme-qualified or protocol-relative).** `resolveSeoUrl` passes both through
|
|
125
|
+
* verbatim, by design — for `extraUrls`, where an absolute URL is explicitly allowed. Here it is
|
|
126
|
+
* not: a protocol-relative `//host/x` lands in the sitemap as a NON-absolute `<loc>`, the exact
|
|
127
|
+
* invalidity `generateContentSitemap`'s `siteUrl` guard exists to prevent, and search engines
|
|
128
|
+
* reject the whole file for it. Refused whatever the origin — including one matching `siteUrl` —
|
|
129
|
+
* so the rule is "return a site-relative path" with no host comparison to get subtly wrong.
|
|
130
|
+
*
|
|
131
|
+
* The returned path is TRIMMED. Surrounding whitespace is never intended and survives into the
|
|
132
|
+
* URL otherwise (`' /blog'` → `<siteUrl>/ /blog`) — which this function would previously detect
|
|
133
|
+
* while checking for emptiness and then hand back untrimmed anyway.
|
|
134
|
+
*/
|
|
135
|
+
function resolveEntrySitemapPath(entry, pathFor) {
|
|
136
|
+
if (!pathFor)
|
|
137
|
+
return entry.urlPath;
|
|
138
|
+
const override = pathFor(entry);
|
|
139
|
+
if (override === null || override === undefined)
|
|
140
|
+
return entry.urlPath;
|
|
141
|
+
const trimmed = override.trim();
|
|
142
|
+
const where = `the ${JSON.stringify(entry.entryType)} entry at ${JSON.stringify(entry.urlPath)}`;
|
|
143
|
+
if (trimmed === '') {
|
|
144
|
+
throw new Error(`CanopyCMS: generateContentSitemap's pathFor returned an empty path for ${where}. An empty ` +
|
|
145
|
+
'path resolves to the site root, so honouring it would advertise this entry at "/" and ' +
|
|
146
|
+
"collide with whatever really lives there. Return null to keep the entry's own urlPath.");
|
|
147
|
+
}
|
|
148
|
+
if (isAbsoluteUrl(trimmed)) {
|
|
149
|
+
throw new Error(`CanopyCMS: generateContentSitemap's pathFor returned an absolute URL ` +
|
|
150
|
+
`(${JSON.stringify(trimmed)}) for ${where}. Return a site-relative path instead — the ` +
|
|
151
|
+
'site origin is applied for you. Absolute returns are refused whatever the origin, rather ' +
|
|
152
|
+
'than only off-origin ones, so there is one rule to remember and no host comparison to get ' +
|
|
153
|
+
'subtly wrong; a protocol-relative value (`//host/x`) is the reason it matters, since that ' +
|
|
154
|
+
'ships as a non-absolute <loc> and invalidates the entire sitemap. Use extraUrls to list a ' +
|
|
155
|
+
'URL on another origin.');
|
|
156
|
+
}
|
|
157
|
+
return trimmed;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Drop duplicate `<loc>` entries, keeping the first occurrence and warning about each collision.
|
|
161
|
+
*
|
|
162
|
+
* A duplicate URL isn't fatal to a crawler, but it usually means two URLs are unintentionally
|
|
163
|
+
* sharing one `<loc>` — an index entry collapsing onto a sibling's path, two `urlPath`s that only
|
|
164
|
+
* differ by case (`urlPath` is lowercased — see `content-listing.ts`), an `extraUrls` path
|
|
165
|
+
* repeating an entry's URL, or a `pathFor` that rewrote two entries onto the same path. Warning
|
|
166
|
+
* rather than silently deduping turns that into a build-time signal an adopter can act on instead
|
|
167
|
+
* of a sitemap that just quietly has fewer URLs than expected.
|
|
168
|
+
*
|
|
169
|
+
* Still needed alongside `assertNoDuplicateUrlPaths` (canopycms `static/index.ts`), which fails a
|
|
170
|
+
* production build on the entry-vs-entry case before generation ever reaches here. This covers the
|
|
171
|
+
* three cases that guard cannot: a collision involving an `extraUrls` path, which is supplied here
|
|
172
|
+
* and never appears in the content enumeration; a collision created by `pathFor`, which rewrites
|
|
173
|
+
* URLs after that guard has already run on the raw listing; and any call outside build mode, where
|
|
174
|
+
* that guard is deliberately silent.
|
|
175
|
+
*/
|
|
176
|
+
function dedupeSitemapItems(items) {
|
|
177
|
+
const seen = new Set();
|
|
178
|
+
const result = [];
|
|
179
|
+
for (const item of items) {
|
|
180
|
+
if (seen.has(item.url)) {
|
|
181
|
+
console.warn(`CanopyCMS: generateContentSitemap found more than one entry resolving to the same sitemap ` +
|
|
182
|
+
`URL ${JSON.stringify(item.url)}. Keeping the first and dropping the rest — this usually means ` +
|
|
183
|
+
'two entries, an entry and an extraUrls path, or a pathFor override are unintentionally ' +
|
|
184
|
+
'sharing one URL.');
|
|
185
|
+
continue;
|
|
186
|
+
}
|
|
187
|
+
seen.add(item.url);
|
|
188
|
+
result.push(item);
|
|
189
|
+
}
|
|
190
|
+
return result;
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Map an entry's SEO fields onto a Next `Metadata` object.
|
|
194
|
+
*
|
|
195
|
+
* Title and description follow ONE convention everywhere: the entry's meta field, else the
|
|
196
|
+
* fallback you pass, else unset (so the root layout's default applies). An empty CMS field counts
|
|
197
|
+
* as unset — see `extractSeoFields`.
|
|
198
|
+
*
|
|
199
|
+
* `noindex` goes through the same core predicate the sitemap uses, so a page marked noindex is
|
|
200
|
+
* suppressed in both surfaces or neither.
|
|
201
|
+
*
|
|
202
|
+
* @example
|
|
203
|
+
* export async function generateMetadata({ params }): Promise<Metadata> {
|
|
204
|
+
* const { slug } = await params
|
|
205
|
+
* const result = await readByUrlPath(`/posts/${slug}`)
|
|
206
|
+
* return entryToMetadata(result?.data, { path: `/posts/${slug}`, fallbackTitle: result?.data.title })
|
|
207
|
+
* }
|
|
208
|
+
*/
|
|
209
|
+
export function entryToMetadata(entryData, opts = {}) {
|
|
210
|
+
const seo = extractSeoFields(entryData, opts);
|
|
211
|
+
const urlOpts = { siteUrl: opts.siteUrl, trailingSlash: opts.trailingSlash };
|
|
212
|
+
// The entry's own canonical wins over the route path; an absolute one passes through verbatim
|
|
213
|
+
// (see resolveSeoUrl — the absolute check runs before any normalization, which is a fixed bug).
|
|
214
|
+
const canonicalSource = seo.canonical ?? opts.path;
|
|
215
|
+
const canonical = canonicalSource ? resolveSeoUrl(canonicalSource, urlOpts) : undefined;
|
|
216
|
+
// Images are files, never directory-style URLs: never append a trailing slash to one.
|
|
217
|
+
const ogImage = seo.ogImage ? resolveSeoUrl(seo.ogImage, { siteUrl: opts.siteUrl }) : undefined;
|
|
218
|
+
// og:title falls back to the site name so a page that inherits the layout title still emits a
|
|
219
|
+
// usable card — Next REPLACES `openGraph` wholesale rather than deep-merging it.
|
|
220
|
+
const socialTitle = seo.title ?? opts.siteName;
|
|
221
|
+
const ogType = seo.ogType ?? opts.defaultOgType ?? 'website';
|
|
222
|
+
const openGraphBase = {
|
|
223
|
+
...(socialTitle ? { title: socialTitle } : {}),
|
|
224
|
+
...(seo.description ? { description: seo.description } : {}),
|
|
225
|
+
...(canonical ? { url: canonical } : {}),
|
|
226
|
+
...(opts.siteName ? { siteName: opts.siteName } : {}),
|
|
227
|
+
...(ogImage ? { images: [{ url: ogImage }] } : {}),
|
|
228
|
+
};
|
|
229
|
+
const metadata = {
|
|
230
|
+
...(canonical ? { alternates: { canonical } } : {}),
|
|
231
|
+
// Spelled out per branch rather than cast: Next's OpenGraph metadata is a discriminated
|
|
232
|
+
// union on `type`.
|
|
233
|
+
openGraph: ogType === 'article'
|
|
234
|
+
? { ...openGraphBase, type: 'article' }
|
|
235
|
+
: ogType === 'profile'
|
|
236
|
+
? { ...openGraphBase, type: 'profile' }
|
|
237
|
+
: { ...openGraphBase, type: 'website' },
|
|
238
|
+
twitter: {
|
|
239
|
+
card: seo.twitterCard ?? 'summary_large_image',
|
|
240
|
+
...(socialTitle ? { title: socialTitle } : {}),
|
|
241
|
+
...(seo.description ? { description: seo.description } : {}),
|
|
242
|
+
...(ogImage ? { images: [ogImage] } : {}),
|
|
243
|
+
},
|
|
244
|
+
};
|
|
245
|
+
if (opts.titleTemplate) {
|
|
246
|
+
metadata.title = { template: opts.titleTemplate, default: seo.title ?? opts.siteName ?? '' };
|
|
247
|
+
}
|
|
248
|
+
else if (seo.title) {
|
|
249
|
+
metadata.title = seo.title;
|
|
250
|
+
}
|
|
251
|
+
if (seo.description)
|
|
252
|
+
metadata.description = seo.description;
|
|
253
|
+
// Same predicate as the sitemap's exclusion — these two must never be derived separately.
|
|
254
|
+
if (isNoindexEntry(entryData, opts))
|
|
255
|
+
metadata.robots = { index: false, follow: false };
|
|
256
|
+
return metadata;
|
|
29
257
|
}
|
|
30
|
-
//# sourceMappingURL=static.js.map
|
package/dist/test-utils.d.ts
CHANGED
|
@@ -9,4 +9,3 @@ export declare const createMockAuthPlugin: (user?: AuthenticatedUser) => AuthPlu
|
|
|
9
9
|
* Create a mock AuthPlugin that rejects all authentication.
|
|
10
10
|
*/
|
|
11
11
|
export declare const createRejectingAuthPlugin: (error?: string) => AuthPlugin;
|
|
12
|
-
//# sourceMappingURL=test-utils.d.ts.map
|
package/dist/test-utils.js
CHANGED
package/dist/with-canopy.d.ts
CHANGED
package/dist/with-canopy.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "canopycms-next",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.64",
|
|
4
4
|
"description": "Next.js adapter for CanopyCMS",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"peerDependencies": {
|
|
37
37
|
"next": "^13.5.7 || ^14.2.25 || ^15.5.21 || >=16.0.0 <16.2.0 || >=16.3.0 <17.0.0",
|
|
38
38
|
"react": "^18.0.0 || ^19.0.0",
|
|
39
|
-
"canopycms": "0.0.
|
|
39
|
+
"canopycms": "0.0.64"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@types/node": "^22.9.0",
|
|
@@ -46,10 +46,10 @@
|
|
|
46
46
|
"react": "^18.3.1",
|
|
47
47
|
"typescript": "^5.6.3",
|
|
48
48
|
"vitest": "^4.1.0",
|
|
49
|
-
"canopycms": "0.0.
|
|
49
|
+
"canopycms": "0.0.64"
|
|
50
50
|
},
|
|
51
51
|
"scripts": {
|
|
52
|
-
"build": "tsc -p tsconfig.build.json && esbuild src/config.ts --bundle --platform=node --packages=external --external:next --format=cjs --outfile=dist/config.cjs && esbuild src/config.ts --bundle --platform=node --packages=external --external:next --format=esm --outfile=dist/config.mjs",
|
|
52
|
+
"build": "rm -rf dist && tsc -p tsconfig.build.json && node ../../scripts/add-js-extensions.mjs dist && esbuild src/config.ts --bundle --platform=node --packages=external --external:next --format=cjs --outfile=dist/config.cjs && esbuild src/config.ts --bundle --platform=node --packages=external --external:next --format=esm --outfile=dist/config.mjs",
|
|
53
53
|
"lint": "eslint src/",
|
|
54
54
|
"test": "vitest run --reporter=dot",
|
|
55
55
|
"typecheck": "tsc --noEmit"
|
package/dist/adapter.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAEA,OAAO,EAIL,KAAK,oBAAoB,EACzB,KAAK,aAAa,EAEnB,MAAM,gBAAgB,CAAA;AAGvB;;;GAGG;AACH,MAAM,MAAM,iBAAiB,GAAG,oBAAoB,CAAA;AAEpD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,GAAG,aAAa,CA0B3D;AAkDD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,eAAO,MAAM,2BAA2B,GAAI,SAAS,iBAAiB,MAIlE,KAAK,OAAO,EACZ,MAAM;IACJ,MAAM,CAAC,EACH,OAAO,CAAC;QAAE,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC,GACzD;QAAE,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAA;CACrD,KACA,OAAO,CAAC,QAAQ,CAoBpB,CAAA"}
|
package/dist/adapter.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"adapter.js","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"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"}
|
package/dist/client.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;AAEhF;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,oBAAoB,GAC/B,QAAQ,kBAAkB,EAC1B,kBAAkB,oBAAoB,kDAwBvC,CAAA"}
|
package/dist/client.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAChC,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAGnD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAClC,MAA0B,EAC1B,eAAsC,EACtC,EAAE;IACF,MAAM,QAAQ,GAAG,gBAAgB,CAAC,MAAM,EAAE,eAAe,CAAC,CAAA;IAE1D,8EAA8E;IAC9E,0EAA0E;IAC1E,+EAA+E;IAC/E,4EAA4E;IAC5E,SAAS,sBAAsB;QAC7B,MAAM,eAAe,GAAG,eAAe,EAAE,CAAA;QACzC,MAAM,YAAY,GAAG;YACnB,MAAM,EAAE,eAAe,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,SAAS;YAClD,KAAK,EAAE,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,SAAS;SACjD,CAAA;QACD,OAAO,KAAC,QAAQ,IAAC,YAAY,EAAE,YAAY,GAAI,CAAA;IACjD,CAAC;IAED,OAAO,SAAS,cAAc;QAC5B,OAAO,CACL,KAAC,QAAQ,IAAC,QAAQ,EAAE,IAAI,YACtB,KAAC,sBAAsB,KAAG,GACjB,CACZ,CAAA;IACH,CAAC,CAAA;AACH,CAAC,CAAA"}
|
package/dist/client.test.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"client.test.d.ts","sourceRoot":"","sources":["../src/client.test.tsx"],"names":[],"mappings":""}
|
package/dist/client.test.js
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it, vi } from 'vitest';
|
|
2
|
-
// Mocked so this stays a node-environment test: the factory under test calls
|
|
3
|
-
// CanopyEditorPage at CALL time (not render time), so asserting what it was
|
|
4
|
-
// handed needs no DOM, no jsdom and no testing-library.
|
|
5
|
-
const canopyEditorPage = vi.fn(() => () => null);
|
|
6
|
-
vi.mock('canopycms/client', () => ({
|
|
7
|
-
CanopyEditorPage: (...args) => canopyEditorPage(...args),
|
|
8
|
-
}));
|
|
9
|
-
vi.mock('next/navigation', () => ({ useSearchParams: () => new URLSearchParams() }));
|
|
10
|
-
const { NextCanopyEditorPage } = await import('./client');
|
|
11
|
-
const config = { apiBase: '/api/canopycms' };
|
|
12
|
-
describe('NextCanopyEditorPage', () => {
|
|
13
|
-
it('forwards customRenderers to CanopyEditorPage', () => {
|
|
14
|
-
// Next is the primary target, so this wrapper is the entrypoint adopters
|
|
15
|
-
// import. Accepting `customRenderers` only on the core CanopyEditorPage
|
|
16
|
-
// left the extension point unreachable from the path every adopter uses
|
|
17
|
-
// - and silently, since an ignored extra argument is not a type error at
|
|
18
|
-
// the call site.
|
|
19
|
-
const customRenderers = { number: () => null };
|
|
20
|
-
NextCanopyEditorPage(config, customRenderers);
|
|
21
|
-
expect(canopyEditorPage).toHaveBeenCalledWith(config, customRenderers);
|
|
22
|
-
});
|
|
23
|
-
it('still works with no customRenderers (the scaffolded call shape)', () => {
|
|
24
|
-
canopyEditorPage.mockClear();
|
|
25
|
-
NextCanopyEditorPage(config);
|
|
26
|
-
expect(canopyEditorPage).toHaveBeenCalledWith(config, undefined);
|
|
27
|
-
});
|
|
28
|
-
});
|
|
29
|
-
//# sourceMappingURL=client.test.js.map
|
package/dist/client.test.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"client.test.js","sourceRoot":"","sources":["../src/client.test.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AAEjD,6EAA6E;AAC7E,4EAA4E;AAC5E,wDAAwD;AACxD,MAAM,gBAAgB,GAAG,EAAE,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAA;AAChD,EAAE,CAAC,IAAI,CAAC,kBAAkB,EAAE,GAAG,EAAE,CAAC,CAAC;IACjC,gBAAgB,EAAE,CAAC,GAAG,IAAe,EAAE,EAAE,CAAC,gBAAgB,CAAC,GAAI,IAAW,CAAC;CAC5E,CAAC,CAAC,CAAA;AACH,EAAE,CAAC,IAAI,CAAC,iBAAiB,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,eAAe,EAAE,GAAG,EAAE,CAAC,IAAI,eAAe,EAAE,EAAE,CAAC,CAAC,CAAA;AAEpF,MAAM,EAAE,oBAAoB,EAAE,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,CAAA;AAEzD,MAAM,MAAM,GAAG,EAAE,OAAO,EAAE,gBAAgB,EAAW,CAAA;AAErD,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;IACpC,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACtD,yEAAyE;QACzE,wEAAwE;QACxE,wEAAwE;QACxE,yEAAyE;QACzE,iBAAiB;QACjB,MAAM,eAAe,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,IAAI,EAAE,CAAA;QAE9C,oBAAoB,CAAC,MAAM,EAAE,eAAe,CAAC,CAAA;QAE7C,MAAM,CAAC,gBAAgB,CAAC,CAAC,oBAAoB,CAAC,MAAM,EAAE,eAAe,CAAC,CAAA;IACxE,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,iEAAiE,EAAE,GAAG,EAAE;QACzE,gBAAgB,CAAC,SAAS,EAAE,CAAA;QAE5B,oBAAoB,CAAC,MAAM,CAAC,CAAA;QAE5B,MAAM,CAAC,gBAAgB,CAAC,CAAC,oBAAoB,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;IAClE,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
|
package/dist/config.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,KAAK,iBAAiB,EAAE,MAAM,eAAe,CAAA"}
|
package/dist/config.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAA0B,MAAM,eAAe,CAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"context-wrapper.d.ts","sourceRoot":"","sources":["../src/context-wrapper.ts"],"names":[],"mappings":"AAGA,OAAO,EAIL,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACvB,KAAK,cAAc,EAWpB,MAAM,kBAAkB,CAAA;AACzB,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAc,WAAW,EAAE,MAAM,WAAW,CAAA;AAGlF,OAAO,EAAE,2BAA2B,EAAE,MAAM,WAAW,CAAA;AACvD,OAAO,EAAuB,KAAK,kCAAkC,EAAE,MAAM,UAAU,CAAA;AAiCvF,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,YAAY,CAAA;IACpB,mGAAmG;IACnG,UAAU,CAAC,EAAE,UAAU,CAAA;IACvB,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,WAAW,EAAE,CAAC,CAAA;CAC5D;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,kBAAkB,EAC5B,MAAM,EAAE,YAAY,GACnB,kBAAkB,CA4CpB;AAED,MAAM,WAAW,uBAAuB;IACtC,8GAA8G;IAC9G,SAAS,EAAE,MAAM,OAAO,CAAC,aAAa,CAAC,CAAA;IACvC;;;;;;;;;;;;;OAaG;IACH,iBAAiB,EAAE,MAAM,OAAO,CAAC,kBAAkB,CAAC,CAAA;IACpD;;;;;;;OAOG;IACH,aAAa,EAAE,aAAa,CAAC,eAAe,CAAC,CAAA;IAC7C,kHAAkH;IAClH,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;IAC3B;;;;;OAKG;IACH,2BAA2B,EAAE,CAC3B,OAAO,CAAC,EAAE,kCAAkC,KACzC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC,CAAC,CAAA;IACtD,kCAAkC;IAClC,OAAO,EAAE,UAAU,CAAC,OAAO,2BAA2B,CAAC,CAAA;IACvD,mDAAmD;IACnD,QAAQ,EAAE,cAAc,CAAA;CACzB;AAED;;;;;;;;GAQG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,uBAAuB,CAAC,CAkLlC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"context-wrapper.js","sourceRoot":"","sources":["../src/context-wrapper.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,2BAA2B,EAAE,eAAe,EAAE,KAAK,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAEhG,OAAO,EACL,uBAAuB,EACvB,KAAK,iBAAiB,EACtB,KAAK,uBAAuB,GAC7B,MAAM,mBAAmB,CAAA;AAE1B,OAAO,EAAE,mBAAmB,EAAE,KAAK,kCAAkC,EAAE,MAAM,UAAU,CAAA;AAEvF,OAAO,EAAE,oBAAoB,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAA"}
|
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,2BAA2B,EAAE,eAAe,EAA0B,MAAM,WAAW,CAAA;AAEhG,OAAO,EACL,uBAAuB,GAGxB,MAAM,mBAAmB,CAAA;AAE1B,OAAO,EAAE,mBAAmB,EAA2C,MAAM,UAAU,CAAA;AAEvF,OAAO,EAAE,oBAAoB,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAA"}
|
package/dist/static.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"static.d.ts","sourceRoot":"","sources":["../src/static.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,kBAAkB,EACvB,KAAK,yBAAyB,EAC/B,MAAM,kBAAkB,CAAA;AAEzB;;;;;;GAMG;AAEH,MAAM,WAAW,kCAAmC,SAAQ,yBAAyB;IACnF,wCAAwC;IACxC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;OAIG;IACH,KAAK,CAAC,EAAE,WAAW,GAAG,QAAQ,CAAA;IAC9B;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,IAAI,CAAC,kBAAkB,EAAE,aAAa,CAAC,EACjD,OAAO,GAAE,kCAAuC,GAC/C,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC,CAAC,CAmBnD"}
|
package/dist/static.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"static.js","sourceRoot":"","sources":["../src/static.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,GAGnB,MAAM,kBAAkB,CAAA;AA4BzB;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,QAAiD,EACjD,UAA8C,EAAE;IAEhD,MAAM,EAAE,SAAS,GAAG,MAAM,EAAE,KAAK,GAAG,WAAW,EAAE,QAAQ,EAAE,GAAG,cAAc,EAAE,GAAG,OAAO,CAAA;IACxF,IAAI,OAAO,GAAG,MAAM,kBAAkB,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAA;IAEhE,IAAI,QAAQ,EAAE,CAAC;QACb,kGAAkG;QAClG,wFAAwF;QACxF,MAAM,MAAM,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAA;QACxF,OAAO,GAAG,OAAO;aACd,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,KAAK,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,MAAM,GAAG,CAAC,CAAC;aACrF,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;YACb,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,KAAK,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;YAClF,OAAO,EAAE,GAAG,KAAK,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAA;QAC1D,CAAC,CAAC,CAAA;IACN,CAAC;IAED,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAC3B,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,SAAS,CAAC,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,SAAS,CAAC,EAAE,KAAK,CAAC,QAAQ,EAAE,CACnF,CAAA;AACH,CAAC"}
|
package/dist/test-utils.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"test-utils.d.ts","sourceRoot":"","sources":["../src/test-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAChD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAIlD;;;GAGG;AACH,eAAO,MAAM,oBAAoB,GAC/B,OAAM,iBAIL,KACA,UAeD,CAAA;AAEF;;GAEG;AACH,eAAO,MAAM,yBAAyB,GAAI,cAAsB,KAAG,UAMjE,CAAA"}
|
package/dist/test-utils.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"test-utils.js","sourceRoot":"","sources":["../src/test-utils.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,GAAG,QAAQ,CAAA;AAEvB;;;GAGG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAClC,OAA0B;IACxB,IAAI,EAAE,eAAe;IACrB,MAAM,EAAE,WAAW;IACnB,MAAM,EAAE,CAAC,MAAM,CAAC;CACjB,EACW,EAAE,CAAC,CAAC;IAChB,YAAY,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;QACzB,OAAO,EAAE,IAAI;QACb,IAAI,EAAE;YACJ,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,cAAc,EAAE,IAAI,CAAC,MAAM;SAC5B;KACF,CAAC;IACF,WAAW,EAAE,KAAK,IAAI,EAAE,CAAC,EAAE;IAC3B,eAAe,EAAE,KAAK,IAAI,EAAE,CAAC,IAAI;IACjC,gBAAgB,EAAE,KAAK,IAAI,EAAE,CAAC,IAAI;IAClC,UAAU,EAAE,KAAK,IAAI,EAAE,CAAC,EAAE;CAC3B,CAAC,CAAA;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,KAAK,GAAG,cAAc,EAAc,EAAE,CAAC,CAAC;IAChF,YAAY,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;IACrD,WAAW,EAAE,KAAK,IAAI,EAAE,CAAC,EAAE;IAC3B,eAAe,EAAE,KAAK,IAAI,EAAE,CAAC,IAAI;IACjC,gBAAgB,EAAE,KAAK,IAAI,EAAE,CAAC,IAAI;IAClC,UAAU,EAAE,KAAK,IAAI,EAAE,CAAC,EAAE;CAC3B,CAAC,CAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"with-canopy.d.ts","sourceRoot":"","sources":["../src/with-canopy.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,MAAM,CAAA;AAoGtC,MAAM,WAAW,iBAAiB;IAChC,mEAAmE;IACnE,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;IACnB;;;;;;;;;;;;;;;;OAgBG;IACH,WAAW,CAAC,EAAE,OAAO,CAAA;CACtB;AAyBD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,wBAAgB,UAAU,CACxB,UAAU,GAAE,UAAe,EAC3B,OAAO,GAAE,iBAAsB,GAC9B,UAAU,CA2EZ"}
|
package/dist/with-canopy.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"with-canopy.js","sourceRoot":"","sources":["../src/with-canopy.ts"],"names":[],"mappings":"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"}
|