@aventara/cli 0.1.0-pilot.4 → 1.0.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/CHANGELOG.md +345 -0
  2. package/README.md +55 -42
  3. package/dist/apply/conflict.confirmer.js +4 -4
  4. package/dist/cli.js +18 -14
  5. package/dist/command/command.parser.js +17 -10
  6. package/dist/plan/project.planner.js +2 -4
  7. package/dist/project/project.inspector.js +8 -8
  8. package/dist/run/command.runner.js +2 -0
  9. package/dist/run/init.orchestrator.js +40 -20
  10. package/dist/run/new.orchestrator.js +32 -14
  11. package/dist/run/step.reporter.js +87 -0
  12. package/dist/templates/docs.links.js +2 -1
  13. package/dist/templates/prisma7/prisma7.templates.js +26 -5
  14. package/dist/templates/template.registry.js +1 -1
  15. package/dist/wizard/answer.resolver.js +5 -5
  16. package/dist/wizard/readline.prompter.js +3 -3
  17. package/dist/wizard/wizard.questions.js +9 -9
  18. package/package.json +4 -3
  19. package/dist/apply/app-module.anchor.d.ts +0 -24
  20. package/dist/apply/conflict.confirmer.d.ts +0 -15
  21. package/dist/apply/e2e-spec.anchor.d.ts +0 -18
  22. package/dist/apply/main-cors.anchor.d.ts +0 -50
  23. package/dist/apply/manifest.merger.d.ts +0 -51
  24. package/dist/aventara.bin.d.ts +0 -2
  25. package/dist/catalog/adapter.catalog.generated.d.ts +0 -20
  26. package/dist/catalog/catalog-entry.interface.d.ts +0 -54
  27. package/dist/catalog/catalog.matcher.d.ts +0 -40
  28. package/dist/catalog/range.reader.d.ts +0 -11
  29. package/dist/cli.d.ts +0 -29
  30. package/dist/command/command.parser.d.ts +0 -38
  31. package/dist/node-version.guard.d.ts +0 -8
  32. package/dist/plan/project.planner.d.ts +0 -53
  33. package/dist/project/package-manager.detector.d.ts +0 -5
  34. package/dist/project/project.inspector.d.ts +0 -32
  35. package/dist/project/service.detector.d.ts +0 -40
  36. package/dist/project/source.scanner.d.ts +0 -16
  37. package/dist/run/command.runner.d.ts +0 -15
  38. package/dist/run/init.orchestrator.d.ts +0 -27
  39. package/dist/run/new.orchestrator.d.ts +0 -20
  40. package/dist/run/scaffold.committer.d.ts +0 -28
  41. package/dist/templates/docs.links.d.ts +0 -8
  42. package/dist/templates/prisma7/prisma7.templates.d.ts +0 -34
  43. package/dist/templates/template.registry.d.ts +0 -152
  44. package/dist/wizard/answer.resolver.d.ts +0 -47
  45. package/dist/wizard/readline.prompter.d.ts +0 -22
  46. package/dist/wizard/wizard.questions.d.ts +0 -120
