vovk-cli 0.0.1-draft.2 → 0.0.1-draft.20
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 +1 -1
- package/dist/{watcher → dev}/diffSchema.d.mts +1 -1
- package/dist/dev/ensureClient.d.mts +5 -0
- package/dist/dev/ensureClient.mjs +31 -0
- package/dist/{watcher → dev}/ensureSchemaFiles.mjs +20 -8
- package/dist/{watcher → dev}/index.d.mts +1 -1
- package/dist/{watcher → dev}/index.mjs +25 -22
- package/dist/{watcher → dev}/logDiffResult.d.mts +2 -2
- package/dist/{watcher → dev}/logDiffResult.mjs +13 -9
- package/dist/{watcher → dev}/writeOneSchemaFile.d.mts +1 -1
- package/dist/{watcher → dev}/writeOneSchemaFile.mjs +4 -3
- package/dist/generateClient.d.mts +1 -1
- package/dist/generateClient.mjs +6 -6
- package/dist/getProjectInfo/getConfigAbsolutePaths.mjs +2 -2
- package/dist/getProjectInfo/getRelativeSrcRoot.mjs +4 -4
- package/dist/getProjectInfo/getUserConfig.mjs +1 -1
- package/dist/getProjectInfo/index.mjs +1 -1
- package/dist/index.d.mts +2 -24
- package/dist/index.mjs +12 -37
- package/dist/init/checkTSConfigForExperimentalDecorators.mjs +2 -2
- package/dist/init/createConfig.d.mts +3 -4
- package/dist/init/createConfig.mjs +5 -5
- package/dist/init/getTemplateFilesFromPackage.d.mts +2 -1
- package/dist/init/getTemplateFilesFromPackage.mjs +3 -4
- package/dist/init/index.d.mts +1 -2
- package/dist/init/index.mjs +36 -85
- 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 +12 -5
- package/dist/init/updateNPMScripts.mjs +1 -1
- package/dist/init/updateTypeScriptConfig.mjs +2 -2
- package/dist/initProgram.d.mts +2 -0
- package/dist/initProgram.mjs +21 -0
- package/dist/locateSegments.mjs +2 -2
- package/dist/new/addClassToSegmentCode.mjs +6 -2
- package/dist/new/index.d.mts +2 -2
- package/dist/new/index.mjs +13 -3
- package/dist/new/newModule.d.mts +6 -2
- package/dist/new/newModule.mjs +50 -26
- package/dist/new/newSegment.d.mts +3 -2
- package/dist/new/newSegment.mjs +5 -5
- package/dist/new/render.d.mts +3 -7
- package/dist/new/render.mjs +11 -7
- package/dist/postinstall.mjs +5 -3
- package/dist/types.d.mts +38 -2
- package/dist/utils/formatLoggedSegmentName.mjs +1 -1
- package/dist/utils/getAvailablePort.mjs +3 -2
- package/dist/utils/getFileSystemEntryType.mjs +1 -1
- package/package.json +8 -6
- package/templates/controller.ejs +18 -17
- package/templates/service.ejs +24 -4
- package/templates/worker.ejs +24 -1
- package/dist/getProjectInfo/directoryExists.d.mts +0 -1
- package/dist/getProjectInfo/directoryExists.mjs +0 -10
- package/templates_old/MyThingController.c.only.template.ts +0 -32
- package/templates_old/MyThingController.c.template.ts +0 -34
- package/templates_old/MyThingService.s.template.ts +0 -18
- package/templates_old/controller.ejs +0 -85
- package/templates_old/service.ejs +0 -9
- package/templates_old/worker.ejs +0 -9
- package/templates_old/zod/MyThingController.c.only.template.ts +0 -32
- package/templates_old/zod/MyThingController.c.template.ts +0 -39
- package/templates_old/zod/MyThingService.s.template.ts +0 -18
- /package/dist/{watcher → dev}/diffSchema.mjs +0 -0
- /package/dist/{watcher → dev}/ensureSchemaFiles.d.mts +0 -0
- /package/dist/{watcher → dev}/isMetadataEmpty.d.mts +0 -0
- /package/dist/{watcher → dev}/isMetadataEmpty.mjs +0 -0
package/README.md
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
Description is coming soon.
|
|
1
|
+
Description is coming soon.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import fs from 'node:fs/promises';
|
|
3
|
+
export default async function ensureClient(projectInfo) {
|
|
4
|
+
const { config, cwd, log } = projectInfo;
|
|
5
|
+
const now = Date.now();
|
|
6
|
+
const clientoOutDirAbsolutePath = path.join(cwd, config.clientOutDir);
|
|
7
|
+
const dts = `// auto-generated
|
|
8
|
+
// This is a temporary placeholder to avoid errors if client is imported before it's generated.
|
|
9
|
+
// If you still see this text, the client is not generated yet because of an unknown problem.
|
|
10
|
+
// Feel free to report an issue at https://github.com/finom/vovk/issues`;
|
|
11
|
+
const js = dts;
|
|
12
|
+
const ts = dts;
|
|
13
|
+
const localJsAbsolutePath = path.join(clientoOutDirAbsolutePath, 'client.js');
|
|
14
|
+
const localDtsAbsolutePath = path.join(clientoOutDirAbsolutePath, 'client.d.ts');
|
|
15
|
+
const localTsAbsolutePath = path.join(clientoOutDirAbsolutePath, 'index.ts');
|
|
16
|
+
const existingJs = await fs.readFile(localJsAbsolutePath, 'utf-8').catch(() => null);
|
|
17
|
+
const existingDts = await fs.readFile(localDtsAbsolutePath, 'utf-8').catch(() => null);
|
|
18
|
+
const existingTs = await fs.readFile(localTsAbsolutePath, 'utf-8').catch(() => null);
|
|
19
|
+
if (existingJs && existingDts && existingTs) {
|
|
20
|
+
return { written: false, path: clientoOutDirAbsolutePath };
|
|
21
|
+
}
|
|
22
|
+
await fs.mkdir(clientoOutDirAbsolutePath, { recursive: true });
|
|
23
|
+
if (!existingJs)
|
|
24
|
+
await fs.writeFile(localJsAbsolutePath, js);
|
|
25
|
+
if (!existingDts)
|
|
26
|
+
await fs.writeFile(localDtsAbsolutePath, dts);
|
|
27
|
+
if (!existingTs)
|
|
28
|
+
await fs.writeFile(localTsAbsolutePath, ts);
|
|
29
|
+
log.info(`Empty client files are generated in ${Date.now() - now}ms`);
|
|
30
|
+
return { written: true, path: clientoOutDirAbsolutePath };
|
|
31
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import fs from 'fs/promises';
|
|
2
|
-
import path from 'path';
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
3
|
import debounce from 'lodash/debounce.js';
|
|
4
4
|
import writeOneSchemaFile, { ROOT_SEGMENT_SCHEMA_NAME } from './writeOneSchemaFile.mjs';
|
|
5
5
|
import formatLoggedSegmentName from '../utils/formatLoggedSegmentName.mjs';
|
|
@@ -7,17 +7,29 @@ export default async function ensureSchemaFiles(projectInfo, schemaOutAbsolutePa
|
|
|
7
7
|
const now = Date.now();
|
|
8
8
|
let hasChanged = false;
|
|
9
9
|
// Create index.js file
|
|
10
|
-
const indexContent =
|
|
10
|
+
const indexContent = `// auto-generated
|
|
11
|
+
${segmentNames
|
|
11
12
|
.map((segmentName) => {
|
|
12
13
|
return `module.exports['${segmentName}'] = require('./${segmentName || ROOT_SEGMENT_SCHEMA_NAME}.json');`;
|
|
13
14
|
})
|
|
14
|
-
.join('\n')
|
|
15
|
-
const dTsContent =
|
|
16
|
-
|
|
15
|
+
.join('\n')}`;
|
|
16
|
+
const dTsContent = `// auto-generated
|
|
17
|
+
import type { VovkSchema } from 'vovk';
|
|
18
|
+
declare const segmentSchema: {
|
|
19
|
+
${segmentNames.map((segmentName) => ` '${segmentName}': VovkSchema;`).join('\n')}
|
|
20
|
+
};
|
|
17
21
|
export default segmentSchema;`;
|
|
22
|
+
const jsAbsolutePath = path.join(schemaOutAbsolutePath, 'index.js');
|
|
23
|
+
const dTsAbsolutePath = path.join(schemaOutAbsolutePath, 'index.d.ts');
|
|
24
|
+
const existingJs = await fs.readFile(jsAbsolutePath, 'utf-8').catch(() => null);
|
|
25
|
+
const existingDTs = await fs.readFile(dTsAbsolutePath, 'utf-8').catch(() => null);
|
|
18
26
|
await fs.mkdir(schemaOutAbsolutePath, { recursive: true });
|
|
19
|
-
|
|
20
|
-
|
|
27
|
+
if (existingJs !== indexContent) {
|
|
28
|
+
await fs.writeFile(jsAbsolutePath, indexContent);
|
|
29
|
+
}
|
|
30
|
+
if (existingDTs !== dTsContent) {
|
|
31
|
+
await fs.writeFile(dTsAbsolutePath, dTsContent);
|
|
32
|
+
}
|
|
21
33
|
// Create JSON files (if not exist) with name [segmentName].json (where segmentName can include /, which means the folder structure can be nested)
|
|
22
34
|
await Promise.all(segmentNames.map(async (segmentName) => {
|
|
23
35
|
const { isCreated } = await writeOneSchemaFile({
|
|
@@ -1,20 +1,21 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
1
3
|
import * as chokidar from 'chokidar';
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
4
|
+
import { Agent, setGlobalDispatcher } from 'undici';
|
|
5
|
+
import keyBy from 'lodash/keyBy.js';
|
|
6
|
+
import capitalize from 'lodash/capitalize.js';
|
|
7
|
+
import debounce from 'lodash/debounce.js';
|
|
8
|
+
import isEmpty from 'lodash/isEmpty.js';
|
|
5
9
|
import { debouncedEnsureSchemaFiles } from './ensureSchemaFiles.mjs';
|
|
6
10
|
import writeOneSchemaFile from './writeOneSchemaFile.mjs';
|
|
7
11
|
import logDiffResult from './logDiffResult.mjs';
|
|
12
|
+
import ensureClient from './ensureClient.mjs';
|
|
13
|
+
import getProjectInfo from '../getProjectInfo/index.mjs';
|
|
8
14
|
import generateClient from '../generateClient.mjs';
|
|
9
15
|
import locateSegments from '../locateSegments.mjs';
|
|
10
16
|
import debounceWithArgs from '../utils/debounceWithArgs.mjs';
|
|
11
|
-
import debounce from 'lodash/debounce.js';
|
|
12
|
-
import isEmpty from 'lodash/isEmpty.js';
|
|
13
17
|
import formatLoggedSegmentName from '../utils/formatLoggedSegmentName.mjs';
|
|
14
|
-
|
|
15
|
-
import capitalize from 'lodash/capitalize.js';
|
|
16
|
-
import { Agent, setGlobalDispatcher } from 'undici';
|
|
17
|
-
export class VovkCLIWatcher {
|
|
18
|
+
export class VovkDev {
|
|
18
19
|
#projectInfo;
|
|
19
20
|
#segments = [];
|
|
20
21
|
#schemas = {};
|
|
@@ -27,7 +28,7 @@ export class VovkCLIWatcher {
|
|
|
27
28
|
const schemaOutAbsolutePath = path.join(cwd, config.schemaOutDir);
|
|
28
29
|
const apiDirAbsolutePath = path.join(cwd, apiDir);
|
|
29
30
|
const getSegmentName = (filePath) => path.relative(apiDirAbsolutePath, filePath).replace(segmentReg, '');
|
|
30
|
-
log.debug(`Watching segments
|
|
31
|
+
log.debug(`Watching segments at ${apiDirAbsolutePath}`);
|
|
31
32
|
this.#segmentWatcher = chokidar
|
|
32
33
|
.watch(apiDirAbsolutePath, {
|
|
33
34
|
persistent: true,
|
|
@@ -51,7 +52,6 @@ export class VovkCLIWatcher {
|
|
|
51
52
|
void this.#requestSchema(getSegmentName(filePath));
|
|
52
53
|
}
|
|
53
54
|
})
|
|
54
|
-
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
55
55
|
.on('addDir', async (dirPath) => {
|
|
56
56
|
log.debug(`Directory ${dirPath} has been added to segments folder`);
|
|
57
57
|
this.#segments = await locateSegments(apiDirAbsolutePath);
|
|
@@ -59,7 +59,6 @@ export class VovkCLIWatcher {
|
|
|
59
59
|
void this.#requestSchema(segmentName);
|
|
60
60
|
}
|
|
61
61
|
})
|
|
62
|
-
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
63
62
|
.on('unlinkDir', async (dirPath) => {
|
|
64
63
|
log.debug(`Directory ${dirPath} has been removed from segments folder`);
|
|
65
64
|
this.#segments = await locateSegments(apiDirAbsolutePath);
|
|
@@ -81,13 +80,13 @@ export class VovkCLIWatcher {
|
|
|
81
80
|
log.debug('Segments watcher is ready');
|
|
82
81
|
})
|
|
83
82
|
.on('error', (error) => {
|
|
84
|
-
log.error(`Error watching segments folder: ${error
|
|
83
|
+
log.error(`Error watching segments folder: ${error?.message ?? 'Unknown error'}`);
|
|
85
84
|
});
|
|
86
85
|
};
|
|
87
86
|
#watchModules = () => {
|
|
88
87
|
const { config, cwd, log } = this.#projectInfo;
|
|
89
88
|
const modulesDirAbsolutePath = path.join(cwd, config.modulesDir);
|
|
90
|
-
log.debug(`Watching modules
|
|
89
|
+
log.debug(`Watching modules at ${modulesDirAbsolutePath}`);
|
|
91
90
|
const processControllerChange = debounceWithArgs(this.#processControllerChange, 500);
|
|
92
91
|
this.#modulesWatcher = chokidar
|
|
93
92
|
.watch(modulesDirAbsolutePath, {
|
|
@@ -119,13 +118,14 @@ export class VovkCLIWatcher {
|
|
|
119
118
|
log.debug('Modules watcher is ready');
|
|
120
119
|
})
|
|
121
120
|
.on('error', (error) => {
|
|
122
|
-
log.error(`Error watching modules folder: ${error
|
|
121
|
+
log.error(`Error watching modules folder: ${error?.message ?? 'Unknown error'}`);
|
|
123
122
|
});
|
|
124
123
|
};
|
|
125
124
|
#watchConfig = () => {
|
|
126
125
|
const { log, cwd } = this.#projectInfo;
|
|
127
126
|
log.debug(`Watching config files`);
|
|
128
127
|
let isInitial = true;
|
|
128
|
+
let isReady = false;
|
|
129
129
|
const handle = debounce(async () => {
|
|
130
130
|
this.#projectInfo = await getProjectInfo();
|
|
131
131
|
if (!isInitial) {
|
|
@@ -148,18 +148,21 @@ export class VovkCLIWatcher {
|
|
|
148
148
|
.on('change', () => void handle())
|
|
149
149
|
.on('unlink', () => void handle())
|
|
150
150
|
.on('ready', () => {
|
|
151
|
+
if (isReady)
|
|
152
|
+
return;
|
|
153
|
+
// for some reason this watcher triggers ready event twice
|
|
151
154
|
log.debug('Config files watcher is ready');
|
|
155
|
+
isReady = true;
|
|
152
156
|
})
|
|
153
|
-
.on('error', (error) => {
|
|
154
|
-
log.error(`Error watching config files: ${error.message}`);
|
|
155
|
-
});
|
|
157
|
+
.on('error', (error) => log.error(`Error watching config files: ${error?.message ?? 'Unknown error'}`));
|
|
156
158
|
void handle();
|
|
157
159
|
};
|
|
158
|
-
#watch() {
|
|
160
|
+
async #watch() {
|
|
159
161
|
if (this.#isWatching)
|
|
160
162
|
throw new Error('Already watching');
|
|
161
163
|
const { log } = this.#projectInfo;
|
|
162
164
|
log.debug(`Starting segments and modules watcher. Detected initial segments: ${JSON.stringify(this.#segments.map((s) => s.segmentName))}.`);
|
|
165
|
+
await ensureClient(this.#projectInfo);
|
|
163
166
|
// automatically watches segments and modules
|
|
164
167
|
this.#watchConfig();
|
|
165
168
|
}
|
|
@@ -275,16 +278,16 @@ export class VovkCLIWatcher {
|
|
|
275
278
|
const schemaOutAbsolutePath = path.join(cwd, config.schemaOutDir);
|
|
276
279
|
this.#segments = await locateSegments(apiDirAbsolutePath);
|
|
277
280
|
await debouncedEnsureSchemaFiles(this.#projectInfo, schemaOutAbsolutePath, this.#segments.map((s) => s.segmentName));
|
|
278
|
-
// Request schema every segment in
|
|
281
|
+
// Request schema every segment in 5 seconds in order to update schema and start watching
|
|
279
282
|
setTimeout(() => {
|
|
280
283
|
for (const { segmentName } of this.#segments) {
|
|
281
284
|
void this.#requestSchema(segmentName);
|
|
282
285
|
}
|
|
283
286
|
this.#watch();
|
|
284
|
-
},
|
|
287
|
+
}, 5000);
|
|
285
288
|
}
|
|
286
289
|
}
|
|
287
290
|
const env = process.env;
|
|
288
291
|
if (env.__VOVK_START_WATCHER_IN_STANDALONE_MODE__ === 'true') {
|
|
289
|
-
void new
|
|
292
|
+
void new VovkDev().start();
|
|
290
293
|
}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import type { DiffResult } from './diffSchema.mjs';
|
|
2
|
+
import type { ProjectInfo } from '../getProjectInfo/index.mjs';
|
|
3
3
|
export default function logDiffResult(segmentName: string, diffResult: DiffResult, projectInfo: ProjectInfo): void;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
1
2
|
import formatLoggedSegmentName from '../utils/formatLoggedSegmentName.mjs';
|
|
2
3
|
import chalkHighlightThing from '../utils/chalkHighlightThing.mjs';
|
|
3
4
|
export default function logDiffResult(segmentName, diffResult, projectInfo) {
|
|
@@ -37,48 +38,51 @@ export default function logDiffResult(segmentName, diffResult, projectInfo) {
|
|
|
37
38
|
});
|
|
38
39
|
});
|
|
39
40
|
const LIMIT = diffNormalized.length < 12 ? diffNormalized.length : 10;
|
|
41
|
+
const addedText = chalk.green('added');
|
|
42
|
+
const removedText = chalk.red('removed');
|
|
43
|
+
const changedText = chalk.cyan('changed');
|
|
40
44
|
for (const diffNormalizedItem of diffNormalized.slice(0, LIMIT)) {
|
|
41
45
|
switch (diffNormalizedItem.what) {
|
|
42
46
|
case 'worker':
|
|
43
47
|
switch (diffNormalizedItem.type) {
|
|
44
48
|
case 'added':
|
|
45
|
-
projectInfo.log.info(`Schema for worker ${chalkHighlightThing(diffNormalizedItem.name)} has been
|
|
49
|
+
projectInfo.log.info(`Schema for worker ${chalkHighlightThing(diffNormalizedItem.name)} has been ${addedText} at ${formatLoggedSegmentName(segmentName)}`);
|
|
46
50
|
break;
|
|
47
51
|
case 'removed':
|
|
48
|
-
projectInfo.log.info(`Schema for worker ${chalkHighlightThing(diffNormalizedItem.name)} has been
|
|
52
|
+
projectInfo.log.info(`Schema for worker ${chalkHighlightThing(diffNormalizedItem.name)} has been ${removedText} from ${formatLoggedSegmentName(segmentName)}`);
|
|
49
53
|
break;
|
|
50
54
|
}
|
|
51
55
|
break;
|
|
52
56
|
case 'controller':
|
|
53
57
|
switch (diffNormalizedItem.type) {
|
|
54
58
|
case 'added':
|
|
55
|
-
projectInfo.log.info(`Schema for controller ${chalkHighlightThing(diffNormalizedItem.name)} has been
|
|
59
|
+
projectInfo.log.info(`Schema for controller ${chalkHighlightThing(diffNormalizedItem.name)} has been ${addedText} at ${formatLoggedSegmentName(segmentName)}`);
|
|
56
60
|
break;
|
|
57
61
|
case 'removed':
|
|
58
|
-
projectInfo.log.info(`Schema for controller ${chalkHighlightThing(diffNormalizedItem.name)} has been
|
|
62
|
+
projectInfo.log.info(`Schema for controller ${chalkHighlightThing(diffNormalizedItem.name)} has been ${removedText} from ${formatLoggedSegmentName(segmentName)}`);
|
|
59
63
|
break;
|
|
60
64
|
}
|
|
61
65
|
break;
|
|
62
66
|
case 'workerHandler':
|
|
63
67
|
switch (diffNormalizedItem.type) {
|
|
64
68
|
case 'added':
|
|
65
|
-
projectInfo.log.info(`Schema for worker method ${chalkHighlightThing(diffNormalizedItem.name)} has been
|
|
69
|
+
projectInfo.log.info(`Schema for worker method ${chalkHighlightThing(diffNormalizedItem.name)} has been ${addedText} at ${formatLoggedSegmentName(segmentName)}`);
|
|
66
70
|
break;
|
|
67
71
|
case 'removed':
|
|
68
|
-
projectInfo.log.info(`Schema for worker method ${chalkHighlightThing(diffNormalizedItem.name)} has been
|
|
72
|
+
projectInfo.log.info(`Schema for worker method ${chalkHighlightThing(diffNormalizedItem.name)} has been ${removedText} from ${formatLoggedSegmentName(segmentName)}`);
|
|
69
73
|
break;
|
|
70
74
|
}
|
|
71
75
|
break;
|
|
72
76
|
case 'controllerHandler':
|
|
73
77
|
switch (diffNormalizedItem.type) {
|
|
74
78
|
case 'added':
|
|
75
|
-
projectInfo.log.info(`Schema for controller method ${chalkHighlightThing(diffNormalizedItem.name)} has been
|
|
79
|
+
projectInfo.log.info(`Schema for controller method ${chalkHighlightThing(diffNormalizedItem.name)} has been ${addedText} at ${formatLoggedSegmentName(segmentName)}`);
|
|
76
80
|
break;
|
|
77
81
|
case 'removed':
|
|
78
|
-
projectInfo.log.info(`Schema for controller method ${chalkHighlightThing(diffNormalizedItem.name)} has been
|
|
82
|
+
projectInfo.log.info(`Schema for controller method ${chalkHighlightThing(diffNormalizedItem.name)} has been ${removedText} from ${formatLoggedSegmentName(segmentName)}`);
|
|
79
83
|
break;
|
|
80
84
|
case 'changed':
|
|
81
|
-
projectInfo.log.info(`Schema for controller method ${chalkHighlightThing(diffNormalizedItem.name)} has been
|
|
85
|
+
projectInfo.log.info(`Schema for controller method ${chalkHighlightThing(diffNormalizedItem.name)} has been ${changedText} at ${formatLoggedSegmentName(segmentName)}`);
|
|
82
86
|
break;
|
|
83
87
|
}
|
|
84
88
|
break;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { VovkSchema } from 'vovk';
|
|
2
|
-
import { DiffResult } from './diffSchema.mjs';
|
|
2
|
+
import { type DiffResult } from './diffSchema.mjs';
|
|
3
3
|
export declare const ROOT_SEGMENT_SCHEMA_NAME = "_root";
|
|
4
4
|
export default function writeOneSchemaFile({ schemaOutAbsolutePath, schema, skipIfExists, }: {
|
|
5
5
|
schemaOutAbsolutePath: string;
|
|
@@ -1,10 +1,11 @@
|
|
|
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 diffSchema from './diffSchema.mjs';
|
|
4
|
+
import getFileSystemEntryType from '../utils/getFileSystemEntryType.mjs';
|
|
4
5
|
export const ROOT_SEGMENT_SCHEMA_NAME = '_root';
|
|
5
6
|
export default async function writeOneSchemaFile({ schemaOutAbsolutePath, schema, skipIfExists = false, }) {
|
|
6
7
|
const segmentPath = path.join(schemaOutAbsolutePath, `${schema.segmentName || ROOT_SEGMENT_SCHEMA_NAME}.json`);
|
|
7
|
-
if (skipIfExists) {
|
|
8
|
+
if (skipIfExists && (await getFileSystemEntryType(segmentPath))) {
|
|
8
9
|
try {
|
|
9
10
|
await fs.stat(segmentPath);
|
|
10
11
|
return { isCreated: false, diffResult: null };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import type { VovkSchema } from 'vovk';
|
|
1
2
|
import type { ProjectInfo } from './getProjectInfo/index.mjs';
|
|
2
3
|
import type { Segment } from './locateSegments.mjs';
|
|
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;
|
|
6
6
|
path: string;
|
package/dist/generateClient.mjs
CHANGED
|
@@ -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 formatLoggedSegmentName from './utils/formatLoggedSegmentName.mjs';
|
|
4
4
|
import prettify from './utils/prettify.mjs';
|
|
5
5
|
export default async function generateClient(projectInfo, segments, segmentsSchema) {
|
|
@@ -48,11 +48,11 @@ type Options = typeof fetcher extends VovkClientFetcher<infer U> ? U : never;
|
|
|
48
48
|
ts += `
|
|
49
49
|
${validateOnClientImportPath ? `import validateOnClient from '${validateOnClientImportPath}';\n` : '\nconst validateOnClient = undefined;'}
|
|
50
50
|
type Options = typeof fetcher extends VovkClientFetcher<infer U> ? U : never;
|
|
51
|
-
const
|
|
51
|
+
const apiRoot = '${apiEntryPoint}';
|
|
52
52
|
`;
|
|
53
53
|
js += `
|
|
54
54
|
const { default: validateOnClient = null } = ${validateOnClientImportPath ? `require('${validateOnClientImportPath}')` : '{}'};
|
|
55
|
-
const
|
|
55
|
+
const apiRoot = '${apiEntryPoint}';
|
|
56
56
|
`;
|
|
57
57
|
for (let i = 0; i < segments.length; i++) {
|
|
58
58
|
const { segmentName } = segments[i];
|
|
@@ -64,8 +64,8 @@ const prefix = '${apiEntryPoint}';
|
|
|
64
64
|
continue;
|
|
65
65
|
for (const key of Object.keys(schema.controllers)) {
|
|
66
66
|
dts += `export const ${key}: ReturnType<typeof clientizeController<Controllers${i}["${key}"], Options>>;\n`;
|
|
67
|
-
js += `exports.${key} = clientizeController(schema['${segmentName}'].controllers.${key}, '${segmentName}', { fetcher, validateOnClient, defaultOptions: {
|
|
68
|
-
ts += `export const ${key} = clientizeController<Controllers${i}["${key}"], Options>(schema['${segmentName}'].controllers.${key}, '${segmentName}', { fetcher, validateOnClient, defaultOptions: {
|
|
67
|
+
js += `exports.${key} = clientizeController(schema['${segmentName}'].controllers.${key}, '${segmentName}', { fetcher, validateOnClient, defaultOptions: { apiRoot } });\n`;
|
|
68
|
+
ts += `export const ${key} = clientizeController<Controllers${i}["${key}"], Options>(schema['${segmentName}'].controllers.${key}, '${segmentName}', { fetcher, validateOnClient, defaultOptions: { apiRoot } });\n`;
|
|
69
69
|
}
|
|
70
70
|
for (const key of Object.keys(schema.workers)) {
|
|
71
71
|
dts += `export const ${key}: ReturnType<typeof promisifyWorker<Workers${i}["${key}"]>>;\n`;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import fs from 'fs/promises';
|
|
2
|
-
import path from 'path';
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
3
|
export default async function getConfigAbsolutePaths({ cwd, relativePath, }) {
|
|
4
4
|
const rootDir = path.resolve(cwd, relativePath || '');
|
|
5
5
|
const baseName = 'vovk.config';
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import path from 'path';
|
|
2
|
-
import
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import getFileSystemEntryType, { FileSystemEntryType } from '../utils/getFileSystemEntryType.mjs';
|
|
3
3
|
export default async function getRelativeSrcRoot({ cwd }) {
|
|
4
4
|
// Next.js Docs: src/app or src/pages will be ignored if app or pages are present in the root directory.
|
|
5
|
-
if (await
|
|
5
|
+
if ((await getFileSystemEntryType(path.join(cwd, 'app'))) === FileSystemEntryType.DIRECTORY) {
|
|
6
6
|
return '.';
|
|
7
7
|
}
|
|
8
|
-
else if (await
|
|
8
|
+
else if ((await getFileSystemEntryType(path.join(cwd, 'src/app'))) === FileSystemEntryType.DIRECTORY) {
|
|
9
9
|
return './src';
|
|
10
10
|
}
|
|
11
11
|
throw new Error(`${cwd} Could not find app router directory. Check Next.js docs for more info.`);
|
|
@@ -11,7 +11,7 @@ async function getUserConfig({ cwd, }) {
|
|
|
11
11
|
try {
|
|
12
12
|
userConfig = await importUncachedModule(configPath);
|
|
13
13
|
}
|
|
14
|
-
catch
|
|
14
|
+
catch {
|
|
15
15
|
try {
|
|
16
16
|
const cacheBuster = Date.now();
|
|
17
17
|
({ default: userConfig } = (await import(`${configPath}?cache=${cacheBuster}`)));
|
package/dist/index.d.mts
CHANGED
|
@@ -1,26 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
import type { LogLevelNames } from 'loglevel';
|
|
4
|
-
import type { VovkConfig, VovkEnv } from './types.mjs';
|
|
2
|
+
import type { VovkConfig, VovkDevEnv } from './types.mjs';
|
|
5
3
|
import 'dotenv/config';
|
|
6
|
-
export type { VovkConfig,
|
|
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
|
-
}
|
|
25
|
-
declare const program: Command;
|
|
26
|
-
export declare function initProgram(p: typeof program, command: string): Command;
|
|
4
|
+
export type { VovkConfig, VovkDevEnv };
|
package/dist/index.mjs
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import path from 'path';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { readFileSync } from 'node:fs';
|
|
3
4
|
import { Command } from 'commander';
|
|
4
|
-
import { readFileSync } from 'fs';
|
|
5
5
|
import concurrently from 'concurrently';
|
|
6
6
|
import getAvailablePort from './utils/getAvailablePort.mjs';
|
|
7
7
|
import getProjectInfo from './getProjectInfo/index.mjs';
|
|
8
8
|
import generateClient from './generateClient.mjs';
|
|
9
9
|
import locateSegments from './locateSegments.mjs';
|
|
10
|
-
import {
|
|
11
|
-
import { Init } from './init/index.mjs';
|
|
10
|
+
import { VovkDev } from './dev/index.mjs';
|
|
12
11
|
import newComponents from './new/index.mjs';
|
|
13
12
|
import 'dotenv/config';
|
|
13
|
+
import initProgram from './initProgram.mjs';
|
|
14
14
|
const program = new Command();
|
|
15
15
|
const packageJSON = JSON.parse(readFileSync(path.join(import.meta.dirname, '../package.json'), 'utf-8'));
|
|
16
16
|
program.name('vovk').description('Vovk CLI').version(packageJSON.version);
|
|
17
|
+
initProgram(program, 'init ');
|
|
17
18
|
program
|
|
18
19
|
.command('dev')
|
|
19
20
|
.description('Start schema watcher (optional flag --next-dev to start it with Next.js)')
|
|
@@ -36,8 +37,8 @@ program
|
|
|
36
37
|
if (options.nextDev) {
|
|
37
38
|
const { result } = concurrently([
|
|
38
39
|
{
|
|
39
|
-
command: `node ${import.meta.dirname}/
|
|
40
|
-
name: 'Vovk
|
|
40
|
+
command: `node ${import.meta.dirname}/dev/index.mjs`,
|
|
41
|
+
name: 'Vovk Dev Command',
|
|
41
42
|
env: Object.assign({ PORT, __VOVK_START_WATCHER_IN_STANDALONE_MODE__: 'true' }, options.clientOut ? { VOVK_CLIENT_OUT_DIR: options.clientOut } : {}),
|
|
42
43
|
},
|
|
43
44
|
{
|
|
@@ -57,7 +58,7 @@ program
|
|
|
57
58
|
}
|
|
58
59
|
}
|
|
59
60
|
else {
|
|
60
|
-
void new
|
|
61
|
+
void new VovkDev().start({ clientOutDir: options.clientOut });
|
|
61
62
|
}
|
|
62
63
|
});
|
|
63
64
|
program
|
|
@@ -72,46 +73,20 @@ program
|
|
|
72
73
|
const schema = (await import(path.join(schemaOutAbsolutePath, 'index.js')));
|
|
73
74
|
await generateClient(projectInfo, segments, schema.default);
|
|
74
75
|
});
|
|
75
|
-
// reused at vovk-init
|
|
76
|
-
export function initProgram(p, command) {
|
|
77
|
-
return p
|
|
78
|
-
.command(command + '[prefix]')
|
|
79
|
-
.description('Initialize Vovk project')
|
|
80
|
-
.option('-Y, --yes', 'Skip all prompts and use default values')
|
|
81
|
-
.option('--log-level <level>', 'Set log level', 'info')
|
|
82
|
-
.option('--use-npm', 'Use npm as package manager')
|
|
83
|
-
.option('--use-yarn', 'Use yarn as package manager')
|
|
84
|
-
.option('--use-pnpm', 'Use pnpm as package manager')
|
|
85
|
-
.option('--use-bun', 'Use bun as package manager')
|
|
86
|
-
.option('--skip-install', 'Skip installing dependencies')
|
|
87
|
-
.option('--update-ts-config', 'Update tsconfig.json')
|
|
88
|
-
.option('--update-scripts <mode>', 'Update package.json scripts (implicit or explicit)')
|
|
89
|
-
.option('--validation-library <library>', 'Validation library to use ("vovk-zod", "vovk-yup", "vovk-dto" or another). Set to "none" to skip validation')
|
|
90
|
-
.option('--validate-on-client', 'Validate on client')
|
|
91
|
-
.option('--dry-run', 'Do not write files to disk')
|
|
92
|
-
.option('--channel <channel>', 'Channel to use for fetching packages', 'latest')
|
|
93
|
-
.action((prefix = '.', options) => new Init().main(prefix, options));
|
|
94
|
-
}
|
|
95
|
-
initProgram(program, 'init ');
|
|
96
76
|
program
|
|
97
77
|
.command('new [components...]')
|
|
98
78
|
.alias('n')
|
|
99
79
|
.description('Create new components. "vovk new [...components] [segmentName/]moduleName" to create a new module or "vovk new segment [segmentName]" to create a new segment')
|
|
80
|
+
.option('-o, --overwrite', 'Overwrite existing files')
|
|
81
|
+
.option('--template, --templates <templates...>', 'Override config template. Accepts an array of strings that correspond the order of the components')
|
|
82
|
+
.option('--dir <dirname>', 'Override dirName in template file. Relative to the root of the project')
|
|
83
|
+
.option('--no-segment-update', 'Do not update segment files when creating a new module')
|
|
100
84
|
.option('--dry-run', 'Do not write files to disk')
|
|
101
85
|
.action((components, options) => newComponents(components, options));
|
|
102
86
|
program
|
|
103
87
|
.command('help')
|
|
104
88
|
.description('Show help message')
|
|
105
89
|
.action(() => program.help());
|
|
106
|
-
/*
|
|
107
|
-
TODO
|
|
108
|
-
vovk new segment [segmentName]
|
|
109
|
-
vovk new controller service [segmentName/]moduleName
|
|
110
|
-
vovk new c s w [segmentName/]moduleName
|
|
111
|
-
|
|
112
|
-
vovk c s w userApi/user
|
|
113
|
-
vovk new c s w user
|
|
114
|
-
*/
|
|
115
90
|
program.parse(process.argv);
|
|
116
91
|
if (!process.argv.slice(2).length) {
|
|
117
92
|
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;
|
|
@@ -22,7 +22,7 @@ export default async function createConfig({ root, log, dryRun, options: { valid
|
|
|
22
22
|
config.validateOnClient = `${validationLibrary}/validateOnClient`;
|
|
23
23
|
}
|
|
24
24
|
try {
|
|
25
|
-
const validationTemplates = await getTemplateFilesFromPackage(validationLibrary);
|
|
25
|
+
const validationTemplates = await getTemplateFilesFromPackage(validationLibrary, channel);
|
|
26
26
|
Object.assign(templates, validationTemplates);
|
|
27
27
|
}
|
|
28
28
|
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,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Readable } from 'node:stream';
|
|
2
|
+
import { createGunzip } from 'node:zlib';
|
|
2
3
|
import tar from 'tar-stream';
|
|
3
|
-
import { Readable } from 'stream';
|
|
4
4
|
import getNPMPackageMetadata from '../utils/getNPMPackageMetadata.mjs';
|
|
5
5
|
/**
|
|
6
6
|
* Retrieves a list of files in the 'templates' folder of an NPM package.
|
|
7
7
|
* @param packageName - The name of the NPM package.
|
|
8
8
|
* @returns A promise that resolves to an array of file paths.
|
|
9
9
|
*/
|
|
10
|
-
export default async function
|
|
11
|
-
) {
|
|
10
|
+
export default async function getTemplateFilesFromPackage(packageName, channel = 'latest') {
|
|
12
11
|
const metadata = await getNPMPackageMetadata(packageName);
|
|
13
12
|
const latestVersion = metadata['dist-tags'][channel];
|
|
14
13
|
const tarballUrl = metadata.versions[latestVersion].dist.tarball;
|
package/dist/init/index.d.mts
CHANGED