canopycms-next 0.0.38 → 0.0.40

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.
@@ -1,29 +1,67 @@
1
1
  import { type CanopyContext, type CanopyBuildContext, type CanopyServices } from 'canopycms/server';
2
2
  import type { CanopyConfig, AuthPlugin, FieldConfig } from 'canopycms';
3
3
  import { createCanopyCatchAllHandler } from './adapter';
4
+ import { type GenerateContentStaticParamsOptions } from './static';
4
5
  export interface NextCanopyOptions {
5
6
  config: CanopyConfig;
6
7
  /** Auth plugin for user authentication. Optional for static deployments (deployedAs: 'static'). */
7
8
  authPlugin?: AuthPlugin;
8
9
  entrySchemaRegistry: Record<string, readonly FieldConfig[]>;
9
10
  }
11
+ /**
12
+ * Wrap a build context so its operations throw if misused at request time on a production server.
13
+ *
14
+ * The build context runs as a synthetic admin and bypasses all branch/path ACLs. At **prod-server
15
+ * request time** there is never a legitimate reason to use it — a real user is on the other end, so
16
+ * content must be read through the request-scoped, ACL-enforcing getCanopy() (or the phase-selecting
17
+ * read/readByUrlPath, which routes to it at request time). So the guard fires for
18
+ * `mode === 'prod' && deployedAs === 'server' && !isBuildMode()` and fails closed (throws) rather than
19
+ * silently leaking protected content.
20
+ *
21
+ * Why not also in dev: Next invokes legitimate static-generation hooks (generateStaticParams,
22
+ * generateMetadata) in `next dev` with the same `!isBuildMode()` signature as the footgun, and there
23
+ * is no reliable way to tell them apart — a dev guard would false-positive on idiomatic code. In prod
24
+ * that ambiguity is gone (generateStaticParams is build-only; request-time build-context use is the
25
+ * footgun). Why not on `static` deployments: they skip ACLs everywhere by design, so there's nothing
26
+ * to leak. `CANOPY_BUILD_MODE=true` marks non-Next static generation as build phase.
27
+ */
28
+ export declare function guardBuildContext(buildCtx: CanopyBuildContext, config: CanopyConfig): CanopyBuildContext;
10
29
  export interface NextCanopyContextResult {
11
30
  /** Request-scoped context. Uses headers() + React cache(). Call from server components and route handlers. */
12
31
  getCanopy: () => Promise<CanopyContext>;
13
32
  /**
14
33
  * Build-time context. Uses STATIC_DEPLOY_USER (full admin, no auth), no request scope needed.
15
- * Safe to call from generateStaticParams, generateMetadata, and other non-request-scoped contexts.
34
+ * Safe to call from generateStaticParams, generateMetadata, sitemap, and build-time page rendering.
16
35
  * Memoized for the process lifetime — multiple calls return the same context.
17
36
  *
18
- * Returns a narrower type than getCanopy() only buildContentTree and listEntries are
19
- * available. read/readByUrlPath are excluded because build-time code should not perform
20
- * per-user content reads.
37
+ * Returns a narrower type than getCanopy() (no `user`) but includes read/readByUrlPath so build-time
38
+ * code can resolve a single entry by path/URL without scanning the whole collection.
21
39
  *
22
- * **Security note:** This context bypasses all branch and path ACLs. It runs as a
23
- * synthetic admin user with unrestricted read access. Only use it in build-time
24
- * code paths that are not exposed to end users (e.g., static generation).
40
+ * **Security note:** This context bypasses all branch and path ACLs (synthetic admin, unrestricted
41
+ * read). It's an advanced escape hatch for ordinary page work prefer the phase-selecting
42
+ * `readByUrlPath`/`read` (content) and `generateContentStaticParams` (paths) below, which don't hand
43
+ * the admin context to your page modules. On a production `server` deployment its operations throw
44
+ * if invoked at request time (where getCanopy() would enforce ACLs).
25
45
  */
26
46
  getCanopyForBuild: () => Promise<CanopyBuildContext>;
47
+ /**
48
+ * Phase-selecting `readByUrlPath`. At build time (isBuildMode()) it reads filesystem-direct via the
49
+ * build context; at request time it uses the branch-aware, ACL-enforced runtime context (getCanopy()).
50
+ *
51
+ * This is the recommended way to resolve a page by URL in a `[...slug]`/`[slug]` route: correct in
52
+ * both phases by construction (working tree at build, branch-clone preview in dev), so page code
53
+ * never has to hand-pick the admin build context. Returns null for non-matching/invalid paths.
54
+ */
55
+ readByUrlPath: CanopyContext['readByUrlPath'];
56
+ /** Phase-selecting `read` (build context at build, runtime context at request) — counterpart to readByUrlPath. */
57
+ read: CanopyContext['read'];
58
+ /**
59
+ * Build the array Next's `generateStaticParams` expects from CanopyCMS content. Enumeration-only
60
+ * (reads the set of routable paths, never entry content) and closes over the build context, so your
61
+ * page module never imports the admin `getCanopyForBuild`. Use `{ rootPath, shape: 'single' }` for a
62
+ * `[slug]` route, or the default catch-all for `[...slug]`.
63
+ */
64
+ generateContentStaticParams: (options?: GenerateContentStaticParamsOptions) => Promise<Array<Record<string, string | string[]>>>;
27
65
  /** API catch-all route handler */
28
66
  handler: ReturnType<typeof createCanopyCatchAllHandler>;
29
67
  /** Underlying services (rarely needed directly) */
@@ -1 +1 @@
1
- {"version":3,"file":"context-wrapper.d.ts","sourceRoot":"","sources":["../src/context-wrapper.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACvB,KAAK,cAAc,EAMpB,MAAM,kBAAkB,CAAA;AACzB,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAc,WAAW,EAAE,MAAM,WAAW,CAAA;AAIlF,OAAO,EAAE,2BAA2B,EAAE,MAAM,WAAW,CAAA;AA2BvD,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,MAAM,WAAW,uBAAuB;IACtC,8GAA8G;IAC9G,SAAS,EAAE,MAAM,OAAO,CAAC,aAAa,CAAC,CAAA;IACvC;;;;;;;;;;;;OAYG;IACH,iBAAiB,EAAE,MAAM,OAAO,CAAC,kBAAkB,CAAC,CAAA;IACpD,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,CAwIlC"}
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,EAUpB,MAAM,kBAAkB,CAAA;AACzB,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAc,WAAW,EAAE,MAAM,WAAW,CAAA;AAIlF,OAAO,EAAE,2BAA2B,EAAE,MAAM,WAAW,CAAA;AACvD,OAAO,EAAuB,KAAK,kCAAkC,EAAE,MAAM,UAAU,CAAA;AA2BvF,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,CA0CpB;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,CA2KlC"}
@@ -1,10 +1,11 @@
1
1
  import path from 'node:path';
2
2
  import { cache } from 'react';
3
3
  import { headers } from 'next/headers';
4
- import { createCanopyContext, createCanopyServices, operatingStrategy, loadInternalGroups, loadBranchContext, STATIC_DEPLOY_USER, } from 'canopycms/server';
4
+ import { createCanopyContext, isBuildMode, startDevContentWatcher, createCanopyServices, operatingStrategy, loadInternalGroups, loadBranchContext, STATIC_DEPLOY_USER, } from 'canopycms/server';
5
5
  import { authResultToCanopyUser } from 'canopycms';
6
6
  import { CachingAuthPlugin, FileBasedAuthCache } from 'canopycms/auth/cache';
7
7
  import { createCanopyCatchAllHandler } from './adapter';
8
+ import { collectStaticParams } from './static';
8
9
  let warnedNoAdmins = false;
9
10
  let warnedStaticMode = false;
10
11
  /**
@@ -28,6 +29,52 @@ const staticDeployAuthPlugin = {
28
29
  return [];
29
30
  },
30
31
  };
32
+ /**
33
+ * Wrap a build context so its operations throw if misused at request time on a production server.
34
+ *
35
+ * The build context runs as a synthetic admin and bypasses all branch/path ACLs. At **prod-server
36
+ * request time** there is never a legitimate reason to use it — a real user is on the other end, so
37
+ * content must be read through the request-scoped, ACL-enforcing getCanopy() (or the phase-selecting
38
+ * read/readByUrlPath, which routes to it at request time). So the guard fires for
39
+ * `mode === 'prod' && deployedAs === 'server' && !isBuildMode()` and fails closed (throws) rather than
40
+ * silently leaking protected content.
41
+ *
42
+ * Why not also in dev: Next invokes legitimate static-generation hooks (generateStaticParams,
43
+ * generateMetadata) in `next dev` with the same `!isBuildMode()` signature as the footgun, and there
44
+ * is no reliable way to tell them apart — a dev guard would false-positive on idiomatic code. In prod
45
+ * that ambiguity is gone (generateStaticParams is build-only; request-time build-context use is the
46
+ * footgun). Why not on `static` deployments: they skip ACLs everywhere by design, so there's nothing
47
+ * to leak. `CANOPY_BUILD_MODE=true` marks non-Next static generation as build phase.
48
+ */
49
+ export function guardBuildContext(buildCtx, config) {
50
+ const assertBuildPhase = (method) => {
51
+ if (config.mode === 'prod' && config.deployedAs === 'server' && !isBuildMode()) {
52
+ throw new Error(`CanopyCMS: getCanopyForBuild().${method}() was called at request time on a production ` +
53
+ "'server' deployment. The build context bypasses all branch and path ACLs and must only be " +
54
+ 'used during static generation (next build / CANOPY_BUILD_MODE=true). Use the request-scoped ' +
55
+ 'getCanopy(), or the phase-selecting read()/readByUrlPath() from createNextCanopyContext.');
56
+ }
57
+ };
58
+ return {
59
+ services: buildCtx.services,
60
+ buildContentTree: (options) => {
61
+ assertBuildPhase('buildContentTree');
62
+ return buildCtx.buildContentTree(options);
63
+ },
64
+ listEntries: (options) => {
65
+ assertBuildPhase('listEntries');
66
+ return buildCtx.listEntries(options);
67
+ },
68
+ read: (input) => {
69
+ assertBuildPhase('read');
70
+ return buildCtx.read(input);
71
+ },
72
+ readByUrlPath: (urlPath, options) => {
73
+ assertBuildPhase('readByUrlPath');
74
+ return buildCtx.readByUrlPath(urlPath, options);
75
+ },
76
+ };
77
+ }
31
78
  /**
32
79
  * Create Next.js-specific wrapper around core context.
33
80
  * Adds React cache() for per-request memoization and API handler.
@@ -73,6 +120,11 @@ export async function createNextCanopyContext(options) {
73
120
  const services = await createCanopyServices(options.config, {
74
121
  entrySchemaRegistry: options.entrySchemaRegistry,
75
122
  });
123
+ // In dev, surface divergence between working-tree content and the served branch clone (warn-only).
124
+ // All logic lives in the core watcher; this is just the once-at-startup trigger (thin Next wiring).
125
+ if (options.config.mode === 'dev' && !isBuildMode()) {
126
+ startDevContentWatcher(services, { mode: options.config.dev?.contentSync });
127
+ }
76
128
  // User extractor: passes Next.js headers to auth plugin, loads internal groups, applies authorization
77
129
  const extractUser = async () => {
78
130
  const headersList = await headers();
@@ -119,11 +171,9 @@ export async function createNextCanopyContext(options) {
119
171
  if (!buildContextPromise) {
120
172
  buildContextPromise = buildContext
121
173
  .getContext()
122
- .then(({ buildContentTree, listEntries, services }) => ({
123
- buildContentTree,
124
- listEntries,
125
- services,
126
- }))
174
+ .then(({ buildContentTree, listEntries, read, readByUrlPath, services }) =>
175
+ // Guard so these reads throw if used at request time on a `server` deployment.
176
+ guardBuildContext({ buildContentTree, listEntries, read, readByUrlPath, services }, options.config))
127
177
  .catch((err) => {
128
178
  buildContextPromise = null;
129
179
  throw err;
@@ -131,6 +181,21 @@ export async function createNextCanopyContext(options) {
131
181
  }
132
182
  return buildContextPromise;
133
183
  };
184
+ // Phase-selecting helpers: build context during static generation, branch-aware runtime at request
185
+ // time. Lets page code resolve content without hand-picking the admin build context (see item #5).
186
+ const readByUrlPath = async (urlPath, opts) => {
187
+ const ctx = isBuildMode() ? await getCanopyForBuild() : await getCanopy();
188
+ return ctx.readByUrlPath(urlPath, opts);
189
+ };
190
+ const read = async (input) => {
191
+ const ctx = isBuildMode() ? await getCanopyForBuild() : await getCanopy();
192
+ return ctx.read(input);
193
+ };
194
+ // Enumeration-only static-params helper, bound to the (guarded) build context so page modules don't
195
+ // import the admin context just to list paths. generateStaticParams is build-only, so this is safe.
196
+ const generateContentStaticParams = async (options = {}) => {
197
+ return collectStaticParams(await getCanopyForBuild(), options);
198
+ };
134
199
  // Create API handler using same services
135
200
  const handler = createCanopyCatchAllHandler({
136
201
  ...options,
@@ -140,6 +205,9 @@ export async function createNextCanopyContext(options) {
140
205
  return {
141
206
  getCanopy,
142
207
  getCanopyForBuild,
208
+ readByUrlPath,
209
+ read,
210
+ generateContentStaticParams,
143
211
  handler,
144
212
  services,
145
213
  };
@@ -1 +1 @@
1
- {"version":3,"file":"context-wrapper.js","sourceRoot":"","sources":["../src/context-wrapper.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"context-wrapper.js","sourceRoot":"","sources":["../src/context-wrapper.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export { createCanopyCatchAllHandler, wrapNextRequest, type CanopyNextOptions } from './adapter';
2
2
  export { createNextCanopyContext, type NextCanopyOptions, type NextCanopyContextResult, } from './context-wrapper';
3
+ export { collectStaticParams, type GenerateContentStaticParamsOptions } from './static';
3
4
  export { createMockAuthPlugin, createRejectingAuthPlugin } from './test-utils';
4
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
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,oBAAoB,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAA"}
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 CHANGED
@@ -1,4 +1,5 @@
1
1
  export { createCanopyCatchAllHandler, wrapNextRequest } from './adapter';
2
2
  export { createNextCanopyContext, } from './context-wrapper';
3
+ export { collectStaticParams } from './static';
3
4
  export { createMockAuthPlugin, createRejectingAuthPlugin } from './test-utils';
4
5
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
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,oBAAoB,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAA"}
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"}
@@ -0,0 +1,39 @@
1
+ import { type CanopyBuildContext, type CollectStaticPathsOptions } from 'canopycms/server';
2
+ /**
3
+ * Next.js static-export helpers built on the framework-agnostic core in `canopycms/server`.
4
+ *
5
+ * Today this ships static-params generation. Sitemap and SEO-metadata helpers are tracked as
6
+ * follow-up work (see .claude/future-tasks/static-export-sitemap.md and
7
+ * .claude/future-tasks/static-export-seo-metadata.md).
8
+ */
9
+ export interface GenerateContentStaticParamsOptions extends CollectStaticPathsOptions {
10
+ /** Route param name. Default 'slug'. */
11
+ paramName?: string;
12
+ /**
13
+ * Route shape:
14
+ * - 'catch-all' (default) → `[...slug]` / `[[...slug]]`: param value is the URL `segments` array.
15
+ * - 'single' → `[slug]`: param value is the entry `slug` (pair with `rootPath` to scope a collection).
16
+ */
17
+ shape?: 'catch-all' | 'single';
18
+ /**
19
+ * For a catch-all route nested under a URL prefix (e.g. `app/docs/[[...slug]]`), set this to the
20
+ * route's base (e.g. `'/docs'`). Entries are scoped to that prefix and `segments` are made relative
21
+ * to it, so the params match the route. Without it, segments are the full URL path. Applies to
22
+ * catch-all shapes (it rewrites `segments`); it has no effect with `shape: 'single'`.
23
+ */
24
+ basePath?: string;
25
+ }
26
+ /**
27
+ * Shape CanopyCMS content paths into the array Next's `generateStaticParams` expects.
28
+ *
29
+ * This is an **enumeration-only** capability: it reads only the set of routable paths (via the build
30
+ * context's `listEntries`), never entry content, and `generateStaticParams` is build-only — so it
31
+ * cannot serve a user request. It takes a build context directly; prefer the bound
32
+ * `generateContentStaticParams` returned from `createNextCanopyContext`, which closes over the build
33
+ * context so your page modules never import the admin context.
34
+ *
35
+ * Note: a root index ('/') yields empty `segments` — keep it only for an optional catch-all
36
+ * `[[...slug]]`, otherwise exclude it via `options.filter` (e.g. `(e) => e.segments.length > 0`).
37
+ */
38
+ export declare function collectStaticParams(buildCtx: Pick<CanopyBuildContext, 'listEntries'>, options?: GenerateContentStaticParamsOptions): Promise<Array<Record<string, string | string[]>>>;
39
+ //# sourceMappingURL=static.d.ts.map
@@ -0,0 +1 @@
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 ADDED
@@ -0,0 +1,30 @@
1
+ import { collectStaticPaths, } from 'canopycms/server';
2
+ /**
3
+ * Shape CanopyCMS content paths into the array Next's `generateStaticParams` expects.
4
+ *
5
+ * This is an **enumeration-only** capability: it reads only the set of routable paths (via the build
6
+ * context's `listEntries`), never entry content, and `generateStaticParams` is build-only — so it
7
+ * cannot serve a user request. It takes a build context directly; prefer the bound
8
+ * `generateContentStaticParams` returned from `createNextCanopyContext`, which closes over the build
9
+ * context so your page modules never import the admin context.
10
+ *
11
+ * Note: a root index ('/') yields empty `segments` — keep it only for an optional catch-all
12
+ * `[[...slug]]`, otherwise exclude it via `options.filter` (e.g. `(e) => e.segments.length > 0`).
13
+ */
14
+ export async function collectStaticParams(buildCtx, options = {}) {
15
+ const { paramName = 'slug', shape = 'catch-all', basePath, ...collectOptions } = options;
16
+ let entries = await collectStaticPaths(buildCtx, collectOptions);
17
+ if (basePath) {
18
+ // Make segments relative to a nested route's base prefix (e.g. '/docs' for app/docs/[[...slug]]).
19
+ // urlPath is always lowercased (see content-listing), so lowercase the prefix to match.
20
+ const prefix = (basePath.endsWith('/') ? basePath.slice(0, -1) : basePath).toLowerCase();
21
+ entries = entries
22
+ .filter((entry) => entry.urlPath === prefix || entry.urlPath.startsWith(`${prefix}/`))
23
+ .map((entry) => {
24
+ const rel = entry.urlPath === prefix ? '' : entry.urlPath.slice(prefix.length + 1);
25
+ return { ...entry, segments: rel ? rel.split('/') : [] };
26
+ });
27
+ }
28
+ return entries.map((entry) => shape === 'single' ? { [paramName]: entry.slug } : { [paramName]: entry.segments });
29
+ }
30
+ //# sourceMappingURL=static.js.map
@@ -0,0 +1 @@
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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "canopycms-next",
3
- "version": "0.0.38",
3
+ "version": "0.0.40",
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.2.3 || ^16",
38
38
  "react": "^18.0.0 || ^19.0.0",
39
- "canopycms": "0.0.38"
39
+ "canopycms": "0.0.40"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@types/node": "^22.9.0",
@@ -46,7 +46,7 @@
46
46
  "react": "^18.3.1",
47
47
  "typescript": "^5.6.3",
48
48
  "vitest": "^1.6.0",
49
- "canopycms": "0.0.38"
49
+ "canopycms": "0.0.40"
50
50
  },
51
51
  "scripts": {
52
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",