vovk-cli 0.0.1-draft.3 → 0.0.1-draft.300
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +29 -1
- package/client-templates/cjs/index.cjs.ejs +19 -0
- package/client-templates/cjs/index.d.cts.ejs +25 -0
- package/client-templates/mixins/mixins.d.ts.ejs +64 -0
- package/client-templates/mixins/mixins.json.ejs +1 -0
- package/client-templates/mjs/index.d.mts.ejs +25 -0
- package/client-templates/mjs/index.mjs.ejs +23 -0
- package/client-templates/packageJson/package.json.ejs +1 -0
- package/client-templates/readme/README.md.ejs +38 -0
- package/client-templates/schemaCjs/schema.cjs.ejs +26 -0
- package/client-templates/schemaCjs/schema.d.cts.ejs +10 -0
- package/client-templates/schemaJson/schema.json.ejs +1 -0
- package/client-templates/schemaTs/schema.ts.ejs +35 -0
- package/client-templates/ts/index.ts.ejs +33 -0
- package/dist/bundle/index.d.mts +8 -0
- package/dist/bundle/index.mjs +90 -0
- package/dist/dev/diffSegmentSchema.d.mts +36 -0
- package/dist/{watcher/diffSchema.mjs → dev/diffSegmentSchema.mjs} +4 -12
- package/dist/{watcher → dev}/ensureSchemaFiles.d.mts +3 -0
- package/dist/{watcher → dev}/ensureSchemaFiles.mjs +17 -21
- package/dist/dev/index.d.mts +9 -0
- package/dist/dev/index.mjs +388 -0
- package/dist/dev/logDiffResult.d.mts +3 -0
- package/dist/dev/logDiffResult.mjs +57 -0
- package/dist/dev/writeMetaJson.d.mts +2 -0
- package/dist/dev/writeMetaJson.mjs +17 -0
- package/dist/dev/writeOneSegmentSchemaFile.d.mts +12 -0
- package/dist/dev/writeOneSegmentSchemaFile.mjs +32 -0
- package/dist/generate/ensureClient.d.mts +3 -0
- package/dist/generate/ensureClient.mjs +32 -0
- package/dist/generate/generate.d.mts +15 -0
- package/dist/generate/generate.mjs +291 -0
- package/dist/generate/getClientTemplateFiles.d.mts +20 -0
- package/dist/generate/getClientTemplateFiles.mjs +89 -0
- package/dist/generate/getProjectFullSchema.d.mts +7 -0
- package/dist/generate/getProjectFullSchema.mjs +65 -0
- package/dist/generate/getTemplateClientImports.d.mts +18 -0
- package/dist/generate/getTemplateClientImports.mjs +38 -0
- package/dist/generate/index.d.mts +33 -0
- package/dist/generate/index.mjs +189 -0
- package/dist/generate/mergePackages.d.mts +7 -0
- package/dist/generate/mergePackages.mjs +55 -0
- package/dist/generate/writeOneClientFile.d.mts +36 -0
- package/dist/generate/writeOneClientFile.mjs +120 -0
- package/dist/getProjectInfo/getConfig/getConfigAbsolutePaths.d.mts +5 -0
- package/dist/getProjectInfo/{getConfigAbsolutePaths.mjs → getConfig/getConfigAbsolutePaths.mjs} +6 -3
- package/dist/getProjectInfo/{getRelativeSrcRoot.d.mts → getConfig/getRelativeSrcRoot.d.mts} +1 -1
- package/dist/getProjectInfo/getConfig/getRelativeSrcRoot.mjs +12 -0
- package/dist/getProjectInfo/getConfig/getTemplateDefs.d.mts +16 -0
- package/dist/getProjectInfo/getConfig/getTemplateDefs.mjs +98 -0
- package/dist/getProjectInfo/{getUserConfig.d.mts → getConfig/getUserConfig.d.mts} +3 -2
- package/dist/getProjectInfo/{getUserConfig.mjs → getConfig/getUserConfig.mjs} +7 -5
- package/dist/getProjectInfo/{importUncachedModule.mjs → getConfig/importUncachedModule.mjs} +1 -5
- package/dist/getProjectInfo/{importUncachedModuleWorker.mjs → getConfig/importUncachedModuleWorker.mjs} +0 -1
- package/dist/getProjectInfo/getConfig/index.d.mts +120 -0
- package/dist/getProjectInfo/getConfig/index.mjs +94 -0
- package/dist/getProjectInfo/index.d.mts +12 -9
- package/dist/getProjectInfo/index.mjs +22 -23
- package/dist/index.d.mts +2 -24
- package/dist/index.mjs +106 -69
- package/dist/init/checkTSConfigForExperimentalDecorators.mjs +2 -2
- package/dist/init/createConfig.d.mts +3 -4
- package/dist/init/createConfig.mjs +22 -16
- package/dist/init/getTemplateFilesFromPackage.d.mts +2 -1
- package/dist/init/getTemplateFilesFromPackage.mjs +13 -9
- package/dist/init/index.d.mts +2 -3
- package/dist/init/index.mjs +119 -138
- package/dist/init/installDependencies.d.mts +4 -1
- package/dist/init/installDependencies.mjs +6 -4
- package/dist/init/logUpdateDependenciesError.d.mts +13 -0
- package/dist/init/logUpdateDependenciesError.mjs +51 -0
- package/dist/init/updateDependenciesWithoutInstalling.d.mts +3 -2
- package/dist/init/updateDependenciesWithoutInstalling.mjs +50 -15
- package/dist/init/updateNPMScripts.d.mts +3 -1
- package/dist/init/updateNPMScripts.mjs +10 -7
- package/dist/init/updateTypeScriptConfig.d.mts +4 -1
- package/dist/init/updateTypeScriptConfig.mjs +13 -9
- package/dist/initProgram.d.mts +2 -0
- package/dist/initProgram.mjs +22 -0
- package/dist/locateSegments.d.mts +8 -1
- package/dist/locateSegments.mjs +16 -6
- package/dist/new/addClassToSegmentCode.d.mts +1 -2
- package/dist/new/addClassToSegmentCode.mjs +9 -5
- package/dist/new/addCommonTerms.mjs +1 -0
- package/dist/new/index.d.mts +2 -2
- package/dist/new/index.mjs +14 -3
- package/dist/new/newModule.d.mts +7 -2
- package/dist/new/newModule.mjs +61 -35
- package/dist/new/newSegment.d.mts +4 -2
- package/dist/new/newSegment.mjs +22 -13
- package/dist/new/render.d.mts +9 -9
- package/dist/new/render.mjs +38 -13
- package/dist/types.d.mts +73 -28
- package/dist/utils/compileJSONSchemaToTypeScriptType.d.mts +5 -0
- package/dist/utils/compileJSONSchemaToTypeScriptType.mjs +9 -0
- package/dist/utils/compileTs.d.mts +12 -0
- package/dist/utils/compileTs.mjs +261 -0
- package/dist/utils/debounceWithArgs.d.mts +2 -2
- package/dist/utils/debounceWithArgs.mjs +24 -9
- package/dist/utils/formatLoggedSegmentName.d.mts +3 -1
- package/dist/utils/formatLoggedSegmentName.mjs +4 -3
- package/dist/utils/getAvailablePort.mjs +3 -2
- package/dist/utils/getFileSystemEntryType.mjs +1 -1
- package/dist/utils/getPackageJson.d.mts +3 -0
- package/dist/utils/getPackageJson.mjs +22 -0
- package/dist/utils/getPublicModuleNameFromPath.d.mts +4 -0
- package/dist/utils/getPublicModuleNameFromPath.mjs +9 -0
- package/dist/utils/normalizeOpenAPIMixins.d.mts +7 -0
- package/dist/utils/normalizeOpenAPIMixins.mjs +67 -0
- package/dist/utils/pickSegmentFullSchema.d.mts +3 -0
- package/dist/utils/pickSegmentFullSchema.mjs +15 -0
- package/dist/utils/removeUnlistedDirectories.d.mts +10 -0
- package/dist/utils/removeUnlistedDirectories.mjs +61 -0
- package/dist/utils/resolveAbsoluteModulePath.d.mts +2 -0
- package/dist/utils/resolveAbsoluteModulePath.mjs +32 -0
- package/module-templates/controller.ts.ejs +56 -0
- package/module-templates/service.ts.ejs +28 -0
- package/package.json +42 -21
- package/dist/generateClient.d.mts +0 -7
- package/dist/generateClient.mjs +0 -97
- package/dist/getProjectInfo/directoryExists.d.mts +0 -1
- package/dist/getProjectInfo/directoryExists.mjs +0 -10
- package/dist/getProjectInfo/getConfig.d.mts +0 -11
- package/dist/getProjectInfo/getConfig.mjs +0 -29
- package/dist/getProjectInfo/getConfigAbsolutePaths.d.mts +0 -4
- package/dist/getProjectInfo/getRelativeSrcRoot.mjs +0 -12
- package/dist/postinstall.d.mts +0 -1
- package/dist/postinstall.mjs +0 -22
- package/dist/watcher/diffSchema.d.mts +0 -43
- package/dist/watcher/index.d.mts +0 -6
- package/dist/watcher/index.mjs +0 -295
- package/dist/watcher/isMetadataEmpty.d.mts +0 -2
- package/dist/watcher/isMetadataEmpty.mjs +0 -4
- package/dist/watcher/logDiffResult.d.mts +0 -3
- package/dist/watcher/logDiffResult.mjs +0 -90
- package/dist/watcher/writeOneSchemaFile.d.mts +0 -11
- package/dist/watcher/writeOneSchemaFile.mjs +0 -27
- package/templates/controller.ejs +0 -50
- package/templates/service.ejs +0 -7
- package/templates/worker.ejs +0 -1
- package/templates_old/MyThingController.c.only.template.ts +0 -32
- package/templates_old/MyThingController.c.template.ts +0 -34
- package/templates_old/MyThingService.s.template.ts +0 -18
- package/templates_old/controller.ejs +0 -85
- package/templates_old/service.ejs +0 -9
- package/templates_old/worker.ejs +0 -9
- package/templates_old/zod/MyThingController.c.only.template.ts +0 -32
- package/templates_old/zod/MyThingController.c.template.ts +0 -39
- package/templates_old/zod/MyThingService.s.template.ts +0 -18
- /package/dist/getProjectInfo/{importUncachedModule.d.mts → getConfig/importUncachedModule.d.mts} +0 -0
- /package/dist/getProjectInfo/{importUncachedModuleWorker.d.mts → getConfig/importUncachedModuleWorker.d.mts} +0 -0
package/dist/watcher/index.mjs
DELETED
|
@@ -1,295 +0,0 @@
|
|
|
1
|
-
import * as chokidar from 'chokidar';
|
|
2
|
-
import fs from 'fs/promises';
|
|
3
|
-
import getProjectInfo from '../getProjectInfo/index.mjs';
|
|
4
|
-
import path from 'path';
|
|
5
|
-
import { debouncedEnsureSchemaFiles } from './ensureSchemaFiles.mjs';
|
|
6
|
-
import writeOneSchemaFile from './writeOneSchemaFile.mjs';
|
|
7
|
-
import logDiffResult from './logDiffResult.mjs';
|
|
8
|
-
import generateClient from '../generateClient.mjs';
|
|
9
|
-
import locateSegments from '../locateSegments.mjs';
|
|
10
|
-
import debounceWithArgs from '../utils/debounceWithArgs.mjs';
|
|
11
|
-
import debounce from 'lodash/debounce.js';
|
|
12
|
-
import isEmpty from 'lodash/isEmpty.js';
|
|
13
|
-
import formatLoggedSegmentName from '../utils/formatLoggedSegmentName.mjs';
|
|
14
|
-
import keyBy from 'lodash/keyBy.js';
|
|
15
|
-
import capitalize from 'lodash/capitalize.js';
|
|
16
|
-
import { Agent, setGlobalDispatcher } from 'undici';
|
|
17
|
-
export class VovkCLIWatcher {
|
|
18
|
-
#projectInfo;
|
|
19
|
-
#segments = [];
|
|
20
|
-
#schemas = {};
|
|
21
|
-
#isWatching = false;
|
|
22
|
-
#modulesWatcher = null;
|
|
23
|
-
#segmentWatcher = null;
|
|
24
|
-
#watchSegments = () => {
|
|
25
|
-
const segmentReg = /\/?\[\[\.\.\.[a-zA-Z-_]+\]\]\/route.ts$/;
|
|
26
|
-
const { cwd, log, config, apiDir } = this.#projectInfo;
|
|
27
|
-
const schemaOutAbsolutePath = path.join(cwd, config.schemaOutDir);
|
|
28
|
-
const apiDirAbsolutePath = path.join(cwd, apiDir);
|
|
29
|
-
const getSegmentName = (filePath) => path.relative(apiDirAbsolutePath, filePath).replace(segmentReg, '');
|
|
30
|
-
log.debug(`Watching segments in ${apiDirAbsolutePath}`);
|
|
31
|
-
this.#segmentWatcher = chokidar
|
|
32
|
-
.watch(apiDirAbsolutePath, {
|
|
33
|
-
persistent: true,
|
|
34
|
-
ignoreInitial: true,
|
|
35
|
-
})
|
|
36
|
-
.on('add', (filePath) => {
|
|
37
|
-
log.debug(`File ${filePath} has been added to segments folder`);
|
|
38
|
-
if (segmentReg.test(filePath)) {
|
|
39
|
-
const segmentName = getSegmentName(filePath);
|
|
40
|
-
this.#segments = this.#segments.find((s) => s.segmentName === segmentName)
|
|
41
|
-
? this.#segments
|
|
42
|
-
: [...this.#segments, { routeFilePath: filePath, segmentName }];
|
|
43
|
-
log.info(`${capitalize(formatLoggedSegmentName(segmentName))} has been added`);
|
|
44
|
-
log.debug(`Full list of segments: ${this.#segments.map((s) => s.segmentName).join(', ')}`);
|
|
45
|
-
void debouncedEnsureSchemaFiles(this.#projectInfo, schemaOutAbsolutePath, this.#segments.map((s) => s.segmentName));
|
|
46
|
-
}
|
|
47
|
-
})
|
|
48
|
-
.on('change', (filePath) => {
|
|
49
|
-
log.debug(`File ${filePath} has been changed at segments folder`);
|
|
50
|
-
if (segmentReg.test(filePath)) {
|
|
51
|
-
void this.#requestSchema(getSegmentName(filePath));
|
|
52
|
-
}
|
|
53
|
-
})
|
|
54
|
-
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
55
|
-
.on('addDir', async (dirPath) => {
|
|
56
|
-
log.debug(`Directory ${dirPath} has been added to segments folder`);
|
|
57
|
-
this.#segments = await locateSegments(apiDirAbsolutePath);
|
|
58
|
-
for (const { segmentName } of this.#segments) {
|
|
59
|
-
void this.#requestSchema(segmentName);
|
|
60
|
-
}
|
|
61
|
-
})
|
|
62
|
-
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
63
|
-
.on('unlinkDir', async (dirPath) => {
|
|
64
|
-
log.debug(`Directory ${dirPath} has been removed from segments folder`);
|
|
65
|
-
this.#segments = await locateSegments(apiDirAbsolutePath);
|
|
66
|
-
for (const { segmentName } of this.#segments) {
|
|
67
|
-
void this.#requestSchema(segmentName);
|
|
68
|
-
}
|
|
69
|
-
})
|
|
70
|
-
.on('unlink', (filePath) => {
|
|
71
|
-
log.debug(`File ${filePath} has been removed from segments folder`);
|
|
72
|
-
if (segmentReg.test(filePath)) {
|
|
73
|
-
const segmentName = getSegmentName(filePath);
|
|
74
|
-
this.#segments = this.#segments.filter((s) => s.segmentName !== segmentName);
|
|
75
|
-
log.info(`${formatLoggedSegmentName(segmentName, { upperFirst: true })} has been removed`);
|
|
76
|
-
log.debug(`Full list of segments: ${this.#segments.map((s) => s.segmentName).join(', ')}`);
|
|
77
|
-
void debouncedEnsureSchemaFiles(this.#projectInfo, schemaOutAbsolutePath, this.#segments.map((s) => s.segmentName));
|
|
78
|
-
}
|
|
79
|
-
})
|
|
80
|
-
.on('ready', () => {
|
|
81
|
-
log.debug('Segments watcher is ready');
|
|
82
|
-
})
|
|
83
|
-
.on('error', (error) => {
|
|
84
|
-
log.error(`Error watching segments folder: ${error.message}`);
|
|
85
|
-
});
|
|
86
|
-
};
|
|
87
|
-
#watchModules = () => {
|
|
88
|
-
const { config, cwd, log } = this.#projectInfo;
|
|
89
|
-
const modulesDirAbsolutePath = path.join(cwd, config.modulesDir);
|
|
90
|
-
log.debug(`Watching modules in ${modulesDirAbsolutePath}`);
|
|
91
|
-
const processControllerChange = debounceWithArgs(this.#processControllerChange, 500);
|
|
92
|
-
this.#modulesWatcher = chokidar
|
|
93
|
-
.watch(modulesDirAbsolutePath, {
|
|
94
|
-
persistent: true,
|
|
95
|
-
ignoreInitial: true,
|
|
96
|
-
})
|
|
97
|
-
.on('add', (filePath) => {
|
|
98
|
-
log.debug(`File ${filePath} has been added to modules folder`);
|
|
99
|
-
void processControllerChange(filePath);
|
|
100
|
-
})
|
|
101
|
-
.on('change', (filePath) => {
|
|
102
|
-
log.debug(`File ${filePath} has been changed at modules folder`);
|
|
103
|
-
void processControllerChange(filePath);
|
|
104
|
-
})
|
|
105
|
-
.on('unlink', (filePath) => {
|
|
106
|
-
log.debug(`File ${filePath} has been removed from modules folder`);
|
|
107
|
-
})
|
|
108
|
-
.on('addDir', () => {
|
|
109
|
-
for (const { segmentName } of this.#segments) {
|
|
110
|
-
void this.#requestSchema(segmentName);
|
|
111
|
-
}
|
|
112
|
-
})
|
|
113
|
-
.on('unlinkDir', () => {
|
|
114
|
-
for (const { segmentName } of this.#segments) {
|
|
115
|
-
void this.#requestSchema(segmentName);
|
|
116
|
-
}
|
|
117
|
-
})
|
|
118
|
-
.on('ready', () => {
|
|
119
|
-
log.debug('Modules watcher is ready');
|
|
120
|
-
})
|
|
121
|
-
.on('error', (error) => {
|
|
122
|
-
log.error(`Error watching modules folder: ${error.message}`);
|
|
123
|
-
});
|
|
124
|
-
};
|
|
125
|
-
#watchConfig = () => {
|
|
126
|
-
const { log, cwd } = this.#projectInfo;
|
|
127
|
-
log.debug(`Watching config files`);
|
|
128
|
-
let isInitial = true;
|
|
129
|
-
const handle = debounce(async () => {
|
|
130
|
-
this.#projectInfo = await getProjectInfo();
|
|
131
|
-
if (!isInitial) {
|
|
132
|
-
log.info('Config file has been updated');
|
|
133
|
-
isInitial = false;
|
|
134
|
-
}
|
|
135
|
-
await this.#modulesWatcher?.close();
|
|
136
|
-
await this.#segmentWatcher?.close();
|
|
137
|
-
this.#watchModules();
|
|
138
|
-
this.#watchSegments();
|
|
139
|
-
}, 1000);
|
|
140
|
-
let ready = false;
|
|
141
|
-
chokidar
|
|
142
|
-
.watch(['vovk.config.{js,mjs,cjs}', '.config/vovk.config.{js,mjs,cjs}'], {
|
|
143
|
-
persistent: true,
|
|
144
|
-
cwd,
|
|
145
|
-
ignoreInitial: false,
|
|
146
|
-
depth: 0,
|
|
147
|
-
})
|
|
148
|
-
.on('add', () => void handle())
|
|
149
|
-
.on('change', () => void handle())
|
|
150
|
-
.on('unlink', () => void handle())
|
|
151
|
-
.on('ready', () => {
|
|
152
|
-
if (ready)
|
|
153
|
-
return;
|
|
154
|
-
// for some reason this watcher triggers ready event twice
|
|
155
|
-
log.debug('Config files watcher is ready');
|
|
156
|
-
ready = true;
|
|
157
|
-
})
|
|
158
|
-
.on('error', (error) => {
|
|
159
|
-
log.error(`Error watching config files: ${error.message}`);
|
|
160
|
-
});
|
|
161
|
-
void handle();
|
|
162
|
-
};
|
|
163
|
-
#watch() {
|
|
164
|
-
if (this.#isWatching)
|
|
165
|
-
throw new Error('Already watching');
|
|
166
|
-
const { log } = this.#projectInfo;
|
|
167
|
-
log.debug(`Starting segments and modules watcher. Detected initial segments: ${JSON.stringify(this.#segments.map((s) => s.segmentName))}.`);
|
|
168
|
-
// automatically watches segments and modules
|
|
169
|
-
this.#watchConfig();
|
|
170
|
-
}
|
|
171
|
-
#processControllerChange = async (filePath) => {
|
|
172
|
-
const { log } = this.#projectInfo;
|
|
173
|
-
const code = await fs.readFile(filePath, 'utf-8').catch(() => null);
|
|
174
|
-
if (typeof code !== 'string') {
|
|
175
|
-
log.error(`Error reading file ${filePath}`);
|
|
176
|
-
return;
|
|
177
|
-
}
|
|
178
|
-
const nameOfClasReg = /\bclass\s+([A-Za-z_]\w*)(?:\s*<[^>]*>)?\s*\{/g;
|
|
179
|
-
const namesOfClasses = [...code.matchAll(nameOfClasReg)].map((match) => match[1]);
|
|
180
|
-
const importRegex = /import\s*{[^}]*\b(get|post|put|del|head|options|worker)\b[^}]*}\s*from\s*['"]vovk['"]/;
|
|
181
|
-
if (importRegex.test(code) && namesOfClasses.length) {
|
|
182
|
-
const affectedSegments = this.#segments.filter((s) => {
|
|
183
|
-
const schema = this.#schemas[s.segmentName];
|
|
184
|
-
if (!schema)
|
|
185
|
-
return false;
|
|
186
|
-
const controllersByOriginalName = keyBy(schema.controllers, '_originalControllerName');
|
|
187
|
-
const workersByOriginalName = keyBy(schema.workers, '_originalWorkerName');
|
|
188
|
-
return namesOfClasses.some((name) => schema.controllers[name] ||
|
|
189
|
-
schema.workers[name] ||
|
|
190
|
-
controllersByOriginalName[name] ||
|
|
191
|
-
workersByOriginalName[name]);
|
|
192
|
-
});
|
|
193
|
-
if (affectedSegments.length) {
|
|
194
|
-
log.debug(`A file with controller or worker ${namesOfClasses.join(', ')} have been modified at path "${filePath}". Segment(s) affected: ${JSON.stringify(affectedSegments.map((s) => s.segmentName))}`);
|
|
195
|
-
for (const segment of affectedSegments) {
|
|
196
|
-
await this.#requestSchema(segment.segmentName);
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
else {
|
|
201
|
-
log.debug(`The file does not contain any controller or worker`);
|
|
202
|
-
}
|
|
203
|
-
};
|
|
204
|
-
#requestSchema = debounceWithArgs(async (segmentName) => {
|
|
205
|
-
const { apiEntryPoint, log, port, config } = this.#projectInfo;
|
|
206
|
-
const { devHttps } = config;
|
|
207
|
-
const endpoint = `${apiEntryPoint.startsWith(`http${devHttps ? 's' : ''}://`) ? apiEntryPoint : `http${devHttps ? 's' : ''}://localhost:${port}${apiEntryPoint}`}/${segmentName ? `${segmentName}/` : ''}_schema_`;
|
|
208
|
-
log.debug(`Requesting schema for ${formatLoggedSegmentName(segmentName)} at ${endpoint}`);
|
|
209
|
-
const resp = await fetch(endpoint);
|
|
210
|
-
if (resp.status !== 200) {
|
|
211
|
-
const probableCause = {
|
|
212
|
-
404: 'The segment is not compiled.',
|
|
213
|
-
500: 'Syntax error in one of controllers.',
|
|
214
|
-
}[resp.status];
|
|
215
|
-
log.warn(`Schema request to ${formatLoggedSegmentName(segmentName)} failed with status code ${resp.status} but expected 200.${probableCause ? ` Probable cause: ${probableCause}` : ''}`);
|
|
216
|
-
return;
|
|
217
|
-
}
|
|
218
|
-
let schema = null;
|
|
219
|
-
try {
|
|
220
|
-
({ schema } = (await resp.json()));
|
|
221
|
-
}
|
|
222
|
-
catch (error) {
|
|
223
|
-
log.error(`Error parsing schema for ${formatLoggedSegmentName(segmentName)}: ${error.message}`);
|
|
224
|
-
}
|
|
225
|
-
await this.#handleSchema(schema);
|
|
226
|
-
}, 500);
|
|
227
|
-
async #handleSchema(schema) {
|
|
228
|
-
const { log, config, cwd } = this.#projectInfo;
|
|
229
|
-
if (!schema) {
|
|
230
|
-
log.warn('Segment schema is null');
|
|
231
|
-
return;
|
|
232
|
-
}
|
|
233
|
-
log.debug(`Handling received schema from ${formatLoggedSegmentName(schema.segmentName)}`);
|
|
234
|
-
const schemaOutAbsolutePath = path.join(cwd, config.schemaOutDir);
|
|
235
|
-
const segment = this.#segments.find((s) => s.segmentName === schema.segmentName);
|
|
236
|
-
if (!segment) {
|
|
237
|
-
log.warn(`Segment "${schema.segmentName}" not found`);
|
|
238
|
-
return;
|
|
239
|
-
}
|
|
240
|
-
this.#schemas[schema.segmentName] = schema;
|
|
241
|
-
if (schema.emitSchema) {
|
|
242
|
-
const now = Date.now();
|
|
243
|
-
const { diffResult } = await writeOneSchemaFile({
|
|
244
|
-
schemaOutAbsolutePath,
|
|
245
|
-
schema,
|
|
246
|
-
skipIfExists: false,
|
|
247
|
-
});
|
|
248
|
-
const timeTook = Date.now() - now;
|
|
249
|
-
if (diffResult) {
|
|
250
|
-
logDiffResult(segment.segmentName, diffResult, this.#projectInfo);
|
|
251
|
-
log.info(`Schema for ${formatLoggedSegmentName(segment.segmentName)} has been updated in ${timeTook}ms`);
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
else if (schema && (!isEmpty(schema.controllers) || !isEmpty(schema.workers))) {
|
|
255
|
-
log.error(`Non-empty schema provided for ${formatLoggedSegmentName(segment.segmentName)} but emitSchema is false`);
|
|
256
|
-
}
|
|
257
|
-
if (this.#segments.every((s) => this.#schemas[s.segmentName])) {
|
|
258
|
-
log.debug(`All segments with "emitSchema" have schema.`);
|
|
259
|
-
await generateClient(this.#projectInfo, this.#segments, this.#schemas);
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
async start({ clientOutDir } = {}) {
|
|
263
|
-
this.#projectInfo = await getProjectInfo({ clientOutDir });
|
|
264
|
-
const { log, config, cwd, apiDir } = this.#projectInfo;
|
|
265
|
-
if (config.devHttps) {
|
|
266
|
-
const agent = new Agent({
|
|
267
|
-
connect: {
|
|
268
|
-
rejectUnauthorized: false,
|
|
269
|
-
},
|
|
270
|
-
});
|
|
271
|
-
setGlobalDispatcher(agent);
|
|
272
|
-
}
|
|
273
|
-
process.on('uncaughtException', (err) => {
|
|
274
|
-
log.error(`Uncaught Exception: ${err.message}`);
|
|
275
|
-
});
|
|
276
|
-
process.on('unhandledRejection', (reason) => {
|
|
277
|
-
log.error(`Unhandled Rejection: ${String(reason)}`);
|
|
278
|
-
});
|
|
279
|
-
const apiDirAbsolutePath = path.join(cwd, apiDir);
|
|
280
|
-
const schemaOutAbsolutePath = path.join(cwd, config.schemaOutDir);
|
|
281
|
-
this.#segments = await locateSegments(apiDirAbsolutePath);
|
|
282
|
-
await debouncedEnsureSchemaFiles(this.#projectInfo, schemaOutAbsolutePath, this.#segments.map((s) => s.segmentName));
|
|
283
|
-
// Request schema every segment in 3 seconds in order to update schema and start watching
|
|
284
|
-
setTimeout(() => {
|
|
285
|
-
for (const { segmentName } of this.#segments) {
|
|
286
|
-
void this.#requestSchema(segmentName);
|
|
287
|
-
}
|
|
288
|
-
this.#watch();
|
|
289
|
-
}, 3000);
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
const env = process.env;
|
|
293
|
-
if (env.__VOVK_START_WATCHER_IN_STANDALONE_MODE__ === 'true') {
|
|
294
|
-
void new VovkCLIWatcher().start();
|
|
295
|
-
}
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
import formatLoggedSegmentName from '../utils/formatLoggedSegmentName.mjs';
|
|
2
|
-
import chalkHighlightThing from '../utils/chalkHighlightThing.mjs';
|
|
3
|
-
export default function logDiffResult(segmentName, diffResult, projectInfo) {
|
|
4
|
-
const diffNormalized = [];
|
|
5
|
-
diffResult.workers.added.forEach((name) => {
|
|
6
|
-
diffNormalized.push({ what: 'worker', type: 'added', name });
|
|
7
|
-
});
|
|
8
|
-
diffResult.workers.removed.forEach((name) => {
|
|
9
|
-
diffNormalized.push({ what: 'worker', type: 'removed', name });
|
|
10
|
-
});
|
|
11
|
-
diffResult.workers.handlers.forEach((handler) => {
|
|
12
|
-
handler.added.forEach((name) => {
|
|
13
|
-
diffNormalized.push({ what: 'workerHandler', type: 'added', name: `${handler.nameOfClass}.${name}` });
|
|
14
|
-
});
|
|
15
|
-
handler.removed.forEach((name) => {
|
|
16
|
-
diffNormalized.push({ what: 'workerHandler', type: 'removed', name: `${handler.nameOfClass}.${name}` });
|
|
17
|
-
});
|
|
18
|
-
handler.changed.forEach((name) => {
|
|
19
|
-
diffNormalized.push({ what: 'workerHandler', type: 'changed', name: `${handler.nameOfClass}.${name}` });
|
|
20
|
-
});
|
|
21
|
-
});
|
|
22
|
-
diffResult.controllers.added.forEach((name) => {
|
|
23
|
-
diffNormalized.push({ what: 'controller', type: 'added', name });
|
|
24
|
-
});
|
|
25
|
-
diffResult.controllers.removed.forEach((name) => {
|
|
26
|
-
diffNormalized.push({ what: 'controller', type: 'removed', name });
|
|
27
|
-
});
|
|
28
|
-
diffResult.controllers.handlers.forEach((handler) => {
|
|
29
|
-
handler.added.forEach((name) => {
|
|
30
|
-
diffNormalized.push({ what: 'controllerHandler', type: 'added', name: `${handler.nameOfClass}.${name}` });
|
|
31
|
-
});
|
|
32
|
-
handler.removed.forEach((name) => {
|
|
33
|
-
diffNormalized.push({ what: 'controllerHandler', type: 'removed', name: `${handler.nameOfClass}.${name}` });
|
|
34
|
-
});
|
|
35
|
-
handler.changed.forEach((name) => {
|
|
36
|
-
diffNormalized.push({ what: 'controllerHandler', type: 'changed', name: `${handler.nameOfClass}.${name}` });
|
|
37
|
-
});
|
|
38
|
-
});
|
|
39
|
-
const LIMIT = diffNormalized.length < 12 ? diffNormalized.length : 10;
|
|
40
|
-
for (const diffNormalizedItem of diffNormalized.slice(0, LIMIT)) {
|
|
41
|
-
switch (diffNormalizedItem.what) {
|
|
42
|
-
case 'worker':
|
|
43
|
-
switch (diffNormalizedItem.type) {
|
|
44
|
-
case 'added':
|
|
45
|
-
projectInfo.log.info(`Schema for worker ${chalkHighlightThing(diffNormalizedItem.name)} has been added at ${formatLoggedSegmentName(segmentName)}`);
|
|
46
|
-
break;
|
|
47
|
-
case 'removed':
|
|
48
|
-
projectInfo.log.info(`Schema for worker ${chalkHighlightThing(diffNormalizedItem.name)} has been removed from ${formatLoggedSegmentName(segmentName)}`);
|
|
49
|
-
break;
|
|
50
|
-
}
|
|
51
|
-
break;
|
|
52
|
-
case 'controller':
|
|
53
|
-
switch (diffNormalizedItem.type) {
|
|
54
|
-
case 'added':
|
|
55
|
-
projectInfo.log.info(`Schema for controller ${chalkHighlightThing(diffNormalizedItem.name)} has been added at ${formatLoggedSegmentName(segmentName)}`);
|
|
56
|
-
break;
|
|
57
|
-
case 'removed':
|
|
58
|
-
projectInfo.log.info(`Schema for controller ${chalkHighlightThing(diffNormalizedItem.name)} has been removed from ${formatLoggedSegmentName(segmentName)}`);
|
|
59
|
-
break;
|
|
60
|
-
}
|
|
61
|
-
break;
|
|
62
|
-
case 'workerHandler':
|
|
63
|
-
switch (diffNormalizedItem.type) {
|
|
64
|
-
case 'added':
|
|
65
|
-
projectInfo.log.info(`Schema for worker method ${chalkHighlightThing(diffNormalizedItem.name)} has been added at ${formatLoggedSegmentName(segmentName)}`);
|
|
66
|
-
break;
|
|
67
|
-
case 'removed':
|
|
68
|
-
projectInfo.log.info(`Schema for worker method ${chalkHighlightThing(diffNormalizedItem.name)} has been removed from ${formatLoggedSegmentName(segmentName)}`);
|
|
69
|
-
break;
|
|
70
|
-
}
|
|
71
|
-
break;
|
|
72
|
-
case 'controllerHandler':
|
|
73
|
-
switch (diffNormalizedItem.type) {
|
|
74
|
-
case 'added':
|
|
75
|
-
projectInfo.log.info(`Schema for controller method ${chalkHighlightThing(diffNormalizedItem.name)} has been added at ${formatLoggedSegmentName(segmentName)}`);
|
|
76
|
-
break;
|
|
77
|
-
case 'removed':
|
|
78
|
-
projectInfo.log.info(`Schema for controller method ${chalkHighlightThing(diffNormalizedItem.name)} has been removed from ${formatLoggedSegmentName(segmentName)}`);
|
|
79
|
-
break;
|
|
80
|
-
case 'changed':
|
|
81
|
-
projectInfo.log.info(`Schema for controller method ${chalkHighlightThing(diffNormalizedItem.name)} has been changed at ${formatLoggedSegmentName(segmentName)}`);
|
|
82
|
-
break;
|
|
83
|
-
}
|
|
84
|
-
break;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
if (diffNormalized.length > LIMIT) {
|
|
88
|
-
projectInfo.log.info(`... and ${diffNormalized.length - LIMIT} more changes`);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { VovkSchema } from 'vovk';
|
|
2
|
-
import { DiffResult } from './diffSchema.mjs';
|
|
3
|
-
export declare const ROOT_SEGMENT_SCHEMA_NAME = "_root";
|
|
4
|
-
export default function writeOneSchemaFile({ schemaOutAbsolutePath, schema, skipIfExists, }: {
|
|
5
|
-
schemaOutAbsolutePath: string;
|
|
6
|
-
schema: VovkSchema;
|
|
7
|
-
skipIfExists?: boolean;
|
|
8
|
-
}): Promise<{
|
|
9
|
-
isCreated: boolean;
|
|
10
|
-
diffResult: DiffResult | null;
|
|
11
|
-
}>;
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import path from 'path';
|
|
2
|
-
import fs from 'fs/promises';
|
|
3
|
-
import diffSchema from './diffSchema.mjs';
|
|
4
|
-
export const ROOT_SEGMENT_SCHEMA_NAME = '_root';
|
|
5
|
-
export default async function writeOneSchemaFile({ schemaOutAbsolutePath, schema, skipIfExists = false, }) {
|
|
6
|
-
const segmentPath = path.join(schemaOutAbsolutePath, `${schema.segmentName || ROOT_SEGMENT_SCHEMA_NAME}.json`);
|
|
7
|
-
if (skipIfExists) {
|
|
8
|
-
try {
|
|
9
|
-
await fs.stat(segmentPath);
|
|
10
|
-
return { isCreated: false, diffResult: null };
|
|
11
|
-
}
|
|
12
|
-
catch {
|
|
13
|
-
// File doesn't exist
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
await fs.mkdir(path.dirname(segmentPath), { recursive: true });
|
|
17
|
-
const schemaStr = JSON.stringify(schema, null, 2);
|
|
18
|
-
const existing = await fs.readFile(segmentPath, 'utf-8').catch(() => null);
|
|
19
|
-
if (existing === schemaStr) {
|
|
20
|
-
return { isCreated: false, diffResult: null };
|
|
21
|
-
}
|
|
22
|
-
await fs.writeFile(segmentPath, schemaStr);
|
|
23
|
-
if (existing) {
|
|
24
|
-
return { isCreated: false, diffResult: diffSchema(JSON.parse(existing), schema) };
|
|
25
|
-
}
|
|
26
|
-
return { isCreated: true, diffResult: null };
|
|
27
|
-
}
|
package/templates/controller.ejs
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
<% var modulePascalName = _.upperFirst(_.camelCase(moduleName)); %>
|
|
2
|
-
<% var modulePascalNamePlural = pluralize(modulePascalName); %>
|
|
3
|
-
<% var ControllerName = modulePascalName + 'Controller'; %>
|
|
4
|
-
<% var RPCName = modulePascalName + 'RPC'; %>
|
|
5
|
-
<% var ServiceName = modulePascalName + 'Service'; %>
|
|
6
|
-
---
|
|
7
|
-
filePath: <%= getModulePath(segmentName, moduleName, ControllerName + '.ts') %> # Relative to "modules" dir
|
|
8
|
-
sourceName: <%= ControllerName %> # Used to define import declaration in a segment route file for the given class
|
|
9
|
-
compiledName: <%= RPCName %> # Used to define a compiled object name
|
|
10
|
-
---
|
|
11
|
-
|
|
12
|
-
import { prefix, get, put, post, del<%= !config.validationLibrary ? ', type VovkRequest' : '' %> } from 'vovk';
|
|
13
|
-
<% if(withService) { %>
|
|
14
|
-
import <%= ServiceName %> from './<%= ServiceName %>';
|
|
15
|
-
<% } %>
|
|
16
|
-
|
|
17
|
-
@prefix('<%= _.kebabCase(moduleName).toLowerCase() %>')
|
|
18
|
-
export default class <%= ControllerName %> {
|
|
19
|
-
@get()
|
|
20
|
-
static get<%= modulePascalNamePlural %> = async (req: VovkRequest<null, { q: string }>) => {
|
|
21
|
-
const q = req.nextUrl.searchParams.get('q');
|
|
22
|
-
<% if(withService) { %>
|
|
23
|
-
return <%= ServiceName %>.getMyThingsExample(q);
|
|
24
|
-
<% } else { %>
|
|
25
|
-
return { q };
|
|
26
|
-
<% } %>
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
@put(':id')
|
|
30
|
-
static update<%= modulePascalNamePlural %> = async (req: VovkRequest<{ foo: 'bar' | 'baz' }, { q: string }>, params: { id: string }) => {
|
|
31
|
-
const { id } = params;
|
|
32
|
-
const body = await req.json();
|
|
33
|
-
const q = req.nextUrl.searchParams.get('q');
|
|
34
|
-
<% if(withService) { %>
|
|
35
|
-
return MyThingService.updateMyThingExample(id, q, body);
|
|
36
|
-
<% } else { %>
|
|
37
|
-
return { id, body, q };
|
|
38
|
-
<% } %>
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
@post()
|
|
42
|
-
static create<%= modulePascalNamePlural %> = () => {
|
|
43
|
-
// ...
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
@del(':id')
|
|
47
|
-
static delete<%= modulePascalNamePlural %> = () => {
|
|
48
|
-
// ...
|
|
49
|
-
};
|
|
50
|
-
}
|
package/templates/service.ejs
DELETED
package/templates/worker.ejs
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
// TODO
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { prefix, get, put, post, del, type VovkRequest } from 'vovk';
|
|
2
|
-
|
|
3
|
-
@prefix('my-things')
|
|
4
|
-
export default class MyThingController {
|
|
5
|
-
@get()
|
|
6
|
-
static getMyThingsExample = (req: VovkRequest<null, { q: string }>) => {
|
|
7
|
-
const q = req.nextUrl.searchParams.get('q');
|
|
8
|
-
return { q };
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
@put(':id')
|
|
12
|
-
static updateMyThingExample = async (
|
|
13
|
-
req: VovkRequest<{ foo: 'bar' | 'baz' }, { q: string }>,
|
|
14
|
-
params: { id: string }
|
|
15
|
-
) => {
|
|
16
|
-
const { id } = params;
|
|
17
|
-
const body = await req.json();
|
|
18
|
-
const q = req.nextUrl.searchParams.get('q');
|
|
19
|
-
|
|
20
|
-
return { id, q, body };
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
@post()
|
|
24
|
-
static createMyThingExample = () => {
|
|
25
|
-
// ...
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
@del(':id')
|
|
29
|
-
static deleteMyThingExample = () => {
|
|
30
|
-
// ...
|
|
31
|
-
};
|
|
32
|
-
}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { prefix, get, put, post, del, type VovkRequest } from 'vovk';
|
|
2
|
-
import MyThingService from './MyThingService.s.template';
|
|
3
|
-
|
|
4
|
-
@prefix('my-things')
|
|
5
|
-
export default class MyThingController {
|
|
6
|
-
@get()
|
|
7
|
-
static getMyThingsExample(req: VovkRequest<null, { q: string }>) {
|
|
8
|
-
const q = req.nextUrl.searchParams.get('q');
|
|
9
|
-
|
|
10
|
-
return MyThingService.getMyThingsExample(q);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
@put(':id')
|
|
14
|
-
static updateMyThingExample = async (
|
|
15
|
-
req: VovkRequest<{ foo: 'bar' | 'baz' }, { q: string }>,
|
|
16
|
-
params: { id: string }
|
|
17
|
-
) => {
|
|
18
|
-
const { id } = params;
|
|
19
|
-
const body = await req.json();
|
|
20
|
-
const q = req.nextUrl.searchParams.get('q');
|
|
21
|
-
|
|
22
|
-
return MyThingService.updateMyThingExample(id, q, body);
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
@post()
|
|
26
|
-
static createMyThingExample = () => {
|
|
27
|
-
// ...
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
@del(':id')
|
|
31
|
-
static deleteMyThingExample = () => {
|
|
32
|
-
// ...
|
|
33
|
-
};
|
|
34
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import type { VovkControllerBody, VovkControllerQuery } from 'vovk';
|
|
2
|
-
import type MyThingController from './MyThingController.c.template';
|
|
3
|
-
|
|
4
|
-
export default class MyThingService {
|
|
5
|
-
static getMyThingsExample = (q: VovkControllerQuery<typeof MyThingController.getMyThingsExample>['q']) => {
|
|
6
|
-
return { q };
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
static updateMyThingExample = (
|
|
10
|
-
id: string,
|
|
11
|
-
q: VovkControllerQuery<typeof MyThingController.updateMyThingExample>['q'],
|
|
12
|
-
body: VovkControllerBody<typeof MyThingController.updateMyThingExample>
|
|
13
|
-
) => {
|
|
14
|
-
return { id, q, body };
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
// ...
|
|
18
|
-
}
|