vovk-cli 0.0.1-beta.60 → 0.0.1-beta.62
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 +11 -11
- package/dist/generate/generate.mjs +5 -1
- package/dist/getProjectInfo/getConfig/getUserConfig.mjs +107 -26
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +1 -1
- package/dist/init/index.mjs +1 -1
- package/dist/new/render.mjs +1 -1
- package/package.json +7 -5
package/README.md
CHANGED
|
@@ -7,30 +7,30 @@
|
|
|
7
7
|
</picture>
|
|
8
8
|
</a>
|
|
9
9
|
<br>
|
|
10
|
-
<strong>Back-end for Next.js
|
|
10
|
+
<strong>Back-end Framework for Next.js App Router</strong>
|
|
11
11
|
<br />
|
|
12
|
-
<a href="https://vovk.dev/
|
|
13
|
-
|
|
12
|
+
<a href="https://vovk.dev/">Documentation</a>
|
|
13
|
+
|
|
14
14
|
<a href="https://vovk.dev/quick-install">Quick Start</a>
|
|
15
|
-
|
|
16
|
-
<a href="https://
|
|
15
|
+
|
|
16
|
+
<a href="https://vovk.dev/performance">Performance</a>
|
|
17
17
|
</p>
|
|
18
18
|
|
|
19
19
|
---
|
|
20
20
|
|
|
21
21
|
## vovk-cli [](https://www.npmjs.com/package/vovk-cli)
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
Vovk.ts CLI that will be used as a devDependency in a Vovk.ts app.
|
|
24
24
|
|
|
25
25
|
```sh
|
|
26
26
|
npm install -D vovk-cli
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
-
- [vovk dev](https://vovk.dev/dev) - starts the development script that watches the changes in [controllers](https://vovk.dev/controller) and regenerates the [schema](https://vovk.dev/schema) and [client](https://vovk.dev/typescript)
|
|
30
|
-
- [vovk generate](https://vovk.dev/generate) - generates the client based on the schema
|
|
31
|
-
- [vovk bundle](https://vovk.dev/bundle) - bundles the client with [tsdown](https://tsdown.dev/)
|
|
32
|
-
- [vovk init](https://vovk.dev/init) - initializes Vovk.ts project
|
|
33
|
-
- [vovk new](https://vovk.dev/new) - generates a new controller, service or a custom module
|
|
29
|
+
- [vovk dev](https://vovk.dev/dev) - starts the development script that watches the changes in [controllers](https://vovk.dev/controller) and regenerates the [schema](https://vovk.dev/schema) and [client](https://vovk.dev/typescript)
|
|
30
|
+
- [vovk generate](https://vovk.dev/generate) - generates the client based on the schema
|
|
31
|
+
- [vovk bundle](https://vovk.dev/bundle) - bundles the client with [tsdown](https://tsdown.dev/)
|
|
32
|
+
- [vovk init](https://vovk.dev/init) - initializes a new Vovk.ts project
|
|
33
|
+
- [vovk new](https://vovk.dev/new) - generates a new controller, service or a custom module
|
|
34
34
|
|
|
35
35
|
```sh
|
|
36
36
|
npx vovk-cli --help
|
|
@@ -38,13 +38,14 @@ const getIncludedSegmentNames = (config, fullSchema, configKey, cliGenerateOptio
|
|
|
38
38
|
};
|
|
39
39
|
function logClientGenerationResults({ results, log, isEnsuringClient = false, forceNothingWrittenLog = false, clientType = 'Composed', startTime, fromTemplates, }) {
|
|
40
40
|
const writtenResults = results.filter(({ written }) => written);
|
|
41
|
+
const origins = _.uniq(results.map((result) => result.origin).filter((origin) => !!origin));
|
|
41
42
|
const duration = Date.now() - startTime;
|
|
42
43
|
const groupedByDir = _.groupBy(writtenResults, ({ outAbsoluteDir }) => outAbsoluteDir);
|
|
43
44
|
const logOrDebug = forceNothingWrittenLog ? log.info : log.debug;
|
|
44
45
|
if (writtenResults.length) {
|
|
45
46
|
for (const [outAbsoluteDir, dirResults] of Object.entries(groupedByDir)) {
|
|
46
47
|
const templateNames = _.uniq(dirResults.map(({ templateName }) => templateName));
|
|
47
|
-
log.info(`${clientType} client${isEnsuringClient ? ' placeholder' : ''} is generated to ${chalkHighlightThing(normalizeOutTemplatePath(outAbsoluteDir, dirResults[0].package))} from template${templateNames.length !== 1 ? 's' : ''} ${chalkHighlightThing(templateNames.map((s) => `"${s}"`).join(', '))} in ${duration}ms`);
|
|
48
|
+
log.info(`${clientType} client${isEnsuringClient ? ' placeholder' : ''} is generated to ${chalkHighlightThing(normalizeOutTemplatePath(outAbsoluteDir, dirResults[0].package))} from template${templateNames.length !== 1 ? 's' : ''} ${chalkHighlightThing(templateNames.map((s) => `"${s}"`).join(', '))}${origins.length && !isEnsuringClient ? ` with origin${origins.length !== 1 ? 's' : ''} ${chalkHighlightThing(origins.join(', '))}` : ''} in ${duration}ms`);
|
|
48
49
|
}
|
|
49
50
|
}
|
|
50
51
|
else if (fromTemplates.length) {
|
|
@@ -191,6 +192,7 @@ export async function generate({ isEnsuringClient = false, isBundle = false, pro
|
|
|
191
192
|
templateName,
|
|
192
193
|
outAbsoluteDir,
|
|
193
194
|
package: packageJson,
|
|
195
|
+
origin,
|
|
194
196
|
};
|
|
195
197
|
}));
|
|
196
198
|
if (composedClientTemplateFiles.length) {
|
|
@@ -272,6 +274,7 @@ export async function generate({ isEnsuringClient = false, isBundle = false, pro
|
|
|
272
274
|
written,
|
|
273
275
|
templateName,
|
|
274
276
|
package: packageJson,
|
|
277
|
+
origin,
|
|
275
278
|
};
|
|
276
279
|
}));
|
|
277
280
|
const outAbsoluteDir = path.resolve(cwd, outCwdRelativeDir);
|
|
@@ -282,6 +285,7 @@ export async function generate({ isEnsuringClient = false, isBundle = false, pro
|
|
|
282
285
|
templateName,
|
|
283
286
|
outAbsoluteDir,
|
|
284
287
|
package: results[0]?.package || {}, // TODO: Might be wrong in Python segmented client (unknown use case)
|
|
288
|
+
origin: results[0]?.origin || '',
|
|
285
289
|
};
|
|
286
290
|
}));
|
|
287
291
|
if (segmentedClientTemplateFiles.length) {
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import { pathToFileURL } from 'node:url';
|
|
1
2
|
import { readFile } from 'node:fs/promises';
|
|
2
3
|
import { createRequire } from 'node:module';
|
|
3
|
-
import { dirname } from 'node:path';
|
|
4
|
-
import
|
|
5
|
-
import { pathToFileURL } from 'node:url';
|
|
4
|
+
import { dirname, extname } from 'node:path';
|
|
5
|
+
import vm from 'node:vm';
|
|
6
6
|
import { getConfigAbsolutePaths } from './getConfigAbsolutePaths.mjs';
|
|
7
|
+
const isVMModulesEnabled = typeof vm.SourceTextModule !== 'undefined';
|
|
7
8
|
export async function getUserConfig({ configPath: givenConfigPath, cwd, }) {
|
|
8
9
|
const configAbsolutePaths = await getConfigAbsolutePaths({ configPath: givenConfigPath, cwd });
|
|
9
10
|
if (!configAbsolutePaths.length) {
|
|
@@ -12,10 +13,7 @@ export async function getUserConfig({ configPath: givenConfigPath, cwd, }) {
|
|
|
12
13
|
const configPath = configAbsolutePaths[0];
|
|
13
14
|
let userConfig;
|
|
14
15
|
let lastError;
|
|
15
|
-
const loaders =
|
|
16
|
-
() => loadConfigWithVm(configPath),
|
|
17
|
-
() => importWithCacheBuster(configPath),
|
|
18
|
-
];
|
|
16
|
+
const loaders = await getLoadersForExtension(configPath);
|
|
19
17
|
for (const loader of loaders) {
|
|
20
18
|
try {
|
|
21
19
|
userConfig = await loader();
|
|
@@ -27,36 +25,119 @@ export async function getUserConfig({ configPath: givenConfigPath, cwd, }) {
|
|
|
27
25
|
}
|
|
28
26
|
return { userConfig: null, configAbsolutePaths, error: lastError };
|
|
29
27
|
}
|
|
30
|
-
async function
|
|
31
|
-
const
|
|
32
|
-
const
|
|
33
|
-
const
|
|
34
|
-
|
|
28
|
+
async function getLoadersForExtension(configPath) {
|
|
29
|
+
const ext = extname(configPath).toLowerCase();
|
|
30
|
+
const code = await readFile(configPath, 'utf-8');
|
|
31
|
+
const hasDynamicImport = /\bimport\s*\(/.test(code);
|
|
32
|
+
// If config has dynamic imports and flag is not enabled, skip VM loaders entirely
|
|
33
|
+
const canUseVM = isVMModulesEnabled || !hasDynamicImport;
|
|
34
|
+
switch (ext) {
|
|
35
|
+
case '.mjs':
|
|
36
|
+
return canUseVM
|
|
37
|
+
? [() => importWithVMModule(configPath, code), () => importWithCacheBuster(configPath)]
|
|
38
|
+
: [() => importWithCacheBuster(configPath)];
|
|
39
|
+
case '.cjs':
|
|
40
|
+
return canUseVM
|
|
41
|
+
? [() => importWithVMCommonJS(configPath, code), () => importWithCacheBuster(configPath)]
|
|
42
|
+
: [() => importWithCacheBuster(configPath)];
|
|
43
|
+
case '.js':
|
|
44
|
+
default:
|
|
45
|
+
return canUseVM
|
|
46
|
+
? [
|
|
47
|
+
() => importWithVMCommonJS(configPath, code),
|
|
48
|
+
() => importWithVMModule(configPath, code),
|
|
49
|
+
() => importWithCacheBuster(configPath),
|
|
50
|
+
]
|
|
51
|
+
: [() => importWithCacheBuster(configPath)];
|
|
52
|
+
}
|
|
35
53
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
54
|
+
function createDynamicImportHandler(context) {
|
|
55
|
+
return async (specifier) => {
|
|
56
|
+
const imported = await import(specifier);
|
|
57
|
+
const exportNames = Object.keys(imported);
|
|
58
|
+
const syntheticModule = new vm.SyntheticModule(exportNames, function () {
|
|
59
|
+
for (const name of exportNames) {
|
|
60
|
+
this.setExport(name, imported[name]);
|
|
61
|
+
}
|
|
62
|
+
}, { context, identifier: specifier });
|
|
63
|
+
await syntheticModule.link(() => {
|
|
64
|
+
throw new Error('Nested linking not supported');
|
|
65
|
+
});
|
|
66
|
+
await syntheticModule.evaluate();
|
|
67
|
+
return syntheticModule;
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
async function importWithVMCommonJS(configPath, code) {
|
|
71
|
+
const require = createRequire(configPath);
|
|
40
72
|
const moduleObj = { exports: {} };
|
|
41
|
-
const
|
|
73
|
+
const contextObject = {
|
|
42
74
|
module: moduleObj,
|
|
43
75
|
exports: moduleObj.exports,
|
|
44
|
-
require
|
|
45
|
-
__dirname: dirname(configPath),
|
|
76
|
+
require,
|
|
46
77
|
__filename: configPath,
|
|
78
|
+
__dirname: dirname(configPath),
|
|
47
79
|
console,
|
|
48
80
|
process,
|
|
49
81
|
Buffer,
|
|
82
|
+
URL,
|
|
83
|
+
URLSearchParams,
|
|
50
84
|
setTimeout,
|
|
51
|
-
clearTimeout,
|
|
52
85
|
setInterval,
|
|
86
|
+
setImmediate,
|
|
87
|
+
clearTimeout,
|
|
53
88
|
clearInterval,
|
|
54
|
-
|
|
89
|
+
clearImmediate,
|
|
55
90
|
};
|
|
56
|
-
|
|
57
|
-
const
|
|
58
|
-
|
|
91
|
+
const context = vm.createContext(contextObject);
|
|
92
|
+
const script = new vm.Script(code, {
|
|
93
|
+
filename: configPath,
|
|
94
|
+
importModuleDynamically: createDynamicImportHandler(context),
|
|
95
|
+
});
|
|
96
|
+
script.runInContext(context);
|
|
97
|
+
return moduleObj.exports;
|
|
59
98
|
}
|
|
60
|
-
function
|
|
61
|
-
|
|
99
|
+
async function importWithVMModule(configPath, code) {
|
|
100
|
+
if (!isVMModulesEnabled) {
|
|
101
|
+
throw new Error('vm.SourceTextModule not available');
|
|
102
|
+
}
|
|
103
|
+
const configUrl = pathToFileURL(configPath).href;
|
|
104
|
+
const context = vm.createContext({
|
|
105
|
+
console,
|
|
106
|
+
process,
|
|
107
|
+
Buffer,
|
|
108
|
+
URL,
|
|
109
|
+
URLSearchParams,
|
|
110
|
+
setTimeout,
|
|
111
|
+
setInterval,
|
|
112
|
+
setImmediate,
|
|
113
|
+
clearTimeout,
|
|
114
|
+
clearInterval,
|
|
115
|
+
clearImmediate,
|
|
116
|
+
});
|
|
117
|
+
const module = new vm.SourceTextModule(code, {
|
|
118
|
+
context,
|
|
119
|
+
identifier: configUrl,
|
|
120
|
+
initializeImportMeta(meta) {
|
|
121
|
+
meta.url = configUrl;
|
|
122
|
+
},
|
|
123
|
+
importModuleDynamically: createDynamicImportHandler(context),
|
|
124
|
+
});
|
|
125
|
+
await module.link(async (specifier) => {
|
|
126
|
+
const imported = await import(specifier);
|
|
127
|
+
const exportNames = Object.keys(imported);
|
|
128
|
+
const syntheticModule = new vm.SyntheticModule(exportNames, function () {
|
|
129
|
+
for (const name of exportNames) {
|
|
130
|
+
this.setExport(name, imported[name]);
|
|
131
|
+
}
|
|
132
|
+
}, { context, identifier: specifier });
|
|
133
|
+
return syntheticModule;
|
|
134
|
+
});
|
|
135
|
+
await module.evaluate();
|
|
136
|
+
return module.namespace.default;
|
|
137
|
+
}
|
|
138
|
+
async function importWithCacheBuster(configPath) {
|
|
139
|
+
const cacheBuster = Date.now();
|
|
140
|
+
const configPathUrl = pathToFileURL(configPath).href;
|
|
141
|
+
const { default: userConfig } = (await import(`${configPathUrl}?cache=${cacheBuster}`));
|
|
142
|
+
return userConfig;
|
|
62
143
|
}
|
package/dist/index.d.mts
CHANGED
package/dist/index.mjs
CHANGED
package/dist/init/index.mjs
CHANGED
|
@@ -223,7 +223,7 @@ export class Init {
|
|
|
223
223
|
}
|
|
224
224
|
}
|
|
225
225
|
bundle ??= await confirm({
|
|
226
|
-
message: 'Do you want to set up "tsdown" to bundle TypeScript client?',
|
|
226
|
+
message: 'Do you want to set up "tsdown" and tsconfig.bundle.json to bundle TypeScript client?',
|
|
227
227
|
default: true,
|
|
228
228
|
});
|
|
229
229
|
updateScripts ??= !pkgJson
|
package/dist/new/render.mjs
CHANGED
|
@@ -46,7 +46,7 @@ export async function render(codeTemplate, { cwd, config, withService, segmentNa
|
|
|
46
46
|
};
|
|
47
47
|
const parsed = matter((await ejs.render(codeTemplate, { t }, { async: true, filename: templateFileName })).trim());
|
|
48
48
|
const { outDir, fileName, sourceName, compiledName } = parsed.data;
|
|
49
|
-
const code = empty ? (sourceName ? `export class ${sourceName} {}` : '') : parsed.content;
|
|
49
|
+
const code = empty ? (sourceName ? `export default class ${sourceName} {}` : '') : parsed.content;
|
|
50
50
|
return {
|
|
51
51
|
outDir,
|
|
52
52
|
fileName,
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vovk-cli",
|
|
3
|
-
"version": "0.0.1-beta.
|
|
3
|
+
"version": "0.0.1-beta.62",
|
|
4
|
+
"description": "CLI tool for managing Vovk.ts projects",
|
|
4
5
|
"bin": {
|
|
5
6
|
"vovk": "./dist/index.mjs"
|
|
6
7
|
},
|
|
@@ -12,11 +13,12 @@
|
|
|
12
13
|
"build": "rm -rf dist tsconfig.build.tsbuildinfo && tsc -P tsconfig.build.json",
|
|
13
14
|
"postbuild": "chmod +x ./dist/index.mjs",
|
|
14
15
|
"pre-test": "npm run build",
|
|
15
|
-
"test-only": "npm run pre-test && node --experimental-transform-types --experimental-strip-types --test --test-only test/spec/**/*.mts",
|
|
16
|
-
"test": "npm run pre-test && node --experimental-transform-types --experimental-strip-types --test --test-concurrency=1 test/spec/**/*.mts",
|
|
16
|
+
"test-only": "npm run pre-test && node --experimental-transform-types --experimental-strip-types --experimental-vm-modules --test --test-only test/spec/**/*.mts",
|
|
17
|
+
"test": "npm run pre-test && node --experimental-transform-types --experimental-strip-types --experimental-vm-modules --test --test-concurrency=1 test/spec/**/*.mts",
|
|
17
18
|
"tsc": "tsc --noEmit",
|
|
18
19
|
"ncu": "npm-check-updates -u -x commander,node-pty",
|
|
19
|
-
"npm-publish": "npm publish"
|
|
20
|
+
"npm-publish": "npm publish",
|
|
21
|
+
"clear-test-cache": "rm -rf ./tmp_*"
|
|
20
22
|
},
|
|
21
23
|
"repository": {
|
|
22
24
|
"type": "git",
|
|
@@ -35,7 +37,7 @@
|
|
|
35
37
|
},
|
|
36
38
|
"homepage": "https://vovk.dev",
|
|
37
39
|
"peerDependencies": {
|
|
38
|
-
"vovk": "^3.0.0-beta.
|
|
40
|
+
"vovk": "^3.0.0-beta.98",
|
|
39
41
|
"vovk-ajv": "^0.0.0-beta.4",
|
|
40
42
|
"vovk-client": "^0.0.4-beta.4",
|
|
41
43
|
"vovk-python": "^0.0.1-beta.4",
|