vyriy 0.3.2 → 0.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +59 -22
- package/README.md +44 -8
- package/cli/args/args.js +21 -10
- package/cli/args/types.d.ts +11 -1
- package/cli/cli.js +16 -2
- package/commands/doctor/doctor.js +5 -16
- package/commands/doctor/types.d.ts +2 -2
- package/commands/new/new.d.ts +2 -1
- package/commands/new/new.js +104 -18
- package/commands/new/types.d.ts +6 -0
- package/doctor/checkCorepack.d.ts +2 -0
- package/doctor/checkCorepack.js +24 -0
- package/doctor/checkGit.d.ts +2 -0
- package/doctor/checkGit.js +23 -0
- package/doctor/checkNodeVersion.d.ts +5 -0
- package/doctor/checkNodeVersion.js +24 -0
- package/doctor/checkYarn.d.ts +10 -0
- package/doctor/checkYarn.js +45 -0
- package/doctor/createDoctorReport.d.ts +2 -0
- package/doctor/createDoctorReport.js +17 -0
- package/doctor/index.d.ts +7 -0
- package/doctor/index.js +6 -0
- package/doctor/printDoctorReport.d.ts +2 -0
- package/doctor/printDoctorReport.js +42 -0
- package/doctor/types.d.ts +25 -0
- package/file-plan/createFilePlan.d.ts +4 -0
- package/file-plan/createFilePlan.js +29 -0
- package/file-plan/index.d.ts +4 -0
- package/file-plan/index.js +3 -0
- package/file-plan/printFilePlan.d.ts +2 -0
- package/file-plan/printFilePlan.js +44 -0
- package/file-plan/types.d.ts +12 -0
- package/file-plan/writeFilePlan.d.ts +2 -0
- package/file-plan/writeFilePlan.js +12 -0
- package/index.d.ts +4 -1
- package/index.js +4 -1
- package/package.json +191 -1
- package/presets/agentsTemplate.d.ts +1 -0
- package/presets/agentsTemplate.js +105 -0
- package/presets/createProjectFiles.d.ts +2 -0
- package/presets/createProjectFiles.js +179 -0
- package/presets/index.d.ts +2 -0
- package/presets/index.js +1 -0
- package/presets/types.d.ts +3 -0
- package/project-plan/ci/ci.d.ts +1 -1
- package/project-plan/ci/ci.js +3 -2
- package/project-plan/create/create.js +9 -4
- package/project-plan/types.d.ts +5 -5
- package/prompts/project-plan/project-plan.js +36 -8
- package/shared/commandExists.d.ts +2 -0
- package/shared/commandExists.js +10 -0
- package/shared/execCommand.d.ts +2 -0
- package/shared/execCommand.js +7 -0
- package/shared/fileExists.d.ts +2 -0
- package/shared/fileExists.js +10 -0
- package/shared/index.d.ts +5 -0
- package/shared/index.js +4 -0
- package/shared/semver.d.ts +1 -0
- package/shared/semver.js +4 -0
- package/shared/types.d.ts +5 -0
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { agentsTemplate } from './agentsTemplate.js';
|
|
2
|
+
const json = (value) => `${JSON.stringify(value, null, 2)}\n`;
|
|
3
|
+
const createRootPackageJson = ({ description, packageScope, projectName, }) => ({
|
|
4
|
+
path: 'package.json',
|
|
5
|
+
content: json({
|
|
6
|
+
name: `${packageScope}/${projectName}`,
|
|
7
|
+
version: '0.1.0',
|
|
8
|
+
description,
|
|
9
|
+
private: true,
|
|
10
|
+
type: 'module',
|
|
11
|
+
packageManager: 'yarn@4.14.1',
|
|
12
|
+
engines: {
|
|
13
|
+
node: '>=24.0.0',
|
|
14
|
+
},
|
|
15
|
+
scripts: {
|
|
16
|
+
lint: 'eslint .',
|
|
17
|
+
test: 'jest --coverage=false',
|
|
18
|
+
build: 'tsc --pretty false',
|
|
19
|
+
deploy: 'echo "Deploy is not configured yet."',
|
|
20
|
+
smoke: 'echo "Smoke checks are not configured yet."',
|
|
21
|
+
e2e: 'echo "E2E checks are not configured yet."',
|
|
22
|
+
},
|
|
23
|
+
devDependencies: {},
|
|
24
|
+
workspaces: [
|
|
25
|
+
'packages/*',
|
|
26
|
+
'workspaces/*',
|
|
27
|
+
],
|
|
28
|
+
}),
|
|
29
|
+
});
|
|
30
|
+
const createPackageManifest = ({ packageScope, workspaceName, }) => ({
|
|
31
|
+
path: `packages/${workspaceName}/package.json`,
|
|
32
|
+
content: json({
|
|
33
|
+
name: `${packageScope}/${workspaceName}`,
|
|
34
|
+
version: '0.1.0',
|
|
35
|
+
private: true,
|
|
36
|
+
type: 'module',
|
|
37
|
+
main: 'index.js',
|
|
38
|
+
}),
|
|
39
|
+
});
|
|
40
|
+
const createPackageFiles = (plan, packagePlan) => [
|
|
41
|
+
createPackageManifest({
|
|
42
|
+
packageScope: plan.packageScope,
|
|
43
|
+
workspaceName: packagePlan.name,
|
|
44
|
+
}),
|
|
45
|
+
{
|
|
46
|
+
path: `packages/${packagePlan.name}/README.md`,
|
|
47
|
+
content: `# ${plan.packageScope}/${packagePlan.name}\n\n${plan.description}\n`,
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
path: `packages/${packagePlan.name}/index.ts`,
|
|
51
|
+
content: packagePlan.kind === 'stack' ? "export * from './stack.js';\n" : "export type * from './types.js';\n",
|
|
52
|
+
},
|
|
53
|
+
...(packagePlan.kind === 'stack'
|
|
54
|
+
? [
|
|
55
|
+
{
|
|
56
|
+
path: `packages/${packagePlan.name}/stack.ts`,
|
|
57
|
+
content: 'export type StackName = string;\n',
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
path: `packages/${packagePlan.name}/stack.test.ts`,
|
|
61
|
+
content: "import { describe, expect, it } from '@jest/globals';\n\ndescribe('stack', () => {\n it('has a test harness', () => {\n expect(true).toBe(true);\n });\n});\n",
|
|
62
|
+
},
|
|
63
|
+
]
|
|
64
|
+
: [
|
|
65
|
+
{
|
|
66
|
+
path: `packages/${packagePlan.name}/types.ts`,
|
|
67
|
+
content: 'export type PackageName = string;\n',
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
path: `packages/${packagePlan.name}/${packagePlan.name}.test.ts`,
|
|
71
|
+
content: "import { describe, expect, it } from '@jest/globals';\n\ndescribe('package', () => {\n it('has a test harness', () => {\n expect(true).toBe(true);\n });\n});\n",
|
|
72
|
+
},
|
|
73
|
+
]),
|
|
74
|
+
];
|
|
75
|
+
const createWorkspaceFiles = (plan, workspacePlan) => [
|
|
76
|
+
{
|
|
77
|
+
path: `workspaces/${workspacePlan.name}/package.json`,
|
|
78
|
+
content: json({
|
|
79
|
+
name: `${plan.packageScope}/${workspacePlan.name}-workspace`,
|
|
80
|
+
version: '0.1.0',
|
|
81
|
+
private: true,
|
|
82
|
+
type: 'module',
|
|
83
|
+
main: 'index.js',
|
|
84
|
+
}),
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
path: `workspaces/${workspacePlan.name}/index.ts`,
|
|
88
|
+
content: 'export type WorkspaceName = string;\n',
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
path: `workspaces/${workspacePlan.name}/${workspacePlan.name}.test.ts`,
|
|
92
|
+
content: "import { describe, expect, it } from '@jest/globals';\n\ndescribe('workspace', () => {\n it('has a test harness', () => {\n expect(true).toBe(true);\n });\n});\n",
|
|
93
|
+
},
|
|
94
|
+
];
|
|
95
|
+
const shouldCreateStylelintConfig = (plan) => plan.features.some((feature) => [
|
|
96
|
+
'react',
|
|
97
|
+
'webpack',
|
|
98
|
+
].includes(feature));
|
|
99
|
+
export const createProjectFiles = (plan) => [
|
|
100
|
+
createRootPackageJson(plan),
|
|
101
|
+
{
|
|
102
|
+
path: 'README.md',
|
|
103
|
+
content: `# ${plan.projectName}\n\n${plan.description}\n`,
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
path: 'doc.mdx',
|
|
107
|
+
content: "import { Meta, Markdown } from '@storybook/addon-docs/blocks';\nimport ReadMe from './README.md?raw';\n\n<Meta title=\"Project/README\" />\n\n<Markdown>{ReadMe}</Markdown>\n",
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
path: 'AGENTS.md',
|
|
111
|
+
content: agentsTemplate,
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
path: '.editorconfig',
|
|
115
|
+
content: 'root = true\n\n[*]\ncharset = utf-8\nend_of_line = lf\ninsert_final_newline = true\nindent_style = space\nindent_size = 2\n',
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
path: '.gitignore',
|
|
119
|
+
content: 'node_modules/\ndist/\ncoverage/\n.yarn/cache/\n.env\n',
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
path: '.npmrc',
|
|
123
|
+
content: 'engine-strict=true\n',
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
path: '.nvmrc',
|
|
127
|
+
content: '24\n',
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
path: '.yarnrc.yml',
|
|
131
|
+
content: 'nodeLinker: node-modules\n',
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
path: 'yarn.lock',
|
|
135
|
+
content: '',
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
path: 'tsconfig.json',
|
|
139
|
+
content: json({
|
|
140
|
+
extends: '@vyriy/typescript-config/index.json',
|
|
141
|
+
compilerOptions: {
|
|
142
|
+
noEmit: false,
|
|
143
|
+
},
|
|
144
|
+
include: [
|
|
145
|
+
'packages/**/*.ts',
|
|
146
|
+
'packages/**/*.tsx',
|
|
147
|
+
'workspaces/**/*.ts',
|
|
148
|
+
'workspaces/**/*.tsx',
|
|
149
|
+
'*.ts',
|
|
150
|
+
],
|
|
151
|
+
}),
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
path: 'prettier.config.ts',
|
|
155
|
+
content: "export { default } from '@vyriy/prettier-config';\n",
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
path: '.prettierignore',
|
|
159
|
+
content: 'node_modules\ndist\ncoverage\nstorybook-static\n',
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
path: 'eslint.config.ts',
|
|
163
|
+
content: "export { default } from '@vyriy/eslint-config';\n",
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
path: 'jest.config.ts',
|
|
167
|
+
content: "export { default } from '@vyriy/jest-config';\n",
|
|
168
|
+
},
|
|
169
|
+
...(shouldCreateStylelintConfig(plan)
|
|
170
|
+
? [
|
|
171
|
+
{
|
|
172
|
+
path: 'stylelint.config.ts',
|
|
173
|
+
content: "export { default } from '@vyriy/stylelint-config';\n",
|
|
174
|
+
},
|
|
175
|
+
]
|
|
176
|
+
: []),
|
|
177
|
+
...plan.packages.flatMap((packagePlan) => createPackageFiles(plan, packagePlan)),
|
|
178
|
+
...plan.workspaces.flatMap((workspacePlan) => createWorkspaceFiles(plan, workspacePlan)),
|
|
179
|
+
];
|
package/presets/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './createProjectFiles.js';
|
package/project-plan/ci/ci.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { CreateCiPlan } from './types.js';
|
|
2
|
-
export declare const defaultValidationPipelines: readonly ["install", "
|
|
2
|
+
export declare const defaultValidationPipelines: readonly ["install", "lint", "test", "build", "deploy", "smoke", "e2e"];
|
|
3
3
|
export declare const createCiPlan: CreateCiPlan;
|
package/project-plan/ci/ci.js
CHANGED
|
@@ -6,9 +6,10 @@ const baseFeatures = [
|
|
|
6
6
|
'eslint',
|
|
7
7
|
'prettier',
|
|
8
8
|
'jest',
|
|
9
|
+
'storybook',
|
|
9
10
|
];
|
|
10
11
|
const presetFeatures = {
|
|
11
|
-
library: ['react'
|
|
12
|
+
library: ['react'],
|
|
12
13
|
api: [],
|
|
13
14
|
'react-csr': ['react', 'webpack'],
|
|
14
15
|
'react-ssr': ['react', 'webpack'],
|
|
@@ -23,7 +24,11 @@ const presetFeatures = {
|
|
|
23
24
|
'bff',
|
|
24
25
|
],
|
|
25
26
|
fullstack: ['react', 'webpack'],
|
|
26
|
-
'aws-serverless': [
|
|
27
|
+
'aws-serverless': [
|
|
28
|
+
'aws-cdk',
|
|
29
|
+
'lambda',
|
|
30
|
+
'apigateway',
|
|
31
|
+
],
|
|
27
32
|
empty: [],
|
|
28
33
|
};
|
|
29
34
|
const packagePlans = {
|
|
@@ -71,7 +76,7 @@ const packagePlans = {
|
|
|
71
76
|
],
|
|
72
77
|
'aws-serverless': [
|
|
73
78
|
{ name: 'api', kind: 'api', publishable: false },
|
|
74
|
-
{ name: '
|
|
79
|
+
{ name: 'stack', kind: 'stack', publishable: false },
|
|
75
80
|
],
|
|
76
81
|
empty: [],
|
|
77
82
|
};
|
|
@@ -105,7 +110,7 @@ const workspacePlans = {
|
|
|
105
110
|
{ name: 'web', kind: 'web' },
|
|
106
111
|
{ name: 'api', kind: 'api' },
|
|
107
112
|
],
|
|
108
|
-
'aws-serverless': [{ name: '
|
|
113
|
+
'aws-serverless': [{ name: 'stack', kind: 'stack' }],
|
|
109
114
|
empty: [],
|
|
110
115
|
};
|
|
111
116
|
const uniqueFeatures = (features) => [...new Set(features)];
|
package/project-plan/types.d.ts
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
export type VyriyProjectKind = 'library' | 'api' | 'csr' | 'ssr' | 'ssg' | 'mfe' | 'fullstack' | 'aws-serverless' | 'empty';
|
|
2
2
|
export type VyriyPreset = 'library' | 'api' | 'react-csr' | 'react-ssr' | 'react-ssg' | 'mfe' | 'openmfe' | 'mfe-bff' | 'openmfe-bff' | 'fullstack' | 'aws-serverless' | 'empty';
|
|
3
|
-
export type VyriyFeature = 'typescript' | 'eslint' | 'prettier' | 'jest' | 'rest-api' | 'graphql-api' | 'react' | 'storybook' | 'webpack' | 'docker' | 'aws-cdk' | '
|
|
3
|
+
export type VyriyFeature = 'typescript' | 'eslint' | 'prettier' | 'jest' | 'rest-api' | 'graphql-api' | 'react' | 'storybook' | 'webpack' | 'docker' | 'aws-cdk' | 'apigateway' | 'lambda' | 'fargate' | 's3' | 'cloudfront' | 'openmfe' | 'bff';
|
|
4
4
|
export type VyriyPackagePlan = {
|
|
5
5
|
readonly name: string;
|
|
6
|
-
readonly kind: 'core' | 'ui' | 'api' | 'bff' | 'ssr' | 'ssg' | 'mfe' | 'contract';
|
|
6
|
+
readonly kind: 'core' | 'ui' | 'api' | 'bff' | 'ssr' | 'ssg' | 'mfe' | 'contract' | 'stack';
|
|
7
7
|
readonly publishable: boolean;
|
|
8
8
|
};
|
|
9
9
|
export type VyriyWorkspacePlan = {
|
|
10
10
|
readonly name: string;
|
|
11
|
-
readonly kind: 'web' | 'api' | 'ssr' | 'ssg' | 'storybook' | 'bff' | 'mfe' | 'openmfe' | '
|
|
11
|
+
readonly kind: 'web' | 'api' | 'ssr' | 'ssg' | 'storybook' | 'bff' | 'mfe' | 'openmfe' | 'stack';
|
|
12
12
|
};
|
|
13
13
|
export type VyriyCiProvider = 'gitlab' | 'github';
|
|
14
|
-
export type VyriyCiPipeline = 'install' | '
|
|
14
|
+
export type VyriyCiPipeline = 'install' | 'lint' | 'test' | 'build' | 'deploy' | 'smoke' | 'e2e';
|
|
15
15
|
export type VyriyCiPlan = {
|
|
16
16
|
readonly enabled: boolean;
|
|
17
17
|
readonly providers: VyriyCiProvider[];
|
|
18
18
|
readonly pipelines: VyriyCiPipeline[];
|
|
19
19
|
};
|
|
20
20
|
export type VyriyApiStyle = 'rest' | 'graphql' | 'mixed';
|
|
21
|
-
export type VyriyApiRuntime = 'node' | 'lambda'
|
|
21
|
+
export type VyriyApiRuntime = 'node' | 'lambda';
|
|
22
22
|
export type VyriyApiPlan = {
|
|
23
23
|
readonly enabled: boolean;
|
|
24
24
|
readonly style: VyriyApiStyle;
|
|
@@ -16,10 +16,33 @@ const presets = [
|
|
|
16
16
|
'empty',
|
|
17
17
|
];
|
|
18
18
|
const extraFeatures = [
|
|
19
|
-
'
|
|
19
|
+
'docker',
|
|
20
|
+
'aws-api',
|
|
21
|
+
'aws-fargate',
|
|
22
|
+
'aws-static',
|
|
23
|
+
];
|
|
24
|
+
const extraFeatureMap = {
|
|
25
|
+
docker: ['docker'],
|
|
26
|
+
'aws-api': [
|
|
27
|
+
'aws-cdk',
|
|
28
|
+
'lambda',
|
|
29
|
+
'apigateway',
|
|
30
|
+
],
|
|
31
|
+
'aws-fargate': [
|
|
32
|
+
'aws-cdk',
|
|
33
|
+
'fargate',
|
|
34
|
+
'docker',
|
|
35
|
+
],
|
|
36
|
+
'aws-static': [
|
|
37
|
+
'aws-cdk',
|
|
38
|
+
's3',
|
|
39
|
+
'cloudfront',
|
|
40
|
+
],
|
|
41
|
+
};
|
|
42
|
+
const directFeatureInputs = [
|
|
20
43
|
'docker',
|
|
21
44
|
'aws-cdk',
|
|
22
|
-
'
|
|
45
|
+
'apigateway',
|
|
23
46
|
'lambda',
|
|
24
47
|
'fargate',
|
|
25
48
|
's3',
|
|
@@ -64,10 +87,15 @@ const parsePreset = (value, defaultValue) => {
|
|
|
64
87
|
}
|
|
65
88
|
return presets.includes(normalizedValue) ? normalizedValue : defaultValue;
|
|
66
89
|
};
|
|
67
|
-
const parseFeatures = (value) =>
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
90
|
+
const parseFeatures = (value) => [
|
|
91
|
+
...new Set(value
|
|
92
|
+
.split(',')
|
|
93
|
+
.map((feature) => feature.trim())
|
|
94
|
+
.flatMap((feature) => extraFeatureMap[feature] ??
|
|
95
|
+
(directFeatureInputs.includes(feature)
|
|
96
|
+
? [feature]
|
|
97
|
+
: []))),
|
|
98
|
+
];
|
|
71
99
|
const parseApiStyle = (value, defaultValue) => {
|
|
72
100
|
const normalizedValue = value.trim().toLowerCase();
|
|
73
101
|
const numericValue = Number.parseInt(normalizedValue, 10);
|
|
@@ -109,9 +137,9 @@ export const askProjectPlan = async ({ defaults = {}, input = stdin, output = st
|
|
|
109
137
|
output.write(' 3. github\n');
|
|
110
138
|
const defaultCiProvider = defaults.ciProvider ?? 'none';
|
|
111
139
|
const ciProvider = parseCiProvider(await promptWithDefault(question, 'CI/CD provider number or name', defaultCiProvider), defaultCiProvider);
|
|
112
|
-
output.write('\nAdditional
|
|
140
|
+
output.write('\nAdditional infrastructure, comma-separated:\n');
|
|
113
141
|
output.write(` ${extraFeatures.join(', ')}\n`);
|
|
114
|
-
const featuresAnswer = await promptWithDefault(question, '
|
|
142
|
+
const featuresAnswer = await promptWithDefault(question, 'Infrastructure', defaults.features?.join(', ') ?? '');
|
|
115
143
|
const features = parseFeatures(featuresAnswer);
|
|
116
144
|
const plan = createProjectPlanFromPreset({
|
|
117
145
|
projectName,
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { execCommand as execCommandDefault } from './execCommand.js';
|
|
2
|
+
export const commandExists = async (command, { execCommand = execCommandDefault } = {}) => {
|
|
3
|
+
try {
|
|
4
|
+
await execCommand(command, ['--version']);
|
|
5
|
+
return true;
|
|
6
|
+
}
|
|
7
|
+
catch {
|
|
8
|
+
return false;
|
|
9
|
+
}
|
|
10
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { execFile } from 'node:child_process';
|
|
2
|
+
import { promisify } from 'node:util';
|
|
3
|
+
const execFileAsync = promisify(execFile);
|
|
4
|
+
export const execCommand = async (command, args = []) => {
|
|
5
|
+
const { stdout } = await execFileAsync(command, args);
|
|
6
|
+
return stdout.trim();
|
|
7
|
+
};
|
package/shared/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const getMajorVersion: (version: string) => number | undefined;
|
package/shared/semver.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export type ExecCommand = (command: string, args?: readonly string[]) => Promise<string>;
|
|
2
|
+
export type CommandExists = (command: string, options?: {
|
|
3
|
+
readonly execCommand?: ExecCommand;
|
|
4
|
+
}) => Promise<boolean>;
|
|
5
|
+
export type FileExists = (filePath: string) => Promise<boolean>;
|