@aventara/cli 0.1.0-pilot.1 → 0.1.0-pilot.3

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 (51) hide show
  1. package/README.md +12 -5
  2. package/dist/apply/app-module.anchor.d.ts +5 -11
  3. package/dist/apply/app-module.anchor.js +0 -23
  4. package/dist/apply/conflict.confirmer.d.ts +0 -9
  5. package/dist/apply/conflict.confirmer.js +0 -15
  6. package/dist/apply/e2e-spec.anchor.js +0 -17
  7. package/dist/apply/main-cors.anchor.d.ts +50 -0
  8. package/dist/apply/main-cors.anchor.js +60 -0
  9. package/dist/apply/manifest.merger.d.ts +17 -13
  10. package/dist/apply/manifest.merger.js +8 -18
  11. package/dist/aventara.bin.js +0 -10
  12. package/dist/catalog/adapter.catalog.generated.d.ts +1 -0
  13. package/dist/catalog/adapter.catalog.generated.js +1 -4
  14. package/dist/catalog/catalog-entry.interface.d.ts +21 -13
  15. package/dist/catalog/catalog.matcher.d.ts +7 -13
  16. package/dist/catalog/catalog.matcher.js +0 -3
  17. package/dist/catalog/range.reader.d.ts +4 -10
  18. package/dist/catalog/range.reader.js +0 -14
  19. package/dist/cli.d.ts +2 -3
  20. package/dist/cli.js +5 -8
  21. package/dist/command/command.parser.d.ts +11 -9
  22. package/dist/command/command.parser.js +24 -18
  23. package/dist/node-version.guard.js +0 -12
  24. package/dist/plan/project.planner.d.ts +7 -13
  25. package/dist/plan/project.planner.js +44 -35
  26. package/dist/project/package-manager.detector.d.ts +0 -7
  27. package/dist/project/package-manager.detector.js +0 -7
  28. package/dist/project/project.inspector.d.ts +3 -9
  29. package/dist/project/project.inspector.js +0 -10
  30. package/dist/project/service.detector.d.ts +5 -10
  31. package/dist/project/service.detector.js +0 -2
  32. package/dist/project/source.scanner.js +0 -13
  33. package/dist/run/command.runner.d.ts +4 -4
  34. package/dist/run/init.orchestrator.d.ts +4 -6
  35. package/dist/run/init.orchestrator.js +3 -16
  36. package/dist/run/new.orchestrator.d.ts +8 -9
  37. package/dist/run/new.orchestrator.js +10 -18
  38. package/dist/run/scaffold.committer.d.ts +28 -0
  39. package/dist/run/scaffold.committer.js +53 -0
  40. package/dist/templates/docs.links.d.ts +8 -0
  41. package/dist/templates/docs.links.js +2 -0
  42. package/dist/templates/prisma7/prisma7.templates.js +0 -27
  43. package/dist/templates/template.registry.d.ts +13 -17
  44. package/dist/templates/template.registry.js +0 -5
  45. package/dist/wizard/answer.resolver.d.ts +5 -7
  46. package/dist/wizard/answer.resolver.js +0 -10
  47. package/dist/wizard/readline.prompter.d.ts +5 -7
  48. package/dist/wizard/readline.prompter.js +0 -10
  49. package/dist/wizard/wizard.questions.d.ts +28 -22
  50. package/dist/wizard/wizard.questions.js +21 -49
  51. package/package.json +2 -2
@@ -1,29 +1,27 @@
1
1
  import type { AdapterCatalog, CatalogEntry } from "../catalog/catalog-entry.interface.js";
2
2
  import { type ExportReference, type ServiceScan } from "../project/service.detector.js";
3
3
  /**
4
- * R5 — every question the two commands ask, in **one table**: its flag, its
5
- * label, its choices and its default. The command-line grammar, the TTY prompt,
6
- * the `--yes` defaults and the non-interactive refusal sentence are all derived
7
- * from it, so a question cannot have a flag the parser does not know or a
8
- * default the refusal does not mention.
4
+ * The command-line grammar, the TTY prompt, the `--yes` defaults and the
5
+ * non-interactive refusal sentence are all derived from it, so a question cannot
6
+ * have a flag the parser does not know or a default the refusal does not mention.
9
7
  *
10
8
  * Choices that are an adapter's facts — which ORMs and majors exist, which
11
- * databases one supports — come from the generated catalog (R14), never from a
12
- * literal here.
9
+ * databases one supports — come from the generated catalog, never from a literal
10
+ * here.
13
11
  */