@@ -1,28 +0,0 @@
1
- import type { CommandRunner } from "./command.runner.js";
2
- /**
3
- * pilot.3 — `aventara new` ends with one commit of the whole scaffold, the
4
- * install's lockfile included, under one fixed message. `.env` is not in it: the
5
- * scaffold's `.gitignore` lists it (Nest's own does too). `init` never commits:
6
- * the project is the developer's.
7
- *
8
- * Never a failure: where a commit cannot or should not be made, one line says why
9
- * and the run still succeeds —
10
- * - git is not installed;
11
- * - the directory `new` ran in is inside a git work tree already (a monorepo): the
12
- * project belongs to that repository, and gets no commit of its own;
13
- * - git has no `user.name` and `user.email` to commit as. `--skip-git` (passed to
14
- * `nest new`, which then initializes no repository) makes no commit and says
15
- * nothing.
16
- *
17
- * git runs through the one process seam, `CommandRunner`.
18
- */
19
- export declare const INITIAL_COMMIT_MESSAGE = "Initial Aventara Scaffold";
20
- /** Where `new` runs, as git sees it — read BEFORE `nest new` initializes a repository. */
21
- export type GitSurroundings = "no-git" | "inside-work-tree" | "outside";
22
- /** Whether git is installed, and whether `directory` lies in a work tree. */
23
- export declare function gitSurroundings(runner: CommandRunner, directory: string): Promise<GitSurroundings>;
24
- /**
25
- * Commits the project in `directory` as its first commit, or says why not: the
26
- * line to print, without the `aventara: ` prefix or the final period.
27
- */
28
- export declare function commitScaffold(runner: CommandRunner, directory: string, surroundings: GitSurroundings, enclosing: string): Promise<string>;
@@ -1,8 +0,0 @@
1
- /**
2
- * Where the public documentation lives: the one base every link the scaffold
3
- * writes into a project starts from. A placeholder until the docs domain is
4
- * settled; changing it changes only comments in the files the CLI writes.
5
- */
6
- export declare const DOCS_BASE_URL = "https://<docs-domain>";
7
- /** The documentation's rate-limiting section, linked from the scaffold's `main.ts`. */
8
- export declare const RATE_LIMITING_DOCS = "https://<docs-domain>/docs/limits-and-safety#rate-limiting";
@@ -1,34 +0,0 @@
1
- import type { PackageManifest } from "../../apply/manifest.merger.js";
2
- import type { ClientShape, ExportReference } from "../../project/service.detector.js";
3
- import { type OrmProjectFacts, type OrmScaffold, type ReuseInput, type ScaffoldInput } from "../template.registry.js";
4
- declare function scaffold(input: ScaffoldInput): OrmScaffold;
5
- declare function reuse(input: ReuseInput): OrmScaffold;
6
- declare function readProject(directory: string, manifest: PackageManifest): OrmProjectFacts;
7
- declare function clientShape(facts: OrmProjectFacts): ClientShape;
8
- export declare const PRISMA7_TEMPLATES: {
9
- readonly providers: {
10
- readonly sqlite: {
11
- readonly driverClass: "PrismaBetterSqlite3";
12
- readonly driverOptions: "{ url }";
13
- readonly databaseUrl: "file:./dev.db";
14
- readonly gitignore: readonly ["/dev.db*"];
15
- readonly nativeBuilds: readonly ["@prisma/engines", "better-sqlite3", "prisma"];
16
- };
17
- readonly postgresql: {
18
- readonly driverClass: "PrismaPg";
19
- readonly driverOptions: "{ connectionString: url }";
20
- readonly databaseUrl: "postgresql://johndoe:randompassword@localhost:5432/mydb?schema=public";
21
- readonly gitignore: readonly [];
22
- readonly nativeBuilds: readonly ["@prisma/engines", "prisma"];
23
- };
24
- };
25
- readonly scaffold: typeof scaffold;
26
- readonly readProject: typeof readProject;
27
- readonly clientShape: typeof clientShape;
28
- readonly newService: {
29
- readonly service: ExportReference;
30
- readonly module: ExportReference;
31
- };
32
- readonly reuse: typeof reuse;
33
- };
34
- export {};
@@ -1,152 +0,0 @@
1
- import type { PackageManifest } from "../apply/manifest.merger.js";
2
- import type { CatalogEntry, EntryId, ProviderOf } from "../catalog/catalog-entry.interface.js";
3
- import type { ClientShape, ExportReference } from "../project/service.detector.js";
4
- import type { PackageManager } from "../wizard/wizard.questions.js";
5
- /**
6
- * The registry is **total** in both directions, and both are checked before a
7
- * project is ever scaffolded:
8
- * - at compile time, over the generated catalog's literal type: an entry with no
9
- * template set, or a template set missing a provider its adapter declares, does
10
- * not type-check;
11
- * - at build time, by the catalog generator: a templates directory with no
12
- * adapter, or an adapter with no templates directory, fails the build.
13
- */
14
- /** What changes with the database provider an entry offers. */
15
- export type ProviderTemplate = {
16
- /** The driver adapter's class, constructed in the written ORM service. */
17
- readonly driverClass: string;
18
- /** The driver class's constructor argument, given the connection string as `url`. */
19
- readonly driverOptions: string;
20
- /** The `DATABASE_URL` line's value; a placeholder where it cannot be known. */
21
- readonly databaseUrl: string;
22
- /** `.gitignore` lines this provider's files need (a SQLite database file). */
23
- readonly gitignore: readonly string[];
24
- /** Packages whose install scripts pnpm must be allowed to run. */
25
- readonly nativeBuilds: readonly string[];
26
- };
27
- export type ModuleKind = "esm" | "cjs";
28
- /**
29
- * The entrypoint every scaffold mounts the protocol at: written into
30
- * `src/aventara.config.ts`, and tested by the e2e spec (pilot.1).
31
- */
32
- export declare const SCAFFOLD_ENTRYPOINT = "/api";
33
- /** What a template set is asked to scaffold. */
34
- export type ScaffoldInput = {
35
- readonly entry: CatalogEntry;
36
- /** One of `entry.providers`. */
37
- readonly provider: string;
38
- readonly moduleKind: ModuleKind;
39
- readonly packageManager: PackageManager;
40
- };
41
- /**
42
- * What an ORM's templates contribute to a project. Everything here is the
43
- * ORM's; what is Nest's (the start scripts, the anchored `app.module.ts` edit,
44
- * `AventaraModule`'s import) and what is Aventara's (its packages, the
45
- * `aventara:prepare` and `postinstall` script names) is the planner's.
46
- */
47
- export type OrmScaffold = {
48
- /** New, developer-owned files. */
49
- readonly files: readonly {
50
- readonly path: string;
51
- readonly content: string;
52
- }[];
53
- /** `.env` entries. */
54
- readonly env: Readonly<Record<string, string>>;
55
- readonly gitignore: readonly string[];
56
- readonly dependencies: Readonly<Record<string, string>>;
57
- readonly devDependencies: Readonly<Record<string, string>>;
58
- /** The command `aventara:prepare` runs. */
59
- readonly prepare: string;
60
- /** What the anchored `app.module.ts` edit adds: import lines, and `imports:` entries. */
61
- readonly appModule: {
62
- readonly imports: readonly string[];
63
- readonly entries: readonly string[];
64
- };
65
- readonly nativeBuilds: readonly string[];
66
- /** The ORM's next steps, after the install and before the server starts. */
67
- readonly nextSteps: readonly string[];
68
- };
69
- /**
70
- * What a project's existing ORM setup states, read by the entry's templates — the
71
- * ORM's own file layout is template knowledge; judging it against the catalog is
72
- * the matcher's (`catalog.matcher.ts`).
73
- */
74
- export type OrmProjectFacts = {
75
- /** The schema the generate step reads, relative to the project root. */
76
- readonly schema: string;
77
- readonly provider: string | undefined;
78
- readonly generator: string | undefined;
79
- /** The generated client's directory, relative to the project root. */
80
- readonly clientOutput: string | undefined;
81
- /** The driver-adapter packages the project depends on. */
82
- readonly drivers: readonly string[];
83
- };
84
- /** Reusing a project's ORM setup: its schema, its output, its service. */
85
- export type ReuseInput = {
86
- readonly entry: CatalogEntry;
87
- readonly facts: OrmProjectFacts & {
88
- readonly provider: string;
89
- readonly clientOutput: string;
90
- };
91
- readonly moduleKind: ModuleKind;
92
- readonly packageManager: PackageManager;
93
- /** The developer's service, or the template's new one when it is to be written. */
94
- readonly service: ExportReference & {
95
- readonly clientMember?: string;
96
- };
97
- readonly module: ExportReference;
98
- /** Whether `service` and `module` are the template's new file, to be written. */
99
- readonly writeService: boolean;
100
- /** Where the discovery artifact goes, relative to the project root. */
101
- readonly artifact: string;
102
- };
103
- export type TemplateSet<I extends EntryId> = {
104
- readonly providers: {
105
- readonly [P in ProviderOf<I>]: ProviderTemplate;
106
- };
107
- readonly scaffold: (input: ScaffoldInput) => OrmScaffold;
108
- /** Reads an existing setup's facts; `undefined` when there is none to read. */
109
- readonly readProject: (directory: string, manifest: PackageManifest) => OrmProjectFacts;
110
- /** How the developer's service is recognised in their source. */
111
- readonly clientShape: (facts: OrmProjectFacts) => ClientShape;
112
- /** The service init writes when the project has none: its file and names. */
113
- readonly newService: {
114
- readonly service: ExportReference;
115
- readonly module: ExportReference;
116
- };
117
- /** A project with the ORM already set up: no ORM file written or edited. */
118
- readonly reuse: (input: ReuseInput) => OrmScaffold;
119
- };
120
- export type TemplateRegistry = {
121
- readonly [I in EntryId]: TemplateSet<I>;
122
- };
123
- export declare const TEMPLATE_REGISTRY: {
124
- readonly prisma7: {
125
- readonly providers: {
126
- readonly sqlite: {
127
- readonly driverClass: "PrismaBetterSqlite3";
128
- readonly driverOptions: "{ url }";
129
- readonly databaseUrl: "file:./dev.db";
130
- readonly gitignore: readonly ["/dev.db*"];
131
- readonly nativeBuilds: readonly ["@prisma/engines", "better-sqlite3", "prisma"];
132
- };
133
- readonly postgresql: {
134
- readonly driverClass: "PrismaPg";
135
- readonly driverOptions: "{ connectionString: url }";
136
- readonly databaseUrl: "postgresql://johndoe:randompassword@localhost:5432/mydb?schema=public";
137
- readonly gitignore: readonly [];
138
- readonly nativeBuilds: readonly ["@prisma/engines", "prisma"];
139
- };
140
- };
141
- readonly scaffold: (input: ScaffoldInput) => OrmScaffold;
142
- readonly readProject: (directory: string, manifest: PackageManifest) => OrmProjectFacts;
143
- readonly clientShape: (facts: OrmProjectFacts) => ClientShape;
144
- readonly newService: {
145
- readonly service: ExportReference;
146
- readonly module: ExportReference;
147
- };
148
- readonly reuse: (input: ReuseInput) => OrmScaffold;
149
- };
150
- };
151
- /** The template set for `entry` — every catalog entry has one (checked at build). */
152
- export declare function templatesFor(entry: CatalogEntry): TemplateSet<EntryId>;
@@ -1,47 +0,0 @@
1
- import type { AnyWizardQuestion, QuestionId, WizardAnswers, WizardContext } from "./wizard.questions.js";
2
- /**
3
- * 1. **its flag**, validated by the question (a bad value is refused, never
4
- * re-asked);
5
- * 2. **the only choice there is**: shown on a terminal with no keypress;
6
- * 3. **`--yes`**: the question's default, when it has one;
7
- * 4. **the prompt**, when someone can answer (stdin is a terminal);
8
- * 5. otherwise the question is **unanswered**, and once every question has been
9
- * tried the run refuses in one sentence naming exactly those flags.
10
- *
11
- * `--yes` comes before the prompt because it means "accept each unanswered
12
- * question's default", on a terminal as much as anywhere; a question with no
13
- * default (`new`'s `<name>`) is still asked on a terminal.
14
- */
15
- /** The seam to a person: `node:readline/promises` on a terminal, a script in specs. */
16
- export type Prompter = {
17
- /** Whether someone can answer: stdin is a terminal. */
18
- readonly interactive: boolean;
19
- /** Asks once; resolves with what was typed, `""` for Enter alone. */
20
- readonly ask: (request: PromptRequest) => Promise<string>;
21
- /** Says one line without asking. */
22
- readonly say: (line: string) => void;
23
- };
24
- export type PromptRequest = {
25
- readonly label: string;
26
- /** The accepted values, shown with the label; absent for free text. */
27
- readonly choices?: readonly string[];
28
- readonly defaultValue?: string;
29
- };
30
- /** Nobody can answer and some questions are unanswered. A refusal: one sentence. */
31
- export declare class UnansweredQuestionsError extends Error {
32
- readonly name = "UnansweredQuestionsError";
33
- }
34
- export type AnswerSources = {
35
- /** Raw answers from the command line, by question. */
36
- readonly given: Readonly<Partial<Record<QuestionId, string>>>;
37
- readonly yes: boolean;
38
- readonly prompter: Prompter;
39
- readonly context: Omit<WizardContext, "answered">;
40
- };
41
- /**
42
- * Settles `questions` in order, each later question seeing the earlier answers.
43
- *
44
- * @throws WizardAnswerError when a flag's value is not an answer.
45
- * @throws UnansweredQuestionsError when nobody can answer and something is unanswered.
46
- */
47
- export declare function resolveAnswers(questions: readonly AnyWizardQuestion[], sources: AnswerSources): Promise<Partial<WizardAnswers>>;
@@ -1,22 +0,0 @@
1
- import type { Readable, Writable } from "node:stream";
2
- import type { Prompter } from "./answer.resolver.js";
3
- /**
4
- * Lines are **queued** as they arrive and handed to questions in order. A terminal
5
- * delivers whatever was typed ahead of a question — and a script piping answers
6
- * into a pseudo-terminal delivers them all at once — and readline drops a line
7
- * nobody is waiting for. Measured: with `readline/promises`' `question`, three
8
- * answers piped into `script(1)` reached the first question only.
9
- */
10
- /** Input ended while a question was open: the person closed the wizard. A refusal. */
11
- export declare class WizardCancelledError extends Error {
12
- readonly name = "WizardCancelledError";
13
- }
14
- export type ReadlinePrompter = Prompter & {
15
- readonly close: () => void;
16
- };
17
- export declare function createReadlinePrompter(streams: {
18
- readonly input: Readable & {
19
- readonly isTTY?: boolean;
20
- };
21
- readonly output: Writable;
22
- }): ReadlinePrompter;
@@ -1,120 +0,0 @@
1
- import type { AdapterCatalog, CatalogEntry } from "../catalog/catalog-entry.interface.js";
2
- import { type ExportReference, type ServiceScan } from "../project/service.detector.js";
3
- /**
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.
7
- *
8
- * Choices that are an adapter's facts — which ORMs and majors exist, which
9
- * databases one supports — come from the generated catalog, never from a literal
10
- * here.
11
- */
12
- /** Yarn is not supported. */
13
- export declare const PACKAGE_MANAGERS: readonly ["npm", "pnpm"];
14
- export type PackageManager = (typeof PACKAGE_MANAGERS)[number];
15
- /** What the wizard settles. */
16
- export type WizardAnswers = {
17
- /** `new`'s project directory. */
18
- readonly name: string;
19
- /** The ORM and major, as the catalog entry that serves it. */
20
- readonly orm: CatalogEntry;
21
- /** One of `orm`'s providers. */
22
- readonly db: string;
23
- readonly packageManager: PackageManager;
24
- /** `init` over an existing ORM setup: the developer's service. */
25
- readonly service: ServiceChoice;
26
- /** The Nest module that provides and exports it. */
27
- readonly module: ExportReference;
28
- };
29
- /** The service `AventaraModule` is given, or the template's new one to be written. */
30
- export type ServiceChoice = ExportReference & {
31
- /** Set when the service holds its client in a member instead of extending it. */
32
- readonly clientMember?: string;
33
- /** The template's new service file, written because the project has none. */
34
- readonly isNew: boolean;
35
- };
36
- export type QuestionId = keyof WizardAnswers;
37
- /** What the scan of the developer's source found, for the service questions. */
38
- export type ServiceContext = {
39
- readonly scan: ServiceScan;
40
- /** The ORM's client class, as the scan looked for it. */
41
- readonly clientClass: string;
42
- /** The service and module init writes when the project has none. */
43
- readonly newService: ExportReference;
44
- readonly newModule: ExportReference;
45
- /** Whether a file already stands where the new service would be written. */
46
- readonly newServiceFileExists: boolean;
47
- /** How the ORM is named to the person, e.g. `Prisma`. */
48
- readonly label: string;
49
- };
50
- /** What a question may consult: the catalog, what was detected, what is already answered. */
51
- export type WizardContext = {
52
- readonly catalog: AdapterCatalog;
53
- readonly detectedPackageManager: PackageManager;
54
- readonly answered: Partial<WizardAnswers>;
55
- /** Present for `init` over an existing ORM setup. */
56
- readonly services?: ServiceContext;
57
- };
58
- export type Choice = {
59
- /** What the flag takes and the prompt accepts, e.g. `prisma7`. */
60
- readonly value: string;
61
- /** How it is shown, e.g. `Prisma 7`. */
62
- readonly label: string;
63
- };
64
- /** An answer the question cannot accept. A refusal: one sentence. */
65
- export declare class WizardAnswerError extends Error {
66
- readonly name = "WizardAnswerError";
67
- }
68
- export type WizardQuestion<K extends QuestionId> = {
69
- readonly id: K;
70
- /** How the command line answers it: a `--flag <value>`, or the positional `<name>`. */
71
- readonly flag: string;
72
- /** The prompt's label. */
73
- readonly label: string;
74
- /** How the usage text shows its value; `<value>` when absent. */
75
- readonly placeholder?: string;
76
- /** A question whose choices depend on an earlier answer is not asked before it. */
77
- readonly after?: QuestionId;
78
- /** The answers on offer, or `undefined` for free text. */
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[];
85
- /** The answer `--yes` (or Enter at the prompt) takes; `undefined` when there is none. */
86
- readonly defaultFor: (context: WizardContext) => string | undefined;
87
- /** @throws WizardAnswerError when `raw` is not an answer to this question. */
88
- readonly parse: (raw: string, context: WizardContext) => WizardAnswers[K];
89
- /** How a settled answer is shown back. */
90
- readonly describe: (answer: WizardAnswers[K]) => string;
91
- };
92
- export type AnyWizardQuestion = {
93
- readonly [K in QuestionId]: WizardQuestion<K>;
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;
100
- export declare const NAME_QUESTION: WizardQuestion<"name">;
101
- /**
102
- * The prompt keeps the family-then-major order; every answer is an alias.
103
- */
104
- export declare const ORM_QUESTION: WizardQuestion<"orm">;
105
- export declare const DB_QUESTION: WizardQuestion<"db">;
106
- export declare const PACKAGE_MANAGER_QUESTION: WizardQuestion<"packageManager">;
107
- export declare const SERVICE_QUESTION: WizardQuestion<"service">;
108
- /** The module that provides and exports the chosen service (or is @Global). */
109
- export declare const MODULE_QUESTION: WizardQuestion<"module">;
110
- /** `aventara new`'s questions, in the order they are asked. */
111
- export declare const NEW_QUESTIONS: readonly [WizardQuestion<"name">, WizardQuestion<"orm">, WizardQuestion<"db">, WizardQuestion<"packageManager">];
112
- /** `aventara init`'s questions when the project has no ORM, in order. */
113
- export declare const INIT_QUESTIONS: readonly [WizardQuestion<"orm">, WizardQuestion<"db">, WizardQuestion<"packageManager">];
114
- /**
115
- * `aventara init`'s questions over an existing ORM setup: the ORM and database are
116
- * read, not asked.
117
- */
118
- export declare const REUSE_QUESTIONS: readonly [WizardQuestion<"service">, WizardQuestion<"module">, WizardQuestion<"packageManager">];
119
- /** Every flag `aventara init` takes for a question, either way. */
120
- export declare const INIT_FLAG_QUESTIONS: readonly [WizardQuestion<"orm">, WizardQuestion<"db">, WizardQuestion<"service">, WizardQuestion<"module">, WizardQuestion<"packageManager">];