vyriy 0.3.8 → 0.4.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.
Files changed (174) hide show
  1. package/README.md +74 -172
  2. package/bin/vyriy.js +2 -2
  3. package/cli/args.js +29 -0
  4. package/cli/cli.d.ts +2 -2
  5. package/cli/cli.js +18 -64
  6. package/cli/index.d.ts +1 -1
  7. package/cli/index.js +1 -1
  8. package/cli/types.d.ts +12 -3
  9. package/commands/check-env.d.ts +2 -0
  10. package/commands/check-env.js +65 -0
  11. package/commands/create/index.d.ts +2 -0
  12. package/commands/create/index.js +121 -0
  13. package/commands/create/plan/index.d.ts +4 -0
  14. package/commands/create/plan/index.js +3 -0
  15. package/commands/create/plan/plan.d.ts +9 -0
  16. package/commands/create/plan/plan.js +34 -0
  17. package/commands/create/plan/question.d.ts +2 -0
  18. package/commands/create/plan/question.js +25 -0
  19. package/commands/create/plan/types.d.ts +14 -0
  20. package/commands/create/preset/api.d.ts +2 -0
  21. package/commands/create/preset/api.js +16 -0
  22. package/commands/create/preset/base.d.ts +2 -0
  23. package/commands/create/preset/base.js +195 -0
  24. package/commands/create/preset/gql.d.ts +2 -0
  25. package/commands/create/preset/gql.js +16 -0
  26. package/commands/create/preset/index.d.ts +12 -0
  27. package/commands/create/preset/index.js +14 -0
  28. package/commands/create/preset/library.d.ts +2 -0
  29. package/commands/create/preset/library.js +227 -0
  30. package/commands/create/preset/mfe.d.ts +2 -0
  31. package/commands/create/preset/mfe.js +16 -0
  32. package/commands/create/preset/rest.d.ts +2 -0
  33. package/commands/create/preset/rest.js +16 -0
  34. package/commands/create/preset/spa.d.ts +2 -0
  35. package/commands/create/preset/spa.js +16 -0
  36. package/commands/create/preset/ssg.d.ts +2 -0
  37. package/commands/create/preset/ssg.js +16 -0
  38. package/commands/create/preset/ssr.d.ts +2 -0
  39. package/commands/create/preset/ssr.js +16 -0
  40. package/commands/create/preset/types.d.ts +15 -0
  41. package/commands/create/prompt/conflict-strategy.d.ts +5 -0
  42. package/commands/create/prompt/conflict-strategy.js +22 -0
  43. package/commands/create/prompt/index.d.ts +7 -0
  44. package/commands/create/prompt/index.js +6 -0
  45. package/commands/create/prompt/preset.d.ts +4 -0
  46. package/commands/create/prompt/preset.js +11 -0
  47. package/commands/create/prompt/prompt.d.ts +2 -0
  48. package/commands/create/prompt/prompt.js +4 -0
  49. package/commands/create/prompt/provider.d.ts +2 -0
  50. package/commands/create/prompt/provider.js +13 -0
  51. package/commands/create/prompt/resolve-option.d.ts +6 -0
  52. package/commands/create/prompt/resolve-option.js +8 -0
  53. package/commands/create/prompt/scope.d.ts +2 -0
  54. package/commands/create/prompt/scope.js +2 -0
  55. package/commands/create/prompt/types.d.ts +4 -0
  56. package/commands/dist.d.ts +2 -0
  57. package/commands/dist.js +274 -0
  58. package/commands/help.d.ts +3 -0
  59. package/commands/help.js +24 -0
  60. package/commands/index.d.ts +5 -0
  61. package/commands/index.js +5 -0
  62. package/commands/types.d.ts +45 -0
  63. package/commands/version.d.ts +2 -0
  64. package/commands/version.js +6 -0
  65. package/package.json +341 -464
  66. package/checks/node/index.d.ts +0 -2
  67. package/checks/node/index.js +0 -1
  68. package/checks/node/node.d.ts +0 -2
  69. package/checks/node/node.js +0 -22
  70. package/checks/node/types.d.ts +0 -11
  71. package/checks/yarn/index.d.ts +0 -2
  72. package/checks/yarn/index.js +0 -1
  73. package/checks/yarn/types.d.ts +0 -7
  74. package/checks/yarn/yarn.d.ts +0 -2
  75. package/checks/yarn/yarn.js +0 -40
  76. package/cli/args/args.js +0 -38
  77. package/cli/args/index.d.ts +0 -2
  78. package/cli/args/index.js +0 -1
  79. package/cli/args/types.d.ts +0 -24
  80. package/commands/doctor/doctor.d.ts +0 -2
  81. package/commands/doctor/doctor.js +0 -9
  82. package/commands/doctor/index.d.ts +0 -2
  83. package/commands/doctor/index.js +0 -1
  84. package/commands/doctor/types.d.ts +0 -8
  85. package/commands/init/index.d.ts +0 -2
  86. package/commands/init/index.js +0 -1
  87. package/commands/init/init.d.ts +0 -2
  88. package/commands/init/init.js +0 -7
  89. package/commands/init/types.d.ts +0 -5
  90. package/commands/new/index.d.ts +0 -2
  91. package/commands/new/index.js +0 -1
  92. package/commands/new/new.d.ts +0 -3
  93. package/commands/new/new.js +0 -189
  94. package/commands/new/types.d.ts +0 -15
  95. package/doctor/checkCorepack.d.ts +0 -2
  96. package/doctor/checkCorepack.js +0 -24
  97. package/doctor/checkGit.d.ts +0 -2
  98. package/doctor/checkGit.js +0 -23
  99. package/doctor/checkNodeVersion.d.ts +0 -5
  100. package/doctor/checkNodeVersion.js +0 -24
  101. package/doctor/checkYarn.d.ts +0 -10
  102. package/doctor/checkYarn.js +0 -45
  103. package/doctor/createDoctorReport.d.ts +0 -2
  104. package/doctor/createDoctorReport.js +0 -17
  105. package/doctor/index.d.ts +0 -7
  106. package/doctor/index.js +0 -6
  107. package/doctor/printDoctorReport.d.ts +0 -2
  108. package/doctor/printDoctorReport.js +0 -42
  109. package/doctor/types.d.ts +0 -25
  110. package/file-plan/createFilePlan.d.ts +0 -4
  111. package/file-plan/createFilePlan.js +0 -29
  112. package/file-plan/index.d.ts +0 -4
  113. package/file-plan/index.js +0 -3
  114. package/file-plan/printFilePlan.d.ts +0 -2
  115. package/file-plan/printFilePlan.js +0 -44
  116. package/file-plan/types.d.ts +0 -12
  117. package/file-plan/writeFilePlan.d.ts +0 -2
  118. package/file-plan/writeFilePlan.js +0 -12
  119. package/index.d.ts +0 -11
  120. package/index.js +0 -11
  121. package/presets/agentsTemplate.d.ts +0 -1
  122. package/presets/agentsTemplate.js +0 -105
  123. package/presets/createProjectFiles.d.ts +0 -2
  124. package/presets/createProjectFiles.js +0 -408
  125. package/presets/index.d.ts +0 -2
  126. package/presets/index.js +0 -1
  127. package/presets/types.d.ts +0 -3
  128. package/project-plan/api/api.d.ts +0 -6
  129. package/project-plan/api/api.js +0 -44
  130. package/project-plan/api/index.d.ts +0 -2
  131. package/project-plan/api/index.js +0 -1
  132. package/project-plan/api/types.d.ts +0 -11
  133. package/project-plan/ci/ci.d.ts +0 -3
  134. package/project-plan/ci/ci.js +0 -20
  135. package/project-plan/ci/index.d.ts +0 -2
  136. package/project-plan/ci/index.js +0 -1
  137. package/project-plan/ci/types.d.ts +0 -6
  138. package/project-plan/create/create.d.ts +0 -2
  139. package/project-plan/create/create.js +0 -129
  140. package/project-plan/create/index.d.ts +0 -2
  141. package/project-plan/create/index.js +0 -1
  142. package/project-plan/create/types.d.ts +0 -13
  143. package/project-plan/index.d.ts +0 -6
  144. package/project-plan/index.js +0 -5
  145. package/project-plan/kind/index.d.ts +0 -2
  146. package/project-plan/kind/index.js +0 -1
  147. package/project-plan/kind/kind.d.ts +0 -2
  148. package/project-plan/kind/kind.js +0 -1
  149. package/project-plan/kind/types.d.ts +0 -2
  150. package/project-plan/print/index.d.ts +0 -2
  151. package/project-plan/print/index.js +0 -1
  152. package/project-plan/print/print.d.ts +0 -2
  153. package/project-plan/print/print.js +0 -47
  154. package/project-plan/print/types.d.ts +0 -2
  155. package/project-plan/types.d.ts +0 -46
  156. package/prompts/project-plan/index.d.ts +0 -2
  157. package/prompts/project-plan/index.js +0 -1
  158. package/prompts/project-plan/project-plan.d.ts +0 -2
  159. package/prompts/project-plan/project-plan.js +0 -194
  160. package/prompts/project-plan/types.d.ts +0 -18
  161. package/shared/commandExists.d.ts +0 -2
  162. package/shared/commandExists.js +0 -10
  163. package/shared/execCommand.d.ts +0 -2
  164. package/shared/execCommand.js +0 -7
  165. package/shared/fileExists.d.ts +0 -2
  166. package/shared/fileExists.js +0 -10
  167. package/shared/index.d.ts +0 -6
  168. package/shared/index.js +0 -5
  169. package/shared/runCommand.d.ts +0 -9
  170. package/shared/runCommand.js +0 -34
  171. package/shared/semver.d.ts +0 -1
  172. package/shared/semver.js +0 -4
  173. package/shared/types.d.ts +0 -12
  174. /package/cli/{args/args.d.ts → args.d.ts} +0 -0
