vovk-cli 0.0.1-draft.380 → 0.0.1-draft.382
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 +18 -16
- package/client-templates/readme/README.md.ejs +2 -2
- package/dist/bundle/index.mjs +32 -44
- package/dist/generate/generate.mjs +3 -3
- package/dist/generate/getClientTemplateFiles.mjs +1 -1
- package/dist/generate/writeOneClientFile.d.mts +1 -1
- package/dist/generate/writeOneClientFile.mjs +2 -2
- package/dist/getProjectInfo/getConfig/getTemplateDefs.mjs +3 -3
- package/dist/getProjectInfo/getConfig/index.d.mts +8 -5
- package/dist/getProjectInfo/getConfig/index.mjs +10 -9
- package/dist/getProjectInfo/getMetaSchema.mjs +4 -4
- package/dist/getProjectInfo/index.mjs +1 -1
- package/dist/index.mjs +0 -1
- package/dist/init/createConfig.mjs +3 -3
- package/dist/types.d.mts +1 -1
- package/dist/utils/normalizeOpenAPIMixin.d.mts +2 -2
- package/module-templates/arktype/controller.ts.ejs +29 -19
- package/module-templates/type/controller.ts.ejs +21 -13
- package/module-templates/type/service.ts.ejs +16 -7
- package/module-templates/valibot/controller.ts.ejs +29 -19
- package/package.json +8 -8
package/README.md
CHANGED
|
@@ -1,29 +1,31 @@
|
|
|
1
|
-
<p align="center">
|
|
2
|
-
<picture>
|
|
3
|
-
<source width="300" media="(prefers-color-scheme: dark)" srcset="https://vovk.dev/vovk-logo-white.svg">
|
|
4
|
-
<source width="300" media="(prefers-color-scheme: light)" srcset="https://vovk.dev/vovk-logo.svg">
|
|
5
|
-
<img width="300" alt="vovk" src="https://vovk.dev/vovk-logo.svg">
|
|
6
|
-
</picture><br>
|
|
7
|
-
<strong>RESTful + RPC = ♥️</strong>
|
|
8
|
-
</p>
|
|
9
|
-
|
|
10
1
|
<p align="center">
|
|
11
|
-
|
|
2
|
+
<a href="https://vovk.dev">
|
|
3
|
+
<picture>
|
|
4
|
+
<source width="300" media="(prefers-color-scheme: dark)" srcset="https://vovk.dev/vovk-logo-white.svg">
|
|
5
|
+
<source width="300" media="(prefers-color-scheme: light)" srcset="https://vovk.dev/vovk-logo.svg">
|
|
6
|
+
<img width="300" alt="vovk" src="https://vovk.dev/vovk-logo.svg">
|
|
7
|
+
</picture>
|
|
8
|
+
</a>
|
|
9
|
+
<br>
|
|
10
|
+
<strong>Back-end for <a href="https://nextjs.org/">Next.js</a></strong>
|
|
12
11
|
</p>
|
|
13
12
|
|
|
14
13
|
---
|
|
15
14
|
|
|
16
15
|
## vovk-cli [](https://www.npmjs.com/package/vovk-cli)
|
|
17
16
|
|
|
18
|
-
The Vovk.ts CLI that
|
|
17
|
+
The Vovk.ts [CLI](https://vovk.dev/cli) that will be used as a devDependency in a Vovk.ts app.
|
|
19
18
|
|
|
20
19
|
```sh
|
|
21
20
|
npm install -D vovk-cli
|
|
22
21
|
```
|
|
23
22
|
|
|
24
|
-
- [vovk dev](https://vovk.dev/
|
|
25
|
-
- [vovk generate](https://vovk.dev/
|
|
26
|
-
- [vovk
|
|
27
|
-
- [vovk
|
|
23
|
+
- [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).
|
|
24
|
+
- [vovk generate](https://vovk.dev/generate) - generates the client based on the schema.
|
|
25
|
+
- [vovk bundle](https://vovk.dev/bundle) - bundles the client with [tsdown](https://tsdown.dev/).
|
|
26
|
+
- [vovk init](https://vovk.dev/init) - initializes Vovk.ts project.
|
|
27
|
+
- [vovk new](https://vovk.dev/new) - generates a new controller, service or a custom module.
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
```sh
|
|
30
|
+
npx vovk-cli --help
|
|
31
|
+
```
|
|
@@ -18,9 +18,9 @@
|
|
|
18
18
|
## <%= controllerSchema.rpcModuleName %>
|
|
19
19
|
<% Object.entries(controllerSchema.handlers).forEach(([handlerName, handlerSchema]) => { %>
|
|
20
20
|
### <%= controllerSchema.rpcModuleName %>.<%= handlerName %>
|
|
21
|
-
<%- handlerSchema.
|
|
21
|
+
<%- handlerSchema.operationObject?.summary ? `> ${handlerSchema.operationObject.summary}` : '' %>
|
|
22
22
|
|
|
23
|
-
<%- handlerSchema.
|
|
23
|
+
<%- handlerSchema.operationObject?.description ? `${handlerSchema.operationObject.description}` : '' %>
|
|
24
24
|
|
|
25
25
|
<% const forceApiRoot = t.segmentMeta[segment.segmentName].forceApiRoot ?? controllerSchema.forceApiRoot; %>
|
|
26
26
|
`<%= handlerSchema.httpMethod %> <%= [...(forceApiRoot ? [forceApiRoot] : [t.apiRoot, segmentName]), controllerSchema.prefix, handlerSchema.path].map((part, i) => i > 0 ? t._.trim(part, '/') : part).filter(Boolean).join('/') %>`
|
package/dist/bundle/index.mjs
CHANGED
|
@@ -1,23 +1,39 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import fs from 'node:fs/promises';
|
|
3
|
-
import { build } from 'tsdown';
|
|
4
3
|
import groupBy from 'lodash/groupBy.js';
|
|
5
4
|
import { generate } from '../generate/generate.mjs';
|
|
6
5
|
import { BuiltInTemplateName } from '../getProjectInfo/getConfig/getTemplateDefs.mjs';
|
|
7
6
|
import chalkHighlightThing from '../utils/chalkHighlightThing.mjs';
|
|
8
7
|
import { locateSegments } from '../locateSegments.mjs';
|
|
8
|
+
/*
|
|
9
|
+
async function tsdownBundle({
|
|
10
|
+
outDirAbsolute,
|
|
11
|
+
tsFullClientOutAbsoluteDirInput,
|
|
12
|
+
}: {
|
|
13
|
+
outDirAbsolute: string;
|
|
14
|
+
tsFullClientOutAbsoluteDirInput: string;
|
|
15
|
+
}) {
|
|
16
|
+
const { build } = await import('tsdown');
|
|
17
|
+
|
|
18
|
+
await build({
|
|
19
|
+
entry: path.join(tsFullClientOutAbsoluteDirInput, './index.ts'),
|
|
20
|
+
dts: true,
|
|
21
|
+
format: ['cjs', 'esm'],
|
|
22
|
+
hash: false,
|
|
23
|
+
fixedExtension: true,
|
|
24
|
+
clean: true,
|
|
25
|
+
...tsdownBuildOptions,
|
|
26
|
+
outDir: outDirAbsolute,
|
|
27
|
+
});
|
|
28
|
+
} */
|
|
9
29
|
export async function bundle({ projectInfo, fullSchema, cliBundleOptions, }) {
|
|
10
30
|
const { config, log, cwd, apiDirAbsolutePath } = projectInfo;
|
|
11
31
|
const locatedSegments = await locateSegments({ dir: apiDirAbsolutePath, config, log });
|
|
12
32
|
const { bundle: bundleConfig } = config;
|
|
13
|
-
const tsFullClientOutAbsoluteDirInput = path.join(cwd, bundleConfig.prebundleOutDir);
|
|
14
|
-
const prebundleOutDir = cliBundleOptions?.prebundleOutDir ?? bundleConfig.prebundleOutDir;
|
|
15
33
|
const keepPrebundleDir = cliBundleOptions?.keepPrebundleDir ?? bundleConfig?.keepPrebundleDir ?? false;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
const outDir = cliBundleOptions?.outDir ?? bundleConfig.tsdownBuildOptions.outDir;
|
|
20
|
-
const tsconfig = cliBundleOptions?.tsconfig ?? bundleConfig.tsdownBuildOptions.tsconfig;
|
|
34
|
+
const prebundleOutDirAbsolute = path.resolve(cwd, cliBundleOptions?.prebundleOutDir ?? bundleConfig.prebundleOutDir);
|
|
35
|
+
const entry = path.join(prebundleOutDirAbsolute, 'index.ts');
|
|
36
|
+
const outDir = cliBundleOptions?.outDir ?? bundleConfig.outDir;
|
|
21
37
|
if (!outDir) {
|
|
22
38
|
throw new Error('No output directory specified for bundling');
|
|
23
39
|
}
|
|
@@ -37,47 +53,19 @@ export async function bundle({ projectInfo, fullSchema, cliBundleOptions, }) {
|
|
|
37
53
|
openapiGetMethodName: cliBundleOptions?.openapiGetMethodName,
|
|
38
54
|
openapiRootUrl: cliBundleOptions?.openapiRootUrl,
|
|
39
55
|
composedFrom: [BuiltInTemplateName.ts],
|
|
40
|
-
composedOut:
|
|
56
|
+
composedOut: prebundleOutDirAbsolute,
|
|
41
57
|
composedOnly: true,
|
|
42
58
|
composedIncludeSegments: cliBundleOptions.includeSegments ?? bundleConfig.includeSegments,
|
|
43
59
|
composedExcludeSegments: cliBundleOptions.excludeSegments ?? bundleConfig.excludeSegments,
|
|
44
60
|
},
|
|
45
61
|
});
|
|
46
|
-
log.debug(
|
|
47
|
-
await build({
|
|
48
|
-
entry: path.join(tsFullClientOutAbsoluteDirInput, './index.ts'),
|
|
49
|
-
dts: true,
|
|
50
|
-
format: ['cjs', 'esm'],
|
|
51
|
-
hash: false,
|
|
52
|
-
fixedExtension: true,
|
|
53
|
-
clean: true,
|
|
54
|
-
...bundleConfig.tsdownBuildOptions,
|
|
62
|
+
log.debug(`Bundling ${chalkHighlightThing(entry)} to ${chalkHighlightThing(outDirAbsolute)}`);
|
|
63
|
+
await bundleConfig.build({
|
|
55
64
|
outDir: outDirAbsolute,
|
|
56
|
-
|
|
65
|
+
prebundleDir: prebundleOutDirAbsolute,
|
|
66
|
+
entry,
|
|
57
67
|
});
|
|
58
68
|
log.debug(`Bundled index.ts to ${chalkHighlightThing(outDirAbsolute)}`);
|
|
59
|
-
log.debug('Bundling schema.ts');
|
|
60
|
-
await build({
|
|
61
|
-
entry: path.join(tsFullClientOutAbsoluteDirInput, './schema.ts'),
|
|
62
|
-
dts: true,
|
|
63
|
-
format: ['cjs'],
|
|
64
|
-
fixedExtension: true,
|
|
65
|
-
outDir: outDirAbsolute,
|
|
66
|
-
clean: false,
|
|
67
|
-
tsconfig,
|
|
68
|
-
});
|
|
69
|
-
log.debug(`Bundled schema.ts to ${chalkHighlightThing(outDirAbsolute)}`);
|
|
70
|
-
log.debug('Bundling openapi.ts');
|
|
71
|
-
await build({
|
|
72
|
-
entry: path.join(tsFullClientOutAbsoluteDirInput, './openapi.ts'),
|
|
73
|
-
dts: true,
|
|
74
|
-
format: ['cjs'],
|
|
75
|
-
fixedExtension: true,
|
|
76
|
-
outDir: outDirAbsolute,
|
|
77
|
-
clean: false,
|
|
78
|
-
tsconfig,
|
|
79
|
-
});
|
|
80
|
-
log.debug(`Bundled openapi.ts to ${chalkHighlightThing(outDirAbsolute)}`);
|
|
81
69
|
const requiresGroup = groupBy(Object.entries(bundleConfig.requires), ([, relativePath]) => relativePath);
|
|
82
70
|
for (const [relativePath, group] of Object.entries(requiresGroup)) {
|
|
83
71
|
await generate({
|
|
@@ -96,11 +84,11 @@ export async function bundle({ projectInfo, fullSchema, cliBundleOptions, }) {
|
|
|
96
84
|
});
|
|
97
85
|
}
|
|
98
86
|
if (!keepPrebundleDir) {
|
|
99
|
-
await fs.rm(
|
|
100
|
-
log.debug(`Deleted temporary TypeScript client output directory: ${chalkHighlightThing(
|
|
87
|
+
await fs.rm(prebundleOutDirAbsolute, { recursive: true, force: true });
|
|
88
|
+
log.debug(`Deleted temporary TypeScript client output directory: ${chalkHighlightThing(prebundleOutDirAbsolute)}`);
|
|
101
89
|
}
|
|
102
90
|
else {
|
|
103
|
-
log.debug(`Temporary TypeScript client output directory not deleted: ${chalkHighlightThing(
|
|
91
|
+
log.debug(`Temporary TypeScript client output directory not deleted because it is marked to keep: ${chalkHighlightThing(prebundleOutDirAbsolute)}`);
|
|
104
92
|
}
|
|
105
93
|
log.info(`Bundled TypeScript client to ${chalkHighlightThing(outDirAbsolute)}`);
|
|
106
94
|
}
|
|
@@ -94,7 +94,7 @@ export async function generate({ isEnsuringClient = false, isBundle = false, pro
|
|
|
94
94
|
.map((segment) => ({ ...segment }))),
|
|
95
95
|
};
|
|
96
96
|
const { config, cwd, log, srcRoot, vovkCliPackage, packageJson: projectPackageJson } = projectInfo;
|
|
97
|
-
Object.entries(config.
|
|
97
|
+
Object.entries(config.outputConfig.segments ?? {})
|
|
98
98
|
.filter(([, segmentConfig]) => segmentConfig.openAPIMixin)
|
|
99
99
|
.forEach(([segmentName, segmentConfig]) => {
|
|
100
100
|
fullSchema.segments = {
|
|
@@ -144,7 +144,7 @@ export async function generate({ isEnsuringClient = false, isBundle = false, pro
|
|
|
144
144
|
: { data: { imports: [] }, content: templateContent };
|
|
145
145
|
const { package: packageJson, readme, origin, samples, reExports, } = resolveGeneratorConfigValues({
|
|
146
146
|
schema: fullSchema,
|
|
147
|
-
configs: [{ origin: cliGenerateOptions?.origin }, templateDef.
|
|
147
|
+
configs: [{ origin: cliGenerateOptions?.origin }, templateDef.outputConfig ?? {}],
|
|
148
148
|
projectPackageJson,
|
|
149
149
|
isBundle,
|
|
150
150
|
segmentName: null,
|
|
@@ -229,7 +229,7 @@ export async function generate({ isEnsuringClient = false, isBundle = false, pro
|
|
|
229
229
|
const results = await Promise.all(segmentNames.map(async (segmentName) => {
|
|
230
230
|
const { package: packageJson, readme, origin, samples, reExports, } = resolveGeneratorConfigValues({
|
|
231
231
|
schema: fullSchema,
|
|
232
|
-
configs: [{ origin: cliGenerateOptions?.origin }, templateDef.
|
|
232
|
+
configs: [{ origin: cliGenerateOptions?.origin }, templateDef.outputConfig ?? {}],
|
|
233
233
|
projectPackageJson,
|
|
234
234
|
segmentName,
|
|
235
235
|
isBundle,
|
|
@@ -73,7 +73,7 @@ export default async function getClientTemplateFiles({ config, cwd, log, configK
|
|
|
73
73
|
}
|
|
74
74
|
def = {
|
|
75
75
|
...def,
|
|
76
|
-
|
|
76
|
+
outputConfig: merge({}, templateDef?.outputConfig, def.outputConfig),
|
|
77
77
|
composedClient: merge(omit(templateDef?.composedClient ?? {}, ['outDir']), def.composedClient),
|
|
78
78
|
segmentedClient: merge(omit(templateDef?.segmentedClient ?? {}, ['outDir']), def.segmentedClient),
|
|
79
79
|
};
|
|
@@ -23,7 +23,7 @@ export default function writeOneClientFile({ cwd, projectInfo, clientTemplateFil
|
|
|
23
23
|
package: PackageJson;
|
|
24
24
|
readme: VovkReadmeConfig;
|
|
25
25
|
samples: VovkSamplesConfig;
|
|
26
|
-
reExports: VovkStrictConfig['
|
|
26
|
+
reExports: VovkStrictConfig['outputConfig']['reExports'];
|
|
27
27
|
isEnsuringClient: boolean;
|
|
28
28
|
outCwdRelativeDir: string;
|
|
29
29
|
templateDef: VovkStrictConfig['clientTemplateDefs'][string];
|
|
@@ -85,8 +85,8 @@ locatedSegments, isNodeNextResolution, hasMixins, isVovkProject, vovkCliPackage,
|
|
|
85
85
|
? path.relative(path.resolve(cwd, outCwdRelativeDir, typeof segmentName === 'string' ? segmentName || ROOT_SEGMENT_FILE_NAME : '.'), path.resolve(cwd, routeFilePath))
|
|
86
86
|
: null;
|
|
87
87
|
const segmentConfig = {
|
|
88
|
-
...config.
|
|
89
|
-
// ...templateDef.
|
|
88
|
+
...config.outputConfig.segments?.[sName],
|
|
89
|
+
// ...templateDef.outputConfig?.segments?.[sName],
|
|
90
90
|
};
|
|
91
91
|
const { origin: segmentConfigOrigin, rootEntry: segmentConfigRootEntry, segmentNameOverride } = segmentConfig;
|
|
92
92
|
return [
|
|
@@ -149,9 +149,9 @@ export default function getTemplateDefs(userTemplateDefs = {}) {
|
|
|
149
149
|
...builtIn.segmentedClient,
|
|
150
150
|
...templateDef.segmentedClient,
|
|
151
151
|
},
|
|
152
|
-
|
|
153
|
-
...builtIn.
|
|
154
|
-
...templateDef.
|
|
152
|
+
outputConfig: {
|
|
153
|
+
...builtIn.outputConfig,
|
|
154
|
+
...templateDef.outputConfig,
|
|
155
155
|
},
|
|
156
156
|
// 'requires' and other props will be overridden
|
|
157
157
|
};
|
|
@@ -48,10 +48,13 @@ export default function getConfig({ configPath, cwd, logLevel, }: {
|
|
|
48
48
|
requires?: Record<string, string>;
|
|
49
49
|
prebundleOutDir?: string;
|
|
50
50
|
keepPrebundleDir?: boolean;
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
51
|
+
outDir?: string;
|
|
52
|
+
build: (options: {
|
|
53
|
+
outDir: string;
|
|
54
|
+
prebundleDir: string;
|
|
55
|
+
entry: string;
|
|
56
|
+
}) => Promise<void>;
|
|
57
|
+
outputConfig?: import("vovk").VovkOutputConfig<{
|
|
55
58
|
fetcher?: string | [string, string] | [string];
|
|
56
59
|
validateOnClient?: string | [string, string] | [string] | null;
|
|
57
60
|
createRPC?: string | [string, string] | [string];
|
|
@@ -70,7 +73,7 @@ export default function getConfig({ configPath, cwd, logLevel, }: {
|
|
|
70
73
|
controller?: string;
|
|
71
74
|
[key: string]: string | undefined;
|
|
72
75
|
};
|
|
73
|
-
|
|
76
|
+
outputConfig?: import("vovk").VovkOutputConfig<{
|
|
74
77
|
fetcher?: string | [string, string] | [string];
|
|
75
78
|
validateOnClient?: string | [string, string] | [string] | null;
|
|
76
79
|
createRPC?: string | [string, string] | [string];
|
|
@@ -38,16 +38,17 @@ export default async function getConfig({ configPath, cwd, logLevel, }) {
|
|
|
38
38
|
bundle: {
|
|
39
39
|
prebundleOutDir: conf.bundle?.prebundleOutDir ?? 'tmp_prebundle',
|
|
40
40
|
keepPrebundleDir: conf.bundle?.keepPrebundleDir ?? false,
|
|
41
|
+
outDir: conf.bundle?.outDir ?? 'dist',
|
|
41
42
|
requires: {
|
|
42
43
|
[BuiltInTemplateName.readme]: '.',
|
|
43
44
|
[BuiltInTemplateName.packageJson]: '.',
|
|
44
45
|
},
|
|
45
|
-
|
|
46
|
+
outputConfig: {},
|
|
47
|
+
build: conf.bundle?.build ??
|
|
48
|
+
(() => {
|
|
49
|
+
throw new Error('No bundle.build function specified');
|
|
50
|
+
}),
|
|
46
51
|
...conf.bundle,
|
|
47
|
-
tsdownBuildOptions: {
|
|
48
|
-
outDir: conf.bundle?.tsdownBuildOptions?.outDir ?? 'dist',
|
|
49
|
-
...conf.bundle?.tsdownBuildOptions,
|
|
50
|
-
},
|
|
51
52
|
},
|
|
52
53
|
modulesDir: conf.modulesDir ?? path.join(srcRoot ?? '.', 'modules'),
|
|
53
54
|
schemaOutDir: env.VOVK_SCHEMA_OUT_DIR ?? conf.schemaOutDir ?? './.vovk-schema',
|
|
@@ -61,10 +62,10 @@ export default async function getConfig({ configPath, cwd, logLevel, }) {
|
|
|
61
62
|
...conf.moduleTemplates,
|
|
62
63
|
},
|
|
63
64
|
libs: conf.libs ?? {},
|
|
64
|
-
|
|
65
|
-
...conf.
|
|
66
|
-
origin: (env.VOVK_ORIGIN ?? conf?.
|
|
67
|
-
segments: Object.fromEntries(await Promise.all(Object.entries(conf.
|
|
65
|
+
outputConfig: {
|
|
66
|
+
...conf.outputConfig,
|
|
67
|
+
origin: (env.VOVK_ORIGIN ?? conf?.outputConfig?.origin ?? '').replace(/\/$/, ''), // Remove trailing slash
|
|
68
|
+
segments: Object.fromEntries(await Promise.all(Object.entries(conf.outputConfig?.segments ?? {}).map(async ([key, value]) => [
|
|
68
69
|
key,
|
|
69
70
|
{
|
|
70
71
|
...value,
|
|
@@ -10,12 +10,12 @@ export default function getMetaSchema({ config, useEmitConfig }) {
|
|
|
10
10
|
? (config
|
|
11
11
|
? pick({
|
|
12
12
|
...config,
|
|
13
|
-
|
|
13
|
+
outputConfig: config.outputConfig
|
|
14
14
|
? {
|
|
15
|
-
...config.
|
|
15
|
+
...config.outputConfig,
|
|
16
16
|
// TODO: Dirty fix! Need to think of a better way to avoid emission of mixins.
|
|
17
|
-
segments: config.
|
|
18
|
-
? mapValues(config.
|
|
17
|
+
segments: config.outputConfig.segments
|
|
18
|
+
? mapValues(config.outputConfig.segments, (segment) => omit(segment, ['openAPIMixin']))
|
|
19
19
|
: undefined,
|
|
20
20
|
}
|
|
21
21
|
: undefined,
|
|
@@ -18,7 +18,7 @@ export default async function getProjectInfo({ port: givenPort, cwd = process.cw
|
|
|
18
18
|
if (srcRootRequired && !srcRoot) {
|
|
19
19
|
throw new Error(`Could not find app router directory at ${cwd}. Check Next.js docs for more info.`);
|
|
20
20
|
}
|
|
21
|
-
const apiRoot = `${config.
|
|
21
|
+
const apiRoot = `${config.outputConfig.origin ?? ''}/${config.rootEntry}`;
|
|
22
22
|
const apiDirAbsolutePath = srcRoot ? path.resolve(cwd, srcRoot, 'app', config.rootEntry) : null;
|
|
23
23
|
if (configAbsolutePaths.length > 1) {
|
|
24
24
|
log.warn(`Multiple config files found. Using the first one: ${configAbsolutePaths[0]}`);
|
package/dist/index.mjs
CHANGED
|
@@ -126,7 +126,6 @@ program
|
|
|
126
126
|
.option('--schema, --schema-path <path>', 'path to schema folder (default: .vovk-schema)')
|
|
127
127
|
.option('--config, --config-path <config>', 'path to config file')
|
|
128
128
|
.option('--origin <url>', 'set the origin URL for the generated client')
|
|
129
|
-
.option('--tsconfig <path>', 'path to tsconfig.json for bundling by tsdown')
|
|
130
129
|
.option('--openapi, --openapi-spec <openapi_path_or_urls...>', 'use OpenAPI schema instead of Vovk schema')
|
|
131
130
|
.option('--openapi-get-module-name <names...>', 'module names corresponding to the index of --openapi option')
|
|
132
131
|
.option('--openapi-get-method-name <names...>', 'method names corresponding to the index of --openapi option')
|
|
@@ -37,9 +37,9 @@ export default async function createConfig({ root, log, options: { validationLib
|
|
|
37
37
|
},
|
|
38
38
|
}[validationLibrary ?? 'type'],
|
|
39
39
|
};
|
|
40
|
-
config.
|
|
41
|
-
config.
|
|
42
|
-
config.
|
|
40
|
+
config.outputConfig ??= {};
|
|
41
|
+
config.outputConfig.imports ??= {};
|
|
42
|
+
config.outputConfig.imports.validateOnClient =
|
|
43
43
|
validationLibrary === 'class-validator' ? 'vovk-dto/validateOnClient' : 'vovk-ajv';
|
|
44
44
|
if (validationLibrary && !moduleTemplates) {
|
|
45
45
|
try {
|
package/dist/types.d.mts
CHANGED
|
@@ -40,12 +40,12 @@ export interface GenerateOptions {
|
|
|
40
40
|
logLevel?: LogLevelNames;
|
|
41
41
|
}
|
|
42
42
|
export interface BundleOptions extends Partial<Pick<VovkStrictConfig['bundle'], 'prebundleOutDir' | 'keepPrebundleDir' | 'includeSegments' | 'excludeSegments'>> {
|
|
43
|
+
bundler?: 'tsdown' | 'ncc';
|
|
43
44
|
configPath?: string;
|
|
44
45
|
schemaPath?: string;
|
|
45
46
|
schema?: string;
|
|
46
47
|
outDir?: string;
|
|
47
48
|
origin?: string;
|
|
48
|
-
tsconfig?: string;
|
|
49
49
|
openapiSpec?: string[];
|
|
50
50
|
openapiGetModuleName?: string[];
|
|
51
51
|
openapiGetMethodName?: string[];
|
|
@@ -8,7 +8,7 @@ export type GetOpenAPINameFn = (config: {
|
|
|
8
8
|
openAPIObject: OpenAPIObject;
|
|
9
9
|
}) => string;
|
|
10
10
|
export declare function normalizeOpenAPIMixin({ mixinModule, log, cwd, }: {
|
|
11
|
-
mixinModule: NonNullable<NonNullable<NonNullable<NonNullable<VovkConfig['
|
|
11
|
+
mixinModule: NonNullable<NonNullable<NonNullable<NonNullable<VovkConfig['outputConfig']>['segments']>[string]>['openAPIMixin']>;
|
|
12
12
|
log: ProjectInfo['log'];
|
|
13
13
|
cwd?: string;
|
|
14
|
-
}): Promise<NonNullable<NonNullable<NonNullable<NonNullable<VovkStrictConfig['
|
|
14
|
+
}): Promise<NonNullable<NonNullable<NonNullable<NonNullable<VovkStrictConfig['outputConfig']>['segments']>[string]>['openAPIMixin']>>;
|
|
@@ -23,13 +23,11 @@ export default class <%= vars.ModuleName %> {
|
|
|
23
23
|
})
|
|
24
24
|
@get()
|
|
25
25
|
static get<%= t.TheThings %> = withArk({
|
|
26
|
-
|
|
27
|
-
handle(req) {
|
|
28
|
-
const search = req.nextUrl.searchParams.get('search');
|
|
26
|
+
handle() {
|
|
29
27
|
<% if(t.withService) { %>
|
|
30
|
-
return <%= vars.ServiceName %>.get<%= t.TheThings %>(
|
|
28
|
+
return <%= vars.ServiceName %>.get<%= t.TheThings %>();
|
|
31
29
|
<% } else { %>
|
|
32
|
-
return {
|
|
30
|
+
return { message: 'TODO: get <%= t.theThings %>' };
|
|
33
31
|
<% } %>
|
|
34
32
|
}
|
|
35
33
|
});
|
|
@@ -39,30 +37,42 @@ export default class <%= vars.ModuleName %> {
|
|
|
39
37
|
})
|
|
40
38
|
@put('{id}')
|
|
41
39
|
static update<%= t.TheThing %> = withArk({
|
|
42
|
-
body: type({
|
|
43
|
-
foo: type('"bar" | "baz"'),
|
|
44
|
-
}),
|
|
45
|
-
query: type({ q: type('string') }),
|
|
40
|
+
body: type({ todo: type('true') }),
|
|
46
41
|
params: type({ id: type('string') }),
|
|
47
42
|
async handle(req, params) {
|
|
48
43
|
const { id } = params;
|
|
49
44
|
const body = await req.json();
|
|
50
|
-
const q = req.nextUrl.searchParams.get('q');
|
|
51
45
|
<% if(t.withService) { %>
|
|
52
|
-
return <%= vars.ServiceName %>.update<%= t.TheThing %>(id,
|
|
46
|
+
return <%= vars.ServiceName %>.update<%= t.TheThing %>(id, body);
|
|
53
47
|
<% } else { %>
|
|
54
|
-
return { id, body
|
|
48
|
+
return { message: `TODO: update <%= t.theThing %>`, id, body };
|
|
55
49
|
<% } %>
|
|
56
50
|
}
|
|
57
51
|
});
|
|
58
52
|
|
|
59
53
|
@post()
|
|
60
|
-
static create<%= t.TheThing %> = (
|
|
61
|
-
|
|
62
|
-
|
|
54
|
+
static create<%= t.TheThing %> = withArk({
|
|
55
|
+
body: type({ todo: type('true') }),
|
|
56
|
+
async handle(req) {
|
|
57
|
+
const body = await req.json();
|
|
58
|
+
<% if(t.withService) { %>
|
|
59
|
+
return <%= vars.ServiceName %>.create<%= t.TheThing %>(body);
|
|
60
|
+
<% } else { %>
|
|
61
|
+
return { message: `TODO: create <%= t.theThing %>`, body };
|
|
62
|
+
<% } %>
|
|
63
|
+
}
|
|
64
|
+
});
|
|
63
65
|
|
|
64
|
-
@del('
|
|
65
|
-
static delete<%= t.TheThing %> = (
|
|
66
|
-
|
|
67
|
-
|
|
66
|
+
@del('{id}')
|
|
67
|
+
static delete<%= t.TheThing %> = withArk({
|
|
68
|
+
params: type({ id: type('string') }),
|
|
69
|
+
handle(_req, params) {
|
|
70
|
+
const { id } = params;
|
|
71
|
+
<% if(t.withService) { %>
|
|
72
|
+
return <%= vars.ServiceName %>.delete<%= t.TheThing %>(id);
|
|
73
|
+
<% } else { %>
|
|
74
|
+
return { message: `TODO: delete <%= t.theThing %>`, id };
|
|
75
|
+
<% } %>
|
|
76
|
+
}
|
|
77
|
+
});
|
|
68
78
|
}
|
|
@@ -20,12 +20,11 @@ export default class <%= vars.ControllerName %> {
|
|
|
20
20
|
summary: 'Get <%= t.TheThings %>',
|
|
21
21
|
})
|
|
22
22
|
@get()
|
|
23
|
-
static get<%= t.TheThings %> =
|
|
24
|
-
const search = req.nextUrl.searchParams.get('search');
|
|
23
|
+
static get<%= t.TheThings %> = () => {
|
|
25
24
|
<% if(t.withService) { %>
|
|
26
|
-
return <%= vars.ServiceName %>.get<%= t.TheThings %>(
|
|
25
|
+
return <%= vars.ServiceName %>.get<%= t.TheThings %>();
|
|
27
26
|
<% } else { %>
|
|
28
|
-
return {
|
|
27
|
+
return { message: 'TODO: get <%= t.theThings %>' };
|
|
29
28
|
<% } %>
|
|
30
29
|
}
|
|
31
30
|
|
|
@@ -33,24 +32,33 @@ export default class <%= vars.ControllerName %> {
|
|
|
33
32
|
summary: 'Update <%= t.TheThing %>',
|
|
34
33
|
})
|
|
35
34
|
@put('{id}')
|
|
36
|
-
static update<%= t.TheThing %> = async (req: VovkRequest<{
|
|
35
|
+
static update<%= t.TheThing %> = async (req: VovkRequest<{ todo: true }>, params: { id: string }) => {
|
|
37
36
|
const { id } = params;
|
|
38
37
|
const body = await req.json();
|
|
39
|
-
const q = req.nextUrl.searchParams.get('q');
|
|
40
38
|
<% if(t.withService) { %>
|
|
41
|
-
return <%= vars.ServiceName %>.update<%= t.TheThing %>(id,
|
|
39
|
+
return <%= vars.ServiceName %>.update<%= t.TheThing %>(id, body);
|
|
42
40
|
<% } else { %>
|
|
43
|
-
return { id, body
|
|
41
|
+
return { message: `TODO: update <%= t.theThing %>`, id, body };
|
|
44
42
|
<% } %>
|
|
45
43
|
};
|
|
46
44
|
|
|
47
45
|
@post()
|
|
48
|
-
static create<%= t.TheThing %> = () => {
|
|
49
|
-
|
|
46
|
+
static create<%= t.TheThing %> = async (req: VovkRequest<{ todo: true }>) => {
|
|
47
|
+
const body = await req.json();
|
|
48
|
+
<% if(t.withService) { %>
|
|
49
|
+
return <%= vars.ServiceName %>.create<%= t.TheThing %>(body);
|
|
50
|
+
<% } else { %>
|
|
51
|
+
return { message: `TODO: create <%= t.theThing %>`, body };
|
|
52
|
+
<% } %>
|
|
50
53
|
};
|
|
51
54
|
|
|
52
|
-
@del('
|
|
53
|
-
static delete<%= t.TheThing %> = () => {
|
|
54
|
-
|
|
55
|
+
@del('{id}')
|
|
56
|
+
static delete<%= t.TheThing %> = (_req: VovkRequest<unknown>, params: { id: string }) => {
|
|
57
|
+
const { id } = params;
|
|
58
|
+
<% if(t.withService) { %>
|
|
59
|
+
return <%= vars.ServiceName %>.delete<%= t.TheThing %>(id);
|
|
60
|
+
<% } else { %>
|
|
61
|
+
return { message: `TODO: delete <%= t.theThing %>`, id };
|
|
62
|
+
<% } %>
|
|
55
63
|
};
|
|
56
64
|
}
|
|
@@ -8,21 +8,30 @@ fileName: <%= vars.ServiceName + '.ts' %>
|
|
|
8
8
|
sourceName: <%= vars.ServiceName %>
|
|
9
9
|
---
|
|
10
10
|
|
|
11
|
-
import type { VovkBody,
|
|
11
|
+
import type { VovkBody, VovkParams } from 'vovk';
|
|
12
12
|
import type <%= vars.ControllerName %> from './<%= vars.ControllerName %><%= t.nodeNextResolutionExt.ts %>';
|
|
13
13
|
|
|
14
14
|
export default class <%= vars.ServiceName %> {
|
|
15
|
-
static get<%= t.TheThings %> = (
|
|
16
|
-
return {
|
|
15
|
+
static get<%= t.TheThings %> = () => {
|
|
16
|
+
return { message: 'TODO: get <%= t.theThings %>' };
|
|
17
17
|
};
|
|
18
18
|
|
|
19
19
|
static update<%= t.TheThing %> = (
|
|
20
|
-
id:
|
|
21
|
-
q: VovkQuery<typeof <%= vars.ControllerName %>.update<%= t.TheThing %>>['q'],
|
|
20
|
+
id: VovkParams<typeof <%= vars.ControllerName %>.update<%= t.TheThing %>>['id'],
|
|
22
21
|
body: VovkBody<typeof <%= vars.ControllerName %>.update<%= t.TheThing %>>
|
|
23
22
|
) => {
|
|
24
|
-
return { id,
|
|
23
|
+
return { message: `TODO: update <%= t.theThing %>`, id, body };
|
|
25
24
|
};
|
|
26
25
|
|
|
27
|
-
|
|
26
|
+
static create<%= t.TheThing %> = (
|
|
27
|
+
body: VovkBody<typeof <%= vars.ControllerName %>.create<%= t.TheThing %>>
|
|
28
|
+
) => {
|
|
29
|
+
return { message: `TODO: create <%= t.theThing %>`, body };
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
static delete<%= t.TheThing %> = (
|
|
33
|
+
id: VovkParams<typeof <%= vars.ControllerName %>.delete<%= t.TheThing %>>['id']
|
|
34
|
+
) => {
|
|
35
|
+
return { message: `TODO: delete <%= t.theThing %>`, id };
|
|
36
|
+
};
|
|
28
37
|
}
|
|
@@ -23,13 +23,11 @@ export default class <%= vars.ModuleName %> {
|
|
|
23
23
|
})
|
|
24
24
|
@get()
|
|
25
25
|
static get<%= t.TheThings %> = withValibot({
|
|
26
|
-
|
|
27
|
-
handle(req) {
|
|
28
|
-
const search = req.nextUrl.searchParams.get('search');
|
|
26
|
+
handle() {
|
|
29
27
|
<% if(t.withService) { %>
|
|
30
|
-
return <%= vars.ServiceName %>.get<%= t.TheThings %>(
|
|
28
|
+
return <%= vars.ServiceName %>.get<%= t.TheThings %>();
|
|
31
29
|
<% } else { %>
|
|
32
|
-
return {
|
|
30
|
+
return { message: 'TODO: get <%= t.theThings %>' };
|
|
33
31
|
<% } %>
|
|
34
32
|
}
|
|
35
33
|
});
|
|
@@ -39,30 +37,42 @@ export default class <%= vars.ModuleName %> {
|
|
|
39
37
|
})
|
|
40
38
|
@put('{id}')
|
|
41
39
|
static update<%= t.TheThing %> = withValibot({
|
|
42
|
-
body: v.object({
|
|
43
|
-
foo: v.union([v.literal('bar'), v.literal('baz')]),
|
|
44
|
-
}),
|
|
45
|
-
query: v.object({ q: v.string() }),
|
|
40
|
+
body: v.object({ todo: v.literal(true) }),
|
|
46
41
|
params: v.object({ id: v.string() }),
|
|
47
42
|
async handle(req, params) {
|
|
48
43
|
const { id } = params;
|
|
49
44
|
const body = await req.json();
|
|
50
|
-
const q = req.nextUrl.searchParams.get('q');
|
|
51
45
|
<% if(t.withService) { %>
|
|
52
|
-
return <%= vars.ServiceName %>.update<%= t.TheThing %>(id,
|
|
46
|
+
return <%= vars.ServiceName %>.update<%= t.TheThing %>(id, body);
|
|
53
47
|
<% } else { %>
|
|
54
|
-
return { id, body
|
|
48
|
+
return { message: `TODO: update <%= t.theThing %>`, id, body };
|
|
55
49
|
<% } %>
|
|
56
50
|
}
|
|
57
51
|
});
|
|
58
52
|
|
|
59
53
|
@post()
|
|
60
|
-
static create<%= t.TheThing %> = (
|
|
61
|
-
|
|
62
|
-
|
|
54
|
+
static create<%= t.TheThing %> = withValibot({
|
|
55
|
+
body: v.object({ todo: v.literal(true) }),
|
|
56
|
+
async handle(req) {
|
|
57
|
+
const body = await req.json();
|
|
58
|
+
<% if(t.withService) { %>
|
|
59
|
+
return <%= vars.ServiceName %>.create<%= t.TheThing %>(body);
|
|
60
|
+
<% } else { %>
|
|
61
|
+
return { message: `TODO: create <%= t.theThing %>`, body };
|
|
62
|
+
<% } %>
|
|
63
|
+
}
|
|
64
|
+
});
|
|
63
65
|
|
|
64
|
-
@del('
|
|
65
|
-
static delete<%= t.TheThing %> = (
|
|
66
|
-
|
|
67
|
-
|
|
66
|
+
@del('{id}')
|
|
67
|
+
static delete<%= t.TheThing %> = withValibot({
|
|
68
|
+
params: v.object({ id: v.string() }),
|
|
69
|
+
handle(_req, params) {
|
|
70
|
+
const { id } = params;
|
|
71
|
+
<% if(t.withService) { %>
|
|
72
|
+
return <%= vars.ServiceName %>.delete<%= t.TheThing %>(id);
|
|
73
|
+
<% } else { %>
|
|
74
|
+
return { message: `TODO: delete <%= t.theThing %>`, id };
|
|
75
|
+
<% } %>
|
|
76
|
+
}
|
|
77
|
+
});
|
|
68
78
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vovk-cli",
|
|
3
|
-
"version": "0.0.1-draft.
|
|
3
|
+
"version": "0.0.1-draft.382",
|
|
4
4
|
"bin": {
|
|
5
5
|
"vovk": "./dist/index.mjs"
|
|
6
6
|
},
|
|
@@ -35,14 +35,14 @@
|
|
|
35
35
|
},
|
|
36
36
|
"homepage": "https://vovk.dev",
|
|
37
37
|
"peerDependencies": {
|
|
38
|
-
"vovk": "^3.0.0-draft.
|
|
39
|
-
"vovk-ajv": "^0.0.0-draft.
|
|
40
|
-
"vovk-client": "^0.0.4-draft.
|
|
41
|
-
"vovk-python": "^0.0.1-draft.
|
|
42
|
-
"vovk-rust": "^0.0.1-draft.
|
|
38
|
+
"vovk": "^3.0.0-draft.464",
|
|
39
|
+
"vovk-ajv": "^0.0.0-draft.110",
|
|
40
|
+
"vovk-client": "^0.0.4-draft.137",
|
|
41
|
+
"vovk-python": "^0.0.1-draft.79",
|
|
42
|
+
"vovk-rust": "^0.0.1-draft.65"
|
|
43
43
|
},
|
|
44
44
|
"optionalDependencies": {
|
|
45
|
-
"@rolldown/binding-linux-x64-gnu": "1.0.0-beta.
|
|
45
|
+
"@rolldown/binding-linux-x64-gnu": "1.0.0-beta.44"
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
48
|
"@iarna/toml": "^2.2.5",
|
|
@@ -68,7 +68,6 @@
|
|
|
68
68
|
"prettier": "^3.6.2",
|
|
69
69
|
"tar-stream": "^3.1.7",
|
|
70
70
|
"ts-morph": "^27.0.0",
|
|
71
|
-
"tsdown": "^0.15.7",
|
|
72
71
|
"type-fest": "^5.0.1",
|
|
73
72
|
"undici": "^7.16.0",
|
|
74
73
|
"yaml": "^2.8.1"
|
|
@@ -84,6 +83,7 @@
|
|
|
84
83
|
"create-next-app": "^15.5.4",
|
|
85
84
|
"http-server": "^14.1.1",
|
|
86
85
|
"node-pty": "^1.0.0",
|
|
86
|
+
"tsdown": "^0.15.9",
|
|
87
87
|
"zod": "^4.1.11"
|
|
88
88
|
}
|
|
89
89
|
}
|