create-ailk 0.10.0 → 0.11.1
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/README.md +7 -2
- package/dist/cli.js +5 -1
- package/dist/content-payloads.d.ts +37 -0
- package/dist/content-payloads.js +64 -0
- package/dist/lib/fetch-module.d.ts +3 -3
- package/dist/lib/fetch-module.js +11 -5
- package/dist/lib/fetch-template.d.ts +1 -1
- package/dist/lib/fetch-template.js +7 -4
- package/dist/lib/scaffold-render-sweep.d.ts +16 -0
- package/dist/lib/scaffold-render-sweep.js +52 -3
- package/dist/module-architecture.d.ts +9 -0
- package/dist/module-architecture.js +43 -12
- package/dist/parse-args.d.ts +2 -0
- package/dist/parse-args.js +7 -0
- package/dist/surfaces.js +2 -3
- package/package.json +3 -3
- package/site-templates/marketing-site-free/TEMPLATE-MANIFEST.md +4 -3
- package/site-templates/shapes/local-business-service/content/en/Service/first-job.mdx +8 -8
- package/site-templates/shapes/local-business-service/content/en/Service/second-job.mdx +8 -8
- package/site-templates/shapes/local-business-service/content/en/Service/third-job.mdx +8 -8
- package/site-templates/shapes/organization-service/content/en/Service/first-engagement.mdx +8 -8
- package/site-templates/shapes/organization-service/content/en/Service/second-engagement.mdx +8 -8
- package/site-templates/shapes/organization-service/content/en/Service/third-engagement.mdx +8 -8
- package/site-templates/shapes/person-service/content/en/Service/first-engagement.mdx +8 -8
- package/site-templates/shapes/person-service/content/en/Service/second-engagement.mdx +8 -8
- package/site-templates/shapes/person-service/content/en/Service/third-engagement.mdx +8 -8
- package/templates/.claude/settings.json +12 -0
- package/templates/.env.example +1 -5
- package/templates/CLAUDE.md +38 -22
- package/templates/README.md +12 -12
- package/templates/apps/api/jest.config.cjs +1 -0
- package/templates/apps/api/package.json +2 -1
- package/templates/apps/mcp/CLAUDE.md +23 -10
- package/templates/apps/mcp/__tests__/catalog-drift.test.ts +160 -17
- package/templates/apps/mcp/__tests__/index.test.ts +118 -1
- package/templates/apps/mcp/__tests__/lib/commerce-claim.test.ts +425 -5
- package/templates/apps/mcp/__tests__/module-exclusion.test.ts +67 -3
- package/templates/apps/mcp/__tests__/server.test.ts +162 -1
- package/templates/apps/mcp/package.json +1 -1
- package/templates/apps/mcp/src/index.ts +35 -3
- package/templates/apps/mcp/src/lib/commerce-claim.ts +193 -24
- package/templates/apps/mcp/src/server.ts +77 -5
- package/templates/apps/mcp/src/tools/purchase.ts +1 -1
- package/templates/apps/web/CLAUDE.md +1 -1
- package/templates/apps/web/app/.well-known/mcp.json/build-manifest.ts +15 -0
- package/templates/apps/web/app/.well-known/mcp.json/route.ts +10 -3
- package/templates/apps/web/app/[locale]/careers/[slug]/page.tsx +0 -10
- package/templates/apps/web/app/[locale]/case-studies/[slug]/page.tsx +0 -10
- package/templates/apps/web/app/[locale]/courses/[slug]/page.tsx +1 -14
- package/templates/apps/web/app/[locale]/events/[slug]/page.tsx +0 -10
- package/templates/apps/web/app/[locale]/features/[slug]/page.tsx +0 -10
- package/templates/apps/web/app/[locale]/for/[slug]/page.tsx +0 -10
- package/templates/apps/web/app/[locale]/how-to/[slug]/page.tsx +1 -14
- package/templates/apps/web/app/[locale]/integrations/[slug]/page.tsx +0 -10
- package/templates/apps/web/app/[locale]/partners/[slug]/page.tsx +0 -10
- package/templates/apps/web/app/[locale]/portfolio/[slug]/page.tsx +0 -10
- package/templates/apps/web/app/[locale]/products/[slug]/page.tsx +0 -10
- package/templates/apps/web/app/[locale]/projects/[slug]/page.tsx +1 -15
- package/templates/apps/web/app/[locale]/resources/[slug]/page.tsx +0 -10
- package/templates/apps/web/app/[locale]/services/[slug]/page.tsx +0 -10
- package/templates/apps/web/app/[locale]/software/[slug]/page.tsx +0 -10
- package/templates/apps/web/app/[locale]/tech-articles/[slug]/page.tsx +1 -14
- package/templates/apps/web/app/[locale]/thanks/[slug]/page.tsx +4 -16
- package/templates/apps/web/app/[locale]/vs/[slug]/__tests__/page.test.tsx +3 -15
- package/templates/apps/web/app/[locale]/vs/[slug]/page.tsx +0 -10
- package/templates/apps/web/app/[locale]/whitepapers/[slug]/page.tsx +1 -14
- package/templates/apps/web/src/lib/commerce-claim.ts +15 -6
- package/templates/content/_site.mdx +23 -4
- package/templates/database/CHANGELOG.md +7 -0
- package/templates/database/package.json +1 -1
- package/versions.json +34 -34
- package/templates/.claude/skills/README.md +0 -37
- package/templates/.claude/skills/add-auth/SKILL.md +0 -313
- package/templates/.claude/skills/add-auth/references/env-vars.md +0 -106
- package/templates/.claude/skills/add-auth/references/oauth-app-setup.md +0 -180
- package/templates/.claude/skills/add-page/SKILL.md +0 -260
- package/templates/.claude/skills/add-page/references/page-types.md +0 -123
- package/templates/.claude/skills/add-page/scripts/site-pages.mjs +0 -87
- package/templates/.claude/skills/add-page/templates/comparison-page.mdx.tmpl +0 -99
- package/templates/.claude/skills/add-page/templates/content.mdx.tmpl +0 -18
- package/templates/.claude/skills/add-page/templates/flow-landing-page.mdx.tmpl +0 -43
- package/templates/.claude/skills/add-page/templates/report-page.mdx.tmpl +0 -52
- package/templates/.claude/skills/add-page/templates/reports-list.mdx.tmpl +0 -38
- package/templates/.claude/skills/check-site/SKILL.md +0 -245
- package/templates/.claude/skills/check-site/references/common-errors.md +0 -116
- package/templates/.claude/skills/check-site/references/findings-glossary.md +0 -140
- package/templates/.claude/skills/check-site/references/severity-levels.md +0 -114
- package/templates/.claude/skills/fill-page/SKILL.md +0 -199
- package/templates/.claude/skills/fill-page/profiles/plumbing.yaml +0 -80
- package/templates/.claude/skills/fill-page/references/section-sources.md +0 -41
- package/templates/.claude/skills/setup-database/SKILL.md +0 -156
- package/templates/.claude/skills/setup-database/scripts/verify-inbox.ts +0 -154
- package/templates/.claude/skills/setup-deploy/SKILL.md +0 -312
- package/templates/.claude/skills/setup-deploy/references/runbook-template.md +0 -204
- package/templates/.claude/skills/setup-deploy/references/vercel-json-template.md +0 -98
- package/templates/.claude/skills/update-page/SKILL.md +0 -117
- package/templates/.claude/skills/update-page/scripts/update-page.ts +0 -640
- package/templates/.claude/skills/update-page/templates/redirects.mjs.tmpl +0 -31
- package/templates/.claude/skills/upgrade-plan/SKILL.md +0 -121
- package/templates/.claude/skills/upgrade-plan/references/options.md +0 -24
- package/templates/.claude/skills/upgrade-plan/scripts/upgrade-plan.ts +0 -527
- package/templates/apps/mcp/__tests__/lib/require-paid-tier.test.ts +0 -75
- package/templates/apps/mcp/src/lib/require-paid-tier.ts +0 -44
|
@@ -14,10 +14,13 @@
|
|
|
14
14
|
* endpoint when MCP_PUBLIC_HTTP_URL is configured.
|
|
15
15
|
* Issue #4157 — `name` resolves from SITE_NAME (env → _site.mdx → neutral
|
|
16
16
|
* default) instead of a hardcoded vendor-brand literal.
|
|
17
|
+
* Issue #7136 — the five `feature`-tagged tools are gated on the licence
|
|
18
|
+
* features the route passes in (`heldFeatures`), as registration is.
|
|
17
19
|
*/
|
|
18
20
|
|
|
19
21
|
import {
|
|
20
22
|
getMcpToolCatalog,
|
|
23
|
+
type McpCatalogOptions,
|
|
21
24
|
type McpToolCatalogEntry,
|
|
22
25
|
} from "@working-theory/metadata";
|
|
23
26
|
|
|
@@ -88,6 +91,16 @@ export interface BuildMcpManifestOptions {
|
|
|
88
91
|
* claim and passes it in. Omitted ⇒ false, the fail-closed default.
|
|
89
92
|
*/
|
|
90
93
|
commerceClaimed?: boolean;
|
|
94
|
+
/**
|
|
95
|
+
* The licence features this deployment holds (#7136). In refuse mode a
|
|
96
|
+
* `feature`-tagged tool is advertised only when its feature is held — the
|
|
97
|
+
* same gate the MCP server's registration applies. Injected, like
|
|
98
|
+
* `commerceClaimed`. Omitted ⇒ none, the fail-closed default.
|
|
99
|
+
*/
|
|
100
|
+
heldFeatures?: readonly string[];
|
|
101
|
+
/** Overrides `MCP_FEATURE_GATE_MODE` — a test seam; `route.ts` never
|
|
102
|
+
* passes it. */
|
|
103
|
+
featureGate?: McpCatalogOptions["featureGate"];
|
|
91
104
|
}
|
|
92
105
|
|
|
93
106
|
/** Path the MCP server is mounted at, relative to baseUrl. */
|
|
@@ -121,6 +134,8 @@ export function buildMcpManifest(opts: BuildMcpManifestOptions): McpManifest {
|
|
|
121
134
|
mcpEndpoint: `${opts.baseUrl}${MCP_ENDPOINT_PATH}`,
|
|
122
135
|
tools: getMcpToolCatalog({
|
|
123
136
|
addons: { commerce: opts.commerceClaimed === true },
|
|
137
|
+
features: opts.heldFeatures ?? [],
|
|
138
|
+
...(opts.featureGate ? { featureGate: opts.featureGate } : {}),
|
|
124
139
|
}),
|
|
125
140
|
transport: {
|
|
126
141
|
type: "http",
|
|
@@ -12,7 +12,9 @@
|
|
|
12
12
|
* the deployments whose MCP server registers it. Without that, a KEYED site
|
|
13
13
|
* would register `start_purchase` while hiding it from its own manifest —
|
|
14
14
|
* the surface disagreement `apps/mcp/__tests__/catalog-drift.test.ts` exists
|
|
15
|
-
* to make impossible.
|
|
15
|
+
* to make impossible. The same single read also yields the licence features
|
|
16
|
+
* the deployment holds (#7136), which gate the five `feature`-tagged tools
|
|
17
|
+
* here exactly as they gate registration on the MCP server.
|
|
16
18
|
*
|
|
17
19
|
* Mirrors /.well-known/ai-plugin.json conventions: Response.json with a
|
|
18
20
|
* conservative cache-control header.
|
|
@@ -23,7 +25,10 @@
|
|
|
23
25
|
*/
|
|
24
26
|
|
|
25
27
|
import packageJson from "../../../package.json";
|
|
26
|
-
import {
|
|
28
|
+
import {
|
|
29
|
+
COMMERCE_FEATURE,
|
|
30
|
+
resolveLicenceFeatures,
|
|
31
|
+
} from "../../../src/lib/commerce-claim";
|
|
27
32
|
import { resolveBaseUrl } from "../../../src/lib/routes";
|
|
28
33
|
|
|
29
34
|
import { buildMcpManifest } from "./build-manifest";
|
|
@@ -46,11 +51,13 @@ export async function GET(): Promise<Response> {
|
|
|
46
51
|
// (apps/mcp running in HTTP mode). When set, the manifest includes it
|
|
47
52
|
// as an additional transport descriptor for discovering agents.
|
|
48
53
|
const mcpHttpUrlEnv = process.env["MCP_PUBLIC_HTTP_URL"];
|
|
54
|
+
const heldFeatures = await resolveLicenceFeatures();
|
|
49
55
|
|
|
50
56
|
const manifest = buildMcpManifest({
|
|
51
57
|
baseUrl: resolveBaseUrl(),
|
|
52
58
|
ailkVersion: packageJson.version,
|
|
53
|
-
commerceClaimed:
|
|
59
|
+
commerceClaimed: heldFeatures.includes(COMMERCE_FEATURE),
|
|
60
|
+
heldFeatures,
|
|
54
61
|
// Spread conditional to satisfy exactOptionalPropertyTypes: omit the key
|
|
55
62
|
// entirely when the env var is not set rather than passing undefined.
|
|
56
63
|
...(mcpHttpUrlEnv ? { mcpHttpUrl: mcpHttpUrlEnv } : {}),
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
// Careers list at /careers links here; each job posting lives at /careers/<slug>.
|
|
4
4
|
import {
|
|
5
5
|
getMdxSource as defaultGetMdxSource,
|
|
6
|
-
getMdxSlugs,
|
|
7
6
|
renderPage,
|
|
8
7
|
renderPageMetadata,
|
|
9
8
|
} from "@working-theory/page-renderer";
|
|
@@ -23,15 +22,6 @@ export async function generateMetadata({
|
|
|
23
22
|
return renderPageMetadata({ type: "JobPosting", slug, locale });
|
|
24
23
|
}
|
|
25
24
|
|
|
26
|
-
export async function generateStaticParams({
|
|
27
|
-
params,
|
|
28
|
-
}: {
|
|
29
|
-
params: { locale: string };
|
|
30
|
-
}): Promise<{ slug: string }[]> {
|
|
31
|
-
const slugs = await getMdxSlugs("JobPosting", params.locale);
|
|
32
|
-
return slugs.map((slug: string) => ({ slug }));
|
|
33
|
-
}
|
|
34
|
-
|
|
35
25
|
export default async function Page({
|
|
36
26
|
params,
|
|
37
27
|
getMdxSource = defaultGetMdxSource,
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
// next-mdx-remote/rsc, and emits a JSON-LD <script>. Unknown slugs trigger 404.
|
|
3
3
|
import {
|
|
4
4
|
getMdxSource as defaultGetMdxSource,
|
|
5
|
-
getMdxSlugs,
|
|
6
5
|
renderPage,
|
|
7
6
|
renderPageMetadata,
|
|
8
7
|
} from "@working-theory/page-renderer";
|
|
@@ -22,15 +21,6 @@ export async function generateMetadata({
|
|
|
22
21
|
return renderPageMetadata({ type: "CaseStudy", slug, locale });
|
|
23
22
|
}
|
|
24
23
|
|
|
25
|
-
export async function generateStaticParams({
|
|
26
|
-
params,
|
|
27
|
-
}: {
|
|
28
|
-
params: { locale: string };
|
|
29
|
-
}): Promise<{ slug: string }[]> {
|
|
30
|
-
const slugs = await getMdxSlugs("CaseStudy", params.locale);
|
|
31
|
-
return slugs.map((slug: string) => ({ slug }));
|
|
32
|
-
}
|
|
33
|
-
|
|
34
24
|
export default async function Page({
|
|
35
25
|
params,
|
|
36
26
|
getMdxSource = defaultGetMdxSource,
|
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
// Course detail page. Reads the Course MDX for the given slug, renders via
|
|
2
2
|
// @working-theory/page-renderer, and emits a JSON-LD <script>. Unknown slugs trigger 404.
|
|
3
3
|
import type { getMdxSource as defaultGetMdxSource } from "@working-theory/page-renderer";
|
|
4
|
-
import {
|
|
5
|
-
getMdxSlugs,
|
|
6
|
-
renderPage,
|
|
7
|
-
renderPageMetadata,
|
|
8
|
-
} from "@working-theory/page-renderer";
|
|
4
|
+
import { renderPage, renderPageMetadata } from "@working-theory/page-renderer";
|
|
9
5
|
import type { Metadata } from "next";
|
|
10
6
|
import type { ReactElement } from "react";
|
|
11
7
|
|
|
@@ -21,15 +17,6 @@ export async function generateMetadata({
|
|
|
21
17
|
return renderPageMetadata({ type: "Course", slug, locale });
|
|
22
18
|
}
|
|
23
19
|
|
|
24
|
-
export async function generateStaticParams({
|
|
25
|
-
params,
|
|
26
|
-
}: {
|
|
27
|
-
params: { locale: string };
|
|
28
|
-
}): Promise<{ slug: string }[]> {
|
|
29
|
-
const slugs = await getMdxSlugs("Course", params.locale);
|
|
30
|
-
return slugs.map((slug) => ({ slug }));
|
|
31
|
-
}
|
|
32
|
-
|
|
33
20
|
export default async function Page({
|
|
34
21
|
params,
|
|
35
22
|
getMdxSource,
|
|
@@ -4,7 +4,6 @@ import {
|
|
|
4
4
|
renderPage,
|
|
5
5
|
renderPageMetadata,
|
|
6
6
|
getMdxSource as defaultGetMdxSource,
|
|
7
|
-
getMdxSlugs,
|
|
8
7
|
} from "@working-theory/page-renderer";
|
|
9
8
|
import type { Metadata } from "next";
|
|
10
9
|
import { notFound } from "next/navigation";
|
|
@@ -22,15 +21,6 @@ export async function generateMetadata({
|
|
|
22
21
|
return renderPageMetadata({ type: "Event", slug, locale });
|
|
23
22
|
}
|
|
24
23
|
|
|
25
|
-
export async function generateStaticParams({
|
|
26
|
-
params,
|
|
27
|
-
}: {
|
|
28
|
-
params: { locale: string };
|
|
29
|
-
}): Promise<{ slug: string }[]> {
|
|
30
|
-
const slugs = await getMdxSlugs("Event", params.locale);
|
|
31
|
-
return slugs.map((slug) => ({ slug }));
|
|
32
|
-
}
|
|
33
|
-
|
|
34
24
|
export default async function Page({
|
|
35
25
|
params,
|
|
36
26
|
getMdxSource = defaultGetMdxSource,
|
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
import type { getMdxSource as defaultGetMdxSource } from "@working-theory/page-renderer";
|
|
8
8
|
import {
|
|
9
9
|
getMdxSource as loadMdxSource,
|
|
10
|
-
getMdxSlugs,
|
|
11
10
|
renderPage,
|
|
12
11
|
renderPageMetadata,
|
|
13
12
|
} from "@working-theory/page-renderer";
|
|
@@ -26,15 +25,6 @@ export async function generateMetadata({
|
|
|
26
25
|
return renderPageMetadata({ type: "Feature", slug, locale });
|
|
27
26
|
}
|
|
28
27
|
|
|
29
|
-
export async function generateStaticParams({
|
|
30
|
-
params,
|
|
31
|
-
}: {
|
|
32
|
-
params: { locale: string };
|
|
33
|
-
}): Promise<{ slug: string }[]> {
|
|
34
|
-
const slugs = await getMdxSlugs("Feature", params.locale);
|
|
35
|
-
return slugs.map((slug) => ({ slug }));
|
|
36
|
-
}
|
|
37
|
-
|
|
38
28
|
export default async function Page({
|
|
39
29
|
params,
|
|
40
30
|
getMdxSource,
|
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
import type { getMdxSource as defaultGetMdxSource } from "@working-theory/page-renderer";
|
|
8
8
|
import {
|
|
9
9
|
getMdxSource as loadMdxSource,
|
|
10
|
-
getMdxSlugs,
|
|
11
10
|
renderPage,
|
|
12
11
|
renderPageMetadata,
|
|
13
12
|
} from "@working-theory/page-renderer";
|
|
@@ -26,15 +25,6 @@ export async function generateMetadata({
|
|
|
26
25
|
return renderPageMetadata({ type: "UseCase", slug, locale });
|
|
27
26
|
}
|
|
28
27
|
|
|
29
|
-
export async function generateStaticParams({
|
|
30
|
-
params,
|
|
31
|
-
}: {
|
|
32
|
-
params: { locale: string };
|
|
33
|
-
}): Promise<{ slug: string }[]> {
|
|
34
|
-
const slugs = await getMdxSlugs("UseCase", params.locale);
|
|
35
|
-
return slugs.map((slug) => ({ slug }));
|
|
36
|
-
}
|
|
37
|
-
|
|
38
28
|
export default async function Page({
|
|
39
29
|
params,
|
|
40
30
|
getMdxSource,
|
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
// HowTo detail page. Reads the HowTo MDX for the given slug, renders via
|
|
2
2
|
// @working-theory/page-renderer, and emits a JSON-LD <script>. Unknown slugs trigger 404.
|
|
3
3
|
import type { getMdxSource as defaultGetMdxSource } from "@working-theory/page-renderer";
|
|
4
|
-
import {
|
|
5
|
-
getMdxSlugs,
|
|
6
|
-
renderPage,
|
|
7
|
-
renderPageMetadata,
|
|
8
|
-
} from "@working-theory/page-renderer";
|
|
4
|
+
import { renderPage, renderPageMetadata } from "@working-theory/page-renderer";
|
|
9
5
|
import type { Metadata } from "next";
|
|
10
6
|
import type { ReactElement } from "react";
|
|
11
7
|
|
|
@@ -21,15 +17,6 @@ export async function generateMetadata({
|
|
|
21
17
|
return renderPageMetadata({ type: "HowTo", slug, locale });
|
|
22
18
|
}
|
|
23
19
|
|
|
24
|
-
export async function generateStaticParams({
|
|
25
|
-
params,
|
|
26
|
-
}: {
|
|
27
|
-
params: { locale: string };
|
|
28
|
-
}): Promise<{ slug: string }[]> {
|
|
29
|
-
const slugs = await getMdxSlugs("HowTo", params.locale);
|
|
30
|
-
return slugs.map((slug) => ({ slug }));
|
|
31
|
-
}
|
|
32
|
-
|
|
33
20
|
export default async function Page({
|
|
34
21
|
params,
|
|
35
22
|
getMdxSource,
|
|
@@ -4,7 +4,6 @@ import {
|
|
|
4
4
|
renderPage,
|
|
5
5
|
renderPageMetadata,
|
|
6
6
|
getMdxSource as defaultGetMdxSource,
|
|
7
|
-
getMdxSlugs,
|
|
8
7
|
} from "@working-theory/page-renderer";
|
|
9
8
|
import type { Metadata } from "next";
|
|
10
9
|
import { notFound } from "next/navigation";
|
|
@@ -22,15 +21,6 @@ export async function generateMetadata({
|
|
|
22
21
|
return renderPageMetadata({ type: "Integration", slug, locale });
|
|
23
22
|
}
|
|
24
23
|
|
|
25
|
-
export async function generateStaticParams({
|
|
26
|
-
params,
|
|
27
|
-
}: {
|
|
28
|
-
params: { locale: string };
|
|
29
|
-
}): Promise<{ slug: string }[]> {
|
|
30
|
-
const slugs = await getMdxSlugs("Integration", params.locale);
|
|
31
|
-
return slugs.map((slug) => ({ slug }));
|
|
32
|
-
}
|
|
33
|
-
|
|
34
24
|
export default async function Page({
|
|
35
25
|
params,
|
|
36
26
|
getMdxSource = defaultGetMdxSource,
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
// next-mdx-remote/rsc, and emits a JSON-LD <script>. Unknown slugs trigger 404.
|
|
3
3
|
import {
|
|
4
4
|
getMdxSource as defaultGetMdxSource,
|
|
5
|
-
getMdxSlugs,
|
|
6
5
|
renderPage,
|
|
7
6
|
renderPageMetadata,
|
|
8
7
|
} from "@working-theory/page-renderer";
|
|
@@ -22,15 +21,6 @@ export async function generateMetadata({
|
|
|
22
21
|
return renderPageMetadata({ type: "Partner", slug, locale });
|
|
23
22
|
}
|
|
24
23
|
|
|
25
|
-
export async function generateStaticParams({
|
|
26
|
-
params,
|
|
27
|
-
}: {
|
|
28
|
-
params: { locale: string };
|
|
29
|
-
}): Promise<{ slug: string }[]> {
|
|
30
|
-
const slugs = await getMdxSlugs("Partner", params.locale);
|
|
31
|
-
return slugs.map((slug: string) => ({ slug }));
|
|
32
|
-
}
|
|
33
|
-
|
|
34
24
|
export default async function Page({
|
|
35
25
|
params,
|
|
36
26
|
getMdxSource = defaultGetMdxSource,
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
// NO_HAND_IMPLEMENT_OK: /build-starter operator-directed live pass (#6687).
|
|
5
5
|
import {
|
|
6
6
|
getMdxSource as defaultGetMdxSource,
|
|
7
|
-
getMdxSlugs,
|
|
8
7
|
renderPage,
|
|
9
8
|
renderPageMetadata,
|
|
10
9
|
} from "@working-theory/page-renderer";
|
|
@@ -24,15 +23,6 @@ export async function generateMetadata({
|
|
|
24
23
|
return renderPageMetadata({ type: "PortfolioItem", slug, locale });
|
|
25
24
|
}
|
|
26
25
|
|
|
27
|
-
export async function generateStaticParams({
|
|
28
|
-
params,
|
|
29
|
-
}: {
|
|
30
|
-
params: { locale: string };
|
|
31
|
-
}): Promise<{ slug: string }[]> {
|
|
32
|
-
const slugs = await getMdxSlugs("PortfolioItem", params.locale);
|
|
33
|
-
return slugs.map((slug: string) => ({ slug }));
|
|
34
|
-
}
|
|
35
|
-
|
|
36
26
|
export default async function Page({
|
|
37
27
|
params,
|
|
38
28
|
getMdxSource = defaultGetMdxSource,
|
|
@@ -4,7 +4,6 @@ import {
|
|
|
4
4
|
renderPage,
|
|
5
5
|
renderPageMetadata,
|
|
6
6
|
getMdxSource as defaultGetMdxSource,
|
|
7
|
-
getMdxSlugs,
|
|
8
7
|
} from "@working-theory/page-renderer";
|
|
9
8
|
import type { Metadata } from "next";
|
|
10
9
|
import { notFound } from "next/navigation";
|
|
@@ -22,15 +21,6 @@ export async function generateMetadata({
|
|
|
22
21
|
return renderPageMetadata({ type: "Product", slug, locale });
|
|
23
22
|
}
|
|
24
23
|
|
|
25
|
-
export async function generateStaticParams({
|
|
26
|
-
params,
|
|
27
|
-
}: {
|
|
28
|
-
params: { locale: string };
|
|
29
|
-
}): Promise<{ slug: string }[]> {
|
|
30
|
-
const slugs = await getMdxSlugs("Product", params.locale);
|
|
31
|
-
return slugs.map((slug) => ({ slug }));
|
|
32
|
-
}
|
|
33
|
-
|
|
34
24
|
export default async function Page({
|
|
35
25
|
params,
|
|
36
26
|
getMdxSource = defaultGetMdxSource,
|
|
@@ -4,11 +4,7 @@ import type {
|
|
|
4
4
|
getMdxSource as defaultGetMdxSource,
|
|
5
5
|
getPageSections as defaultGetPageSections,
|
|
6
6
|
} from "@working-theory/page-renderer";
|
|
7
|
-
import {
|
|
8
|
-
getContentAdapter,
|
|
9
|
-
renderPage,
|
|
10
|
-
renderPageMetadata,
|
|
11
|
-
} from "@working-theory/page-renderer";
|
|
7
|
+
import { renderPage, renderPageMetadata } from "@working-theory/page-renderer";
|
|
12
8
|
import type { Metadata } from "next";
|
|
13
9
|
import type { ReactElement } from "react";
|
|
14
10
|
|
|
@@ -25,16 +21,6 @@ export async function generateMetadata({
|
|
|
25
21
|
return renderPageMetadata({ type: "Project", slug, locale });
|
|
26
22
|
}
|
|
27
23
|
|
|
28
|
-
export async function generateStaticParams({
|
|
29
|
-
params,
|
|
30
|
-
}: {
|
|
31
|
-
params: { locale: string };
|
|
32
|
-
}): Promise<{ slug: string }[]> {
|
|
33
|
-
const adapter = getContentAdapter();
|
|
34
|
-
const pages = await adapter.listDetail("Project", params.locale);
|
|
35
|
-
return pages.map((page) => ({ slug: page.slug }));
|
|
36
|
-
}
|
|
37
|
-
|
|
38
24
|
export default async function Page({
|
|
39
25
|
params,
|
|
40
26
|
getMdxSource,
|
|
@@ -4,7 +4,6 @@ import type {
|
|
|
4
4
|
getMdxSource as defaultGetMdxSource,
|
|
5
5
|
} from "@working-theory/page-renderer";
|
|
6
6
|
import {
|
|
7
|
-
getMdxSlugs,
|
|
8
7
|
getMdxSource as defaultGetMdxSourceImpl,
|
|
9
8
|
renderPage,
|
|
10
9
|
renderPageMetadata,
|
|
@@ -25,15 +24,6 @@ export async function generateMetadata({
|
|
|
25
24
|
return renderPageMetadata({ type: "ResourceDetail", slug, locale });
|
|
26
25
|
}
|
|
27
26
|
|
|
28
|
-
export async function generateStaticParams({
|
|
29
|
-
params,
|
|
30
|
-
}: {
|
|
31
|
-
params: { locale: string };
|
|
32
|
-
}): Promise<{ slug: string }[]> {
|
|
33
|
-
const slugs = await getMdxSlugs("ResourceDetail", params.locale);
|
|
34
|
-
return slugs.map((slug) => ({ slug }));
|
|
35
|
-
}
|
|
36
|
-
|
|
37
27
|
export default async function Page({
|
|
38
28
|
params,
|
|
39
29
|
getMdxSource = defaultGetMdxSourceImpl,
|
|
@@ -4,7 +4,6 @@ import {
|
|
|
4
4
|
renderPage,
|
|
5
5
|
renderPageMetadata,
|
|
6
6
|
getMdxSource as defaultGetMdxSource,
|
|
7
|
-
getMdxSlugs,
|
|
8
7
|
} from "@working-theory/page-renderer";
|
|
9
8
|
import type { Metadata } from "next";
|
|
10
9
|
import { notFound } from "next/navigation";
|
|
@@ -22,15 +21,6 @@ export async function generateMetadata({
|
|
|
22
21
|
return renderPageMetadata({ type: "Service", slug, locale });
|
|
23
22
|
}
|
|
24
23
|
|
|
25
|
-
export async function generateStaticParams({
|
|
26
|
-
params,
|
|
27
|
-
}: {
|
|
28
|
-
params: { locale: string };
|
|
29
|
-
}): Promise<{ slug: string }[]> {
|
|
30
|
-
const slugs = await getMdxSlugs("Service", params.locale);
|
|
31
|
-
return slugs.map((slug) => ({ slug }));
|
|
32
|
-
}
|
|
33
|
-
|
|
34
24
|
export default async function Page({
|
|
35
25
|
params,
|
|
36
26
|
getMdxSource = defaultGetMdxSource,
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
// renders them; a prose-only page keeps the MDX-body render.
|
|
5
5
|
import type { getMdxSource as defaultGetMdxSource } from "@working-theory/page-renderer";
|
|
6
6
|
import {
|
|
7
|
-
getMdxSlugs,
|
|
8
7
|
getMdxSource as loadMdxSource,
|
|
9
8
|
renderPage,
|
|
10
9
|
renderPageMetadata,
|
|
@@ -24,15 +23,6 @@ export async function generateMetadata({
|
|
|
24
23
|
return renderPageMetadata({ type: "SoftwareProduct", slug, locale });
|
|
25
24
|
}
|
|
26
25
|
|
|
27
|
-
export async function generateStaticParams({
|
|
28
|
-
params,
|
|
29
|
-
}: {
|
|
30
|
-
params: { locale: string };
|
|
31
|
-
}): Promise<{ slug: string }[]> {
|
|
32
|
-
const slugs = await getMdxSlugs("SoftwareProduct", params.locale);
|
|
33
|
-
return slugs.map((slug) => ({ slug }));
|
|
34
|
-
}
|
|
35
|
-
|
|
36
26
|
export default async function Page({
|
|
37
27
|
params,
|
|
38
28
|
getMdxSource,
|
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
// TechArticle detail page. Reads the TechArticle MDX for the given slug, renders via
|
|
2
2
|
// @working-theory/page-renderer, and emits a JSON-LD <script>. Unknown slugs trigger 404.
|
|
3
3
|
import type { getMdxSource as defaultGetMdxSource } from "@working-theory/page-renderer";
|
|
4
|
-
import {
|
|
5
|
-
getMdxSlugs,
|
|
6
|
-
renderPage,
|
|
7
|
-
renderPageMetadata,
|
|
8
|
-
} from "@working-theory/page-renderer";
|
|
4
|
+
import { renderPage, renderPageMetadata } from "@working-theory/page-renderer";
|
|
9
5
|
import type { Metadata } from "next";
|
|
10
6
|
import type { ReactElement } from "react";
|
|
11
7
|
|
|
@@ -21,15 +17,6 @@ export async function generateMetadata({
|
|
|
21
17
|
return renderPageMetadata({ type: "TechArticle", slug, locale });
|
|
22
18
|
}
|
|
23
19
|
|
|
24
|
-
export async function generateStaticParams({
|
|
25
|
-
params,
|
|
26
|
-
}: {
|
|
27
|
-
params: { locale: string };
|
|
28
|
-
}): Promise<{ slug: string }[]> {
|
|
29
|
-
const slugs = await getMdxSlugs("TechArticle", params.locale);
|
|
30
|
-
return slugs.map((slug) => ({ slug }));
|
|
31
|
-
}
|
|
32
|
-
|
|
33
20
|
export default async function Page({
|
|
34
21
|
params,
|
|
35
22
|
getMdxSource,
|
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
// ThankYouPage detail page (#3960 D6) — the segment-keyed flow-completion
|
|
2
|
-
// redirect target. Sections-mode renderPage (the ContactPage pattern)
|
|
3
|
-
//
|
|
2
|
+
// redirect target. Sections-mode renderPage (the ContactPage pattern),
|
|
3
|
+
// rendered on request under the cookie-reading locale layout; [slug]/page.tsx's
|
|
4
|
+
// header says why there is no static-params export (#7379). Unknown slugs 404
|
|
4
5
|
// via renderPage's own detail-route branch (no translationsNamespace passed
|
|
5
6
|
// — renderPage calls notFound() itself when getMdxSource resolves null).
|
|
6
7
|
import type { getMdxSource as defaultGetMdxSource } from "@working-theory/page-renderer";
|
|
7
|
-
import {
|
|
8
|
-
getMdxSlugs,
|
|
9
|
-
renderPage,
|
|
10
|
-
renderPageMetadata,
|
|
11
|
-
} from "@working-theory/page-renderer";
|
|
8
|
+
import { renderPage, renderPageMetadata } from "@working-theory/page-renderer";
|
|
12
9
|
import type { Metadata } from "next";
|
|
13
10
|
import type { ReactElement } from "react";
|
|
14
11
|
|
|
@@ -24,15 +21,6 @@ export async function generateMetadata({
|
|
|
24
21
|
return renderPageMetadata({ type: "ThankYouPage", slug, locale });
|
|
25
22
|
}
|
|
26
23
|
|
|
27
|
-
export async function generateStaticParams({
|
|
28
|
-
params,
|
|
29
|
-
}: {
|
|
30
|
-
params: { locale: string };
|
|
31
|
-
}): Promise<{ slug: string }[]> {
|
|
32
|
-
const slugs = await getMdxSlugs("ThankYouPage", params.locale);
|
|
33
|
-
return slugs.map((slug) => ({ slug }));
|
|
34
|
-
}
|
|
35
|
-
|
|
36
24
|
export default async function Page({
|
|
37
25
|
params,
|
|
38
26
|
getMdxSource,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Tests for /vs/[slug] (#6878 D9) — the ComparisonPage detail route.
|
|
3
|
-
* `renderPage`/`renderPageMetadata
|
|
3
|
+
* `renderPage`/`renderPageMetadata` are mocked at the
|
|
4
4
|
* `@working-theory/page-renderer` boundary; `getMdxSource` is supplied
|
|
5
5
|
* per-call through the route's DI prop.
|
|
6
6
|
*/
|
|
@@ -10,24 +10,19 @@
|
|
|
10
10
|
// production, unaffected by this mock's loose type here.
|
|
11
11
|
const mockRenderPage = jest.fn(async (..._args: unknown[]) => "<rendered/>");
|
|
12
12
|
const mockRenderPageMetadata = jest.fn((..._args: unknown[]) => undefined);
|
|
13
|
-
const mockGetMdxSlugs = jest.fn((..._args: unknown[]) => Promise.resolve<string[]>([]));
|
|
14
13
|
|
|
15
14
|
jest.mock("@working-theory/page-renderer", () => ({
|
|
16
15
|
__esModule: true,
|
|
17
|
-
getMdxSlugs: (...args: unknown[]) => mockGetMdxSlugs(...args),
|
|
18
16
|
renderPage: (...args: unknown[]) => mockRenderPage(...args),
|
|
19
17
|
renderPageMetadata: (...args: unknown[]) => mockRenderPageMetadata(...args),
|
|
20
18
|
getMdxSource: jest.fn(),
|
|
21
19
|
}));
|
|
22
20
|
|
|
23
|
-
import ComparisonPage, {
|
|
24
|
-
generateMetadata,
|
|
25
|
-
generateStaticParams,
|
|
26
|
-
} from "../page";
|
|
21
|
+
import ComparisonPage, { generateMetadata } from "../page";
|
|
27
22
|
|
|
28
23
|
beforeEach(() => jest.clearAllMocks());
|
|
29
24
|
|
|
30
|
-
describe("ComparisonPage detail — metadata
|
|
25
|
+
describe("ComparisonPage detail — metadata", () => {
|
|
31
26
|
it("resolves metadata for the given slug", async () => {
|
|
32
27
|
await generateMetadata({
|
|
33
28
|
params: Promise.resolve({ locale: "en", slug: "acme" }),
|
|
@@ -38,13 +33,6 @@ describe("ComparisonPage detail — metadata + static params", () => {
|
|
|
38
33
|
locale: "en",
|
|
39
34
|
});
|
|
40
35
|
});
|
|
41
|
-
|
|
42
|
-
it("enumerates every ComparisonPage slug for static generation", async () => {
|
|
43
|
-
mockGetMdxSlugs.mockResolvedValue(["acme", "globex"]);
|
|
44
|
-
const params = await generateStaticParams({ params: { locale: "en" } });
|
|
45
|
-
expect(mockGetMdxSlugs).toHaveBeenCalledWith("ComparisonPage", "en");
|
|
46
|
-
expect(params).toEqual([{ slug: "acme" }, { slug: "globex" }]);
|
|
47
|
-
});
|
|
48
36
|
});
|
|
49
37
|
|
|
50
38
|
describe("ComparisonPage detail — sections vs mdx-body", () => {
|
|
@@ -12,7 +12,6 @@
|
|
|
12
12
|
import type { getMdxSource as defaultGetMdxSource } from "@working-theory/page-renderer";
|
|
13
13
|
import {
|
|
14
14
|
getMdxSource as loadMdxSource,
|
|
15
|
-
getMdxSlugs,
|
|
16
15
|
renderPage,
|
|
17
16
|
renderPageMetadata,
|
|
18
17
|
} from "@working-theory/page-renderer";
|
|
@@ -31,15 +30,6 @@ export async function generateMetadata({
|
|
|
31
30
|
return renderPageMetadata({ type: "ComparisonPage", slug, locale });
|
|
32
31
|
}
|
|
33
32
|
|
|
34
|
-
export async function generateStaticParams({
|
|
35
|
-
params,
|
|
36
|
-
}: {
|
|
37
|
-
params: { locale: string };
|
|
38
|
-
}): Promise<{ slug: string }[]> {
|
|
39
|
-
const slugs = await getMdxSlugs("ComparisonPage", params.locale);
|
|
40
|
-
return slugs.map((slug) => ({ slug }));
|
|
41
|
-
}
|
|
42
|
-
|
|
43
33
|
export default async function Page({
|
|
44
34
|
params,
|
|
45
35
|
getMdxSource,
|
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
// Whitepaper detail page. Reads the Whitepaper MDX for the given slug, renders via
|
|
2
2
|
// @working-theory/page-renderer, and emits a JSON-LD <script>. Unknown slugs trigger 404.
|
|
3
3
|
import type { getMdxSource as defaultGetMdxSource } from "@working-theory/page-renderer";
|
|
4
|
-
import {
|
|
5
|
-
getMdxSlugs,
|
|
6
|
-
renderPage,
|
|
7
|
-
renderPageMetadata,
|
|
8
|
-
} from "@working-theory/page-renderer";
|
|
4
|
+
import { renderPage, renderPageMetadata } from "@working-theory/page-renderer";
|
|
9
5
|
import type { Metadata } from "next";
|
|
10
6
|
import type { ReactElement } from "react";
|
|
11
7
|
|
|
@@ -21,15 +17,6 @@ export async function generateMetadata({
|
|
|
21
17
|
return renderPageMetadata({ type: "Whitepaper", slug, locale });
|
|
22
18
|
}
|
|
23
19
|
|
|
24
|
-
export async function generateStaticParams({
|
|
25
|
-
params,
|
|
26
|
-
}: {
|
|
27
|
-
params: { locale: string };
|
|
28
|
-
}): Promise<{ slug: string }[]> {
|
|
29
|
-
const slugs = await getMdxSlugs("Whitepaper", params.locale);
|
|
30
|
-
return slugs.map((slug) => ({ slug }));
|
|
31
|
-
}
|
|
32
|
-
|
|
33
20
|
export default async function Page({
|
|
34
21
|
params,
|
|
35
22
|
getMdxSource,
|
|
@@ -15,19 +15,28 @@
|
|
|
15
15
|
* unlike `apps/mcp/src/lib/commerce-claim.ts`'s boot-time memoisation — so a
|
|
16
16
|
* site that buys commerce after its last deploy starts serving immediately
|
|
17
17
|
* rather than waiting on a redeploy.
|
|
18
|
+
*
|
|
19
|
+
* {@link resolveLicenceFeatures} (#7136) is the same single read, returning
|
|
20
|
+
* every licence feature the deployment holds: `/.well-known/mcp.json` gates
|
|
21
|
+
* the five `feature`-tagged MCP tools on it, from one call per request.
|
|
18
22
|
*/
|
|
19
23
|
import { checkLicense } from "@working-theory/license";
|
|
20
24
|
|
|
21
25
|
/** The licence `features[]` claim that turns the commerce add-on on. */
|
|
22
|
-
const COMMERCE_FEATURE = "commerce";
|
|
26
|
+
export const COMMERCE_FEATURE = "commerce";
|
|
23
27
|
|
|
24
|
-
|
|
28
|
+
/** The licence features this deployment positively holds — `[]` when the
|
|
29
|
+
* licence is revoked, carries no `features` array, or cannot be read. */
|
|
30
|
+
export async function resolveLicenceFeatures(): Promise<readonly string[]> {
|
|
25
31
|
try {
|
|
26
32
|
const result = await checkLicense();
|
|
27
|
-
return
|
|
28
|
-
|
|
29
|
-
);
|
|
33
|
+
if (result.revoked === true) return [];
|
|
34
|
+
return Array.isArray(result.features) ? result.features : [];
|
|
30
35
|
} catch {
|
|
31
|
-
return
|
|
36
|
+
return [];
|
|
32
37
|
}
|
|
33
38
|
}
|
|
39
|
+
|
|
40
|
+
export async function resolveCommerceClaim(): Promise<boolean> {
|
|
41
|
+
return (await resolveLicenceFeatures()).includes(COMMERCE_FEATURE);
|
|
42
|
+
}
|