package/README.md CHANGED
@@ -1,215 +1,117 @@
1
1
  # vyriy
2
2
 
3
- Interactive project master for calm cloud-ready applications.
3
+ Interactive project master for Vyriy projects.
4
4
 
5
5
  ## Purpose
6
6
 
7
- `vyriy` is the user-facing CLI entry point for the Vyriy ecosystem.
8
-
9
- The CLI checks the local environment, runs a small project wizard, creates a normalized `VyriyProjectPlan`, builds generated project files in memory, prints a file plan, and writes only files that are safe to create or explicitly allowed to overwrite.
10
-
11
- For a detailed map of CLI choices, diagrams, current generated files, and next
12
- generator targets, see [PROJECT-MASTER.md](./PROJECT-MASTER.md).
7
+ `vyriy` is a CLI tool that scaffolds new projects with Vyriy configuration
8
+ presets, validates the local environment, merges optional provider files, and
9
+ prepares packages for publishing.
13
10
 
14
11
  ## Install
15
12
 
16
- Install globally:
13
+ With npm:
17
14
 
18
15
  ```bash
19
- npm i -g vyriy
16
+ npm install -g vyriy
20
17
  ```
21
18
 
22
- Or run the package temporarily:
19
+ With Yarn:
23
20
 
24
21
  ```bash
25
- npx vyriy new my-app
26
- yarn dlx vyriy new my-app
22
+ yarn global add vyriy
27
23
  ```
