@canonical/pragma-cli 0.32.0 → 0.34.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 +72 -0
- package/dist/pragma +0 -0
- package/package.json +19 -15
- package/pragma.conf.ts +664 -0
- package/src/bin.ts +15 -6
- package/src/capabilities/block.parity.test.ts +250 -0
- package/src/capabilities/capabilities/capabilities.render.ts +3 -2
- package/src/capabilities/capabilities/capabilities.test.ts +10 -1
- package/src/capabilities/capabilities/capabilities.verb.ts +32 -14
- package/src/capabilities/capabilities/catalog.ts +20 -8
- package/src/capabilities/capabilities/hints.ts +21 -36
- package/src/capabilities/capabilities/types.ts +2 -0
- package/src/capabilities/colophon/collectColophon.ts +34 -19
- package/src/capabilities/colophon/colophon.render.test.ts +31 -4
- package/src/capabilities/colophon/colophon.render.ts +13 -4
- package/src/capabilities/colophon/colophon.test.ts +3 -3
- package/src/capabilities/colophon/colophon.verb.ts +11 -4
- package/src/capabilities/colophon/markdownTerminal.ts +33 -14
- package/src/capabilities/colophon/types.ts +16 -7
- package/src/capabilities/config/collectConfigShow.test.ts +57 -0
- package/src/capabilities/config/collectConfigShow.ts +41 -4
- package/src/capabilities/config/fields.ts +10 -108
- package/src/capabilities/config/set.test.ts +6 -6
- package/src/capabilities/config/set.verb.ts +12 -8
- package/src/capabilities/config/show.render.test.ts +137 -0
- package/src/capabilities/config/show.render.ts +57 -16
- package/src/capabilities/config/show.verb.ts +9 -8
- package/src/capabilities/config/types.ts +8 -0
- package/src/capabilities/create/byteEquality.subprocess.test.ts +1 -1
- package/src/capabilities/create/byteEquality.test.ts +82 -101
- package/src/capabilities/create/compiledCreate.subprocess.test.ts +53 -16
- package/src/capabilities/create/constants.ts +75 -0
- package/src/capabilities/create/create.mcp.test.ts +2 -2
- package/src/capabilities/create/create.test.ts +192 -16
- package/src/capabilities/create/create.verb.ts +208 -79
- package/src/capabilities/create/index.ts +2 -10
- package/src/capabilities/create/pickGenerator.ts +34 -28
- package/src/capabilities/create/templates.embedded.generated.ts +4 -29
- package/src/capabilities/create/types.ts +10 -6
- package/src/capabilities/{standard/parity.test.ts → distribution.parity.test.ts} +24 -14
- package/src/capabilities/distribution.test.ts +120 -0
- package/src/capabilities/distribution.ts +59 -0
- package/src/capabilities/doctor/checks/checkConfigFile.ts +6 -5
- package/src/capabilities/doctor/checks/checkKeStore.ts +2 -2
- package/src/capabilities/doctor/checks/checkMcpCommands.ts +6 -0
- package/src/capabilities/doctor/checks/checkMcpConfigured.ts +15 -8
- package/src/capabilities/doctor/checks/checkPackageRefs.ts +79 -45
- package/src/capabilities/doctor/checks/checkPragmaVersion.ts +3 -2
- package/src/capabilities/doctor/checks/checkShellCompletions.test.ts +61 -11
- package/src/capabilities/doctor/checks/checkShellCompletions.ts +63 -23
- package/src/capabilities/doctor/checks/checkSkillsSymlinked.ts +3 -2
- package/src/capabilities/doctor/checks/deriveBand.test.ts +42 -0
- package/src/capabilities/doctor/checks/deriveBand.ts +28 -0
- package/src/capabilities/doctor/doctor.render.test.ts +170 -0
- package/src/capabilities/doctor/doctor.render.ts +117 -34
- package/src/capabilities/doctor/doctor.test.ts +68 -9
- package/src/capabilities/doctor/doctor.verb.ts +6 -2
- package/src/capabilities/doctor/runChecks.ts +33 -9
- package/src/capabilities/doctor/types.ts +16 -1
- package/src/capabilities/emptyRecovery.test.ts +32 -15
- package/src/capabilities/graph/inspect.verb.ts +3 -2
- package/src/capabilities/graph/query.verb.ts +3 -2
- package/src/capabilities/graph/runQuery.ts +8 -5
- package/src/capabilities/index.ts +22 -18
- package/src/capabilities/info/collectInfo.ts +10 -6
- package/src/capabilities/info/info.render.ts +3 -2
- package/src/capabilities/info/info.verb.ts +3 -2
- package/src/capabilities/lazy.test.ts +93 -2
- package/src/capabilities/ontology/index.ts +10 -3
- package/src/capabilities/ontology/ontology.test.ts +157 -5
- package/src/capabilities/ontology/verbs.ts +203 -104
- package/src/capabilities/prompt/prompt.render.test.ts +94 -0
- package/src/capabilities/prompt/prompt.render.ts +23 -6
- package/src/capabilities/prompt/prompt.test.ts +68 -1
- package/src/capabilities/prompt/verbs.ts +24 -11
- package/src/capabilities/reference.test.ts +32 -0
- package/src/capabilities/resources/provider.ts +58 -25
- package/src/capabilities/resources/resources.test.ts +176 -21
- package/src/capabilities/scopeTypeSync.test.ts +37 -0
- package/src/capabilities/setup/index.ts +7 -1
- package/src/capabilities/setup/operations/setupCompletions.ts +49 -16
- package/src/capabilities/setup/operations/setupGenerator.ts +166 -63
- package/src/capabilities/setup/operations/setupLsp.ts +56 -12
- package/src/capabilities/setup/operations/setupMcp.ts +216 -39
- package/src/capabilities/setup/operations/setupSkills.ts +10 -4
- package/src/capabilities/setup/setup.render.test.ts +109 -0
- package/src/capabilities/setup/setup.render.ts +61 -14
- package/src/capabilities/setup/setup.test.ts +352 -1
- package/src/capabilities/setup/setup.verb.ts +68 -9
- package/src/capabilities/setup/shell.ts +29 -3
- package/src/capabilities/setup/types.ts +59 -2
- package/src/capabilities/shared/bands.ts +16 -0
- package/src/capabilities/skill/discover.ts +11 -5
- package/src/capabilities/skill/render.ts +4 -5
- package/src/capabilities/skill/verbs.ts +7 -7
- package/src/capabilities/sources/collectStatus.ts +69 -49
- package/src/capabilities/sources/index.ts +1 -1
- package/src/capabilities/sources/installSkills.ts +2 -2
- package/src/capabilities/sources/runUpdate.ts +146 -98
- package/src/capabilities/sources/sources.test.ts +264 -84
- package/src/capabilities/sources/status.render.test.ts +94 -0
- package/src/capabilities/sources/status.render.ts +55 -33
- package/src/capabilities/sources/status.verb.ts +15 -8
- package/src/capabilities/sources/types.ts +18 -25
- package/src/capabilities/sources/update.render.ts +9 -2
- package/src/capabilities/sources/update.verb.ts +12 -23
- package/src/capabilities/surface.test.ts +65 -17
- package/src/capabilities/tier.parity.test.ts +144 -0
- package/src/capabilities/upgrade/upgrade.verb.ts +7 -3
- package/src/constants.test.ts +9 -7
- package/src/constants.ts +49 -23
- package/src/identity.test.ts +333 -0
- package/src/index.ts +2 -2
- package/src/kernel/completion/__snapshots__/emitScripts.test.ts.snap +18 -16
- package/src/kernel/completion/complete.test.ts +3 -5
- package/src/kernel/completion/emitScripts.test.ts +1 -1
- package/src/kernel/completion/emitScripts.ts +4 -2
- package/src/kernel/completion/entitySource.test.ts +185 -41
- package/src/kernel/completion/entitySource.ts +131 -113
- package/src/kernel/completion/model.test.ts +3 -3
- package/src/kernel/completion/model.ts +11 -1
- package/src/kernel/completion/parse.test.ts +2 -4
- package/src/kernel/completion/safety.test.ts +82 -36
- package/src/kernel/completion/shellDrive.test.ts +592 -0
- package/src/kernel/completion/templates/fish.ts +28 -6
- package/src/kernel/completion/types.ts +3 -3
- package/src/kernel/config/__snapshots__/firstRun.test.ts.snap +1 -1
- package/src/kernel/config/defaults.test.ts +85 -0
- package/src/kernel/config/defaults.ts +12 -23
- package/src/kernel/config/evaluateProjectConfig.ts +2 -3
- package/src/kernel/config/findProjectConfig.ts +4 -3
- package/src/kernel/config/firstRun.ts +12 -5
- package/src/kernel/config/globalConfig.ts +2 -2
- package/src/kernel/config/index.ts +4 -5
- package/src/kernel/config/paths.ts +17 -17
- package/src/kernel/config/readConfig.test.ts +242 -6
- package/src/kernel/config/readConfig.ts +8 -8
- package/src/kernel/config/schema.test.ts +50 -0
- package/src/kernel/config/schema.ts +97 -10
- package/src/kernel/config/types.ts +73 -19
- package/src/kernel/copy.test.ts +453 -0
- package/src/kernel/error/PragmaError.test.ts +5 -5
- package/src/kernel/error/constants.ts +3 -2
- package/src/kernel/error/index.ts +1 -1
- package/src/kernel/error/recovery.test.ts +22 -45
- package/src/kernel/error/recovery.ts +22 -27
- package/src/kernel/error/renderError.ts +1 -1
- package/src/kernel/error/types.ts +5 -4
- package/src/kernel/packs/collect.test.ts +195 -11
- package/src/kernel/packs/collect.ts +213 -58
- package/src/kernel/packs/compile.test.ts +163 -7
- package/src/kernel/packs/compile.ts +15 -12
- package/src/kernel/packs/disclosure.test.ts +5 -2
- package/src/kernel/packs/graphql/fetchGraphqlLookup.ts +11 -10
- package/src/kernel/packs/graphqlSource.test.ts +6 -3
- package/src/kernel/packs/iri.ts +5 -7
- package/src/kernel/packs/renderPack.ts +5 -3
- package/src/kernel/packs/resolveEntity.ts +21 -17
- package/src/kernel/packs/runBodies.ts +15 -14
- package/src/kernel/packs/schema.ts +96 -10
- package/src/kernel/packs/sparql/runSelect.test.ts +104 -10
- package/src/kernel/packs/sparql/runSelect.ts +73 -34
- package/src/kernel/packs/toolDescription.test.ts +10 -2
- package/src/kernel/packs/types.ts +39 -4
- package/src/kernel/packs/uniqueness.ts +4 -4
- package/src/kernel/project/cli/buildProgram.test.ts +60 -11
- package/src/kernel/project/cli/buildProgram.ts +11 -0
- package/src/kernel/project/cli/dispatch.test.ts +67 -0
- package/src/kernel/project/cli/dispatch.ts +34 -12
- package/src/kernel/project/cli/globalFlags.test.ts +12 -4
- package/src/kernel/project/cli/globalFlags.ts +14 -14
- package/src/kernel/project/cli/helpFormat.ts +1 -1
- package/src/kernel/project/cli/rootHelp.ts +109 -107
- package/src/kernel/project/mcp/buildServer.ts +11 -6
- package/src/kernel/project/mcp/instructions.ts +12 -7
- package/src/kernel/project/mcp/mcpError.ts +52 -0
- package/src/kernel/project/mcp/parity.test.ts +39 -1
- package/src/kernel/project/mcp/prompts/prompts.test.ts +128 -5
- package/src/kernel/project/mcp/prompts/provider.ts +51 -7
- package/src/kernel/project/mcp/prompts/source.ts +68 -67
- package/src/kernel/project/mcp/registerVerb.ts +25 -6
- package/src/kernel/project/mcp/serve.ts +11 -3
- package/src/kernel/project/mcp/toolDescriptions.test.ts +6 -2
- package/src/kernel/render/disclosure.ts +4 -2
- package/src/kernel/render/formatters.ts +5 -4
- package/src/kernel/render/prefixes.test.ts +36 -0
- package/src/kernel/render/prefixes.ts +40 -13
- package/src/kernel/render/renderers.test.ts +35 -1
- package/src/kernel/render/renderers.ts +25 -7
- package/src/kernel/render/style.test.ts +31 -0
- package/src/kernel/render/style.ts +74 -0
- package/src/kernel/runtime/graphpack/build.ts +57 -3
- package/src/kernel/runtime/graphpack/buildIndex.test.ts +149 -0
- package/src/kernel/runtime/graphpack/buildIndex.ts +173 -50
- package/src/kernel/runtime/graphpack/embedded/pack.generated.ts +5 -8
- package/src/kernel/runtime/graphpack/embedded/pack.index.generated.ts +3 -4
- package/src/kernel/runtime/graphpack/embedded/pack.stories.generated.ts +3 -0
- package/src/kernel/runtime/graphpack/embedded.ts +37 -11
- package/src/kernel/runtime/graphpack/graphpack.test.ts +274 -6
- package/src/kernel/runtime/graphpack/hash.ts +3 -2
- package/src/kernel/runtime/graphpack/index.ts +1 -1
- package/src/kernel/runtime/graphpack/manifest.ts +114 -12
- package/src/kernel/runtime/graphpack/read.ts +32 -22
- package/src/kernel/runtime/graphpack/schemas.ts +74 -0
- package/src/kernel/runtime/graphpack/stories.ts +84 -0
- package/src/kernel/runtime/graphpack/types.ts +72 -45
- package/src/kernel/runtime/loadSession.ts +4 -12
- package/src/kernel/runtime/paths.ts +64 -15
- package/src/kernel/runtime/probe.test.ts +8 -4
- package/src/kernel/runtime/readEntity.ts +6 -5
- package/src/kernel/runtime/refs/gitOps.ts +1 -19
- package/src/kernel/runtime/refs/parseRef.ts +7 -7
- package/src/kernel/runtime/refs/resolve.ts +141 -65
- package/src/kernel/runtime/resolveSources.test.ts +63 -24
- package/src/kernel/runtime/resolveSources.ts +36 -25
- package/src/kernel/runtime/storeReadiness.ts +62 -0
- package/src/kernel/runtime/storeless.test.ts +1 -1
- package/src/kernel/runtime/types.ts +1 -1
- package/src/kernel/runtime/wasmEmbed.test.ts +25 -20
- package/src/kernel/spec/emitReference.test.ts +196 -0
- package/src/kernel/spec/emitReference.ts +624 -0
- package/src/kernel/spec/emitSurface.ts +13 -7
- package/src/kernel/spec/index.ts +2 -0
- package/src/kernel/spec/surfaceConformance.test.ts +2 -2
- package/src/kernel/spec/surfaceConformance.ts +8 -0
- package/src/kernel/spec/types.ts +29 -9
- package/src/kernel/spec/validate.ts +2 -1
- package/src/kernel/vocabulary.test.ts +164 -0
- package/src/kernel/vocabulary.ts +146 -0
- package/src/testing/PARITY_GAPS.ts +9 -3
- package/src/testing/behavioral/README.md +3 -3
- package/src/testing/behavioral/autoLlm.e2e.test.ts +12 -2
- package/src/testing/behavioral/completion.test.ts +21 -8
- package/src/testing/behavioral/disclosure.test.ts +12 -0
- package/src/testing/behavioral/docExamples.test.ts +283 -0
- package/src/testing/behavioral/errorMatrix.mcp.test.ts +4 -3
- package/src/testing/behavioral/errorMatrix.storeless.test.ts +3 -2
- package/src/testing/behavioral/exitCodes.e2e.test.ts +6 -5
- package/src/testing/behavioral/harness.foundation.test.ts +14 -5
- package/src/testing/behavioral/journeys.cli.test.ts +116 -73
- package/src/testing/behavioral/journeys.defaultPack.test.ts +477 -0
- package/src/testing/behavioral/journeys.firstInstall.test.ts +167 -0
- package/src/testing/behavioral/journeys.interactiveTty.e2e.test.ts +66 -0
- package/src/testing/behavioral/journeys.livePack.e2e.test.ts +129 -0
- package/src/testing/behavioral/journeys.mcpLifecycle.mcp.test.ts +179 -0
- package/src/testing/behavioral/journeys.packageStories.test.ts +188 -0
- package/src/testing/behavioral/liveReadSurface.ts +4 -3
- package/src/testing/behavioral/mcpSurface.test.ts +10 -5
- package/src/testing/behavioral/staleCommands.test.ts +86 -0
- package/src/testing/eval/__snapshots__/eval.test.ts.snap +9 -9
- package/src/testing/eval/cases/assembly.ts +16 -9
- package/src/testing/eval/cases/effectful.ts +31 -16
- package/src/testing/eval/cases/readNouns.ts +23 -18
- package/src/testing/eval/cases/stable.ts +5 -1
- package/src/testing/eval/eval.test.ts +7 -1
- package/src/testing/fixtures/fixtureCapability.ts +201 -1
- package/src/testing/fixtures/graph/canonical.ts +6 -3
- package/src/testing/fixtures/graph/defaultPack.ts +179 -0
- package/src/testing/fixtures/graph/owlExport.ts +97 -0
- package/src/testing/helpers/extractSnippets.ts +29 -0
- package/src/testing/helpers/fixtureGraph.ts +33 -16
- package/src/testing/helpers/golden.ts +1 -1
- package/src/testing/helpers/packRuntime.ts +2 -3
- package/src/testing/helpers/projectCli.ts +2 -1
- package/src/testing/helpers/projectMcp.ts +6 -0
- package/src/testing/perf/budgets.test.ts +4 -0
- package/src/testing/perf/budgets.ts +22 -7
- package/src/testing/perf/globalSetup.ts +121 -6
- package/src/types.ts +2 -2
- package/src/capabilities/block/blockList.verb.ts +0 -150
- package/src/capabilities/block/index.ts +0 -25
- package/src/capabilities/block/pack.ts +0 -155
- package/src/capabilities/block/parity.test.ts +0 -180
- package/src/capabilities/block/tierChain.ts +0 -78
- package/src/capabilities/colophon/pragmaColophon.ts +0 -66
- package/src/capabilities/config/field.test.ts +0 -188
- package/src/capabilities/modifier/index.ts +0 -15
- package/src/capabilities/modifier/pack.ts +0 -64
- package/src/capabilities/standard/index.ts +0 -18
- package/src/capabilities/standard/pack.ts +0 -128
- package/src/capabilities/tier/index.ts +0 -19
- package/src/capabilities/tier/lookup.render.ts +0 -34
- package/src/capabilities/tier/lookup.test.ts +0 -68
- package/src/capabilities/tier/lookup.verb.ts +0 -44
- package/src/capabilities/tier/pack.ts +0 -28
- package/src/capabilities/tier/runLookup.ts +0 -59
- package/src/capabilities/token/addConfig.render.ts +0 -27
- package/src/capabilities/token/addConfig.test.ts +0 -62
- package/src/capabilities/token/addConfig.verb.ts +0 -40
- package/src/capabilities/token/index.ts +0 -19
- package/src/capabilities/token/pack.ts +0 -58
- package/src/capabilities/token/runAddConfig.ts +0 -95
- package/src/kernel/completion/bashDrive.test.ts +0 -73
- package/src/kernel/runtime/graphpack/embedded/sample.ttl +0 -39
- package/src/kernel/runtime/lock.ts +0 -90
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The `create` verbs — `component` / `package` / `application` (path capped at
|
|
3
|
-
* two segments; the
|
|
3
|
+
* two segments; the declared component frameworks collapse to one verb + a
|
|
4
4
|
* `--framework` enum). Each is a mutating, interactive, storeless verb.
|
|
5
5
|
*
|
|
6
6
|
* LAZY DISPATCH (R9 + lazy-React): the params are STATIC — built by the
|
|
7
7
|
* generator→grammar adapter over static prompt MIRRORS, never the live
|
|
8
|
-
* generators (importing a generator
|
|
8
|
+
* generators (importing a generator pulls summon-core, and with it React). The
|
|
9
9
|
* `run` body lazily `import()`s `pickGenerator` + summon-core, so `buildProgram`
|
|
10
10
|
* / `--help` / `__complete` / reads never load summon-core or the generators —
|
|
11
11
|
* and `create --yes` never loads React (the Ink UI is dynamic-only, and only the
|
|
@@ -15,9 +15,11 @@
|
|
|
15
15
|
|
|
16
16
|
import type { GeneratorResult, PromptDefinition } from "@canonical/summon-core";
|
|
17
17
|
import type { Task } from "@canonical/task";
|
|
18
|
+
import { BIN_NAME } from "../../constants.js";
|
|
18
19
|
import { PragmaError } from "../../kernel/error/PragmaError.js";
|
|
19
20
|
import type { PragmaRuntime } from "../../kernel/runtime/types.js";
|
|
20
21
|
import type { ParamSpec, VerbSpec } from "../../kernel/spec/types.js";
|
|
22
|
+
import { CREATE_GENERATORS } from "./constants.js";
|
|
21
23
|
import { createFormatters } from "./create.render.js";
|
|
22
24
|
import { generatorToParams } from "./generatorToVerbSpec.js";
|
|
23
25
|
import { assertInsideWorkspace } from "./pathJail.js";
|
|
@@ -27,13 +29,14 @@ import type { CreateKind } from "./types.js";
|
|
|
27
29
|
// Static params (mirrors of the generators' prompts — see the module doc)
|
|
28
30
|
// =============================================================================
|
|
29
31
|
|
|
30
|
-
/** `--framework` — the
|
|
32
|
+
/** `--framework` — the declared component generators collapsed to one enum. */
|
|
31
33
|
const FRAMEWORK_PARAM: ParamSpec = {
|
|
32
34
|
kind: "enum",
|
|
33
35
|
name: "framework",
|
|
34
36
|
doc: "Component framework.",
|
|
35
|
-
values:
|
|
36
|
-
default
|
|
37
|
+
values: CREATE_GENERATORS.component.frameworks,
|
|
38
|
+
// The FIRST declared framework, so the default is always inside the enum.
|
|
39
|
+
default: CREATE_GENERATORS.component.frameworks[0],
|
|
37
40
|
};
|
|
38
41
|
|
|
39
42
|
/**
|
|
@@ -129,6 +132,13 @@ const PACKAGE_MIRROR: PromptDefinition[] = [
|
|
|
129
132
|
},
|
|
130
133
|
];
|
|
131
134
|
|
|
135
|
+
// The include-flag prompts carry the CLI grammar's `--with-X` names
|
|
136
|
+
// (`withSsr`/`withRouter`/`withForms`/`withRelay`, AV-228 B8) rather than the
|
|
137
|
+
// summon generator's bare prompt names (`ssr`/`router`/`forms`/`relay`). {@link
|
|
138
|
+
// INCLUDE_FLAG_ALIASES} maps them back at the CLI↔generator boundary so the
|
|
139
|
+
// generator prompt names — and their embedded templates + byte-equality
|
|
140
|
+
// goldens — stay stable. `--run-install` (default false) is an action flag, not
|
|
141
|
+
// an include, so it keeps its spelling.
|
|
132
142
|
const APPLICATION_MIRROR: PromptDefinition[] = [
|
|
133
143
|
{
|
|
134
144
|
name: "appPath",
|
|
@@ -137,21 +147,21 @@ const APPLICATION_MIRROR: PromptDefinition[] = [
|
|
|
137
147
|
default: "my-app",
|
|
138
148
|
positional: true,
|
|
139
149
|
},
|
|
140
|
-
{ name: "
|
|
150
|
+
{ name: "withSsr", type: "confirm", message: "Include SSR?", default: true },
|
|
141
151
|
{
|
|
142
|
-
name: "
|
|
152
|
+
name: "withRouter",
|
|
143
153
|
type: "confirm",
|
|
144
154
|
message: "Include router?",
|
|
145
155
|
default: true,
|
|
146
156
|
},
|
|
147
157
|
{
|
|
148
|
-
name: "
|
|
158
|
+
name: "withForms",
|
|
149
159
|
type: "confirm",
|
|
150
160
|
message: "Include form components?",
|
|
151
161
|
default: true,
|
|
152
162
|
},
|
|
153
163
|
{
|
|
154
|
-
name: "
|
|
164
|
+
name: "withRelay",
|
|
155
165
|
type: "confirm",
|
|
156
166
|
message: "Include a Relay (GraphQL) data layer?",
|
|
157
167
|
default: false,
|
|
@@ -164,6 +174,50 @@ const APPLICATION_MIRROR: PromptDefinition[] = [
|
|
|
164
174
|
},
|
|
165
175
|
];
|
|
166
176
|
|
|
177
|
+
/**
|
|
178
|
+
* CLI include-flag names → summon generator prompt names, per create kind
|
|
179
|
+
* (AV-228 B8). All four `create application` include-flags are exposed on the
|
|
180
|
+
* unified `--with-X` convention, so their params arrive keyed `withSsr`/
|
|
181
|
+
* `withRouter`/`withForms`/`withRelay`; the summon generator reads the bare
|
|
182
|
+
* `ssr`/`router`/`forms`/`relay`. We normalize at the ONE CLI↔generator seam
|
|
183
|
+
* ({@link toGeneratorAnswers}), keeping the generator prompt names (and their
|
|
184
|
+
* templates/goldens) untouched. Component and package already use `--with-X`
|
|
185
|
+
* names that match their prompts, so their maps are empty.
|
|
186
|
+
*/
|
|
187
|
+
export const INCLUDE_FLAG_ALIASES: Record<
|
|
188
|
+
CreateKind,
|
|
189
|
+
Readonly<Record<string, string>>
|
|
190
|
+
> = {
|
|
191
|
+
component: {},
|
|
192
|
+
package: {},
|
|
193
|
+
application: {
|
|
194
|
+
withSsr: "ssr",
|
|
195
|
+
withRouter: "router",
|
|
196
|
+
withForms: "forms",
|
|
197
|
+
withRelay: "relay",
|
|
198
|
+
},
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Re-key a param bag's CLI include-flag aliases to the generator prompt names,
|
|
203
|
+
* so the summon generator reads `ssr` where the CLI grammar exposes `--with-ssr`.
|
|
204
|
+
*
|
|
205
|
+
* @param kind - The create noun (selects the alias map).
|
|
206
|
+
* @param params - The coerced CLI/MCP param bag.
|
|
207
|
+
* @returns A new bag with aliased keys renamed to the generator prompt names.
|
|
208
|
+
*/
|
|
209
|
+
export function toGeneratorAnswers(
|
|
210
|
+
kind: CreateKind,
|
|
211
|
+
params: Readonly<Record<string, unknown>>,
|
|
212
|
+
): Record<string, unknown> {
|
|
213
|
+
const aliases = INCLUDE_FLAG_ALIASES[kind];
|
|
214
|
+
const answers: Record<string, unknown> = {};
|
|
215
|
+
for (const [key, value] of Object.entries(params)) {
|
|
216
|
+
answers[aliases[key] ?? key] = value;
|
|
217
|
+
}
|
|
218
|
+
return answers;
|
|
219
|
+
}
|
|
220
|
+
|
|
167
221
|
const componentParams: ParamSpec[] = [
|
|
168
222
|
FRAMEWORK_PARAM,
|
|
169
223
|
COMPONENT_PATH_PARAM,
|
|
@@ -183,20 +237,16 @@ const PATH_PARAM: Record<CreateKind, string | undefined> = {
|
|
|
183
237
|
// The lazy run — the one-line summon↔pragma seam per invocation
|
|
184
238
|
// =============================================================================
|
|
185
239
|
|
|
186
|
-
/**
|
|
187
|
-
* Build the `create` Task for one invocation: pick the generator, jail its
|
|
188
|
-
* output path, pre-validate flag/arg answers, pick the prompt strategy against
|
|
189
|
-
* the interaction context, wire `runtime.exec`, and return `execute`.
|
|
190
|
-
*
|
|
191
|
-
* @returns A `Promise<Task<GeneratorResult>>` (the union's third arm) the
|
|
192
|
-
* dispatcher/MCP handler awaits into a Task before interpreting.
|
|
193
|
-
*/
|
|
194
240
|
/**
|
|
195
241
|
* The standalone `bun build --compile` binary resolves every bundled module
|
|
196
242
|
* under the virtual `/$bunfs` filesystem — a marker absent from any source or
|
|
197
|
-
* `bun`-run module URL.
|
|
198
|
-
*
|
|
199
|
-
*
|
|
243
|
+
* `bun`-run module URL. Only a generator that routes its template reads through
|
|
244
|
+
* the embedded manifest can run there
|
|
245
|
+
* (`CREATE_GENERATORS[kind].readsEmbeddedTemplates`);
|
|
246
|
+
* the others call `template({ source })`, which falls through to
|
|
247
|
+
* `readFile(source)` and dies with `ENOENT … /$bunfs/…` after `mkdir` has
|
|
248
|
+
* already run, leaving partially-created files behind.
|
|
249
|
+
* `compiledCreate.subprocess.test.ts` pins the refusal AND the empty cwd.
|
|
200
250
|
*/
|
|
201
251
|
const IS_COMPILED_BINARY = import.meta.url.includes("/$bunfs/");
|
|
202
252
|
|
|
@@ -230,23 +280,22 @@ export function isModuleNotFound(cause: unknown): boolean {
|
|
|
230
280
|
* `--compile` bundler includes them — they stay behind this lazy boundary, so
|
|
231
281
|
* the fast paths and `create --yes` still load neither summon-core nor React).
|
|
232
282
|
*
|
|
233
|
-
* The manifest is injected BEFORE `pickGenerator` —
|
|
234
|
-
*
|
|
235
|
-
*
|
|
236
|
-
*
|
|
237
|
-
*
|
|
238
|
-
*
|
|
283
|
+
* The manifest is injected BEFORE `pickGenerator` — the component loader
|
|
284
|
+
* consults it when its disk read fails (the compiled binary), and the generators
|
|
285
|
+
* load their templates on first `generate()`. It is imported from
|
|
286
|
+
* summon-component's `loadTemplate` submodule so this does not evaluate the
|
|
287
|
+
* generator index first. In a source run the disk read wins and the manifest is
|
|
288
|
+
* inert.
|
|
239
289
|
*
|
|
240
|
-
*
|
|
241
|
-
*
|
|
242
|
-
*
|
|
243
|
-
* {@link isModuleNotFound} turns into the same clean gate.
|
|
290
|
+
* A binding whose generator does not read through that manifest is gated to a
|
|
291
|
+
* source run here ({@link IS_COMPILED_BINARY}). A stale resolution failure is a
|
|
292
|
+
* defensive backstop {@link isModuleNotFound} turns into the same clean gate.
|
|
244
293
|
*/
|
|
245
294
|
async function loadCreateRuntime(kind: CreateKind) {
|
|
246
|
-
if (IS_COMPILED_BINARY && kind
|
|
295
|
+
if (IS_COMPILED_BINARY && !CREATE_GENERATORS[kind].readsEmbeddedTemplates) {
|
|
247
296
|
throw new PragmaError({
|
|
248
297
|
code: "UNSUPPORTED",
|
|
249
|
-
message: `\`create ${kind}\` is not available in the compiled
|
|
298
|
+
message: `\`create ${kind}\` is not available in the compiled ${BIN_NAME} binary — ${SOURCE_ONLY_REASON}. Run it from a source checkout, or use the \`summon\` CLI.`,
|
|
250
299
|
recovery: {
|
|
251
300
|
message: `Run \`create ${kind}\` from a source checkout, or use \`summon\`.`,
|
|
252
301
|
},
|
|
@@ -280,26 +329,42 @@ async function loadCreateRuntime(kind: CreateKind) {
|
|
|
280
329
|
}
|
|
281
330
|
}
|
|
282
331
|
|
|
332
|
+
/**
|
|
333
|
+
* Build the `create` Task for one invocation: pick the generator, jail its
|
|
334
|
+
* output path, pre-validate flag/arg answers, pick the prompt strategy against
|
|
335
|
+
* the interaction context, wire `runtime.exec`, and return `execute`.
|
|
336
|
+
*
|
|
337
|
+
* @param kind - The create noun.
|
|
338
|
+
* @param params - The coerced params for this invocation.
|
|
339
|
+
* @param rt - The pragma runtime.
|
|
340
|
+
* @returns A `Promise<Task<GeneratorResult>>` (the union's third arm) the
|
|
341
|
+
* dispatcher/MCP handler awaits into a Task before interpreting.
|
|
342
|
+
*/
|
|
283
343
|
async function runCreate(
|
|
284
344
|
kind: CreateKind,
|
|
285
345
|
params: Record<string, unknown>,
|
|
286
346
|
rt: PragmaRuntime,
|
|
287
347
|
): Promise<Task<GeneratorResult>> {
|
|
288
|
-
// Lazy: importing these
|
|
289
|
-
//
|
|
290
|
-
//
|
|
291
|
-
//
|
|
348
|
+
// Lazy: importing these pulls summon-core (and with it React) — kept off every
|
|
349
|
+
// non-create path. Now STATIC dynamic imports so `--compile` bundles them; the
|
|
350
|
+
// embedded `.ejs` manifest is injected here. A binding that does not read
|
|
351
|
+
// through it stays a source-run feature in the binary.
|
|
292
352
|
const { pickGenerator, summon } = await loadCreateRuntime(kind);
|
|
293
353
|
|
|
294
|
-
|
|
354
|
+
// Normalize the CLI/MCP `--with-X` include-flags to the generator prompt names
|
|
355
|
+
// (AV-228 B8) once, at this seam; every summon interaction below reads the
|
|
356
|
+
// generator-facing `answers` bag so the generator prompt names stay stable.
|
|
357
|
+
const answers = toGeneratorAnswers(kind, params);
|
|
358
|
+
|
|
359
|
+
const generator = pickGenerator(kind, answers);
|
|
295
360
|
|
|
296
361
|
// SEC-2: reject a path escaping the workspace BEFORE any effect runs.
|
|
297
362
|
const pathParam = PATH_PARAM[kind];
|
|
298
|
-
if (pathParam) assertInsideWorkspace(pathParam,
|
|
363
|
+
if (pathParam) assertInsideWorkspace(pathParam, answers[pathParam], rt.cwd);
|
|
299
364
|
|
|
300
365
|
// Reject a flag/arg-provided answer that fails its prompt's own constraint,
|
|
301
366
|
// with a clean INVALID_INPUT (execute re-validates as a backstop).
|
|
302
|
-
const invalid = summon.validateAnswers(generator.prompts,
|
|
367
|
+
const invalid = summon.validateAnswers(generator.prompts, answers);
|
|
303
368
|
if (invalid !== null) {
|
|
304
369
|
throw new PragmaError({ code: "INVALID_INPUT", message: invalid });
|
|
305
370
|
}
|
|
@@ -318,7 +383,13 @@ async function runCreate(
|
|
|
318
383
|
// `onCancel` (H2): an in-Ink Ctrl-C during execution aborts the run so the
|
|
319
384
|
// interpreter stops writing — raw mode swallows the SIGINT, so the wizard
|
|
320
385
|
// drives the abort. Shared with setup by construction.
|
|
321
|
-
|
|
386
|
+
// `cwd` also reaches the wizard: its confirm-gate preview reads the same
|
|
387
|
+
// jail-checked write root the interpreter resolves effect paths against.
|
|
388
|
+
const session = summon.inkPrompt(generator, {
|
|
389
|
+
signal,
|
|
390
|
+
onCancel: abort,
|
|
391
|
+
cwd: rt.cwd,
|
|
392
|
+
});
|
|
322
393
|
// Thread the per-call write root: the interpreter resolves the generator's
|
|
323
394
|
// relative output paths against `rt.cwd` — the SAME dir the SEC-2 jail
|
|
324
395
|
// validated above — so the write can never escape the checked directory.
|
|
@@ -336,14 +407,16 @@ async function runCreate(
|
|
|
336
407
|
};
|
|
337
408
|
return summon.execute(generator, {
|
|
338
409
|
prompt: session.promptHandler,
|
|
339
|
-
params,
|
|
410
|
+
params: answers,
|
|
340
411
|
signal,
|
|
341
412
|
});
|
|
342
413
|
}
|
|
343
414
|
|
|
344
415
|
// Non-interactive: MCP → params-or-error; CLI/--yes/CI → flags+defaults.
|
|
345
416
|
const prompt =
|
|
346
|
-
transport === "mcp"
|
|
417
|
+
transport === "mcp"
|
|
418
|
+
? summon.mcpPrompt(answers)
|
|
419
|
+
: summon.autoPrompt(answers);
|
|
347
420
|
// Same per-call write root as the Ink branch: `rt.cwd` feeds both the SEC-2
|
|
348
421
|
// jail and the interpreter's effect-path base, atomically.
|
|
349
422
|
rt.exec = {
|
|
@@ -353,7 +426,7 @@ async function runCreate(
|
|
|
353
426
|
onLog: (_level, message) => process.stderr.write(`${message}\n`),
|
|
354
427
|
signal,
|
|
355
428
|
};
|
|
356
|
-
return summon.execute(generator, { prompt, params, signal });
|
|
429
|
+
return summon.execute(generator, { prompt, params: answers, signal });
|
|
357
430
|
}
|
|
358
431
|
|
|
359
432
|
/**
|
|
@@ -375,10 +448,51 @@ const CREATE_CAPABILITY = {
|
|
|
375
448
|
},
|
|
376
449
|
};
|
|
377
450
|
|
|
451
|
+
/**
|
|
452
|
+
* Why a binding is source-run only — the ONE authoring of it, shared by the
|
|
453
|
+
* documentation below and by {@link loadCreateRuntime}'s `UNSUPPORTED` refusal,
|
|
454
|
+
* so what the reference promises and what the binary does cannot disagree.
|
|
455
|
+
*/
|
|
456
|
+
const SOURCE_ONLY_REASON =
|
|
457
|
+
"its generator reads templates from disk, which the binary does not carry";
|
|
458
|
+
|
|
459
|
+
/**
|
|
460
|
+
* The published caveat for a binding the compiled binary cannot run. DERIVED
|
|
461
|
+
* from `CREATE_GENERATORS[kind].readsEmbeddedTemplates` — flipping that bit
|
|
462
|
+
* moves the caveat, `docs/reference/*.md`, and `create.test.ts`'s binding
|
|
463
|
+
* assertion together.
|
|
464
|
+
*
|
|
465
|
+
* It LEADS WITH THE PURPOSE, because `tools.md` and the MCP tool description
|
|
466
|
+
* both render `doc ?? summary` — so a caveat alone REPLACED the only sentence
|
|
467
|
+
* saying what the tool makes, and an agent enumerating tools could not learn
|
|
468
|
+
* that `create_package` scaffolds a package. The tool works from a source
|
|
469
|
+
* checkout; describing nothing but its refusal made a live tool
|
|
470
|
+
* undiscoverable. The repeated sentence in `commands.md`'s section is the
|
|
471
|
+
* cheaper of the two costs.
|
|
472
|
+
*
|
|
473
|
+
* It names no CLI flag (`mcp/toolDescriptions.test.ts` forbids one, and an
|
|
474
|
+
* agent has no flags): the plan-only refusal is stated in the terms BOTH
|
|
475
|
+
* surfaces share.
|
|
476
|
+
*
|
|
477
|
+
* @param kind - The create binding.
|
|
478
|
+
* @param summary - The verb's own one-liner, which the `doc` replaces on MCP.
|
|
479
|
+
* @returns The `doc` for a source-run-only binding, or `undefined`.
|
|
480
|
+
*/
|
|
481
|
+
function buildAvailabilityDoc(
|
|
482
|
+
kind: CreateKind,
|
|
483
|
+
summary: string,
|
|
484
|
+
): string | undefined {
|
|
485
|
+
if (CREATE_GENERATORS[kind].readsEmbeddedTemplates) return undefined;
|
|
486
|
+
return `${summary} From the compiled ${BIN_NAME} binary, \`create ${kind}\` refuses with \`UNSUPPORTED\` and writes nothing. Asking it only to PLAN refuses too — the gate runs while the plan is built — so a successful plan is never evidence it would run. The cause is that ${SOURCE_ONLY_REASON}. Run it from a source checkout, or use the \`summon\` CLI.`;
|
|
487
|
+
}
|
|
488
|
+
|
|
378
489
|
/**
|
|
379
490
|
* Build a create verb. `run` presents `Promise<Task<R>>` through the `Task<R>`
|
|
380
491
|
* arm by an honest cast at this one site (mirroring `sources update`): a literal
|
|
381
492
|
* `Promise<Task<R>>` arm in the union would poison async read-verb inference.
|
|
493
|
+
*
|
|
494
|
+
* A binding the compiled binary cannot run says so in its `summary` (which is
|
|
495
|
+
* what `--help` and the noun listing show) and explains itself in its `doc`.
|
|
382
496
|
*/
|
|
383
497
|
function createVerb(
|
|
384
498
|
kind: CreateKind,
|
|
@@ -386,9 +500,11 @@ function createVerb(
|
|
|
386
500
|
params: ParamSpec[],
|
|
387
501
|
examples: VerbSpec["examples"],
|
|
388
502
|
): VerbSpec<Record<string, unknown>, GeneratorResult> {
|
|
503
|
+
const doc = buildAvailabilityDoc(kind, summary);
|
|
389
504
|
return {
|
|
390
505
|
path: ["create", kind],
|
|
391
|
-
summary,
|
|
506
|
+
summary: doc ? `${summary} Source-run only.` : summary,
|
|
507
|
+
...(doc ? { doc } : {}),
|
|
392
508
|
params,
|
|
393
509
|
output: { formatters: createFormatters },
|
|
394
510
|
examples,
|
|
@@ -398,38 +514,51 @@ function createVerb(
|
|
|
398
514
|
};
|
|
399
515
|
}
|
|
400
516
|
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
)
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
517
|
+
/**
|
|
518
|
+
* The `create` verbs, one per declared generator binding — so adding a binding
|
|
519
|
+
* to {@link CREATE_GENERATORS} without surfacing it is a type error rather than
|
|
520
|
+
* a silent no-op. Key order is authoring order, which `index.ts` preserves into
|
|
521
|
+
* the command tree, `--help` and the emitted surface.
|
|
522
|
+
*/
|
|
523
|
+
export const createVerbs: Record<
|
|
524
|
+
CreateKind,
|
|
525
|
+
VerbSpec<Record<string, unknown>, GeneratorResult>
|
|
526
|
+
> = {
|
|
527
|
+
component: createVerb(
|
|
528
|
+
"component",
|
|
529
|
+
"Scaffold a React, Svelte, or Lit component.",
|
|
530
|
+
componentParams,
|
|
531
|
+
[
|
|
532
|
+
{
|
|
533
|
+
cmd: `${BIN_NAME} create component src/components/Button --framework react`,
|
|
534
|
+
note: "React component with tests, stories, and styles",
|
|
535
|
+
},
|
|
536
|
+
{
|
|
537
|
+
cmd: `${BIN_NAME} create component src/lib/Card --framework svelte --dry-run`,
|
|
538
|
+
note: "preview the files without writing",
|
|
539
|
+
},
|
|
540
|
+
],
|
|
541
|
+
),
|
|
542
|
+
package: createVerb(
|
|
543
|
+
"package",
|
|
544
|
+
"Scaffold a new npm package for the monorepo.",
|
|
545
|
+
packageParams,
|
|
546
|
+
[
|
|
547
|
+
{
|
|
548
|
+
cmd: `${BIN_NAME} create package --name @canonical/my-lib --type library`,
|
|
549
|
+
},
|
|
550
|
+
{
|
|
551
|
+
cmd: `${BIN_NAME} create package --name @canonical/my-tool --run-install`,
|
|
552
|
+
},
|
|
553
|
+
],
|
|
554
|
+
),
|
|
555
|
+
application: createVerb(
|
|
556
|
+
"application",
|
|
557
|
+
"Scaffold a full React application with SSR and routing.",
|
|
558
|
+
applicationParams,
|
|
559
|
+
[
|
|
560
|
+
{ cmd: `${BIN_NAME} create application my-app` },
|
|
561
|
+
{ cmd: `${BIN_NAME} create application my-app --with-relay` },
|
|
562
|
+
],
|
|
563
|
+
),
|
|
564
|
+
};
|
|
@@ -8,18 +8,10 @@
|
|
|
8
8
|
|
|
9
9
|
import { asVerb } from "../../kernel/spec/asVerb.js";
|
|
10
10
|
import type { CapabilityModule } from "../../kernel/spec/types.js";
|
|
11
|
-
import {
|
|
12
|
-
createApplicationVerb,
|
|
13
|
-
createComponentVerb,
|
|
14
|
-
createPackageVerb,
|
|
15
|
-
} from "./create.verb.js";
|
|
11
|
+
import { createVerbs } from "./create.verb.js";
|
|
16
12
|
|
|
17
13
|
/** The `create` capability module. */
|
|
18
14
|
export const createModule: CapabilityModule = {
|
|
19
15
|
name: "create",
|
|
20
|
-
verbs:
|
|
21
|
-
asVerb(createComponentVerb),
|
|
22
|
-
asVerb(createPackageVerb),
|
|
23
|
-
asVerb(createApplicationVerb),
|
|
24
|
-
],
|
|
16
|
+
verbs: Object.values(createVerbs).map(asVerb),
|
|
25
17
|
};
|
|
@@ -1,38 +1,46 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Select the summon generator for a `create` invocation.
|
|
3
|
-
*
|
|
4
|
-
* This module statically imports the summon generator packages' `generators`
|
|
5
|
-
* maps — and importing them runs a top-level `await loadTemplate` that reads
|
|
6
|
-
* every template file from disk. So this module MUST stay behind `create`'s
|
|
7
|
-
* lazy `import()` (R9): the fast paths (`buildProgram` / `__complete` / `--help`
|
|
8
|
-
* / reads) never load it, and `create --yes` never loads React either (the
|
|
9
|
-
* generators pull summon-core, whose Ink UI is dynamic-only).
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
1
|
import { generators as applicationGenerators } from "@canonical/summon-application";
|
|
13
2
|
import { generators as componentGenerators } from "@canonical/summon-component";
|
|
14
3
|
import type { GeneratorDefinition } from "@canonical/summon-core";
|
|
15
4
|
import { generators as packageGenerators } from "@canonical/summon-package";
|
|
16
5
|
import { PragmaError } from "../../kernel/error/PragmaError.js";
|
|
6
|
+
import { CREATE_GENERATORS } from "./constants.js";
|
|
17
7
|
import type { CreateKind } from "./types.js";
|
|
18
8
|
|
|
19
|
-
|
|
20
|
-
export const FRAMEWORKS = ["react", "svelte", "lit"] as const;
|
|
9
|
+
type GeneratorMap = Record<string, GeneratorDefinition | undefined>;
|
|
21
10
|
|
|
22
11
|
/**
|
|
23
|
-
* The
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
12
|
+
* The declared packages' generator maps, bound by noun. The STATIC imports above
|
|
13
|
+
* are load-bearing: `bun build --compile` bundles only statically analysable
|
|
14
|
+
* specifiers, so `import(CREATE_GENERATORS[kind].name)` would leave the
|
|
15
|
+
* generators out of the binary (measured: `Cannot find module
|
|
16
|
+
* '@canonical/summon-component' from '/$bunfs/root/…'`). The declaration decides
|
|
17
|
+
* WHICH generator runs; it cannot decide which module is linked.
|
|
18
|
+
*
|
|
19
|
+
* The maps' `generate` is invariant in its (specific) answer type, so they are
|
|
20
|
+
* erased to the base definition via `unknown` — runtime-safe because `execute`
|
|
21
|
+
* calls `generate(answers)` with the resolved answers, which carry the fields
|
|
22
|
+
* the specific generator reads.
|
|
27
23
|
*/
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
24
|
+
const GENERATOR_MAPS: Record<CreateKind, GeneratorMap> = {
|
|
25
|
+
component: componentGenerators as unknown as GeneratorMap,
|
|
26
|
+
package: packageGenerators as unknown as GeneratorMap,
|
|
27
|
+
application: applicationGenerators as unknown as GeneratorMap,
|
|
28
|
+
};
|
|
32
29
|
|
|
33
30
|
/**
|
|
34
31
|
* Pick the generator for a `create <kind>` run.
|
|
35
32
|
*
|
|
33
|
+
* The module this lives in statically imports the summon generator packages'
|
|
34
|
+
* `generators` maps — and importing them pulls summon-core. So it MUST stay
|
|
35
|
+
* behind `create`'s lazy `import()` (R9): the fast paths (`buildProgram` /
|
|
36
|
+
* `__complete` / `--help` / reads) never load it, and `create --yes` never loads
|
|
37
|
+
* React either (summon-core's Ink UI is dynamic-only).
|
|
38
|
+
*
|
|
39
|
+
* `component` is branched on literally: it is the only noun with a framework
|
|
40
|
+
* axis (which is why the verb synthesises a `--framework` enum), and narrowing
|
|
41
|
+
* on `kind` here lets `CREATE_GENERATORS[kind].key` type-check over the
|
|
42
|
+
* remaining nouns without `in`-narrowing gymnastics.
|
|
43
|
+
*
|
|
36
44
|
* @param kind - The create noun.
|
|
37
45
|
* @param params - The coerced params (used for `--framework` on `component`).
|
|
38
46
|
* @returns The selected generator definition.
|
|
@@ -43,19 +51,17 @@ export function pickGenerator(
|
|
|
43
51
|
params: Readonly<Record<string, unknown>>,
|
|
44
52
|
): GeneratorDefinition {
|
|
45
53
|
if (kind === "component") {
|
|
46
|
-
const
|
|
47
|
-
const
|
|
54
|
+
const { frameworks } = CREATE_GENERATORS.component;
|
|
55
|
+
const framework = String(params.framework ?? frameworks[0]);
|
|
56
|
+
const generator = GENERATOR_MAPS.component[`component/${framework}`];
|
|
48
57
|
if (!generator) {
|
|
49
58
|
throw PragmaError.invalidInput("framework", framework, {
|
|
50
|
-
validOptions: [...
|
|
59
|
+
validOptions: [...frameworks],
|
|
51
60
|
});
|
|
52
61
|
}
|
|
53
62
|
return generator;
|
|
54
63
|
}
|
|
55
|
-
const generator =
|
|
56
|
-
kind === "package"
|
|
57
|
-
? packageMap.package
|
|
58
|
-
: applicationMap["application/react"];
|
|
64
|
+
const generator = GENERATOR_MAPS[kind][CREATE_GENERATORS[kind].key];
|
|
59
65
|
if (!generator) {
|
|
60
66
|
throw PragmaError.internalError(`missing ${kind} generator`);
|
|
61
67
|
}
|