vyriy 0.0.0 → 0.2.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.
- package/LICENSE +21 -0
- package/README.md +159 -0
- package/bin/vyriy.d.ts +2 -0
- package/bin/vyriy.js +3 -0
- package/checks/node/index.d.ts +2 -0
- package/checks/node/index.js +1 -0
- package/checks/node/node.d.ts +2 -0
- package/checks/node/node.js +22 -0
- package/checks/node/types.d.ts +11 -0
- package/checks/yarn/index.d.ts +2 -0
- package/checks/yarn/index.js +1 -0
- package/checks/yarn/types.d.ts +7 -0
- package/checks/yarn/yarn.d.ts +2 -0
- package/checks/yarn/yarn.js +40 -0
- package/cli/args/args.d.ts +2 -0
- package/cli/args/args.js +23 -0
- package/cli/args/index.d.ts +2 -0
- package/cli/args/index.js +1 -0
- package/cli/args/types.d.ts +10 -0
- package/cli/cli.d.ts +2 -0
- package/cli/cli.js +49 -0
- package/cli/index.d.ts +3 -0
- package/cli/index.js +2 -0
- package/cli/types.d.ts +4 -0
- package/commands/doctor/doctor.d.ts +2 -0
- package/commands/doctor/doctor.js +20 -0
- package/commands/doctor/index.d.ts +2 -0
- package/commands/doctor/index.js +1 -0
- package/commands/doctor/types.d.ts +8 -0
- package/commands/init/index.d.ts +2 -0
- package/commands/init/index.js +1 -0
- package/commands/init/init.d.ts +2 -0
- package/commands/init/init.js +7 -0
- package/commands/init/types.d.ts +5 -0
- package/commands/new/index.d.ts +2 -0
- package/commands/new/index.js +1 -0
- package/commands/new/new.d.ts +2 -0
- package/commands/new/new.js +32 -0
- package/commands/new/types.d.ts +7 -0
- package/index.d.ts +8 -0
- package/index.js +8 -1
- package/package.json +308 -9
- package/project-plan/api/api.d.ts +6 -0
- package/project-plan/api/api.js +56 -0
- package/project-plan/api/index.d.ts +2 -0
- package/project-plan/api/index.js +1 -0
- package/project-plan/api/types.d.ts +10 -0
- package/project-plan/ci/ci.d.ts +3 -0
- package/project-plan/ci/ci.js +19 -0
- package/project-plan/ci/index.d.ts +2 -0
- package/project-plan/ci/index.js +1 -0
- package/project-plan/ci/types.d.ts +6 -0
- package/project-plan/create/create.d.ts +2 -0
- package/project-plan/create/create.js +133 -0
- package/project-plan/create/index.d.ts +2 -0
- package/project-plan/create/index.js +1 -0
- package/project-plan/create/types.d.ts +13 -0
- package/project-plan/index.d.ts +6 -0
- package/project-plan/index.js +5 -0
- package/project-plan/kind/index.d.ts +2 -0
- package/project-plan/kind/index.js +1 -0
- package/project-plan/kind/kind.d.ts +2 -0
- package/project-plan/kind/kind.js +16 -0
- package/project-plan/kind/types.d.ts +2 -0
- package/project-plan/print/index.d.ts +2 -0
- package/project-plan/print/index.js +1 -0
- package/project-plan/print/print.d.ts +2 -0
- package/project-plan/print/print.js +47 -0
- package/project-plan/print/types.d.ts +2 -0
- package/project-plan/types.d.ts +46 -0
- package/prompts/project-plan/index.d.ts +2 -0
- package/prompts/project-plan/index.js +1 -0
- package/prompts/project-plan/project-plan.d.ts +2 -0
- package/prompts/project-plan/project-plan.js +132 -0
- package/prompts/project-plan/types.d.ts +18 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
const printList = (values) => values.length === 0 ? ' - none' : values.map((value) => ` - ${value}`).join('\n');
|
|
2
|
+
const printCi = (plan) => plan.ci.enabled
|
|
3
|
+
? `CI/CD:
|
|
4
|
+
enabled: yes
|
|
5
|
+
providers:
|
|
6
|
+
${printList(plan.ci.providers)}
|
|
7
|
+
pipelines:
|
|
8
|
+
${printList(plan.ci.pipelines)}
|
|
9
|
+
`
|
|
10
|
+
: `CI/CD:
|
|
11
|
+
enabled: no
|
|
12
|
+
`;
|
|
13
|
+
const printApi = (plan) => {
|
|
14
|
+
if (!plan.api) {
|
|
15
|
+
return '';
|
|
16
|
+
}
|
|
17
|
+
const rest = plan.api.rest
|
|
18
|
+
? ` REST:
|
|
19
|
+
router: ${plan.api.rest.packageName}
|
|
20
|
+
`
|
|
21
|
+
: '';
|
|
22
|
+
const graphql = plan.api.graphql
|
|
23
|
+
? ` GraphQL:
|
|
24
|
+
package: ${plan.api.graphql.packageName}
|
|
25
|
+
`
|
|
26
|
+
: '';
|
|
27
|
+
return `API:
|
|
28
|
+
style: ${plan.api.style}
|
|
29
|
+
runtime: ${plan.api.runtime}
|
|
30
|
+
${rest}${graphql}`;
|
|
31
|
+
};
|
|
32
|
+
export const printProjectPlan = (plan) => `Project summary:
|
|
33
|
+
|
|
34
|
+
Name: ${plan.projectName}
|
|
35
|
+
Target directory: ${plan.targetDirectory}
|
|
36
|
+
Scope: ${plan.packageScope}
|
|
37
|
+
Description: ${plan.description}
|
|
38
|
+
Preset: ${plan.preset}
|
|
39
|
+
Kind: ${plan.projectKind}
|
|
40
|
+
Features:
|
|
41
|
+
${printList(plan.features)}
|
|
42
|
+
Packages:
|
|
43
|
+
${printList(plan.packages.map((packagePlan) => `${packagePlan.name} (${packagePlan.kind})`))}
|
|
44
|
+
Workspaces:
|
|
45
|
+
${printList(plan.workspaces.map((workspacePlan) => `${workspacePlan.name} (${workspacePlan.kind})`))}
|
|
46
|
+
${printApi(plan)}${printCi(plan)}
|
|
47
|
+
`;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export type VyriyProjectKind = 'library' | 'api' | 'csr' | 'ssr' | 'ssg' | 'mfe' | 'fullstack' | 'aws-serverless' | 'empty';
|
|
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' | 'dynamodb' | 'lambda' | 'fargate' | 's3' | 'cloudfront' | 'openmfe' | 'bff';
|
|
4
|
+
export type VyriyPackagePlan = {
|
|
5
|
+
readonly name: string;
|
|
6
|
+
readonly kind: 'core' | 'ui' | 'api' | 'bff' | 'ssr' | 'ssg' | 'mfe' | 'contract';
|
|
7
|
+
readonly publishable: boolean;
|
|
8
|
+
};
|
|
9
|
+
export type VyriyWorkspacePlan = {
|
|
10
|
+
readonly name: string;
|
|
11
|
+
readonly kind: 'web' | 'api' | 'ssr' | 'ssg' | 'storybook' | 'bff' | 'mfe' | 'openmfe' | 'cdk';
|
|
12
|
+
};
|
|
13
|
+
export type VyriyCiProvider = 'gitlab' | 'github';
|
|
14
|
+
export type VyriyCiPipeline = 'install' | 'typecheck' | 'lint' | 'prettier' | 'test' | 'build' | 'storybook' | 'docker' | 'npm-publish' | 'aws-deploy';
|
|
15
|
+
export type VyriyCiPlan = {
|
|
16
|
+
readonly enabled: boolean;
|
|
17
|
+
readonly providers: VyriyCiProvider[];
|
|
18
|
+
readonly pipelines: VyriyCiPipeline[];
|
|
19
|
+
};
|
|
20
|
+
export type VyriyApiStyle = 'rest' | 'graphql' | 'mixed';
|
|
21
|
+
export type VyriyApiRuntime = 'node' | 'lambda' | 'fargate';
|
|
22
|
+
export type VyriyApiPlan = {
|
|
23
|
+
readonly enabled: boolean;
|
|
24
|
+
readonly style: VyriyApiStyle;
|
|
25
|
+
readonly runtime: VyriyApiRuntime;
|
|
26
|
+
readonly rest?: {
|
|
27
|
+
readonly router: 'vyriy-router';
|
|
28
|
+
readonly packageName: '@vyriy/router';
|
|
29
|
+
};
|
|
30
|
+
readonly graphql?: {
|
|
31
|
+
readonly packageName: 'graphql';
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
export type VyriyProjectPlan = {
|
|
35
|
+
readonly projectName: string;
|
|
36
|
+
readonly targetDirectory: string;
|
|
37
|
+
readonly packageScope: string;
|
|
38
|
+
readonly description: string;
|
|
39
|
+
readonly projectKind: VyriyProjectKind;
|
|
40
|
+
readonly preset: VyriyPreset;
|
|
41
|
+
readonly features: VyriyFeature[];
|
|
42
|
+
readonly packages: VyriyPackagePlan[];
|
|
43
|
+
readonly workspaces: VyriyWorkspacePlan[];
|
|
44
|
+
readonly ci: VyriyCiPlan;
|
|
45
|
+
readonly api?: VyriyApiPlan;
|
|
46
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './project-plan.js';
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { stdin, stdout } from 'node:process';
|
|
2
|
+
import { createInterface } from 'node:readline';
|
|
3
|
+
import { createProjectPlanFromPreset, getDefaultApiStyleFromPreset, isApiPreset, } from '../../project-plan/index.js';
|
|
4
|
+
const presets = [
|
|
5
|
+
'library',
|
|
6
|
+
'api',
|
|
7
|
+
'react-csr',
|
|
8
|
+
'react-ssr',
|
|
9
|
+
'react-ssg',
|
|
10
|
+
'mfe',
|
|
11
|
+
'openmfe',
|
|
12
|
+
'mfe-bff',
|
|
13
|
+
'openmfe-bff',
|
|
14
|
+
'fullstack',
|
|
15
|
+
'aws-serverless',
|
|
16
|
+
'empty',
|
|
17
|
+
];
|
|
18
|
+
const extraFeatures = [
|
|
19
|
+
'storybook',
|
|
20
|
+
'docker',
|
|
21
|
+
'aws-cdk',
|
|
22
|
+
'dynamodb',
|
|
23
|
+
'lambda',
|
|
24
|
+
'fargate',
|
|
25
|
+
's3',
|
|
26
|
+
'cloudfront',
|
|
27
|
+
];
|
|
28
|
+
const apiStyles = ['rest', 'graphql', 'mixed'];
|
|
29
|
+
const ciProviders = ['none', 'gitlab', 'github'];
|
|
30
|
+
const createQuestion = (readline, output) => {
|
|
31
|
+
const queuedLines = [];
|
|
32
|
+
const pendingQuestions = [];
|
|
33
|
+
readline.on('line', (line) => {
|
|
34
|
+
const resolve = pendingQuestions.shift();
|
|
35
|
+
if (resolve) {
|
|
36
|
+
resolve(line);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
queuedLines.push(line);
|
|
40
|
+
});
|
|
41
|
+
readline.on('close', () => {
|
|
42
|
+
for (const resolve of pendingQuestions.splice(0)) {
|
|
43
|
+
resolve('');
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
return (query) => {
|
|
47
|
+
output.write(query);
|
|
48
|
+
const queuedLine = queuedLines.shift();
|
|
49
|
+
if (queuedLine !== undefined) {
|
|
50
|
+
return Promise.resolve(queuedLine);
|
|
51
|
+
}
|
|
52
|
+
return new Promise((resolve) => pendingQuestions.push(resolve));
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
const promptWithDefault = async (question, label, defaultValue) => {
|
|
56
|
+
const answer = (await question(`${label} (${defaultValue}): `)).trim();
|
|
57
|
+
return answer || defaultValue;
|
|
58
|
+
};
|
|
59
|
+
const parsePreset = (value, defaultValue) => {
|
|
60
|
+
const normalizedValue = value.trim();
|
|
61
|
+
const numericValue = Number.parseInt(normalizedValue, 10);
|
|
62
|
+
if (Number.isInteger(numericValue) && presets[numericValue - 1]) {
|
|
63
|
+
return presets[numericValue - 1];
|
|
64
|
+
}
|
|
65
|
+
return presets.includes(normalizedValue) ? normalizedValue : defaultValue;
|
|
66
|
+
};
|
|
67
|
+
const parseFeatures = (value) => value
|
|
68
|
+
.split(',')
|
|
69
|
+
.map((feature) => feature.trim())
|
|
70
|
+
.filter((feature) => extraFeatures.includes(feature));
|
|
71
|
+
const parseApiStyle = (value, defaultValue) => {
|
|
72
|
+
const normalizedValue = value.trim().toLowerCase();
|
|
73
|
+
const numericValue = Number.parseInt(normalizedValue, 10);
|
|
74
|
+
if (Number.isInteger(numericValue) && apiStyles[numericValue - 1]) {
|
|
75
|
+
return apiStyles[numericValue - 1];
|
|
76
|
+
}
|
|
77
|
+
return apiStyles.includes(normalizedValue) ? normalizedValue : defaultValue;
|
|
78
|
+
};
|
|
79
|
+
const parseCiProvider = (value, defaultValue) => {
|
|
80
|
+
const normalizedValue = value.trim().toLowerCase();
|
|
81
|
+
const numericValue = Number.parseInt(normalizedValue, 10);
|
|
82
|
+
if (Number.isInteger(numericValue) && ciProviders[numericValue - 1]) {
|
|
83
|
+
return ciProviders[numericValue - 1];
|
|
84
|
+
}
|
|
85
|
+
return ciProviders.includes(normalizedValue)
|
|
86
|
+
? normalizedValue
|
|
87
|
+
: defaultValue;
|
|
88
|
+
};
|
|
89
|
+
export const askProjectPlan = async ({ defaults = {}, input = stdin, output = stdout } = {}) => {
|
|
90
|
+
const readline = createInterface({ input, output });
|
|
91
|
+
const question = createQuestion(readline, output);
|
|
92
|
+
try {
|
|
93
|
+
output.write('Vyriy Project Master\n\n');
|
|
94
|
+
const projectName = await promptWithDefault(question, 'Project name', defaults.projectName ?? 'my-app');
|
|
95
|
+
const targetDirectory = await promptWithDefault(question, 'Target directory', defaults.targetDirectory ?? projectName);
|
|
96
|
+
const packageScope = await promptWithDefault(question, 'Package scope', defaults.packageScope ?? `@${projectName}`);
|
|
97
|
+
const description = await promptWithDefault(question, 'Description', defaults.description ?? 'Calm cloud-ready application.');
|
|
98
|
+
output.write('\nProject preset:\n');
|
|
99
|
+
presets.forEach((preset, index) => output.write(` ${index + 1}. ${preset}\n`));
|
|
100
|
+
const presetAnswer = await promptWithDefault(question, 'Preset number or name', defaults.preset ?? 'react-ssr');
|
|
101
|
+
const preset = parsePreset(presetAnswer, defaults.preset ?? 'react-ssr');
|
|
102
|
+
const defaultApiStyle = defaults.apiStyle ?? getDefaultApiStyleFromPreset(preset);
|
|
103
|
+
const apiStyle = isApiPreset(preset)
|
|
104
|
+
? parseApiStyle(await promptWithDefault(question, 'API style: 1. rest (@vyriy/router), 2. graphql, 3. mixed', defaultApiStyle), defaultApiStyle)
|
|
105
|
+
: undefined;
|
|
106
|
+
output.write('\nCI/CD provider:\n');
|
|
107
|
+
output.write(' 1. none\n');
|
|
108
|
+
output.write(' 2. gitlab\n');
|
|
109
|
+
output.write(' 3. github\n');
|
|
110
|
+
const defaultCiProvider = defaults.ciProvider ?? 'none';
|
|
111
|
+
const ciProvider = parseCiProvider(await promptWithDefault(question, 'CI/CD provider number or name', defaultCiProvider), defaultCiProvider);
|
|
112
|
+
output.write('\nAdditional features, comma-separated:\n');
|
|
113
|
+
output.write(` ${extraFeatures.join(', ')}\n`);
|
|
114
|
+
const featuresAnswer = await promptWithDefault(question, 'Features', defaults.features?.join(', ') ?? '');
|
|
115
|
+
const features = parseFeatures(featuresAnswer);
|
|
116
|
+
const plan = createProjectPlanFromPreset({
|
|
117
|
+
projectName,
|
|
118
|
+
targetDirectory,
|
|
119
|
+
packageScope,
|
|
120
|
+
description,
|
|
121
|
+
preset,
|
|
122
|
+
features,
|
|
123
|
+
apiStyle,
|
|
124
|
+
ciProvider,
|
|
125
|
+
});
|
|
126
|
+
const confirmation = (await promptWithDefault(question, 'Use this project plan?', 'yes')).toLowerCase();
|
|
127
|
+
return confirmation === 'yes' || confirmation === 'y' ? plan : undefined;
|
|
128
|
+
}
|
|
129
|
+
finally {
|
|
130
|
+
readline.close();
|
|
131
|
+
}
|
|
132
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Readable, Writable } from 'node:stream';
|
|
2
|
+
import { VyriyApiStyle, VyriyCiPromptProvider, VyriyFeature, VyriyPreset, VyriyProjectPlan } from '../../project-plan/index.js';
|
|
3
|
+
export type PromptProjectPlanDefaults = {
|
|
4
|
+
readonly projectName?: string;
|
|
5
|
+
readonly targetDirectory?: string;
|
|
6
|
+
readonly packageScope?: string;
|
|
7
|
+
readonly description?: string;
|
|
8
|
+
readonly preset?: VyriyPreset;
|
|
9
|
+
readonly features?: readonly VyriyFeature[];
|
|
10
|
+
readonly apiStyle?: VyriyApiStyle;
|
|
11
|
+
readonly ciProvider?: VyriyCiPromptProvider;
|
|
12
|
+
};
|
|
13
|
+
export type PromptProjectPlanOptions = {
|
|
14
|
+
readonly defaults?: PromptProjectPlanDefaults;
|
|
15
|
+
readonly input?: Readable;
|
|
16
|
+
readonly output?: Writable;
|
|
17
|
+
};
|
|
18
|
+
export type PromptProjectPlan = (options?: PromptProjectPlanOptions) => Promise<VyriyProjectPlan | undefined>;
|