28
24
 
29
- ## Commands
25
+ ## Usage
30
26
 
31
27
  ```bash
32
- vyriy new
33
- vyriy new my-app
34
- vyriy .
35
- vyriy init
36
- vyriy doctor
37
- vyriy --dry-run
38
- vyriy --yes
39
- vyriy --no-install
40
- vyriy --no-verify
41
- vyriy --install-only
42
- vyriy --verify
43
- vyriy --overwrite
44
- vyriy --skip-existing
45
- vyriy --help
46
- vyriy --version
28
+ vyriy [name] Create a new Vyriy project
29
+ vyriy . Initialise a new Vyriy project in the current directory
30
+ vyriy --help, -h Show help
31
+ vyriy --version, -v Show version
32
+ vyriy --check-env, -c Check local environment (Node.js and Yarn versions)
33
+ vyriy --dist, -d Prepare dist package metadata without publishing to npm
34
+ vyriy --dry-run Print the merged file plan without writing project files
35
+ vyriy --overwrite Overwrite existing generated paths
36
+ vyriy --skip-existing Leave existing generated paths untouched
37
+ vyriy --no-install Create files without installing dependencies
38
+ vyriy --no-verify Install dependencies without running checks
47
39
  ```
48
40
 
49
- ### `vyriy`
50
-
51
- Runs the same flow as `vyriy new`.
52
-
53
- ### `vyriy new [name]`
54
-
55
- Starts the project planning wizard, prints the project summary and file plan, writes generated files when no unresolved conflicts exist, installs dependencies, and runs generated project checks.
56
-
57
- If `name` is provided, it is used as the default project name and target directory.
58
-
59
- ### `vyriy init`
60
-
61
- Starts the same planning wizard for the current directory.
62
-
63
- The current directory name is used as the default project name.
64
-
65
- ### `vyriy .`
66
-
67
- Alias for `vyriy init`.
68
-
69
- ### `vyriy doctor`
70
-
71
- Runs environment checks only.
72
-
73
- Current checks:
74
-
75
- - Node.js `>=24`
76
- - Corepack availability
77
- - Yarn `>=4`
78
- - Git availability
79
-
80
- Node.js is fatal when unsupported. Yarn and Git are warnings so generation can continue without silently installing tools or initializing Git.
81
-
82
- ## Flags
83
-
84
- ### `--dry-run`
85
-
86
- Prints the doctor report, project summary, and file plan without writing files, installing dependencies, or running checks.
87
-
88
- ### `--no-install`
89
-
90
- Writes generated files but skips `yarn install` and `yarn check`.
91
-
92
- ### `--no-verify`
93
-
94
- Writes generated files and runs `yarn install`, but skips `yarn check`.
95
-
96
- ### `--install-only`
97
-
98
- Alias for `--no-verify`.
99
-
100
- ### `--verify`
101
-
102
- Explicitly enables `yarn check`. This is already the default unless `--no-install`, `--no-verify`, or `--install-only` is passed.
103
-
104
- ### `--yes`
105
-
106
- Uses default wizard answers and avoids prompts where possible. In non-interactive mode, the default preset is `empty` with no CI/CD provider. It does not overwrite existing files unless `--overwrite` is also passed.
107
-
108
- ### `--overwrite`
41
+ ## Commands
109
42
 
