vovk-cli 0.0.1-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/.eslintrc.js +20 -0
  2. package/README.md +1 -0
  3. package/dist/getProjectInfo/directoryExists.d.ts +1 -0
  4. package/dist/getProjectInfo/directoryExists.js +16 -0
  5. package/dist/getProjectInfo/getConfig.d.ts +7 -0
  6. package/dist/getProjectInfo/getConfig.js +29 -0
  7. package/dist/getProjectInfo/getCwdPath.d.ts +1 -0
  8. package/dist/getProjectInfo/getCwdPath.js +19 -0
  9. package/dist/getProjectInfo/getSrcRoot.d.ts +1 -0
  10. package/dist/getProjectInfo/getSrcRoot.js +19 -0
  11. package/dist/getProjectInfo/index.d.ts +48 -0
  12. package/dist/getProjectInfo/index.js +78 -0
  13. package/dist/getProjectInfo/readConfig.d.ts +3 -0
  14. package/dist/getProjectInfo/readConfig.js +73 -0
  15. package/dist/index.d.ts +3 -0
  16. package/dist/index.js +104 -0
  17. package/dist/init.d.ts +2 -0
  18. package/dist/init.js +173 -0
  19. package/dist/locateSegments.d.ts +5 -0
  20. package/dist/locateSegments.js +58 -0
  21. package/dist/postinstall.d.ts +1 -0
  22. package/dist/postinstall.js +27 -0
  23. package/dist/server/createMetadataServer.d.ts +5 -0
  24. package/dist/server/createMetadataServer.js +31 -0
  25. package/dist/server/diffMetadata.d.ts +43 -0
  26. package/dist/server/diffMetadata.js +77 -0
  27. package/dist/server/ensureMetadataFiles.d.ts +3 -0
  28. package/dist/server/ensureMetadataFiles.js +100 -0
  29. package/dist/server/generateClient.d.ts +7 -0
  30. package/dist/server/generateClient.js +98 -0
  31. package/dist/server/index.d.ts +6 -0
  32. package/dist/server/index.js +285 -0
  33. package/dist/server/isMetadataEmpty.d.ts +2 -0
  34. package/dist/server/isMetadataEmpty.js +7 -0
  35. package/dist/server/logDiffResult.d.ts +3 -0
  36. package/dist/server/logDiffResult.js +84 -0
  37. package/dist/server/writeOneMetadataFile.d.ts +11 -0
  38. package/dist/server/writeOneMetadataFile.js +34 -0
  39. package/dist/types.d.ts +30 -0
  40. package/dist/types.js +2 -0
  41. package/dist/utils/debounceWithArgs.d.ts +2 -0
  42. package/dist/utils/debounceWithArgs.js +20 -0
  43. package/dist/utils/fileExists.d.ts +1 -0
  44. package/dist/utils/fileExists.js +16 -0
  45. package/dist/utils/getAvailablePort.d.ts +10 -0
  46. package/dist/utils/getAvailablePort.js +47 -0
  47. package/package.json +43 -0
  48. package/src/getProjectInfo/directoryExists.ts +10 -0
  49. package/src/getProjectInfo/getConfig.ts +29 -0
  50. package/src/getProjectInfo/getCwdPath.ts +15 -0
  51. package/src/getProjectInfo/getSrcRoot.ts +14 -0
  52. package/src/getProjectInfo/index.ts +63 -0
  53. package/src/getProjectInfo/readConfig.ts +50 -0
  54. package/src/index.ts +112 -0
  55. package/src/init.ts +174 -0
  56. package/src/locateSegments.ts +40 -0
  57. package/src/postinstall.ts +27 -0
  58. package/src/server/createMetadataServer.ts +30 -0
  59. package/src/server/diffMetadata.ts +110 -0
  60. package/src/server/ensureMetadataFiles.ts +92 -0
  61. package/src/server/generateClient.ts +108 -0
  62. package/src/server/index.ts +306 -0
  63. package/src/server/isMetadataEmpty.ts +6 -0
  64. package/src/server/logDiffResult.ts +114 -0
  65. package/src/server/writeOneMetadataFile.ts +44 -0
  66. package/src/types.ts +58 -0
  67. package/src/utils/debounceWithArgs.ts +22 -0
  68. package/src/utils/fileExists.ts +10 -0
  69. package/src/utils/getAvailablePort.ts +50 -0
  70. package/test/data/segments/[[...vovk]]/route.ts +0 -0
  71. package/test/data/segments/bar/[[...custom]]/route.ts +0 -0
  72. package/test/data/segments/baz/[[...vovk]]/noroute.ts +0 -0
  73. package/test/data/segments/foo/[[...vovk]]/route.ts +0 -0
  74. package/test/data/segments/garply/waldo/route.ts +0 -0
  75. package/test/data/segments/grault/xxxx/[[...vovk]]/noroute.ts +0 -0
  76. package/test/data/segments/quux/corge/[[...vovk]]/route.ts +0 -0
  77. package/test/index.ts +3 -0
  78. package/test/metadata-diff.test.ts +300 -0
  79. package/test/metadata-write.test.ts +82 -0
  80. package/test/utils.test.ts +49 -0
  81. package/tsconfig.json +11 -0
  82. package/tsconfig.test.json +4 -0
