create-ailk 0.27.0 → 0.28.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 +84 -7
- package/dist/add-module-core.js +2 -1
- package/dist/add-module.d.ts +2 -1
- package/dist/add-module.js +9 -4
- package/dist/add-route.js +46 -19
- package/dist/body-heading.d.ts +56 -0
- package/dist/body-heading.js +394 -0
- package/dist/cli.js +28 -1
- package/dist/content-payloads.js +2 -2
- package/dist/derive-architecture.js +8 -2
- package/dist/index.d.ts +2 -1
- package/dist/index.js +4 -1
- package/dist/lib/auth-secret-file.d.ts +6 -2
- package/dist/lib/auth-secret-file.js +46 -20
- package/dist/lib/chrome-readers.d.ts +21 -5
- package/dist/lib/chrome-readers.js +128 -20
- package/dist/lib/declared-env.d.ts +6 -0
- package/dist/lib/declared-env.js +2 -0
- package/dist/lib/env-catalog.js +20 -0
- package/dist/lib/import-graph.d.ts +16 -0
- package/dist/lib/import-graph.js +53 -0
- package/dist/lib/site-modules.d.ts +8 -0
- package/dist/lib/site-modules.js +34 -0
- package/dist/module-architecture.js +23 -14
- package/dist/paid-sections.d.ts +17 -0
- package/dist/paid-sections.js +39 -0
- package/dist/programmatic.d.ts +16 -0
- package/dist/programmatic.js +73 -4
- package/dist/remove-module.d.ts +98 -0
- package/dist/remove-module.js +620 -0
- package/dist/seed-flows.d.ts +2 -2
- package/dist/seed-flows.js +16 -9
- package/dist/site-roster.js +4 -1
- package/dist/starter-grid.d.ts +26 -0
- package/dist/starter-grid.js +34 -0
- package/dist/surfaces.d.ts +26 -0
- package/dist/surfaces.js +105 -9
- package/dist/sync-routes.d.ts +7 -0
- package/dist/sync-routes.js +53 -6
- package/dist/template-pages.d.ts +36 -0
- package/dist/template-pages.js +129 -0
- package/dist/template-record.d.ts +13 -4
- package/dist/template-record.js +8 -4
- package/dist/topology.d.ts +2 -1
- package/dist/topology.js +4 -2
- package/dist/update.d.ts +34 -2
- package/dist/update.js +395 -48
- package/package.json +3 -3
- package/release-scope.json +2 -1
- package/site-templates/aliases/hub.TEMPLATE-MANIFEST.json +115 -0
- package/templates/.env.example +5 -2
- package/templates/apps/api/.env.example +9 -5
- package/templates/apps/api/CLAUDE.md +14 -9
- package/templates/apps/api/src/__tests__/vercel-handler.test.ts +37 -0
- package/templates/apps/api/src/vercel-handler.ts +8 -1
- package/templates/apps/mcp/CLAUDE.md +18 -10
- package/templates/apps/web/.env.example +25 -11
- package/templates/apps/web/CLAUDE.md +45 -4
- package/templates/apps/web/__tests__/setup.ts +7 -0
- package/templates/apps/web/app/.well-known/mcp.json/route.ts +7 -7
- package/templates/apps/web/app/[locale]/(authed)/account/artifacts/[pieceId]/versions/[version]/file/route.ts +61 -2
- package/templates/apps/web/app/[locale]/(authed)/account/artifacts/__tests__/file-route.test.ts +81 -0
- package/templates/apps/web/app/[locale]/(authed)/account/connect/__tests__/page.test.tsx +197 -0
- package/templates/apps/web/app/[locale]/(authed)/account/connect/page.tsx +152 -0
- package/templates/apps/web/app/[locale]/about/__tests__/about-routes.test.tsx +2 -2
- package/templates/apps/web/app/[locale]/careers/[slug]/[action]/page.tsx +76 -21
- package/templates/apps/web/app/[locale]/careers/[slug]/apply.actions.ts +46 -16
- package/templates/apps/web/app/[locale]/careers/[slug]/page.tsx +20 -3
- package/templates/apps/web/app/[locale]/careers/__tests__/apply.actions.test.ts +180 -2
- package/templates/apps/web/app/[locale]/careers/__tests__/careers-set.test.tsx +6 -2
- package/templates/apps/web/app/[locale]/careers/__tests__/job-apply-page.test.tsx +122 -0
- package/templates/apps/web/app/[locale]/careers/__tests__/page-renderer-migration.test.tsx +1 -1
- package/templates/apps/web/app/[locale]/case-studies/[slug]/page.tsx +20 -3
- package/templates/apps/web/app/[locale]/case-studies/__tests__/hub-children.test.tsx +65 -0
- package/templates/apps/web/app/[locale]/case-studies/__tests__/page-renderer-migration.test.tsx +6 -2
- package/templates/apps/web/app/[locale]/case-studies/page.tsx +23 -11
- package/templates/apps/web/app/[locale]/checkout/__tests__/thank-you-account.test.tsx +11 -1
- package/templates/apps/web/app/[locale]/clients/__tests__/page-renderer-migration.test.tsx +1 -1
- package/templates/apps/web/app/[locale]/consent.actions.ts +44 -6
- package/templates/apps/web/app/[locale]/contact/__tests__/ConversationalIntakeWrapper.test.tsx +4 -4
- package/templates/apps/web/app/[locale]/contact/__tests__/contact.actions.test.ts +269 -42
- package/templates/apps/web/app/[locale]/contact/contact.actions.ts +88 -30
- package/templates/apps/web/app/[locale]/courses/[slug]/page.tsx +20 -3
- package/templates/apps/web/app/[locale]/courses/__tests__/hub-children.test.tsx +32 -0
- package/templates/apps/web/app/[locale]/courses/__tests__/page-renderer-migration.test.tsx +6 -2
- package/templates/apps/web/app/[locale]/courses/page.tsx +22 -6
- package/templates/apps/web/app/[locale]/events/[slug]/page.tsx +15 -2
- package/templates/apps/web/app/[locale]/events/__tests__/hub-children.test.tsx +32 -0
- package/templates/apps/web/app/[locale]/events/__tests__/page-renderer-migration.test.tsx +8 -2
- package/templates/apps/web/app/[locale]/events/page.tsx +23 -7
- package/templates/apps/web/app/[locale]/features/__tests__/hub-children.test.tsx +32 -0
- package/templates/apps/web/app/[locale]/features/page.tsx +23 -25
- package/templates/apps/web/app/[locale]/flows/[slug]/__tests__/flow.actions.test.ts +95 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/__tests__/save.actions.test.ts +193 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/email-moment.ts +92 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/flow.actions.ts +10 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/results/[payload]/ResultsClient.tsx +513 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/results/[payload]/ResultsEmailStep.tsx +122 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/results/[payload]/__tests__/ResultsClient.no-commerce.test.tsx +195 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/results/[payload]/__tests__/landing.test.tsx +293 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/results/[payload]/__tests__/page.test.tsx +397 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/results/[payload]/checkout-seam.ts +74 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/results/[payload]/page.tsx +264 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/save.actions.ts +75 -0
- package/templates/apps/web/app/[locale]/for/__tests__/hub-children.test.tsx +32 -0
- package/templates/apps/web/app/[locale]/for/__tests__/page-renderer-migration.test.tsx +5 -1
- package/templates/apps/web/app/[locale]/for/page.tsx +23 -25
- package/templates/apps/web/app/[locale]/how-to/[slug]/page.tsx +20 -3
- 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 +25 -4
- package/templates/apps/web/app/[locale]/integrations/__tests__/hub-children.test.tsx +38 -0
- package/templates/apps/web/app/[locale]/integrations/__tests__/page-renderer-migration.test.tsx +8 -2
- package/templates/apps/web/app/[locale]/integrations/page.tsx +23 -11
- package/templates/apps/web/app/[locale]/layout.tsx +157 -139
- package/templates/apps/web/app/[locale]/page.tsx +51 -3
- package/templates/apps/web/app/[locale]/partners/[slug]/page.tsx +16 -3
- package/templates/apps/web/app/[locale]/partners/__tests__/hub-children.test.tsx +32 -0
- package/templates/apps/web/app/[locale]/partners/__tests__/page-renderer-migration.test.tsx +6 -2
- package/templates/apps/web/app/[locale]/partners/page.tsx +22 -6
- package/templates/apps/web/app/[locale]/portfolio/__tests__/hub-children.test.tsx +38 -0
- package/templates/apps/web/app/[locale]/portfolio/page.tsx +25 -24
- package/templates/apps/web/app/[locale]/pricing/[slug]/__tests__/page.test.tsx +321 -0
- package/templates/apps/web/app/[locale]/pricing/[slug]/page.tsx +87 -0
- package/templates/apps/web/app/[locale]/pricing/__tests__/offerings.test.tsx +3 -0
- package/templates/apps/web/app/[locale]/pricing/__tests__/pricing-pages.test.tsx +215 -0
- package/templates/apps/web/app/[locale]/pricing/page.tsx +56 -341
- package/templates/apps/web/app/[locale]/products/[slug]/page.tsx +21 -4
- package/templates/apps/web/app/[locale]/products/__tests__/hub-children.test.tsx +32 -0
- package/templates/apps/web/app/[locale]/products/__tests__/page-renderer-migration.test.tsx +8 -2
- package/templates/apps/web/app/[locale]/products/page.tsx +22 -6
- package/templates/apps/web/app/[locale]/projects/__tests__/hub-children.test.tsx +32 -0
- package/templates/apps/web/app/[locale]/projects/__tests__/page-renderer-migration.test.tsx +4 -0
- package/templates/apps/web/app/[locale]/projects/page.tsx +18 -11
- package/templates/apps/web/app/[locale]/resources/[slug]/page.tsx +25 -4
- package/templates/apps/web/app/[locale]/resources/__tests__/hub-children.test.tsx +38 -0
- package/templates/apps/web/app/[locale]/resources/__tests__/page-renderer-migration.test.tsx +6 -2
- package/templates/apps/web/app/[locale]/resources/page.tsx +20 -10
- package/templates/apps/web/app/[locale]/services/[slug]/[child]/page.tsx +68 -0
- package/templates/apps/web/app/[locale]/services/[slug]/page.tsx +64 -9
- package/templates/apps/web/app/[locale]/services/__tests__/hub-children.test.tsx +158 -0
- package/templates/apps/web/app/[locale]/services/__tests__/page-renderer-migration.test.tsx +12 -2
- package/templates/apps/web/app/[locale]/services/__tests__/service-detail-sections.test.tsx +224 -0
- package/templates/apps/web/app/[locale]/services/__tests__/service-families.test.tsx +368 -0
- package/templates/apps/web/app/[locale]/services/page.tsx +45 -19
- package/templates/apps/web/app/[locale]/software/__tests__/page-renderer-migration.test.tsx +1 -1
- package/templates/apps/web/app/[locale]/team/__tests__/hub-children.test.tsx +32 -0
- package/templates/apps/web/app/[locale]/team/page.tsx +25 -24
- package/templates/apps/web/app/[locale]/tech-articles/[slug]/page.tsx +24 -3
- package/templates/apps/web/app/[locale]/tech-articles/__tests__/page-renderer-migration.test.tsx +1 -1
- package/templates/apps/web/app/[locale]/templates/[slug]/__tests__/page.test.tsx +203 -0
- package/templates/apps/web/app/[locale]/templates/[slug]/page.tsx +81 -0
- package/templates/apps/web/app/[locale]/templates/__tests__/page.test.tsx +237 -0
- package/templates/apps/web/app/[locale]/templates/page.tsx +108 -0
- package/templates/apps/web/app/[locale]/testimonials/__tests__/page-renderer-migration.test.tsx +1 -1
- package/templates/apps/web/app/[locale]/whitepapers/[slug]/page.tsx +24 -3
- package/templates/apps/web/app/[locale]/whitepapers/__tests__/page-renderer-migration.test.tsx +1 -1
- package/templates/apps/web/app/api/auth/hub/authorize/__tests__/route.test.ts +204 -2
- package/templates/apps/web/app/api/auth/hub/authorize/route.ts +151 -33
- package/templates/apps/web/app/api/offerings/checkout/[lookupKey]/__tests__/route.test.ts +233 -7
- package/templates/apps/web/app/api/offerings/checkout/[lookupKey]/route.ts +92 -41
- package/templates/apps/web/app/api/offerings/checkout/__tests__/route.test.ts +77 -39
- package/templates/apps/web/app/llms.txt/route.ts +41 -3
- package/templates/apps/web/app/robots.txt/route.ts +5 -1
- package/templates/apps/web/app/sitemap.xml/route.ts +45 -3
- package/templates/apps/web/auth.ts +102 -50
- package/templates/apps/web/components/signed-in-nav.tsx +8 -1
- package/templates/apps/web/lib/__tests__/bot-check.test.ts +254 -0
- package/templates/apps/web/lib/__tests__/consent-visitor.test.ts +212 -13
- package/templates/apps/web/lib/__tests__/deck-page.test.ts +13 -1
- package/templates/apps/web/lib/__tests__/docs-index.test.ts +93 -0
- package/templates/apps/web/lib/__tests__/docs-path.test.ts +168 -0
- package/templates/apps/web/lib/__tests__/hub-children.fixtures.ts +279 -0
- package/templates/apps/web/lib/__tests__/nav-label-keys.test.ts +138 -0
- package/templates/apps/web/lib/__tests__/newsletter.actions.test.ts +178 -2
- package/templates/apps/web/lib/__tests__/offerings-pricing.test.ts +183 -0
- package/templates/apps/web/lib/__tests__/page-chrome.test.ts +412 -0
- package/templates/apps/web/lib/__tests__/pricing-page.test.ts +142 -0
- package/templates/apps/web/lib/__tests__/relay.test.ts +202 -10
- package/templates/apps/web/lib/__tests__/route-family.test.ts +57 -0
- package/templates/apps/web/lib/__tests__/service-listing.test.ts +111 -0
- package/templates/apps/web/lib/__tests__/services-path.test.ts +96 -0
- package/templates/apps/web/lib/__tests__/site-header.test.ts +151 -0
- package/templates/apps/web/lib/__tests__/structured-data.test.tsx +148 -6
- package/templates/apps/web/lib/__tests__/telemetry-scrub.test.ts +84 -0
- package/templates/apps/web/lib/__tests__/template-listing.test.ts +158 -0
- package/templates/apps/web/lib/auth-secret.ts +57 -0
- package/templates/apps/web/lib/bot-check.ts +138 -0
- package/templates/apps/web/lib/consent-visitor.ts +81 -7
- package/templates/apps/web/lib/deck-page.ts +6 -3
- package/templates/apps/web/lib/docs-index.ts +100 -0
- package/templates/apps/web/lib/docs-path.ts +94 -0
- package/templates/apps/web/lib/hub-children.tsx +318 -0
- package/templates/apps/web/lib/modules.generated.ts +9 -0
- package/templates/apps/web/lib/nav-label-check.ts +61 -0
- package/templates/apps/web/lib/nav-label-keys.ts +78 -0
- package/templates/apps/web/lib/newsletter.actions.ts +31 -6
- package/templates/apps/web/lib/offerings-pricing.ts +135 -6
- package/templates/apps/web/lib/page-chrome.ts +367 -0
- package/templates/apps/web/lib/posting-title.ts +26 -4
- package/templates/apps/web/lib/pricing-page.ts +430 -0
- package/templates/apps/web/lib/relay.ts +31 -106
- package/templates/apps/web/lib/route-family.ts +69 -0
- package/templates/apps/web/lib/service-listing.ts +89 -0
- package/templates/apps/web/lib/services-path.ts +97 -0
- package/templates/apps/web/lib/site-header.ts +94 -0
- package/templates/apps/web/lib/telemetry-scrub.ts +68 -3
- package/templates/apps/web/lib/template-listing.ts +169 -0
- package/templates/apps/web/messages/en.json +86 -30
- package/templates/apps/web/middleware.ts +171 -11
- package/templates/apps/web/next.config.mjs +211 -2
- package/templates/apps/web/package.json +1 -1
- package/templates/apps/web/scripts/assert-content-bundled.ts +28 -6
- package/templates/apps/web/scripts/check-nav-labels.ts +39 -0
- package/templates/apps/web/sentry.server.config.ts +30 -2
- package/templates/apps/web/src/lib/__tests__/rate-limit.test.ts +67 -9
- package/templates/apps/web/src/lib/rate-limit.ts +68 -27
- package/templates/apps/web/src/lib/routes.ts +15 -1
- package/templates/tools/declared-env.ts +7 -0
- package/versions.json +48 -48
package/dist/programmatic.js
CHANGED
|
@@ -39,6 +39,7 @@ import { classifyModules, isAddition } from "./lib/module-tier.js";
|
|
|
39
39
|
import { normalizeModules } from "./module-architecture.js";
|
|
40
40
|
import { writePaidSections } from "./paid-sections.js";
|
|
41
41
|
import { RECOGNIZED_SHAPES, RESERVED_SHAPES, } from "./parse-args.js";
|
|
42
|
+
import { RemoveModuleRefusedError, removeModuleFromScaffold, } from "./remove-module.js";
|
|
42
43
|
import { writeSpokeFlowsReadme } from "./seed-flows.js";
|
|
43
44
|
import { SITE_CHROME_PATH, renderSiteChrome, resolveSiteChrome, } from "./site-chrome.js";
|
|
44
45
|
import { SITE_FONTS_PATH, renderSiteFonts } from "./site-fonts.js";
|
|
@@ -47,7 +48,7 @@ import { SITE_ROSTER_PATH, planHomeRecord, planSiteManifestDesign, readSiteRoste
|
|
|
47
48
|
import { SPOKE_CHECKOUT_TEMPLATE_PATHS, dropSpokeCheckoutDependency, spokeCheckoutSite, spokeEnvRowOptions, writeSpokeCheckoutSlice, } from "./spoke-checkout.js";
|
|
48
49
|
import { GATEABLE_SURFACES, MODULE_SURFACES, NAV_CONFIG_PATH, excludedRoutePaths, isUnservedSurfaceContent, renderNavConfig, resolveSurfaces, } from "./surfaces.js";
|
|
49
50
|
import { syncRoutes } from "./sync-routes.js";
|
|
50
|
-
import { BASE_LAYER_DIR, SHAPE_STARTERS, TEMPLATE_MANIFESTS, TemplateError, mergeRoster, resolveTemplate, resolveTemplateLineage, rosterDeclares, templateDelivery, templateTreeDir, } from "./template-manifest.js";
|
|
51
|
+
import { BASE_LAYER_DIR, SHAPE_STARTERS, isOwnTree, shippedManifestPath, TEMPLATE_MANIFESTS, TemplateError, mergeRoster, resolveTemplate, resolveTemplateLineage, rosterDeclares, templateDelivery, templateTreeDir, } from "./template-manifest.js";
|
|
51
52
|
import { TEMPLATE_RECORD_PATH, isRecordable, planTemplateRecord, serializeTemplateRecord, sha256Hex, } from "./template-record.js";
|
|
52
53
|
import { SPOKE_ONLY_FILES, TopologyError, applySpokeTransforms, isSpokeExcluded, normalizeHubSignInUrl, normalizeHubUrl, readSiteTopology, spokeExclusions, spokeDestination, spokeModuleRefusal, spokeModules, writeHubOriginEnv, writeHubSignInEnv, } from "./topology.js";
|
|
53
54
|
import { validateTarget } from "./validate.js";
|
|
@@ -134,7 +135,9 @@ function resolveShapeTemplate(shape) {
|
|
|
134
135
|
...Object.values(TEMPLATE_MANIFESTS),
|
|
135
136
|
...Object.values(SHAPE_STARTERS),
|
|
136
137
|
].filter((manifest) => manifest.shape === shape);
|
|
137
|
-
|
|
138
|
+
// #10040 D8 — a shape's Free starter is its public site: an alias with no
|
|
139
|
+
// `marketing` in `requires` (the hub starter) is never a shape's starter.
|
|
140
|
+
const free = ofShape.filter((manifest) => templateDelivery(manifest) === "free" && manifest.requires.includes("marketing"));
|
|
138
141
|
if (free.length === 0) {
|
|
139
142
|
const names = ofShape.map((manifest) => manifest.name).join(", ");
|
|
140
143
|
throw new TemplateError(`shape "${shape}" has no Free starter yet — its page list lands with #6743. Templates built on this shape: ${names || "none"}.`);
|
|
@@ -373,9 +376,12 @@ export async function scaffold(opts) {
|
|
|
373
376
|
if (opts.template !== undefined) {
|
|
374
377
|
// Alias run — untouched (NFR-4): the union line and its
|
|
375
378
|
// resolvePaidModules({ …, templateName }) call stay exactly as they were.
|
|
379
|
+
// #10040 D8 — the template's `requires` is unioned in, so the only
|
|
380
|
+
// alias a `["marketing"]` default changed was one that deliberately
|
|
381
|
+
// lacks it (the hub starter); every existing alias lists `marketing`.
|
|
376
382
|
modules = normalizeModules([
|
|
377
383
|
...(template?.requires ?? []),
|
|
378
|
-
...(opts.modules ?? [
|
|
384
|
+
...(opts.modules ?? []),
|
|
379
385
|
]);
|
|
380
386
|
const { paid } = classifyModules(modules);
|
|
381
387
|
bundles = await resolvePaidModules({
|
|
@@ -656,7 +662,11 @@ export async function scaffold(opts) {
|
|
|
656
662
|
sourceRoot,
|
|
657
663
|
targetDir: result.targetDir,
|
|
658
664
|
name: template.name,
|
|
659
|
-
|
|
665
|
+
// #10040 D8 — a treeless alias installs its SHAPE's tree, whose
|
|
666
|
+
// ailk-template.json declares the shape starter's requires.
|
|
667
|
+
templateRequires: isOwnTree(template.name)
|
|
668
|
+
? template.requires
|
|
669
|
+
: (SHAPE_STARTERS[template.shape]?.requires ?? template.requires),
|
|
660
670
|
templateExtends: template.extends,
|
|
661
671
|
versions,
|
|
662
672
|
markers,
|
|
@@ -698,6 +708,13 @@ export async function scaffold(opts) {
|
|
|
698
708
|
// #6939 — the scaffold's DESIGN.md is the design it wears, not the one
|
|
699
709
|
// its template layer shipped; the site's own header lines are kept.
|
|
700
710
|
writeFileSync(join(result.targetDir, "DESIGN.md"), planDesignMd(resolvedDesign.dir, result.targetDir));
|
|
711
|
+
// #10040 D8 — a treeless alias (`ownTree: false`) ships no DESIGN.md of
|
|
712
|
+
// its own, so the kept line would still name the overlay's `_base`;
|
|
713
|
+
// the scaffold's provenance is the alias.
|
|
714
|
+
if (template !== undefined && !isOwnTree(template.name)) {
|
|
715
|
+
const designPath = join(result.targetDir, "DESIGN.md");
|
|
716
|
+
writeFileSync(designPath, readFileSync(designPath, "utf8").replace(/^([ \t]*)Source template:.*$/m, (_m, indent) => `${indent}Source template: ${template.name}`));
|
|
717
|
+
}
|
|
701
718
|
// #7720 D4.1 — the faces the design sources, beside site-chrome.ts. A
|
|
702
719
|
// design that sources none renders the overlay's committed default, so
|
|
703
720
|
// the file is left as the template tree wrote it.
|
|
@@ -828,6 +845,11 @@ export async function scaffold(opts) {
|
|
|
828
845
|
// plain alias or `--modules`-keep run, and is never inferred from `modules`.
|
|
829
846
|
// A scaffold with no manifest (the bare overlay, `saas-product`) writes none.
|
|
830
847
|
if (template !== undefined) {
|
|
848
|
+
// #10040 D8 — a treeless alias installed its SHAPE's tree, whose record
|
|
849
|
+
// names the shape; the site's roster of record is the alias's own.
|
|
850
|
+
if (!isOwnTree(template.name)) {
|
|
851
|
+
writeFileSync(join(result.targetDir, SITE_ROSTER_PATH), readFileSync(join(SITE_TEMPLATES_DIR, shippedManifestPath(template.name)), "utf8"));
|
|
852
|
+
}
|
|
831
853
|
const roster = readSiteRoster(result.targetDir);
|
|
832
854
|
if (roster !== undefined) {
|
|
833
855
|
writeFileSync(join(result.targetDir, roster.path), planSiteManifest({
|
|
@@ -858,6 +880,23 @@ export async function scaffold(opts) {
|
|
|
858
880
|
// #7536 D3 — the registry follows `apps/web/package.json`, which a module
|
|
859
881
|
// bundle's `patches` (and the template layer) just finished editing.
|
|
860
882
|
writePaidSections(result.targetDir);
|
|
883
|
+
// #10040 D8 — a template whose resolved module set lacks `marketing` (the
|
|
884
|
+
// hub starter) is the same scaffold with the public tree removed: one code
|
|
885
|
+
// path, the command's. Runs after the record and the manifest are written,
|
|
886
|
+
// so the removed paths retire exactly as they would on a live site.
|
|
887
|
+
if (template !== undefined && !modules.includes("marketing")) {
|
|
888
|
+
removeModuleFromScaffold({
|
|
889
|
+
targetDir: result.targetDir,
|
|
890
|
+
moduleName: "marketing",
|
|
891
|
+
force: true,
|
|
892
|
+
fromScaffold: true,
|
|
893
|
+
templatesDir: TEMPLATES_DIR,
|
|
894
|
+
siteTemplatesDir: SITE_TEMPLATES_DIR,
|
|
895
|
+
versions,
|
|
896
|
+
markers,
|
|
897
|
+
version: markers["CREATE_AILK_VERSION"] ?? "",
|
|
898
|
+
});
|
|
899
|
+
}
|
|
861
900
|
// #7874 D9 — a spoke's rows again, now the module bundles and the template
|
|
862
901
|
// layer are in the scan; it appends only what those layers added. A
|
|
863
902
|
// commerce spoke also declares what the checkout package reads (#7838 D9).
|
|
@@ -1234,6 +1273,36 @@ export async function addModule(opts) {
|
|
|
1234
1273
|
siteTemplatesDir: SITE_TEMPLATES_DIR,
|
|
1235
1274
|
});
|
|
1236
1275
|
}
|
|
1276
|
+
/**
|
|
1277
|
+
* Take a module's public pages off an already-scaffolded site in place
|
|
1278
|
+
* (`create-ailk remove-module`, #10040) — the thin package-rooted wrapper
|
|
1279
|
+
* around `remove-module.ts`'s `removeModuleFromScaffold`, the `addModule`
|
|
1280
|
+
* split. Every refusal is the core's and throws before the first write.
|
|
1281
|
+
*/
|
|
1282
|
+
export function removeModule(opts) {
|
|
1283
|
+
const targetAbs = resolve(opts.targetDir);
|
|
1284
|
+
if (!existsSync(targetAbs)) {
|
|
1285
|
+
throw new Error(`remove-module target does not exist: ${targetAbs}. Point remove-module at an already-scaffolded repo.`);
|
|
1286
|
+
}
|
|
1287
|
+
if (!statSync(targetAbs).isDirectory()) {
|
|
1288
|
+
throw new Error(`remove-module target is not a directory: ${targetAbs}`);
|
|
1289
|
+
}
|
|
1290
|
+
const markers = buildScaffoldMarkers(basename(targetAbs));
|
|
1291
|
+
const version = markers["CREATE_AILK_VERSION"];
|
|
1292
|
+
if (version === undefined || version === "") {
|
|
1293
|
+
throw new RemoveModuleRefusedError("CREATE_AILK_VERSION is unset: a retired record row needs the running version.");
|
|
1294
|
+
}
|
|
1295
|
+
return removeModuleFromScaffold({
|
|
1296
|
+
targetDir: targetAbs,
|
|
1297
|
+
moduleName: opts.moduleName,
|
|
1298
|
+
...(opts.force !== undefined ? { force: opts.force } : {}),
|
|
1299
|
+
templatesDir: TEMPLATES_DIR,
|
|
1300
|
+
siteTemplatesDir: SITE_TEMPLATES_DIR,
|
|
1301
|
+
versions: readVersionMap(),
|
|
1302
|
+
markers,
|
|
1303
|
+
version,
|
|
1304
|
+
});
|
|
1305
|
+
}
|
|
1237
1306
|
/** Re-exported so the CLI can name the file it wrote without duplicating it. */
|
|
1238
1307
|
export { CATALOG_TARGET_PATH };
|
|
1239
1308
|
/**
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import type { InstallReportRow } from "./lib/extract-module-bundle.js";
|
|
2
|
+
import { type ModuleName } from "./parse-args.js";
|
|
3
|
+
import type { MarkerMap, WorkspaceVersionMap } from "./substitute.js";
|
|
4
|
+
/** The modules `remove-module` takes (decision 6). */
|
|
5
|
+
export declare const REMOVABLE_MODULES: readonly ModuleName[];
|
|
6
|
+
/**
|
|
7
|
+
* The `content/<locale>/<type>/` directories a site keeps when it drops
|
|
8
|
+
* `marketing`: the seeds of the kept legal pages (`HUB_KEPT_ROUTES`).
|
|
9
|
+
*/
|
|
10
|
+
export declare const HUB_KEPT_CONTENT_TYPES: readonly string[];
|
|
11
|
+
/** A refusal the CLI exits 2 on — the same shape `add-module` throws. */
|
|
12
|
+
export declare class RemoveModuleRefusedError extends Error {
|
|
13
|
+
readonly exitCode = 2;
|
|
14
|
+
constructor(message: string);
|
|
15
|
+
}
|
|
16
|
+
export interface RemoveModuleOptions {
|
|
17
|
+
/** The already-scaffolded site. */
|
|
18
|
+
targetDir: string;
|
|
19
|
+
moduleName: ModuleName;
|
|
20
|
+
/** Delete the site's own edits too (decision 5). */
|
|
21
|
+
force?: boolean;
|
|
22
|
+
/** The package's `templates/` snapshot — the record's template copies and the overlay seeds. */
|
|
23
|
+
templatesDir: string;
|
|
24
|
+
/** The package's `site-templates/` dir — the base layer and the template tree's seeds. */
|
|
25
|
+
siteTemplatesDir: string;
|
|
26
|
+
/** Workspace version map, for rendering a template copy the way `copyTemplate` did. */
|
|
27
|
+
versions: WorkspaceVersionMap;
|
|
28
|
+
/** The scaffold's marker map (`buildScaffoldMarkers`). */
|
|
29
|
+
markers: MarkerMap;
|
|
30
|
+
/** The running create-ailk version — the `version` a new record row carries. */
|
|
31
|
+
version: string;
|
|
32
|
+
/**
|
|
33
|
+
* `scaffold()`'s own call (#10040 D8): the header already lacks the module
|
|
34
|
+
* because the resolved set never had it, so the carry check is skipped.
|
|
35
|
+
*/
|
|
36
|
+
fromScaffold?: boolean;
|
|
37
|
+
}
|
|
38
|
+
export interface RemoveModuleResult {
|
|
39
|
+
targetDir: string;
|
|
40
|
+
moduleName: ModuleName;
|
|
41
|
+
/** The module set `architecture.yaml` now declares. */
|
|
42
|
+
modules: ModuleName[];
|
|
43
|
+
/** Every path deleted, site-relative, sorted. */
|
|
44
|
+
removed: string[];
|
|
45
|
+
/** The deleted paths now carried as retired rows in the record (D1). */
|
|
46
|
+
retired: string[];
|
|
47
|
+
/** The site's own files the run deleted under `--force`. */
|
|
48
|
+
forced: string[];
|
|
49
|
+
/** Removal-set files kept because a kept file imports them, with the importer. */
|
|
50
|
+
keptImports: Array<{
|
|
51
|
+
path: string;
|
|
52
|
+
importedBy: string;
|
|
53
|
+
}>;
|
|
54
|
+
/** Config patches a removed module left in place, for the owner to reverse by hand (D7). */
|
|
55
|
+
review: Array<{
|
|
56
|
+
path: string;
|
|
57
|
+
reason: string;
|
|
58
|
+
}>;
|
|
59
|
+
/** Generated files rewritten (nav, flags, registries) or left for review (an edited nav). */
|
|
60
|
+
report: InstallReportRow[];
|
|
61
|
+
roster: {
|
|
62
|
+
state: "trimmed" | "unchanged" | "none";
|
|
63
|
+
dropped: string[];
|
|
64
|
+
path: string;
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/** The directories `remove-module marketing` removes: the public route tree and the non-legal seeds. */
|
|
68
|
+
export declare function marketingRemovalDirs(targetDir: string): string[];
|
|
69
|
+
/**
|
|
70
|
+
* The removal-set files a KEPT file imports — kept with their own imports,
|
|
71
|
+
* to a fixed point (#10040). `apps/web/app/[locale]/contact/` holds helpers
|
|
72
|
+
* the locale layout and `lib/in-page-magnet.ts` import beside its page;
|
|
73
|
+
* deleting them with the page breaks the kept tree's type-check. Only
|
|
74
|
+
* `apps/web` code is scanned; a kept file is any `.ts`/`.tsx` outside the
|
|
75
|
+
* removal set (node_modules, .next and dist excluded).
|
|
76
|
+
*/
|
|
77
|
+
export declare function importedByKept(targetDir: string, removal: string[]): Map<string, string>;
|
|
78
|
+
/** The paths a module's removal deletes, site-relative, only those on disk. */
|
|
79
|
+
export declare function removalSet(targetDir: string, moduleName: ModuleName): string[];
|
|
80
|
+
/**
|
|
81
|
+
* Removes one module from a scaffolded site. Every refusal is raised before
|
|
82
|
+
* the first write; the writes that follow (delete → record → architecture →
|
|
83
|
+
* manifest → generated files) are not atomic, but each is idempotent on its
|
|
84
|
+
* own inputs, so a run interrupted mid-way converges on the next invocation —
|
|
85
|
+
* `--force` is then needed only if the first run needed it.
|
|
86
|
+
*/
|
|
87
|
+
export declare function removeModuleFromScaffold(opts: RemoveModuleOptions): RemoveModuleResult;
|
|
88
|
+
/** The report `remove-module` prints. */
|
|
89
|
+
export declare function formatRemoveModuleReport(result: RemoveModuleResult): string;
|
|
90
|
+
export interface RemoveModuleArgs {
|
|
91
|
+
module: ModuleName | undefined;
|
|
92
|
+
target: string | undefined;
|
|
93
|
+
force: boolean;
|
|
94
|
+
help: boolean;
|
|
95
|
+
}
|
|
96
|
+
export declare const REMOVE_MODULE_HELP = "create-ailk remove-module \u2014 take a module's public pages off an existing site.\n\nUsage:\n create-ailk remove-module <module> [<target-dir>] [--force]\n\nArguments:\n <module> marketing or docs-blog. Nothing else can be removed.\n <target-dir> An already-scaffolded repo (contains\n architecture.yaml). Defaults to the current dir.\n\nOptions:\n --force Also delete files the site has edited or authored\n inside the module's pages. Without it, such files\n are listed and nothing is removed.\n --help, -h Print this message.\n\nDeletes the module's route directories and seed content, drops the module\nfrom .ailk-site-manifest.json and architecture.yaml, and records every removed\napp file as retired in .ailk-template-files.json, so create-ailk update and\nsync-routes never bring it back. A site without marketing redirects / to\n/account, serves robots.txt disallowing everything, sends noindex on every page\nand answers 404 at sitemap.xml and llms.txt. Removing marketing while docs-blog\nis installed is refused: remove docs-blog first.\n";
|
|
97
|
+
/** Parse the argv AFTER the `remove-module` word, the `parseAddModuleArgs` shape. */
|
|
98
|
+
export declare function parseRemoveModuleArgs(argv: string[]): RemoveModuleArgs;
|