110
- Marks existing generated paths as overwrite candidates and writes them.
43
+ ### `create` (default)
111
44
 
112
- ### `--skip-existing`
45
+ The interactive wizard collects project details and writes the scaffold:
113
46
 
114
- Marks existing generated paths as skipped and leaves them untouched.
47
+ 1. Project name and description
48
+ 2. Target directory
49
+ 3. Preset selection
50
+ 4. Package scope (for package-based presets)
51
+ 5. CI/CD provider when the preset offers one
52
+ 6. Deploy provider when the preset offers one
53
+ 7. Confirmation (`y` to continue)
115
54
 
116
- `--overwrite` and `--skip-existing` cannot be used together.
55
+ The generated file set is built from the selected preset and then merged with
56
+ the selected CI/CD and deploy provider files. Later entries override earlier
57
+ entries with the same path.
117
58
 
118
- ## Wizard
59
+ When generated paths already exist, use `--overwrite` or `--skip-existing` to
60
+ avoid the interactive conflict prompt. Without either flag, `vyriy` asks whether
61
+ to overwrite existing files, skip them, or abort.
119
62
 
120
- The wizard collects:
63
+ ### `--check-env`
121
64
 
122
- - project name
123
- - target directory
124
- - package scope
125
- - description
126
- - project preset
127
- - API style for API-capable presets
128
- - CI/CD provider
129
- - infrastructure provider
130
- - confirmation
65
+ Validates Node.js and Yarn versions against the engine requirements declared in
66
+ `package.json`.
131
67
 
132
- After confirmation, the CLI prints the project plan, creates generated files in memory, builds a conflict-aware file plan, writes the accepted file plan, runs `yarn install`, and runs `yarn check`.
68
+ ### `--dist`
133
69
 
134
- Presets do not write to disk directly.
70
+ Prepares every package inside the `dist/` directory for npm publishing:
135
71
 
136
- Generated projects always include `AGENTS.md` based on the shared Vyriy package agent guide.
72
+ - Strips dev-only fields from `package.json`
73
+ - Builds the `exports` map from compiled JS files
74
+ - Copies README, LICENSE, and AGENTS.md
75
+ - Makes bin files executable
137
76
 
138
- ## Project Presets
77
+ ## Presets
139
78
 
140
- Supported presets:
79
+ Registered presets:
141
80
 
142
- - `empty`
143
- - `library`
144
- - `api`
145
- - `ssr`
146
- - `ssg`
147
- - `csr`
148
- - `fullstack`
149
- - `mfe`
81
+ | Key | Description |
82
+ | --------- | --------------------------------------------- |
83
+ | `base` | Minimal monorepo with config only |
84
+ | `library` | Workspaces layout with a sample React package |
150
85
 
151
- The preset is the concrete future generated setup. The project kind is the broader architecture category. The infrastructure choice is selected separately: Docker is the default local/container shape, while AWS selects CDK plus Lambda/API Gateway for API-capable presets.
86
+ Presets in progress:
152
87
 
153
- The `mfe` preset uses OpenMFE as the default MFE contract shape. There is no separate `openmfe` preset unless a future use case proves that split is useful.
88
+ | Key | Direction |
89
+ | ------ | ------------------------------ |
90
+ | `api` | Backend API project |
91
+ | `rest` | REST API project |
92
+ | `gql` | GraphQL API project |
93
+ | `ssr` | Server-side rendering project |
94
+ | `ssg` | Static site generation project |
95
+ | `spa` | Single-page application |
96
+ | `mfe` | Micro-frontend project |
154
97
 