package/.eslintrc.js ADDED
@@ -0,0 +1,20 @@
1
+ module.exports = {
2
+ extends: '../../.eslintrc.js',
3
+ rules: {
4
+ '@typescript-eslint/no-unsafe-argument': 'off',
5
+ '@typescript-eslint/no-unsafe-assignment': 'off',
6
+ '@typescript-eslint/no-var-requires': 'off',
7
+ '@typescript-eslint/no-unsafe-call': 'off',
8
+ '@typescript-eslint/no-unsafe-member-access': 'off',
9
+ '@typescript-eslint/no-unsafe-return': 'off',
10
+ 'no-console': 'error',
11
+ },
12
+ parserOptions: {
13
+ ecmaVersion: 2022,
14
+ sourceType: 'module',
15
+ project: './tsconfig.test.json',
16
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
17
+ tsconfigRootDir: __dirname,
18
+ createDefaultProgram: true,
19
+ },
20
+ };
package/README.md ADDED
@@ -0,0 +1 @@
1
+ Description is coming soon.
@@ -0,0 +1 @@
1
+ export default function directoryExists(dir: string): Promise<boolean>;
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.default = directoryExists;
7
+ const promises_1 = __importDefault(require("fs/promises"));
8
+ async function directoryExists(dir) {
9
+ try {
10
+ const stats = await promises_1.default.stat(dir);
11
+ return stats.isDirectory();
12
+ }
13
+ catch (error) {
14
+ return false;
15
+ }
16
+ }
@@ -0,0 +1,7 @@
1
+ import type { VovkConfig } from '../types';
2
+ export default function getConfig({ clientOutDir }: {
3
+ clientOutDir?: string;
4
+ }): Promise<{
5
+ config: Required<VovkConfig>;
6
+ srcRoot: string;
7
+ }>;
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.default = getConfig;
7
+ const readConfig_1 = __importDefault(require("./readConfig"));
8
+ const getCwdPath_1 = __importDefault(require("./getCwdPath"));
9
+ const getSrcRoot_1 = __importDefault(require("./getSrcRoot"));
10
+ const path_1 = __importDefault(require("path"));
11
+ async function getConfig({ clientOutDir }) {
12
+ const env = process.env;
13
+ const userConfig = await (0, readConfig_1.default)();
14
+ const srcRoot = await (0, getSrcRoot_1.default)();
15
+ const cwd = process.cwd();
16
+ const config = {
17
+ modulesDir: path_1.default.join(cwd, env.VOVK_MODULES_DIR ?? userConfig.modulesDir ?? './' + [srcRoot, 'modules'].filter(Boolean).join('/')),
18
+ validateOnClient: (0, getCwdPath_1.default)(env.VOVK_VALIDATE_ON_CLIENT ?? userConfig.validateOnClient ?? null),
19
+ validationLibrary: (0, getCwdPath_1.default)(env.VOVK_VALIDATION_LIBRARY ?? userConfig.validationLibrary ?? null),
20
+ fetcher: (0, getCwdPath_1.default)(env.VOVK_FETCHER ?? userConfig.fetcher ?? 'vovk/client/defaultFetcher'),
21
+ metadataOutDir: env.VOVK_METADATA_OUT_DIR ?? userConfig.metadataOutDir ?? './.vovk-schema',
22
+ clientOutDir: clientOutDir ?? env.VOVK_CLIENT_OUT_DIR ?? userConfig.clientOutDir ?? './node_modules/.vovk',
23
+ origin: (env.VOVK_ORIGIN ?? userConfig.origin ?? '').replace(/\/$/, ''), // Remove trailing slash
24
+ rootEntry: env.VOVK_ROOT_ENTRY ?? userConfig.rootEntry ?? 'api',
25
+ rootSegmentModulesDirName: env.VOVK_ROOT_SEGMENT_MODULES_DIR_NAME ?? userConfig.rootSegmentModulesDirName ?? '',
26
+ logLevel: env.VOVK_LOG_LEVEL ?? userConfig.logLevel ?? 'debug', // TODO: change to 'warn' when v3 is ready
27
+ };
28
+ return { config, srcRoot };
29
+ }
@@ -0,0 +1 @@
1
+ export default function getCwdPath<T extends string | null>(inputPath: T, baseDir?: string): T;
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.default = getCwdPath;
7
+ const path_1 = __importDefault(require("path"));
8
+ // TODO Rename
9
+ function getCwdPath(inputPath, baseDir = process.cwd()) {
10
+ if (inputPath === null) {
11
+ return null;
12
+ }
13
+ // Check if the path is absolute
14
+ if (path_1.default.isAbsolute(inputPath) || inputPath.startsWith('./') || inputPath.startsWith('../')) {
15
+ return path_1.default.resolve(baseDir, inputPath);
16
+ }
17
+ // If it's a module or absolute path, keep it as is
18
+ return inputPath;
19
+ }
@@ -0,0 +1 @@
1
+ export default function getSrcRoot(): Promise<string>;
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.default = getSrcRoot;
7
+ const path_1 = __importDefault(require("path"));
8
+ const directoryExists_1 = __importDefault(require("./directoryExists"));
9
+ async function getSrcRoot() {
10
+ const cwd = process.cwd();
11
+ // Next.js Docs: src/app or src/pages will be ignored if app or pages are present in the root directory.
12
+ if (await (0, directoryExists_1.default)(path_1.default.join(cwd, 'app'))) {
13
+ return cwd;
14
+ }
15
+ else if (await (0, directoryExists_1.default)(path_1.default.join(cwd, 'src/app'))) {
16
+ return path_1.default.join(cwd, 'src');
17
+ }
18
+ throw new Error(`Could not find app router directory. Check Next.js docs for more info.`);
19
+ }
@@ -0,0 +1,48 @@
1
+ import * as loglevel from 'loglevel';
2
+ export type ProjectInfo = Awaited<ReturnType<typeof getProjectInfo>>;
3
+ export default function getProjectInfo({ port: givenPort, clientOutDir, }?: {
4
+ port?: number;
5
+ clientOutDir?: string;
6
+ }): Promise<{
7
+ cwd: string;
8
+ port: string;
9
+ vovkPort: string;
10
+ apiEntryPoint: string;
11
+ apiPrefix: string;
12
+ apiDir: string;
13
+ srcRoot: string;
14
+ metadataOutFullPath: string;
15
+ metadataOutImportPath: string;
16
+ clientOutFullPath: string;
17
+ fetcherClientImportPath: string;
18
+ config: Required<import("../types").VovkConfig>;
19
+ log: {
20
+ info: (msg: string) => void;
21
+ warn: (msg: string) => void;
22
+ error: (msg: string) => void;
23
+ debug: (msg: string) => void;
24
+ raw: {
25
+ default: loglevel.RootLogger;
26
+ noConflict(): any;
27
+ getLogger(name: string | symbol): loglevel.Logger;
28
+ getLoggers(): {
29
+ [name: string]: loglevel.Logger;
30
+ };
31
+ levels: loglevel.LogLevel;
32
+ methodFactory: loglevel.MethodFactory;
33
+ trace(...msg: any[]): void;
34
+ debug(...msg: any[]): void;
35
+ log(...msg: any[]): void;
36
+ info(...msg: any[]): void;
37
+ warn(...msg: any[]): void;
38
+ error(...msg: any[]): void;
39
+ setLevel(level: loglevel.LogLevelDesc, persist?: boolean): void;
40
+ getLevel(): loglevel.LogLevel[keyof loglevel.LogLevel];
41
+ setDefaultLevel(level: loglevel.LogLevelDesc): void;
42
+ resetLevel(): void;
43
+ enableAll(persist?: boolean): void;
44
+ disableAll(persist?: boolean): void;
45
+ rebuild(): void;
46
+ };
47
+ };
48
+ }>;
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ exports.default = getProjectInfo;
30
+ const path_1 = __importDefault(require("path"));
31
+ const loglevel = __importStar(require("loglevel"));
32
+ const chalk_1 = __importDefault(require("chalk"));
33
+ const getConfig_1 = __importDefault(require("./getConfig"));
34
+ // TODO: Rename all occurrences of metadata to schema
35
+ // TODO: Rename default API option "prefix" to "apiRoot" or just "root" (?). Also think of renaming prefix as an option to origin (?)
36
+ // TODO: Load config dynamically to generate client and write schema
37
+ // TODO: Create VovkCLIError class
38
+ async function getProjectInfo({ port: givenPort, clientOutDir, } = {}) {
39
+ const env = process.env;
40
+ const port = givenPort?.toString() ?? process.env.PORT ?? '3000';
41
+ // Make PORT available to the config file at getConfig
42
+ process.env.PORT = port;
43
+ const cwd = process.cwd();
44
+ const { config, srcRoot } = await (0, getConfig_1.default)({ clientOutDir });
45
+ const vovkPort = env.VOVK_PORT || (parseInt(port) + 6969).toString();
46
+ const apiEntryPoint = `${config.origin}/${config.rootEntry}`; // ??? TODO
47
+ const apiPrefix = `${config.origin}/${config.rootEntry}`; // ??? TODO
48
+ const apiDir = path_1.default.join(srcRoot, 'app', config.rootEntry);
49
+ const metadataOutFullPath = path_1.default.join(cwd, config.metadataOutDir);
50
+ const metadataOutImportPath = path_1.default.relative(config.clientOutDir, metadataOutFullPath);
51
+ const fetcherClientImportPath = config.fetcher.startsWith('.')
52
+ ? path_1.default.relative(config.clientOutDir, config.fetcher)
53
+ : config.fetcher;
54
+ const clientOutFullPath = path_1.default.join(cwd, config.clientOutDir);
55
+ const log = {
56
+ info: (msg) => loglevel.info(chalk_1.default.blueBright(`🐺 ${msg}`)),
57
+ warn: (msg) => loglevel.warn(chalk_1.default.yellowBright(`🐺 ${msg}`)),
58
+ error: (msg) => loglevel.error(chalk_1.default.redBright(`🐺 ${msg}`)),
59
+ debug: (msg) => loglevel.debug(chalk_1.default.gray(`🐺 ${msg}`)),
60
+ raw: loglevel,
61
+ };
62
+ loglevel.setLevel(config.logLevel);
63
+ return {
64
+ cwd,
65
+ port,
66
+ vovkPort,
67
+ apiEntryPoint,
68
+ apiPrefix,
69
+ apiDir,
70
+ srcRoot,
71
+ metadataOutFullPath,
72
+ metadataOutImportPath,
73
+ clientOutFullPath,
74
+ fetcherClientImportPath,
75
+ config,
76
+ log,
77
+ };
78
+ }
@@ -0,0 +1,3 @@
1
+ import type { VovkConfig } from '../types';
2
+ declare function readConfig(): Promise<VovkConfig>;
3
+ export default readConfig;
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ const fs_1 = require("fs");
30
+ const path_1 = __importDefault(require("path"));
31
+ async function findConfigPath() {
32
+ const rootDir = process.cwd();
33
+ const baseName = 'vovk.config';
34
+ const extensions = ['cjs', 'mjs', 'js'];
35
+ for (const ext of extensions) {
36
+ const filePath = path_1.default.join(rootDir, `${baseName}.${ext}`);
37
+ try {
38
+ await fs_1.promises.stat(filePath);
39
+ return filePath; // Return the path if the file exists
40
+ }
41
+ catch {
42
+ // If the file doesn't exist, an error is thrown. Catch it and continue checking.
43
+ }
44
+ }
45
+ return null; // Return null if no config file was found
46
+ }
47
+ async function readConfig() {
48
+ const configPath = await findConfigPath();
49
+ let config = {};
50
+ if (!configPath) {
51
+ return config;
52
+ }
53
+ try {
54
+ if (configPath.endsWith('.cjs') || configPath.endsWith('.js')) {
55
+ try {
56
+ delete require.cache[require.resolve(configPath)];
57
+ }
58
+ finally {
59
+ config = require(configPath);
60
+ }
61
+ }
62
+ else if (configPath.endsWith('.mjs')) {
63
+ const cacheBuster = Date.now();
64
+ ({ default: config } = await Promise.resolve(`${`${configPath}?cache=${cacheBuster}`}`).then(s => __importStar(require(s))));
65
+ }
66
+ }
67
+ catch (e) {
68
+ // eslint-disable-next-line no-console
69
+ console.error('🐺 ❌ Error reading config file:', e.message);
70
+ }
71
+ return config;
72
+ }
73
+ exports.default = readConfig;
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ import { VovkConfig, VovkEnv } from './types';
3
+ export type { VovkConfig, VovkEnv };
package/dist/index.js ADDED
@@ -0,0 +1,104 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
16
+ }) : function(o, v) {
17
+ o["default"] = v;
18
+ });
19
+ var __importStar = (this && this.__importStar) || function (mod) {
20
+ if (mod && mod.__esModule) return mod;
21
+ var result = {};
22
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
23
+ __setModuleDefault(result, mod);
24
+ return result;
25
+ };
26
+ var __importDefault = (this && this.__importDefault) || function (mod) {
27
+ return (mod && mod.__esModule) ? mod : { "default": mod };
28
+ };
29
+ Object.defineProperty(exports, "__esModule", { value: true });
30
+ const commander_1 = require("commander");
31
+ const concurrently_1 = __importDefault(require("concurrently"));
32
+ const getAvailablePort_1 = __importDefault(require("./utils/getAvailablePort"));
33
+ const server_1 = require("./server");
34
+ const getProjectInfo_1 = __importDefault(require("./getProjectInfo"));
35
+ const generateClient_1 = __importDefault(require("./server/generateClient"));
36
+ const locateSegments_1 = __importDefault(require("./locateSegments"));
37
+ const program = new commander_1.Command();
38
+ program.name('vovk').description('Vovk CLI tool').version('1.0.0');
39
+ program
40
+ .command('dev')
41
+ .description('Start development server (optional flag --next-dev to start Vovk Server with Next.js)')
42
+ .option('--project <path>', 'Path to Next.js project', process.cwd())
43
+ .option('--client-out <path>', 'Path to client output directory')
44
+ .option('--next-dev', 'Start Vovk Server and Next.js with automatic port allocation', false)
45
+ .allowUnknownOption(true)
46
+ .action(async (options, command) => {
47
+ const portAttempts = 30;
48
+ const PORT = !options.nextDev
49
+ ? process.env.PORT
50
+ : process.env.PORT ||
51
+ (await (0, getAvailablePort_1.default)(3000, portAttempts, 0, (failedPort, tryingPort) =>
52
+ // eslint-disable-next-line no-console
53
+ console.warn(`🐺 Next.js Port ${failedPort} is in use, trying ${tryingPort} instead.`)).catch(() => {
54
+ throw new Error(`🐺 ❌ Failed to find available Next port after ${portAttempts} attempts`);
55
+ }));
56
+ if (!PORT) {
57
+ throw new Error('🐺 ❌ PORT env variable is required');
58
+ }
59
+ if (options.nextDev) {
60
+ const { result } = (0, concurrently_1.default)([
61
+ {
62
+ command: `node ${__dirname}/server/index.js`,
63
+ name: 'Vovk.ts Metadata Server',
64
+ env: Object.assign({ PORT, __VOVK_START_SERVER_IN_STANDALONE_MODE__: 'true' }, options.clientOut ? { VOVK_CLIENT_OUT_DIR: options.clientOut } : {}),
65
+ },
66
+ {
67
+ command: `cd ${options.project} && npx next dev ${command.args.join(' ')}`,
68
+ name: 'Next.js Development Server',
69
+ env: { PORT },
70
+ },
71
+ ], {
72
+ killOthers: ['failure', 'success'],
73
+ prefix: 'none',
74
+ });
75
+ try {
76
+ await result;
77
+ }
78
+ finally {
79
+ // eslint-disable-next-line no-console
80
+ console.log('🐺 Exiting...');
81
+ }
82
+ }
83
+ else {
84
+ void new server_1.VovkCLIServer().startServer({ clientOutDir: options.clientOut });
85
+ }
86
+ });
87
+ program
88
+ .command('generate')
89
+ .description('Generate client')
90
+ .option('--client-out <path>', 'Path to output directory')
91
+ .action(async (options) => {
92
+ const projectInfo = await (0, getProjectInfo_1.default)({ clientOutDir: options.clientOut });
93
+ const segments = await (0, locateSegments_1.default)(projectInfo.apiDir);
94
+ const metadata = await Promise.resolve(`${projectInfo.metadataOutFullPath}`).then(s => __importStar(require(s)));
95
+ await (0, generateClient_1.default)(projectInfo, segments, metadata.default);
96
+ });
97
+ program
98
+ .command('help')
99
+ .description('Show help message')
100
+ .action(() => program.help());
101
+ program.parse(process.argv);
102
+ if (!process.argv.slice(2).length) {
103
+ program.outputHelp();
104
+ }
package/dist/init.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/init.js ADDED
@@ -0,0 +1,173 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ /*
4
+ npx vovk-cli init
5
+ - Check if the project is already initialized
6
+ - Do you want to reinitialize the project?
7
+ - Yes
8
+ - No (exit)
9
+ - Check for package.json, if not found, show error and exit
10
+ - Check for tsconfig.json, if not found, show error and exit
11
+ - Check Next.js installed
12
+ - Choose validation library: add to the installation list
13
+ - vovk-zod
14
+ - Further installation notes: install zod
15
+ - vovk-yup
16
+ - Further installation notes: install yup
17
+ - vovk-dto
18
+ - Further installation notes: install class-validator and class-transformer
19
+ - None
20
+ - If validation library is not None,
21
+ - Do you want to enable client validation?
22
+ - Yes
23
+ - Add client validation to the config
24
+ - No
25
+ - Do you want to use concurrently? (NO NEED, USE CONCURRENTLY BY DEFAULT)
26
+ - Yes (recommended)
27
+ - Add concurrently to the installation list
28
+ - No
29
+ - Do you want to update NPM scripts?
30
+ - Yes
31
+ - Update NPM scripts
32
+ - No
33
+ - if experimentalDecorators is not found in tsconfig.json,
34
+ - Do you want to add experimentalDecorators to tsconfig.json?
35
+ - Yes
36
+ - Add experimentalDecorators to tsconfig.json
37
+ - No
38
+ - Do you want to create route file with example service and controller? (NO NEED)
39
+ - Yes
40
+ - Create route file with example controller
41
+ - No, I will create it myself
42
+ - End
43
+ - If there are any packages to install, install them
44
+ - Show installation notes
45
+ - If there are any files to create, create
46
+ - If there are any config files to update, update
47
+ - If example route file is NOT created, show example route file and controller
48
+ - Show how to run the project
49
+ - If npm scripts are updated
50
+ - npm run dev
51
+ - If npm scripts are NOT updated
52
+ - If concurrently is installed
53
+ - concurrently "vovk dev" "next dev"
54
+ - If concurrently is NOT installed
55
+ - vovk dev --next-dev
56
+ - Open http://localhost:3000/api/hello-world
57
+ - Show how to make a request to the example route
58
+ - Show success message
59
+ */
60
+ Object.defineProperty(exports, "__esModule", { value: true });
61
+ const prompts_1 = require("@inquirer/prompts");
62
+ // Or
63
+ // import confirm from '@inquirer/confirm';
64
+ // eslint-disable-next-line no-console
65
+ void (0, prompts_1.confirm)({ message: 'Continue?' }).then(console.info);
66
+ /*
67
+ const wizard = [
68
+ {
69
+ description: 'Check if the project is already initialized',
70
+ type: 'check',
71
+ choices: {
72
+ type: 'choice',
73
+ choices: [
74
+ {
75
+ label: 'Yes',
76
+ action: 'continue',
77
+ },
78
+ {
79
+ label: 'No',
80
+ action: 'exit',
81
+ exitMessage: 'Exiting...',
82
+ },
83
+ ],
84
+ },
85
+ },
86
+ {
87
+ description: 'Check for package.json',
88
+ type: 'check',
89
+ handleCheck: () => {
90
+ // Check if the project is already initialized
91
+ },
92
+ yes: {
93
+ action: 'continue',
94
+ },
95
+ no: {
96
+ action: 'exit',
97
+ exitMessage: 'Exiting...',
98
+ },
99
+ },
100
+ {
101
+ description: 'Check for tsconfig.json',
102
+ type: 'check',
103
+ handleCheck: () => {
104
+ // Check for package.json
105
+ },
106
+ yes: {
107
+ action: 'continue',
108
+ },
109
+ no: {
110
+ action: 'exit',
111
+ exitMessage: 'Exiting...',
112
+ },
113
+ },
114
+ {
115
+ description: 'Check Next.js installed with app router',
116
+ type: 'check',
117
+ handleCheck: () => {
118
+ // Check for tsconfig.json
119
+ },
120
+ yes: {
121
+ action: 'continue',
122
+ },
123
+ no: {
124
+ action: 'exit',
125
+ exitMessage: 'Exiting...',
126
+ },
127
+ },
128
+ {
129
+ description: 'Choose validation library',
130
+ type: 'install',
131
+ choices: {
132
+ type: 'choice',
133
+ choices: [
134
+ {
135
+ package: 'vovk-zod',
136
+ action: 'install',
137
+ notes: 'Further installation notes: install zod',
138
+ },
139
+ {
140
+ package: 'vovk-yup',
141
+ action: 'install',
142
+ notes: 'Further installation notes: install yup',
143
+ },
144
+ {
145
+ package: 'vovk-dto',
146
+ action: 'install',
147
+ notes: 'Further installation notes: install class-validator and class-transformer',
148
+ },
149
+ {
150
+ package: null,
151
+ action: 'continue',
152
+ },
153
+ ],
154
+ },
155
+ },
156
+ {
157
+ description: 'Do you want to enable client validation?',
158
+ type: 'choice',
159
+ choices: [
160
+ {
161
+ label: 'Yes',
162
+ action: 'updateConfig',
163
+ },
164
+ {
165
+ label: 'No',
166
+ action: 'updateConfig',
167
+ },
168
+ ],
169
+ },
170
+ ];
171
+
172
+ // export default console.info(wizard);
173
+ */
@@ -0,0 +1,5 @@
1
+ export type Segment = {
2
+ routeFilePath: string;
3
+ segmentName: string;
4
+ };
5
+ export default function locateSegments(dir: string, rootDir?: string): Promise<Segment[]>;