create-ailk 0.5.0 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +55 -8
- package/component-catalog.json +336 -27
- package/component-catalog.md +25 -12
- package/dist/cli.js +54 -5
- package/dist/copy.d.ts +14 -0
- package/dist/copy.js +38 -1
- package/dist/lib/api-boot-assertion.d.ts +46 -0
- package/dist/lib/api-boot-assertion.js +70 -0
- package/dist/lib/extract-module-bundle.d.ts +20 -1
- package/dist/lib/extract-module-bundle.js +64 -5
- package/dist/lib/import-graph.d.ts +29 -0
- package/dist/lib/import-graph.js +140 -0
- package/dist/lib/module-license-gate.d.ts +6 -1
- package/dist/lib/module-license-gate.js +6 -1
- package/dist/lib/pro-callout.js +1 -1
- package/dist/module-architecture.d.ts +1 -0
- package/dist/module-architecture.js +253 -127
- package/dist/modules/commerce/0.6.0.tar.gz +0 -0
- package/dist/modules/docs-blog/0.6.0.tar.gz +0 -0
- package/dist/modules/multi-tenant/0.6.0.tar.gz +0 -0
- package/dist/modules/scheduling/0.6.0.tar.gz +0 -0
- package/dist/modules/signal-collectors/0.6.0.tar.gz +0 -0
- package/dist/modules/workspace/0.6.0.tar.gz +0 -0
- package/dist/programmatic.js +14 -10
- package/dist/surfaces.js +105 -7
- package/dist/template-manifest.d.ts +33 -0
- package/dist/template-manifest.js +99 -16
- package/dist/template-names.d.ts +1 -1
- package/dist/template-names.js +1 -0
- package/package.json +3 -2
- package/site-templates/marketing-site/DESIGN.md +148 -0
- package/site-templates/marketing-site/TEMPLATE-MANIFEST.json +22 -2
- package/site-templates/marketing-site/TEMPLATE-MANIFEST.md +9 -2
- package/site-templates/marketing-site/ailk-template.json +1 -1
- package/site-templates/marketing-site-free/DESIGN.md +148 -0
- package/site-templates/marketing-site-free/TEMPLATE-MANIFEST.json +2 -2
- package/site-templates/marketing-site-free/TEMPLATE-MANIFEST.md +1 -0
- package/site-templates/minimalism-site/DESIGN.md +148 -0
- package/site-templates/minimalism-site/TEMPLATE-MANIFEST.json +10 -2
- package/site-templates/minimalism-site/TEMPLATE-MANIFEST.md +47 -35
- package/site-templates/minimalism-site/ailk-template.json +2 -1
- package/site-templates/minimalism-site/assets/wordmark-placeholder.svg +28 -0
- package/site-templates/minimalism-site/content/en/HomePage/home.mdx +49 -19
- package/site-templates/saas-product/DESIGN.md +148 -0
- package/site-templates/simple-service/DESIGN.md +148 -0
- package/site-templates/simple-service/TEMPLATE-MANIFEST.json +240 -0
- package/site-templates/simple-service/TEMPLATE-MANIFEST.md +278 -0
- package/site-templates/simple-service/ailk-template.json +10 -0
- package/site-templates/simple-service/content/en/AboutPage/about.mdx +38 -0
- package/site-templates/simple-service/content/en/ContactPage/contact.mdx +67 -0
- package/site-templates/simple-service/content/en/FAQPage/faq.mdx +56 -0
- package/site-templates/simple-service/content/en/HomePage/home.mdx +85 -0
- package/site-templates/simple-service/content/en/Service/landscape-design.mdx +40 -0
- package/site-templates/simple-service/content/en/Service/lawn-maintenance.mdx +40 -0
- package/site-templates/simple-service/content/en/Service/seasonal-cleanup.mdx +40 -0
- package/site-templates/simple-service/content/en/ServicesList/services.mdx +72 -0
- package/site-templates/simple-service/provenance.json +4 -0
- package/templates/.env.example +72 -7
- package/templates/CLAUDE.md +2 -3
- package/templates/DESIGN.md +155 -0
- package/templates/README.md +42 -8
- package/templates/apps/api/.ailk/inbox/2026-09-20T14-57-31.552Z-fallback-1789916251590-037e9005.json +8 -0
- package/templates/apps/api/.ailk/inbox/2026-09-20T14-57-33.840Z-fallback-1789916253842-b52659e9.json +12 -0
- package/templates/apps/api/.ailk/inbox/2026-09-20T14-57-33.844Z-fallback-1789916253845-6b266f8c.json +12 -0
- package/templates/apps/api/.env.example +13 -0
- package/templates/apps/api/CLAUDE.md +26 -2
- package/templates/apps/api/jest.config.cjs +3 -0
- package/templates/apps/api/package.json +1 -0
- package/templates/apps/api/src/__tests__/commerce-claim-registration.test.ts +407 -0
- package/templates/apps/api/src/__tests__/module-exclusion.test.ts +83 -7
- package/templates/apps/api/src/__tests__/server.test.ts +471 -0
- package/templates/apps/api/src/__tests__/vercel-handler.test.ts +45 -0
- package/templates/apps/api/src/__tests__/workspace-module-registration.test.ts +2 -0
- package/templates/apps/api/src/config/index.ts +62 -0
- package/templates/apps/api/src/config/modules.ts +7 -3
- package/templates/apps/api/src/lib/__mocks__/prisma.ts +238 -2
- package/templates/apps/api/src/lib/__tests__/auth-email-budget.test.ts +143 -0
- package/templates/apps/api/src/lib/__tests__/content-adapter.test.ts +23 -0
- package/templates/apps/api/src/lib/__tests__/deliverable-asset-store.test.ts +125 -0
- package/templates/apps/api/src/lib/__tests__/error-serializer.test.ts +20 -0
- package/templates/apps/api/src/lib/__tests__/require-commerce-claim.test.ts +317 -0
- package/templates/apps/api/src/lib/__tests__/site.test.ts +238 -0
- package/templates/apps/api/src/lib/__tests__/stripe.test.ts +75 -0
- package/templates/apps/api/src/lib/auth-email-budget.ts +160 -0
- package/templates/apps/api/src/lib/content-adapter.ts +57 -31
- package/templates/apps/api/src/lib/deliverable-asset-store.ts +76 -0
- package/templates/apps/api/src/lib/error-serializer.ts +23 -3
- package/templates/apps/api/src/lib/outbound-http.ts +7 -2
- package/templates/apps/api/src/lib/require-commerce-claim.ts +250 -0
- package/templates/apps/api/src/lib/site.ts +208 -9
- package/templates/apps/api/src/lib/stripe.ts +66 -0
- package/templates/apps/api/src/middleware/__tests__/default-tenant.test.ts +182 -0
- package/templates/apps/api/src/middleware/__tests__/rate-limit.test.ts +42 -0
- package/templates/apps/api/src/middleware/rate-limit.ts +7 -1
- package/templates/apps/api/src/openapi/spec.ts +543 -2
- package/templates/apps/api/src/routes/auth/__tests__/auth-user.functional.test.ts +48 -0
- package/templates/apps/api/src/routes/auth/__tests__/transactional-email.test.ts +309 -0
- package/templates/apps/api/src/routes/auth/__tests__/user.test.ts +123 -0
- package/templates/apps/api/src/routes/auth/transactional-email.ts +273 -0
- package/templates/apps/api/src/routes/auth/user.ts +61 -0
- package/templates/apps/api/src/routes/checkout/__tests__/session.test.ts +434 -0
- package/templates/apps/api/src/routes/checkout/__tests__/sessions.test.ts +888 -0
- package/templates/apps/api/src/routes/checkout/index.ts +34 -0
- package/templates/apps/api/src/routes/checkout/session.ts +139 -0
- package/templates/apps/api/src/routes/checkout/sessions.ts +197 -0
- package/templates/apps/api/src/routes/content/__tests__/get-page.test.ts +554 -0
- package/templates/apps/api/src/routes/content/__tests__/list-pages.test.ts +108 -0
- package/templates/apps/api/src/routes/content/__tests__/search.test.ts +450 -0
- package/templates/apps/api/src/routes/content/get-page.ts +94 -12
- package/templates/apps/api/src/routes/content/index.ts +13 -73
- package/templates/apps/api/src/routes/content/list-pages.ts +15 -3
- package/templates/apps/api/src/routes/content/rate-limit.ts +15 -6
- package/templates/apps/api/src/routes/content/search.ts +129 -0
- package/templates/apps/api/src/routes/leads/__tests__/index.test.ts +447 -31
- package/templates/apps/api/src/routes/leads/index.ts +100 -13
- package/templates/apps/api/src/routes/project-listings/__tests__/configured-application.test.ts +51 -0
- package/templates/apps/api/src/routes/project-listings/__tests__/drafts.test.ts +351 -0
- package/templates/apps/api/src/routes/project-listings/__tests__/founder-identity.test.ts +51 -0
- package/templates/apps/api/src/routes/project-listings/__tests__/me.test.ts +5 -2
- package/templates/apps/api/src/routes/project-listings/__tests__/public.test.ts +4 -1
- package/templates/apps/api/src/routes/project-listings/__tests__/resume-email.test.ts +58 -0
- package/templates/apps/api/src/routes/project-listings/__tests__/site-answers.test.ts +107 -6
- package/templates/apps/api/src/routes/project-listings/__tests__/site-key.test.ts +87 -2
- package/templates/apps/api/src/routes/project-listings/__tests__/structured-address.test.ts +51 -0
- package/templates/apps/api/src/routes/project-listings/start.ts +5 -1
- package/templates/apps/api/src/routes/requests/__tests__/confirm.test.ts +686 -0
- package/templates/apps/api/src/routes/requests/confirm.ts +601 -0
- package/templates/apps/api/src/routes/requests/index.ts +54 -0
- package/templates/apps/api/src/routes/webhooks/README.md +265 -0
- package/templates/apps/api/src/routes/webhooks/__tests__/stripe-dunning.test.ts +749 -0
- package/templates/apps/api/src/routes/webhooks/__tests__/stripe-flow-checkout.test.ts +330 -0
- package/templates/apps/api/src/routes/webhooks/__tests__/stripe-idempotency.test.ts +262 -0
- package/templates/apps/api/src/routes/webhooks/__tests__/stripe-org-billing.test.ts +285 -0
- package/templates/apps/api/src/routes/webhooks/__tests__/stripe-rate-limit.test.ts +213 -0
- package/templates/apps/api/src/routes/webhooks/__tests__/stripe-request-paid.test.ts +301 -0
- package/templates/apps/api/src/routes/webhooks/__tests__/stripe.test.ts +648 -0
- package/templates/apps/api/src/routes/webhooks/index.ts +89 -0
- package/templates/apps/api/src/routes/webhooks/stripe.ts +1399 -0
- package/templates/apps/api/src/server.ts +439 -49
- package/templates/apps/api/src/services/__tests__/abandon-email.test.ts +39 -0
- package/templates/apps/api/src/services/__tests__/aeo-score.test.ts +217 -40
- package/templates/apps/api/src/services/__tests__/audit-log.test.ts +620 -0
- package/templates/apps/api/src/services/__tests__/consent.test.ts +2 -0
- package/templates/apps/api/src/services/__tests__/deliverable-fulfillment.test.ts +300 -5
- package/templates/apps/api/src/services/__tests__/deliverable-resend.test.ts +20 -0
- package/templates/apps/api/src/services/__tests__/dunning-policy.test.ts +368 -0
- package/templates/apps/api/src/services/__tests__/lead-routing.test.ts +160 -0
- package/templates/apps/api/src/services/__tests__/listing-config.test.ts +166 -0
- package/templates/apps/api/src/services/__tests__/project-listings.fence.test.ts +154 -0
- package/templates/apps/api/src/services/__tests__/public-site-resolver.test.ts +137 -0
- package/templates/apps/api/src/services/__tests__/request-confirm.test.ts +444 -0
- package/templates/apps/api/src/services/__tests__/revalidation.test.ts +238 -0
- package/templates/apps/api/src/services/__tests__/verified-email.test.ts +78 -0
- package/templates/apps/api/src/services/abandon-email.ts +8 -2
- package/templates/apps/api/src/services/aeo-score.ts +49 -12
- package/templates/apps/api/src/services/audit-log.ts +668 -0
- package/templates/apps/api/src/services/consent.ts +18 -0
- package/templates/apps/api/src/services/default-tenant.ts +70 -31
- package/templates/apps/api/src/services/deliverable-fulfillment.ts +141 -13
- package/templates/apps/api/src/services/dunning-policy.ts +294 -0
- package/templates/apps/api/src/services/entitlements.ts +80 -0
- package/templates/apps/api/src/services/lead-promotion.ts +13 -14
- package/templates/apps/api/src/services/lead-routing.ts +161 -2
- package/templates/apps/api/src/services/leads-inbox.ts +23 -2
- package/templates/apps/api/src/services/listing-config.ts +27 -9
- package/templates/apps/api/src/services/project-listings.ts +201 -6
- package/templates/apps/api/src/services/public-site-resolver.ts +106 -0
- package/templates/apps/api/src/services/request-confirm.ts +646 -0
- package/templates/apps/api/src/services/revalidation.ts +173 -0
- package/templates/apps/api/src/services/verified-email.ts +71 -0
- package/templates/apps/api/src/vercel-handler.ts +75 -35
- package/templates/apps/mcp/.env.example +17 -0
- package/templates/apps/mcp/CLAUDE.md +57 -24
- package/templates/apps/mcp/__tests__/aeo-cli-parity.test.ts +6 -0
- package/templates/apps/mcp/__tests__/audit.test.ts +137 -8
- package/templates/apps/mcp/__tests__/catalog-drift.test.ts +79 -36
- package/templates/apps/mcp/__tests__/get_offerings.test.ts +111 -2
- package/templates/apps/mcp/__tests__/get_pricing.test.ts +82 -2
- package/templates/apps/mcp/__tests__/http-transport.test.ts +541 -2
- package/templates/apps/mcp/__tests__/index.test.ts +39 -0
- package/templates/apps/mcp/__tests__/lib/audit-single-page-readiness-scan.test.ts +143 -0
- package/templates/apps/mcp/__tests__/lib/commerce-claim.test.ts +111 -0
- package/templates/apps/mcp/__tests__/lib/content-adapter-parity.test.ts +65 -0
- package/templates/apps/mcp/__tests__/lib/content-adapter.test.ts +188 -0
- package/templates/apps/mcp/__tests__/lib/fail-closed-tools.test.ts +165 -0
- package/templates/apps/mcp/__tests__/lib/public-workspace.test.ts +124 -0
- package/templates/apps/mcp/__tests__/list_pages.test.ts +116 -0
- package/templates/apps/mcp/__tests__/module-exclusion.test.ts +7 -1
- package/templates/apps/mcp/__tests__/parity.test.ts +10 -7
- package/templates/apps/mcp/__tests__/purchase-disabled.test.ts +89 -22
- package/templates/apps/mcp/__tests__/read_content.test.ts +322 -1
- package/templates/apps/mcp/__tests__/search_content.test.ts +105 -2
- package/templates/apps/mcp/__tests__/server.test.ts +67 -14
- package/templates/apps/mcp/__tests__/start_purchase.test.ts +252 -0
- package/templates/apps/mcp/__tests__/tools/purchase.test.ts +300 -123
- package/templates/apps/mcp/jest.config.cjs +13 -0
- package/templates/apps/mcp/package.json +2 -0
- package/templates/apps/mcp/src/abuse/index.ts +159 -24
- package/templates/apps/mcp/src/config/modules.ts +10 -5
- package/templates/apps/mcp/src/http-transport.ts +102 -29
- package/templates/apps/mcp/src/index.ts +73 -11
- package/templates/apps/mcp/src/lib/audit-single-page.ts +90 -3
- package/templates/apps/mcp/src/lib/commerce-claim.ts +94 -0
- package/templates/apps/mcp/src/lib/content-adapter.ts +113 -0
- package/templates/apps/mcp/src/lib/empty-content-adapter.ts +139 -0
- package/templates/apps/mcp/src/lib/prisma.ts +39 -0
- package/templates/apps/mcp/src/lib/public-workspace.ts +133 -0
- package/templates/apps/mcp/src/lib/stripe-tax-signal.ts +59 -0
- package/templates/apps/mcp/src/server.ts +59 -35
- package/templates/apps/mcp/src/tools/audit.ts +26 -2
- package/templates/apps/mcp/src/tools/get_business_hours.ts +4 -3
- package/templates/apps/mcp/src/tools/get_faq.ts +4 -3
- package/templates/apps/mcp/src/tools/get_locations.ts +5 -3
- package/templates/apps/mcp/src/tools/get_offerings.ts +16 -4
- package/templates/apps/mcp/src/tools/get_pricing.ts +25 -6
- package/templates/apps/mcp/src/tools/get_site_info.ts +4 -3
- package/templates/apps/mcp/src/tools/index.ts +6 -4
- package/templates/apps/mcp/src/tools/list_pages.ts +4 -3
- package/templates/apps/mcp/src/tools/purchase.ts +128 -45
- package/templates/apps/mcp/src/tools/read_content.ts +20 -6
- package/templates/apps/mcp/src/tools/search_content.ts +11 -4
- package/templates/apps/web/.env.example +71 -5
- package/templates/apps/web/CLAUDE.md +44 -0
- package/templates/apps/web/PRODUCT.md +86 -0
- package/templates/apps/web/app/.well-known/mcp.json/build-manifest.ts +18 -2
- package/templates/apps/web/app/.well-known/mcp.json/route.ts +11 -3
- package/templates/apps/web/app/[locale]/(auth)/__tests__/auth-pages.test.tsx +282 -0
- package/templates/apps/web/app/[locale]/(auth)/__tests__/password-reset.test.tsx +515 -0
- package/templates/apps/web/app/[locale]/(auth)/forgot-password/forgot-password-card.tsx +89 -0
- package/templates/apps/web/app/[locale]/(auth)/forgot-password/page.tsx +109 -0
- package/templates/apps/web/app/[locale]/(auth)/layout.tsx +92 -0
- package/templates/apps/web/app/[locale]/(auth)/reset-password/page.tsx +135 -0
- package/templates/apps/web/app/[locale]/(auth)/reset-password/reset-password-card.tsx +109 -0
- package/templates/apps/web/app/[locale]/{sign-in → (auth)/sign-in}/__tests__/page.test.tsx +48 -2
- package/templates/apps/web/app/[locale]/{sign-in → (auth)/sign-in}/page.tsx +20 -6
- package/templates/apps/web/app/[locale]/(auth)/sign-in/sign-in-card.tsx +125 -0
- package/templates/apps/web/app/[locale]/(auth)/sign-up/page.tsx +96 -0
- package/templates/apps/web/app/[locale]/(auth)/sign-up/sign-up-card.tsx +101 -0
- package/templates/apps/web/app/[locale]/(auth)/use-auth-card-flow.ts +102 -0
- package/templates/apps/web/app/[locale]/(auth)/verify-email/page.tsx +87 -0
- package/templates/apps/web/app/[locale]/(authed)/__tests__/gate.test.tsx +20 -10
- package/templates/apps/web/app/[locale]/(authed)/account/__tests__/page.test.tsx +84 -0
- package/templates/apps/web/app/[locale]/(authed)/account/actions.ts +58 -0
- package/templates/apps/web/app/[locale]/(authed)/account/page.tsx +63 -8
- package/templates/apps/web/app/[locale]/(authed)/layout.tsx +18 -1
- package/templates/apps/web/app/[locale]/cancellation/page.tsx +44 -0
- package/templates/apps/web/app/[locale]/layout.tsx +133 -87
- package/templates/apps/web/app/[locale]/purchase/__tests__/cancel.test.tsx +162 -0
- package/templates/apps/web/app/[locale]/purchase/__tests__/module-scope.test.ts +68 -0
- package/templates/apps/web/app/[locale]/purchase/__tests__/success.test.tsx +361 -0
- package/templates/apps/web/app/[locale]/purchase/cancel/page.tsx +115 -0
- package/templates/apps/web/app/[locale]/purchase/success/page.tsx +307 -0
- package/templates/apps/web/app/[locale]/returns/page.tsx +44 -0
- package/templates/apps/web/app/[locale]/shipping/page.tsx +44 -0
- package/templates/apps/web/app/api/revalidate/__tests__/route.test.ts +670 -0
- package/templates/apps/web/app/api/revalidate/route.ts +194 -0
- package/templates/apps/web/auth.ts +407 -8
- package/templates/apps/web/jest.config.cjs +8 -4
- package/templates/apps/web/lib/__tests__/auth-email.test.ts +214 -0
- package/templates/apps/web/lib/__tests__/auth-routes.test.ts +74 -0
- package/templates/apps/web/lib/__tests__/meeting-slugs.test.ts +72 -0
- package/templates/apps/web/lib/__tests__/site-theme.test.ts +135 -20
- package/templates/apps/web/lib/__tests__/structured-data.test.tsx +18 -1
- package/templates/apps/web/lib/auth-email.ts +318 -0
- package/templates/apps/web/lib/auth-env.ts +85 -0
- package/templates/apps/web/lib/auth-routes.ts +55 -0
- package/templates/apps/web/lib/meeting-slugs.ts +53 -0
- package/templates/apps/web/lib/site-brand.tsx +4 -8
- package/templates/apps/web/lib/telemetry-scrub.ts +5 -1
- package/templates/apps/web/messages/en.json +187 -0
- package/templates/apps/web/middleware.ts +1 -1
- package/templates/apps/web/package.json +2 -1
- package/templates/apps/web/src/lib/commerce-claim.ts +33 -0
- package/templates/apps/web/src/lib/commerce-sections.ts +93 -0
- package/templates/content/_site.mdx +18 -3
- package/templates/content/en/CancellationPolicyPage/cancellation.mdx +108 -0
- package/templates/content/en/ReturnsPolicyPage/returns.mdx +108 -0
- package/templates/content/en/ShippingPolicyPage/shipping.mdx +108 -0
- package/templates/database/CHANGELOG.md +149 -0
- package/templates/database/README.md +10 -3
- package/templates/database/__tests__/appointment.db.test.ts +106 -0
- package/templates/database/__tests__/artifact-content-store.db.test.ts +316 -0
- package/templates/database/__tests__/composite-fence.db.test.ts +206 -0
- package/templates/database/__tests__/fence-fan-out.db.test.ts +711 -0
- package/templates/database/__tests__/fixtures/appointment-create-probe.ts +79 -0
- package/templates/database/__tests__/fixtures/project-listing-consent-probe.ts +100 -0
- package/templates/database/__tests__/flow-workspace-key.db.test.ts +263 -0
- package/templates/database/__tests__/prefixed-ids.db.test.ts +85 -9
- package/templates/database/__tests__/project-listing-consent-at.db.test.ts +111 -0
- package/templates/database/__tests__/tenancy.test.ts +141 -0
- package/templates/database/config/schema.prisma +79 -2
- package/templates/database/content/schema.prisma +87 -11
- package/templates/database/inbox/schema.prisma +452 -9
- package/templates/database/jest.config.cjs +5 -3
- package/templates/database/migrations/20260915120000_project_listing_solution/migration.sql +15 -0
- package/templates/database/migrations/20260916120000_artifact_content_store/migration.sql +158 -0
- package/templates/database/migrations/20260917120000_callback_request_confirm/migration.sql +40 -0
- package/templates/database/migrations/20260918120000_add_appointment/migration.sql +67 -0
- package/templates/database/migrations/20260918120000_asset_metadata_columns/migration.sql +70 -0
- package/templates/database/migrations/20260919120000_flow_workspace_key/migration.sql +181 -0
- package/templates/database/migrations/20260919130000_flow_definition_admin_columns/migration.sql +172 -0
- package/templates/database/migrations/20260919130000_workspace_meetings/migration.sql +41 -0
- package/templates/database/migrations/20260919140000_inbox_workspace_key/migration.sql +185 -0
- package/templates/database/migrations/20260920120000_lead_handled_at/migration.sql +70 -0
- package/templates/database/migrations/20260920130000_lead_workspace_source_index/migration.sql +57 -0
- package/templates/database/migrations/20260921120000_deliverable_grant_workspace_key/migration.sql +68 -0
- package/templates/database/migrations/20260922120000_tenancy_fence/migration.sql +1067 -0
- package/templates/database/migrations/20260923120000_listing_capturing_magnet/migration.sql +210 -0
- package/templates/database/package.json +3 -2
- package/templates/database/tenancy.ts +86 -1
- package/templates/database/tsconfig.json +1 -0
- package/versions.json +34 -34
- package/templates/apps/api/src/routes/content/__tests__/create.test.ts +0 -253
- package/templates/apps/api/src/routes/content/__tests__/delete.test.ts +0 -215
- package/templates/apps/api/src/routes/content/__tests__/update.test.ts +0 -266
- package/templates/apps/api/src/routes/content/create.ts +0 -115
- package/templates/apps/api/src/routes/content/delete.ts +0 -82
- package/templates/apps/api/src/routes/content/update.ts +0 -112
- package/templates/apps/mcp/__tests__/create_page.test.ts +0 -202
- package/templates/apps/mcp/__tests__/delete_page.test.ts +0 -177
- package/templates/apps/mcp/__tests__/update_page.test.ts +0 -196
- package/templates/apps/mcp/src/tools/create_page.ts +0 -96
- package/templates/apps/mcp/src/tools/delete_page.ts +0 -74
- package/templates/apps/mcp/src/tools/update_page.ts +0 -92
- package/templates/apps/web/app/[locale]/sign-in/sign-in-card.tsx +0 -123
- package/templates/apps/web/public/logo-dark.svg +0 -21
- package/templates/apps/web/public/logo-light.svg +0 -21
- /package/templates/apps/web/app/[locale]/{sign-in → (auth)/sign-in}/__tests__/next-path.test.ts +0 -0
- /package/templates/apps/web/app/[locale]/{sign-in → (auth)/sign-in}/next-path.ts +0 -0
|
@@ -83,8 +83,10 @@ import { isAbsolute, join, normalize, relative, resolve, sep } from "node:path";
|
|
|
83
83
|
import { pipeline } from "node:stream/promises";
|
|
84
84
|
import { createGunzip } from "node:zlib";
|
|
85
85
|
import * as tar from "tar";
|
|
86
|
+
import { isTextFile } from "../copy.js";
|
|
86
87
|
import { coOwnedModuleDestinations, } from "../module-architecture.js";
|
|
87
88
|
import { validateTemplateLayout, } from "../site-chrome.js";
|
|
89
|
+
import { substituteMarkers, } from "../substitute.js";
|
|
88
90
|
import { computeModulePatches, writeModulePatches } from "./apply-module-patches.js";
|
|
89
91
|
/** Soft limits to prevent decompression-bomb / zip-bomb attacks. Same values as extractBundle. */
|
|
90
92
|
const MAX_ENTRIES = 1000;
|
|
@@ -446,6 +448,7 @@ export async function extractModuleBundle(options) {
|
|
|
446
448
|
: {}),
|
|
447
449
|
...(options.ownership !== undefined ? { ownership: options.ownership } : {}),
|
|
448
450
|
...(options.versions !== undefined ? { versions: options.versions } : {}),
|
|
451
|
+
...(options.markers !== undefined ? { markers: options.markers } : {}),
|
|
449
452
|
});
|
|
450
453
|
}
|
|
451
454
|
finally {
|
|
@@ -463,7 +466,7 @@ export async function extractModuleBundle(options) {
|
|
|
463
466
|
* rejected tree leaves `targetDir` exactly as it was.
|
|
464
467
|
*/
|
|
465
468
|
export function installBundleTree(options) {
|
|
466
|
-
const { sourceRoot, name, templateRequires, templateExtends, ownership } = options;
|
|
469
|
+
const { sourceRoot, name, templateRequires, templateExtends, ownership, markers } = options;
|
|
467
470
|
const targetAbs = resolve(options.targetDir);
|
|
468
471
|
const isTemplate = templateRequires !== undefined;
|
|
469
472
|
const subject = isTemplate ? `template "${name}"` : `module "${name}"`;
|
|
@@ -526,6 +529,17 @@ export function installBundleTree(options) {
|
|
|
526
529
|
// installMap destination) is read from the STAGED tree here, since
|
|
527
530
|
// targetDir would not have it yet at this point.
|
|
528
531
|
const installMapDestinationToSource = new Map(Object.entries(installMap).map(([source, destination]) => [destination, source]));
|
|
532
|
+
// #6460 — a patch target is read RAW from the staged tree here, while
|
|
533
|
+
// `copyTree` below writes the same path SUBSTITUTED, and
|
|
534
|
+
// `writeModulePatches` runs after `copyTree`. So a file a bundle both
|
|
535
|
+
// delivers as plain content AND patches would end up carrying unsubstituted
|
|
536
|
+
// markers. Unreachable today and asserted as such rather than guarded: the
|
|
537
|
+
// only patch targets any slice declares are `apps/web/package.json`,
|
|
538
|
+
// `next.config.mjs` and `jest.config.cjs`, all three delivered by the base
|
|
539
|
+
// `templates/` snapshot rather than by a bundle — so this reader falls
|
|
540
|
+
// through to the `targetAbs` branch and reads already-substituted bytes —
|
|
541
|
+
// and a template is refused `patches` outright above. A bundle that starts
|
|
542
|
+
// delivering one of its own patch targets must substitute here too.
|
|
529
543
|
const readPatchTarget = (target) => {
|
|
530
544
|
const mappedSource = installMapDestinationToSource.get(target);
|
|
531
545
|
if (mappedSource !== undefined) {
|
|
@@ -550,11 +564,18 @@ export function installBundleTree(options) {
|
|
|
550
564
|
// every installMap source are excluded from the whole-tree copy — the
|
|
551
565
|
// manifest never lands in the scaffold, and a mapped source lands ONLY
|
|
552
566
|
// at its mapped destination, never also at its original path.
|
|
553
|
-
copyTree(sourceRoot, targetAbs, excluded);
|
|
567
|
+
copyTree(sourceRoot, targetAbs, excluded, markers);
|
|
554
568
|
for (const [source, destination] of Object.entries(installMap)) {
|
|
555
569
|
const destAbs = resolve(targetAbs, destination);
|
|
556
570
|
mkdirSync(join(destAbs, ".."), { recursive: true });
|
|
557
|
-
|
|
571
|
+
// BOTH ends decide text-ness (#6460), because an installMap entry is free
|
|
572
|
+
// to rename across the boundary and the two mismatches are not
|
|
573
|
+
// symmetric: a text source landing at a binary name merely misses a
|
|
574
|
+
// substitution, while a BINARY source landing at a text name would be
|
|
575
|
+
// read as utf8 and rewritten, turning every invalid byte sequence into
|
|
576
|
+
// U+FFFD — silent, unrecoverable corruption. Requiring both makes the
|
|
577
|
+
// safe direction structural rather than a property of today's manifests.
|
|
578
|
+
writeOneFile(resolve(sourceRoot, source), destAbs, [source, destination], markers);
|
|
558
579
|
}
|
|
559
580
|
// patches write AFTER every file the tree brought is in place (D5) —
|
|
560
581
|
// after installMap, before postInstall — so a patch can never race a
|
|
@@ -589,8 +610,11 @@ export function installBundleTree(options) {
|
|
|
589
610
|
* `safeExtractTarGz` has validated every entry, so no additional
|
|
590
611
|
* path-safety check is needed here — `srcRoot` is our own staging tree, not
|
|
591
612
|
* attacker-controlled input.
|
|
613
|
+
*
|
|
614
|
+
* `markers`, when given, is substituted into every TEXT file on the way
|
|
615
|
+
* through (#6460) — see `InstallBundleTreeOptions.markers`.
|
|
592
616
|
*/
|
|
593
|
-
function copyTree(srcRoot, destRoot, excluded = new Set()) {
|
|
617
|
+
function copyTree(srcRoot, destRoot, excluded = new Set(), markers) {
|
|
594
618
|
const stack = [srcRoot];
|
|
595
619
|
while (stack.length > 0) {
|
|
596
620
|
const dir = stack.pop();
|
|
@@ -608,12 +632,47 @@ function copyTree(srcRoot, destRoot, excluded = new Set()) {
|
|
|
608
632
|
if (excluded.has(rel.split(sep).join("/")))
|
|
609
633
|
continue;
|
|
610
634
|
mkdirSync(join(destPath, ".."), { recursive: true });
|
|
611
|
-
|
|
635
|
+
writeOneFile(srcPath, destPath, [rel], markers);
|
|
612
636
|
}
|
|
613
637
|
// symlinks: never present — safeExtractTarGz rejects them outright.
|
|
614
638
|
}
|
|
615
639
|
}
|
|
616
640
|
}
|
|
641
|
+
/**
|
|
642
|
+
* Land one file at `destAbs`, substituting `markers` into it when EVERY path
|
|
643
|
+
* in `relsForType` is text by `copy.ts`'s own `isTextFile` (#6460) — the
|
|
644
|
+
* source's relative path alone for a plain-content copy, source AND
|
|
645
|
+
* destination for an installMap entry, which may rename across the
|
|
646
|
+
* text/binary boundary. Unanimity rather than either-or, so binary content is
|
|
647
|
+
* never round-tripped through a utf8 string by construction; see the
|
|
648
|
+
* installMap loop for why the two mismatch directions are not symmetric.
|
|
649
|
+
*
|
|
650
|
+
* With no `markers`, or with any non-text path, this is exactly the
|
|
651
|
+
* `copyFileSync` it replaced.
|
|
652
|
+
*
|
|
653
|
+
* `isTextFile` is an allowlist of extensions, NOT "anything that parses as
|
|
654
|
+
* text": `.css`, `.html`, `.svg`, `.sh`, `.toml` and `.sql` are outside it, so
|
|
655
|
+
* a marker authored in one of those survives verbatim. That is pre-existing
|
|
656
|
+
* `copyTemplate` behaviour, deliberately shared rather than forked here.
|
|
657
|
+
*
|
|
658
|
+
* The source's mode rides along, because `copyFileSync` preserves it and
|
|
659
|
+
* `writeFileSync` does not: no tree this installs carries an executable file
|
|
660
|
+
* today, but a module slice is free to ship one, and a substituted `.mjs`
|
|
661
|
+
* silently losing its `+x` surfaces as "the scaffold builds but the hook never
|
|
662
|
+
* runs". Masked to the permission bits — `statSync().mode` carries the
|
|
663
|
+
* `S_IFREG` type bits too, which `open(2)` ignores but which have no business
|
|
664
|
+
* being passed. Like `copyFileSync`, this only sets the mode when the file is
|
|
665
|
+
* CREATED: an overwrite (the layer-over-layer case) keeps the existing one.
|
|
666
|
+
*/
|
|
667
|
+
function writeOneFile(srcAbs, destAbs, relsForType, markers) {
|
|
668
|
+
if (markers === undefined || !relsForType.every(isTextFile)) {
|
|
669
|
+
copyFileSync(srcAbs, destAbs);
|
|
670
|
+
return;
|
|
671
|
+
}
|
|
672
|
+
writeFileSync(destAbs, substituteMarkers(readFileSync(srcAbs, "utf8"), markers), {
|
|
673
|
+
mode: statSync(srcAbs).mode & 0o777,
|
|
674
|
+
});
|
|
675
|
+
}
|
|
617
676
|
/**
|
|
618
677
|
* `extractBundle`'s validating-filter tar extraction, ported verbatim (see
|
|
619
678
|
* file doc for why this is a port and not an import). Extracts `tarGzPath`
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export declare const SOURCE_EXTS: string[];
|
|
2
|
+
/** Every source file under the given repo-relative roots, as "/"-joined paths. */
|
|
3
|
+
export declare function listFilesUnder(repoRoot: string, roots: string[]): Set<string>;
|
|
4
|
+
/** The relative import specifiers a source file names (static imports + re-exports). */
|
|
5
|
+
export declare function relativeImportsOf(absPath: string): string[];
|
|
6
|
+
/**
|
|
7
|
+
* Resolve a relative specifier against the candidate set. TypeScript ESM writes
|
|
8
|
+
* `./x.js` for `./x.ts`, so the `.js` → `.ts`/`.tsx` rewrite is the common case.
|
|
9
|
+
*/
|
|
10
|
+
export declare function resolveRelativeImport(fromFile: string, spec: string, candidates: Set<string>): string | undefined;
|
|
11
|
+
/**
|
|
12
|
+
* The companion closure of `seeds` under `roots`: the seeds themselves plus
|
|
13
|
+
* every source file under `roots` that reaches one transitively through a
|
|
14
|
+
* relative import, to a fixed point.
|
|
15
|
+
*
|
|
16
|
+
* This is the shape both consumers need, and the reason the walk is shared
|
|
17
|
+
* rather than copied. `paidModuleTemplateExclusions()` seeds it with every
|
|
18
|
+
* paid module's `ownedFiles` to get the files a keyless starter must not
|
|
19
|
+
* carry; `tools/lint-slice-registration.ts` seeds it with the same set to
|
|
20
|
+
* derive, by subtraction, the files a scaffold ships UNCONDITIONALLY.
|
|
21
|
+
*
|
|
22
|
+
* Never a filename-stem rule (#5182 D7), which misses eleven files and
|
|
23
|
+
* over-marks three.
|
|
24
|
+
*
|
|
25
|
+
* @param repoRoot absolute path to the tree being walked.
|
|
26
|
+
* @param roots repo-relative roots the walk is confined to.
|
|
27
|
+
* @param seeds repo-relative, "/"-separated files the closure starts from.
|
|
28
|
+
*/
|
|
29
|
+
export declare function importClosure(repoRoot: string, roots: readonly string[], seeds: Iterable<string>): Set<string>;
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The relative-import graph walker over a repo-relative source tree.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from `module-architecture.ts` (#5701) so the two consumers that
|
|
5
|
+
* need this resolution share ONE implementation rather than two that can
|
|
6
|
+
* disagree:
|
|
7
|
+
*
|
|
8
|
+
* - `paidModuleTemplateExclusions()` (module-architecture.ts) walks it to take
|
|
9
|
+
* the companion closure of every paid module's `ownedFiles` — the files that
|
|
10
|
+
* would ship dangling into a keyless starter.
|
|
11
|
+
* - `tools/lint-slice-registration.ts` walks it to close over the specifiers an
|
|
12
|
+
* `isModuleEnabled("X")` branch in `apps/api/src/server.ts` loads, and to
|
|
13
|
+
* check every reached file against what module X's slice delivers.
|
|
14
|
+
*
|
|
15
|
+
* Both questions are "which files does this one reach through relative
|
|
16
|
+
* imports", and the answer must be the same function in both mouths: a lint
|
|
17
|
+
* that resolved specifiers differently from the exclusion set it checks
|
|
18
|
+
* against would pass on a tree the scaffold cannot boot.
|
|
19
|
+
*
|
|
20
|
+
* The resolution is deliberately TEXTUAL — a regex over import/export
|
|
21
|
+
* specifiers plus a candidate-set lookup, no type-checker and no bundler — so
|
|
22
|
+
* it runs inside `pnpm preflight`'s memory budget.
|
|
23
|
+
*/
|
|
24
|
+
import { readFileSync, readdirSync } from "node:fs";
|
|
25
|
+
import { dirname, join, sep } from "node:path";
|
|
26
|
+
export const SOURCE_EXTS = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
|
|
27
|
+
/** Every source file under the given repo-relative roots, as "/"-joined paths. */
|
|
28
|
+
export function listFilesUnder(repoRoot, roots) {
|
|
29
|
+
const out = new Set();
|
|
30
|
+
const skip = new Set(["node_modules", ".next", "dist", ".turbo", ".source"]);
|
|
31
|
+
const stack = roots.map((r) => r);
|
|
32
|
+
while (stack.length > 0) {
|
|
33
|
+
const rel = stack.pop();
|
|
34
|
+
const abs = join(repoRoot, rel);
|
|
35
|
+
let entries;
|
|
36
|
+
try {
|
|
37
|
+
entries = readdirSync(abs, { withFileTypes: true });
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
for (const entry of entries) {
|
|
43
|
+
if (skip.has(entry.name))
|
|
44
|
+
continue;
|
|
45
|
+
const childRel = `${rel}/${entry.name}`;
|
|
46
|
+
if (entry.isDirectory())
|
|
47
|
+
stack.push(childRel);
|
|
48
|
+
else if (SOURCE_EXTS.some((e) => entry.name.endsWith(e)))
|
|
49
|
+
out.add(childRel);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return out;
|
|
53
|
+
}
|
|
54
|
+
/** The relative import specifiers a source file names (static imports + re-exports). */
|
|
55
|
+
export function relativeImportsOf(absPath) {
|
|
56
|
+
let src;
|
|
57
|
+
try {
|
|
58
|
+
src = readFileSync(absPath, "utf8");
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return [];
|
|
62
|
+
}
|
|
63
|
+
const out = [];
|
|
64
|
+
for (const m of src.matchAll(/(?:^|\n)\s*(?:import|export)[\s\S]{0,400}?from\s*["'](\.[^"']*)["']/g))
|
|
65
|
+
out.push(m[1]);
|
|
66
|
+
for (const m of src.matchAll(/\bimport\s*\(\s*["'](\.[^"']*)["']\s*\)/g))
|
|
67
|
+
out.push(m[1]);
|
|
68
|
+
return out;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Resolve a relative specifier against the candidate set. TypeScript ESM writes
|
|
72
|
+
* `./x.js` for `./x.ts`, so the `.js` → `.ts`/`.tsx` rewrite is the common case.
|
|
73
|
+
*/
|
|
74
|
+
export function resolveRelativeImport(fromFile, spec, candidates) {
|
|
75
|
+
const base = posixJoin(dirname(fromFile.split("/").join(sep)), spec);
|
|
76
|
+
const stem = base.replace(/\.(js|jsx|mjs|cjs)$/, "");
|
|
77
|
+
for (const cand of [
|
|
78
|
+
base,
|
|
79
|
+
...SOURCE_EXTS.map((e) => stem + e),
|
|
80
|
+
...SOURCE_EXTS.map((e) => `${stem}/index${e}`),
|
|
81
|
+
])
|
|
82
|
+
if (candidates.has(cand))
|
|
83
|
+
return cand;
|
|
84
|
+
return undefined;
|
|
85
|
+
}
|
|
86
|
+
/** Join and normalize a "/"-separated path, resolving `.` and `..` segments. */
|
|
87
|
+
function posixJoin(dir, spec) {
|
|
88
|
+
const parts = `${dir.split(sep).join("/")}/${spec}`.split("/");
|
|
89
|
+
const out = [];
|
|
90
|
+
for (const part of parts) {
|
|
91
|
+
if (part === "" || part === ".")
|
|
92
|
+
continue;
|
|
93
|
+
if (part === "..")
|
|
94
|
+
out.pop();
|
|
95
|
+
else
|
|
96
|
+
out.push(part);
|
|
97
|
+
}
|
|
98
|
+
return out.join("/");
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* The companion closure of `seeds` under `roots`: the seeds themselves plus
|
|
102
|
+
* every source file under `roots` that reaches one transitively through a
|
|
103
|
+
* relative import, to a fixed point.
|
|
104
|
+
*
|
|
105
|
+
* This is the shape both consumers need, and the reason the walk is shared
|
|
106
|
+
* rather than copied. `paidModuleTemplateExclusions()` seeds it with every
|
|
107
|
+
* paid module's `ownedFiles` to get the files a keyless starter must not
|
|
108
|
+
* carry; `tools/lint-slice-registration.ts` seeds it with the same set to
|
|
109
|
+
* derive, by subtraction, the files a scaffold ships UNCONDITIONALLY.
|
|
110
|
+
*
|
|
111
|
+
* Never a filename-stem rule (#5182 D7), which misses eleven files and
|
|
112
|
+
* over-marks three.
|
|
113
|
+
*
|
|
114
|
+
* @param repoRoot absolute path to the tree being walked.
|
|
115
|
+
* @param roots repo-relative roots the walk is confined to.
|
|
116
|
+
* @param seeds repo-relative, "/"-separated files the closure starts from.
|
|
117
|
+
*/
|
|
118
|
+
export function importClosure(repoRoot, roots, seeds) {
|
|
119
|
+
const closed = new Set(seeds);
|
|
120
|
+
const candidates = listFilesUnder(repoRoot, [...roots]);
|
|
121
|
+
for (;;) {
|
|
122
|
+
let grew = false;
|
|
123
|
+
for (const file of candidates) {
|
|
124
|
+
if (closed.has(file))
|
|
125
|
+
continue;
|
|
126
|
+
const imports = relativeImportsOf(join(repoRoot, file));
|
|
127
|
+
for (const spec of imports) {
|
|
128
|
+
const target = resolveRelativeImport(file, spec, candidates);
|
|
129
|
+
if (target !== undefined && closed.has(target)) {
|
|
130
|
+
closed.add(file);
|
|
131
|
+
grew = true;
|
|
132
|
+
break;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
if (!grew)
|
|
137
|
+
break;
|
|
138
|
+
}
|
|
139
|
+
return closed;
|
|
140
|
+
}
|
|
@@ -18,7 +18,12 @@
|
|
|
18
18
|
* gate (K1's regression floor).
|
|
19
19
|
*/
|
|
20
20
|
import type { ModuleName } from "../parse-args.js";
|
|
21
|
-
|
|
21
|
+
/**
|
|
22
|
+
* Where a refused run sends the buyer. `/pricing`, not `/pro`: there is no
|
|
23
|
+
* `/pro` route and there will not be one (#6439, operator decision OD-2) —
|
|
24
|
+
* pricing is where every level and the commerce add-on are actually listed.
|
|
25
|
+
*/
|
|
26
|
+
export declare const CONVERSION_HINT_URL = "https://ailaunchkit.ai/pricing";
|
|
22
27
|
/**
|
|
23
28
|
* Thrown for both honest-denial states (no key, and an invalid/lapsed key).
|
|
24
29
|
* The CLI does not distinguish them in its exit code — both are "this run
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { FetchModuleError, fetchModule } from "./fetch-module.js";
|
|
2
|
-
|
|
2
|
+
/**
|
|
3
|
+
* Where a refused run sends the buyer. `/pricing`, not `/pro`: there is no
|
|
4
|
+
* `/pro` route and there will not be one (#6439, operator decision OD-2) —
|
|
5
|
+
* pricing is where every level and the commerce add-on are actually listed.
|
|
6
|
+
*/
|
|
7
|
+
export const CONVERSION_HINT_URL = "https://ailaunchkit.ai/pricing";
|
|
3
8
|
/**
|
|
4
9
|
* Thrown for both honest-denial states (no key, and an invalid/lapsed key).
|
|
5
10
|
* The CLI does not distinguish them in its exit code — both are "this run
|
package/dist/lib/pro-callout.js
CHANGED
|
@@ -15,6 +15,6 @@ export function proCallout() {
|
|
|
15
15
|
"your business, generates a vertical-aware page plan, configures",
|
|
16
16
|
"Stripe / auth / lead routing / analytics, and sets up your",
|
|
17
17
|
"GitHub→Vercel deploy — all in one orchestrated flow. Or invoke the",
|
|
18
|
-
"free scaffolders one at a time → ailaunchkit.ai/
|
|
18
|
+
"free scaffolders one at a time → ailaunchkit.ai/pricing",
|
|
19
19
|
].join("\n");
|
|
20
20
|
}
|
|
@@ -397,4 +397,5 @@ export declare function normalizeModules(modules: string[]): ModuleName[];
|
|
|
397
397
|
* whole invariant.
|
|
398
398
|
*/
|
|
399
399
|
export declare function coOwnedModuleDestinations(): ReadonlySet<string>;
|
|
400
|
+
export declare const EXCLUDE_TEMPLATE_DIRS: readonly string[];
|
|
400
401
|
export declare function paidModuleTemplateExclusions(snapshotRoots: readonly string[], repoRoot: string): string[];
|