14
- /** Q16-5 (a). Yarn is not supported (U1). */
12
+ /** Yarn is not supported. */
15
13
  export declare const PACKAGE_MANAGERS: readonly ["npm", "pnpm"];
16
14
  export type PackageManager = (typeof PACKAGE_MANAGERS)[number];
17
15
  /** What the wizard settles. */
18
16
  export type WizardAnswers = {
19
- /** `new`'s project directory (Q16-3). */
17
+ /** `new`'s project directory. */
20
18
  readonly name: string;
21
- /** The ORM and major, as the catalog entry that serves it (R14). */
19
+ /** The ORM and major, as the catalog entry that serves it. */
22
20
  readonly orm: CatalogEntry;
23
- /** One of `orm`'s providers (R10). */
21
+ /** One of `orm`'s providers. */
24
22
  readonly db: string;
25
23
  readonly packageManager: PackageManager;
26
- /** `init` over an existing ORM setup: the developer's service (R6). */
24
+ /** `init` over an existing ORM setup: the developer's service. */
27
25
  readonly service: ServiceChoice;
28
26
  /** The Nest module that provides and exports it. */
29
27
  readonly module: ExportReference;
@@ -36,7 +34,7 @@ export type ServiceChoice = ExportReference & {
36
34
  readonly isNew: boolean;
37
35
  };
38
36
  export type QuestionId = keyof WizardAnswers;
39
- /** What the scan of the developer's source found, for the service questions (R6). */
37
+ /** What the scan of the developer's source found, for the service questions. */
40
38
  export type ServiceContext = {
41
39
  readonly scan: ServiceScan;
42
40
  /** The ORM's client class, as the scan looked for it. */
@@ -52,14 +50,13 @@ export type ServiceContext = {
52
50
  /** What a question may consult: the catalog, what was detected, what is already answered. */
53
51
  export type WizardContext = {
54
52
  readonly catalog: AdapterCatalog;
55
- /** Q16-5's default: the lockfile, else the launching package manager (B11), else npm. */
56
53
  readonly detectedPackageManager: PackageManager;
57
54
  readonly answered: Partial<WizardAnswers>;
58
55
  /** Present for `init` over an existing ORM setup. */
59
56
  readonly services?: ServiceContext;
60
57
  };
61
58
  export type Choice = {
62
- /** What the flag takes and the prompt accepts, e.g. `prisma@7`. */
59
+ /** What the flag takes and the prompt accepts, e.g. `prisma7`. */
63
60
  readonly value: string;
64
61
  /** How it is shown, e.g. `Prisma 7`. */
65
62
  readonly label: string;
@@ -80,6 +77,11 @@ export type WizardQuestion<K extends QuestionId> = {
80
77
  readonly after?: QuestionId;
81
78
  /** The answers on offer, or `undefined` for free text. */
82
79
  readonly choices: (context: WizardContext) => readonly Choice[] | undefined;
80
+ /**
81
+ * Every value its flag takes before anything is answered — what `--help`
82
+ * lists (pilot.3); absent for free text. From the catalog, never a literal.
83
+ */
84
+ readonly accepts?: (catalog: AdapterCatalog) => readonly string[];
83
85
  /** The answer `--yes` (or Enter at the prompt) takes; `undefined` when there is none. */
84
86
  readonly defaultFor: (context: WizardContext) => string | undefined;
85
87
  /** @throws WizardAnswerError when `raw` is not an answer to this question. */
@@ -90,25 +92,29 @@ export type WizardQuestion<K extends QuestionId> = {
90
92
  export type AnyWizardQuestion = {
91
93
  readonly [K in QuestionId]: WizardQuestion<K>;
92
94
  }[QuestionId];
95
+ /**
96
+ * What `--orm` takes: each adapter's alias, with what it is — the refusal's words,
97
+ * and the usage's.
98
+ */
99
+ export declare function ormAliasesSentence(catalog: AdapterCatalog): string;
93
100
  export declare const NAME_QUESTION: WizardQuestion<"name">;
94
101
  /**
95
- * R14 — the ORM, from the catalog: `--orm <family>@<major>`, or `--orm <family>`
96
- * for the family's highest major (Q16-31).
102
+ * The prompt keeps the family-then-major order; every answer is an alias.
97
103
  */
98
104
  export declare const ORM_QUESTION: WizardQuestion<"orm">;
99
- /** R10 — the database, from the chosen entry's providers; the first is the default. */
100
105
  export declare const DB_QUESTION: WizardQuestion<"db">;
101
- /** Q16-5 — npm or pnpm; the default is detected. */
102
106
  export declare const PACKAGE_MANAGER_QUESTION: WizardQuestion<"packageManager">;
103
- /** R6, Q16-11 — the developer's service; a new one is written only when there is none. */
104
107
  export declare const SERVICE_QUESTION: WizardQuestion<"service">;
105
108
  /** The module that provides and exports the chosen service (or is @Global). */
106
109
  export declare const MODULE_QUESTION: WizardQuestion<"module">;
107
110
  /** `aventara new`'s questions, in the order they are asked. */
108
111
  export declare const NEW_QUESTIONS: readonly [WizardQuestion<"name">, WizardQuestion<"orm">, WizardQuestion<"db">, WizardQuestion<"packageManager">];
109
- /** `aventara init`'s questions when the project has no ORM (S6), in order. */
112
+ /** `aventara init`'s questions when the project has no ORM, in order. */
110
113
  export declare const INIT_QUESTIONS: readonly [WizardQuestion<"orm">, WizardQuestion<"db">, WizardQuestion<"packageManager">];
111
- /** `aventara init`'s questions over an existing ORM setup (S7): the ORM and database are read, not asked. */
114
+ /**
115
+ * `aventara init`'s questions over an existing ORM setup: the ORM and database are
116
+ * read, not asked.
117
+ */
112
118
  export declare const REUSE_QUESTIONS: readonly [WizardQuestion<"service">, WizardQuestion<"module">, WizardQuestion<"packageManager">];
113
119
  /** Every flag `aventara init` takes for a question, either way. */
114
120
  export declare const INIT_FLAG_QUESTIONS: readonly [WizardQuestion<"orm">, WizardQuestion<"db">, WizardQuestion<"service">, WizardQuestion<"module">, WizardQuestion<"packageManager">];
@@ -1,33 +1,24 @@
1
1
  import { modulesProviding, } from "../project/service.detector.js";
2
- /**
3
- * R5 — every question the two commands ask, in **one table**: its flag, its
4
- * label, its choices and its default. The command-line grammar, the TTY prompt,
5
- * the `--yes` defaults and the non-interactive refusal sentence are all derived
6
- * from it, so a question cannot have a flag the parser does not know or a
7
- * default the refusal does not mention.
8
- *
9
- * Choices that are an adapter's facts — which ORMs and majors exist, which
10
- * databases one supports — come from the generated catalog (R14), never from a
11
- * literal here.
12
- */
13
- /** Q16-5 (a). Yarn is not supported (U1). */
14
2
  export const PACKAGE_MANAGERS = ["npm", "pnpm"];
15
- /** An answer the question cannot accept. A refusal: one sentence. */
16
3
  export class WizardAnswerError extends Error {
17
4
  name = "WizardAnswerError";
18
5
  }
19
6
  function ormLabel(entry) {
20
7
  return `${entry.orm.label} ${entry.orm.major}`;
21
8
  }
22
- function available(catalog) {
23
- return catalog
24
- .map((entry) => `${ormLabel(entry)} (${entry.adapterPackage})`)
25
- .join(", ");
9
+ function listed(items) {
10
+ return items.length <= 1
11
+ ? items.join("")
12
+ : `${items.slice(0, -1).join(", ")} or ${items[items.length - 1]}`;
13
+ }
14
+ function families(catalog) {
15
+ return [...new Set(catalog.map((entry) => entry.orm.family))];
16
+ }
17
+ export function ormAliasesSentence(catalog) {
18
+ return `--orm takes ${listed(ormChoices(catalog).map((entry) => `${entry.alias} (${ormLabel(entry)}, ${entry.adapterPackage})`))}`;
26
19
  }
27
- /** Ordered for the wizard: by family as the catalog lists them, majors newest first. */
28
20
  function ormChoices(catalog) {
29
- const families = [...new Set(catalog.map((entry) => entry.orm.family))];
30
- return families.flatMap((family) => catalog
21
+ return families(catalog).flatMap((family) => catalog
31
22
  .filter((entry) => entry.orm.family === family)
32
23
  .sort((left, right) => right.orm.major - left.orm.major));
33
24
  }
@@ -47,33 +38,21 @@ export const NAME_QUESTION = {
47
38
  },
48
39
  describe: (name) => name,
49
40
  };
50
- /**
51
- * R14 — the ORM, from the catalog: `--orm <family>@<major>`, or `--orm <family>`
52
- * for the family's highest major (Q16-31).
53
- */
54
41
  export const ORM_QUESTION = {
55
42
  id: "orm",
56
43
  flag: "--orm",
57
44
  label: "ORM",
58
45
  choices: (context) => ormChoices(context.catalog).map((entry) => ({
59
- value: `${entry.orm.family}@${entry.orm.major}`,
46
+ value: entry.alias,
60
47
  label: ormLabel(entry),
61
48
  })),
62
- defaultFor: (context) => context.catalog.length === 1
63
- ? `${context.catalog[0]?.orm.family}@${context.catalog[0]?.orm.major}`
64
- : undefined,
49
+ accepts: (catalog) => ormChoices(catalog).map((entry) => entry.alias),
50
+ defaultFor: (context) => context.catalog.length === 1 ? context.catalog[0]?.alias : undefined,
65
51
  parse: (raw, context) => {
66
- const [family, major, ...rest] = raw.trim().toLowerCase().split("@");
67
- const offered = ormChoices(context.catalog).filter((entry) => entry.orm.family === family);
68
- if (rest.length > 0 || offered.length === 0) {
69
- throw new WizardAnswerError(`there is no Aventara adapter for the ORM ${JSON.stringify(raw)}; available: ${available(context.catalog)}`);
70
- }
71
- if (major === undefined) {
72
- return offered[0];
73
- }
74
- const entry = offered.find((candidate) => String(candidate.orm.major) === major);
52
+ const alias = raw.trim().toLowerCase();
53
+ const entry = context.catalog.find((candidate) => candidate.alias === alias);
75
54
  if (entry === undefined) {
76
- throw new WizardAnswerError(`there is no Aventara adapter for ${offered[0]?.orm.label} ${major}; available: ${available(context.catalog)}`);
55
+ throw new WizardAnswerError(`there is no Aventara adapter for the ORM ${JSON.stringify(raw)}; ${ormAliasesSentence(context.catalog)}`);
77
56
  }
78
57
  return entry;
79
58
  },
@@ -86,7 +65,6 @@ function requireOrm(context) {
86
65
  }
87
66
  return orm;
88
67
  }
89
- /** R10 — the database, from the chosen entry's providers; the first is the default. */
90
68
  export const DB_QUESTION = {
91
69
  id: "db",
92
70
  flag: "--db",
@@ -96,6 +74,9 @@ export const DB_QUESTION = {
96
74
  value: provider,
97
75
  label: provider,
98
76
  })),
77
+ accepts: (catalog) => [
78
+ ...new Set(catalog.flatMap((entry) => entry.providers)),
79
+ ],
99
80
  defaultFor: (context) => requireOrm(context).providers[0],
100
81
  parse: (raw, context) => {
101
82
  const orm = requireOrm(context);
@@ -107,12 +88,12 @@ export const DB_QUESTION = {
107
88
  },
108
89
  describe: (db) => db,
109
90
  };
110
- /** Q16-5 — npm or pnpm; the default is detected. */
111
91
  export const PACKAGE_MANAGER_QUESTION = {
112
92
  id: "packageManager",
113
93
  flag: "--package-manager",
114
94
  label: "Package manager",
115
95
  choices: () => PACKAGE_MANAGERS.map((manager) => ({ value: manager, label: manager })),
96
+ accepts: () => PACKAGE_MANAGERS,
116
97
  defaultFor: (context) => context.detectedPackageManager,
117
98
  parse: (raw) => {
118
99
  const manager = PACKAGE_MANAGERS.find((candidate) => candidate === raw.trim().toLowerCase());
@@ -139,7 +120,6 @@ function requireServices(context) {
139
120
  }
140
121
  return context.services;
141
122
  }
142
- /** The services on offer: what the scan found, or — when it found none — the template's new file. */
143
123
  function serviceOptions(services) {
144
124
  const found = [
145
125
  ...services.scan.candidates.map((candidate) => ({
@@ -156,14 +136,11 @@ function serviceOptions(services) {
156
136
  ? found
157
137
  : [{ ...services.newService, isNew: true }];
158
138
  }
159
- /** R6, Q16-11 — the developer's service; a new one is written only when there is none. */
160
139
  export const SERVICE_QUESTION = {
161
140
  id: "service",
162
141
  flag: "--prisma-service",
163
142
  placeholder: "<path#Export>",
164
143
  label: "Service to give Aventara (file#Export)",
165
- // With no service found, the offer to write one is a question with a default
166
- // (asked on a terminal, taken by --yes), not a single choice taken silently.
167
144
  choices: (context) => {
168
145
  const options = serviceOptions(requireServices(context));
169
146
  return options.every((option) => option.isNew)
@@ -198,7 +175,6 @@ export const SERVICE_QUESTION = {
198
175
  },
199
176
  describe: spelled,
200
177
  };
201
- /** The module that provides and exports the chosen service (or is @Global). */
202
178
  export const MODULE_QUESTION = {
203
179
  id: "module",
204
180
  flag: "--prisma-module",
@@ -232,26 +208,22 @@ export const MODULE_QUESTION = {
232
208
  },
233
209
  describe: spelled,
234
210
  };
235
- /** `aventara new`'s questions, in the order they are asked. */
236
211
  export const NEW_QUESTIONS = [
237
212
  NAME_QUESTION,
238
213
  ORM_QUESTION,
239
214
  DB_QUESTION,
240
215
  PACKAGE_MANAGER_QUESTION,
241
216
  ];
242
- /** `aventara init`'s questions when the project has no ORM (S6), in order. */
243
217
  export const INIT_QUESTIONS = [
244
218
  ORM_QUESTION,
245
219
  DB_QUESTION,
246
220
  PACKAGE_MANAGER_QUESTION,
247
221
  ];
248
- /** `aventara init`'s questions over an existing ORM setup (S7): the ORM and database are read, not asked. */
249
222
  export const REUSE_QUESTIONS = [
250
223
  SERVICE_QUESTION,
251
224
  MODULE_QUESTION,
252
225
  PACKAGE_MANAGER_QUESTION,
253
226
  ];
254
- /** Every flag `aventara init` takes for a question, either way. */
255
227
  export const INIT_FLAG_QUESTIONS = [
256
228
  ORM_QUESTION,
257
229
  DB_QUESTION,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aventara/cli",
3
- "version": "0.1.0-pilot.1",
3
+ "version": "0.1.0-pilot.3",
4
4
  "license": "SEE LICENSE IN LICENSE",
5
5
  "description": "Scaffolds an Aventara server: `aventara new` for a new NestJS project, `aventara init` for an existing one.",
6
6
  "type": "module",
@@ -23,7 +23,7 @@
23
23
  },
24
24
  "scripts": {
25
25
  "prebuild": "node scripts/adapter-catalog.generator.ts",
26
- "build": "tsc -p tsconfig.json",
26
+ "build": "tsc -p tsconfig.json --removeComments --declaration false && tsc -p tsconfig.json --emitDeclarationOnly && node ../../scripts/build/declaration-comments.sanitizer.ts dist",
27
27
  "typecheck": "tsc -p tsconfig.typecheck.json --noEmit",
28
28
  "test": "vitest run --typecheck --config ../../vitest.config.mts --root .",
29
29
  "lint": "biome lint src scripts"