155
- Workspace kinds describe deployment intent: `ui` is universal UI output, `api` is Docker-oriented, `lambda` is the AWS API runtime, `fargate` is an AWS container runtime, and `stack` contains AWS infrastructure.
98
+ Only registered presets are selectable by the wizard today. In-progress presets
99
+ exist as source modules and are expected to become selectable as their generated
100
+ project shape is finalized.
156
101
 
157
- Examples:
102
+ ## Providers
158
103
 
159
- - `csr` -> `csr`
160
- - `ssr` -> `ssr`
161
- - `ssg` -> `ssg`
162
- - `mfe` -> `mfe`
163
- - `fullstack` -> `fullstack`
104
+ Provider selections add files to the generated project.
164
105
 
165
- ## Public API
106
+ | Preset | CI/CD providers | Deploy providers |
107
+ | --------- | ------------------ | ---------------- |
108
+ | `base` | `gitlab`, `github` | none |
109
+ | `library` | `gitlab`, `github` | `docker` |
166
110
 
167
- The package exports the CLI runner, command helpers, doctor checks, file-plan utilities, generated preset files, prompt helper, and project-plan utilities.
111
+ ## API
168
112
 
169
113
  ```ts
170
- import {
171
- askProjectPlan,
172
- checkNodeVersion,
173
- checkYarnVersion,
174
- createDoctorReport,
175
- createFilePlan,
176
- createProjectFiles,
177
- createApiPlan,
178
- createCiPlan,
179
- createProjectPlanFromPreset,
180
- getProjectKindFromPreset,
181
- parseArgs,
182
- printProjectPlan,
183
- writeFilePlan,
184
- runDoctorCommand,
185
- runInitCommand,
186
- runNewCommand,
187
- runVyriyCli,
188
- } from 'vyriy';
189
- ```
190
-
191
- ## Project Plan
192
-
193
- The central model is `VyriyProjectPlan`.
194
-
195
- It includes:
114
+ import { cli } from 'vyriy';
196
115
 
