@c9up/ream 0.2.25 → 0.2.27

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.
Files changed (178) hide show
  1. package/README.md +2 -0
  2. package/dist/Codemods.d.ts +12 -0
  3. package/dist/Codemods.d.ts.map +1 -1
  4. package/dist/Codemods.js +114 -23
  5. package/dist/Codemods.js.map +1 -1
  6. package/dist/HttpKernel.d.ts +5 -1
  7. package/dist/HttpKernel.d.ts.map +1 -1
  8. package/dist/HttpKernel.js +6 -6
  9. package/dist/HttpKernel.js.map +1 -1
  10. package/dist/Ignitor.d.ts.map +1 -1
  11. package/dist/Ignitor.js +87 -14
  12. package/dist/Ignitor.js.map +1 -1
  13. package/dist/console/Kernel.d.ts.map +1 -1
  14. package/dist/console/Kernel.js +20 -1
  15. package/dist/console/Kernel.js.map +1 -1
  16. package/dist/console/cliui.d.ts +9 -245
  17. package/dist/console/cliui.d.ts.map +1 -1
  18. package/dist/console/cliui.js +9 -583
  19. package/dist/console/cliui.js.map +1 -1
  20. package/dist/console/make/commands.d.ts +19 -0
  21. package/dist/console/make/commands.d.ts.map +1 -0
  22. package/dist/console/make/commands.js +252 -0
  23. package/dist/console/make/commands.js.map +1 -0
  24. package/dist/console/make/eject.d.ts +28 -0
  25. package/dist/console/make/eject.d.ts.map +1 -0
  26. package/dist/console/make/eject.js +161 -0
  27. package/dist/console/make/eject.js.map +1 -0
  28. package/dist/console/make/flush.d.ts +51 -0
  29. package/dist/console/make/flush.d.ts.map +1 -0
  30. package/dist/console/make/flush.js +93 -0
  31. package/dist/console/make/flush.js.map +1 -0
  32. package/dist/console/make/generators.d.ts +36 -0
  33. package/dist/console/make/generators.d.ts.map +1 -0
  34. package/dist/console/make/generators.js +148 -0
  35. package/dist/console/make/generators.js.map +1 -0
  36. package/dist/console/make/naming.d.ts +32 -0
  37. package/dist/console/make/naming.d.ts.map +1 -0
  38. package/dist/console/make/naming.js +82 -0
  39. package/dist/console/make/naming.js.map +1 -0
  40. package/dist/console/make/resolve.d.ts +46 -0
  41. package/dist/console/make/resolve.d.ts.map +1 -0
  42. package/dist/console/make/resolve.js +113 -0
  43. package/dist/console/make/resolve.js.map +1 -0
  44. package/dist/console/prompts.d.ts.map +1 -1
  45. package/dist/console/prompts.js +34 -46
  46. package/dist/console/prompts.js.map +1 -1
  47. package/dist/console/selection.d.ts +54 -0
  48. package/dist/console/selection.d.ts.map +1 -0
  49. package/dist/console/selection.js +235 -0
  50. package/dist/console/selection.js.map +1 -0
  51. package/dist/console/ui.d.ts +9 -15
  52. package/dist/console/ui.d.ts.map +1 -1
  53. package/dist/console/ui.js +11 -24
  54. package/dist/console/ui.js.map +1 -1
  55. package/dist/dev/fullReload.d.ts +35 -10
  56. package/dist/dev/fullReload.d.ts.map +1 -1
  57. package/dist/dev/fullReload.js +55 -14
  58. package/dist/dev/fullReload.js.map +1 -1
  59. package/dist/dev/hotWatcher.d.ts +19 -3
  60. package/dist/dev/hotWatcher.d.ts.map +1 -1
  61. package/dist/dev/hotWatcher.js +168 -18
  62. package/dist/dev/hotWatcher.js.map +1 -1
  63. package/dist/dev/readyBanner.d.ts +45 -0
  64. package/dist/dev/readyBanner.d.ts.map +1 -0
  65. package/dist/dev/readyBanner.js +72 -0
  66. package/dist/dev/readyBanner.js.map +1 -0
  67. package/dist/dev/shortcuts.d.ts +41 -0
  68. package/dist/dev/shortcuts.d.ts.map +1 -0
  69. package/dist/dev/shortcuts.js +142 -0
  70. package/dist/dev/shortcuts.js.map +1 -0
  71. package/dist/errors/prettyPrintError.d.ts.map +1 -1
  72. package/dist/errors/prettyPrintError.js +5 -8
  73. package/dist/errors/prettyPrintError.js.map +1 -1
  74. package/dist/errors/renderError.d.ts +46 -0
  75. package/dist/errors/renderError.d.ts.map +1 -0
  76. package/dist/errors/renderError.js +197 -0
  77. package/dist/errors/renderError.js.map +1 -0
  78. package/dist/hot.js +12 -2
  79. package/dist/hot.js.map +1 -1
  80. package/dist/index.d.ts +4 -3
  81. package/dist/index.d.ts.map +1 -1
  82. package/dist/index.js +5 -2
  83. package/dist/index.js.map +1 -1
  84. package/dist/profiler/MemoryProfileStore.d.ts +23 -0
  85. package/dist/profiler/MemoryProfileStore.d.ts.map +1 -0
  86. package/dist/profiler/MemoryProfileStore.js +70 -0
  87. package/dist/profiler/MemoryProfileStore.js.map +1 -0
  88. package/dist/profiler/Profiler.d.ts +56 -0
  89. package/dist/profiler/Profiler.d.ts.map +1 -0
  90. package/dist/profiler/Profiler.js +162 -0
  91. package/dist/profiler/Profiler.js.map +1 -0
  92. package/dist/profiler/collectors.d.ts +105 -0
  93. package/dist/profiler/collectors.d.ts.map +1 -0
  94. package/dist/profiler/collectors.js +164 -0
  95. package/dist/profiler/collectors.js.map +1 -0
  96. package/dist/profiler/endpoint.d.ts +27 -0
  97. package/dist/profiler/endpoint.d.ts.map +1 -0
  98. package/dist/profiler/endpoint.js +79 -0
  99. package/dist/profiler/endpoint.js.map +1 -0
  100. package/dist/profiler/index.d.ts +26 -0
  101. package/dist/profiler/index.d.ts.map +1 -0
  102. package/dist/profiler/index.js +41 -0
  103. package/dist/profiler/index.js.map +1 -0
  104. package/dist/profiler/middleware.d.ts +17 -0
  105. package/dist/profiler/middleware.d.ts.map +1 -0
  106. package/dist/profiler/middleware.js +79 -0
  107. package/dist/profiler/middleware.js.map +1 -0
  108. package/dist/profiler/render.d.ts +23 -0
  109. package/dist/profiler/render.d.ts.map +1 -0
  110. package/dist/profiler/render.js +141 -0
  111. package/dist/profiler/render.js.map +1 -0
  112. package/dist/profiler/toolbar.d.ts +34 -0
  113. package/dist/profiler/toolbar.d.ts.map +1 -0
  114. package/dist/profiler/toolbar.js +104 -0
  115. package/dist/profiler/toolbar.js.map +1 -0
  116. package/dist/profiler/types.d.ts +70 -0
  117. package/dist/profiler/types.d.ts.map +1 -0
  118. package/dist/profiler/types.js +11 -0
  119. package/dist/profiler/types.js.map +1 -0
  120. package/dist/router/Router.d.ts +11 -0
  121. package/dist/router/Router.d.ts.map +1 -1
  122. package/dist/router/Router.js +16 -0
  123. package/dist/router/Router.js.map +1 -1
  124. package/dist/stubs/index.d.ts +11 -0
  125. package/dist/stubs/index.d.ts.map +1 -0
  126. package/dist/stubs/index.js +12 -0
  127. package/dist/stubs/index.js.map +1 -0
  128. package/dist/stubs/template.d.ts +63 -0
  129. package/dist/stubs/template.d.ts.map +1 -0
  130. package/dist/stubs/template.js +209 -0
  131. package/dist/stubs/template.js.map +1 -0
  132. package/events.win32-x64-msvc.node +0 -0
  133. package/index.win32-x64-msvc.node +0 -0
  134. package/package.json +7 -1
  135. package/scheduler.win32-x64-msvc.node +0 -0
  136. package/src/Codemods.ts +153 -29
  137. package/src/HttpKernel.ts +12 -8
  138. package/src/Ignitor.ts +95 -14
  139. package/src/console/Kernel.ts +21 -1
  140. package/src/console/cliui.ts +44 -754
  141. package/src/console/make/commands.ts +270 -0
  142. package/src/console/make/eject.ts +163 -0
  143. package/src/console/make/flush.ts +125 -0
  144. package/src/console/make/generators.ts +176 -0
  145. package/src/console/make/naming.ts +85 -0
  146. package/src/console/make/resolve.ts +134 -0
  147. package/src/console/prompts.ts +45 -64
  148. package/src/console/selection.ts +274 -0
  149. package/src/console/ui.ts +12 -24
  150. package/src/dev/fullReload.ts +57 -15
  151. package/src/dev/hotWatcher.ts +165 -21
  152. package/src/dev/readyBanner.ts +84 -0
  153. package/src/dev/shortcuts.ts +158 -0
  154. package/src/errors/prettyPrintError.ts +5 -5
  155. package/src/errors/renderError.ts +230 -0
  156. package/src/hot.ts +12 -2
  157. package/src/index.ts +23 -3
  158. package/src/profiler/MemoryProfileStore.ts +75 -0
  159. package/src/profiler/Profiler.ts +182 -0
  160. package/src/profiler/collectors.ts +230 -0
  161. package/src/profiler/endpoint.ts +98 -0
  162. package/src/profiler/index.ts +56 -0
  163. package/src/profiler/middleware.ts +83 -0
  164. package/src/profiler/render.ts +173 -0
  165. package/src/profiler/toolbar.ts +106 -0
  166. package/src/profiler/types.ts +75 -0
  167. package/src/router/Router.ts +16 -0
  168. package/src/stubs/index.ts +14 -0
  169. package/src/stubs/template.ts +262 -0
  170. package/stubs/make/command.stub +29 -0
  171. package/stubs/make/controller.stub +30 -0
  172. package/stubs/make/entity.stub +11 -0
  173. package/stubs/make/event.stub +13 -0
  174. package/stubs/make/listener.stub +13 -0
  175. package/stubs/make/middleware.stub +16 -0
  176. package/stubs/make/provider.stub +26 -0
  177. package/stubs/make/service.stub +27 -0
  178. package/stubs/make/validator.stub +10 -0
