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/cli.js
CHANGED
|
@@ -3,43 +3,114 @@
|
|
|
3
3
|
* `create-ailk` — entry point.
|
|
4
4
|
*
|
|
5
5
|
* Orchestration:
|
|
6
|
+
* 0. on a `sync-routes` subcommand: parse its own argv, run syncRoutesSync(),
|
|
7
|
+
* print the report, exit (1 iff routes are missing in check mode)
|
|
6
8
|
* 1. parse argv → CliOptions
|
|
7
9
|
* 2. on --help: print helpText, exit 0
|
|
8
10
|
* 3. on --version: print version, exit 0
|
|
9
|
-
* 4. delegate to
|
|
11
|
+
* 4. delegate to scaffold() in programmatic.ts — gates + fetches any
|
|
12
|
+
* requested paid module (K1, #5089 — Flavor 3), then validates + copies
|
|
13
|
+
* the local template, then merges each fetched bundle in
|
|
10
14
|
* 5. when --install: spawn `pnpm install` (cwd = target, hard-coded argv)
|
|
11
15
|
* 6. print next-steps message
|
|
12
16
|
*
|
|
13
|
-
* Any thrown error (parse failure, validation failure, copy failure
|
|
14
|
-
* caught at the top level: stderr
|
|
17
|
+
* Any thrown error (parse failure, validation failure, copy failure,
|
|
18
|
+
* `LicenseRequiredError`) is caught at the top level: stderr
|
|
19
|
+
* "[create-ailk] <message>", exit non-zero. `LicenseRequiredError` is not
|
|
20
|
+
* special-cased — its message already states which honest state fired (no
|
|
21
|
+
* key / licence does not cover this module), so the existing single
|
|
22
|
+
* error-handling path is the whole contract.
|
|
23
|
+
*
|
|
24
|
+
* `main()` is async ONLY because Deliverable 2 needs to `await` the paid-
|
|
25
|
+
* module network round trip; every other branch below is exactly as
|
|
26
|
+
* synchronous as before.
|
|
15
27
|
*/
|
|
16
28
|
import { spawnSync } from "node:child_process";
|
|
17
29
|
import { readFileSync } from "node:fs";
|
|
18
30
|
import { dirname, resolve } from "node:path";
|
|
19
31
|
import { fileURLToPath } from "node:url";
|
|
20
32
|
import { proCallout } from "./lib/pro-callout.js";
|
|
21
|
-
import { helpText, parseCliArgs } from "./parse-args.js";
|
|
22
|
-
import {
|
|
33
|
+
import { helpText, parseCliArgs, parseModules } from "./parse-args.js";
|
|
34
|
+
import { formatSurfaceDrift, scaffold, syncArchitectureSync, syncCatalogSync, syncRoutesSync, } from "./programmatic.js";
|
|
35
|
+
import { CORE_SURFACE_PATHS } from "./surfaces.js";
|
|
36
|
+
import { SYNC_ROUTES_HELP, formatSyncRoutesReport, parseSyncRoutesArgs, } from "./sync-routes.js";
|
|
23
37
|
const PKG_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
24
38
|
const PKG_JSON = resolve(PKG_ROOT, "package.json");
|
|
25
39
|
function readPackageVersion() {
|
|
26
40
|
const raw = readFileSync(PKG_JSON, "utf8");
|
|
27
41
|
return JSON.parse(raw).version;
|
|
28
42
|
}
|
|
29
|
-
function main() {
|
|
30
|
-
const
|
|
43
|
+
async function main() {
|
|
44
|
+
const argv = process.argv.slice(2);
|
|
45
|
+
// Subcommand dispatch, ahead of the flag parser: `sync-routes` has its own
|
|
46
|
+
// argv shape (#4986). Check mode exits 1 iff a template route is missing;
|
|
47
|
+
// locally modified routes are reported but do not fail; --apply exits 0.
|
|
48
|
+
if (argv[0] === "sync-routes") {
|
|
49
|
+
const args = parseSyncRoutesArgs(argv.slice(1));
|
|
50
|
+
if (args.help) {
|
|
51
|
+
process.stdout.write(SYNC_ROUTES_HELP);
|
|
52
|
+
process.exit(0);
|
|
53
|
+
}
|
|
54
|
+
const result = syncRoutesSync({
|
|
55
|
+
targetDir: args.target ?? process.cwd(),
|
|
56
|
+
apply: args.apply,
|
|
57
|
+
});
|
|
58
|
+
process.stdout.write(formatSyncRoutesReport(result, args.apply));
|
|
59
|
+
process.exit(!args.apply && result.missing.length > 0 ? 1 : 0);
|
|
60
|
+
}
|
|
61
|
+
const opts = parseCliArgs(argv);
|
|
31
62
|
if (opts.help) {
|
|
32
|
-
process.stdout.write(helpText);
|
|
63
|
+
process.stdout.write(helpText + "\n" + SYNC_ROUTES_HELP);
|
|
33
64
|
process.exit(0);
|
|
34
65
|
}
|
|
35
66
|
if (opts.version) {
|
|
36
67
|
process.stdout.write(readPackageVersion() + "\n");
|
|
37
68
|
process.exit(0);
|
|
38
69
|
}
|
|
39
|
-
//
|
|
40
|
-
//
|
|
41
|
-
|
|
70
|
+
// Catalog-sync mode: refresh COMPONENT-CATALOG.md in an already-scaffolded
|
|
71
|
+
// repo, then exit — the `--sync-architecture` shape with a different artifact
|
|
72
|
+
// (#4636). Data-only: one file rewritten, no template copy, no install.
|
|
73
|
+
if (opts.syncCatalog) {
|
|
74
|
+
const { catalogPath } = syncCatalogSync({
|
|
75
|
+
targetDir: opts.target ?? process.cwd(),
|
|
76
|
+
});
|
|
77
|
+
process.stdout.write(`[create-ailk] Wrote ${catalogPath}\n` +
|
|
78
|
+
`[create-ailk] Search it by CAPABILITY before building a component — it indexes every @working-theory/ui section, block and chrome component by what it does.\n`);
|
|
79
|
+
process.exit(0);
|
|
80
|
+
}
|
|
81
|
+
// Sync mode: regenerate architecture.yaml in an already-scaffolded repo from
|
|
82
|
+
// the module set, then exit — bypassing the scaffold / --install / next-steps
|
|
83
|
+
// path entirely (spec #3561 D2). Data-only and non-destructive: only
|
|
84
|
+
// architecture.yaml is rewritten. The value was already validated at parse
|
|
85
|
+
// time; re-parse it through the SAME parseModules to the module list.
|
|
86
|
+
if (opts.syncArchitecture !== undefined) {
|
|
87
|
+
const modules = parseModules(opts.syncArchitecture);
|
|
88
|
+
const targetDir = opts.target ?? process.cwd();
|
|
89
|
+
const { targetDir: targetAbs, surfaces, undeclared, } = syncArchitectureSync({
|
|
90
|
+
targetDir,
|
|
91
|
+
modules,
|
|
92
|
+
surfaces: opts.surfaces,
|
|
93
|
+
});
|
|
94
|
+
process.stdout.write(`[create-ailk] Regenerated architecture.yaml in ${targetAbs} from modules: ${modules.join(", ")}\n`);
|
|
95
|
+
process.stdout.write(`[create-ailk] Declared route surfaces: ${surfaces.length > 0 ? surfaces.join(", ") : "core only"}\n`);
|
|
96
|
+
// Surface drift is advisory, never fatal and never auto-removed (#4154 D5):
|
|
97
|
+
// the operator deletes the named paths in their own reviewable commit.
|
|
98
|
+
const drift = formatSurfaceDrift(undeclared);
|
|
99
|
+
if (drift)
|
|
100
|
+
process.stdout.write(drift);
|
|
101
|
+
process.exit(0);
|
|
102
|
+
}
|
|
103
|
+
// scaffold() gates + fetches any requested paid module (K1, #5089), then
|
|
104
|
+
// validates and copies the local template — throws ValidationError or
|
|
105
|
+
// LicenseRequiredError on rejection (caught at top level below). Neither
|
|
106
|
+
// AILK_LICENSE_KEY nor AILK_MODULE_REGISTRY_URL is read, and no network
|
|
107
|
+
// call is made, when `opts.modules` names no paid module — the regression
|
|
108
|
+
// floor (see `resolvePaidModules` in `lib/module-license-gate.ts`).
|
|
109
|
+
const { targetDir: targetAbs, surfaces } = await scaffold({
|
|
42
110
|
targetDir: opts.target,
|
|
111
|
+
modules: opts.modules,
|
|
112
|
+
surfaces: opts.surfaces,
|
|
113
|
+
withCatalog: opts.withCatalog,
|
|
43
114
|
});
|
|
44
115
|
if (opts.install) {
|
|
45
116
|
// Hard-coded argv. User input only flows through `cwd`, never the command.
|
|
@@ -65,16 +136,21 @@ function main() {
|
|
|
65
136
|
lines.push(" pnpm dev");
|
|
66
137
|
lines.push("");
|
|
67
138
|
lines.push("Open http://localhost:3000 to see the home page.");
|
|
139
|
+
lines.push("");
|
|
140
|
+
lines.push(`Route surfaces: ${CORE_SURFACE_PATHS.join(", ")}` +
|
|
141
|
+
(surfaces.length > 0 ? ` + ${surfaces.join(", ")}` : ""));
|
|
142
|
+
lines.push("Add another with the `scaffold-page` skill, or re-run with --surfaces <id>.");
|
|
143
|
+
// Only when asked for. The default scaffold's output is unchanged.
|
|
144
|
+
if (opts.withCatalog) {
|
|
145
|
+
lines.push("Component catalog: COMPONENT-CATALOG.md — search it by capability before building a component.");
|
|
146
|
+
}
|
|
68
147
|
lines.push("Reference: ADR 0007 — pnpm create ailk@latest is the canonical install path.");
|
|
69
148
|
lines.push("");
|
|
70
149
|
lines.push(proCallout());
|
|
71
150
|
lines.push("");
|
|
72
151
|
process.stdout.write(lines.join("\n"));
|
|
73
152
|
}
|
|
74
|
-
|
|
75
|
-
main();
|
|
76
|
-
}
|
|
77
|
-
catch (err) {
|
|
153
|
+
main().catch((err) => {
|
|
78
154
|
process.stderr.write(`[create-ailk] ${err.message}\n`);
|
|
79
155
|
process.exit(1);
|
|
80
|
-
}
|
|
156
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** Where the catalog lands in a consuming repo. The address is the contract. */
|
|
2
|
+
export declare const CATALOG_TARGET_PATH = "COMPONENT-CATALOG.md";
|
|
3
|
+
/**
|
|
4
|
+
* Copy the shipped catalog to `<targetAbs>/COMPONENT-CATALOG.md`, overwriting
|
|
5
|
+
* any previous copy. Returns the absolute path written.
|
|
6
|
+
*
|
|
7
|
+
* Throws when the package carries no catalog — that means `build-catalog` never
|
|
8
|
+
* ran, and writing nothing silently would leave the consuming repo believing it
|
|
9
|
+
* has an inventory it does not have.
|
|
10
|
+
*/
|
|
11
|
+
export declare function writeComponentCatalog(targetAbs: string): string;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Distribution of the generated component catalog into a consuming repo.
|
|
3
|
+
*
|
|
4
|
+
* The catalog (`component-catalog.md`, generated by
|
|
5
|
+
* `scripts/build-component-catalog.mjs` and shipped in this package's tarball)
|
|
6
|
+
* answers "what component gives me a modal form on a dimmed backdrop?" with
|
|
7
|
+
* `FormLightbox`. It is only useful where the person asking that question is,
|
|
8
|
+
* which is a scaffolded site's own repo — a cloud session there is single-repo
|
|
9
|
+
* by construction and cannot reach AILK (#4636 cause 1: no address).
|
|
10
|
+
*
|
|
11
|
+
* The file lands at the TARGET ROOT, beside `CLAUDE.md`, `CONVENTIONS.md` and
|
|
12
|
+
* `project.yaml`. Root rather than `docs/`: a scaffold has no `docs/` today,
|
|
13
|
+
* and the whole failure being fixed is that the inventory had no address a
|
|
14
|
+
* worker could resolve — the root is the one place every reader already looks.
|
|
15
|
+
*/
|
|
16
|
+
import { copyFileSync, existsSync } from "node:fs";
|
|
17
|
+
import { dirname, join, resolve } from "node:path";
|
|
18
|
+
import { fileURLToPath } from "node:url";
|
|
19
|
+
const PKG_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
20
|
+
/** The catalog as shipped in this package (generated at `prepublishOnly`). */
|
|
21
|
+
const CATALOG_SOURCE = join(PKG_ROOT, "component-catalog.md");
|
|
22
|
+
/** Where the catalog lands in a consuming repo. The address is the contract. */
|
|
23
|
+
export const CATALOG_TARGET_PATH = "COMPONENT-CATALOG.md";
|
|
24
|
+
/**
|
|
25
|
+
* Copy the shipped catalog to `<targetAbs>/COMPONENT-CATALOG.md`, overwriting
|
|
26
|
+
* any previous copy. Returns the absolute path written.
|
|
27
|
+
*
|
|
28
|
+
* Throws when the package carries no catalog — that means `build-catalog` never
|
|
29
|
+
* ran, and writing nothing silently would leave the consuming repo believing it
|
|
30
|
+
* has an inventory it does not have.
|
|
31
|
+
*/
|
|
32
|
+
export function writeComponentCatalog(targetAbs) {
|
|
33
|
+
if (!existsSync(CATALOG_SOURCE)) {
|
|
34
|
+
throw new Error(`no component catalog in this create-ailk install (${CATALOG_SOURCE}). Run \`pnpm --filter create-ailk run build-catalog\` first.`);
|
|
35
|
+
}
|
|
36
|
+
const dest = join(targetAbs, CATALOG_TARGET_PATH);
|
|
37
|
+
copyFileSync(CATALOG_SOURCE, dest);
|
|
38
|
+
return dest;
|
|
39
|
+
}
|
package/dist/copy.d.ts
CHANGED
|
@@ -4,5 +4,12 @@ export interface CopyTemplateOptions {
|
|
|
4
4
|
targetDir: string;
|
|
5
5
|
versions: WorkspaceVersionMap;
|
|
6
6
|
markers: MarkerMap;
|
|
7
|
+
/**
|
|
8
|
+
* Template-relative directory paths to SKIP entirely — the route directories
|
|
9
|
+
* of gateable surfaces the declared architecture does not carry (spec #4154).
|
|
10
|
+
* Forward-slash separated. Matching is anchored at a directory boundary, so
|
|
11
|
+
* `.../services` never excludes a sibling `.../services-extra`.
|
|
12
|
+
*/
|
|
13
|
+
excludePaths?: string[];
|
|
7
14
|
}
|
|
8
15
|
export declare function copyTemplate(opts: CopyTemplateOptions): void;
|
package/dist/copy.js
CHANGED
|
@@ -21,6 +21,24 @@
|
|
|
21
21
|
import { copyFileSync, mkdirSync, readFileSync, readdirSync, writeFileSync, } from "node:fs";
|
|
22
22
|
import { extname, join, relative, resolve, sep } from "node:path";
|
|
23
23
|
import { substituteMarkers, substituteWorkspaceVersions, } from "./substitute.js";
|
|
24
|
+
/**
|
|
25
|
+
* Whether a walked template-relative path is inside (or equal to) an excluded
|
|
26
|
+
* directory. Compares `/`-normalized paths so the check holds on Windows, and
|
|
27
|
+
* only at a directory boundary — a prefix that stops mid-segment is no match.
|
|
28
|
+
*/
|
|
29
|
+
function isExcluded(relativePath, excluded) {
|
|
30
|
+
if (excluded.length === 0)
|
|
31
|
+
return false;
|
|
32
|
+
const rel = relativePath.split(sep).join("/");
|
|
33
|
+
for (const raw of excluded) {
|
|
34
|
+
const ex = raw.replace(/\/+$/, "");
|
|
35
|
+
if (ex.length === 0)
|
|
36
|
+
continue;
|
|
37
|
+
if (rel === ex || rel.startsWith(ex + "/"))
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
24
42
|
/** File extensions whose content we treat as text (and run markers over). */
|
|
25
43
|
const TEXT_EXTS = new Set([
|
|
26
44
|
".md",
|
|
@@ -61,6 +79,7 @@ function isPackageJson(relativePath) {
|
|
|
61
79
|
export function copyTemplate(opts) {
|
|
62
80
|
const templatesAbs = resolve(opts.templatesDir);
|
|
63
81
|
const targetAbs = resolve(opts.targetDir);
|
|
82
|
+
const excluded = opts.excludePaths ?? [];
|
|
64
83
|
mkdirSync(targetAbs, { recursive: true });
|
|
65
84
|
const stack = [templatesAbs];
|
|
66
85
|
while (stack.length > 0) {
|
|
@@ -75,6 +94,11 @@ export function copyTemplate(opts) {
|
|
|
75
94
|
continue;
|
|
76
95
|
const srcPath = join(dir, entry.name);
|
|
77
96
|
const rel = relative(templatesAbs, srcPath);
|
|
97
|
+
// Surface gating (#4154): a route directory belonging to a surface the
|
|
98
|
+
// declared architecture does not carry is skipped outright — the route is
|
|
99
|
+
// ABSENT from the scaffold, not present-and-serving-a-placeholder.
|
|
100
|
+
if (isExcluded(rel, excluded))
|
|
101
|
+
continue;
|
|
78
102
|
const dstPath = join(targetAbs, rel);
|
|
79
103
|
// Path-safety guard: dstPath MUST be within targetAbs. Use `path.sep`
|
|
80
104
|
// so the check holds on Windows (`\\`) as well as POSIX (`/`).
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Derive the `architecture.yaml` document for a module set.
|
|
3
|
+
*
|
|
4
|
+
* @param modules the selected module names (any order; deduped). Defaults to
|
|
5
|
+
* the same set `parse-args` defaults to when omitted (`['marketing']`).
|
|
6
|
+
* @param surfaces the enabled gateable route surfaces. Omitted ⟹ derived from
|
|
7
|
+
* the module set alone (`resolveSurfaces`), so a caller that passes only
|
|
8
|
+
* modules gets exactly what the modules imply.
|
|
9
|
+
* @returns the complete `architecture.yaml` file content (a deterministic
|
|
10
|
+
* function of the module SET and the surface SET).
|
|
11
|
+
* @throws Error on an unrecognized module (defensive; parse-args rejects first).
|
|
12
|
+
*/
|
|
13
|
+
export declare function deriveArchitecture(modules?: string[], surfaces?: string[]): string;
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Derive a scaffolded site's `architecture.yaml` from its selected module set.
|
|
3
|
+
*
|
|
4
|
+
* `deriveArchitecture(modules)` composes the module-independent BASE
|
|
5
|
+
* (module-architecture.ts `ARCHITECTURE_BASE`) with the selected module slices
|
|
6
|
+
* into ONE deterministic `architecture.yaml` document string. The module set is
|
|
7
|
+
* the single source of truth for the result — same set → byte-identical output
|
|
8
|
+
* (no timestamps, stable key/array ordering), so the derivation doubles as the
|
|
9
|
+
* re-runnable sync path (add a module, re-derive, the file updates; re-deriving
|
|
10
|
+
* an unchanged set is a no-op).
|
|
11
|
+
*
|
|
12
|
+
* Zero runtime dependencies (create-ailk is a published, standalone CLI): the
|
|
13
|
+
* YAML is emitted by a small, purpose-built deterministic serializer over the
|
|
14
|
+
* fixed document shape this module produces — no `yaml`/`js-yaml` dependency.
|
|
15
|
+
*/
|
|
16
|
+
import { ARCHITECTURE_BASE, MODULE_SLICES, normalizeModules, } from "./module-architecture.js";
|
|
17
|
+
import { CORE_SURFACE_PATHS, RECOGNIZED_SURFACES, resolveSurfaces, } from "./surfaces.js";
|
|
18
|
+
function isScalar(v) {
|
|
19
|
+
return typeof v === "string" || typeof v === "number";
|
|
20
|
+
}
|
|
21
|
+
/** A bare (unquoted-safe) scalar: identifier chars only, not a YAML keyword/number. */
|
|
22
|
+
function isBareSafe(s) {
|
|
23
|
+
if (s === "")
|
|
24
|
+
return false;
|
|
25
|
+
if (!/^[A-Za-z0-9._-]+$/.test(s))
|
|
26
|
+
return false;
|
|
27
|
+
if (/^[0-9]/.test(s))
|
|
28
|
+
return false; // avoid numeric-looking bare scalars
|
|
29
|
+
if (/^(true|false|null|yes|no|on|off|~)$/i.test(s))
|
|
30
|
+
return false;
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
function scalar(v) {
|
|
34
|
+
if (typeof v === "number")
|
|
35
|
+
return String(v);
|
|
36
|
+
return isBareSafe(v) ? v : JSON.stringify(v); // double-quoted, correctly escaped
|
|
37
|
+
}
|
|
38
|
+
function emitSeq(arr, indent) {
|
|
39
|
+
const pad = " ".repeat(indent);
|
|
40
|
+
const lines = [];
|
|
41
|
+
for (const item of arr) {
|
|
42
|
+
if (isScalar(item)) {
|
|
43
|
+
lines.push(`${pad}- ${scalar(item)}`);
|
|
44
|
+
}
|
|
45
|
+
else if (Array.isArray(item)) {
|
|
46
|
+
// Nested sequence — not produced by our shapes, but handled for safety.
|
|
47
|
+
lines.push(`${pad}-`);
|
|
48
|
+
lines.push(...emitSeq(item, indent + 2));
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
const inner = emitMap(item, indent + 2);
|
|
52
|
+
// Splice the "- " marker onto the first line of the mapping block.
|
|
53
|
+
const first = inner[0] ?? "";
|
|
54
|
+
inner[0] = `${pad}- ${first.slice(indent + 2)}`;
|
|
55
|
+
lines.push(...inner);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return lines;
|
|
59
|
+
}
|
|
60
|
+
function emitMap(obj, indent) {
|
|
61
|
+
const pad = " ".repeat(indent);
|
|
62
|
+
const lines = [];
|
|
63
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
64
|
+
if (isScalar(v)) {
|
|
65
|
+
lines.push(`${pad}${k}: ${scalar(v)}`);
|
|
66
|
+
}
|
|
67
|
+
else if (Array.isArray(v)) {
|
|
68
|
+
if (v.length === 0) {
|
|
69
|
+
lines.push(`${pad}${k}: []`);
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
lines.push(`${pad}${k}:`);
|
|
73
|
+
lines.push(...emitSeq(v, indent + 2));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
lines.push(`${pad}${k}:`);
|
|
78
|
+
lines.push(...emitMap(v, indent + 2));
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return lines;
|
|
82
|
+
}
|
|
83
|
+
function emitDocument(doc) {
|
|
84
|
+
return emitMap(doc, 0).join("\n") + "\n";
|
|
85
|
+
}
|
|
86
|
+
// ── Deterministic set helpers ──────────────────────────────────────────────
|
|
87
|
+
/** Sorted unique union of string arrays (a set → a stable, ordered list). */
|
|
88
|
+
function sortedUnion(...lists) {
|
|
89
|
+
const set = new Set();
|
|
90
|
+
for (const list of lists)
|
|
91
|
+
for (const s of list ?? [])
|
|
92
|
+
set.add(s);
|
|
93
|
+
return [...set].sort();
|
|
94
|
+
}
|
|
95
|
+
/** Union of forbidden patterns, deduped by `pattern`, base-first then sorted. */
|
|
96
|
+
function mergeForbidden(base, extra) {
|
|
97
|
+
const seen = new Set();
|
|
98
|
+
const out = [];
|
|
99
|
+
for (const p of base) {
|
|
100
|
+
if (!seen.has(p.pattern)) {
|
|
101
|
+
seen.add(p.pattern);
|
|
102
|
+
out.push(p);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
const sortedExtra = [...extra].sort((a, b) => a.pattern < b.pattern ? -1 : a.pattern > b.pattern ? 1 : 0);
|
|
106
|
+
for (const p of sortedExtra) {
|
|
107
|
+
if (!seen.has(p.pattern)) {
|
|
108
|
+
seen.add(p.pattern);
|
|
109
|
+
out.push(p);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return out;
|
|
113
|
+
}
|
|
114
|
+
function forbiddenToYaml(p) {
|
|
115
|
+
const m = { pattern: p.pattern, reason: p.reason };
|
|
116
|
+
if (p.paths_excluded && p.paths_excluded.length > 0) {
|
|
117
|
+
m.paths_excluded = [...p.paths_excluded].sort();
|
|
118
|
+
}
|
|
119
|
+
return m;
|
|
120
|
+
}
|
|
121
|
+
function appToYaml(app) {
|
|
122
|
+
const m = {
|
|
123
|
+
path: app.path,
|
|
124
|
+
description: app.description,
|
|
125
|
+
may_import_from: [...app.may_import_from].sort(),
|
|
126
|
+
may_not_import_from: [...app.may_not_import_from].sort(),
|
|
127
|
+
};
|
|
128
|
+
if (app.forbidden_patterns && app.forbidden_patterns.length > 0) {
|
|
129
|
+
m.forbidden_patterns = app.forbidden_patterns.map(forbiddenToYaml);
|
|
130
|
+
}
|
|
131
|
+
return m;
|
|
132
|
+
}
|
|
133
|
+
function packageToYaml(pkg) {
|
|
134
|
+
return {
|
|
135
|
+
description: pkg.description,
|
|
136
|
+
may_import_from: [...pkg.may_import_from].sort(),
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
function namespacesToYaml(ns) {
|
|
140
|
+
const members = {};
|
|
141
|
+
const sortedMembers = Object.entries(ns.members).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0);
|
|
142
|
+
for (const [key, mem] of sortedMembers) {
|
|
143
|
+
members[key] = { path: mem.path, description: mem.description };
|
|
144
|
+
}
|
|
145
|
+
return {
|
|
146
|
+
description: ns.description,
|
|
147
|
+
members,
|
|
148
|
+
rules: [...ns.rules],
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Derive the `architecture.yaml` document for a module set.
|
|
153
|
+
*
|
|
154
|
+
* @param modules the selected module names (any order; deduped). Defaults to
|
|
155
|
+
* the same set `parse-args` defaults to when omitted (`['marketing']`).
|
|
156
|
+
* @param surfaces the enabled gateable route surfaces. Omitted ⟹ derived from
|
|
157
|
+
* the module set alone (`resolveSurfaces`), so a caller that passes only
|
|
158
|
+
* modules gets exactly what the modules imply.
|
|
159
|
+
* @returns the complete `architecture.yaml` file content (a deterministic
|
|
160
|
+
* function of the module SET and the surface SET).
|
|
161
|
+
* @throws Error on an unrecognized module (defensive; parse-args rejects first).
|
|
162
|
+
*/
|
|
163
|
+
export function deriveArchitecture(modules = ["marketing"], surfaces) {
|
|
164
|
+
const selected = normalizeModules(modules);
|
|
165
|
+
const slices = selected.map((m) => MODULE_SLICES[m]);
|
|
166
|
+
// The declared route surface (#4154). A scaffold's live-route set is a
|
|
167
|
+
// function of this list; the `surfaces:` block below is its machine-readable
|
|
168
|
+
// record, so "which routes does this site declare" is answerable without
|
|
169
|
+
// walking the app directory.
|
|
170
|
+
const enabledSurfaces = surfaces === undefined
|
|
171
|
+
? resolveSurfaces(selected)
|
|
172
|
+
: [...new Set(surfaces)].sort();
|
|
173
|
+
// apps/web (BASE) — may_import_from filled from the selected modules' webImports.
|
|
174
|
+
const webImports = sortedUnion(...slices.map((s) => s.webImports));
|
|
175
|
+
const apps = {
|
|
176
|
+
web: {
|
|
177
|
+
path: ARCHITECTURE_BASE.web.path,
|
|
178
|
+
description: ARCHITECTURE_BASE.web.description,
|
|
179
|
+
may_import_from: webImports,
|
|
180
|
+
may_not_import_from: [...ARCHITECTURE_BASE.web.may_not_import_from].sort(),
|
|
181
|
+
forbidden_patterns: ARCHITECTURE_BASE.web.forbidden_patterns.map(forbiddenToYaml),
|
|
182
|
+
},
|
|
183
|
+
};
|
|
184
|
+
// Additional apps (api, mcp, workspace) in canonical order.
|
|
185
|
+
const extraApps = {};
|
|
186
|
+
for (const s of slices)
|
|
187
|
+
Object.assign(extraApps, s.apps ?? {});
|
|
188
|
+
for (const key of ["api", "mcp", "workspace"]) {
|
|
189
|
+
const a = extraApps[key];
|
|
190
|
+
if (a)
|
|
191
|
+
apps[key] = appToYaml(a);
|
|
192
|
+
}
|
|
193
|
+
// packages — sorted union across the selected slices.
|
|
194
|
+
const packagesRaw = {};
|
|
195
|
+
for (const s of slices)
|
|
196
|
+
Object.assign(packagesRaw, s.packages ?? {});
|
|
197
|
+
const packages = {};
|
|
198
|
+
const sortedPackages = Object.entries(packagesRaw).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0);
|
|
199
|
+
for (const [key, pkg] of sortedPackages) {
|
|
200
|
+
packages[key] = packageToYaml(pkg);
|
|
201
|
+
}
|
|
202
|
+
// namespaces — present only if a data-tier module contributes one.
|
|
203
|
+
const nsSlice = slices.find((s) => s.namespaces)?.namespaces;
|
|
204
|
+
// forbidden_patterns — base floor first, then the selected modules' patterns.
|
|
205
|
+
const extraForbidden = [];
|
|
206
|
+
for (const s of slices)
|
|
207
|
+
extraForbidden.push(...(s.forbiddenPatterns ?? []));
|
|
208
|
+
const forbidden = mergeForbidden([...ARCHITECTURE_BASE.forbiddenPatterns], extraForbidden);
|
|
209
|
+
const doc = {
|
|
210
|
+
version: ARCHITECTURE_BASE.version,
|
|
211
|
+
composition_model: {
|
|
212
|
+
reference: ARCHITECTURE_BASE.composition_model.reference,
|
|
213
|
+
tiers: { ...ARCHITECTURE_BASE.composition_model.tiers },
|
|
214
|
+
},
|
|
215
|
+
surfaces: {
|
|
216
|
+
core: [...CORE_SURFACE_PATHS],
|
|
217
|
+
enabled: enabledSurfaces,
|
|
218
|
+
available: [...RECOGNIZED_SURFACES],
|
|
219
|
+
},
|
|
220
|
+
apps,
|
|
221
|
+
packages,
|
|
222
|
+
...(nsSlice ? { namespaces: namespacesToYaml(nsSlice) } : {}),
|
|
223
|
+
forbidden_patterns: forbidden.map(forbiddenToYaml),
|
|
224
|
+
};
|
|
225
|
+
const header = [
|
|
226
|
+
"# Architecture Boundaries — AI Launch Kit site",
|
|
227
|
+
"#",
|
|
228
|
+
"# GENERATED by create-ailk from the selected module set (--modules).",
|
|
229
|
+
"# The module set is the single source of truth for these boundaries.",
|
|
230
|
+
"# To change them, re-run create-ailk (or re-derive) with the new module",
|
|
231
|
+
"# set — do NOT hand-edit. Enforced by tools/lint-architecture.ts.",
|
|
232
|
+
"#",
|
|
233
|
+
`# Modules: ${selected.join(", ")}`,
|
|
234
|
+
`# Surfaces: ${enabledSurfaces.length > 0 ? enabledSurfaces.join(", ") : "core only"}`,
|
|
235
|
+
"",
|
|
236
|
+
].join("\n");
|
|
237
|
+
return header + emitDocument(doc);
|
|
238
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -4,7 +4,12 @@
|
|
|
4
4
|
* `dist/cli.js` (per `bin` in package.json).
|
|
5
5
|
*/
|
|
6
6
|
export { copyTemplate, type CopyTemplateOptions } from "./copy.js";
|
|
7
|
-
export { parseCliArgs, ParseError, helpText, type CliOptions, } from "./parse-args.js";
|
|
8
|
-
export { scaffold, scaffoldSync, type ScaffoldOptions, type ScaffoldResult, } from "./programmatic.js";
|
|
7
|
+
export { parseCliArgs, parseModules, ParseError, helpText, RECOGNIZED_MODULES, type ModuleName, type CliOptions, } from "./parse-args.js";
|
|
8
|
+
export { CATALOG_TARGET_PATH, FREE_MODULES, LicenseRequiredError, PAID_MODULES, classifyModules, formatSurfaceDrift, scaffold, scaffoldSync, syncArchitectureSync, syncCatalogSync, syncRoutesSync, type ResolvePaidModulesOptions, type ScaffoldOptions, type ScaffoldResult, type SyncArchitectureOptions, type SyncArchitectureResult, type SyncCatalogResult, type SyncRoutesSyncOptions, } from "./programmatic.js";
|
|
9
|
+
export { DEFAULT_AILK_MODULE_REGISTRY_URL, FetchModuleError, fetchModule, type FetchModuleOptions, } from "./lib/fetch-module.js";
|
|
10
|
+
export { extractModuleBundle, type ExtractModuleBundleOptions, } from "./lib/extract-module-bundle.js";
|
|
11
|
+
export { SYNC_ROUTES_HELP, formatSyncRoutesReport, listTemplateRouteDirs, parseSyncRoutesArgs, syncRoutes, type RouteReport, type SyncRoutesOptions, type SyncRoutesResult, } from "./sync-routes.js";
|
|
12
|
+
export { deriveArchitecture } from "./derive-architecture.js";
|
|
13
|
+
export { CORE_ROUTE_DIRS, CORE_SURFACE_PATHS, NAV_CONFIG_PATH, GATEABLE_SURFACES, MODULE_SURFACES, RECOGNIZED_SURFACES, ROUTE_SINCE, SurfaceError, excludedContentPaths, excludedRoutePaths, parseSurfaces, renderNavConfig, resolveSurfaces, surfaceForRouteDir, type Surface, } from "./surfaces.js";
|
|
9
14
|
export { substituteMarkers, substituteWorkspaceVersions, type MarkerMap, type WorkspaceVersionMap, } from "./substitute.js";
|
|
10
15
|
export { validateTarget, ValidationError } from "./validate.js";
|
package/dist/index.js
CHANGED
|
@@ -4,7 +4,24 @@
|
|
|
4
4
|
* `dist/cli.js` (per `bin` in package.json).
|
|
5
5
|
*/
|
|
6
6
|
export { copyTemplate } from "./copy.js";
|
|
7
|
-
export { parseCliArgs, ParseError, helpText, } from "./parse-args.js";
|
|
8
|
-
export { scaffold, scaffoldSync, } from "./programmatic.js";
|
|
7
|
+
export { parseCliArgs, parseModules, ParseError, helpText, RECOGNIZED_MODULES, } from "./parse-args.js";
|
|
8
|
+
export { CATALOG_TARGET_PATH, FREE_MODULES, LicenseRequiredError, PAID_MODULES, classifyModules, formatSurfaceDrift, scaffold, scaffoldSync, syncArchitectureSync, syncCatalogSync, syncRoutesSync, } from "./programmatic.js";
|
|
9
|
+
// The paid-module fetch/extract primitives (K1, #5089 — Flavor 3). Exported
|
|
10
|
+
// so tooling (and this repo's own evidence-run scripts) can drive the fetch
|
|
11
|
+
// path directly without re-implementing its shape.
|
|
12
|
+
export { DEFAULT_AILK_MODULE_REGISTRY_URL, FetchModuleError, fetchModule, } from "./lib/fetch-module.js";
|
|
13
|
+
export { extractModuleBundle, } from "./lib/extract-module-bundle.js";
|
|
14
|
+
// `create-ailk sync-routes` (#4986) — the template-route drift check + copy.
|
|
15
|
+
// The pure module is exported so tooling can run it against any template dir.
|
|
16
|
+
export { SYNC_ROUTES_HELP, formatSyncRoutesReport, listTemplateRouteDirs, parseSyncRoutesArgs, syncRoutes, } from "./sync-routes.js";
|
|
17
|
+
// The module-set → architecture.yaml derivation. Exported so the sync path
|
|
18
|
+
// (re-derive after a module is added) can re-run it (spec #3787 §2.1). The
|
|
19
|
+
// module→slice registry it composes is an internal detail, deliberately not
|
|
20
|
+
// re-exported.
|
|
21
|
+
export { deriveArchitecture } from "./derive-architecture.js";
|
|
22
|
+
// The route-surface registry (#4154) — which public routes a scaffold carries.
|
|
23
|
+
// Exported so tooling can answer "what surfaces does this site declare" without
|
|
24
|
+
// re-parsing architecture.yaml.
|
|
25
|
+
export { CORE_ROUTE_DIRS, CORE_SURFACE_PATHS, NAV_CONFIG_PATH, GATEABLE_SURFACES, MODULE_SURFACES, RECOGNIZED_SURFACES, ROUTE_SINCE, SurfaceError, excludedContentPaths, excludedRoutePaths, parseSurfaces, renderNavConfig, resolveSurfaces, surfaceForRouteDir, } from "./surfaces.js";
|
|
9
26
|
export { substituteMarkers, substituteWorkspaceVersions, } from "./substitute.js";
|
|
10
27
|
export { validateTarget, ValidationError } from "./validate.js";
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface ExtractModuleBundleOptions {
|
|
2
|
+
/** The fetched bundle bytes (a gzipped tar archive). */
|
|
3
|
+
bytes: Uint8Array;
|
|
4
|
+
/** The already-scaffolded target directory the module's files land in. */
|
|
5
|
+
targetDir: string;
|
|
6
|
+
/** The module name — used only for error messages and staging dir naming. */
|
|
7
|
+
moduleName: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Extract a fetched module bundle into `targetDir`, merging its files onto
|
|
11
|
+
* the tree `copyTemplate` already wrote. Throws on any unsafe entry,
|
|
12
|
+
* decompress error, or limit overrun — `targetDir` is left untouched on
|
|
13
|
+
* failure (validation completes in a throwaway staging dir before any file
|
|
14
|
+
* is copied into place).
|
|
15
|
+
*/
|
|
16
|
+
export declare function extractModuleBundle(options: ExtractModuleBundleOptions): Promise<void>;
|