197
- - project identity: `projectName`, `targetDirectory`, `packageScope`, `description`
198
- - architecture: `preset`, `projectKind`
199
- - selected features
200
- - CI/CD planning: enabled state, providers, and validation pipelines
201
- - API planning for API-capable presets: REST or GraphQL API style
202
- - future package plans
203
- - future workspace plans
204
-
205
- This model is intentionally useful before files are written. It gives generator steps a stable contract to build from.
206
-
207
- ## Current Non-Goals
208
-
209
- The CLI does not yet:
210
-
211
- - initialize Git
212
- - run `yarn install`
213
- - generate AWS CDK stacks
214
- - generate Docker files
215
- - generate React, OpenMFE, API, or service workspaces
116
+ await cli(process.argv.slice(2));
117
+ ```
package/bin/vyriy.js CHANGED
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env node
2
- import { runVyriyCli } from '../cli/index.js';
3
- await runVyriyCli(process.argv.slice(2));
2
+ import { cli } from '../cli/index.js';
3
+ await cli(process.argv.slice(2));
package/cli/args.js ADDED
@@ -0,0 +1,29 @@
1
+ export const parseArgs = (args) => {
2
+ if (args.includes('--help') || args.includes('-h')) {
3
+ return { type: 'help' };
4
+ }
5
+ if (args.includes('--version') || args.includes('-v')) {
6
+ return { type: 'version' };
7
+ }
8
+ if (args.includes('--dist') || args.includes('-d')) {
9
+ return { type: 'dist' };
10
+ }
11
+ if (args.includes('--check-env') || args.includes('-c')) {
12
+ return { type: 'check-env' };
13
+ }
14
+ const dryRun = args.includes('--dry-run');
15
+ const overwrite = args.includes('--overwrite');
16
+ const skipExisting = args.includes('--skip-existing');
17
+ const install = !args.includes('--no-install');
18
+ const verify = install && !args.includes('--no-verify');
19
+ const directory = args.find((arg) => !arg.startsWith('-')) ?? '';
20
+ return {
21
+ type: 'create',
22
+ directory,
23
+ dryRun,
24
+ overwrite,
25
+ skipExisting,
26
+ install,
27
+ verify,
28
+ };
29
+ };
package/cli/cli.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { RunVyriyCli } from './types.js';
2
- export declare const runVyriyCli: RunVyriyCli;
1
+ import type { Cli } from './types.js';
2
+ export declare const cli: Cli;
package/cli/cli.js CHANGED
@@ -1,74 +1,28 @@
1
- import { runDoctorCommand } from '../commands/doctor/index.js';
2
- import { runInitCommand } from '../commands/init/index.js';
3
- import { runNewCommand } from '../commands/new/index.js';
4
- import packageJson from '../package.json' with { type: 'json' };
5
- import { parseArgs } from './args/index.js';
6
- const helpText = `Vyriy Project Master
7
-
8
- Usage:
9
- vyriy new [name] Create a new Vyriy project
10
- vyriy init Initialize the current directory
11
- vyriy . Initialize the current directory
12
- vyriy doctor Check local environment
13
- vyriy --yes, -y Use defaults where possible (empty preset)
14
- vyriy --dry-run Print checks and file plan without writing
15
- vyriy --overwrite Overwrite existing generated paths
16
- vyriy --skip-existing Leave existing generated paths untouched
17
- vyriy --no-install Create files without installing dependencies
18
- vyriy --no-verify Install dependencies without running checks
19
- vyriy --install-only Alias for --no-verify
20
- vyriy --verify Explicitly enable generated project checks
21
- vyriy --help, -h Show help
22
- vyriy --version, -v Show version
23
-
24
- Examples:
25
- vyriy new my-app
26
- vyriy .
27
- vyriy init`;
28
- export const runVyriyCli = async (args = [], { output = console } = {}) => {
1
+ import { parseArgs } from './args.js';
2
+ import { help, version, dist, checkEnv, create } from '../commands/index.js';
3
+ export const cli = async (args = []) => {
29
4
  const command = parseArgs(args);
30
- let code = 0;
31
5
  switch (command.type) {
32
- case 'new':
33
- code = await runNewCommand({
34
- dryRun: command.dryRun,
35
- install: command.install,
36
- output,
37
- overwrite: command.overwrite,
38
- projectName: command.projectName,
39
- skipExisting: command.skipExisting,
40
- verify: command.verify,
41
- yes: command.yes,
42
- });
6
+ case 'help':
7
+ process.exitCode = await help();
43
8
  break;
44
- case 'init':
45
- code = await runInitCommand({
46
- dryRun: command.dryRun,
47
- install: command.install,
48
- output,
49
- overwrite: command.overwrite,
50
- skipExisting: command.skipExisting,
51
- verify: command.verify,
52
- yes: command.yes,
53
- });
9
+ case 'version':
10
+ process.exitCode = await version();
54
11
  break;
55
- case 'doctor': {
56
- const result = await runDoctorCommand({ output });
57
- code = result.code;
12
+ case 'dist':
13
+ process.exitCode = await dist();
58
14
  break;
59
- }
60
- case 'help':
61
- output.log(helpText);
15
+ case 'check-env': {
16
+ process.exitCode = await checkEnv();
62
17
  break;
63
- case 'version':
64
- output.log(packageJson.version);
18
+ }
19
+ case 'create':
20
+ process.exitCode = await create(command);
65
21
  break;
66
- case 'unknown':
67
- output.error(`Unknown command: ${command.command}\n`);
68
- output.error(helpText);
69
- code = 1;
22
+ default:
23
+ console.error(`Unknown command.\n`);
24
+ await help();
25
+ process.exitCode = 1;
70
26
  break;
71
27
  }
72
- process.exitCode = code;
73
- return code;
74
28
  };
package/cli/index.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- export * from './args/index.js';
1
+ export * from './args.js';
2
2
  export * from './cli.js';
3
3
  export type * from './types.js';
package/cli/index.js CHANGED
@@ -1,2 +1,2 @@
1
- export * from './args/index.js';
1
+ export * from './args.js';
2
2
  export * from './cli.js';
package/cli/types.d.ts CHANGED
@@ -1,4 +1,13 @@
1
- export type RunVyriyCliOptions = {
2
- readonly output?: Pick<typeof console, 'log' | 'error'>;
1
+ export type Command = {
2
+ readonly type: 'help' | 'version' | 'dist' | 'check-env';
3
+ } | {
4
+ readonly type: 'create';
5
+ readonly directory: string;
6
+ readonly dryRun: boolean;
7
+ readonly overwrite: boolean;
8
+ readonly skipExisting: boolean;
9
+ readonly install: boolean;
10
+ readonly verify: boolean;
3
11
  };
4
- export type RunVyriyCli = (args?: readonly string[], options?: RunVyriyCliOptions) => Promise<number>;
12
+ export type ParseArgs = (args: readonly string[]) => Command;
13
+ export type Cli = (args?: readonly string[]) => Promise<void>;
@@ -0,0 +1,2 @@
1
+ import { Command } from './types.js';
2
+ export declare const checkEnv: Command;
@@ -0,0 +1,65 @@
1
+ import { exec as processExec } from 'node:child_process';
2
+ import { promisify } from 'node:util';
3
+ import packageJson from '../package.json' with { type: 'json' };
4
+ const exec = promisify(processExec);
5
+ const node = () => {
6
+ const majorVersion = Number.parseInt(process.versions.node.split('.')[0]);
7
+ const minimumMajorVersion = Number.parseInt(packageJson.engines.node.match(/(\d+)/)?.[0]);
8
+ if (majorVersion && majorVersion >= minimumMajorVersion) {
9
+ return {
10
+ ok: true,
11
+ version: process.versions.node,
12
+ message: `Node.js ${majorVersion}`,
13
+ };
14
+ }
15
+ return {
16
+ ok: false,
17
+ version: process.versions.node,
18
+ message: `Vyriy requires Node.js >= ${minimumMajorVersion}.\n\nCurrent version: ${process.versions.node}\n\nPlease upgrade Node.js and run the command again.`,
19
+ };
20
+ };
21
+ const yarn = async () => {
22
+ const minimumMajorVersion = Number.parseInt(packageJson.packageManager.match(/(\d+)/)?.[0]);
23
+ let currentVersion;
24
+ try {
25
+ const { stdout } = await exec('yarn --version');
26
+ currentVersion = stdout.trim();
27
+ }
28
+ catch {
29
+ return {
30
+ ok: false,
31
+ message: `Yarn was not found.\n\nVyriy requires Yarn >= ${minimumMajorVersion}.\n\nTry:\n corepack enable\n yarn set version stable`,
32
+ };
33
+ }
34
+ const majorVersion = Number.parseInt(currentVersion.match(/(\d+)/)?.[0]);
35
+ if (majorVersion && majorVersion >= minimumMajorVersion) {
36
+ return {
37
+ ok: true,
38
+ message: `Yarn ${currentVersion}`,
39
+ };
40
+ }
41
+ return {
42
+ ok: false,
43
+ message: `Vyriy requires Yarn >= ${minimumMajorVersion}.\n\nCurrent version: ${currentVersion}\n\nTry:\n corepack enable\n yarn set version stable`,
44
+ };
45
+ };
46
+ export const checkEnv = async () => {
47
+ const nodeResults = node();
48
+ console.log('Check env:');
49
+ if (nodeResults.ok) {
50
+ console.log(' ', nodeResults.message);
51
+ }
52
+ else {
53
+ console.error(nodeResults.message);
54
+ return 1;
55
+ }
56
+ const yarnResults = await yarn();
57
+ if (yarnResults.ok) {
58
+ console.log(' ', yarnResults.message);
59
+ }
60
+ else {
61
+ console.error(yarnResults.message);
62
+ return 1;
63
+ }
64
+ return 0;
65
+ };
@@ -0,0 +1,2 @@
1
+ import { Create } from '../types.js';
2
+ export declare const create: Create;
@@ -0,0 +1,121 @@
1
+ import { cwd } from 'node:process';
2
+ import { basename, dirname, resolve } from 'node:path';
3
+ import { existsSync, mkdirSync, writeFileSync } from 'node:fs';
4
+ import { exec as processExec } from 'node:child_process';
5
+ import { promisify } from 'node:util';
6
+ import { checkEnv } from '../check-env.js';
7
+ import { plan } from './plan/index.js';
8
+ import { conflictStrategy as promptConflictStrategy } from './prompt/index.js';
9
+ import { presets } from './preset/index.js';
10
+ const exec = promisify(processExec);
11
+ const getProviderFiles = (providers, provider) => provider === undefined ? {} : (providers[provider] ?? {});
12
+ const isPresetName = (preset) => preset in presets;
13
+ const mergeFiles = (planOption) => {
14
+ if (!isPresetName(planOption.preset)) {
15
+ return undefined;
16
+ }
17
+ const preset = presets[planOption.preset].preset;
18
+ return {
19
+ ...preset.files(planOption),
20
+ ...getProviderFiles(preset.ci, planOption.ci),
21
+ ...getProviderFiles(preset.deploy, planOption.deploy),
22
+ };
23
+ };
24
+ const getSortedFileNames = (files) => Object.keys(files).sort();
25
+ const logFilePlan = (target, files) => {
26
+ console.log(`\nFile plan (${target}):`);
27
+ console.log(' ', getSortedFileNames(files).join('\n '));
28
+ };
29
+ const getExistingFiles = (target, files) => {
30
+ const existingFiles = getSortedFileNames(files).filter((file) => existsSync(resolve(target, file)));
31
+ if (existingFiles.length) {
32
+ console.log('\nExisting files found:\n');
33
+ existingFiles.forEach((file) => console.log(' ', file));
34
+ }
35
+ return existingFiles;
36
+ };
37
+ const resolveConflictStrategy = async (filesExist, overwrite, skipExisting) => {
38
+ if (!filesExist || overwrite || skipExisting) {
39
+ return { overwrite, skipExisting };
40
+ }
41
+ const strategy = await promptConflictStrategy();
42
+ if (strategy) {
43
+ return strategy;
44
+ }
45
+ console.error('\nCannot continue without a conflict strategy.\n');
46
+ console.error('Use one of:\n\n vyriy --overwrite\n vyriy --skip-existing\n vyriy --dry-run');
47
+ return undefined;
48
+ };
49
+ const writeFiles = (target, files, overwrite) => {
50
+ console.log(`\nFile creating (${target}):`);
51
+ getSortedFileNames(files).forEach((file) => {
52
+ if (!existsSync(resolve(target, file)) || overwrite) {
53
+ console.log(' ', file);
54
+ const filePath = resolve(target, file);
55
+ mkdirSync(dirname(filePath), { recursive: true });
56
+ writeFileSync(filePath, files[file]);
57
+ }
58
+ });
59
+ };
60
+ export const create = async (options) => {
61
+ const { directory, dryRun, overwrite, skipExisting, install, verify } = options;
62
+ const checkEnvCode = await checkEnv();
63
+ if (checkEnvCode) {
64
+ return checkEnvCode;
65
+ }
66
+ const cliPath = cwd();
67
+ let dirName = 'app';
68
+ let appPath = resolve(cliPath, dirName);
69
+ if (directory) {
70
+ if (directory === '.') {
71
+ dirName = basename(cliPath);
72
+ appPath = cliPath;
73
+ }
74
+ else {
75
+ dirName = directory;
76
+ appPath = resolve(cwd(), dirName);
77
+ }
78
+ }
79
+ const planOption = await plan(dirName, appPath);
80
+ if (planOption) {
81
+ const { target } = planOption;
82
+ const files = mergeFiles(planOption);
83
+ if (!files) {
84
+ console.error(`Unknown preset: ${planOption.preset}`);
85
+ return 1;
86
+ }
87
+ if (dryRun) {
88
+ logFilePlan(target, files);
89
+ return 0;
90
+ }
91
+ console.log(`\nFile checking (${target})...`);
92
+ const existingFiles = getExistingFiles(target, files);
93
+ const conflictStrategy = await resolveConflictStrategy(Boolean(existingFiles.length), overwrite, skipExisting);
94
+ if (!conflictStrategy) {
95
+ return 1;
96
+ }
97
+ writeFiles(target, files, conflictStrategy.overwrite);
98
+ if (install) {
99
+ console.log('Installing dependencies...');
100
+ await exec(`yarn --cwd ${target} set version berry`);
101
+ await exec(`yarn --cwd ${target} install`);
102
+ }
103
+ else {
104
+ console.log('Installing dependencies... SKIPPED');
105
+ console.log('Running checks... SKIPPED');
106
+ console.log('\nProject files were created.');
107
+ return 0;
108
+ }
109
+ if (verify) {
110
+ console.log('Running checks...');
111
+ await exec(`yarn --cwd ${target} check`);
112
+ }
113
+ else {
114
+ console.log('Running checks... SKIPPED');
115
+ console.log('\nProject files were created.');
116
+ return 0;
117
+ }
118
+ return 0;
119
+ }
120
+ return 1;
121
+ };
@@ -0,0 +1,4 @@
1
+ export * from './plan.js';
2
+ export * from '../prompt/index.js';
3
+ export * from './question.js';
4
+ export type * from './types.js';
@@ -0,0 +1,3 @@
1
+ export * from './plan.js';
2
+ export * from '../prompt/index.js';
3
+ export * from './question.js';
@@ -0,0 +1,9 @@
1
+ export declare const plan: (dirName: string, appPath: string) => Promise<{
2
+ name: string;
3
+ description: string;
4
+ target: string;
5
+ preset: "base" | "library";
6
+ scope: string | undefined;
7
+ ci: import("../preset/types.js").CiProvider | undefined;
8
+ deploy: import("../preset/types.js").DeployProvider | undefined;
9
+ } | undefined>;