vovk-cli 0.0.1-draft.5 → 0.0.1-draft.53
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/README.md +29 -1
- package/client-templates/main/main.d.ts.ejs +15 -0
- package/client-templates/main/main.js.ejs +16 -0
- package/client-templates/module/module.d.ts.ejs +15 -0
- package/client-templates/module/module.js.ejs +20 -0
- package/client-templates/python/__init__.py +276 -0
- package/client-templates/ts/index.ts.ejs +25 -0
- package/dist/dev/diffSchema.d.mts +36 -0
- package/dist/{watcher → dev}/diffSchema.mjs +3 -11
- package/dist/dev/ensureClient.d.mts +5 -0
- package/dist/dev/ensureClient.mjs +30 -0
- package/dist/{watcher → dev}/ensureSchemaFiles.d.mts +3 -0
- package/dist/{watcher → dev}/ensureSchemaFiles.mjs +6 -4
- package/dist/dev/index.d.mts +6 -0
- package/dist/{watcher → dev}/index.mjs +128 -62
- package/dist/{watcher → dev}/isMetadataEmpty.mjs +1 -1
- package/dist/{watcher → dev}/logDiffResult.d.mts +2 -2
- package/dist/dev/logDiffResult.mjs +57 -0
- package/dist/{watcher → dev}/writeOneSchemaFile.d.mts +1 -1
- package/dist/{watcher → dev}/writeOneSchemaFile.mjs +3 -3
- package/dist/generate/getClientTemplates.d.mts +11 -0
- package/dist/generate/getClientTemplates.mjs +27 -0
- package/dist/generate/index.d.mts +12 -0
- package/dist/generate/index.mjs +79 -0
- package/dist/getProjectInfo/getConfig.mjs +5 -5
- package/dist/getProjectInfo/getConfigAbsolutePaths.mjs +2 -2
- package/dist/getProjectInfo/getRelativeSrcRoot.mjs +3 -3
- package/dist/getProjectInfo/getUserConfig.mjs +3 -1
- package/dist/getProjectInfo/importUncachedModule.mjs +0 -1
- package/dist/getProjectInfo/importUncachedModuleWorker.mjs +0 -1
- package/dist/getProjectInfo/index.d.mts +2 -1
- package/dist/getProjectInfo/index.mjs +14 -10
- package/dist/index.d.mts +1 -27
- package/dist/index.mjs +47 -60
- package/dist/init/checkTSConfigForExperimentalDecorators.mjs +2 -2
- package/dist/init/createConfig.d.mts +3 -4
- package/dist/init/createConfig.mjs +6 -8
- package/dist/init/getTemplateFilesFromPackage.d.mts +2 -1
- package/dist/init/getTemplateFilesFromPackage.mjs +4 -5
- package/dist/init/index.d.mts +1 -2
- package/dist/init/index.mjs +46 -93
- package/dist/init/installDependencies.d.mts +4 -1
- package/dist/init/installDependencies.mjs +2 -2
- package/dist/init/logUpdateDependenciesError.d.mts +11 -0
- package/dist/init/logUpdateDependenciesError.mjs +45 -0
- package/dist/init/updateDependenciesWithoutInstalling.d.mts +3 -2
- package/dist/init/updateDependenciesWithoutInstalling.mjs +13 -8
- package/dist/init/updateNPMScripts.d.mts +3 -1
- package/dist/init/updateNPMScripts.mjs +10 -6
- package/dist/init/updateTypeScriptConfig.mjs +2 -2
- package/dist/initProgram.d.mts +2 -0
- package/dist/initProgram.mjs +21 -0
- package/dist/locateSegments.d.mts +7 -1
- package/dist/locateSegments.mjs +9 -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 +4 -4
- package/dist/new/newModule.d.mts +4 -4
- package/dist/new/newModule.mjs +45 -33
- package/dist/new/newSegment.mjs +6 -6
- package/dist/new/render.mjs +2 -5
- package/dist/postinstall.mjs +16 -17
- package/dist/types.d.mts +42 -9
- package/dist/utils/debounceWithArgs.d.mts +1 -1
- package/dist/utils/debounceWithArgs.mjs +24 -9
- package/dist/utils/formatLoggedSegmentName.mjs +1 -1
- package/dist/utils/getAvailablePort.mjs +3 -2
- package/dist/utils/getFileSystemEntryType.mjs +1 -1
- package/package.json +20 -17
- package/templates/controller.ejs +12 -11
- package/templates/service.ejs +6 -6
- package/dist/generateClient.d.mts +0 -7
- package/dist/generateClient.mjs +0 -97
- package/dist/watcher/diffSchema.d.mts +0 -43
- package/dist/watcher/index.d.mts +0 -6
- package/dist/watcher/logDiffResult.mjs +0 -90
- package/templates/worker.ejs +0 -1
- /package/dist/{watcher → dev}/isMetadataEmpty.d.mts +0 -0
|
@@ -6,11 +6,12 @@ export default function getProjectInfo({ port: givenPort, clientOutDir, cwd, }?:
|
|
|
6
6
|
}): Promise<{
|
|
7
7
|
cwd: string;
|
|
8
8
|
port: string;
|
|
9
|
-
|
|
9
|
+
apiRoot: string;
|
|
10
10
|
apiDir: string;
|
|
11
11
|
srcRoot: string;
|
|
12
12
|
schemaOutImportPath: string;
|
|
13
13
|
fetcherClientImportPath: string;
|
|
14
|
+
createRPCImportPath: string;
|
|
14
15
|
validateOnClientImportPath: string | null;
|
|
15
16
|
config: Required<import("../types.mjs").VovkConfig>;
|
|
16
17
|
log: {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import path from 'path';
|
|
1
|
+
import path from 'node:path';
|
|
2
2
|
import getConfig from './getConfig.mjs';
|
|
3
3
|
import getLogger from '../utils/getLogger.mjs';
|
|
4
4
|
export default async function getProjectInfo({ port: givenPort, clientOutDir, cwd = process.cwd(), } = {}) {
|
|
@@ -6,15 +6,18 @@ export default async function getProjectInfo({ port: givenPort, clientOutDir, cw
|
|
|
6
6
|
// Make PORT available to the config file at getConfig
|
|
7
7
|
process.env.PORT = port;
|
|
8
8
|
const { config, srcRoot, configAbsolutePaths, userConfig, error } = await getConfig({ clientOutDir, cwd });
|
|
9
|
-
const
|
|
9
|
+
const apiRoot = `${config.origin ?? ''}/${config.rootEntry}`;
|
|
10
10
|
const apiDir = path.join(srcRoot, 'app', config.rootEntry);
|
|
11
|
-
const schemaOutImportPath = path.relative(config.clientOutDir, config.schemaOutDir);
|
|
12
|
-
const fetcherClientImportPath = config.
|
|
13
|
-
? path.relative(config.clientOutDir, config.
|
|
14
|
-
: config.
|
|
15
|
-
const
|
|
16
|
-
? path.relative(config.clientOutDir, config.
|
|
17
|
-
: config.
|
|
11
|
+
const schemaOutImportPath = path.relative(config.clientOutDir, config.schemaOutDir).replace(/\\/g, '/'); // windows fix
|
|
12
|
+
const fetcherClientImportPath = config.fetcherPath.startsWith('.')
|
|
13
|
+
? path.relative(config.clientOutDir, config.fetcherPath)
|
|
14
|
+
: config.fetcherPath;
|
|
15
|
+
const createRPCImportPath = config.createRPCPath.startsWith('.')
|
|
16
|
+
? path.relative(config.clientOutDir, config.createRPCPath)
|
|
17
|
+
: config.createRPCPath;
|
|
18
|
+
const validateOnClientImportPath = config.validateOnClientPath?.startsWith('.')
|
|
19
|
+
? path.relative(config.clientOutDir, config.validateOnClientPath)
|
|
20
|
+
: config.validateOnClientPath;
|
|
18
21
|
const log = getLogger(config.logLevel);
|
|
19
22
|
if (configAbsolutePaths.length > 1) {
|
|
20
23
|
log.warn(`Multiple config files found. Using the first one: ${configAbsolutePaths[0]}`);
|
|
@@ -25,11 +28,12 @@ export default async function getProjectInfo({ port: givenPort, clientOutDir, cw
|
|
|
25
28
|
return {
|
|
26
29
|
cwd,
|
|
27
30
|
port,
|
|
28
|
-
|
|
31
|
+
apiRoot,
|
|
29
32
|
apiDir,
|
|
30
33
|
srcRoot,
|
|
31
34
|
schemaOutImportPath,
|
|
32
35
|
fetcherClientImportPath,
|
|
36
|
+
createRPCImportPath,
|
|
33
37
|
validateOnClientImportPath,
|
|
34
38
|
config,
|
|
35
39
|
log,
|
package/dist/index.d.mts
CHANGED
|
@@ -1,30 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { Command } from 'commander';
|
|
3
|
-
import type { LogLevelNames } from 'loglevel';
|
|
4
|
-
import type { VovkConfig, VovkEnv } from './types.mjs';
|
|
5
2
|
import 'dotenv/config';
|
|
3
|
+
import type { VovkConfig, VovkEnv } from './types.mjs';
|
|
6
4
|
export type { VovkConfig, VovkEnv };
|
|
7
|
-
export interface InitOptions {
|
|
8
|
-
yes?: boolean;
|
|
9
|
-
logLevel: LogLevelNames;
|
|
10
|
-
useNpm?: boolean;
|
|
11
|
-
useYarn?: boolean;
|
|
12
|
-
usePnpm?: boolean;
|
|
13
|
-
useBun?: boolean;
|
|
14
|
-
skipInstall?: boolean;
|
|
15
|
-
updateTsConfig?: boolean;
|
|
16
|
-
updateScripts?: 'implicit' | 'explicit';
|
|
17
|
-
validationLibrary?: string | null;
|
|
18
|
-
validateOnClient?: boolean;
|
|
19
|
-
dryRun?: boolean;
|
|
20
|
-
channel?: 'latest' | 'beta' | 'dev';
|
|
21
|
-
}
|
|
22
|
-
export interface NewOptions {
|
|
23
|
-
dryRun?: boolean;
|
|
24
|
-
template?: string;
|
|
25
|
-
dirName?: string;
|
|
26
|
-
fileName?: string;
|
|
27
|
-
overwrite?: boolean;
|
|
28
|
-
}
|
|
29
|
-
declare const program: Command;
|
|
30
|
-
export declare function initProgram(p: typeof program, command: string): Command;
|
package/dist/index.mjs
CHANGED
|
@@ -1,51 +1,62 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import path from 'path';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { readFileSync } from 'node:fs';
|
|
4
|
+
import { pathToFileURL } from 'node:url';
|
|
5
|
+
import 'dotenv/config';
|
|
3
6
|
import { Command } from 'commander';
|
|
4
|
-
import { readFileSync } from 'fs';
|
|
5
7
|
import concurrently from 'concurrently';
|
|
6
8
|
import getAvailablePort from './utils/getAvailablePort.mjs';
|
|
7
9
|
import getProjectInfo from './getProjectInfo/index.mjs';
|
|
8
|
-
import
|
|
10
|
+
import generate from './generate/index.mjs';
|
|
9
11
|
import locateSegments from './locateSegments.mjs';
|
|
10
|
-
import {
|
|
11
|
-
import { Init } from './init/index.mjs';
|
|
12
|
+
import { VovkDev } from './dev/index.mjs';
|
|
12
13
|
import newComponents from './new/index.mjs';
|
|
13
|
-
import '
|
|
14
|
+
import initProgram from './initProgram.mjs';
|
|
14
15
|
const program = new Command();
|
|
15
16
|
const packageJSON = JSON.parse(readFileSync(path.join(import.meta.dirname, '../package.json'), 'utf-8'));
|
|
16
17
|
program.name('vovk').description('Vovk CLI').version(packageJSON.version);
|
|
18
|
+
initProgram(program.command('init'));
|
|
17
19
|
program
|
|
18
20
|
.command('dev')
|
|
19
|
-
.
|
|
20
|
-
.
|
|
21
|
-
.option('--next-dev', '
|
|
21
|
+
.alias('d')
|
|
22
|
+
.description('start schema watcher (optional flag --next-dev to start it with Next.js)')
|
|
23
|
+
.option('--next-dev', 'start schema watcher and Next.js with automatic port allocation')
|
|
24
|
+
.option('--exit', 'kill the processe when schema and client is generated')
|
|
22
25
|
.allowUnknownOption(true)
|
|
23
26
|
.action(async (options, command) => {
|
|
27
|
+
const { nextDev, exit = false } = options;
|
|
24
28
|
const portAttempts = 30;
|
|
25
|
-
const PORT = !
|
|
29
|
+
const PORT = !nextDev
|
|
26
30
|
? process.env.PORT
|
|
27
31
|
: process.env.PORT ||
|
|
28
|
-
(await getAvailablePort(3000, portAttempts, 0, (failedPort, tryingPort) =>
|
|
29
|
-
|
|
32
|
+
(await getAvailablePort(3000, portAttempts, 0, (failedPort, tryingPort) =>
|
|
33
|
+
// eslint-disable-next-line no-console
|
|
34
|
+
console.warn(`🐺 Port ${failedPort} is in use, trying ${tryingPort} instead.`)).catch(() => {
|
|
35
|
+
throw new Error(`🐺 ❌ Failed to find an available port after ${portAttempts} attempts`);
|
|
30
36
|
}));
|
|
31
37
|
if (!PORT) {
|
|
32
38
|
throw new Error('🐺 ❌ PORT env variable is required');
|
|
33
39
|
}
|
|
34
|
-
if (
|
|
40
|
+
if (nextDev) {
|
|
35
41
|
const { result } = concurrently([
|
|
36
|
-
{
|
|
37
|
-
command: `node ${import.meta.dirname}/watcher/index.mjs`,
|
|
38
|
-
name: 'Vovk.ts Schema Watcher',
|
|
39
|
-
env: Object.assign({ PORT, __VOVK_START_WATCHER_IN_STANDALONE_MODE__: 'true' }, options.clientOut ? { VOVK_CLIENT_OUT_DIR: options.clientOut } : {}),
|
|
40
|
-
},
|
|
41
42
|
{
|
|
42
43
|
command: `npx next dev ${command.args.join(' ')}`,
|
|
43
44
|
name: 'Next.js Development Server',
|
|
44
45
|
env: { PORT },
|
|
45
46
|
},
|
|
47
|
+
{
|
|
48
|
+
command: `node ${import.meta.dirname}/dev/index.mjs`,
|
|
49
|
+
name: 'Vovk Dev Watcher',
|
|
50
|
+
env: {
|
|
51
|
+
PORT,
|
|
52
|
+
__VOVK_START_WATCHER_IN_STANDALONE_MODE__: 'true',
|
|
53
|
+
__VOVK_EXIT__: exit ? 'true' : 'false',
|
|
54
|
+
},
|
|
55
|
+
},
|
|
46
56
|
], {
|
|
47
57
|
killOthers: ['failure', 'success'],
|
|
48
58
|
prefix: 'none',
|
|
59
|
+
successCondition: 'first',
|
|
49
60
|
});
|
|
50
61
|
try {
|
|
51
62
|
await result;
|
|
@@ -55,65 +66,41 @@ program
|
|
|
55
66
|
}
|
|
56
67
|
}
|
|
57
68
|
else {
|
|
58
|
-
void new
|
|
69
|
+
void new VovkDev().start({ exit });
|
|
59
70
|
}
|
|
60
71
|
});
|
|
61
72
|
program
|
|
62
73
|
.command('generate')
|
|
74
|
+
.alias('g')
|
|
63
75
|
.description('Generate client')
|
|
64
|
-
.option('--client-out <path>', '
|
|
76
|
+
.option('--out, --client-out-dir <path>', 'path to output directory')
|
|
77
|
+
.option('--template, --templates <templates...>', 'client code templates ("ts", "compiled", "python", "none", a custom path)')
|
|
78
|
+
.option('--full-schema [fileName]', 'generate client with full schema')
|
|
79
|
+
.option('--prettify', 'prettify output files')
|
|
65
80
|
.action(async (options) => {
|
|
66
|
-
const
|
|
81
|
+
const { clientOutDir, templates, prettify, fullSchema } = options;
|
|
82
|
+
const projectInfo = await getProjectInfo({ clientOutDir });
|
|
67
83
|
const { cwd, config, apiDir } = projectInfo;
|
|
68
|
-
const segments = await locateSegments(apiDir);
|
|
84
|
+
const segments = await locateSegments({ dir: apiDir, config });
|
|
69
85
|
const schemaOutAbsolutePath = path.join(cwd, config.schemaOutDir);
|
|
70
|
-
const
|
|
71
|
-
await
|
|
86
|
+
const schemaImportUrl = pathToFileURL(path.join(schemaOutAbsolutePath, 'index.js')).href;
|
|
87
|
+
const { default: segmentsSchema } = (await import(schemaImportUrl));
|
|
88
|
+
await generate({ projectInfo, segments, segmentsSchema, templates, prettify, fullSchema });
|
|
72
89
|
});
|
|
73
|
-
// reused at vovk-init
|
|
74
|
-
export function initProgram(p, command) {
|
|
75
|
-
return p
|
|
76
|
-
.command(command + '[prefix]')
|
|
77
|
-
.description('Initialize Vovk project')
|
|
78
|
-
.option('-Y, --yes', 'Skip all prompts and use default values')
|
|
79
|
-
.option('--log-level <level>', 'Set log level', 'info')
|
|
80
|
-
.option('--use-npm', 'Use npm as package manager')
|
|
81
|
-
.option('--use-yarn', 'Use yarn as package manager')
|
|
82
|
-
.option('--use-pnpm', 'Use pnpm as package manager')
|
|
83
|
-
.option('--use-bun', 'Use bun as package manager')
|
|
84
|
-
.option('--skip-install', 'Skip installing dependencies')
|
|
85
|
-
.option('--update-ts-config', 'Update tsconfig.json')
|
|
86
|
-
.option('--update-scripts <mode>', 'Update package.json scripts (implicit or explicit)')
|
|
87
|
-
.option('--validation-library <library>', 'Validation library to use ("vovk-zod", "vovk-yup", "vovk-dto" or another). Set to "none" to skip validation')
|
|
88
|
-
.option('--validate-on-client', 'Validate on client')
|
|
89
|
-
.option('--channel <channel>', 'Channel to use for fetching packages', 'latest')
|
|
90
|
-
.option('--dry-run', 'Do not write files to disk')
|
|
91
|
-
.action((prefix = '.', options) => new Init().main(prefix, options));
|
|
92
|
-
}
|
|
93
|
-
initProgram(program, 'init ');
|
|
94
90
|
program
|
|
95
91
|
.command('new [components...]')
|
|
96
92
|
.alias('n')
|
|
97
|
-
.description('
|
|
98
|
-
.option('-
|
|
99
|
-
.option('--template', '
|
|
100
|
-
.option('--dir
|
|
101
|
-
.option('--
|
|
102
|
-
.option('--dry-run', '
|
|
93
|
+
.description('create new components. "vovk new [...components] [segmentName/]moduleName" to create a new module or "vovk new segment [segmentName]" to create a new segment')
|
|
94
|
+
.option('-o, --overwrite', 'overwrite existing files')
|
|
95
|
+
.option('--template, --templates <templates...>', 'override config template; accepts an array of strings that correspond the order of the components')
|
|
96
|
+
.option('--dir <dirname>', 'override dirName in template file; relative to the root of the project')
|
|
97
|
+
.option('--no-segment-update', 'do not update segment files when creating a new module')
|
|
98
|
+
.option('--dry-run', 'do not write files to disk')
|
|
103
99
|
.action((components, options) => newComponents(components, options));
|
|
104
100
|
program
|
|
105
101
|
.command('help')
|
|
106
102
|
.description('Show help message')
|
|
107
103
|
.action(() => program.help());
|
|
108
|
-
/*
|
|
109
|
-
TODO
|
|
110
|
-
vovk new segment [segmentName]
|
|
111
|
-
vovk new controller service [segmentName/]moduleName
|
|
112
|
-
vovk new c s w [segmentName/]moduleName
|
|
113
|
-
|
|
114
|
-
vovk c s w userApi/user
|
|
115
|
-
vovk new c s w user
|
|
116
|
-
*/
|
|
117
104
|
program.parse(process.argv);
|
|
118
105
|
if (!process.argv.slice(2).length) {
|
|
119
106
|
program.outputHelp();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import path from 'path';
|
|
2
|
-
import fs from 'fs/promises';
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import fs from 'node:fs/promises';
|
|
3
3
|
import * as jsonc from 'jsonc-parser';
|
|
4
4
|
export default async function checkTSConfigForExperimentalDecorators(root) {
|
|
5
5
|
const tsconfigPath = path.resolve(root, 'tsconfig.json');
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import type getLogger from '../utils/getLogger.mjs';
|
|
2
|
-
import type { InitOptions } from '../
|
|
3
|
-
export default function createConfig({ root, log,
|
|
2
|
+
import type { InitOptions } from '../types.mjs';
|
|
3
|
+
export default function createConfig({ root, log, options: { validationLibrary, validateOnClient, channel, dryRun }, }: {
|
|
4
4
|
root: string;
|
|
5
5
|
log: ReturnType<typeof getLogger>;
|
|
6
|
-
dryRun
|
|
7
|
-
options: Pick<InitOptions, 'validationLibrary' | 'validateOnClient'>;
|
|
6
|
+
options: Pick<InitOptions, 'validationLibrary' | 'validateOnClient' | 'channel' | 'dryRun'>;
|
|
8
7
|
}): Promise<{
|
|
9
8
|
configAbsolutePath: string;
|
|
10
9
|
}>;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import path from 'path';
|
|
2
|
-
import fs from 'fs/promises';
|
|
3
|
-
import getFileSystemEntryType, { FileSystemEntryType } from '../utils/getFileSystemEntryType.mjs';
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import fs from 'node:fs/promises';
|
|
4
3
|
import getTemplateFilesFromPackage from './getTemplateFilesFromPackage.mjs';
|
|
5
4
|
import prettify from '../utils/prettify.mjs';
|
|
6
|
-
|
|
5
|
+
import getFileSystemEntryType, { FileSystemEntryType } from '../utils/getFileSystemEntryType.mjs';
|
|
6
|
+
export default async function createConfig({ root, log, options: { validationLibrary, validateOnClient, channel, dryRun }, }) {
|
|
7
7
|
const config = {};
|
|
8
8
|
const dotConfigPath = path.join(root, '.config');
|
|
9
9
|
const dir = (await getFileSystemEntryType(dotConfigPath)) === FileSystemEntryType.DIRECTORY ? dotConfigPath : root;
|
|
@@ -14,15 +14,13 @@ export default async function createConfig({ root, log, dryRun, options: { valid
|
|
|
14
14
|
const templates = {
|
|
15
15
|
controller: 'vovk-cli/templates/controller.ejs',
|
|
16
16
|
service: 'vovk-cli/templates/service.ejs',
|
|
17
|
-
worker: 'vovk-cli/templates/worker.ejs',
|
|
18
17
|
};
|
|
19
18
|
if (validationLibrary) {
|
|
20
|
-
config.validationLibrary = validationLibrary;
|
|
21
19
|
if (validateOnClient) {
|
|
22
|
-
config.
|
|
20
|
+
config.validateOnClientPath = `${validationLibrary}/validateOnClient`;
|
|
23
21
|
}
|
|
24
22
|
try {
|
|
25
|
-
const validationTemplates = await getTemplateFilesFromPackage(validationLibrary);
|
|
23
|
+
const validationTemplates = await getTemplateFilesFromPackage(validationLibrary, channel);
|
|
26
24
|
Object.assign(templates, validationTemplates);
|
|
27
25
|
}
|
|
28
26
|
catch (error) {
|
|
@@ -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,14 @@
|
|
|
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
|
+
// Crereated with AI
|
|
5
6
|
/**
|
|
6
7
|
* Retrieves a list of files in the 'templates' folder of an NPM package.
|
|
7
8
|
* @param packageName - The name of the NPM package.
|
|
8
9
|
* @returns A promise that resolves to an array of file paths.
|
|
9
10
|
*/
|
|
10
|
-
export default async function
|
|
11
|
-
) {
|
|
11
|
+
export default async function getTemplateFilesFromPackage(packageName, channel = 'latest') {
|
|
12
12
|
const metadata = await getNPMPackageMetadata(packageName);
|
|
13
13
|
const latestVersion = metadata['dist-tags'][channel];
|
|
14
14
|
const tarballUrl = metadata.versions[latestVersion].dist.tarball;
|
|
@@ -37,7 +37,6 @@ function extractTemplatesFromTarball(tarballBuffer) {
|
|
|
37
37
|
const files = [];
|
|
38
38
|
extract.on('entry', (header, stream, next) => {
|
|
39
39
|
const filePath = header.name;
|
|
40
|
-
// TODO revisit comments
|
|
41
40
|
// Check if the file is in the 'templates' folder
|
|
42
41
|
if (filePath.startsWith('package/templates/')) {
|
|
43
42
|
files.push(filePath.replace('package/', ''));
|
package/dist/init/index.d.mts
CHANGED
package/dist/init/index.mjs
CHANGED
|
@@ -1,80 +1,25 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/*
|
|
3
|
-
npx vovk-cli init
|
|
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
1
|
import { confirm, select } from '@inquirer/prompts';
|
|
60
|
-
import path from 'path';
|
|
61
|
-
import fs from 'fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import fs from 'node:fs/promises';
|
|
62
4
|
import getConfigPaths from '../getProjectInfo/getConfigAbsolutePaths.mjs';
|
|
63
5
|
import chalk from 'chalk';
|
|
64
6
|
import getFileSystemEntryType from '../utils/getFileSystemEntryType.mjs';
|
|
65
|
-
import installDependencies from './installDependencies.mjs';
|
|
7
|
+
import installDependencies, { getPackageManager } from './installDependencies.mjs';
|
|
66
8
|
import getLogger from '../utils/getLogger.mjs';
|
|
67
9
|
import createConfig from './createConfig.mjs';
|
|
68
|
-
import updateNPMScripts from './updateNPMScripts.mjs';
|
|
10
|
+
import updateNPMScripts, { getDevScript } from './updateNPMScripts.mjs';
|
|
69
11
|
import checkTSConfigForExperimentalDecorators from './checkTSConfigForExperimentalDecorators.mjs';
|
|
70
12
|
import updateTypeScriptConfig from './updateTypeScriptConfig.mjs';
|
|
71
13
|
import updateDependenciesWithoutInstalling from './updateDependenciesWithoutInstalling.mjs';
|
|
14
|
+
import logUpdateDependenciesError from './logUpdateDependenciesError.mjs';
|
|
15
|
+
import chalkHighlightThing from '../utils/chalkHighlightThing.mjs';
|
|
16
|
+
import NPMCliPackageJson from '@npmcli/package-json';
|
|
72
17
|
export class Init {
|
|
73
18
|
root;
|
|
74
19
|
log;
|
|
75
|
-
async #init({ configPaths, }, { useNpm, useYarn, usePnpm, useBun, skipInstall, updateTsConfig, updateScripts, validationLibrary, validateOnClient, dryRun, channel, }) {
|
|
20
|
+
async #init({ configPaths, pkgJson, }, { useNpm, useYarn, usePnpm, useBun, skipInstall, updateTsConfig, updateScripts, validationLibrary, validateOnClient, dryRun, channel, }) {
|
|
76
21
|
const { log, root } = this;
|
|
77
|
-
const dependencies = ['vovk'];
|
|
22
|
+
const dependencies = ['vovk', 'vovk-client'];
|
|
78
23
|
const devDependencies = ['vovk-cli'];
|
|
79
24
|
// delete older config files
|
|
80
25
|
if (configPaths.length) {
|
|
@@ -86,13 +31,13 @@ export class Init {
|
|
|
86
31
|
dependencies.push(...({
|
|
87
32
|
'vovk-zod': ['zod'],
|
|
88
33
|
'vovk-yup': ['yup'],
|
|
89
|
-
'vovk-dto': ['class-validator', 'class-transformer'],
|
|
34
|
+
'vovk-dto': ['class-validator', 'class-transformer', 'vovk-mapped-types', 'reflect-metadata'],
|
|
90
35
|
}[validationLibrary] ?? []));
|
|
91
36
|
}
|
|
92
37
|
if (updateScripts) {
|
|
93
38
|
try {
|
|
94
39
|
if (!dryRun)
|
|
95
|
-
await updateNPMScripts(root, updateScripts);
|
|
40
|
+
await updateNPMScripts(pkgJson, root, updateScripts);
|
|
96
41
|
log.info('Updated scripts at package.json');
|
|
97
42
|
}
|
|
98
43
|
catch (error) {
|
|
@@ -113,6 +58,7 @@ export class Init {
|
|
|
113
58
|
}
|
|
114
59
|
}
|
|
115
60
|
if (!dryRun) {
|
|
61
|
+
let depsUpdated = false;
|
|
116
62
|
try {
|
|
117
63
|
await updateDependenciesWithoutInstalling({
|
|
118
64
|
log,
|
|
@@ -121,27 +67,34 @@ export class Init {
|
|
|
121
67
|
devDependencyNames: devDependencies,
|
|
122
68
|
channel: channel ?? 'latest',
|
|
123
69
|
});
|
|
124
|
-
|
|
70
|
+
depsUpdated = true;
|
|
125
71
|
}
|
|
126
|
-
catch (
|
|
127
|
-
|
|
72
|
+
catch (e) {
|
|
73
|
+
const error = e;
|
|
74
|
+
logUpdateDependenciesError({ log, error, useNpm, useYarn, usePnpm, useBun, dependencies, devDependencies });
|
|
128
75
|
}
|
|
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');
|
|
76
|
+
if (depsUpdated) {
|
|
77
|
+
const packageManager = getPackageManager({ useNpm, useYarn, usePnpm, useBun });
|
|
78
|
+
if (skipInstall) {
|
|
79
|
+
log.info(`Installation skipped. Please, install them manually with ${chalkHighlightThing(packageManager + ' install')}`);
|
|
142
80
|
}
|
|
143
|
-
|
|
144
|
-
|
|
81
|
+
else {
|
|
82
|
+
try {
|
|
83
|
+
await installDependencies({
|
|
84
|
+
log,
|
|
85
|
+
cwd: root,
|
|
86
|
+
options: {
|
|
87
|
+
useNpm,
|
|
88
|
+
useYarn,
|
|
89
|
+
usePnpm,
|
|
90
|
+
useBun,
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
log.info('Dependencies installed successfully');
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
log.warn(`Failed to install dependencies: ${error.message}. Please, install them manually with ${chalkHighlightThing(packageManager + ' install')}`);
|
|
97
|
+
}
|
|
145
98
|
}
|
|
146
99
|
}
|
|
147
100
|
}
|
|
@@ -149,8 +102,7 @@ export class Init {
|
|
|
149
102
|
const { configAbsolutePath } = await createConfig({
|
|
150
103
|
root,
|
|
151
104
|
log,
|
|
152
|
-
options: { validationLibrary, validateOnClient },
|
|
153
|
-
dryRun,
|
|
105
|
+
options: { validationLibrary, validateOnClient, channel, dryRun },
|
|
154
106
|
});
|
|
155
107
|
log.info('Config created successfully at ' + configAbsolutePath);
|
|
156
108
|
}
|
|
@@ -162,11 +114,12 @@ export class Init {
|
|
|
162
114
|
const cwd = process.cwd();
|
|
163
115
|
const root = path.resolve(cwd, prefix);
|
|
164
116
|
const log = getLogger(logLevel);
|
|
117
|
+
const pkgJson = await NPMCliPackageJson.load(root);
|
|
165
118
|
this.root = root;
|
|
166
119
|
this.log = log;
|
|
167
120
|
const configPaths = await getConfigPaths({ cwd, relativePath: prefix });
|
|
168
121
|
if (yes) {
|
|
169
|
-
return this.#init({ configPaths }, {
|
|
122
|
+
return this.#init({ configPaths, pkgJson }, {
|
|
170
123
|
useNpm: useNpm ?? (!useYarn && !usePnpm && !useBun),
|
|
171
124
|
useYarn: useYarn ?? false,
|
|
172
125
|
usePnpm: usePnpm ?? false,
|
|
@@ -213,7 +166,7 @@ export class Init {
|
|
|
213
166
|
{
|
|
214
167
|
name: 'vovk-dto',
|
|
215
168
|
value: 'vovk-dto',
|
|
216
|
-
description: 'Use class-validator
|
|
169
|
+
description: 'Use class-validator for data validation. Also installs class-transformer, vovk-mapped-types and reflect-metadata',
|
|
217
170
|
},
|
|
218
171
|
{ name: 'None', value: null, description: 'Install validation library later' },
|
|
219
172
|
],
|
|
@@ -228,23 +181,23 @@ export class Init {
|
|
|
228
181
|
updateScripts =
|
|
229
182
|
updateScripts ??
|
|
230
183
|
(await select({
|
|
231
|
-
message: 'Do you want to update package.json by adding "generate" and "dev" scripts?',
|
|
184
|
+
message: 'Do you want to update package.json by adding "generate" and "dev" NPM scripts?',
|
|
232
185
|
default: 'implicit',
|
|
233
186
|
choices: [
|
|
234
187
|
{
|
|
235
188
|
name: 'Yes, use "concurrently" implicitly',
|
|
236
|
-
description: `The "dev" script will use "concurrently" API internally in order to run "next dev" and "vovk dev" together and automatically look for an available port ${chalk.whiteBright.bold(`"vovk dev --next-dev"`)}`,
|
|
237
189
|
value: 'implicit',
|
|
190
|
+
description: `The "dev" 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')}"`)}`,
|
|
238
191
|
},
|
|
239
192
|
{
|
|
240
193
|
name: 'Yes, use "concurrently" explicitly',
|
|
241
194
|
value: 'explicit',
|
|
242
|
-
description: `The "dev" script will use pre-defined PORT variable and run "next dev" and "vovk dev" as "concurrently" CLI arguments ${chalk.whiteBright.bold(`"
|
|
195
|
+
description: `The "dev" script will use pre-defined PORT variable and run "next dev" and "vovk dev" as "concurrently" CLI arguments ${chalk.whiteBright.bold(`"${getDevScript(pkgJson, 'explicit')}"`)}`,
|
|
243
196
|
},
|
|
244
197
|
{
|
|
245
198
|
name: 'No',
|
|
246
199
|
value: undefined,
|
|
247
|
-
description: 'Add the scripts manually',
|
|
200
|
+
description: 'Add the NPM scripts manually',
|
|
248
201
|
},
|
|
249
202
|
],
|
|
250
203
|
}));
|
|
@@ -262,7 +215,7 @@ export class Init {
|
|
|
262
215
|
});
|
|
263
216
|
}
|
|
264
217
|
}
|
|
265
|
-
await this.#init({ configPaths }, {
|
|
218
|
+
await this.#init({ configPaths, pkgJson }, {
|
|
266
219
|
useNpm: useNpm ?? (!useYarn && !usePnpm && !useBun),
|
|
267
220
|
useYarn: useYarn ?? false,
|
|
268
221
|
usePnpm: usePnpm ?? false,
|
|
@@ -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 {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type getLogger from '../utils/getLogger.mjs';
|
|
2
|
+
export default function logUpdateDependenciesError({ useNpm, useYarn, usePnpm, useBun, log, dependencies, devDependencies, error, }: {
|
|
3
|
+
useNpm?: boolean;
|
|
4
|
+
useYarn?: boolean;
|
|
5
|
+
usePnpm?: boolean;
|
|
6
|
+
useBun?: boolean;
|
|
7
|
+
log: ReturnType<typeof getLogger>;
|
|
8
|
+
dependencies: string[];
|
|
9
|
+
devDependencies: string[];
|
|
10
|
+
error: Error;
|
|
11
|
+
}): void;
|