vovk-cli 0.0.1-draft.3 → 0.0.1-draft.300
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 +1 -1
- package/README.md +29 -1
- package/client-templates/cjs/index.cjs.ejs +19 -0
- package/client-templates/cjs/index.d.cts.ejs +25 -0
- package/client-templates/mixins/mixins.d.ts.ejs +64 -0
- package/client-templates/mixins/mixins.json.ejs +1 -0
- package/client-templates/mjs/index.d.mts.ejs +25 -0
- package/client-templates/mjs/index.mjs.ejs +23 -0
- package/client-templates/packageJson/package.json.ejs +1 -0
- package/client-templates/readme/README.md.ejs +38 -0
- package/client-templates/schemaCjs/schema.cjs.ejs +26 -0
- package/client-templates/schemaCjs/schema.d.cts.ejs +10 -0
- package/client-templates/schemaJson/schema.json.ejs +1 -0
- package/client-templates/schemaTs/schema.ts.ejs +35 -0
- package/client-templates/ts/index.ts.ejs +33 -0
- package/dist/bundle/index.d.mts +8 -0
- package/dist/bundle/index.mjs +90 -0
- package/dist/dev/diffSegmentSchema.d.mts +36 -0
- package/dist/{watcher/diffSchema.mjs → dev/diffSegmentSchema.mjs} +4 -12
- package/dist/{watcher → dev}/ensureSchemaFiles.d.mts +3 -0
- package/dist/{watcher → dev}/ensureSchemaFiles.mjs +17 -21
- package/dist/dev/index.d.mts +9 -0
- package/dist/dev/index.mjs +388 -0
- package/dist/dev/logDiffResult.d.mts +3 -0
- package/dist/dev/logDiffResult.mjs +57 -0
- package/dist/dev/writeMetaJson.d.mts +2 -0
- package/dist/dev/writeMetaJson.mjs +17 -0
- package/dist/dev/writeOneSegmentSchemaFile.d.mts +12 -0
- package/dist/dev/writeOneSegmentSchemaFile.mjs +32 -0
- package/dist/generate/ensureClient.d.mts +3 -0
- package/dist/generate/ensureClient.mjs +32 -0
- package/dist/generate/generate.d.mts +15 -0
- package/dist/generate/generate.mjs +291 -0
- package/dist/generate/getClientTemplateFiles.d.mts +20 -0
- package/dist/generate/getClientTemplateFiles.mjs +89 -0
- package/dist/generate/getProjectFullSchema.d.mts +7 -0
- package/dist/generate/getProjectFullSchema.mjs +65 -0
- package/dist/generate/getTemplateClientImports.d.mts +18 -0
- package/dist/generate/getTemplateClientImports.mjs +38 -0
- package/dist/generate/index.d.mts +33 -0
- package/dist/generate/index.mjs +189 -0
- package/dist/generate/mergePackages.d.mts +7 -0
- package/dist/generate/mergePackages.mjs +55 -0
- package/dist/generate/writeOneClientFile.d.mts +36 -0
- package/dist/generate/writeOneClientFile.mjs +120 -0
- package/dist/getProjectInfo/getConfig/getConfigAbsolutePaths.d.mts +5 -0
- package/dist/getProjectInfo/{getConfigAbsolutePaths.mjs → getConfig/getConfigAbsolutePaths.mjs} +6 -3
- package/dist/getProjectInfo/{getRelativeSrcRoot.d.mts → getConfig/getRelativeSrcRoot.d.mts} +1 -1
- package/dist/getProjectInfo/getConfig/getRelativeSrcRoot.mjs +12 -0
- package/dist/getProjectInfo/getConfig/getTemplateDefs.d.mts +16 -0
- package/dist/getProjectInfo/getConfig/getTemplateDefs.mjs +98 -0
- package/dist/getProjectInfo/{getUserConfig.d.mts → getConfig/getUserConfig.d.mts} +3 -2
- package/dist/getProjectInfo/{getUserConfig.mjs → getConfig/getUserConfig.mjs} +7 -5
- package/dist/getProjectInfo/{importUncachedModule.mjs → getConfig/importUncachedModule.mjs} +1 -5
- package/dist/getProjectInfo/{importUncachedModuleWorker.mjs → getConfig/importUncachedModuleWorker.mjs} +0 -1
- package/dist/getProjectInfo/getConfig/index.d.mts +120 -0
- package/dist/getProjectInfo/getConfig/index.mjs +94 -0
- package/dist/getProjectInfo/index.d.mts +12 -9
- package/dist/getProjectInfo/index.mjs +22 -23
- package/dist/index.d.mts +2 -24
- package/dist/index.mjs +106 -69
- package/dist/init/checkTSConfigForExperimentalDecorators.mjs +2 -2
- package/dist/init/createConfig.d.mts +3 -4
- package/dist/init/createConfig.mjs +22 -16
- package/dist/init/getTemplateFilesFromPackage.d.mts +2 -1
- package/dist/init/getTemplateFilesFromPackage.mjs +13 -9
- package/dist/init/index.d.mts +2 -3
- package/dist/init/index.mjs +119 -138
- package/dist/init/installDependencies.d.mts +4 -1
- package/dist/init/installDependencies.mjs +6 -4
- package/dist/init/logUpdateDependenciesError.d.mts +13 -0
- package/dist/init/logUpdateDependenciesError.mjs +51 -0
- package/dist/init/updateDependenciesWithoutInstalling.d.mts +3 -2
- package/dist/init/updateDependenciesWithoutInstalling.mjs +50 -15
- package/dist/init/updateNPMScripts.d.mts +3 -1
- package/dist/init/updateNPMScripts.mjs +10 -7
- package/dist/init/updateTypeScriptConfig.d.mts +4 -1
- package/dist/init/updateTypeScriptConfig.mjs +13 -9
- package/dist/initProgram.d.mts +2 -0
- package/dist/initProgram.mjs +22 -0
- package/dist/locateSegments.d.mts +8 -1
- package/dist/locateSegments.mjs +16 -6
- package/dist/new/addClassToSegmentCode.d.mts +1 -2
- package/dist/new/addClassToSegmentCode.mjs +9 -5
- package/dist/new/addCommonTerms.mjs +1 -0
- package/dist/new/index.d.mts +2 -2
- package/dist/new/index.mjs +14 -3
- package/dist/new/newModule.d.mts +7 -2
- package/dist/new/newModule.mjs +61 -35
- package/dist/new/newSegment.d.mts +4 -2
- package/dist/new/newSegment.mjs +22 -13
- package/dist/new/render.d.mts +9 -9
- package/dist/new/render.mjs +38 -13
- package/dist/types.d.mts +73 -28
- package/dist/utils/compileJSONSchemaToTypeScriptType.d.mts +5 -0
- package/dist/utils/compileJSONSchemaToTypeScriptType.mjs +9 -0
- package/dist/utils/compileTs.d.mts +12 -0
- package/dist/utils/compileTs.mjs +261 -0
- package/dist/utils/debounceWithArgs.d.mts +2 -2
- package/dist/utils/debounceWithArgs.mjs +24 -9
- package/dist/utils/formatLoggedSegmentName.d.mts +3 -1
- package/dist/utils/formatLoggedSegmentName.mjs +4 -3
- package/dist/utils/getAvailablePort.mjs +3 -2
- package/dist/utils/getFileSystemEntryType.mjs +1 -1
- package/dist/utils/getPackageJson.d.mts +3 -0
- package/dist/utils/getPackageJson.mjs +22 -0
- package/dist/utils/getPublicModuleNameFromPath.d.mts +4 -0
- package/dist/utils/getPublicModuleNameFromPath.mjs +9 -0
- package/dist/utils/normalizeOpenAPIMixins.d.mts +7 -0
- package/dist/utils/normalizeOpenAPIMixins.mjs +67 -0
- package/dist/utils/pickSegmentFullSchema.d.mts +3 -0
- package/dist/utils/pickSegmentFullSchema.mjs +15 -0
- package/dist/utils/removeUnlistedDirectories.d.mts +10 -0
- package/dist/utils/removeUnlistedDirectories.mjs +61 -0
- package/dist/utils/resolveAbsoluteModulePath.d.mts +2 -0
- package/dist/utils/resolveAbsoluteModulePath.mjs +32 -0
- package/module-templates/controller.ts.ejs +56 -0
- package/module-templates/service.ts.ejs +28 -0
- package/package.json +42 -21
- package/dist/generateClient.d.mts +0 -7
- package/dist/generateClient.mjs +0 -97
- package/dist/getProjectInfo/directoryExists.d.mts +0 -1
- package/dist/getProjectInfo/directoryExists.mjs +0 -10
- package/dist/getProjectInfo/getConfig.d.mts +0 -11
- package/dist/getProjectInfo/getConfig.mjs +0 -29
- package/dist/getProjectInfo/getConfigAbsolutePaths.d.mts +0 -4
- package/dist/getProjectInfo/getRelativeSrcRoot.mjs +0 -12
- package/dist/postinstall.d.mts +0 -1
- package/dist/postinstall.mjs +0 -22
- package/dist/watcher/diffSchema.d.mts +0 -43
- package/dist/watcher/index.d.mts +0 -6
- package/dist/watcher/index.mjs +0 -295
- package/dist/watcher/isMetadataEmpty.d.mts +0 -2
- package/dist/watcher/isMetadataEmpty.mjs +0 -4
- package/dist/watcher/logDiffResult.d.mts +0 -3
- package/dist/watcher/logDiffResult.mjs +0 -90
- package/dist/watcher/writeOneSchemaFile.d.mts +0 -11
- package/dist/watcher/writeOneSchemaFile.mjs +0 -27
- package/templates/controller.ejs +0 -50
- package/templates/service.ejs +0 -7
- package/templates/worker.ejs +0 -1
- package/templates_old/MyThingController.c.only.template.ts +0 -32
- package/templates_old/MyThingController.c.template.ts +0 -34
- package/templates_old/MyThingService.s.template.ts +0 -18
- package/templates_old/controller.ejs +0 -85
- package/templates_old/service.ejs +0 -9
- package/templates_old/worker.ejs +0 -9
- package/templates_old/zod/MyThingController.c.only.template.ts +0 -32
- package/templates_old/zod/MyThingController.c.template.ts +0 -39
- package/templates_old/zod/MyThingService.s.template.ts +0 -18
- /package/dist/getProjectInfo/{importUncachedModule.d.mts → getConfig/importUncachedModule.d.mts} +0 -0
- /package/dist/getProjectInfo/{importUncachedModuleWorker.d.mts → getConfig/importUncachedModuleWorker.d.mts} +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { InitOptions } from '../types.mjs';
|
|
1
2
|
/**
|
|
2
3
|
* Retrieves a list of files in the 'templates' folder of an NPM package.
|
|
3
4
|
* @param packageName - The name of the NPM package.
|
|
4
5
|
* @returns A promise that resolves to an array of file paths.
|
|
5
6
|
*/
|
|
6
|
-
export default function
|
|
7
|
+
export default function getTemplateFilesFromPackage(packageName: string, channel?: InitOptions['channel']): Promise<Record<string, string>>;
|
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Readable } from 'node:stream';
|
|
2
|
+
import { createGunzip } from 'node:zlib';
|
|
2
3
|
import tar from 'tar-stream';
|
|
3
|
-
import { Readable } from 'stream';
|
|
4
4
|
import getNPMPackageMetadata from '../utils/getNPMPackageMetadata.mjs';
|
|
5
5
|
/**
|
|
6
6
|
* Retrieves a list of files in the 'templates' folder of an NPM package.
|
|
7
7
|
* @param packageName - The name of the NPM package.
|
|
8
8
|
* @returns A promise that resolves to an array of file paths.
|
|
9
9
|
*/
|
|
10
|
-
export default async function
|
|
11
|
-
) {
|
|
10
|
+
export default async function getTemplateFilesFromPackage(packageName, channel = 'latest') {
|
|
12
11
|
const metadata = await getNPMPackageMetadata(packageName);
|
|
13
12
|
const latestVersion = metadata['dist-tags'][channel];
|
|
14
13
|
const tarballUrl = metadata.versions[latestVersion].dist.tarball;
|
|
@@ -22,8 +21,14 @@ export default async function getTemplatesFiles(packageName, channel = 'beta' //
|
|
|
22
21
|
// Extract the tarball in memory and collect template files
|
|
23
22
|
const templateFiles = await extractTemplatesFromTarball(tarballBuffer);
|
|
24
23
|
const entries = templateFiles
|
|
25
|
-
.filter((fileName) => fileName.startsWith('templates/') && !fileName.endsWith('/') && fileName.endsWith('.ejs'))
|
|
26
|
-
.map((fileName) => [
|
|
24
|
+
.filter((fileName) => fileName.startsWith('module-templates/') && !fileName.endsWith('/') && fileName.endsWith('.ts.ejs'))
|
|
25
|
+
.map((fileName) => [
|
|
26
|
+
fileName
|
|
27
|
+
.substring('module-templates/'.length)
|
|
28
|
+
.replace(/\.ts\.ejs$/, '')
|
|
29
|
+
.toLowerCase(),
|
|
30
|
+
`${packageName}/${fileName}`,
|
|
31
|
+
]);
|
|
27
32
|
return Object.fromEntries(entries);
|
|
28
33
|
}
|
|
29
34
|
/**
|
|
@@ -37,9 +42,8 @@ function extractTemplatesFromTarball(tarballBuffer) {
|
|
|
37
42
|
const files = [];
|
|
38
43
|
extract.on('entry', (header, stream, next) => {
|
|
39
44
|
const filePath = header.name;
|
|
40
|
-
//
|
|
41
|
-
|
|
42
|
-
if (filePath.startsWith('package/templates/')) {
|
|
45
|
+
// Check if the file is in the 'module-templates' folder
|
|
46
|
+
if (filePath.startsWith('package/module-templates/')) {
|
|
43
47
|
files.push(filePath.replace('package/', ''));
|
|
44
48
|
}
|
|
45
49
|
stream.on('end', () => next());
|
package/dist/init/index.d.mts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import type { InitOptions } from '../index.mjs';
|
|
3
1
|
import getLogger from '../utils/getLogger.mjs';
|
|
2
|
+
import type { InitOptions } from '../types.mjs';
|
|
4
3
|
export declare class Init {
|
|
5
4
|
#private;
|
|
6
5
|
root: string;
|
|
7
6
|
log: ReturnType<typeof getLogger>;
|
|
8
|
-
main(prefix: string, { yes, logLevel, useNpm, useYarn, usePnpm, useBun, skipInstall, updateTsConfig, updateScripts, validationLibrary,
|
|
7
|
+
main(prefix: string, { yes, logLevel, useNpm, useYarn, usePnpm, useBun, skipInstall, updateTsConfig, updateScripts, validationLibrary, reactQuery, lang, dryRun, channel, }: InitOptions): Promise<void>;
|
|
9
8
|
}
|
package/dist/init/index.mjs
CHANGED
|
@@ -1,98 +1,50 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
- Check if the project is already initialized
|
|
5
|
-
- Do you want to reinitialize the project?
|
|
6
|
-
- Yes
|
|
7
|
-
- No (exit)
|
|
8
|
-
- Check for package.json, if not found, show error and exit
|
|
9
|
-
- Check for tsconfig.json, if not found, show error and exit
|
|
10
|
-
- Check Next.js installed
|
|
11
|
-
- Choose validation library: add to the installation list
|
|
12
|
-
- vovk-zod
|
|
13
|
-
- Further installation notes: install zod
|
|
14
|
-
- vovk-yup
|
|
15
|
-
- Further installation notes: install yup
|
|
16
|
-
- vovk-dto
|
|
17
|
-
- Further installation notes: install class-validator and class-transformer
|
|
18
|
-
- None
|
|
19
|
-
- If validation library is not None,
|
|
20
|
-
- Do you want to enable client validation?
|
|
21
|
-
- Yes
|
|
22
|
-
- Add client validation to the config
|
|
23
|
-
- No
|
|
24
|
-
- Do you want to update NPM scripts?
|
|
25
|
-
- Yes
|
|
26
|
-
- Update NPM scripts
|
|
27
|
-
- No
|
|
28
|
-
- Do you want to use explicit concurrently?
|
|
29
|
-
- Yes (recommended)
|
|
30
|
-
- Add concurrently to the installation list
|
|
31
|
-
- No
|
|
32
|
-
- if experimentalDecorators is not found in tsconfig.json,
|
|
33
|
-
- Do you want to add experimentalDecorators to tsconfig.json?
|
|
34
|
-
- Yes
|
|
35
|
-
- Add experimentalDecorators to tsconfig.json
|
|
36
|
-
- No
|
|
37
|
-
- Do you want to create route file with example service and controller? (NO NEED)
|
|
38
|
-
- Yes
|
|
39
|
-
- Create route file with example controller
|
|
40
|
-
- No, I will create it myself
|
|
41
|
-
- End
|
|
42
|
-
- If there are any packages to install, install them
|
|
43
|
-
- Show installation notes
|
|
44
|
-
- If there are any files to create, create
|
|
45
|
-
- If there are any config files to update, update
|
|
46
|
-
- If example route file is NOT created, show example route file and controller
|
|
47
|
-
- Show how to run the project
|
|
48
|
-
- If npm scripts are updated
|
|
49
|
-
- npm run dev
|
|
50
|
-
- If npm scripts are NOT updated
|
|
51
|
-
- If concurrently is installed
|
|
52
|
-
- concurrently "vovk dev" "next dev"
|
|
53
|
-
- If concurrently is NOT installed
|
|
54
|
-
- vovk dev --next-dev
|
|
55
|
-
- Open http://localhost:3000/api/hello-world
|
|
56
|
-
- Show how to make a request to the example route
|
|
57
|
-
- Show success message
|
|
58
|
-
*/
|
|
59
|
-
import { confirm, select } from '@inquirer/prompts';
|
|
60
|
-
import path from 'path';
|
|
61
|
-
import fs from 'fs/promises';
|
|
62
|
-
import getConfigPaths from '../getProjectInfo/getConfigAbsolutePaths.mjs';
|
|
1
|
+
import { confirm, select, checkbox } from '@inquirer/prompts';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import fs from 'node:fs/promises';
|
|
63
4
|
import chalk from 'chalk';
|
|
5
|
+
import NPMCliPackageJson from '@npmcli/package-json';
|
|
6
|
+
import getConfigPaths from '../getProjectInfo/getConfig/getConfigAbsolutePaths.mjs';
|
|
64
7
|
import getFileSystemEntryType from '../utils/getFileSystemEntryType.mjs';
|
|
65
|
-
import installDependencies from './installDependencies.mjs';
|
|
8
|
+
import installDependencies, { getPackageManager } from './installDependencies.mjs';
|
|
66
9
|
import getLogger from '../utils/getLogger.mjs';
|
|
67
10
|
import createConfig from './createConfig.mjs';
|
|
68
|
-
import updateNPMScripts from './updateNPMScripts.mjs';
|
|
11
|
+
import updateNPMScripts, { getDevScript } from './updateNPMScripts.mjs';
|
|
69
12
|
import checkTSConfigForExperimentalDecorators from './checkTSConfigForExperimentalDecorators.mjs';
|
|
70
13
|
import updateTypeScriptConfig from './updateTypeScriptConfig.mjs';
|
|
71
14
|
import updateDependenciesWithoutInstalling from './updateDependenciesWithoutInstalling.mjs';
|
|
15
|
+
import logUpdateDependenciesError from './logUpdateDependenciesError.mjs';
|
|
16
|
+
import chalkHighlightThing from '../utils/chalkHighlightThing.mjs';
|
|
72
17
|
export class Init {
|
|
73
18
|
root;
|
|
74
19
|
log;
|
|
75
|
-
async #init({ configPaths, }, { useNpm, useYarn, usePnpm, useBun, skipInstall, updateTsConfig, updateScripts, validationLibrary,
|
|
20
|
+
async #init({ configPaths, pkgJson, }, { useNpm, useYarn, usePnpm, useBun, skipInstall, updateTsConfig, updateScripts, validationLibrary, reactQuery, lang, dryRun, channel, }) {
|
|
76
21
|
const { log, root } = this;
|
|
77
|
-
const dependencies = ['vovk'];
|
|
22
|
+
const dependencies = ['vovk', 'vovk-client', 'vovk-ajv', 'openapi3-ts'];
|
|
78
23
|
const devDependencies = ['vovk-cli'];
|
|
24
|
+
if (lang?.includes('py')) {
|
|
25
|
+
devDependencies.push('vovk-python');
|
|
26
|
+
}
|
|
27
|
+
if (lang?.includes('rs')) {
|
|
28
|
+
devDependencies.push('vovk-rust');
|
|
29
|
+
}
|
|
79
30
|
// delete older config files
|
|
80
31
|
if (configPaths.length) {
|
|
81
32
|
await Promise.all(configPaths.map((configPath) => fs.rm(configPath)));
|
|
82
33
|
log.debug(`Deleted existing config file${configPaths.length > 1 ? 's' : ''} at ${configPaths.join(', ')}`);
|
|
83
34
|
}
|
|
84
35
|
if (validationLibrary) {
|
|
85
|
-
dependencies.push(validationLibrary
|
|
86
|
-
dependencies.push(...({
|
|
36
|
+
dependencies.push(validationLibrary, ...({
|
|
87
37
|
'vovk-zod': ['zod'],
|
|
88
|
-
'vovk-
|
|
89
|
-
'vovk-dto': ['class-validator', 'class-transformer'],
|
|
38
|
+
'vovk-dto': ['class-validator', 'class-transformer', 'dto-mapped-types', 'reflect-metadata'],
|
|
90
39
|
}[validationLibrary] ?? []));
|
|
91
40
|
}
|
|
41
|
+
if (reactQuery) {
|
|
42
|
+
dependencies.push('vovk-react-query', '@tanstack/react-query');
|
|
43
|
+
}
|
|
92
44
|
if (updateScripts) {
|
|
93
45
|
try {
|
|
94
46
|
if (!dryRun)
|
|
95
|
-
await updateNPMScripts(root, updateScripts);
|
|
47
|
+
await updateNPMScripts(pkgJson, root, updateScripts);
|
|
96
48
|
log.info('Updated scripts at package.json');
|
|
97
49
|
}
|
|
98
50
|
catch (error) {
|
|
@@ -104,15 +56,24 @@ export class Init {
|
|
|
104
56
|
}
|
|
105
57
|
if (updateTsConfig) {
|
|
106
58
|
try {
|
|
59
|
+
const compilerOptions = {
|
|
60
|
+
experimentalDecorators: true,
|
|
61
|
+
};
|
|
62
|
+
if (validationLibrary === 'vovk-dto') {
|
|
63
|
+
compilerOptions.emitDecoratorMetadata = true;
|
|
64
|
+
}
|
|
107
65
|
if (!dryRun)
|
|
108
|
-
await updateTypeScriptConfig(root);
|
|
109
|
-
log.info(
|
|
66
|
+
await updateTypeScriptConfig(root, compilerOptions);
|
|
67
|
+
log.info(`Added ${Object.keys(compilerOptions)
|
|
68
|
+
.map((k) => `"${k}"`)
|
|
69
|
+
.join(' and ')} to tsconfig.json`);
|
|
110
70
|
}
|
|
111
71
|
catch (error) {
|
|
112
72
|
log.error(`Failed to update tsconfig.json: ${error.message}`);
|
|
113
73
|
}
|
|
114
74
|
}
|
|
115
75
|
if (!dryRun) {
|
|
76
|
+
let depsUpdated = false;
|
|
116
77
|
try {
|
|
117
78
|
await updateDependenciesWithoutInstalling({
|
|
118
79
|
log,
|
|
@@ -121,27 +82,44 @@ export class Init {
|
|
|
121
82
|
devDependencyNames: devDependencies,
|
|
122
83
|
channel: channel ?? 'latest',
|
|
123
84
|
});
|
|
124
|
-
|
|
85
|
+
depsUpdated = true;
|
|
125
86
|
}
|
|
126
|
-
catch (
|
|
127
|
-
|
|
87
|
+
catch (e) {
|
|
88
|
+
const error = e;
|
|
89
|
+
logUpdateDependenciesError({
|
|
90
|
+
log,
|
|
91
|
+
error,
|
|
92
|
+
useNpm,
|
|
93
|
+
useYarn,
|
|
94
|
+
usePnpm,
|
|
95
|
+
useBun,
|
|
96
|
+
dependencies,
|
|
97
|
+
devDependencies,
|
|
98
|
+
channel,
|
|
99
|
+
});
|
|
128
100
|
}
|
|
129
|
-
if (
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
cwd: root,
|
|
134
|
-
options: {
|
|
135
|
-
useNpm,
|
|
136
|
-
useYarn,
|
|
137
|
-
usePnpm,
|
|
138
|
-
useBun,
|
|
139
|
-
},
|
|
140
|
-
});
|
|
141
|
-
log.info('Dependencies installed successfully');
|
|
101
|
+
if (depsUpdated) {
|
|
102
|
+
const packageManager = getPackageManager({ useNpm, useYarn, usePnpm, useBun });
|
|
103
|
+
if (skipInstall) {
|
|
104
|
+
log.info(`Installation skipped. Please, install them manually with ${chalkHighlightThing(packageManager + ' install')}`);
|
|
142
105
|
}
|
|
143
|
-
|
|
144
|
-
|
|
106
|
+
else {
|
|
107
|
+
try {
|
|
108
|
+
await installDependencies({
|
|
109
|
+
log,
|
|
110
|
+
cwd: root,
|
|
111
|
+
options: {
|
|
112
|
+
useNpm,
|
|
113
|
+
useYarn,
|
|
114
|
+
usePnpm,
|
|
115
|
+
useBun,
|
|
116
|
+
},
|
|
117
|
+
});
|
|
118
|
+
log.info('Dependencies installed successfully');
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
log.warn(`Failed to install dependencies. ${error.message}. Please, install them manually with ${chalkHighlightThing(packageManager + ' install')}`);
|
|
122
|
+
}
|
|
145
123
|
}
|
|
146
124
|
}
|
|
147
125
|
}
|
|
@@ -149,24 +127,24 @@ export class Init {
|
|
|
149
127
|
const { configAbsolutePath } = await createConfig({
|
|
150
128
|
root,
|
|
151
129
|
log,
|
|
152
|
-
options: { validationLibrary,
|
|
153
|
-
dryRun,
|
|
130
|
+
options: { validationLibrary, reactQuery, channel, lang, dryRun },
|
|
154
131
|
});
|
|
155
|
-
log.info('Config created successfully at ' + configAbsolutePath);
|
|
132
|
+
log.info('Config created successfully at ' + chalkHighlightThing(configAbsolutePath));
|
|
156
133
|
}
|
|
157
134
|
catch (error) {
|
|
158
135
|
log.error(`Failed to create config: ${error.message}`);
|
|
159
136
|
}
|
|
160
137
|
}
|
|
161
|
-
async main(prefix, { yes, logLevel, useNpm, useYarn, usePnpm, useBun, skipInstall, updateTsConfig, updateScripts, validationLibrary,
|
|
138
|
+
async main(prefix, { yes, logLevel, useNpm, useYarn, usePnpm, useBun, skipInstall, updateTsConfig, updateScripts, validationLibrary, reactQuery, lang, dryRun, channel, }) {
|
|
162
139
|
const cwd = process.cwd();
|
|
163
140
|
const root = path.resolve(cwd, prefix);
|
|
164
141
|
const log = getLogger(logLevel);
|
|
142
|
+
const pkgJson = await NPMCliPackageJson.load(root);
|
|
165
143
|
this.root = root;
|
|
166
144
|
this.log = log;
|
|
167
145
|
const configPaths = await getConfigPaths({ cwd, relativePath: prefix });
|
|
168
146
|
if (yes) {
|
|
169
|
-
return this.#init({ configPaths }, {
|
|
147
|
+
return this.#init({ configPaths, pkgJson }, {
|
|
170
148
|
useNpm: useNpm ?? (!useYarn && !usePnpm && !useBun),
|
|
171
149
|
useYarn: useYarn ?? false,
|
|
172
150
|
usePnpm: usePnpm ?? false,
|
|
@@ -175,9 +153,10 @@ export class Init {
|
|
|
175
153
|
updateTsConfig: updateTsConfig ?? true,
|
|
176
154
|
updateScripts: updateScripts ?? 'implicit',
|
|
177
155
|
validationLibrary: validationLibrary?.toLocaleLowerCase() === 'none' ? null : (validationLibrary ?? 'vovk-zod'),
|
|
178
|
-
|
|
156
|
+
reactQuery: reactQuery ?? true,
|
|
179
157
|
dryRun: dryRun ?? false,
|
|
180
158
|
channel: channel ?? 'latest',
|
|
159
|
+
lang: lang ?? [],
|
|
181
160
|
});
|
|
182
161
|
}
|
|
183
162
|
if (!(await getFileSystemEntryType(path.join(root, 'package.json')))) {
|
|
@@ -205,64 +184,65 @@ export class Init {
|
|
|
205
184
|
value: 'vovk-zod',
|
|
206
185
|
description: 'Use Zod for data validation',
|
|
207
186
|
},
|
|
208
|
-
{
|
|
209
|
-
name: 'vovk-yup',
|
|
210
|
-
value: 'vovk-yup',
|
|
211
|
-
description: 'Use Yup for data validation',
|
|
212
|
-
},
|
|
213
187
|
{
|
|
214
188
|
name: 'vovk-dto',
|
|
215
189
|
value: 'vovk-dto',
|
|
216
|
-
description: 'Use class-validator
|
|
190
|
+
description: 'Use class-validator for data validation. Also installs class-transformer, dto-mapped-types and reflect-metadata',
|
|
217
191
|
},
|
|
218
192
|
{ name: 'None', value: null, description: 'Install validation library later' },
|
|
219
193
|
],
|
|
220
194
|
})));
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
value: undefined,
|
|
247
|
-
description: 'Add the scripts manually',
|
|
248
|
-
},
|
|
249
|
-
],
|
|
250
|
-
}));
|
|
195
|
+
updateScripts ??= await select({
|
|
196
|
+
message: 'Do you want to update "dev" NPM script at package.json?',
|
|
197
|
+
default: 'implicit',
|
|
198
|
+
choices: [
|
|
199
|
+
{
|
|
200
|
+
name: 'Yes, use "concurrently" implicitly',
|
|
201
|
+
value: 'implicit',
|
|
202
|
+
description: `The script will use "concurrently" API to run "next dev" and "vovk dev" commands together and automatically find an available port ${chalk.whiteBright.bold(`"${getDevScript(pkgJson, 'implicit')}"`)}`,
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
name: 'Yes, use "concurrently" explicitly',
|
|
206
|
+
value: 'explicit',
|
|
207
|
+
description: `The script will use pre-defined PORT variable and run "next dev" and "vovk dev" as "concurrently" CLI arguments ${chalk.whiteBright.bold(`"${getDevScript(pkgJson, 'explicit')}"`)}`,
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
name: 'No',
|
|
211
|
+
value: undefined,
|
|
212
|
+
description: 'Add the NPM scripts manually',
|
|
213
|
+
},
|
|
214
|
+
],
|
|
215
|
+
});
|
|
216
|
+
reactQuery ??= await confirm({
|
|
217
|
+
default: false,
|
|
218
|
+
message: 'Do you want to use @tanstack/react-query for data fetching at React components?',
|
|
219
|
+
});
|
|
251
220
|
if (typeof updateTsConfig === 'undefined') {
|
|
252
221
|
let shouldAsk = false;
|
|
253
222
|
try {
|
|
254
|
-
shouldAsk = !(await checkTSConfigForExperimentalDecorators(root));
|
|
223
|
+
shouldAsk = !(await checkTSConfigForExperimentalDecorators(root)); // TODO also check for emitDecoratorMetadata when vovk-dto is used
|
|
255
224
|
}
|
|
256
225
|
catch (error) {
|
|
257
|
-
log.error(`Failed to check tsconfig.json for experimentalDecorators: ${error.message}`);
|
|
226
|
+
log.error(`Failed to check tsconfig.json for "experimentalDecorators": ${error.message}`);
|
|
258
227
|
}
|
|
259
228
|
if (shouldAsk) {
|
|
229
|
+
const keys = ['experimentalDecorators'];
|
|
230
|
+
if (validationLibrary === 'vovk-dto') {
|
|
231
|
+
keys.push('emitDecoratorMetadata');
|
|
232
|
+
}
|
|
260
233
|
updateTsConfig = await confirm({
|
|
261
|
-
message:
|
|
234
|
+
message: `Do you want to add ${keys.map((k) => `"${k}"`).join(' and ')} to tsconfig.json? (recommended)`,
|
|
262
235
|
});
|
|
263
236
|
}
|
|
264
237
|
}
|
|
265
|
-
await
|
|
238
|
+
lang ??= await checkbox({
|
|
239
|
+
message: 'Do you want to generate RPC client for other languages besides TypeScript?',
|
|
240
|
+
choices: [
|
|
241
|
+
{ name: 'Python', value: 'py' },
|
|
242
|
+
{ name: 'Rust', value: 'rs' },
|
|
243
|
+
],
|
|
244
|
+
});
|
|
245
|
+
await this.#init({ configPaths, pkgJson }, {
|
|
266
246
|
useNpm: useNpm ?? (!useYarn && !usePnpm && !useBun),
|
|
267
247
|
useYarn: useYarn ?? false,
|
|
268
248
|
usePnpm: usePnpm ?? false,
|
|
@@ -271,7 +251,8 @@ export class Init {
|
|
|
271
251
|
updateTsConfig,
|
|
272
252
|
updateScripts,
|
|
273
253
|
validationLibrary,
|
|
274
|
-
|
|
254
|
+
reactQuery,
|
|
255
|
+
lang,
|
|
275
256
|
dryRun,
|
|
276
257
|
channel,
|
|
277
258
|
});
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
import { InitOptions } from '../index.mjs';
|
|
2
1
|
import getLogger from '../utils/getLogger.mjs';
|
|
2
|
+
import type { InitOptions } from '../types.mjs';
|
|
3
|
+
type PackageManager = 'npm' | 'yarn' | 'pnpm' | 'bun';
|
|
4
|
+
export declare function getPackageManager(options: Pick<InitOptions, 'useNpm' | 'useYarn' | 'usePnpm' | 'useBun'>): PackageManager;
|
|
3
5
|
export default function installDependencies({ log, cwd, options, }: {
|
|
4
6
|
log: ReturnType<typeof getLogger>;
|
|
5
7
|
cwd: string;
|
|
6
8
|
options: Pick<InitOptions, 'useNpm' | 'useYarn' | 'usePnpm' | 'useBun'>;
|
|
7
9
|
}): Promise<void>;
|
|
10
|
+
export {};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { spawn } from 'child_process';
|
|
2
|
-
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import chalkHighlightThing from '../utils/chalkHighlightThing.mjs';
|
|
3
|
+
export function getPackageManager(options) {
|
|
3
4
|
if (options.useNpm)
|
|
4
5
|
return 'npm';
|
|
5
6
|
if (options.useYarn)
|
|
@@ -12,9 +13,10 @@ function getPackageManager(options) {
|
|
|
12
13
|
}
|
|
13
14
|
export default async function installDependencies({ log, cwd, options, }) {
|
|
14
15
|
const packageManager = getPackageManager(options);
|
|
15
|
-
log.info(`Installing dependencies at ${cwd} using ${packageManager}...`);
|
|
16
|
+
log.info(`Installing dependencies at ${chalkHighlightThing(cwd)} using ${chalkHighlightThing(packageManager)}...`);
|
|
16
17
|
await new Promise((resolve, reject) => {
|
|
17
|
-
const
|
|
18
|
+
const args = packageManager === 'yarn' ? ['install', '--non-interactive'] : ['install'];
|
|
19
|
+
const child = spawn(packageManager, args, { cwd, stdio: 'inherit' });
|
|
18
20
|
child.on('close', (code) => {
|
|
19
21
|
if (code === 0) {
|
|
20
22
|
resolve();
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { InitOptions } from '../types.mjs';
|
|
2
|
+
import type getLogger from '../utils/getLogger.mjs';
|
|
3
|
+
export default function logUpdateDependenciesError({ useNpm, useYarn, usePnpm, useBun, log, dependencies, devDependencies, error, channel, }: {
|
|
4
|
+
useNpm?: boolean;
|
|
5
|
+
useYarn?: boolean;
|
|
6
|
+
usePnpm?: boolean;
|
|
7
|
+
useBun?: boolean;
|
|
8
|
+
log: ReturnType<typeof getLogger>;
|
|
9
|
+
dependencies: string[];
|
|
10
|
+
devDependencies: string[];
|
|
11
|
+
error: Error;
|
|
12
|
+
channel: InitOptions['channel'];
|
|
13
|
+
}): void;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import chalkHighlightThing from '../utils/chalkHighlightThing.mjs';
|
|
2
|
+
import { getPackageManager } from './installDependencies.mjs';
|
|
3
|
+
export default function logUpdateDependenciesError({ useNpm, useYarn, usePnpm, useBun, log, dependencies, devDependencies, error, channel, }) {
|
|
4
|
+
const packageManager = getPackageManager({ useNpm, useYarn, usePnpm, useBun });
|
|
5
|
+
const installCommands = [];
|
|
6
|
+
const addChannel = (packageName) => {
|
|
7
|
+
const isVovk = packageName.startsWith('vovk') && packageName !== 'dto-mapped-types';
|
|
8
|
+
return isVovk ? (!channel || channel !== 'latest' ? `${packageName}@${channel}` : packageName) : packageName;
|
|
9
|
+
};
|
|
10
|
+
dependencies = dependencies.map(addChannel);
|
|
11
|
+
devDependencies = devDependencies.map(addChannel);
|
|
12
|
+
if (dependencies.length > 0) {
|
|
13
|
+
let depInstallCmd = '';
|
|
14
|
+
switch (packageManager) {
|
|
15
|
+
case 'npm':
|
|
16
|
+
depInstallCmd = `npm install ${dependencies.join(' ')}`;
|
|
17
|
+
break;
|
|
18
|
+
case 'yarn':
|
|
19
|
+
depInstallCmd = `yarn add ${dependencies.join(' ')}`;
|
|
20
|
+
break;
|
|
21
|
+
case 'pnpm':
|
|
22
|
+
depInstallCmd = `pnpm add ${dependencies.join(' ')}`;
|
|
23
|
+
break;
|
|
24
|
+
case 'bun':
|
|
25
|
+
depInstallCmd = `bun add ${dependencies.join(' ')}`;
|
|
26
|
+
break;
|
|
27
|
+
}
|
|
28
|
+
installCommands.push(depInstallCmd);
|
|
29
|
+
}
|
|
30
|
+
if (devDependencies.length > 0) {
|
|
31
|
+
let devDepInstallCmd = '';
|
|
32
|
+
switch (packageManager) {
|
|
33
|
+
case 'npm':
|
|
34
|
+
devDepInstallCmd = `npm install -D ${devDependencies.join(' ')}`;
|
|
35
|
+
break;
|
|
36
|
+
case 'yarn':
|
|
37
|
+
devDepInstallCmd = `yarn add --dev ${devDependencies.join(' ')}`;
|
|
38
|
+
break;
|
|
39
|
+
case 'pnpm':
|
|
40
|
+
devDepInstallCmd = `pnpm add -D ${devDependencies.join(' ')}`;
|
|
41
|
+
break;
|
|
42
|
+
case 'bun':
|
|
43
|
+
devDepInstallCmd = `bun add -d ${devDependencies.join(' ')}`;
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
installCommands.push(devDepInstallCmd);
|
|
47
|
+
}
|
|
48
|
+
const installCmd = installCommands.join(' && ');
|
|
49
|
+
// Log the error with the appropriate manual installation instructions
|
|
50
|
+
log.warn(`Failed to update dependencies: ${error.message}. Please, install them manually with ${chalkHighlightThing(installCmd)}`);
|
|
51
|
+
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import getLogger from '../utils/getLogger.mjs';
|
|
1
|
+
import type getLogger from '../utils/getLogger.mjs';
|
|
2
|
+
import { InitOptions } from '../types.mjs';
|
|
2
3
|
export default function updateDependenciesWithoutInstalling({ log, dir, dependencyNames, devDependencyNames, channel, }: {
|
|
3
4
|
log: ReturnType<typeof getLogger>;
|
|
4
5
|
dir: string;
|
|
5
6
|
dependencyNames: string[];
|
|
6
7
|
devDependencyNames: string[];
|
|
7
|
-
channel: '
|
|
8
|
+
channel: InitOptions['channel'];
|
|
8
9
|
}): Promise<void>;
|
|
@@ -1,25 +1,60 @@
|
|
|
1
|
-
import fs from 'fs/promises';
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import chalk from 'chalk';
|
|
2
4
|
import getNPMPackageMetadata from '../utils/getNPMPackageMetadata.mjs';
|
|
3
|
-
|
|
4
|
-
async function updateDeps({ packageJson, packageNames, channel, key, }) {
|
|
5
|
+
async function updateDeps({ packageJson, packageNames, channel, key, log, }) {
|
|
5
6
|
return Promise.all(packageNames.map(async (packageName) => {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
let name;
|
|
8
|
+
let version;
|
|
9
|
+
if (packageName.startsWith('@')) {
|
|
10
|
+
// Handle scoped packages (@org/name@version)
|
|
11
|
+
const lastAtIndex = packageName.lastIndexOf('@');
|
|
12
|
+
if (lastAtIndex > 0) {
|
|
13
|
+
name = packageName.substring(0, lastAtIndex);
|
|
14
|
+
version = packageName.substring(lastAtIndex + 1);
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
name = packageName;
|
|
18
|
+
version = undefined;
|
|
19
|
+
}
|
|
13
20
|
}
|
|
14
|
-
|
|
21
|
+
else {
|
|
22
|
+
// Handle regular packages (name@version)
|
|
23
|
+
const parts = packageName.split('@');
|
|
24
|
+
name = parts[0];
|
|
25
|
+
version = parts[1];
|
|
26
|
+
}
|
|
27
|
+
if (version) {
|
|
28
|
+
packageJson[key] ??= {};
|
|
29
|
+
packageJson[key][name] = version;
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
let metadata;
|
|
33
|
+
try {
|
|
34
|
+
metadata = await getNPMPackageMetadata(name);
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
log.error(`Failed to fetch metadata for package ${name}@${channel ?? 'latest'}: ${error}`);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
const isVovk = name.startsWith('vovk') && name !== 'dto-mapped-types';
|
|
41
|
+
const latestVersion = metadata['dist-tags'][isVovk ? (channel ?? 'latest') : 'latest'];
|
|
42
|
+
packageJson[key] ??= {};
|
|
43
|
+
packageJson[key][name] = `^${latestVersion}`;
|
|
15
44
|
}));
|
|
16
45
|
}
|
|
17
46
|
export default async function updateDependenciesWithoutInstalling({ log, dir, dependencyNames, devDependencyNames, channel, }) {
|
|
18
47
|
const packageJsonPath = path.join(dir, 'package.json');
|
|
19
48
|
const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf-8'));
|
|
20
|
-
await updateDeps({ packageJson, packageNames: dependencyNames, channel, key: 'dependencies' });
|
|
21
|
-
|
|
22
|
-
await updateDeps({ packageJson, packageNames: devDependencyNames, channel, key: 'devDependencies' });
|
|
23
|
-
log.debug('Updated devDependencies in package.json');
|
|
49
|
+
await updateDeps({ packageJson, packageNames: dependencyNames, channel, log, key: 'dependencies' });
|
|
50
|
+
await updateDeps({ packageJson, packageNames: devDependencyNames, channel, log, key: 'devDependencies' });
|
|
24
51
|
await fs.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2));
|
|
52
|
+
log.info('Added dependencies to package.json:');
|
|
53
|
+
for (const dependency of dependencyNames) {
|
|
54
|
+
log.raw.info(` - ${chalk.cyan(dependency)}`);
|
|
55
|
+
}
|
|
56
|
+
log.info('Added devDependencies to package.json:');
|
|
57
|
+
for (const dependency of devDependencyNames) {
|
|
58
|
+
log.raw.info(` - ${chalk.cyan(dependency)}`);
|
|
59
|
+
}
|
|
25
60
|
}
|
|
@@ -1 +1,3 @@
|
|
|
1
|
-
|
|
1
|
+
import NPMCliPackageJson from '@npmcli/package-json';
|
|
2
|
+
export declare function getDevScript(pkgJson: NPMCliPackageJson, updateScriptsMode: 'implicit' | 'explicit'): string;
|
|
3
|
+
export default function updateNPMScripts(pkgJson: NPMCliPackageJson, root: string, updateScriptsMode: 'implicit' | 'explicit'): Promise<void>;
|