@@ -0,0 +1,36 @@
1
+ /**
2
+ * What each `make:` command generates.
3
+ *
4
+ * One table rather than ten near-identical commands: every generator is a
5
+ * name, a stub and the variables that stub reads. The differences that matter
6
+ * — which suffix a class carries, whether the name is snake_cased for the file
7
+ * — live here, in one place, instead of being spread across ten files that
8
+ * drift.
9
+ *
10
+ * The DESTINATION is not here. It is in the stub's own front matter, so an
11
+ * application that publishes `stubs/make/controller.stub` can move the file as
12
+ * well as change its contents.
13
+ */
14
+ import type { StubState } from '../../stubs/template.js';
15
+ /** Extra input a generator takes beyond the name. */
16
+ export interface GeneratorInput {
17
+ /** `app/<module>/…` — where a module-scoped file lands. */
18
+ module?: string;
19
+ /** `make:middleware --stack server|router|named`. */
20
+ stack?: string;
21
+ /** `make:listener --event OrderShipped`. */
22
+ event?: string;
23
+ }
24
+ export interface Generator {
25
+ /** The stub, under `stubs/make/`. */
26
+ kind: string;
27
+ commandName: string;
28
+ description: string;
29
+ /** Does it take `--module`? */
30
+ moduleScoped: boolean;
31
+ /** The variables its stub reads. */
32
+ state(name: string, input: GeneratorInput): StubState;
33
+ }
34
+ export declare const GENERATORS: readonly Generator[];
35
+ export declare function generatorFor(kind: string): Generator | undefined;
36
+ //# sourceMappingURL=generators.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generators.d.ts","sourceRoot":"","sources":["../../../src/console/make/generators.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAGxD,qDAAqD;AACrD,MAAM,WAAW,cAAc;IAC7B,2DAA2D;IAC3D,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,qDAAqD;IACrD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,4CAA4C;IAC5C,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,SAAS;IACxB,qCAAqC;IACrC,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,MAAM,CAAA;IACnB,+BAA+B;IAC/B,YAAY,EAAE,OAAO,CAAA;IACrB,oCAAoC;IACpC,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,GAAG,SAAS,CAAA;CACtD;AAOD,eAAO,MAAM,UAAU,EAAE,SAAS,SAAS,EAgI1C,CAAA;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAEhE"}
@@ -0,0 +1,148 @@
1
+ /**
2
+ * What each `make:` command generates.
3
+ *
4
+ * One table rather than ten near-identical commands: every generator is a
5
+ * name, a stub and the variables that stub reads. The differences that matter
6
+ * — which suffix a class carries, whether the name is snake_cased for the file
7
+ * — live here, in one place, instead of being spread across ten files that
8
+ * drift.
9
+ *
10
+ * The DESTINATION is not here. It is in the stub's own front matter, so an
11
+ * application that publishes `stubs/make/controller.stub` can move the file as
12
+ * well as change its contents.
13
+ */
14
+ import { ensureSuffix, stripSuffixInsensitive, toPascalCase, toSnakeCase } from './naming.js';
15
+ /** The shared trio every stub may read. */
16
+ function base(name, className, module) {
17
+ return { className, module, name };
18
+ }
19
+ export const GENERATORS = [
20
+ {
21
+ kind: 'controller',
22
+ commandName: 'make:controller',
23
+ description: 'Generate an HTTP controller',
24
+ moduleScoped: true,
25
+ state: (name, input) => base(name, ensureSuffix(name, 'Controller'), input.module ?? 'controllers'),
26
+ },
27
+ {
28
+ kind: 'service',
29
+ commandName: 'make:service',
30
+ description: 'Generate a service class',
31
+ moduleScoped: true,
32
+ state: (name, input) => base(name, ensureSuffix(name, 'Service'), input.module ?? 'services'),
33
+ },
34
+ {
35
+ kind: 'entity',
36
+ commandName: 'make:entity',
37
+ description: 'Generate an Atlas entity',
38
+ moduleScoped: true,
39
+ state: (name, input) => ({
40
+ // No suffix: an entity is `User`, not `UserEntity`.
41
+ ...base(name, toPascalCase(name), input.module ?? 'entities'),
42
+ tableName: `${toSnakeCase(name)}s`,
43
+ }),
44
+ },
45
+ {
46
+ kind: 'validator',
47
+ commandName: 'make:validator',
48
+ description: 'Generate a Rune validator',
49
+ moduleScoped: true,
50
+ state: (name, input) => base(name, ensureSuffix(name, 'Validator'), input.module ?? 'validators'),
51
+ },
52
+ {
53
+ kind: 'provider',
54
+ commandName: 'make:provider',
55
+ description: 'Generate a service provider',
56
+ moduleScoped: false,
57
+ state: (name) => base(name, ensureSuffix(name, 'Provider'), ''),
58
+ },
59
+ {
60
+ kind: 'command',
61
+ commandName: 'make:command',
62
+ description: 'Generate a console command',
63
+ moduleScoped: false,
64
+ state: (name) => {
65
+ // `app:provision` is the command NAME; the class and the file come from
66
+ // its last segment, or the published stub would generate a command
67
+ // unreachable under the name it was asked for.
68
+ const segments = name.split(':');
69
+ const last = segments[segments.length - 1] ?? name;
70
+ return {
71
+ className: toPascalCase(toSnakeCase(last)),
72
+ fileName: toSnakeCase(last),
73
+ name,
74
+ };
75
+ },
76
+ },
77
+ {
78
+ kind: 'middleware',
79
+ commandName: 'make:middleware',
80
+ description: 'Generate an HTTP middleware',
81
+ moduleScoped: false,
82
+ state: (name, input) => {
83
+ const fileName = toSnakeCase(stripSuffixInsensitive(name, 'middleware'));
84
+ const stack = input.stack ?? 'router';
85
+ const importer = `() => import('#middleware/${fileName}_middleware.js')`;
86
+ // The line the user pastes into their kernel — different per stack, and
87
+ // wrong in a way that is hard to spot if it is guessed.
88
+ const registration = stack === 'server'
89
+ ? `server.use([${importer}])`
90
+ : stack === 'named'
91
+ ? `router.named({ ${fileName}: ${importer} })`
92
+ : `router.use([${importer}])`;
93
+ return {
94
+ className: `${toPascalCase(fileName)}Middleware`,
95
+ fileName,
96
+ name,
97
+ registration,
98
+ stack,
99
+ };
100
+ },
101
+ },
102
+ {
103
+ kind: 'event',
104
+ commandName: 'make:event',
105
+ description: 'Generate an event class',
106
+ moduleScoped: false,
107
+ state: (name) => {
108
+ const fileName = toSnakeCase(name);
109
+ return { className: toPascalCase(fileName), fileName, name };
110
+ },
111
+ },
112
+ {
113
+ kind: 'listener',
114
+ commandName: 'make:listener',
115
+ description: 'Generate an event listener',
116
+ moduleScoped: false,
117
+ state: (name, input) => {
118
+ const fileName = toSnakeCase(name);
119
+ const className = toPascalCase(fileName);
120
+ if (input.event === undefined) {
121
+ // Without `--event` there is nothing to type the handler with, and
122
+ // inventing an import would point at a file that does not exist.
123
+ return {
124
+ className,
125
+ fileName,
126
+ name,
127
+ importLine: '',
128
+ eventType: 'unknown',
129
+ registration: `emitter.on(SomeEvent, ${className})`,
130
+ };
131
+ }
132
+ const eventFile = toSnakeCase(input.event);
133
+ const eventClass = toPascalCase(eventFile);
134
+ return {
135
+ className,
136
+ fileName,
137
+ name,
138
+ importLine: `import type ${eventClass} from '#app/events/${eventFile}.js'\n\n`,
139
+ eventType: eventClass,
140
+ registration: `emitter.on(${eventClass}, ${className})`,
141
+ };
142
+ },
143
+ },
144
+ ];
145
+ export function generatorFor(kind) {
146
+ return GENERATORS.find((generator) => generator.kind === kind);
147
+ }
148
+ //# sourceMappingURL=generators.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generators.js","sourceRoot":"","sources":["../../../src/console/make/generators.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * The naming conventions the generators follow.
3
+ *
4
+ * Ported from the Rust generator they replace, case for case: a rename here
5
+ * changes what `make:controller user` produces, so the rules are written out
6
+ * rather than approximated.
7
+ */
8
+ /** Add the suffix unless the name already carries it. */
9
+ export declare function ensureSuffix(name: string, suffix: string): string;
10
+ /** `user_profile` / `user-profile` / `user profile` → `UserProfile`. */
11
+ export declare function toPascalCase(name: string): string;
12
+ /**
13
+ * `UserProfile` → `user_profile`, `HTTPServer` → `http_server`.
14
+ *
15
+ * The acronym case is why this is not a one-line regex: an underscore goes
16
+ * before a capital that FOLLOWS a lowercase, or that follows a capital and is
17
+ * followed by a lowercase — which is where `HTTPServer` splits.
18
+ */
19
+ export declare function toSnakeCase(name: string): string;
20
+ /** Drop a trailing `Middleware` / `middleware` / `_middleware`, whatever the case. */
21
+ export declare function stripSuffixInsensitive(name: string, suffix: string): string;
22
+ /** Longer than this is not a name, it is a paste accident. */
23
+ export declare const MAX_NAME_LENGTH = 128;
24
+ /**
25
+ * Is this a name a generator may build a path from?
26
+ *
27
+ * Refused rather than sanitised: a name with a separator in it is either a
28
+ * mistake or an attempt to write outside the project, and quietly rewriting it
29
+ * would produce a file somewhere the user did not ask for.
30
+ */
31
+ export declare function nameProblem(name: string): string | undefined;
32
+ //# sourceMappingURL=naming.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"naming.d.ts","sourceRoot":"","sources":["../../../src/console/make/naming.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,yDAAyD;AACzD,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAEjE;AAED,wEAAwE;AACxE,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMjD;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAwBhD;AAED,sFAAsF;AACtF,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAO3E;AAED,8DAA8D;AAC9D,eAAO,MAAM,eAAe,MAAM,CAAA;AAElC;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAS5D"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * The naming conventions the generators follow.
3
+ *
4
+ * Ported from the Rust generator they replace, case for case: a rename here
5
+ * changes what `make:controller user` produces, so the rules are written out
6
+ * rather than approximated.
7
+ */
8
+ /** Add the suffix unless the name already carries it. */
9
+ export function ensureSuffix(name, suffix) {
10
+ return name.endsWith(suffix) ? name : `${name}${suffix}`;
11
+ }
12
+ /** `user_profile` / `user-profile` / `user profile` → `UserProfile`. */
13
+ export function toPascalCase(name) {
14
+ return name
15
+ .split(/[_\-\s]/)
16
+ .filter((part) => part !== '')
17
+ .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
18
+ .join('');
19
+ }
20
+ /**
21
+ * `UserProfile` → `user_profile`, `HTTPServer` → `http_server`.
22
+ *
23
+ * The acronym case is why this is not a one-line regex: an underscore goes
24
+ * before a capital that FOLLOWS a lowercase, or that follows a capital and is
25
+ * followed by a lowercase — which is where `HTTPServer` splits.
26
+ */
27
+ export function toSnakeCase(name) {
28
+ const chars = [...name];
29
+ let out = '';
30
+ for (const [index, char] of chars.entries()) {
31
+ if (char.toUpperCase() === char && char.toLowerCase() !== char) {
32
+ const previous = chars[index - 1];
33
+ const next = chars[index + 1];
34
+ const previousLower = previous !== undefined &&
35
+ previous === previous.toLowerCase() &&
36
+ previous !== previous.toUpperCase();
37
+ const nextLower = next !== undefined && next === next.toLowerCase() && next !== next.toUpperCase();
38
+ const previousUpper = previous !== undefined &&
39
+ previous === previous.toUpperCase() &&
40
+ previous !== previous.toLowerCase();
41
+ if (index > 0 && (previousLower || (nextLower && previousUpper)))
42
+ out += '_';
43
+ out += char.toLowerCase();
44
+ continue;
45
+ }
46
+ out += char;
47
+ }
48
+ return out;
49
+ }
50
+ /** Drop a trailing `Middleware` / `middleware` / `_middleware`, whatever the case. */
51
+ export function stripSuffixInsensitive(name, suffix) {
52
+ const lower = name.toLowerCase();
53
+ const suffixLower = suffix.toLowerCase();
54
+ if (lower.length > suffixLower.length && lower.endsWith(suffixLower)) {
55
+ return name.slice(0, name.length - suffix.length).replace(/[_-]+$/, '');
56
+ }
57
+ return name;
58
+ }
59
+ /** Longer than this is not a name, it is a paste accident. */
60
+ export const MAX_NAME_LENGTH = 128;
61
+ /**
62
+ * Is this a name a generator may build a path from?
63
+ *
64
+ * Refused rather than sanitised: a name with a separator in it is either a
65
+ * mistake or an attempt to write outside the project, and quietly rewriting it
66
+ * would produce a file somewhere the user did not ask for.
67
+ */
68
+ export function nameProblem(name) {
69
+ if (name.trim() === '')
70
+ return 'the name is empty';
71
+ if (name.length > MAX_NAME_LENGTH)
72
+ return `the name is longer than ${MAX_NAME_LENGTH} characters`;
73
+ if (/[/\\]/.test(name))
74
+ return 'a name may not contain a path separator';
75
+ if (name.includes('..'))
76
+ return 'a name may not contain ".."';
77
+ if (!/^[A-Za-z][A-Za-z0-9_\-:]*$/.test(name)) {
78
+ return 'a name starts with a letter and holds letters, digits, "_", "-" or ":"';
79
+ }
80
+ return undefined;
81
+ }
82
+ //# sourceMappingURL=naming.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"naming.js","sourceRoot":"","sources":["../../../src/console/make/naming.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Finding a stub, rendering it, and knowing where it goes.
3
+ *
4
+ * A stub is addressed the way `codemods.makeUsingStub` addresses one — a
5
+ * package's `stubsRoot` plus a path inside it, `make/controller.stub` — so a
6
+ * generator and a package's `configure()` hook read the same file through the
7
+ * same rule. The application's own copy under `stubs/` wins over the shipped
8
+ * one, which is what `ream eject` is for.
9
+ */
10
+ import { type StubState } from '../../stubs/template.js';
11
+ /** Where an application keeps its own copies — Adonis' `stubs/` root. */
12
+ export declare const PUBLISHED_ROOT = "stubs";
13
+ /** The stubs this package ships. */
14
+ export declare const REAM_STUBS_ROOT: string;
15
+ export interface RenderedStub {
16
+ /** Relative to the project root, as the stub's front matter declares it. */
17
+ path: string;
18
+ contents: string;
19
+ /** Did the application's own copy win? */
20
+ published: boolean;
21
+ }
22
+ /**
23
+ * A stub path that could escape its root never reaches the filesystem.
24
+ *
25
+ * `eject` takes one from the command line, so this is the boundary: no
26
+ * absolute path, no `..`, and a `.stub` file at the end of it.
27
+ */
28
+ export declare function isSafeStubPath(stubPath: string): boolean;
29
+ /** Where the application's copy of `stubPath` would live. */
30
+ export declare function publishedPath(stubPath: string, cwd: string): string | undefined;
31
+ /** Read `stubPath` — the application's copy when there is one. */
32
+ export declare function readStub(stubsRoot: string, stubPath: string, cwd: string): {
33
+ source: string;
34
+ published: boolean;
35
+ };
36
+ /** Split `---\nto: …\n---\n<body>`; the front matter names the destination. */
37
+ export declare function splitFrontMatter(template: string): {
38
+ to?: string;
39
+ body: string;
40
+ };
41
+ export declare function renderStub(stubsRoot: string, stubPath: string, state: StubState, cwd: string, fallbackPath?: string): RenderedStub;
42
+ /** `make/controller.stub` — the stub a generator of that kind reads. */
43
+ export declare function stubPathFor(kind: string): string;
44
+ /** Render one of this package's own generator stubs. */
45
+ export declare function renderStubFor(kind: string, state: StubState, cwd: string): RenderedStub;
46
+ //# sourceMappingURL=resolve.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../../src/console/make/resolve.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,EAAU,KAAK,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAEhE,yEAAyE;AACzE,eAAO,MAAM,cAAc,UAAU,CAAA;AAErC,oCAAoC;AACpC,eAAO,MAAM,eAAe,QAA4D,CAAA;AAExF,MAAM,WAAW,YAAY;IAC3B,4EAA4E;IAC5E,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,0CAA0C;IAC1C,SAAS,EAAE,OAAO,CAAA;CACnB;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAMxD;AAED,6DAA6D;AAC7D,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAG/E;AAED,kEAAkE;AAClE,wBAAgB,QAAQ,CACtB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,GACV;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,CAaxC;AAED,+EAA+E;AAC/E,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG;IAAE,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAmBhF;AAkBD,wBAAgB,UAAU,CACxB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,SAAS,EAChB,GAAG,EAAE,MAAM,EACX,YAAY,CAAC,EAAE,MAAM,GACpB,YAAY,CAWd;AAED,wEAAwE;AACxE,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,wDAAwD;AACxD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,YAAY,CAEvF"}
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Finding a stub, rendering it, and knowing where it goes.
3
+ *
4
+ * A stub is addressed the way `codemods.makeUsingStub` addresses one — a
5
+ * package's `stubsRoot` plus a path inside it, `make/controller.stub` — so a
6
+ * generator and a package's `configure()` hook read the same file through the
7
+ * same rule. The application's own copy under `stubs/` wins over the shipped
8
+ * one, which is what `ream eject` is for.
9
+ */
10
+ import * as fs from 'node:fs';
11
+ import * as path from 'node:path';
12
+ import { render } from '../../stubs/template.js';
13
+ /** Where an application keeps its own copies — Adonis' `stubs/` root. */
14
+ export const PUBLISHED_ROOT = 'stubs';
15
+ /** The stubs this package ships. */
16
+ export const REAM_STUBS_ROOT = path.join(import.meta.dirname, '..', '..', '..', 'stubs');
17
+ /**
18
+ * A stub path that could escape its root never reaches the filesystem.
19
+ *
20
+ * `eject` takes one from the command line, so this is the boundary: no
21
+ * absolute path, no `..`, and a `.stub` file at the end of it.
22
+ */
23
+ export function isSafeStubPath(stubPath) {
24
+ if (stubPath === '' || stubPath.length > 256)
25
+ return false;
26
+ if (path.isAbsolute(stubPath))
27
+ return false;
28
+ const segments = stubPath.split(/[/\\]/);
29
+ if (segments.includes('..') || segments.includes(''))
30
+ return false;
31
+ return segments.every((segment) => /^[\w.-]+$/.test(segment));
32
+ }
33
+ /** Where the application's copy of `stubPath` would live. */
34
+ export function publishedPath(stubPath, cwd) {
35
+ if (!isSafeStubPath(stubPath))
36
+ return undefined;
37
+ return path.join(cwd, PUBLISHED_ROOT, stubPath);
38
+ }
39
+ /** Read `stubPath` — the application's copy when there is one. */
40
+ export function readStub(stubsRoot, stubPath, cwd) {
41
+ const published = publishedPath(stubPath, cwd);
42
+ if (published !== undefined && fs.existsSync(published)) {
43
+ return { source: fs.readFileSync(published, 'utf8'), published: true };
44
+ }
45
+ if (!isSafeStubPath(stubPath)) {
46
+ throw new Error(`[make] unusable stub path: ${stubPath}`);
47
+ }
48
+ const shipped = path.join(stubsRoot, stubPath);
49
+ if (!fs.existsSync(shipped)) {
50
+ throw new Error(`[make] no stub at "${stubPath}" (looked in ${stubsRoot})`);
51
+ }
52
+ return { source: fs.readFileSync(shipped, 'utf8'), published: false };
53
+ }
54
+ /** Split `---\nto: …\n---\n<body>`; the front matter names the destination. */
55
+ export function splitFrontMatter(template) {
56
+ const trimmed = template.replace(/^[\r\n]+/, '');
57
+ if (!trimmed.startsWith('---'))
58
+ return { body: template };
59
+ const after = trimmed.slice(3).replace(/^\r?\n/, '');
60
+ const end = after.indexOf('\n---');
61
+ if (end === -1) {
62
+ throw new Error('[make] a stub opened its front matter with `---` and never closed it');
63
+ }
64
+ const block = after.slice(0, end);
65
+ const body = after.slice(end + 4).replace(/^\r?\n/, '');
66
+ let to;
67
+ for (const rawLine of block.split('\n')) {
68
+ const line = rawLine.trim();
69
+ if (line === '' || line.startsWith('#'))
70
+ continue;
71
+ const at = line.indexOf(':');
72
+ if (at === -1)
73
+ throw new Error(`[make] unreadable stub front-matter line: \`${line}\``);
74
+ if (line.slice(0, at).trim() === 'to')
75
+ to = line.slice(at + 1).trim();
76
+ }
77
+ return to === undefined ? { body } : { to, body };
78
+ }
79
+ /**
80
+ * The destination a stub declares, checked.
81
+ *
82
+ * Absolute paths and `..` are refused rather than normalised: a published stub
83
+ * is a file in the project, and a generator is not a way to write outside it.
84
+ */
85
+ function assertInsideProject(destination) {
86
+ if (destination === '')
87
+ throw new Error('[make] the stub declares an empty destination');
88
+ if (path.isAbsolute(destination)) {
89
+ throw new Error(`[make] a stub may not write to an absolute path: ${destination}`);
90
+ }
91
+ if (destination.split(/[/\\]/).includes('..')) {
92
+ throw new Error(`[make] a stub may not write outside the project: ${destination}`);
93
+ }
94
+ }
95
+ export function renderStub(stubsRoot, stubPath, state, cwd, fallbackPath) {
96
+ const { source, published } = readStub(stubsRoot, stubPath, cwd);
97
+ const { to, body } = splitFrontMatter(source);
98
+ const destination = to === undefined ? fallbackPath : render(to, state);
99
+ if (destination === undefined) {
100
+ throw new Error(`[make] the stub at "${stubPath}" declares no destination — add a \`to:\` front-matter line.`);
101
+ }
102
+ assertInsideProject(destination);
103
+ return { path: destination, contents: render(body, state), published };
104
+ }
105
+ /** `make/controller.stub` — the stub a generator of that kind reads. */
106
+ export function stubPathFor(kind) {
107
+ return `make/${kind}.stub`;
108
+ }
109
+ /** Render one of this package's own generator stubs. */
110
+ export function renderStubFor(kind, state, cwd) {
111
+ return renderStub(REAM_STUBS_ROOT, stubPathFor(kind), state, cwd);
112
+ }
113
+ //# sourceMappingURL=resolve.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../../src/console/make/resolve.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../src/console/prompts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAOH,6EAA6E;AAC7E,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAErF;;;;;GAKG;AACH,MAAM,WAAW,mBAAoB,SAAQ,IAAI,CAAC,aAAa,EAAE,SAAS,CAAC;IACzE,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAAA;CACrC;AAED;;;;;;GAMG;AACH,MAAM,WAAW,qBACf,SAAQ,IAAI,CAAC,mBAAmB,EAAE,UAAU,GAAG,QAAQ,GAAG,QAAQ,CAAC;IACnE,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,MAAM,CAAC,CAAA;IAC7E,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,OAAO,CAAA;CACvC;AAED,MAAM,WAAW,aAAa,CAAC,CAAC,GAAG,MAAM;IACvC,qCAAqC;IACrC,OAAO,CAAC,EAAE,CAAC,CAAA;IACX,8EAA8E;IAC9E,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,kCAAkC;IAClC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,qEAAqE;IACrE,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,MAAM,CAAC,CAAA;IACrE,6CAA6C;IAC7C,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,CAAA;IAC9B;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,CAAA;CACzB;AAED;;;;;GAKG;AACH,qBAAa,UAAU;;gBAGT,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI;IAI7C,mDAAmD;IACnD,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAI9B,+CAA+C;IAC/C,MAAM,IAAI,IAAI;IAId,8CAA8C;IAC9C,MAAM,IAAI,IAAI;IAId,6DAA6D;IAC7D,YAAY,CAAC,KAAK,SAAI,GAAG,IAAI;IAI7B,qCAAqC;IACrC,aAAa,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI;CAGhD;AAED;;;;GAIG;AACH,MAAM,WAAW,oBAAoB,CAAC,CAAC,GAAG,OAAO,CAC/C,SAAQ,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;IACzD,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,CAAC,CAAA;CAC/B;AAOD,qBAAa,MAAM;;IAGjB;;;OAGG;IACH,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU;IAM9B,0EAA0E;IAC1E,IAAI,YAAY,IAAI,MAAM,EAAE,CAE3B;IAEK,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,OAAO,CAAC;IAIzE,8CAA8C;IACxC,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,OAAO,CAAC;IAItE,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC,OAAO,CAAC;IAC1E,OAAO,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,oBAAoB,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAK/E,8DAA8D;IACxD,MAAM,CACV,OAAO,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,EAClC,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,OAAO,CAAC;IACb,MAAM,CAAC,CAAC,EACZ,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,EAC7C,OAAO,EAAE,oBAAoB,CAAC,CAAC,CAAC,GAC/B,OAAO,CAAC,CAAC,CAAC;IAgDb,0CAA0C;IACpC,MAAM,CACV,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,SAAS,YAAY,EAAE,EAChC,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,OAAO,CAAC;IAKnB,iDAAiD;IAC3C,QAAQ,CACZ,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,SAAS,YAAY,EAAE,EAChC,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,OAAO,CAAC;IAKnB;;;;;OAKG;IACG,YAAY,CAChB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,SAAS,YAAY,EAAE,EAChC,OAAO,GAAE,mBAAmB,GAAG;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAO,GACrD,OAAO,CAAC,OAAO,CAAC;IA8PnB;;;;;;OAMG;IACH,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,UAAQ,GAAG,OAAO,CAAC,MAAM,CAAC;CAuCnE"}
1
+ {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../src/console/prompts.ts"],"names":[],"mappings":"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"}
@@ -11,6 +11,7 @@
11
11
  import { stdin, stdout } from 'node:process';
12
12
  import { clearLine, createInterface, cursorTo } from 'node:readline';
13
13
  import { ReamError } from '../errors/ReamError.js';
14
+ import { runSelection } from './selection.js';
14
15
  import { colourise } from './ui.js';
15
16
  /**
16
17
  * Scripted answer builder — Console's `prompt.trap(name)`.
@@ -129,21 +130,11 @@ export class Prompt {
129
130
  await this.#validateSelection(picked, options, false);
130
131
  return this.#applyResult(picked[0], options);
131
132
  }
132
- const limit = options.limit ?? 10;
133
- for (;;) {
134
- const typed = await this.readLine(this.#label(message, options, '(type to filter)'));
135
- const matches = choices.filter((choice) => nameOf(choice).toLowerCase().includes(typed.toLowerCase()));
136
- if (matches.length === 0) {
137
- stdout.write(`${colourise('No match.', 'yellow')}\n`);
138
- continue;
139
- }
140
- const first = matches[0];
141
- if (matches.length === 1 && first !== undefined) {
142
- return this.#finish(nameOf(first), options);
143
- }
144
- const picked = await this.#select(message, matches.slice(0, limit), { ...options, name: undefined }, false);
145
- return picked[0];
146
- }
133
+ // One list that narrows as you type, rather than a filter question
134
+ // followed by a list: upstream's autocomplete is a single prompt, and
135
+ // answering twice for one value is a different thing wearing its name.
136
+ const picked = await this.#select(message, choices, { ...options, name: undefined }, false, true, options.limit ?? 10);
137
+ return picked[0];
147
138
  }
148
139
  // ─── internals ──────────────────────────────────────────────
149
140
  async #text(message, options, masked) {
@@ -163,7 +154,7 @@ export class Prompt {
163
154
  return options.result ? options.result(value) : value;
164
155
  }
165
156
  }
166
- async #select(message, choices, options, many) {
157
+ async #select(message, choices, options, many, filter, limit) {
167
158
  if (choices.length === 0) {
168
159
  throw new ReamError('E_CONSOLE_EMPTY_CHOICES', `"${message}" was asked with no options.`);
169
160
  }
@@ -175,39 +166,36 @@ export class Prompt {
175
166
  await this.#validateSelection(picked, options, many);
176
167
  return many ? picked : picked.map((value) => this.#applyResult(value, options));
177
168
  }
178
- const defaultLabel = options.default === undefined
179
- ? undefined
180
- : [options.default]
181
- .flat()
182
- .map((index) => {
183
- const choice = choices[index];
184
- return choice === undefined ? String(index) : displayOf(choice);
185
- })
186
- .join(', ');
169
+ // Arrow keys, as upstream's prompts navigate. The list redraws in place
170
+ // until the user answers; a cancel is no answer, not an empty one.
187
171
  for (;;) {
188
- stdout.write(`${this.#label(message, { ...options, default: defaultLabel }).trimEnd()}\n`);
189
- choices.forEach((choice, index) => {
190
- const hint = typeof choice === 'string' ? undefined : choice.hint;
191
- stdout.write(` ${colourise(String(index + 1), 'cyan')}) ${displayOf(choice)}` +
192
- `${hint === undefined ? '' : colourise(` — ${hint}`, 'dim')}\n`);
172
+ const outcome = await runSelection({
173
+ title: this.#label(message, { ...options, default: undefined }).trimEnd(),
174
+ items: choices.map((choice) => {
175
+ const hint = typeof choice === 'string' ? undefined : choice.hint;
176
+ return hint === undefined
177
+ ? { label: displayOf(choice) }
178
+ : { label: displayOf(choice), hint };
179
+ }),
180
+ many,
181
+ ...(options.default === undefined
182
+ ? {}
183
+ : {
184
+ selected: [options.default]
185
+ .flat()
186
+ .filter((index) => Number.isInteger(index) && index >= 0 && index < choices.length),
187
+ }),
188
+ ...(filter === true ? { filter: true } : {}),
189
+ ...(limit === undefined ? {} : { limit }),
193
190
  });
194
- const answer = await this.readLine(many ? `Select (e.g. 1,3) from 1-${choices.length}: ` : `Select (1-${choices.length}): `);
195
- // An empty answer takes the default — which for a selection prompt is an
196
- // index, as Adonis spells it. Without this the default was shown in the
197
- // label and then rejected as an invalid selection.
198
- const indexes = answer === '' && options.default !== undefined
199
- ? [options.default]
200
- .flat()
201
- .filter((index) => Number.isInteger(index) && index >= 0 && index < choices.length)
202
- : answer
203
- .split(',')
204
- .map((part) => Number(part.trim()) - 1)
205
- .filter((index) => Number.isInteger(index) && index >= 0 && index < choices.length);
206
- if (indexes.length === 0 || (!many && indexes.length !== 1)) {
207
- stdout.write(`${colourise('Invalid selection.', 'yellow')}\n`);
208
- continue;
191
+ if (outcome.kind === 'cancelled') {
192
+ throw new ReamError('E_CONSOLE_PROMPT_CANCELLED', `"${message}" was cancelled.`, {
193
+ hint: 'Answer the prompt, or pass the value as a flag.',
194
+ });
209
195
  }
210
- const picked = indexes.map((index) => nameOf(choices[index]));
196
+ // A multiple with nothing ticked is an answer of none, which is only
197
+ // valid if the command says so — `validate` is where that is decided.
198
+ const picked = outcome.indexes.map((index) => nameOf(choices[index]));
211
199
  const problem = await this.#selectionProblem(picked, options, many);
212
200
  if (problem !== undefined) {
213
201
  stdout.write(`${colourise(problem, 'yellow')}\n`);