vovk-cli 0.0.1-beta.12 → 0.0.1-beta.14
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/dist/{server/generateClient.d.mts → generateClient.d.mts} +2 -2
- package/dist/{server/generateClient.mjs → generateClient.mjs} +5 -4
- package/dist/getProjectInfo/getConfigPath.d.mts +1 -0
- package/dist/getProjectInfo/getConfigPath.mjs +18 -0
- package/dist/getProjectInfo/index.d.mts +1 -2
- package/dist/getProjectInfo/index.mjs +2 -10
- package/dist/getProjectInfo/readConfig.mjs +2 -19
- package/dist/index.d.mts +5 -0
- package/dist/index.mjs +17 -9
- package/dist/init/index.d.mts +20 -0
- package/dist/init/index.mjs +244 -0
- package/dist/init/installDependencies.d.mts +1 -0
- package/dist/init/installDependencies.mjs +28 -0
- package/dist/types.d.mts +1 -1
- package/dist/utils/formatLoggedSegmentName.d.mts +1 -0
- package/dist/utils/formatLoggedSegmentName.mjs +5 -0
- package/dist/utils/getLogger.d.mts +8 -0
- package/dist/utils/getLogger.mjs +13 -0
- package/dist/{server → watcher}/ensureSchemaFiles.mjs +3 -2
- package/dist/watcher/index.d.mts +6 -0
- package/dist/{server → watcher}/index.mjs +20 -19
- package/dist/{server → watcher}/logDiffResult.mjs +10 -9
- package/package.json +7 -1
- package/dist/init.d.mts +0 -2
- package/dist/init.mjs +0 -171
- package/dist/server/index.d.mts +0 -6
- /package/dist/{server → watcher}/diffSchema.d.mts +0 -0
- /package/dist/{server → watcher}/diffSchema.mjs +0 -0
- /package/dist/{server → watcher}/ensureSchemaFiles.d.mts +0 -0
- /package/dist/{server → watcher}/isMetadataEmpty.d.mts +0 -0
- /package/dist/{server → watcher}/isMetadataEmpty.mjs +0 -0
- /package/dist/{server → watcher}/logDiffResult.d.mts +0 -0
- /package/dist/{server → watcher}/writeOneSchemaFile.d.mts +0 -0
- /package/dist/{server → watcher}/writeOneSchemaFile.mjs +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { ProjectInfo } from '
|
|
2
|
-
import type { Segment } from '
|
|
1
|
+
import type { ProjectInfo } from './getProjectInfo/index.mjs';
|
|
2
|
+
import type { Segment } from './locateSegments.mjs';
|
|
3
3
|
import type { VovkSchema } from 'vovk';
|
|
4
4
|
export default function generateClient(projectInfo: ProjectInfo, segments: Segment[], segmentsSchema: Record<string, VovkSchema>): Promise<{
|
|
5
5
|
written: boolean;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import path from 'path';
|
|
2
2
|
import fs from 'fs/promises';
|
|
3
|
+
import formatLoggedSegmentName from './utils/formatLoggedSegmentName.mjs';
|
|
3
4
|
export default async function generateClient(projectInfo, segments, segmentsSchema) {
|
|
4
5
|
const now = Date.now();
|
|
5
6
|
const clientoOutDirFullPath = path.join(projectInfo.cwd, projectInfo.config.clientOutDir);
|
|
@@ -34,7 +35,7 @@ import schema from '${projectInfo.schemaOutImportPath}';
|
|
|
34
35
|
const { routeFilePath, segmentName } = segments[i];
|
|
35
36
|
const schema = segmentsSchema[segmentName];
|
|
36
37
|
if (!schema) {
|
|
37
|
-
throw new Error(`Unable to generate client. No schema found for
|
|
38
|
+
throw new Error(`Unable to generate client. No schema found for ${formatLoggedSegmentName(segmentName)}`);
|
|
38
39
|
}
|
|
39
40
|
if (!schema.emitSchema)
|
|
40
41
|
continue;
|
|
@@ -44,12 +45,12 @@ import schema from '${projectInfo.schemaOutImportPath}';
|
|
|
44
45
|
}
|
|
45
46
|
dts += `
|
|
46
47
|
type Options = typeof fetcher extends VovkClientFetcher<infer U> ? U : never;
|
|
47
|
-
|
|
48
|
+
`;
|
|
48
49
|
ts += `
|
|
49
50
|
${validateFullPath ? `import validateOnClient from '${validateFullPath}';\n` : '\nconst validateOnClient = undefined;'}
|
|
50
51
|
type Options = typeof fetcher extends VovkClientFetcher<infer U> ? U : never;
|
|
51
52
|
const prefix = '${projectInfo.apiEntryPoint}';
|
|
52
|
-
|
|
53
|
+
`;
|
|
53
54
|
js += `
|
|
54
55
|
const { default: validateOnClient = null } = ${validateFullPath ? `require('${validateFullPath}')` : '{}'};
|
|
55
56
|
const prefix = '${projectInfo.apiEntryPoint}';
|
|
@@ -58,7 +59,7 @@ const prefix = '${projectInfo.apiEntryPoint}';
|
|
|
58
59
|
const { segmentName } = segments[i];
|
|
59
60
|
const schema = segmentsSchema[segmentName];
|
|
60
61
|
if (!schema) {
|
|
61
|
-
throw new Error(`Unable to generate client. No schema found for
|
|
62
|
+
throw new Error(`Unable to generate client. No schema found for ${formatLoggedSegmentName(segmentName)}`);
|
|
62
63
|
}
|
|
63
64
|
if (!schema.emitSchema)
|
|
64
65
|
continue;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function getConfigPath(relativePath?: string): Promise<string | null>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import fs from 'fs/promises';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
export default async function getConfigPath(relativePath = '') {
|
|
4
|
+
const rootDir = path.resolve(process.cwd(), relativePath || '');
|
|
5
|
+
const baseName = 'vovk.config';
|
|
6
|
+
const extensions = ['cjs', 'mjs', 'js'];
|
|
7
|
+
for (const ext of extensions) {
|
|
8
|
+
const filePath = path.join(rootDir, `${baseName}.${ext}`);
|
|
9
|
+
try {
|
|
10
|
+
await fs.stat(filePath);
|
|
11
|
+
return filePath; // Return the path if the file exists
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
// Empty
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
return null; // Return null if no config file was found
|
|
18
|
+
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import loglevel from 'loglevel';
|
|
2
1
|
export type ProjectInfo = Awaited<ReturnType<typeof getProjectInfo>>;
|
|
3
2
|
export default function getProjectInfo({ port: givenPort, clientOutDir, }?: {
|
|
4
3
|
port?: number;
|
|
@@ -17,6 +16,6 @@ export default function getProjectInfo({ port: givenPort, clientOutDir, }?: {
|
|
|
17
16
|
warn: (msg: string) => void;
|
|
18
17
|
error: (msg: string) => void;
|
|
19
18
|
debug: (msg: string) => void;
|
|
20
|
-
raw: loglevel.RootLogger;
|
|
19
|
+
raw: import("loglevel").RootLogger;
|
|
21
20
|
};
|
|
22
21
|
}>;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import path from 'path';
|
|
2
|
-
import loglevel from 'loglevel';
|
|
3
|
-
import chalk from 'chalk';
|
|
4
2
|
import getConfig from './getConfig.mjs';
|
|
3
|
+
import getLogger from '../utils/getLogger.mjs';
|
|
5
4
|
export default async function getProjectInfo({ port: givenPort, clientOutDir, } = {}) {
|
|
6
5
|
const port = givenPort?.toString() ?? process.env.PORT ?? '3000';
|
|
7
6
|
// Make PORT available to the config file at getConfig
|
|
@@ -14,14 +13,7 @@ export default async function getProjectInfo({ port: givenPort, clientOutDir, }
|
|
|
14
13
|
const fetcherClientImportPath = config.fetcher.startsWith('.')
|
|
15
14
|
? path.relative(config.clientOutDir, config.fetcher)
|
|
16
15
|
: config.fetcher;
|
|
17
|
-
const log =
|
|
18
|
-
info: (msg) => loglevel.info(chalk.blueBright(`🐺 ${msg}`)),
|
|
19
|
-
warn: (msg) => loglevel.warn(chalk.yellowBright(`🐺 ${msg}`)),
|
|
20
|
-
error: (msg) => loglevel.error(chalk.redBright(`🐺 ${msg}`)),
|
|
21
|
-
debug: (msg) => loglevel.debug(chalk.gray(`🐺 ${msg}`)),
|
|
22
|
-
raw: loglevel,
|
|
23
|
-
};
|
|
24
|
-
loglevel.setLevel(config.logLevel);
|
|
16
|
+
const log = getLogger(config.logLevel);
|
|
25
17
|
return {
|
|
26
18
|
cwd,
|
|
27
19
|
port,
|
|
@@ -1,23 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
import path from 'path';
|
|
3
|
-
async function findConfigPath() {
|
|
4
|
-
const rootDir = process.cwd();
|
|
5
|
-
const baseName = 'vovk.config';
|
|
6
|
-
const extensions = ['cjs', 'mjs', 'js'];
|
|
7
|
-
for (const ext of extensions) {
|
|
8
|
-
const filePath = path.join(rootDir, `${baseName}.${ext}`);
|
|
9
|
-
try {
|
|
10
|
-
await fs.stat(filePath);
|
|
11
|
-
return filePath; // Return the path if the file exists
|
|
12
|
-
}
|
|
13
|
-
catch {
|
|
14
|
-
// If the file doesn't exist, an error is thrown. Catch it and continue checking.
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
return null; // Return null if no config file was found
|
|
18
|
-
}
|
|
1
|
+
import getConfigPath from './getConfigPath.mjs';
|
|
19
2
|
async function readConfig() {
|
|
20
|
-
const configPath = await
|
|
3
|
+
const configPath = await getConfigPath();
|
|
21
4
|
let config = {};
|
|
22
5
|
if (!configPath) {
|
|
23
6
|
return config;
|
package/dist/index.d.mts
CHANGED
package/dist/index.mjs
CHANGED
|
@@ -2,21 +2,21 @@
|
|
|
2
2
|
import { Command } from 'commander';
|
|
3
3
|
import concurrently from 'concurrently';
|
|
4
4
|
import getAvailablePort from './utils/getAvailablePort.mjs';
|
|
5
|
-
import {
|
|
5
|
+
import { VovkCLIWatcher } from './watcher/index.mjs';
|
|
6
6
|
import getProjectInfo from './getProjectInfo/index.mjs';
|
|
7
|
-
import generateClient from './
|
|
7
|
+
import generateClient from './generateClient.mjs';
|
|
8
8
|
import locateSegments from './locateSegments.mjs';
|
|
9
9
|
import path from 'path';
|
|
10
10
|
import { readFileSync } from 'fs';
|
|
11
|
+
import { Init } from './init/index.mjs';
|
|
11
12
|
const program = new Command();
|
|
12
13
|
const packageJSON = JSON.parse(readFileSync(path.join(import.meta.dirname, '../package.json'), 'utf-8'));
|
|
13
14
|
program.name('vovk').description('Vovk CLI').version(packageJSON.version);
|
|
14
15
|
program
|
|
15
16
|
.command('dev')
|
|
16
|
-
.description('Start
|
|
17
|
-
.option('--project <path>', 'Path to Next.js project', process.cwd())
|
|
17
|
+
.description('Start schema watcher (optional flag --next-dev to start it with Next.js)')
|
|
18
18
|
.option('--client-out <path>', 'Path to client output directory')
|
|
19
|
-
.option('--next-dev', 'Start
|
|
19
|
+
.option('--next-dev', 'Start schema watcher and Next.js with automatic port allocation', false)
|
|
20
20
|
.allowUnknownOption(true)
|
|
21
21
|
.action(async (options, command) => {
|
|
22
22
|
const portAttempts = 30;
|
|
@@ -34,9 +34,9 @@ program
|
|
|
34
34
|
if (options.nextDev) {
|
|
35
35
|
const { result } = concurrently([
|
|
36
36
|
{
|
|
37
|
-
command: `node ${import.meta.dirname}/
|
|
38
|
-
name: 'Vovk.ts Schema
|
|
39
|
-
env: Object.assign({ PORT,
|
|
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
40
|
},
|
|
41
41
|
{
|
|
42
42
|
command: `cd ${options.project} && npx next dev ${command.args.join(' ')}`,
|
|
@@ -56,7 +56,7 @@ program
|
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
else {
|
|
59
|
-
void new
|
|
59
|
+
void new VovkCLIWatcher().start({ clientOutDir: options.clientOut });
|
|
60
60
|
}
|
|
61
61
|
});
|
|
62
62
|
program
|
|
@@ -71,6 +71,14 @@ program
|
|
|
71
71
|
const schema = (await import(path.join(schemaOutFullPath, 'index.js')));
|
|
72
72
|
await generateClient(projectInfo, segments, schema.default);
|
|
73
73
|
});
|
|
74
|
+
program
|
|
75
|
+
.command('init [prefix]')
|
|
76
|
+
.description('Initialize Vovk project')
|
|
77
|
+
.option('-Y, --yes', 'Skip all prompts and use default values')
|
|
78
|
+
.option('--log-level <level>', 'Set log level', 'info')
|
|
79
|
+
.action(async (prefix = '.', options) => {
|
|
80
|
+
await Init.main(prefix, options);
|
|
81
|
+
});
|
|
74
82
|
program
|
|
75
83
|
.command('help')
|
|
76
84
|
.description('Show help message')
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import type { VovkConfig } from '../types.mjs';
|
|
3
|
+
import type { InitOptions } from '../index.mjs';
|
|
4
|
+
import getLogger from '../utils/getLogger.mjs';
|
|
5
|
+
declare abstract class Action<T> {
|
|
6
|
+
context: Context;
|
|
7
|
+
data: T;
|
|
8
|
+
action: () => void;
|
|
9
|
+
constructor(context: Context);
|
|
10
|
+
toJSON: () => T;
|
|
11
|
+
}
|
|
12
|
+
declare class Context {
|
|
13
|
+
actions: Action<unknown>[];
|
|
14
|
+
vovkConfig: VovkConfig;
|
|
15
|
+
root: string;
|
|
16
|
+
log: ReturnType<typeof getLogger>;
|
|
17
|
+
static main(prefix: string, { yes, logLevel }: InitOptions): Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
export declare const Init: typeof Context;
|
|
20
|
+
export {};
|
|
@@ -0,0 +1,244 @@
|
|
|
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
|
+
import { confirm, select } from '@inquirer/prompts';
|
|
60
|
+
import NPMCliPackageJson from '@npmcli/package-json';
|
|
61
|
+
import path from 'path';
|
|
62
|
+
import fs from 'fs/promises';
|
|
63
|
+
import * as jsonc from 'jsonc-parser';
|
|
64
|
+
import getConfigPath from '../getProjectInfo/getConfigPath.mjs';
|
|
65
|
+
import chalk from 'chalk';
|
|
66
|
+
import fileExists from '../utils/fileExists.mjs';
|
|
67
|
+
import installDependencies from './installDependencies.mjs';
|
|
68
|
+
import getLogger from '../utils/getLogger.mjs';
|
|
69
|
+
class Action {
|
|
70
|
+
context;
|
|
71
|
+
data;
|
|
72
|
+
// public prevAction: Action | null = null;
|
|
73
|
+
action;
|
|
74
|
+
constructor(context) {
|
|
75
|
+
this.context = context;
|
|
76
|
+
}
|
|
77
|
+
toJSON = () => this.data;
|
|
78
|
+
}
|
|
79
|
+
class InstallValidationLibraryAction extends Action {
|
|
80
|
+
constructor(context, data) {
|
|
81
|
+
super(context);
|
|
82
|
+
this.data = data;
|
|
83
|
+
}
|
|
84
|
+
action = () => {
|
|
85
|
+
this.context.vovkConfig.validationLibrary = this.data.validationLibrary;
|
|
86
|
+
if (this.data.validationLibrary && this.data.enableClientValidation) {
|
|
87
|
+
this.context.vovkConfig.validateOnClient = `${this.data.validationLibrary}/validateOnClient`;
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
class UpdateNpmScriptsAction extends Action {
|
|
92
|
+
constructor(context) {
|
|
93
|
+
super(context);
|
|
94
|
+
this.data = { shouldUpdateNpmScripts: true };
|
|
95
|
+
}
|
|
96
|
+
action = async () => {
|
|
97
|
+
if (this.data.shouldUpdateNpmScripts && typeof this.data.useConcurrently === 'undefined') {
|
|
98
|
+
throw new Error('useConcurrently must be defined');
|
|
99
|
+
}
|
|
100
|
+
const pkgJson = await NPMCliPackageJson.load(this.context.root);
|
|
101
|
+
pkgJson.update({
|
|
102
|
+
scripts: {
|
|
103
|
+
generate: 'vovk generate',
|
|
104
|
+
dev: this.data.useConcurrently
|
|
105
|
+
? 'PORT=3000 concurrently "vovk dev" "next dev" --kill-others'
|
|
106
|
+
: 'vovk dev --next-dev',
|
|
107
|
+
},
|
|
108
|
+
});
|
|
109
|
+
await pkgJson.save();
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
class UpdateTsconfigAction extends Action {
|
|
113
|
+
constructor(context) {
|
|
114
|
+
super(context);
|
|
115
|
+
}
|
|
116
|
+
action = async () => {
|
|
117
|
+
const tsconfigPath = path.resolve(process.cwd(), 'tsconfig.json');
|
|
118
|
+
try {
|
|
119
|
+
// Read the content of tsconfig.json asynchronously
|
|
120
|
+
const tsconfigContent = await fs.readFile(tsconfigPath, 'utf8');
|
|
121
|
+
// Use jsonc-parser to generate edits and modify the experimentalDecorators property
|
|
122
|
+
const edits = jsonc.modify(tsconfigContent, ['compilerOptions', 'experimentalDecorators'], true, {
|
|
123
|
+
formattingOptions: {},
|
|
124
|
+
});
|
|
125
|
+
// Apply the edits to the original content
|
|
126
|
+
const updatedContent = jsonc.applyEdits(tsconfigContent, edits);
|
|
127
|
+
// Write the updated content back to the file asynchronously
|
|
128
|
+
await fs.writeFile(tsconfigPath, updatedContent, 'utf8');
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
throw new Error(`Failed to update tsconfig.json at ${tsconfigPath}. ${String(error)}`);
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
static async checkTsconfigForExperimentalDecorators() {
|
|
135
|
+
const tsconfigPath = path.resolve(process.cwd(), 'tsconfig.json');
|
|
136
|
+
let tsconfigContent;
|
|
137
|
+
try {
|
|
138
|
+
tsconfigContent = await fs.readFile(tsconfigPath, 'utf8');
|
|
139
|
+
}
|
|
140
|
+
catch (error) {
|
|
141
|
+
throw new Error(`Failed to read tsconfig.json at ${tsconfigPath}. You can run "npx tsc --init" to create it. ${String(error)}`);
|
|
142
|
+
}
|
|
143
|
+
const tsconfig = jsonc.parse(tsconfigContent);
|
|
144
|
+
return !!tsconfig?.compilerOptions?.experimentalDecorators;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
class Context {
|
|
148
|
+
actions = [];
|
|
149
|
+
vovkConfig = {};
|
|
150
|
+
root;
|
|
151
|
+
log;
|
|
152
|
+
static async main(prefix, { yes, logLevel }) {
|
|
153
|
+
// TODO handle yes option
|
|
154
|
+
console.log('yes', yes);
|
|
155
|
+
const context = new Context();
|
|
156
|
+
const cwd = process.cwd();
|
|
157
|
+
const configPath = await getConfigPath(prefix);
|
|
158
|
+
const toBeInstalled = ['vovk'];
|
|
159
|
+
const root = path.join(cwd, prefix);
|
|
160
|
+
const log = getLogger(logLevel);
|
|
161
|
+
context.root = root;
|
|
162
|
+
context.log = log;
|
|
163
|
+
if (!(await fileExists(path.join(root, 'package.json')))) {
|
|
164
|
+
throw new Error(`package.json not found at ${root}. Run "npx create-next-app" to create a new Next.js project.`);
|
|
165
|
+
}
|
|
166
|
+
if (!(await fileExists(path.join(root, 'tsconfig.json')))) {
|
|
167
|
+
throw new Error(`tsconfig.json not found at ${root}. Run "npx tsc --init" to create a new tsconfig.json file.`);
|
|
168
|
+
}
|
|
169
|
+
if (configPath) {
|
|
170
|
+
if (!(await confirm({
|
|
171
|
+
message: `Found existing config file at ${configPath}. Do you want to reinitialize the project?`,
|
|
172
|
+
})))
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
const validationLibrary = await select({
|
|
176
|
+
message: 'Choose validation library',
|
|
177
|
+
default: 'vovk-zod',
|
|
178
|
+
choices: [
|
|
179
|
+
{
|
|
180
|
+
name: 'vovk-zod',
|
|
181
|
+
value: 'vovk-zod',
|
|
182
|
+
description: 'Use Zod for data validation',
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
name: 'vovk-yup',
|
|
186
|
+
value: 'vovk-yup',
|
|
187
|
+
description: 'Use Yup for data validation',
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
name: 'vovk-dto',
|
|
191
|
+
value: 'vovk-dto',
|
|
192
|
+
description: 'Use class-validator and class-transformer for data validation',
|
|
193
|
+
},
|
|
194
|
+
{ name: 'None', value: null, description: 'Install validation library later' },
|
|
195
|
+
],
|
|
196
|
+
});
|
|
197
|
+
if (validationLibrary) {
|
|
198
|
+
toBeInstalled.push(validationLibrary);
|
|
199
|
+
toBeInstalled.push(...({
|
|
200
|
+
'vovk-zod': ['zod'],
|
|
201
|
+
'vovk-yup': ['yup'],
|
|
202
|
+
'vovk-dto': ['class-validator', 'class-transformer'],
|
|
203
|
+
}[validationLibrary] ?? []));
|
|
204
|
+
const installValidationLibraryAction = new InstallValidationLibraryAction(context, { validationLibrary });
|
|
205
|
+
context.actions.push(installValidationLibraryAction);
|
|
206
|
+
installValidationLibraryAction.data.enableClientValidation = await confirm({
|
|
207
|
+
message: 'Do you want to enable client validation?',
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
const devScriptType = await select({
|
|
211
|
+
message: 'Do you want to update package.json by adding "generate" and "dev" scripts?',
|
|
212
|
+
default: 'IMPLICIT',
|
|
213
|
+
choices: [
|
|
214
|
+
{
|
|
215
|
+
name: 'Yes, with implicit concurrently',
|
|
216
|
+
description: `The "dev" script will use concurrently API internally and automatically set a port ${chalk.whiteBright(`"vovk dev --next-dev"`)}`,
|
|
217
|
+
value: 'IMPLICIT',
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
name: 'Yes, with explicit concurrently',
|
|
221
|
+
value: 'EXPLICIT',
|
|
222
|
+
description: `The "dev" script will use pre-defined PORT variable ${chalk.whiteBright(`"PORT=3000 concurrently 'vovk dev' 'next dev' --kill-others"`)}`,
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
name: 'No',
|
|
226
|
+
value: null,
|
|
227
|
+
description: 'Add the scripts manually',
|
|
228
|
+
},
|
|
229
|
+
],
|
|
230
|
+
});
|
|
231
|
+
if (devScriptType) {
|
|
232
|
+
const updateNpmScriptsAction = new UpdateNpmScriptsAction(context);
|
|
233
|
+
context.actions.push(updateNpmScriptsAction);
|
|
234
|
+
updateNpmScriptsAction.data.useConcurrently = devScriptType === 'EXPLICIT';
|
|
235
|
+
}
|
|
236
|
+
if (!(await UpdateTsconfigAction.checkTsconfigForExperimentalDecorators()) &&
|
|
237
|
+
(await confirm({ message: 'Do you want to add experimentalDecorators to tsconfig.json?' }))) {
|
|
238
|
+
const updateTsconfigAction = new UpdateTsconfigAction(context);
|
|
239
|
+
context.actions.push(updateTsconfigAction);
|
|
240
|
+
}
|
|
241
|
+
await installDependencies(root, toBeInstalled, ['concurrently', 'vovk-cli']);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
export const Init = Context;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function installDependencies(installDir: string, dependencies: string[], devDependencies: string[]): Promise<void>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { exec } from 'child_process';
|
|
2
|
+
import { promisify } from 'util';
|
|
3
|
+
import * as path from 'path';
|
|
4
|
+
const execPromise = promisify(exec);
|
|
5
|
+
export default async function installDependencies(installDir, dependencies, devDependencies) {
|
|
6
|
+
const fullPath = path.resolve(installDir);
|
|
7
|
+
try {
|
|
8
|
+
if (dependencies.length > 0) {
|
|
9
|
+
console.log(`Installing dependencies in ${fullPath}...`);
|
|
10
|
+
const { stdout, stderr } = await execPromise(`npm install ${dependencies.join(' ')} --prefix ${fullPath}`);
|
|
11
|
+
console.log(stdout);
|
|
12
|
+
if (stderr) {
|
|
13
|
+
console.error(stderr);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
if (devDependencies.length > 0) {
|
|
17
|
+
console.log(`Installing dev dependencies in ${fullPath}...`);
|
|
18
|
+
const { stdout, stderr } = await execPromise(`npm install --save-dev ${devDependencies.join(' ')} --prefix ${fullPath}`);
|
|
19
|
+
console.log(stdout);
|
|
20
|
+
if (stderr) {
|
|
21
|
+
console.error(stderr);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
catch (err) {
|
|
26
|
+
console.error(`Error installing dependencies: ${err.message}`);
|
|
27
|
+
}
|
|
28
|
+
}
|
package/dist/types.d.mts
CHANGED
|
@@ -13,7 +13,7 @@ export type VovkEnv = {
|
|
|
13
13
|
VOVK_API_ENTRY_POINT?: string;
|
|
14
14
|
VOVK_ROOT_SEGMENT_MODULES_DIR_NAME?: string;
|
|
15
15
|
VOVK_LOG_LEVEL?: LogLevelNames;
|
|
16
|
-
|
|
16
|
+
__VOVK_START_WATCHER_IN_STANDALONE_MODE__?: 'true';
|
|
17
17
|
};
|
|
18
18
|
export type VovkConfig = {
|
|
19
19
|
clientOutDir?: string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function formatLoggedSegmentName(segmentName: string, withChalk?: boolean): string;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import loglevel, { type LogLevelNames } from 'loglevel';
|
|
2
|
+
export default function getLogger(level: LogLevelNames): {
|
|
3
|
+
info: (msg: string) => void;
|
|
4
|
+
warn: (msg: string) => void;
|
|
5
|
+
error: (msg: string) => void;
|
|
6
|
+
debug: (msg: string) => void;
|
|
7
|
+
raw: loglevel.RootLogger;
|
|
8
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import loglevel from 'loglevel';
|
|
3
|
+
export default function getLogger(level) {
|
|
4
|
+
const log = {
|
|
5
|
+
info: (msg) => loglevel.info(chalk.cyanBright(`🐺 ${msg}`)),
|
|
6
|
+
warn: (msg) => loglevel.warn(chalk.yellowBright(`🐺 ${msg}`)),
|
|
7
|
+
error: (msg) => loglevel.error(chalk.redBright(`🐺 ${msg}`)),
|
|
8
|
+
debug: (msg) => loglevel.debug(chalk.gray(`🐺 ${msg}`)),
|
|
9
|
+
raw: loglevel,
|
|
10
|
+
};
|
|
11
|
+
loglevel.setLevel(level);
|
|
12
|
+
return log;
|
|
13
|
+
}
|
|
@@ -2,6 +2,7 @@ import fs from 'fs/promises';
|
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import debounce from 'lodash/debounce.js';
|
|
4
4
|
import writeOneSchemaFile, { ROOT_SEGMENT_SCHEMA_NAME } from './writeOneSchemaFile.mjs';
|
|
5
|
+
import formatLoggedSegmentName from '../utils/formatLoggedSegmentName.mjs';
|
|
5
6
|
export default async function ensureSchemaFiles(schemaOutFullPath, segmentNames, projectInfo) {
|
|
6
7
|
const now = Date.now();
|
|
7
8
|
let hasChanged = false;
|
|
@@ -30,7 +31,7 @@ export default segmentSchema;`;
|
|
|
30
31
|
skipIfExists: true,
|
|
31
32
|
});
|
|
32
33
|
if (isCreated) {
|
|
33
|
-
projectInfo?.log.debug(`Created empty schema file for
|
|
34
|
+
projectInfo?.log.debug(`Created empty schema file for ${formatLoggedSegmentName(segmentName, true)}`);
|
|
34
35
|
hasChanged = true;
|
|
35
36
|
}
|
|
36
37
|
}));
|
|
@@ -56,7 +57,7 @@ export default segmentSchema;`;
|
|
|
56
57
|
if (!segmentNames.includes(segmentName) &&
|
|
57
58
|
!segmentNames.includes(segmentName.replace(ROOT_SEGMENT_SCHEMA_NAME, ''))) {
|
|
58
59
|
await fs.unlink(fullPath);
|
|
59
|
-
projectInfo?.log.debug(`Deleted unnecessary schema file for
|
|
60
|
+
projectInfo?.log.debug(`Deleted unnecessary schema file for ${formatLoggedSegmentName(segmentName, true)}`);
|
|
60
61
|
hasChanged = true;
|
|
61
62
|
}
|
|
62
63
|
}
|
|
@@ -5,12 +5,13 @@ import path from 'path';
|
|
|
5
5
|
import { debouncedEnsureSchemaFiles } from './ensureSchemaFiles.mjs';
|
|
6
6
|
import writeOneSchemaFile from './writeOneSchemaFile.mjs';
|
|
7
7
|
import logDiffResult from './logDiffResult.mjs';
|
|
8
|
-
import generateClient from '
|
|
8
|
+
import generateClient from '../generateClient.mjs';
|
|
9
9
|
import locateSegments from '../locateSegments.mjs';
|
|
10
10
|
import debounceWithArgs from '../utils/debounceWithArgs.mjs';
|
|
11
11
|
import debounce from 'lodash/debounce.js';
|
|
12
12
|
import isEmpty from 'lodash/isEmpty.js';
|
|
13
|
-
|
|
13
|
+
import formatLoggedSegmentName from '../utils/formatLoggedSegmentName.mjs';
|
|
14
|
+
export class VovkCLIWatcher {
|
|
14
15
|
#projectInfo;
|
|
15
16
|
#segments = [];
|
|
16
17
|
#schemas = {};
|
|
@@ -45,7 +46,7 @@ export class VovkCLIServer {
|
|
|
45
46
|
.on('change', (filePath) => {
|
|
46
47
|
log.debug(`File ${filePath} has been changed at segments folder`);
|
|
47
48
|
if (segmentReg.test(filePath)) {
|
|
48
|
-
void this.#
|
|
49
|
+
void this.#requestSchema(getSegmentName(filePath));
|
|
49
50
|
}
|
|
50
51
|
})
|
|
51
52
|
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
@@ -53,7 +54,7 @@ export class VovkCLIServer {
|
|
|
53
54
|
log.debug(`Directory ${dirPath} has been added to segments folder`);
|
|
54
55
|
this.#segments = await locateSegments(apiDirFullPath);
|
|
55
56
|
for (const { segmentName } of this.#segments) {
|
|
56
|
-
void this.#
|
|
57
|
+
void this.#requestSchema(segmentName);
|
|
57
58
|
}
|
|
58
59
|
})
|
|
59
60
|
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
@@ -61,7 +62,7 @@ export class VovkCLIServer {
|
|
|
61
62
|
log.debug(`Directory ${dirPath} has been removed from segments folder`);
|
|
62
63
|
this.#segments = await locateSegments(apiDirFullPath);
|
|
63
64
|
for (const { segmentName } of this.#segments) {
|
|
64
|
-
void this.#
|
|
65
|
+
void this.#requestSchema(segmentName);
|
|
65
66
|
}
|
|
66
67
|
})
|
|
67
68
|
.on('unlink', (filePath) => {
|
|
@@ -104,12 +105,12 @@ export class VovkCLIServer {
|
|
|
104
105
|
})
|
|
105
106
|
.on('addDir', () => {
|
|
106
107
|
for (const { segmentName } of this.#segments) {
|
|
107
|
-
void this.#
|
|
108
|
+
void this.#requestSchema(segmentName);
|
|
108
109
|
}
|
|
109
110
|
})
|
|
110
111
|
.on('unlinkDir', () => {
|
|
111
112
|
for (const { segmentName } of this.#segments) {
|
|
112
|
-
void this.#
|
|
113
|
+
void this.#requestSchema(segmentName);
|
|
113
114
|
}
|
|
114
115
|
})
|
|
115
116
|
.on('ready', () => {
|
|
@@ -177,18 +178,18 @@ export class VovkCLIServer {
|
|
|
177
178
|
if (affectedSegments.length) {
|
|
178
179
|
log.debug(`A file with controller or worker ${namesOfClasses.join(', ')} have been modified at path "${filePath}". Segment(s) affected: ${affectedSegments.map((s) => s.segmentName).join(', ')}`);
|
|
179
180
|
for (const segment of affectedSegments) {
|
|
180
|
-
await this.#
|
|
181
|
+
await this.#requestSchema(segment.segmentName);
|
|
181
182
|
}
|
|
182
183
|
}
|
|
183
184
|
}
|
|
184
185
|
};
|
|
185
|
-
#
|
|
186
|
+
#requestSchema = debounceWithArgs(async (segmentName) => {
|
|
186
187
|
const { apiEntryPoint, log, port } = this.#projectInfo;
|
|
187
188
|
const endpoint = `${apiEntryPoint.startsWith('http') ? apiEntryPoint : `http://localhost:${port}${apiEntryPoint}`}/${segmentName ? `${segmentName}/` : ''}_schema_`;
|
|
188
|
-
log.debug(`
|
|
189
|
+
log.debug(`Requesting schema for ${formatLoggedSegmentName(segmentName, true)} at ${endpoint}`);
|
|
189
190
|
const resp = await fetch(endpoint);
|
|
190
191
|
if (resp.status !== 200) {
|
|
191
|
-
log.warn(`
|
|
192
|
+
log.warn(`Schema request to ${formatLoggedSegmentName(segmentName, true)} failed with status code ${resp.status}. Expected 200.`);
|
|
192
193
|
return;
|
|
193
194
|
}
|
|
194
195
|
let schema = null;
|
|
@@ -196,7 +197,7 @@ export class VovkCLIServer {
|
|
|
196
197
|
({ schema } = (await resp.json()));
|
|
197
198
|
}
|
|
198
199
|
catch (error) {
|
|
199
|
-
log.error(`Error parsing schema for
|
|
200
|
+
log.error(`Error parsing schema for ${formatLoggedSegmentName(segmentName, true)}: ${error.message}`);
|
|
200
201
|
}
|
|
201
202
|
await this.#handleSchema(schema);
|
|
202
203
|
}, 500);
|
|
@@ -224,18 +225,18 @@ export class VovkCLIServer {
|
|
|
224
225
|
const timeTook = Date.now() - now;
|
|
225
226
|
if (diffResult) {
|
|
226
227
|
logDiffResult(segment.segmentName, diffResult, this.#projectInfo);
|
|
227
|
-
log.info(`Schema for
|
|
228
|
+
log.info(`Schema for ${formatLoggedSegmentName(segment.segmentName, true)} has been updated in ${timeTook}ms`);
|
|
228
229
|
}
|
|
229
230
|
}
|
|
230
231
|
else if (schema && (!isEmpty(schema.controllers) || !isEmpty(schema.workers))) {
|
|
231
|
-
log.error(`Non-empty schema provided for
|
|
232
|
+
log.error(`Non-empty schema provided for ${formatLoggedSegmentName(segment.segmentName, true)} but emitSchema is false`);
|
|
232
233
|
}
|
|
233
234
|
if (this.#segments.every((s) => this.#schemas[s.segmentName])) {
|
|
234
235
|
log.debug(`All segments with emitSchema=true have schema.`);
|
|
235
236
|
await generateClient(this.#projectInfo, this.#segments, this.#schemas);
|
|
236
237
|
}
|
|
237
238
|
}
|
|
238
|
-
async
|
|
239
|
+
async start({ clientOutDir } = {}) {
|
|
239
240
|
this.#projectInfo = await getProjectInfo({ clientOutDir });
|
|
240
241
|
const { log, config, cwd, apiDir } = this.#projectInfo;
|
|
241
242
|
process.on('uncaughtException', (err) => {
|
|
@@ -248,16 +249,16 @@ export class VovkCLIServer {
|
|
|
248
249
|
const schemaOutFullPath = path.join(cwd, config.schemaOutDir);
|
|
249
250
|
this.#segments = await locateSegments(apiDirFullPath);
|
|
250
251
|
await debouncedEnsureSchemaFiles(schemaOutFullPath, this.#segments.map((s) => s.segmentName), this.#projectInfo);
|
|
251
|
-
//
|
|
252
|
+
// Request schema every segment in 3 seconds in order to update schema and start watching
|
|
252
253
|
setTimeout(() => {
|
|
253
254
|
for (const { segmentName } of this.#segments) {
|
|
254
|
-
void this.#
|
|
255
|
+
void this.#requestSchema(segmentName);
|
|
255
256
|
}
|
|
256
257
|
this.#watch();
|
|
257
258
|
}, 3000);
|
|
258
259
|
}
|
|
259
260
|
}
|
|
260
261
|
const env = process.env;
|
|
261
|
-
if (env.
|
|
262
|
-
void new
|
|
262
|
+
if (env.__VOVK_START_WATCHER_IN_STANDALONE_MODE__ === 'true') {
|
|
263
|
+
void new VovkCLIWatcher().start();
|
|
263
264
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
|
+
import formatLoggedSegmentName from '../utils/formatLoggedSegmentName.mjs';
|
|
2
3
|
export default function logDiffResult(segmentName, diffResult, projectInfo) {
|
|
3
4
|
const diffNormalized = [];
|
|
4
5
|
diffResult.workers.added.forEach((name) => {
|
|
@@ -30,43 +31,43 @@ export default function logDiffResult(segmentName, diffResult, projectInfo) {
|
|
|
30
31
|
case 'worker':
|
|
31
32
|
switch (diffNormalizedItem.type) {
|
|
32
33
|
case 'added':
|
|
33
|
-
projectInfo.log.info(`
|
|
34
|
+
projectInfo.log.info(`Schema for worker ${chalk.white.bold(diffNormalizedItem.name)} has been added at ${formatLoggedSegmentName(segmentName, true)}`);
|
|
34
35
|
break;
|
|
35
36
|
case 'removed':
|
|
36
|
-
projectInfo.log.info(`
|
|
37
|
+
projectInfo.log.info(`Schema for worker ${chalk.white.bold(diffNormalizedItem.name)} has been removed from ${formatLoggedSegmentName(segmentName, true)}`);
|
|
37
38
|
break;
|
|
38
39
|
}
|
|
39
40
|
break;
|
|
40
41
|
case 'controller':
|
|
41
42
|
switch (diffNormalizedItem.type) {
|
|
42
43
|
case 'added':
|
|
43
|
-
projectInfo.log.info(`
|
|
44
|
+
projectInfo.log.info(`Schema for controller ${chalk.white.bold(diffNormalizedItem.name)} has been added at ${formatLoggedSegmentName(segmentName, true)}`);
|
|
44
45
|
break;
|
|
45
46
|
case 'removed':
|
|
46
|
-
projectInfo.log.info(`
|
|
47
|
+
projectInfo.log.info(`Schema for controller ${chalk.white.bold(diffNormalizedItem.name)} has been removed from ${formatLoggedSegmentName(segmentName, true)}`);
|
|
47
48
|
break;
|
|
48
49
|
}
|
|
49
50
|
break;
|
|
50
51
|
case 'workerHandler':
|
|
51
52
|
switch (diffNormalizedItem.type) {
|
|
52
53
|
case 'added':
|
|
53
|
-
projectInfo.log.info(`
|
|
54
|
+
projectInfo.log.info(`Schema for worker method ${chalk.white.bold(diffNormalizedItem.name)} has been added at ${formatLoggedSegmentName(segmentName, true)}`);
|
|
54
55
|
break;
|
|
55
56
|
case 'removed':
|
|
56
|
-
projectInfo.log.info(`
|
|
57
|
+
projectInfo.log.info(`Schema for worker method ${chalk.white.bold(diffNormalizedItem.name)} has been removed from ${formatLoggedSegmentName(segmentName, true)}`);
|
|
57
58
|
break;
|
|
58
59
|
}
|
|
59
60
|
break;
|
|
60
61
|
case 'controllerHandler':
|
|
61
62
|
switch (diffNormalizedItem.type) {
|
|
62
63
|
case 'added':
|
|
63
|
-
projectInfo.log.info(`
|
|
64
|
+
projectInfo.log.info(`Schema for controller method ${chalk.white.bold(diffNormalizedItem.name)} has been added at ${formatLoggedSegmentName(segmentName, true)}`);
|
|
64
65
|
break;
|
|
65
66
|
case 'removed':
|
|
66
|
-
projectInfo.log.info(`
|
|
67
|
+
projectInfo.log.info(`Schema for controller method ${chalk.white.bold(diffNormalizedItem.name)} has been removed from ${formatLoggedSegmentName(segmentName, true)}`);
|
|
67
68
|
break;
|
|
68
69
|
case 'changed':
|
|
69
|
-
projectInfo.log.info(`
|
|
70
|
+
projectInfo.log.info(`Schema for controller method ${chalk.white.bold(diffNormalizedItem.name)} has been changed at ${formatLoggedSegmentName(segmentName, true)}`);
|
|
70
71
|
break;
|
|
71
72
|
}
|
|
72
73
|
break;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vovk-cli",
|
|
3
|
-
"version": "0.0.1-beta.
|
|
3
|
+
"version": "0.0.1-beta.14",
|
|
4
4
|
"bin": {
|
|
5
5
|
"vovk": "./dist/index.mjs"
|
|
6
6
|
},
|
|
@@ -34,11 +34,17 @@
|
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@inquirer/prompts": "^5.3.8",
|
|
37
|
+
"@npmcli/package-json": "^5.2.0",
|
|
37
38
|
"chalk": "^5.3.0",
|
|
38
39
|
"chokidar": "^3.6.0",
|
|
39
40
|
"commander": "^12.1.0",
|
|
40
41
|
"concurrently": "^8.2.2",
|
|
42
|
+
"jsonc-parser": "^3.3.1",
|
|
41
43
|
"lodash": "^4.17.21",
|
|
42
44
|
"loglevel": "^1.9.1"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"@types/npmcli__package-json": "^4.0.4",
|
|
48
|
+
"type-fest": "^4.26.0"
|
|
43
49
|
}
|
|
44
50
|
}
|
package/dist/init.d.mts
DELETED
package/dist/init.mjs
DELETED
|
@@ -1,171 +0,0 @@
|
|
|
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 use concurrently? (NO NEED, USE CONCURRENTLY BY DEFAULT)
|
|
25
|
-
- Yes (recommended)
|
|
26
|
-
- Add concurrently to the installation list
|
|
27
|
-
- No
|
|
28
|
-
- Do you want to update NPM scripts?
|
|
29
|
-
- Yes
|
|
30
|
-
- Update NPM scripts
|
|
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 } from '@inquirer/prompts';
|
|
60
|
-
// Or
|
|
61
|
-
// import confirm from '@inquirer/confirm';
|
|
62
|
-
// eslint-disable-next-line no-console
|
|
63
|
-
void confirm({ message: 'Continue?' }).then(console.info);
|
|
64
|
-
/*
|
|
65
|
-
const wizard = [
|
|
66
|
-
{
|
|
67
|
-
description: 'Check if the project is already initialized',
|
|
68
|
-
type: 'check',
|
|
69
|
-
choices: {
|
|
70
|
-
type: 'choice',
|
|
71
|
-
choices: [
|
|
72
|
-
{
|
|
73
|
-
label: 'Yes',
|
|
74
|
-
action: 'continue',
|
|
75
|
-
},
|
|
76
|
-
{
|
|
77
|
-
label: 'No',
|
|
78
|
-
action: 'exit',
|
|
79
|
-
exitMessage: 'Exiting...',
|
|
80
|
-
},
|
|
81
|
-
],
|
|
82
|
-
},
|
|
83
|
-
},
|
|
84
|
-
{
|
|
85
|
-
description: 'Check for package.json',
|
|
86
|
-
type: 'check',
|
|
87
|
-
handleCheck: () => {
|
|
88
|
-
// Check if the project is already initialized
|
|
89
|
-
},
|
|
90
|
-
yes: {
|
|
91
|
-
action: 'continue',
|
|
92
|
-
},
|
|
93
|
-
no: {
|
|
94
|
-
action: 'exit',
|
|
95
|
-
exitMessage: 'Exiting...',
|
|
96
|
-
},
|
|
97
|
-
},
|
|
98
|
-
{
|
|
99
|
-
description: 'Check for tsconfig.json',
|
|
100
|
-
type: 'check',
|
|
101
|
-
handleCheck: () => {
|
|
102
|
-
// Check for package.json
|
|
103
|
-
},
|
|
104
|
-
yes: {
|
|
105
|
-
action: 'continue',
|
|
106
|
-
},
|
|
107
|
-
no: {
|
|
108
|
-
action: 'exit',
|
|
109
|
-
exitMessage: 'Exiting...',
|
|
110
|
-
},
|
|
111
|
-
},
|
|
112
|
-
{
|
|
113
|
-
description: 'Check Next.js installed with app router',
|
|
114
|
-
type: 'check',
|
|
115
|
-
handleCheck: () => {
|
|
116
|
-
// Check for tsconfig.json
|
|
117
|
-
},
|
|
118
|
-
yes: {
|
|
119
|
-
action: 'continue',
|
|
120
|
-
},
|
|
121
|
-
no: {
|
|
122
|
-
action: 'exit',
|
|
123
|
-
exitMessage: 'Exiting...',
|
|
124
|
-
},
|
|
125
|
-
},
|
|
126
|
-
{
|
|
127
|
-
description: 'Choose validation library',
|
|
128
|
-
type: 'install',
|
|
129
|
-
choices: {
|
|
130
|
-
type: 'choice',
|
|
131
|
-
choices: [
|
|
132
|
-
{
|
|
133
|
-
package: 'vovk-zod',
|
|
134
|
-
action: 'install',
|
|
135
|
-
notes: 'Further installation notes: install zod',
|
|
136
|
-
},
|
|
137
|
-
{
|
|
138
|
-
package: 'vovk-yup',
|
|
139
|
-
action: 'install',
|
|
140
|
-
notes: 'Further installation notes: install yup',
|
|
141
|
-
},
|
|
142
|
-
{
|
|
143
|
-
package: 'vovk-dto',
|
|
144
|
-
action: 'install',
|
|
145
|
-
notes: 'Further installation notes: install class-validator and class-transformer',
|
|
146
|
-
},
|
|
147
|
-
{
|
|
148
|
-
package: null,
|
|
149
|
-
action: 'continue',
|
|
150
|
-
},
|
|
151
|
-
],
|
|
152
|
-
},
|
|
153
|
-
},
|
|
154
|
-
{
|
|
155
|
-
description: 'Do you want to enable client validation?',
|
|
156
|
-
type: 'choice',
|
|
157
|
-
choices: [
|
|
158
|
-
{
|
|
159
|
-
label: 'Yes',
|
|
160
|
-
action: 'updateConfig',
|
|
161
|
-
},
|
|
162
|
-
{
|
|
163
|
-
label: 'No',
|
|
164
|
-
action: 'updateConfig',
|
|
165
|
-
},
|
|
166
|
-
],
|
|
167
|
-
},
|
|
168
|
-
];
|
|
169
|
-
|
|
170
|
-
// export default console.info(wizard);
|
|
171
|
-
*/
|
package/dist/server/index.d.mts
DELETED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|