create-ailk 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +124 -3
- package/component-catalog.md +456 -0
- package/dist/cli.js +92 -16
- package/dist/component-catalog.d.ts +11 -0
- package/dist/component-catalog.js +39 -0
- package/dist/copy.d.ts +7 -0
- package/dist/copy.js +24 -0
- package/dist/derive-architecture.d.ts +13 -0
- package/dist/derive-architecture.js +238 -0
- package/dist/index.d.ts +7 -2
- package/dist/index.js +19 -2
- package/dist/lib/extract-module-bundle.d.ts +16 -0
- package/dist/lib/extract-module-bundle.js +184 -0
- package/dist/lib/fetch-module.d.ts +55 -0
- package/dist/lib/fetch-module.js +125 -0
- package/dist/lib/module-license-gate.d.ts +48 -0
- package/dist/lib/module-license-gate.js +67 -0
- package/dist/lib/module-tier.d.ts +35 -0
- package/dist/lib/module-tier.js +37 -0
- package/dist/module-architecture.d.ts +175 -0
- package/dist/module-architecture.js +663 -0
- package/dist/parse-args.d.ts +47 -1
- package/dist/parse-args.js +143 -2
- package/dist/programmatic.d.ts +160 -3
- package/dist/programmatic.js +196 -7
- package/dist/surfaces.d.ts +211 -0
- package/dist/surfaces.js +532 -0
- package/dist/sync-routes.d.ts +92 -0
- package/dist/sync-routes.js +350 -0
- package/package.json +12 -5
- package/templates/.claude/rules/architecture.md +6 -2
- package/templates/.claude/skills/README.md +9 -9
- package/templates/.claude/skills/add-schema/SKILL.md +14 -7
- package/templates/.claude/skills/add-schema/references/schema-types.md +109 -6
- package/templates/.claude/skills/provision-config/SKILL.md +1 -1
- package/templates/.claude/skills/scaffold-commerce/SKILL.md +498 -1
- package/templates/.claude/skills/scaffold-commerce/templates/checkout-route.template.ts +370 -0
- package/templates/.claude/skills/scaffold-commerce/templates/invoice-route.template.ts +376 -0
- package/templates/.claude/skills/scaffold-commerce/templates/payment-link-route.template.ts +471 -0
- package/templates/.claude/skills/scaffold-commerce/templates/portal-route.template.ts +365 -0
- package/templates/.claude/skills/scaffold-commerce/templates/stripe-config.template.ts +60 -0
- package/templates/.claude/skills/scaffold-commerce/templates/subscription-route.template.ts +446 -0
- package/templates/.claude/skills/suggest-site-pages/references/categories.md +4 -4
- package/templates/.env.example +126 -2
- package/templates/CLAUDE.md +11 -5
- package/templates/README.md +1 -1
- package/templates/apps/api/.env.example +38 -0
- package/templates/apps/api/CLAUDE.md +78 -1
- package/templates/apps/api/LICENSE +201 -0
- package/templates/apps/api/api/index.ts +6 -141
- package/templates/apps/api/jest.config.cjs +16 -0
- package/templates/apps/api/package.json +22 -6
- package/templates/apps/api/src/__tests__/module-exclusion.test.ts +141 -0
- package/templates/apps/api/src/__tests__/server.test.ts +46 -0
- package/templates/apps/api/src/__tests__/vercel-handler.test.ts +211 -0
- package/templates/apps/api/src/bin/abandon-sweep.ts +42 -0
- package/templates/apps/api/src/bin/deliverable-resend.ts +144 -0
- package/templates/apps/api/src/bin/deliverable-upload.ts +114 -0
- package/templates/apps/api/src/bin/followup-sweep.ts +44 -0
- package/templates/apps/api/src/bin/listing-csv-sweep.ts +46 -0
- package/templates/apps/api/src/bin/seed-presets.ts +58 -0
- package/templates/apps/api/src/bin/seed-waitlist-experiments.ts +104 -0
- package/templates/apps/api/src/bin/session-retention-sweep.ts +46 -0
- package/templates/apps/api/src/cli.ts +5 -11
- package/templates/apps/api/src/config/index.ts +35 -0
- package/templates/apps/api/src/config/modules.ts +43 -0
- package/templates/apps/api/src/lib/__mocks__/prisma-client.js +11 -0
- package/templates/apps/api/src/lib/__mocks__/prisma.ts +241 -0
- package/templates/apps/api/src/lib/__tests__/lead-capture-store.test.ts +2 -2
- package/templates/apps/api/src/lib/site.ts +16 -0
- package/templates/apps/api/src/lib/stripe.ts +22 -0
- package/templates/apps/api/src/lib/tenant-db.ts +225 -0
- package/templates/apps/api/src/lib/ws-token.ts +91 -0
- package/templates/apps/api/src/middleware/__tests__/adversarial/session-fixation.test.ts +7 -1
- package/templates/apps/api/src/middleware/__tests__/auth.cookie-path.test.ts +7 -1
- package/templates/apps/api/src/middleware/__tests__/rate-limit.test.ts +91 -4
- package/templates/apps/api/src/middleware/auth.ts +43 -8
- package/templates/apps/api/src/middleware/rate-limit.ts +78 -3
- package/templates/apps/api/src/middleware/tenant.ts +99 -0
- package/templates/apps/api/src/openapi/__tests__/openapi.test.ts +92 -0
- package/templates/apps/api/src/openapi/spec.ts +312 -3
- package/templates/apps/api/src/routes/aeo/__tests__/index.test.ts +175 -0
- package/templates/apps/api/src/routes/aeo/index.ts +107 -0
- package/templates/apps/api/src/routes/auth/__tests__/auth-tokens.functional.test.ts +5 -2
- package/templates/apps/api/src/routes/auth/__tests__/tokens.test.ts +22 -3
- package/templates/apps/api/src/routes/auth/tokens.ts +13 -1
- package/templates/apps/api/src/routes/billing/__tests__/portal.test.ts +450 -0
- package/templates/apps/api/src/routes/billing/__tests__/read.test.ts +262 -0
- package/templates/apps/api/src/routes/billing/__tests__/usage.test.ts +436 -0
- package/templates/apps/api/src/routes/billing/index.ts +36 -0
- package/templates/apps/api/src/routes/billing/portal.ts +182 -0
- package/templates/apps/api/src/routes/billing/read.ts +75 -0
- package/templates/apps/api/src/routes/billing/usage.ts +153 -0
- package/templates/apps/api/src/routes/checkout/__tests__/sessions.test.ts +99 -0
- package/templates/apps/api/src/routes/checkout/sessions.ts +20 -8
- package/templates/apps/api/src/routes/content/create.ts +1 -0
- package/templates/apps/api/src/routes/content/delete.ts +1 -0
- package/templates/apps/api/src/routes/content/index.ts +42 -6
- package/templates/apps/api/src/routes/content/update.ts +1 -0
- package/templates/apps/api/src/routes/deliverables/__tests__/index.test.ts +393 -0
- package/templates/apps/api/src/routes/deliverables/index.ts +200 -0
- package/templates/apps/api/src/routes/flow-checkouts/__tests__/index.test.ts +443 -0
- package/templates/apps/api/src/routes/flow-checkouts/index.ts +82 -0
- package/templates/apps/api/src/routes/flows/README.md +147 -0
- package/templates/apps/api/src/routes/flows/__tests__/index.test.ts +752 -0
- package/templates/apps/api/src/routes/flows/__tests__/recommender.test.ts +671 -0
- package/templates/apps/api/src/routes/flows/index.ts +202 -0
- package/templates/apps/api/src/routes/flows/recommender.ts +443 -0
- package/templates/apps/api/src/routes/leads/__tests__/index.test.ts +438 -31
- package/templates/apps/api/src/routes/leads/__tests__/track.test.ts +10 -10
- package/templates/apps/api/src/routes/leads/index.ts +43 -9
- package/templates/apps/api/src/routes/project-listings/__tests__/configured-application.test.ts +558 -0
- package/templates/apps/api/src/routes/project-listings/__tests__/copy-edit.test.ts +815 -0
- package/templates/apps/api/src/routes/project-listings/__tests__/drafts.test.ts +869 -0
- package/templates/apps/api/src/routes/project-listings/__tests__/me-route-precedence.test.ts +221 -0
- package/templates/apps/api/src/routes/project-listings/__tests__/me.test.ts +468 -0
- package/templates/apps/api/src/routes/project-listings/__tests__/public.test.ts +424 -0
- package/templates/apps/api/src/routes/project-listings/__tests__/site-answers.test.ts +707 -0
- package/templates/apps/api/src/routes/project-listings/__tests__/site-key.test.ts +375 -0
- package/templates/apps/api/src/routes/project-listings/__tests__/structured-address.test.ts +467 -0
- package/templates/apps/api/src/routes/project-listings/__tests__/tenant-isolation.test.ts +566 -0
- package/templates/apps/api/src/routes/project-listings/get.ts +70 -0
- package/templates/apps/api/src/routes/project-listings/index.ts +120 -0
- package/templates/apps/api/src/routes/project-listings/list.ts +47 -0
- package/templates/apps/api/src/routes/project-listings/me.ts +76 -0
- package/templates/apps/api/src/routes/project-listings/patch-copy.ts +222 -0
- package/templates/apps/api/src/routes/project-listings/patch-draft.ts +97 -0
- package/templates/apps/api/src/routes/project-listings/patch.ts +136 -0
- package/templates/apps/api/src/routes/project-listings/public.ts +52 -0
- package/templates/apps/api/src/routes/project-listings/respond.ts +37 -0
- package/templates/apps/api/src/routes/project-listings/resume-token.ts +22 -0
- package/templates/apps/api/src/routes/project-listings/start.ts +106 -0
- package/templates/apps/api/src/routes/project-listings/submit.ts +122 -0
- package/templates/apps/api/src/routes/schedule/__tests__/index.test.ts +490 -0
- package/templates/apps/api/src/routes/schedule/index.ts +249 -0
- package/templates/apps/api/src/routes/slack/__tests__/actions.test.ts +385 -0
- package/templates/apps/api/src/routes/slack/actions.ts +177 -0
- package/templates/apps/api/src/routes/slack/index.ts +38 -0
- package/templates/apps/api/src/routes/test/auth/__tests__/session.test.ts +16 -6
- package/templates/apps/api/src/routes/test/auth/session.ts +8 -6
- package/templates/apps/api/src/routes/waitlist-experiments/__tests__/tenant-isolation.test.ts +577 -0
- package/templates/apps/api/src/routes/waitlist-experiments/comparison.ts +78 -0
- package/templates/apps/api/src/routes/waitlist-experiments/index.ts +41 -0
- package/templates/apps/api/src/routes/waitlist-experiments/list.ts +64 -0
- package/templates/apps/api/src/routes/waitlist-experiments/respond.ts +42 -0
- package/templates/apps/api/src/routes/waitlist-experiments/signup.ts +84 -0
- package/templates/apps/api/src/routes/waitlist-experiments/signups.ts +119 -0
- package/templates/apps/api/src/routes/waitlist-signups/__tests__/index.test.ts +238 -0
- package/templates/apps/api/src/routes/waitlist-signups/index.ts +101 -0
- package/templates/apps/api/src/routes/webhooks/README.md +35 -12
- package/templates/apps/api/src/routes/webhooks/__tests__/stripe-flow-checkout.test.ts +315 -0
- package/templates/apps/api/src/routes/webhooks/__tests__/stripe-org-billing.test.ts +270 -0
- package/templates/apps/api/src/routes/webhooks/stripe.ts +248 -20
- package/templates/apps/api/src/routes/workspaces/__tests__/config-tenant-isolation.test.ts +356 -0
- package/templates/apps/api/src/routes/workspaces/__tests__/tenant-isolation.test.ts +671 -0
- package/templates/apps/api/src/routes/workspaces/config.ts +125 -0
- package/templates/apps/api/src/routes/workspaces/index.ts +194 -0
- package/templates/apps/api/src/routes/workspaces/sessions.ts +218 -0
- package/templates/apps/api/src/server.ts +307 -7
- package/templates/apps/api/src/services/__tests__/abandon-email.test.ts +489 -0
- package/templates/apps/api/src/services/__tests__/aeo-score.test.ts +475 -0
- package/templates/apps/api/src/services/__tests__/answer-distributions.test.ts +132 -0
- package/templates/apps/api/src/services/__tests__/consent-migration.test.ts +65 -0
- package/templates/apps/api/src/services/__tests__/consent.test.ts +282 -0
- package/templates/apps/api/src/services/__tests__/deliverable-fulfillment.test.ts +523 -0
- package/templates/apps/api/src/services/__tests__/deliverable-resend.test.ts +359 -0
- package/templates/apps/api/src/services/__tests__/entitlements.test.ts +142 -0
- package/templates/apps/api/src/services/__tests__/flow-aggregate.test.ts +425 -0
- package/templates/apps/api/src/services/__tests__/flow-engine.test.ts +2840 -0
- package/templates/apps/api/src/services/__tests__/lead-promotion.test.ts +393 -0
- package/templates/apps/api/src/services/__tests__/lead-routing.test.ts +8 -8
- package/templates/apps/api/src/services/__tests__/listing-csv-sweep.test.ts +560 -0
- package/templates/apps/api/src/services/__tests__/listing-promotion.test.ts +684 -0
- package/templates/apps/api/src/services/__tests__/playbook-compile.test.ts +406 -0
- package/templates/apps/api/src/services/__tests__/playbook-render.test.ts +290 -0
- package/templates/apps/api/src/services/__tests__/project-listing-decision.test.ts +736 -0
- package/templates/apps/api/src/services/__tests__/project-listing-flow.test.ts +475 -0
- package/templates/apps/api/src/services/__tests__/project-listing-issue.test.ts +340 -0
- package/templates/apps/api/src/services/__tests__/recommender-capture.test.ts +983 -0
- package/templates/apps/api/src/services/__tests__/slack-notify.test.ts +278 -0
- package/templates/apps/api/src/services/__tests__/tenant-context-cascade.test.ts +71 -0
- package/templates/apps/api/src/services/__tests__/tenant-context.test.ts +379 -0
- package/templates/apps/api/src/services/__tests__/usage-aggregation.test.ts +941 -0
- package/templates/apps/api/src/services/__tests__/usage-credits.test.ts +588 -0
- package/templates/apps/api/src/services/__tests__/usage-metering.test.ts +768 -0
- package/templates/apps/api/src/services/__tests__/waitlist-dashboard.test.ts +1314 -0
- package/templates/apps/api/src/services/__tests__/waitlist-experiments.test.ts +341 -0
- package/templates/apps/api/src/services/__tests__/waitlist-followup.test.ts +567 -0
- package/templates/apps/api/src/services/__tests__/waitlist-scoring.test.ts +474 -0
- package/templates/apps/api/src/services/__tests__/waitlist-signups.test.ts +354 -0
- package/templates/apps/api/src/services/abandon-email.ts +307 -0
- package/templates/apps/api/src/services/aeo-score.ts +288 -0
- package/templates/apps/api/src/services/answer-distributions.ts +138 -0
- package/templates/apps/api/src/services/consent.ts +236 -0
- package/templates/apps/api/src/services/deliverable-fulfillment.ts +523 -0
- package/templates/apps/api/src/services/entitlements.ts +102 -0
- package/templates/apps/api/src/services/flow-aggregate.ts +232 -0
- package/templates/apps/api/src/services/flow-checkouts.ts +123 -0
- package/templates/apps/api/src/services/flow-engine.ts +1296 -0
- package/templates/apps/api/src/services/lead-promotion.ts +176 -0
- package/templates/apps/api/src/services/lead-routing.ts +3 -3
- package/templates/apps/api/src/services/listing-config.ts +102 -0
- package/templates/apps/api/src/services/listing-csv-sweep.ts +455 -0
- package/templates/apps/api/src/services/listing-promotion.ts +342 -0
- package/templates/apps/api/src/services/playbook-compile.ts +398 -0
- package/templates/apps/api/src/services/playbook-render.ts +263 -0
- package/templates/apps/api/src/services/project-listing-decision.ts +510 -0
- package/templates/apps/api/src/services/project-listing-flow.ts +426 -0
- package/templates/apps/api/src/services/project-listing-issue.ts +251 -0
- package/templates/apps/api/src/services/project-listings.ts +1472 -0
- package/templates/apps/api/src/services/recommender-capture.ts +835 -0
- package/templates/apps/api/src/services/scheduling/cal-provider.ts +392 -0
- package/templates/apps/api/src/services/scheduling/index.ts +63 -0
- package/templates/apps/api/src/services/scheduling/types.ts +88 -0
- package/templates/apps/api/src/services/slack-notify.ts +240 -0
- package/templates/apps/api/src/services/tenant-context.ts +451 -0
- package/templates/apps/api/src/services/usage-aggregation.ts +516 -0
- package/templates/apps/api/src/services/usage-credits.ts +340 -0
- package/templates/apps/api/src/services/usage-metering.ts +699 -0
- package/templates/apps/api/src/services/waitlist-dashboard.ts +947 -0
- package/templates/apps/api/src/services/waitlist-experiments.ts +213 -0
- package/templates/apps/api/src/services/waitlist-followup.ts +486 -0
- package/templates/apps/api/src/services/waitlist-scoring.ts +166 -0
- package/templates/apps/api/src/services/waitlist-signups.ts +165 -0
- package/templates/apps/api/src/vercel-handler.ts +165 -0
- package/templates/apps/api/tsconfig.json +0 -12
- package/templates/apps/mcp/CLAUDE.md +19 -9
- package/templates/apps/mcp/LICENSE +201 -0
- package/templates/apps/mcp/__tests__/create_page.test.ts +1 -0
- package/templates/apps/mcp/__tests__/delete_page.test.ts +1 -0
- package/templates/apps/mcp/__tests__/module-exclusion.test.ts +105 -0
- package/templates/apps/mcp/__tests__/parity.test.ts +70 -6
- package/templates/apps/mcp/__tests__/request_callback.test.ts +4 -4
- package/templates/apps/mcp/__tests__/schedule_tools.test.ts +242 -0
- package/templates/apps/mcp/__tests__/submit_lead.test.ts +4 -4
- package/templates/apps/mcp/__tests__/subscribe_newsletter.test.ts +4 -4
- package/templates/apps/mcp/__tests__/tools/purchase.test.ts +47 -0
- package/templates/apps/mcp/__tests__/update_page.test.ts +1 -0
- package/templates/apps/mcp/package.json +6 -4
- package/templates/apps/mcp/src/config/modules.ts +37 -0
- package/templates/apps/mcp/src/server.ts +109 -18
- package/templates/apps/mcp/src/tools/capture_lead.ts +1 -1
- package/templates/apps/mcp/src/tools/create_booking.ts +58 -0
- package/templates/apps/mcp/src/tools/create_page.ts +1 -0
- package/templates/apps/mcp/src/tools/delete_page.ts +1 -0
- package/templates/apps/mcp/src/tools/get_event_meta.ts +55 -0
- package/templates/apps/mcp/src/tools/get_flow.ts +61 -0
- package/templates/apps/mcp/src/tools/index.ts +25 -0
- package/templates/apps/mcp/src/tools/list_availability.ts +67 -0
- package/templates/apps/mcp/src/tools/purchase.ts +3 -0
- package/templates/apps/mcp/src/tools/submit_flow_step.ts +83 -0
- package/templates/apps/mcp/src/tools/update_page.ts +1 -0
- package/templates/apps/mcp/tsconfig.json +1 -9
- package/templates/apps/web/.env.example +44 -0
- package/templates/apps/web/CLAUDE.md +28 -0
- package/templates/apps/web/LICENSE +201 -0
- package/templates/apps/web/__tests__/__mocks__/code-highlight.jest-stub.ts +24 -0
- package/templates/apps/web/__tests__/__mocks__/next-intl-server.ts +33 -0
- package/templates/apps/web/__tests__/__mocks__/next-intl.ts +18 -0
- package/templates/apps/web/__tests__/__mocks__/server-only.ts +13 -0
- package/templates/apps/web/__tests__/__mocks__/style-mock.js +4 -0
- package/templates/apps/web/__tests__/__mocks__/vercel-analytics-server.ts +9 -0
- package/templates/apps/web/__tests__/jest-support/import-meta-transformer.cjs +90 -0
- package/templates/apps/web/__tests__/setup.ts +22 -32
- package/templates/apps/web/app/.well-known/ai-plugin.json/route.ts +6 -3
- package/templates/apps/web/app/.well-known/mcp.json/build-manifest.ts +8 -2
- package/templates/apps/web/app/[locale]/(authed)/account/__tests__/page.test.tsx +260 -0
- package/templates/apps/web/app/[locale]/(authed)/account/page.tsx +263 -0
- package/templates/apps/web/app/[locale]/(authed)/account/sign-out-button.tsx +39 -0
- package/templates/apps/web/app/[locale]/(authed)/layout.tsx +54 -0
- package/templates/apps/web/app/[locale]/(authed)/sign-in-gate.tsx +96 -0
- package/templates/apps/web/app/[locale]/(authed)/waitlist/[experimentId]/page.tsx +309 -0
- package/templates/apps/web/app/[locale]/(authed)/waitlist/[experimentId]/signups/[leadId]/page.tsx +149 -0
- package/templates/apps/web/app/[locale]/(authed)/waitlist/__tests__/comparison.test.tsx +273 -0
- package/templates/apps/web/app/[locale]/(authed)/waitlist/__tests__/gate.test.tsx +172 -0
- package/templates/apps/web/app/[locale]/(authed)/waitlist/__tests__/list.test.tsx +171 -0
- package/templates/apps/web/app/[locale]/(authed)/waitlist/__tests__/signup.test.tsx +179 -0
- package/templates/apps/web/app/[locale]/(authed)/waitlist/components/ExperimentsTable.tsx +116 -0
- package/templates/apps/web/app/[locale]/(authed)/waitlist/components/ForbiddenState.tsx +24 -0
- package/templates/apps/web/app/[locale]/(authed)/waitlist/components/OfferFunnelTable.tsx +66 -0
- package/templates/apps/web/app/[locale]/(authed)/waitlist/components/RollupTicker.tsx +61 -0
- package/templates/apps/web/app/[locale]/(authed)/waitlist/components/ScoreTrace.tsx +114 -0
- package/templates/apps/web/app/[locale]/(authed)/waitlist/components/SignupsTable.tsx +139 -0
- package/templates/apps/web/app/[locale]/(authed)/waitlist/components/WaitlistComparisonTabs.tsx +85 -0
- package/templates/apps/web/app/[locale]/(authed)/waitlist/components/status-badges.tsx +67 -0
- package/templates/apps/web/app/[locale]/(authed)/waitlist/format.ts +111 -0
- package/templates/apps/web/app/[locale]/(authed)/waitlist/page.tsx +179 -0
- package/templates/apps/web/app/[locale]/about/page.tsx +10 -1
- package/templates/apps/web/app/[locale]/blog/[[...slug]]/page.tsx +6 -1
- package/templates/apps/web/app/[locale]/careers/[slug]/page.tsx +9 -0
- package/templates/apps/web/app/[locale]/careers/__tests__/page-renderer-migration.test.tsx +3 -3
- package/templates/apps/web/app/[locale]/careers/page.tsx +9 -1
- package/templates/apps/web/app/[locale]/case-studies/[slug]/page.tsx +9 -0
- package/templates/apps/web/app/[locale]/case-studies/__tests__/page-renderer-migration.test.tsx +3 -3
- package/templates/apps/web/app/[locale]/case-studies/page.tsx +13 -1
- package/templates/apps/web/app/[locale]/clients/__tests__/page-renderer-migration.test.tsx +11 -1
- package/templates/apps/web/app/[locale]/clients/page.tsx +9 -1
- package/templates/apps/web/app/[locale]/contact/ContactForm.tsx +21 -1
- package/templates/apps/web/app/[locale]/contact/ConversationalIntakeWrapper.tsx +188 -0
- package/templates/apps/web/app/[locale]/contact/__tests__/ConversationalIntakeWrapper.test.tsx +242 -0
- package/templates/apps/web/app/[locale]/contact/__tests__/contact.actions.test.ts +29 -0
- package/templates/apps/web/app/[locale]/contact/__tests__/intake-analytics.test.ts +51 -0
- package/templates/apps/web/app/[locale]/contact/__tests__/page-renderer-migration.test.tsx +39 -15
- package/templates/apps/web/app/[locale]/contact/contact.actions.ts +21 -3
- package/templates/apps/web/app/[locale]/contact/intake-analytics.ts +49 -0
- package/templates/apps/web/app/[locale]/contact/intake-script.ts +66 -0
- package/templates/apps/web/app/[locale]/contact/page.tsx +14 -4
- package/templates/apps/web/app/[locale]/courses/[slug]/page.tsx +13 -1
- package/templates/apps/web/app/[locale]/courses/__tests__/page-renderer-migration.test.tsx +3 -3
- package/templates/apps/web/app/[locale]/courses/page.tsx +9 -1
- package/templates/apps/web/app/[locale]/docs/[[...slug]]/page.tsx +1 -0
- package/templates/apps/web/app/[locale]/downloads/__tests__/page-renderer-migration.test.tsx +11 -1
- package/templates/apps/web/app/[locale]/downloads/page.tsx +13 -1
- package/templates/apps/web/app/[locale]/events/[slug]/page.tsx +9 -0
- package/templates/apps/web/app/[locale]/events/__tests__/page-renderer-migration.test.tsx +12 -2
- package/templates/apps/web/app/[locale]/events/page.tsx +9 -1
- package/templates/apps/web/app/[locale]/faq/page.tsx +10 -1
- package/templates/apps/web/app/[locale]/flows/[slug]/FlowStepperClient.tsx +265 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/__tests__/FlowStepperClient.permalink.test.tsx +445 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/__tests__/FlowStepperClient.test.tsx +341 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/__tests__/checkout.actions.test.ts +287 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/__tests__/flow.actions.test.ts +302 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/__tests__/two-route-tool.test.tsx +128 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/checkout.actions.ts +254 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/flow.actions.ts +144 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/page.tsx +108 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/results/[payload]/ResultsClient.tsx +532 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/results/[payload]/ResultsEmailStep.tsx +121 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/results/[payload]/__tests__/ResultsClient.checkout.test.tsx +457 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/results/[payload]/__tests__/page.test.tsx +396 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/results/[payload]/page.tsx +114 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/start/page.tsx +52 -0
- package/templates/apps/web/app/[locale]/how-to/[slug]/page.tsx +13 -1
- package/templates/apps/web/app/[locale]/how-to/__tests__/page-renderer-migration.test.tsx +1 -1
- package/templates/apps/web/app/[locale]/integrations/[slug]/page.tsx +9 -0
- package/templates/apps/web/app/[locale]/integrations/__tests__/page-renderer-migration.test.tsx +3 -3
- package/templates/apps/web/app/[locale]/integrations/page.tsx +13 -1
- package/templates/apps/web/app/[locale]/launch-service/page.tsx +14 -1
- package/templates/apps/web/app/[locale]/layout.tsx +127 -16
- package/templates/apps/web/app/[locale]/page.tsx +10 -1
- package/templates/apps/web/app/[locale]/partners/[slug]/page.tsx +9 -0
- package/templates/apps/web/app/[locale]/partners/__tests__/page-renderer-migration.test.tsx +3 -3
- package/templates/apps/web/app/[locale]/partners/page.tsx +9 -1
- package/templates/apps/web/app/[locale]/products/[slug]/page.tsx +9 -0
- package/templates/apps/web/app/[locale]/products/__tests__/page-renderer-migration.test.tsx +3 -3
- package/templates/apps/web/app/[locale]/products/page.tsx +9 -1
- package/templates/apps/web/app/[locale]/projects/[slug]/page.tsx +13 -1
- package/templates/apps/web/app/[locale]/projects/__tests__/page-renderer-migration.test.tsx +10 -0
- package/templates/apps/web/app/[locale]/projects/apply/ListingApplicationClient.tsx +110 -0
- package/templates/apps/web/app/[locale]/projects/apply/__tests__/ListingApplicationClient.test.tsx +96 -0
- package/templates/apps/web/app/[locale]/projects/page.tsx +13 -1
- package/templates/apps/web/app/[locale]/resources/[slug]/page.tsx +9 -0
- package/templates/apps/web/app/[locale]/resources/__tests__/page-renderer-migration.test.tsx +12 -2
- package/templates/apps/web/app/[locale]/resources/page.tsx +13 -1
- package/templates/apps/web/app/[locale]/schedule/__tests__/page.test.tsx +117 -0
- package/templates/apps/web/app/[locale]/schedule/confirmed/__tests__/page.test.tsx +96 -0
- package/templates/apps/web/app/[locale]/schedule/confirmed/page.tsx +92 -0
- package/templates/apps/web/app/[locale]/schedule/page.tsx +82 -0
- package/templates/apps/web/app/[locale]/services/[slug]/page.tsx +9 -0
- package/templates/apps/web/app/[locale]/services/__tests__/page-renderer-migration.test.tsx +3 -3
- package/templates/apps/web/app/[locale]/services/page.tsx +9 -1
- package/templates/apps/web/app/[locale]/sign-in/__tests__/next-path.test.ts +31 -0
- package/templates/apps/web/app/[locale]/sign-in/__tests__/page.test.tsx +152 -0
- package/templates/apps/web/app/[locale]/sign-in/next-path.ts +0 -0
- package/templates/apps/web/app/[locale]/sign-in/page.tsx +83 -0
- package/templates/apps/web/app/[locale]/sign-in/sign-in-card.tsx +123 -0
- package/templates/apps/web/app/[locale]/software/[slug]/page.tsx +13 -1
- package/templates/apps/web/app/[locale]/software/__tests__/page-renderer-migration.test.tsx +1 -1
- package/templates/apps/web/app/[locale]/tech-articles/[slug]/page.tsx +13 -1
- package/templates/apps/web/app/[locale]/tech-articles/__tests__/page-renderer-migration.test.tsx +1 -1
- package/templates/apps/web/app/[locale]/testimonials/__tests__/page-renderer-migration.test.tsx +11 -1
- package/templates/apps/web/app/[locale]/testimonials/page.tsx +13 -1
- package/templates/apps/web/app/[locale]/thanks/[slug]/__tests__/page.test.tsx +93 -0
- package/templates/apps/web/app/[locale]/thanks/[slug]/page.tsx +48 -0
- package/templates/apps/web/app/[locale]/use-cases/__tests__/page-renderer-migration.test.tsx +11 -1
- package/templates/apps/web/app/[locale]/use-cases/page.tsx +13 -1
- package/templates/apps/web/app/[locale]/whitepapers/[slug]/page.tsx +13 -1
- package/templates/apps/web/app/[locale]/whitepapers/__tests__/page-renderer-migration.test.tsx +1 -1
- package/templates/apps/web/app/globals.css +35 -0
- package/templates/apps/web/app/llms.txt/route.ts +2 -1
- package/templates/apps/web/app/og/route.tsx +10 -2
- package/templates/apps/web/auth.ts +8 -0
- package/templates/apps/web/components/sign-out-trigger.tsx +42 -0
- package/templates/apps/web/content/en/blog/README.txt +25 -0
- package/templates/apps/web/content/en/docs/index.mdx +28 -0
- package/templates/apps/web/jest.config.cjs +90 -27
- package/templates/apps/web/lib/__tests__/site-brand.test.ts +119 -0
- package/templates/apps/web/lib/__tests__/site-theme.test.ts +112 -0
- package/templates/apps/web/lib/__tests__/structured-data.test.tsx +499 -0
- package/templates/apps/web/lib/account-config.ts +13 -0
- package/templates/apps/web/lib/server-api.ts +85 -0
- package/templates/apps/web/lib/site-brand.tsx +121 -0
- package/templates/apps/web/lib/site-theme.ts +74 -0
- package/templates/apps/web/messages/en.json +275 -7
- package/templates/apps/web/middleware.ts +11 -3
- package/templates/apps/web/next.config.mjs +8 -2
- package/templates/apps/web/package.json +17 -7
- package/templates/apps/web/postcss.config.mjs +23 -0
- package/templates/apps/web/public/.well-known/security.txt +3 -3
- package/templates/apps/web/src/lib/routes.ts +15 -2
- package/templates/apps/web/tsconfig.json +1 -16
- package/templates/content/_site.mdx +36 -25
- package/templates/content/en/AboutPage/about.mdx +24 -14
- package/templates/content/en/ContactPage/contact.mdx +23 -14
- package/templates/content/en/FAQPage/faq.mdx +10 -392
- package/templates/content/en/HomePage/home.mdx +14 -285
- package/templates/database/CHANGELOG.md +443 -0
- package/templates/database/LICENSE +201 -0
- package/templates/database/README.md +3 -1
- package/templates/database/__tests__/flows-listing-diagnostic.test.ts +392 -0
- package/templates/database/__tests__/flows-presets.test.ts +173 -0
- package/templates/database/__tests__/prefixed-ids.db.test.ts +146 -0
- package/templates/database/__tests__/seed.test.ts +88 -0
- package/templates/database/__tests__/user-cascade.test.ts +19 -4
- package/templates/database/auth/schema.prisma +521 -0
- package/templates/database/config/schema.prisma +234 -0
- package/templates/database/content/schema.prisma +263 -0
- package/templates/database/flows/listing-diagnostic.ts +182 -0
- package/templates/database/flows/presets.ts +315 -0
- package/templates/database/inbox/__tests__/schema.test.ts +4 -0
- package/templates/database/inbox/schema.prisma +574 -3
- package/templates/database/jest.config.cjs +8 -0
- package/templates/database/migrations/20260712215647_add_multi_tenant_tenancy/migration.sql +201 -0
- package/templates/database/migrations/20260713143320_reanchor_site_config_to_workspace/migration.sql +67 -0
- package/templates/database/migrations/20260713174000_add_audit_logs/migration.sql +46 -0
- package/templates/database/migrations/20260713190000_drop_telemetry_records/migration.sql +25 -0
- package/templates/database/migrations/20260713192000_add_uuidv7_function/migration.sql +49 -0
- package/templates/database/migrations/20260713192429_prefixed_uuid_entity_ids/migration.sql +197 -0
- package/templates/database/migrations/20260713200000_add_org_billing/migration.sql +32 -0
- package/templates/database/migrations/20260714000000_add_lead_promotion_fields/migration.sql +22 -0
- package/templates/database/migrations/20260714010000_add_usage_billing_content_models/migration.sql +151 -0
- package/templates/database/migrations/20260714020000_add_usage_billing_auth_config_models/migration.sql +223 -0
- package/templates/database/migrations/20260714030000_credit_balance_non_negative/migration.sql +22 -0
- package/templates/database/migrations/20260714030000_widen_usage_billing_report_aggregates/migration.sql +32 -0
- package/templates/database/migrations/20260810233516_add_flow_engine_models/migration.sql +40 -0
- package/templates/database/migrations/20260811020000_add_flow_session_abandon_email_columns/migration.sql +4 -0
- package/templates/database/migrations/20260811030000_add_flow_session_abandon_email_index/migration.sql +2 -0
- package/templates/database/migrations/20260811040000_add_flow_session_segment/migration.sql +2 -0
- package/templates/database/migrations/20260811050000_add_deliverable_models/migration.sql +29 -0
- package/templates/database/migrations/20260812000000_add_deliverable_grant_send_columns/migration.sql +6 -0
- package/templates/database/migrations/20260902222948_add_waitlist_experiment_models/migration.sql +39 -0
- package/templates/database/migrations/20260902224500_add_waitlist_id_format_checks/migration.sql +24 -0
- package/templates/database/migrations/20260903004112_add_flow_session_flags_aeo_score/migration.sql +3 -0
- package/templates/database/migrations/20260903010000_add_playbook_instance/migration.sql +33 -0
- package/templates/database/migrations/20260904000000_add_waitlist_followup_send/migration.sql +30 -0
- package/templates/database/migrations/20260905230000_add_flow_checkout/migration.sql +47 -0
- package/templates/database/migrations/20260906000000_add_flow_checkout_idempotency/migration.sql +16 -0
- package/templates/database/migrations/20260907120000_add_project_listing/migration.sql +47 -0
- package/templates/database/migrations/20260907130000_add_project_listing_slack_columns/migration.sql +10 -0
- package/templates/database/migrations/20260907180000_add_listing_csv_send/migration.sql +26 -0
- package/templates/database/migrations/20260909120000_project_listings_platform/migration.sql +90 -0
- package/templates/database/migrations/20260909180000_listing_draft_and_fields/migration.sql +174 -0
- package/templates/database/migrations/20260910120000_listing_public_site_key/migration.sql +14 -0
- package/templates/database/migrations/20260911120000_listing_copy_edit_audit/migration.sql +25 -0
- package/templates/database/migrations/20260911140000_listing_structured_address/migration.sql +32 -0
- package/templates/database/migrations/20260911180000_consent_grants/migration.sql +71 -0
- package/templates/database/migrations/20260911200000_listing_site_answers/migration.sql +30 -0
- package/templates/database/migrations/20260912120000_listing_owner_link/migration.sql +49 -0
- package/templates/database/ops/schema.prisma +27 -0
- package/templates/database/package.json +42 -4
- package/templates/database/prisma.config.ts +1 -1
- package/templates/database/schema.prisma +19 -435
- package/templates/database/seed-test.ts +14 -4
- package/templates/database/seed.ts +148 -0
- package/templates/database/tenancy.ts +45 -0
- package/templates/database/tsconfig.flows.json +15 -0
- package/templates/database/tsconfig.json +7 -1
- package/templates/database/tsconfig.tenancy.json +14 -0
- package/templates/package.json +30 -55
- package/templates/pnpm-workspace.yaml +0 -3
- package/templates/project.yaml +1 -1
- package/templates/tsconfig.json +1 -37
- package/templates/apps/web/__tests__/auth/adversarial/cookie-attributes.test.ts +0 -94
- package/templates/apps/web/__tests__/auth/adversarial/oauth-state-parameter.test.ts +0 -75
- package/templates/apps/web/__tests__/auth/adversarial/redirect-uri-allowlist.test.ts +0 -82
- package/templates/apps/web/__tests__/auth/env-helpers.test.ts +0 -168
- package/templates/apps/web/__tests__/authority-list-routes.test.tsx +0 -208
- package/templates/apps/web/__tests__/better-stack.test.ts +0 -66
- package/templates/apps/web/__tests__/blog-dir-resolution.test.ts +0 -87
- package/templates/apps/web/__tests__/blog-source-populated.test.ts +0 -130
- package/templates/apps/web/__tests__/data-testid-coverage.test.tsx +0 -60
- package/templates/apps/web/__tests__/google-analytics.test.tsx +0 -104
- package/templates/apps/web/__tests__/i18n/middleware.test.ts +0 -119
- package/templates/apps/web/__tests__/i18n/routing.test.ts +0 -114
- package/templates/apps/web/__tests__/i18n/translations.test.ts +0 -191
- package/templates/apps/web/__tests__/json-ld.test.ts +0 -98
- package/templates/apps/web/__tests__/knowledge-events-routes.test.tsx +0 -580
- package/templates/apps/web/__tests__/layout-stealth.test.ts +0 -39
- package/templates/apps/web/__tests__/lighthouse-fixtures/improvement-image-shrink.tsx +0 -103
- package/templates/apps/web/__tests__/lighthouse-fixtures/override-fixture.md +0 -114
- package/templates/apps/web/__tests__/lighthouse-fixtures/regression-bloat.tsx +0 -94
- package/templates/apps/web/__tests__/page.test.tsx +0 -230
- package/templates/apps/web/__tests__/products-services-phase1.test.tsx +0 -321
- package/templates/apps/web/__tests__/projects-routes.test.tsx +0 -392
- package/templates/apps/web/__tests__/resources-downloads-integrations-phase2.test.tsx +0 -475
- package/templates/apps/web/__tests__/routes/ai-plugin-json.test.ts +0 -53
- package/templates/apps/web/__tests__/routes/blog-route.test.tsx +0 -191
- package/templates/apps/web/__tests__/routes/llms-txt.test.ts +0 -123
- package/templates/apps/web/__tests__/routes/robots-txt.test.ts +0 -52
- package/templates/apps/web/__tests__/routes/sitemap-xml.test.ts +0 -78
- package/templates/apps/web/__tests__/routes/well-known-mcp.test.ts +0 -203
- package/templates/apps/web/__tests__/section-routes.test.tsx +0 -693
- package/templates/apps/web/__tests__/security-headers.test.ts +0 -201
- package/templates/apps/web/__tests__/sentry-config.test.ts +0 -116
- package/templates/apps/web/__tests__/sitemap-locales.test.ts +0 -415
- package/templates/apps/web/__tests__/standalone-informational-routes.test.tsx +0 -844
- package/templates/apps/web/app/[locale]/__tests__/layout.test.tsx +0 -120
- package/templates/apps/web/app/[locale]/__tests__/page-renderer-migration.test.tsx +0 -202
- package/templates/apps/web/app/__tests__/error-boundaries.test.tsx +0 -152
- package/templates/apps/web/content/en/blog/index.mdx +0 -15
- package/templates/apps/web/content/en/blog/launching-ailk.mdx +0 -20
- package/templates/apps/web/content/en/docs/getting-started.mdx +0 -30
- package/templates/content/.gitkeep +0 -0
- package/templates/content/CLAUDE.md +0 -85
- package/templates/content/ar/HomePage/home.mdx +0 -123
- package/templates/content/ar/_site.mdx +0 -35
- package/templates/content/de/_site.mdx +0 -29
- package/templates/content/en/.gitkeep +0 -0
- package/templates/content/en/AboutPage/about.schema.json +0 -82
- package/templates/content/en/BookCall/book-call.mdx +0 -19
- package/templates/content/en/BookCall/book-call.schema.json +0 -121
- package/templates/content/en/BreadcrumbList/site-breadcrumbs.mdx +0 -20
- package/templates/content/en/CareersList/careers.mdx +0 -24
- package/templates/content/en/CaseStudiesList/case-studies.mdx +0 -22
- package/templates/content/en/CaseStudiesList/showcase.mdx +0 -8
- package/templates/content/en/CaseStudy/ailk-aeo-rollout.mdx +0 -32
- package/templates/content/en/CaseStudy/schema-builder-migration.mdx +0 -41
- package/templates/content/en/ClientsList/clients.mdx +0 -38
- package/templates/content/en/ContactPage/contact.schema.json +0 -100
- package/templates/content/en/ContactPoint/primary.mdx +0 -14
- package/templates/content/en/Course/aeo-fundamentals.mdx +0 -37
- package/templates/content/en/Course/schema-builder-workshop.mdx +0 -62
- package/templates/content/en/CoursesList/courses.mdx +0 -22
- package/templates/content/en/DownloadsList/downloads.mdx +0 -22
- package/templates/content/en/Event/aeo-office-hours-may-2026.mdx +0 -39
- package/templates/content/en/Event/ailk-launch-day-2026.mdx +0 -35
- package/templates/content/en/EventsList/events.mdx +0 -26
- package/templates/content/en/FAQPage/faq.schema.json +0 -231
- package/templates/content/en/GlossaryList/glossary.mdx +0 -19
- package/templates/content/en/GlossaryList/glossary.schema.json +0 -300
- package/templates/content/en/HomePage/home.schema.json +0 -88
- package/templates/content/en/HomePage/launch-service.mdx +0 -475
- package/templates/content/en/HomePage/launch-service.schema.json +0 -138
- package/templates/content/en/HowTo/add-mdx-content.mdx +0 -38
- package/templates/content/en/HowTo/configure-aeo-scoring.mdx +0 -35
- package/templates/content/en/HowTo/set-up-json-ld.mdx +0 -36
- package/templates/content/en/Integration/github-actions.mdx +0 -31
- package/templates/content/en/Integration/openai-api.mdx +0 -26
- package/templates/content/en/Integration/vercel.mdx +0 -32
- package/templates/content/en/IntegrationsList/integrations.mdx +0 -22
- package/templates/content/en/JobPosting/content-strategist.mdx +0 -46
- package/templates/content/en/JobPosting/developer-advocate.mdx +0 -47
- package/templates/content/en/JobPosting/senior-fullstack-engineer.mdx +0 -57
- package/templates/content/en/LandingPage/aeo-audit.mdx +0 -19
- package/templates/content/en/LandingPage/aeo-audit.schema.json +0 -92
- package/templates/content/en/LandingPage/agency-waitlist.mdx +0 -340
- package/templates/content/en/LandingPage/agency-waitlist.schema.json +0 -152
- package/templates/content/en/LandingPage/developers.mdx +0 -19
- package/templates/content/en/LandingPage/developers.schema.json +0 -109
- package/templates/content/en/LandingPage/for-agencies.mdx +0 -390
- package/templates/content/en/LandingPage/for-agencies.schema.json +0 -107
- package/templates/content/en/LandingPage/for-ai-search-agencies.mdx +0 -417
- package/templates/content/en/LandingPage/for-ai-search-agencies.schema.json +0 -105
- package/templates/content/en/LandingPage/for-businesses.mdx +0 -19
- package/templates/content/en/LandingPage/for-businesses.schema.json +0 -96
- package/templates/content/en/LandingPage/platform.mdx +0 -369
- package/templates/content/en/LandingPage/platform.schema.json +0 -166
- package/templates/content/en/LandingPage/vs-ai-website-builders.mdx +0 -19
- package/templates/content/en/LandingPage/vs-ai-website-builders.schema.json +0 -102
- package/templates/content/en/LandingPage/vs-wordpress.mdx +0 -19
- package/templates/content/en/LandingPage/vs-wordpress.schema.json +0 -53
- package/templates/content/en/NewsletterSignup/newsletter.mdx +0 -236
- package/templates/content/en/NewsletterSignup/newsletter.schema.json +0 -91
- package/templates/content/en/Organization/site-owner.mdx +0 -16
- package/templates/content/en/Partner/prisma.mdx +0 -31
- package/templates/content/en/Partner/supabase.mdx +0 -30
- package/templates/content/en/Partner/vercel.mdx +0 -28
- package/templates/content/en/PartnersList/partners.mdx +0 -22
- package/templates/content/en/Person/founder.mdx +0 -18
- package/templates/content/en/Pricing/pricing.mdx +0 -538
- package/templates/content/en/Pricing/pricing.schema.json +0 -209
- package/templates/content/en/PrivacyPage/privacy.mdx +0 -165
- package/templates/content/en/PrivacyPage/privacy.schema.json +0 -64
- package/templates/content/en/Product/ailk.mdx +0 -19
- package/templates/content/en/Product/ailk.schema.json +0 -94
- package/templates/content/en/Product/api-launch-kit.mdx +0 -26
- package/templates/content/en/Product/launch-kit.mdx +0 -28
- package/templates/content/en/ProductsList/products.mdx +0 -26
- package/templates/content/en/Project/ailk-phase-2.mdx +0 -54
- package/templates/content/en/ProjectsList/projects.mdx +0 -25
- package/templates/content/en/ResourceDetail/aeo-scoring-guide.mdx +0 -27
- package/templates/content/en/ResourceDetail/content-model-whitepaper.mdx +0 -28
- package/templates/content/en/ResourceDetail/schema-org-quick-reference.mdx +0 -39
- package/templates/content/en/ResourcesHub/resources.mdx +0 -22
- package/templates/content/en/Service/consulting.mdx +0 -22
- package/templates/content/en/Service/implementation.mdx +0 -30
- package/templates/content/en/Service/launch-service.mdx +0 -232
- package/templates/content/en/Service/launch.mdx +0 -228
- package/templates/content/en/ServicesList/services.mdx +0 -84
- package/templates/content/en/SoftwareProduct/ailk-aeo.mdx +0 -44
- package/templates/content/en/SoftwareProduct/ailk-content-adapters.mdx +0 -47
- package/templates/content/en/SoftwareProduct/ailk-schema.mdx +0 -49
- package/templates/content/en/TeamList/team.mdx +0 -63
- package/templates/content/en/TeamMember/founder.mdx +0 -72
- package/templates/content/en/TermsPage/terms.mdx +0 -19
- package/templates/content/en/TermsPage/terms.schema.json +0 -99
- package/templates/content/en/TestimonialsList/testimonials.mdx +0 -44
- package/templates/content/en/UseCasesList/use-cases.mdx +0 -30
- package/templates/content/en/Whitepaper/ax-first-product-development.mdx +0 -27
- package/templates/content/en/Whitepaper/open-core-commercial-strategy.mdx +0 -27
- package/templates/content/en/Whitepaper/structured-data-for-answer-engines.mdx +0 -31
- package/templates/content/en-XA/AboutPage/about.mdx +0 -8
- package/templates/content/en-XA/FAQPage/faq.mdx +0 -8
- package/templates/content/en-XA/HomePage/home.mdx +0 -8
- package/templates/content/es/_site.mdx +0 -30
- package/templates/content/fr/_site.mdx +0 -30
- package/templates/content/ja/_site.mdx +0 -30
- package/templates/content/pt-BR/AboutPage/about.mdx +0 -8
- package/templates/content/pt-BR/FAQPage/faq.mdx +0 -8
- package/templates/content/pt-BR/HomePage/home.mdx +0 -23
package/dist/parse-args.d.ts
CHANGED
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The recognized module vocabulary for the `--modules` selector.
|
|
3
|
+
*
|
|
4
|
+
* A MODULE is a composable, potentially full-stack unit AILK's three-tier app
|
|
5
|
+
* is composed from (see architecture.yaml `composition_model`). At the MVP
|
|
6
|
+
* plumbing layer only the selection is threaded through; per-module template
|
|
7
|
+
* composition is downstream work, so the default (`marketing`) reproduces
|
|
8
|
+
* today's fixed-tree scaffold exactly.
|
|
9
|
+
*/
|
|
10
|
+
export declare const RECOGNIZED_MODULES: readonly ["marketing", "docs", "multi-tenant", "scheduling"];
|
|
11
|
+
export type ModuleName = (typeof RECOGNIZED_MODULES)[number];
|
|
1
12
|
export interface CliOptions {
|
|
2
13
|
/** Positional target directory (the dir to scaffold into). Optional only
|
|
3
14
|
* when `help` or `version` is set. */
|
|
@@ -5,9 +16,44 @@ export interface CliOptions {
|
|
|
5
16
|
install: boolean;
|
|
6
17
|
help: boolean;
|
|
7
18
|
version: boolean;
|
|
19
|
+
/** Selected modules (recognized: marketing, docs, multi-tenant, scheduling).
|
|
20
|
+
* Defaults to ['marketing'] when the flag is absent. */
|
|
21
|
+
modules: string[];
|
|
22
|
+
/** Explicitly requested route surfaces (`--surfaces`). Empty when the flag is
|
|
23
|
+
* absent — the module set alone then decides (see surfaces.ts
|
|
24
|
+
* `resolveSurfaces`). Validated, lowercased, deduped and sorted. */
|
|
25
|
+
surfaces: string[];
|
|
26
|
+
/**
|
|
27
|
+
* When set, regenerate the target's COMPONENT-CATALOG.md in place from the
|
|
28
|
+
* catalog this create-ailk ships (catalog-sync mode) and exit. Mirrors
|
|
29
|
+
* `--sync-architecture`: data-only, one file, an already-scaffolded target.
|
|
30
|
+
*/
|
|
31
|
+
syncCatalog: boolean;
|
|
32
|
+
/**
|
|
33
|
+
* When set, a fresh scaffold ALSO gets COMPONENT-CATALOG.md. Off by default
|
|
34
|
+
* so a scaffold that does not ask for the catalog is byte-identical to the
|
|
35
|
+
* pre-#4636 output.
|
|
36
|
+
*/
|
|
37
|
+
withCatalog: boolean;
|
|
38
|
+
/** When set, the raw `--sync-architecture <csv>` value: regenerate the
|
|
39
|
+
* target's architecture.yaml in place from this module set (sync mode). The
|
|
40
|
+
* value is validated through `parseModules` at parse time; cli.ts re-parses
|
|
41
|
+
* it to the module list. Undefined when the flag is absent (scaffold mode). */
|
|
42
|
+
syncArchitecture: string | undefined;
|
|
8
43
|
}
|
|
9
44
|
export declare class ParseError extends Error {
|
|
10
45
|
constructor(message: string);
|
|
11
46
|
}
|
|
12
|
-
export declare const helpText
|
|
47
|
+
export declare const helpText: string;
|
|
13
48
|
export declare function parseCliArgs(argv: string[]): CliOptions;
|
|
49
|
+
/**
|
|
50
|
+
* Parse a module CSV (the `--modules` or `--sync-architecture` value) into a
|
|
51
|
+
* validated, normalized string[].
|
|
52
|
+
*
|
|
53
|
+
* Splits on `,`, trims and lowercases each entry, drops empties, and validates
|
|
54
|
+
* each against RECOGNIZED_MODULES. An absent flag (or an all-empty value)
|
|
55
|
+
* defaults to DEFAULT_MODULES (`['marketing']`) — reproducing today's scaffold.
|
|
56
|
+
*
|
|
57
|
+
* @throws ParseError on an unrecognized module value, naming the recognized set.
|
|
58
|
+
*/
|
|
59
|
+
export declare function parseModules(raw: string | undefined): string[];
|
package/dist/parse-args.js
CHANGED
|
@@ -8,6 +8,24 @@
|
|
|
8
8
|
* top-level catch turns this into a stderr write + non-zero exit.
|
|
9
9
|
*/
|
|
10
10
|
import { parseArgs } from "node:util";
|
|
11
|
+
import { RECOGNIZED_SURFACES, parseSurfaces } from "./surfaces.js";
|
|
12
|
+
/**
|
|
13
|
+
* The recognized module vocabulary for the `--modules` selector.
|
|
14
|
+
*
|
|
15
|
+
* A MODULE is a composable, potentially full-stack unit AILK's three-tier app
|
|
16
|
+
* is composed from (see architecture.yaml `composition_model`). At the MVP
|
|
17
|
+
* plumbing layer only the selection is threaded through; per-module template
|
|
18
|
+
* composition is downstream work, so the default (`marketing`) reproduces
|
|
19
|
+
* today's fixed-tree scaffold exactly.
|
|
20
|
+
*/
|
|
21
|
+
export const RECOGNIZED_MODULES = [
|
|
22
|
+
"marketing",
|
|
23
|
+
"docs",
|
|
24
|
+
"multi-tenant",
|
|
25
|
+
"scheduling",
|
|
26
|
+
];
|
|
27
|
+
/** The default module selection when `--modules` is absent (reproduces today's scaffold). */
|
|
28
|
+
const DEFAULT_MODULES = ["marketing"];
|
|
11
29
|
export class ParseError extends Error {
|
|
12
30
|
constructor(message) {
|
|
13
31
|
super(message);
|
|
@@ -26,6 +44,37 @@ Arguments:
|
|
|
26
44
|
rejected.
|
|
27
45
|
|
|
28
46
|
Options:
|
|
47
|
+
--modules <csv> Comma-separated list of modules to compose the site
|
|
48
|
+
from (recognized: ${RECOGNIZED_MODULES.join(", ")}).
|
|
49
|
+
Defaults to \`marketing\`, which reproduces today's
|
|
50
|
+
scaffold. A module is a composable unit across the
|
|
51
|
+
three tiers (data · API · presentation).
|
|
52
|
+
--surfaces <csv> Comma-separated route surfaces to scaffold IN
|
|
53
|
+
ADDITION to the core set (/, /about, /contact, /faq,
|
|
54
|
+
/thanks). Recognized: ${RECOGNIZED_SURFACES.join(", ")}.
|
|
55
|
+
Surfaces the declared architecture does not carry are
|
|
56
|
+
NOT scaffolded — their routes are absent, so a fresh
|
|
57
|
+
site never serves a stock page with placeholder
|
|
58
|
+
content. Add one later with the \`scaffold-page\`
|
|
59
|
+
skill, or re-run with the surface named here.
|
|
60
|
+
--sync-architecture <csv> Regenerate architecture.yaml in place in an
|
|
61
|
+
already-scaffolded repo from the given module set
|
|
62
|
+
(recognized: ${RECOGNIZED_MODULES.join(", ")}), then
|
|
63
|
+
exit. Data-only: rewrites only architecture.yaml, at
|
|
64
|
+
the target dir (positional arg, else cwd). Bypasses
|
|
65
|
+
the scaffold path — copies no template, runs no
|
|
66
|
+
install.
|
|
67
|
+
--with-catalog Also write COMPONENT-CATALOG.md — the capability-
|
|
68
|
+
indexed index of every @working-theory/ui component,
|
|
69
|
+
so a worker in the scaffolded repo can check what
|
|
70
|
+
already exists before building it. Off by default; a
|
|
71
|
+
scaffold without it is unchanged.
|
|
72
|
+
--sync-catalog Refresh COMPONENT-CATALOG.md in place in an already-
|
|
73
|
+
scaffolded repo from the catalog this create-ailk
|
|
74
|
+
ships, then exit. Data-only: rewrites only that one
|
|
75
|
+
file, at the target dir (positional arg, else cwd).
|
|
76
|
+
Bypasses the scaffold path — copies no template, runs
|
|
77
|
+
no install. Re-run after upgrading create-ailk.
|
|
29
78
|
--install After scaffolding, run \`pnpm install\` in the
|
|
30
79
|
target directory. Off by default.
|
|
31
80
|
--help, -h Print this message.
|
|
@@ -50,6 +99,11 @@ export function parseCliArgs(argv) {
|
|
|
50
99
|
strict: true,
|
|
51
100
|
allowPositionals: true,
|
|
52
101
|
options: {
|
|
102
|
+
modules: { type: "string" },
|
|
103
|
+
surfaces: { type: "string" },
|
|
104
|
+
"sync-architecture": { type: "string" },
|
|
105
|
+
"sync-catalog": { type: "boolean", default: false },
|
|
106
|
+
"with-catalog": { type: "boolean", default: false },
|
|
53
107
|
install: { type: "boolean", default: false },
|
|
54
108
|
help: { type: "boolean", default: false, short: "h" },
|
|
55
109
|
version: { type: "boolean", default: false },
|
|
@@ -62,9 +116,52 @@ export function parseCliArgs(argv) {
|
|
|
62
116
|
const help = parsed.values.help === true;
|
|
63
117
|
const version = parsed.values.version === true;
|
|
64
118
|
const install = parsed.values.install === true;
|
|
65
|
-
|
|
119
|
+
const modules = parseModules(parsed.values.modules);
|
|
120
|
+
const surfaces = parseSurfaceList(parsed.values.surfaces);
|
|
121
|
+
const syncArchitecture = parsed.values["sync-architecture"];
|
|
122
|
+
const syncCatalog = parsed.values["sync-catalog"] === true;
|
|
123
|
+
const withCatalog = parsed.values["with-catalog"] === true;
|
|
124
|
+
// The two sync modes each exit after rewriting their one file, so asking for
|
|
125
|
+
// both in one invocation has no coherent meaning.
|
|
126
|
+
if (syncCatalog && syncArchitecture !== undefined) {
|
|
127
|
+
throw new ParseError("--sync-catalog and --sync-architecture cannot be combined; run them one at a time");
|
|
128
|
+
}
|
|
129
|
+
// Validate the sync-architecture value now, through the SAME parseModules
|
|
130
|
+
// path `--modules` uses, so an unknown module throws ParseError at parse time
|
|
131
|
+
// (cli.ts re-parses the raw value to the module list in sync mode).
|
|
132
|
+
if (syncArchitecture !== undefined) {
|
|
133
|
+
parseModules(syncArchitecture);
|
|
134
|
+
}
|
|
135
|
+
// When help or version is set, target is optional (help/version win).
|
|
66
136
|
if (help || version) {
|
|
67
|
-
return {
|
|
137
|
+
return {
|
|
138
|
+
target: undefined,
|
|
139
|
+
install,
|
|
140
|
+
help,
|
|
141
|
+
version,
|
|
142
|
+
modules,
|
|
143
|
+
surfaces,
|
|
144
|
+
syncCatalog: false,
|
|
145
|
+
withCatalog: false,
|
|
146
|
+
syncArchitecture: undefined,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
// Sync modes: the target dir is optional (positional if given, else cwd).
|
|
150
|
+
if (syncArchitecture !== undefined || syncCatalog) {
|
|
151
|
+
if (parsed.positionals.length > 1) {
|
|
152
|
+
throw new ParseError(`expected at most one target directory, got ${parsed.positionals.length}`);
|
|
153
|
+
}
|
|
154
|
+
return {
|
|
155
|
+
target: parsed.positionals[0],
|
|
156
|
+
install,
|
|
157
|
+
help,
|
|
158
|
+
version,
|
|
159
|
+
modules,
|
|
160
|
+
surfaces,
|
|
161
|
+
syncCatalog,
|
|
162
|
+
withCatalog,
|
|
163
|
+
syncArchitecture,
|
|
164
|
+
};
|
|
68
165
|
}
|
|
69
166
|
if (parsed.positionals.length === 0) {
|
|
70
167
|
throw new ParseError("missing target directory. Usage: pnpm create ailk@latest <target-dir>");
|
|
@@ -77,5 +174,49 @@ export function parseCliArgs(argv) {
|
|
|
77
174
|
install,
|
|
78
175
|
help,
|
|
79
176
|
version,
|
|
177
|
+
modules,
|
|
178
|
+
surfaces,
|
|
179
|
+
syncCatalog,
|
|
180
|
+
withCatalog,
|
|
181
|
+
syncArchitecture: undefined,
|
|
80
182
|
};
|
|
81
183
|
}
|
|
184
|
+
/**
|
|
185
|
+
* Parse + validate the `--surfaces` CSV, re-throwing an unrecognized-surface
|
|
186
|
+
* failure as a ParseError so every CLI parse failure reaches the orchestrator's
|
|
187
|
+
* top-level catch through ONE error type.
|
|
188
|
+
*/
|
|
189
|
+
function parseSurfaceList(raw) {
|
|
190
|
+
try {
|
|
191
|
+
return parseSurfaces(raw);
|
|
192
|
+
}
|
|
193
|
+
catch (err) {
|
|
194
|
+
throw new ParseError(err.message);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Parse a module CSV (the `--modules` or `--sync-architecture` value) into a
|
|
199
|
+
* validated, normalized string[].
|
|
200
|
+
*
|
|
201
|
+
* Splits on `,`, trims and lowercases each entry, drops empties, and validates
|
|
202
|
+
* each against RECOGNIZED_MODULES. An absent flag (or an all-empty value)
|
|
203
|
+
* defaults to DEFAULT_MODULES (`['marketing']`) — reproducing today's scaffold.
|
|
204
|
+
*
|
|
205
|
+
* @throws ParseError on an unrecognized module value, naming the recognized set.
|
|
206
|
+
*/
|
|
207
|
+
export function parseModules(raw) {
|
|
208
|
+
if (raw === undefined)
|
|
209
|
+
return [...DEFAULT_MODULES];
|
|
210
|
+
const requested = raw
|
|
211
|
+
.split(",")
|
|
212
|
+
.map((m) => m.trim().toLowerCase())
|
|
213
|
+
.filter(Boolean);
|
|
214
|
+
if (requested.length === 0)
|
|
215
|
+
return [...DEFAULT_MODULES];
|
|
216
|
+
for (const m of requested) {
|
|
217
|
+
if (!RECOGNIZED_MODULES.includes(m)) {
|
|
218
|
+
throw new ParseError(`unknown module "${m}". Recognized: ${RECOGNIZED_MODULES.join(", ")}`);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
return requested;
|
|
222
|
+
}
|
package/dist/programmatic.d.ts
CHANGED
|
@@ -15,6 +15,9 @@
|
|
|
15
15
|
* import { scaffoldSync } from './programmatic.js';
|
|
16
16
|
* const result = scaffoldSync({ targetDir: '/tmp/my-site', projectName: 'my-site' });
|
|
17
17
|
*/
|
|
18
|
+
import { CATALOG_TARGET_PATH } from "./component-catalog.js";
|
|
19
|
+
import { type ModuleName } from "./parse-args.js";
|
|
20
|
+
import { type SyncRoutesResult } from "./sync-routes.js";
|
|
18
21
|
export interface ScaffoldOptions {
|
|
19
22
|
/** Absolute or relative path to the target directory. Must not exist or be empty. */
|
|
20
23
|
targetDir: string;
|
|
@@ -25,12 +28,57 @@ export interface ScaffoldOptions {
|
|
|
25
28
|
* Ignored at runtime until named presets are implemented.
|
|
26
29
|
*/
|
|
27
30
|
preset?: string;
|
|
31
|
+
/**
|
|
32
|
+
* Selected modules (recognized: marketing, docs, multi-tenant). Defaults to
|
|
33
|
+
* ['marketing']. The scaffolder does NOT yet vary the copied template tree by
|
|
34
|
+
* module (per-module template composition is downstream work), so the copied
|
|
35
|
+
* files are today's fixed-tree scaffold — BUT the derived `architecture.yaml`
|
|
36
|
+
* (its code-boundary config) IS a function of this set (spec #3787), written
|
|
37
|
+
* at the target root after the template copy.
|
|
38
|
+
*
|
|
39
|
+
* As of #4154 the module set ALSO selects route surfaces (via
|
|
40
|
+
* `surfaces.ts` `MODULE_SURFACES`), so the copied tree is no longer
|
|
41
|
+
* module-invariant: a surface no module carries is not scaffolded at all.
|
|
42
|
+
*/
|
|
43
|
+
modules?: string[];
|
|
44
|
+
/**
|
|
45
|
+
* Route surfaces to scaffold IN ADDITION to the core set (`--surfaces`).
|
|
46
|
+
* Omitted ⟹ the module set alone decides. Every gateable surface not in the
|
|
47
|
+
* resolved set has its route directories skipped by the copy, so its routes
|
|
48
|
+
* are ABSENT from the output rather than serving placeholder content (#4154).
|
|
49
|
+
*/
|
|
50
|
+
surfaces?: string[];
|
|
51
|
+
/**
|
|
52
|
+
* Also write COMPONENT-CATALOG.md at the target root (`--with-catalog`).
|
|
53
|
+
* Defaults to false: a scaffold that does not ask for the catalog produces
|
|
54
|
+
* byte-identical output to the pre-#4636 scaffolder.
|
|
55
|
+
*/
|
|
56
|
+
withCatalog?: boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Licensed module delivery (K1, #5089 — Flavor 3). Consumed ONLY by the
|
|
59
|
+
* async `scaffold()` below — `scaffoldSync` remains oblivious to licensing
|
|
60
|
+
* entirely, so every existing synchronous caller (the vast majority of this
|
|
61
|
+
* package's own tests) is untouched by this card.
|
|
62
|
+
*
|
|
63
|
+
* `licenseKey` defaults to `process.env["AILK_LICENSE_KEY"]`; `fetchImpl`
|
|
64
|
+
* defaults to `globalThis.fetch` (injectable so tests — and this repo's own
|
|
65
|
+
* evidence runs — never make a live network call). Both are ignored
|
|
66
|
+
* entirely when `modules` names no paid module (the regression floor: a
|
|
67
|
+
* bare/all-Free scaffold reads neither).
|
|
68
|
+
*/
|
|
69
|
+
licenseKey?: string;
|
|
70
|
+
/** Overrides `AILK_MODULE_REGISTRY_URL` / the built-in module-distribution default. */
|
|
71
|
+
moduleRegistryUrl?: string;
|
|
72
|
+
/** Injected fetch for tests. Never a live network call in CI or in this repo's evidence runs. */
|
|
73
|
+
fetchImpl?: typeof fetch;
|
|
28
74
|
}
|
|
29
75
|
export interface ScaffoldResult {
|
|
30
76
|
/** Resolved absolute path to the scaffolded directory. */
|
|
31
77
|
targetDir: string;
|
|
32
78
|
/** Number of files written. */
|
|
33
79
|
filesCreated: number;
|
|
80
|
+
/** The gateable route surfaces this scaffold declares (sorted). */
|
|
81
|
+
surfaces: string[];
|
|
34
82
|
}
|
|
35
83
|
/**
|
|
36
84
|
* Scaffold an AI Launch Kit starter project into targetDir (synchronous).
|
|
@@ -42,8 +90,117 @@ export declare function scaffoldSync(opts: ScaffoldOptions): ScaffoldResult;
|
|
|
42
90
|
/**
|
|
43
91
|
* Scaffold an AI Launch Kit starter project into targetDir (async wrapper).
|
|
44
92
|
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
93
|
+
* The ONLY entry point that resolves paid modules (K1, #5089 — Flavor 3):
|
|
94
|
+
*
|
|
95
|
+
* 1. Classify the requested module set into free / paid (`module-tier.ts`).
|
|
96
|
+
* 2. `resolvePaidModules` — zero-paid-modules returns instantly with no key
|
|
97
|
+
* read and no network call (the regression floor). A paid module with
|
|
98
|
+
* no key, or a licence the module distribution rejects, throws
|
|
99
|
+
* `LicenseRequiredError` HERE — before anything is written to disk.
|
|
100
|
+
* 3. `scaffoldSync` — unchanged, today's local `templates/` copy.
|
|
101
|
+
* 4. Merge each resolved paid module's fetched bundle into the freshly
|
|
102
|
+
* scaffolded tree (`extractModuleBundle`).
|
|
103
|
+
*
|
|
104
|
+
* `scaffoldSync` itself stays licensing-oblivious on purpose: every existing
|
|
105
|
+
* synchronous caller (this package's own test suite, overwhelmingly) is
|
|
106
|
+
* unaffected by this card — only a caller that goes through THIS function
|
|
107
|
+
* with a paid module in `opts.modules` exercises the gate at all.
|
|
48
108
|
*/
|
|
49
109
|
export declare function scaffold(opts: ScaffoldOptions): Promise<ScaffoldResult>;
|
|
110
|
+
export { LicenseRequiredError, type ResolvePaidModulesOptions, } from "./lib/module-license-gate.js";
|
|
111
|
+
export { FREE_MODULES, PAID_MODULES, classifyModules } from "./lib/module-tier.js";
|
|
112
|
+
export type { ModuleName };
|
|
113
|
+
export interface SyncArchitectureOptions {
|
|
114
|
+
/**
|
|
115
|
+
* The already-scaffolded repo to sync (absolute or relative). It MUST exist
|
|
116
|
+
* and contain an `architecture.yaml` — the inverse of scaffold's empty-target
|
|
117
|
+
* rule (spec D3), so this path does NOT reuse `validateTarget`.
|
|
118
|
+
*/
|
|
119
|
+
targetDir: string;
|
|
120
|
+
/** The module set to regenerate architecture.yaml from (validated upstream). */
|
|
121
|
+
modules: string[];
|
|
122
|
+
/** Route surfaces to declare in addition to the module-derived set (#4154). */
|
|
123
|
+
surfaces?: string[];
|
|
124
|
+
}
|
|
125
|
+
export interface SyncArchitectureResult {
|
|
126
|
+
/** Resolved absolute path to the synced directory. */
|
|
127
|
+
targetDir: string;
|
|
128
|
+
/** The gateable route surfaces the regenerated architecture.yaml declares. */
|
|
129
|
+
surfaces: string[];
|
|
130
|
+
/**
|
|
131
|
+
* Surface drift — route and content directories that EXIST in the target but
|
|
132
|
+
* belong to a surface the regenerated declaration does not carry. Reported,
|
|
133
|
+
* never removed: deleting files in an already-scaffolded repo is the
|
|
134
|
+
* operator's call, made as one reviewable commit (spec #4154 D5). Repo-
|
|
135
|
+
* relative, sorted.
|
|
136
|
+
*/
|
|
137
|
+
undeclared: string[];
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Regenerate an already-scaffolded repo's `architecture.yaml` in place from a
|
|
141
|
+
* module set (the "module added later" sync path — spec #3561).
|
|
142
|
+
*
|
|
143
|
+
* Mirrors scaffoldSync's architecture-write step MINUS the template copy: it
|
|
144
|
+
* overwrites exactly the one `architecture.yaml` file at the target root via
|
|
145
|
+
* the shipped, byte-deterministic `deriveArchitecture`, so a synced repo's
|
|
146
|
+
* config is identical to a fresh scaffold's for the same module set. Data-only
|
|
147
|
+
* and non-destructive: no template re-copy, no subprocess, no other file
|
|
148
|
+
* touched.
|
|
149
|
+
*
|
|
150
|
+
* Validates the target is an EXISTING scaffolded dir (an existing directory
|
|
151
|
+
* containing `architecture.yaml`) — the inverse of `validateTarget` (D3).
|
|
152
|
+
* Throws Error on a missing target, a non-directory target, or a directory with
|
|
153
|
+
* no `architecture.yaml`; the CLI's top-level catch turns that into a
|
|
154
|
+
* `[create-ailk] <message>` stderr write + exit 1.
|
|
155
|
+
*/
|
|
156
|
+
export declare function syncArchitectureSync(opts: SyncArchitectureOptions): SyncArchitectureResult;
|
|
157
|
+
export interface SyncCatalogResult {
|
|
158
|
+
/** Resolved absolute path to the synced directory. */
|
|
159
|
+
targetDir: string;
|
|
160
|
+
/** Absolute path of the file written. */
|
|
161
|
+
catalogPath: string;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Refresh an already-scaffolded repo's `COMPONENT-CATALOG.md` in place from the
|
|
165
|
+
* catalog this create-ailk ships (#4636).
|
|
166
|
+
*
|
|
167
|
+
* The same shape as `syncArchitectureSync`, with a different artifact: validate
|
|
168
|
+
* the target is an existing scaffolded dir, overwrite exactly one file, touch
|
|
169
|
+
* nothing else, spawn nothing. The catalog is regenerated from `packages/ui` at
|
|
170
|
+
* publish time, so re-running this after upgrading create-ailk is how a site
|
|
171
|
+
* picks up components added since it was scaffolded.
|
|
172
|
+
*/
|
|
173
|
+
export declare function syncCatalogSync(opts: {
|
|
174
|
+
targetDir: string;
|
|
175
|
+
}): SyncCatalogResult;
|
|
176
|
+
export interface SyncRoutesSyncOptions {
|
|
177
|
+
/** The already-scaffolded repo to sync (absolute or relative). */
|
|
178
|
+
targetDir: string;
|
|
179
|
+
/** Copy the missing route directories in. Default false = check only. */
|
|
180
|
+
apply?: boolean;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Compare an already-scaffolded repo's route tree with the template this
|
|
184
|
+
* create-ailk ships and, with `apply`, copy in the route dirs it is missing
|
|
185
|
+
* (`create-ailk sync-routes`, #4986).
|
|
186
|
+
*
|
|
187
|
+
* The same shape as `syncArchitectureSync` / `syncCatalogSync`: validate the
|
|
188
|
+
* target is an existing scaffolded dir, spawn nothing, touch nothing else. The
|
|
189
|
+
* one difference is what it writes — not a regenerated file but the ABSENT
|
|
190
|
+
* route directories, copied through the scaffold's own `copyTemplate` with the
|
|
191
|
+
* scaffold's own markers, so a synced route is byte-identical to a fresh
|
|
192
|
+
* scaffold's. No other template file is re-copied; a route the site changed is
|
|
193
|
+
* reported and left as-is; nothing is deleted. The logic lives in
|
|
194
|
+
* `sync-routes.ts` (a pure module jest imports directly); this wrapper only
|
|
195
|
+
* supplies the package's `templates/` dir and version map.
|
|
196
|
+
*/
|
|
197
|
+
export declare function syncRoutesSync(opts: SyncRoutesSyncOptions): SyncRoutesResult;
|
|
198
|
+
/** Re-exported beside the other sync results so consumers see one surface. */
|
|
199
|
+
export type { RouteReport, SyncRoutesResult } from "./sync-routes.js";
|
|
200
|
+
/** Re-exported so the CLI can name the file it wrote without duplicating it. */
|
|
201
|
+
export { CATALOG_TARGET_PATH };
|
|
202
|
+
/**
|
|
203
|
+
* Render the surface-drift report the CLI prints after a sync run. Returns an
|
|
204
|
+
* empty string when there is no drift, so the caller can skip the write.
|
|
205
|
+
*/
|
|
206
|
+
export declare function formatSurfaceDrift(undeclared: string[]): string;
|
package/dist/programmatic.js
CHANGED
|
@@ -15,10 +15,18 @@
|
|
|
15
15
|
* import { scaffoldSync } from './programmatic.js';
|
|
16
16
|
* const result = scaffoldSync({ targetDir: '/tmp/my-site', projectName: 'my-site' });
|
|
17
17
|
*/
|
|
18
|
-
import { existsSync, readdirSync, readFileSync } from "node:fs";
|
|
19
|
-
import { basename, dirname, resolve } from "node:path";
|
|
18
|
+
import { existsSync, readdirSync, readFileSync, statSync, writeFileSync, } from "node:fs";
|
|
19
|
+
import { basename, dirname, join, resolve } from "node:path";
|
|
20
20
|
import { fileURLToPath } from "node:url";
|
|
21
|
+
import { CATALOG_TARGET_PATH, writeComponentCatalog, } from "./component-catalog.js";
|
|
21
22
|
import { copyTemplate } from "./copy.js";
|
|
23
|
+
import { deriveArchitecture } from "./derive-architecture.js";
|
|
24
|
+
import { extractModuleBundle } from "./lib/extract-module-bundle.js";
|
|
25
|
+
import { resolvePaidModules } from "./lib/module-license-gate.js";
|
|
26
|
+
import { classifyModules } from "./lib/module-tier.js";
|
|
27
|
+
import { normalizeModules } from "./module-architecture.js";
|
|
28
|
+
import { NAV_CONFIG_PATH, excludedRoutePaths, renderNavConfig, resolveSurfaces, } from "./surfaces.js";
|
|
29
|
+
import { syncRoutes } from "./sync-routes.js";
|
|
22
30
|
import { validateTarget } from "./validate.js";
|
|
23
31
|
const PKG_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
24
32
|
const TEMPLATES_DIR = resolve(PKG_ROOT, "templates");
|
|
@@ -63,27 +71,208 @@ export function scaffoldSync(opts) {
|
|
|
63
71
|
// Validate target — throws ValidationError on rejection.
|
|
64
72
|
const targetAbs = validateTarget(opts.targetDir);
|
|
65
73
|
const projectName = opts.projectName ?? basename(targetAbs);
|
|
74
|
+
// The declared route surface (#4154). Resolved BEFORE the copy: it decides
|
|
75
|
+
// both which route directories are skipped and what architecture.yaml records.
|
|
76
|
+
const enabledSurfaces = resolveSurfaces(opts.modules ?? ["marketing"], opts.surfaces ?? []);
|
|
66
77
|
const versions = readVersionMap();
|
|
67
78
|
copyTemplate({
|
|
68
79
|
templatesDir: TEMPLATES_DIR,
|
|
69
80
|
targetDir: targetAbs,
|
|
70
81
|
versions,
|
|
82
|
+
excludePaths: excludedRoutePaths(enabledSurfaces),
|
|
71
83
|
markers: {
|
|
72
84
|
PROJECT_NAME: projectName,
|
|
73
85
|
COMPANY_NAME: "Your Company",
|
|
74
86
|
COMPANY_DOMAIN: "example.com",
|
|
75
87
|
},
|
|
76
88
|
});
|
|
89
|
+
// Derive + write the module-set-driven architecture.yaml (spec #3787). This
|
|
90
|
+
// is the single source of the scaffolded site's code-boundary config and
|
|
91
|
+
// closes the dangling `architecture_rules: architecture.yaml` reference in
|
|
92
|
+
// the scaffolded project.yaml. Written AFTER the template copy, at the target
|
|
93
|
+
// root — a deterministic function of the selected module set.
|
|
94
|
+
writeFileSync(join(targetAbs, "architecture.yaml"), deriveArchitecture(opts.modules ?? ["marketing"], enabledSurfaces));
|
|
95
|
+
// Regenerate the site nav from the same surface set (#4154). The nav is a
|
|
96
|
+
// static list the layout renders into the header AND the footer, so leaving
|
|
97
|
+
// the template's copy in place would link /docs and /blog sitewide in a
|
|
98
|
+
// scaffold that carries neither route.
|
|
99
|
+
writeFileSync(join(targetAbs, NAV_CONFIG_PATH), renderNavConfig(enabledSurfaces));
|
|
100
|
+
// Opt-in only (#4636). Every write above this line is unconditional, so a
|
|
101
|
+
// scaffold with `withCatalog` unset touches exactly the files it did before.
|
|
102
|
+
if (opts.withCatalog === true)
|
|
103
|
+
writeComponentCatalog(targetAbs);
|
|
77
104
|
const filesCreated = countFiles(targetAbs);
|
|
78
|
-
return { targetDir: targetAbs, filesCreated };
|
|
105
|
+
return { targetDir: targetAbs, filesCreated, surfaces: enabledSurfaces };
|
|
79
106
|
}
|
|
80
107
|
/**
|
|
81
108
|
* Scaffold an AI Launch Kit starter project into targetDir (async wrapper).
|
|
82
109
|
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
110
|
+
* The ONLY entry point that resolves paid modules (K1, #5089 — Flavor 3):
|
|
111
|
+
*
|
|
112
|
+
* 1. Classify the requested module set into free / paid (`module-tier.ts`).
|
|
113
|
+
* 2. `resolvePaidModules` — zero-paid-modules returns instantly with no key
|
|
114
|
+
* read and no network call (the regression floor). A paid module with
|
|
115
|
+
* no key, or a licence the module distribution rejects, throws
|
|
116
|
+
* `LicenseRequiredError` HERE — before anything is written to disk.
|
|
117
|
+
* 3. `scaffoldSync` — unchanged, today's local `templates/` copy.
|
|
118
|
+
* 4. Merge each resolved paid module's fetched bundle into the freshly
|
|
119
|
+
* scaffolded tree (`extractModuleBundle`).
|
|
120
|
+
*
|
|
121
|
+
* `scaffoldSync` itself stays licensing-oblivious on purpose: every existing
|
|
122
|
+
* synchronous caller (this package's own test suite, overwhelmingly) is
|
|
123
|
+
* unaffected by this card — only a caller that goes through THIS function
|
|
124
|
+
* with a paid module in `opts.modules` exercises the gate at all.
|
|
86
125
|
*/
|
|
87
126
|
export async function scaffold(opts) {
|
|
88
|
-
|
|
127
|
+
const { paid } = classifyModules(normalizeModules(opts.modules ?? ["marketing"]));
|
|
128
|
+
const bundles = await resolvePaidModules({
|
|
129
|
+
paidModules: paid,
|
|
130
|
+
licenseKey: opts.licenseKey,
|
|
131
|
+
...(opts.moduleRegistryUrl !== undefined
|
|
132
|
+
? { registryUrl: opts.moduleRegistryUrl }
|
|
133
|
+
: {}),
|
|
134
|
+
...(opts.fetchImpl !== undefined ? { fetchImpl: opts.fetchImpl } : {}),
|
|
135
|
+
});
|
|
136
|
+
const result = scaffoldSync(opts);
|
|
137
|
+
for (const [moduleName, bytes] of bundles) {
|
|
138
|
+
await extractModuleBundle({
|
|
139
|
+
bytes,
|
|
140
|
+
targetDir: result.targetDir,
|
|
141
|
+
moduleName,
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
return result;
|
|
145
|
+
}
|
|
146
|
+
// Re-exported so a consumer of the async `scaffold()` above can type its own
|
|
147
|
+
// wrapper (e.g. the MCP scaffold-site tool) without reaching into `lib/`.
|
|
148
|
+
export { LicenseRequiredError, } from "./lib/module-license-gate.js";
|
|
149
|
+
export { FREE_MODULES, PAID_MODULES, classifyModules } from "./lib/module-tier.js";
|
|
150
|
+
/**
|
|
151
|
+
* Regenerate an already-scaffolded repo's `architecture.yaml` in place from a
|
|
152
|
+
* module set (the "module added later" sync path — spec #3561).
|
|
153
|
+
*
|
|
154
|
+
* Mirrors scaffoldSync's architecture-write step MINUS the template copy: it
|
|
155
|
+
* overwrites exactly the one `architecture.yaml` file at the target root via
|
|
156
|
+
* the shipped, byte-deterministic `deriveArchitecture`, so a synced repo's
|
|
157
|
+
* config is identical to a fresh scaffold's for the same module set. Data-only
|
|
158
|
+
* and non-destructive: no template re-copy, no subprocess, no other file
|
|
159
|
+
* touched.
|
|
160
|
+
*
|
|
161
|
+
* Validates the target is an EXISTING scaffolded dir (an existing directory
|
|
162
|
+
* containing `architecture.yaml`) — the inverse of `validateTarget` (D3).
|
|
163
|
+
* Throws Error on a missing target, a non-directory target, or a directory with
|
|
164
|
+
* no `architecture.yaml`; the CLI's top-level catch turns that into a
|
|
165
|
+
* `[create-ailk] <message>` stderr write + exit 1.
|
|
166
|
+
*/
|
|
167
|
+
export function syncArchitectureSync(opts) {
|
|
168
|
+
const targetAbs = resolve(opts.targetDir);
|
|
169
|
+
if (!existsSync(targetAbs)) {
|
|
170
|
+
throw new Error(`sync target does not exist: ${targetAbs}. Point --sync-architecture at an already-scaffolded repo.`);
|
|
171
|
+
}
|
|
172
|
+
if (!statSync(targetAbs).isDirectory()) {
|
|
173
|
+
throw new Error(`sync target is not a directory: ${targetAbs}`);
|
|
174
|
+
}
|
|
175
|
+
const archPath = join(targetAbs, "architecture.yaml");
|
|
176
|
+
if (!existsSync(archPath)) {
|
|
177
|
+
throw new Error(`not a scaffolded repo: no architecture.yaml at ${targetAbs}. Run \`create-ailk <target-dir>\` to scaffold first.`);
|
|
178
|
+
}
|
|
179
|
+
const enabledSurfaces = resolveSurfaces(opts.modules, opts.surfaces ?? []);
|
|
180
|
+
writeFileSync(archPath, deriveArchitecture(opts.modules, enabledSurfaces));
|
|
181
|
+
return {
|
|
182
|
+
targetDir: targetAbs,
|
|
183
|
+
surfaces: enabledSurfaces,
|
|
184
|
+
undeclared: findUndeclaredSurfacePaths(targetAbs, enabledSurfaces),
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* List the ROUTE directories present in an already-scaffolded repo that belong
|
|
189
|
+
* to a gateable surface the given declaration does not carry.
|
|
190
|
+
*
|
|
191
|
+
* This is the adoption path for a site scaffolded before #4154 (spec D5): the
|
|
192
|
+
* sync run declares what the site actually has, then names what is left over so
|
|
193
|
+
* the operator can remove it in one reviewable commit. It is READ-ONLY — it
|
|
194
|
+
* stats paths and returns strings, and never writes or deletes.
|
|
195
|
+
*
|
|
196
|
+
* Routes only, deliberately. A surface's content directories are informational
|
|
197
|
+
* (`Surface.content`), not drift: `apps/web/content/<locale>/{blog,docs}` must
|
|
198
|
+
* exist in EVERY scaffold — `source.config.ts` resolves those paths at build
|
|
199
|
+
* time whether or not the route is mounted — so sweeping content here would
|
|
200
|
+
* tell every operator to delete directories the build requires.
|
|
201
|
+
*/
|
|
202
|
+
function findUndeclaredSurfacePaths(targetAbs, enabled) {
|
|
203
|
+
return excludedRoutePaths(enabled)
|
|
204
|
+
.filter((rel) => existsSync(join(targetAbs, rel)))
|
|
205
|
+
.sort();
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Refresh an already-scaffolded repo's `COMPONENT-CATALOG.md` in place from the
|
|
209
|
+
* catalog this create-ailk ships (#4636).
|
|
210
|
+
*
|
|
211
|
+
* The same shape as `syncArchitectureSync`, with a different artifact: validate
|
|
212
|
+
* the target is an existing scaffolded dir, overwrite exactly one file, touch
|
|
213
|
+
* nothing else, spawn nothing. The catalog is regenerated from `packages/ui` at
|
|
214
|
+
* publish time, so re-running this after upgrading create-ailk is how a site
|
|
215
|
+
* picks up components added since it was scaffolded.
|
|
216
|
+
*/
|
|
217
|
+
export function syncCatalogSync(opts) {
|
|
218
|
+
const targetAbs = resolve(opts.targetDir);
|
|
219
|
+
if (!existsSync(targetAbs)) {
|
|
220
|
+
throw new Error(`sync target does not exist: ${targetAbs}. Point --sync-catalog at an already-scaffolded repo.`);
|
|
221
|
+
}
|
|
222
|
+
if (!statSync(targetAbs).isDirectory()) {
|
|
223
|
+
throw new Error(`sync target is not a directory: ${targetAbs}`);
|
|
224
|
+
}
|
|
225
|
+
if (!existsSync(join(targetAbs, "architecture.yaml"))) {
|
|
226
|
+
throw new Error(`not a scaffolded repo: no architecture.yaml at ${targetAbs}. Run \`create-ailk <target-dir>\` to scaffold first.`);
|
|
227
|
+
}
|
|
228
|
+
return {
|
|
229
|
+
targetDir: targetAbs,
|
|
230
|
+
catalogPath: writeComponentCatalog(targetAbs),
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Compare an already-scaffolded repo's route tree with the template this
|
|
235
|
+
* create-ailk ships and, with `apply`, copy in the route dirs it is missing
|
|
236
|
+
* (`create-ailk sync-routes`, #4986).
|
|
237
|
+
*
|
|
238
|
+
* The same shape as `syncArchitectureSync` / `syncCatalogSync`: validate the
|
|
239
|
+
* target is an existing scaffolded dir, spawn nothing, touch nothing else. The
|
|
240
|
+
* one difference is what it writes — not a regenerated file but the ABSENT
|
|
241
|
+
* route directories, copied through the scaffold's own `copyTemplate` with the
|
|
242
|
+
* scaffold's own markers, so a synced route is byte-identical to a fresh
|
|
243
|
+
* scaffold's. No other template file is re-copied; a route the site changed is
|
|
244
|
+
* reported and left as-is; nothing is deleted. The logic lives in
|
|
245
|
+
* `sync-routes.ts` (a pure module jest imports directly); this wrapper only
|
|
246
|
+
* supplies the package's `templates/` dir and version map.
|
|
247
|
+
*/
|
|
248
|
+
export function syncRoutesSync(opts) {
|
|
249
|
+
return syncRoutes({
|
|
250
|
+
...opts,
|
|
251
|
+
templatesDir: TEMPLATES_DIR,
|
|
252
|
+
versions: readVersionMap(),
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
/** Re-exported so the CLI can name the file it wrote without duplicating it. */
|
|
256
|
+
export { CATALOG_TARGET_PATH };
|
|
257
|
+
/**
|
|
258
|
+
* Render the surface-drift report the CLI prints after a sync run. Returns an
|
|
259
|
+
* empty string when there is no drift, so the caller can skip the write.
|
|
260
|
+
*/
|
|
261
|
+
export function formatSurfaceDrift(undeclared) {
|
|
262
|
+
if (undeclared.length === 0)
|
|
263
|
+
return "";
|
|
264
|
+
const lines = [
|
|
265
|
+
"",
|
|
266
|
+
`[create-ailk] ${undeclared.length} path(s) belong to route surfaces this architecture.yaml does not declare:`,
|
|
267
|
+
...undeclared.map((p) => ` ${p}`),
|
|
268
|
+
"",
|
|
269
|
+
"These are NOT removed automatically. Either declare the surface",
|
|
270
|
+
"(re-run with --surfaces <id>) or delete the paths above — a scaffolded",
|
|
271
|
+
"site that keeps them serves routes its declared architecture does not carry.",
|
|
272
|
+
"",
|
|
273
|
+
"Content that fed those routes may be orphaned too: content whose route is",
|
|
274
|
+
"gone still appears in /sitemap.xml and /llms.txt, advertising URLs that 404.",
|
|
275
|
+
"",
|
|
276
|
+
];
|
|
277
|
+
return lines.join("\n");
|
|
89
278
|
}
|