vovk-cli 0.0.1-draft.333 → 0.0.1-draft.334
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/client-templates/schemaCjs/schema.cjs.ejs +1 -4
- package/client-templates/schemaTs/schema.ts.ejs +1 -5
- package/dist/bundle/index.mjs +8 -4
- package/dist/dev/index.d.mts +1 -1
- package/dist/dev/index.mjs +8 -5
- package/dist/getProjectInfo/getConfig/index.d.mts +6 -4
- package/dist/getProjectInfo/getConfig/index.mjs +3 -3
- package/dist/getProjectInfo/index.d.mts +4 -2
- package/dist/getProjectInfo/index.mjs +4 -1
- package/dist/index.mjs +22 -5
- package/dist/init/createConfig.mjs +26 -4
- package/dist/init/createStandardSchemaValidatorFile.d.mts +4 -0
- package/dist/init/createStandardSchemaValidatorFile.mjs +38 -0
- package/dist/init/index.mjs +56 -21
- package/dist/init/updateNPMScripts.d.mts +0 -1
- package/dist/init/updateNPMScripts.mjs +1 -5
- package/dist/initProgram.mjs +1 -1
- package/dist/new/index.d.mts +2 -1
- package/dist/new/index.mjs +3 -2
- package/dist/new/newModule.d.mts +3 -1
- package/dist/new/newModule.mjs +2 -3
- package/dist/new/newSegment.d.mts +3 -1
- package/dist/new/newSegment.mjs +2 -3
- package/dist/types.d.mts +8 -3
- package/module-templates/arktype/controller.ts.ejs +68 -0
- package/module-templates/valibot/controller.ts.ejs +68 -0
- package/package.json +2 -2
- /package/module-templates/{controller.ts.ejs → type/controller.ts.ejs} +0 -0
- /package/module-templates/{service.ts.ejs → type/service.ts.ejs} +0 -0
|
@@ -16,10 +16,7 @@ const schema = {
|
|
|
16
16
|
$schema: '<%- t.VovkSchemaIdEnum.SCHEMA %>',
|
|
17
17
|
segments,
|
|
18
18
|
meta: {
|
|
19
|
-
|
|
20
|
-
<% if(t.isVovkProject) { %>
|
|
21
|
-
...meta
|
|
22
|
-
<% } %>
|
|
19
|
+
<% if(t.isVovkProject) { %>...meta<% } %>
|
|
23
20
|
}
|
|
24
21
|
};
|
|
25
22
|
|
|
@@ -22,11 +22,7 @@ export const schema = {
|
|
|
22
22
|
$schema: '<%- t.VovkSchemaIdEnum.SCHEMA %>',
|
|
23
23
|
segments,
|
|
24
24
|
meta: {
|
|
25
|
-
|
|
26
|
-
apiRoot: '<%= t.apiRoot %>', // for debugging purposes
|
|
27
|
-
<% if(t.isVovkProject) { %>
|
|
28
|
-
...meta,
|
|
29
|
-
<% } %>
|
|
25
|
+
<% if(t.isVovkProject) { %>...meta,<% } %>
|
|
30
26
|
}
|
|
31
27
|
};
|
|
32
28
|
|
package/dist/bundle/index.mjs
CHANGED
|
@@ -17,9 +17,11 @@ export async function bundle({ projectInfo, fullSchema, cliBundleOptions, }) {
|
|
|
17
17
|
throw new Error('No output directory specified for composed client');
|
|
18
18
|
}
|
|
19
19
|
const outDir = cliBundleOptions?.outDir ?? bundleConfig.tsdownBuildOptions.outDir;
|
|
20
|
+
const tsconfig = cliBundleOptions?.tsconfig ?? bundleConfig.tsdownBuildOptions.tsconfig;
|
|
20
21
|
if (!outDir) {
|
|
21
22
|
throw new Error('No output directory specified for bundling');
|
|
22
23
|
}
|
|
24
|
+
const outDirAbsolute = path.resolve(cwd, outDir);
|
|
23
25
|
await generate({
|
|
24
26
|
isEnsuringClient: false,
|
|
25
27
|
isBundle: true,
|
|
@@ -47,18 +49,20 @@ export async function bundle({ projectInfo, fullSchema, cliBundleOptions, }) {
|
|
|
47
49
|
dts: true,
|
|
48
50
|
format: ['cjs', 'esm'],
|
|
49
51
|
fixedExtension: true,
|
|
50
|
-
|
|
52
|
+
clean: true,
|
|
51
53
|
...bundleConfig.tsdownBuildOptions,
|
|
54
|
+
outDir: outDirAbsolute,
|
|
55
|
+
tsconfig,
|
|
52
56
|
});
|
|
53
|
-
const outDirAbsolute = path.resolve(cwd, outDir);
|
|
54
57
|
log.debug(`Bundled index.ts to ${chalkHighlightThing(outDirAbsolute)}`);
|
|
55
58
|
await build({
|
|
56
59
|
entry: path.join(tsFullClientOutAbsoluteDirInput, './schema.ts'),
|
|
57
60
|
dts: true,
|
|
58
61
|
format: ['cjs'],
|
|
59
62
|
fixedExtension: true,
|
|
60
|
-
outDir,
|
|
63
|
+
outDir: outDirAbsolute,
|
|
61
64
|
clean: false,
|
|
65
|
+
tsconfig,
|
|
62
66
|
});
|
|
63
67
|
log.debug(`Bundled schema.ts to ${chalkHighlightThing(outDirAbsolute)}`);
|
|
64
68
|
const requiresGroup = groupBy(Object.entries(bundleConfig.requires), ([, relativePath]) => relativePath);
|
|
@@ -74,7 +78,7 @@ export async function bundle({ projectInfo, fullSchema, cliBundleOptions, }) {
|
|
|
74
78
|
cliGenerateOptions: {
|
|
75
79
|
origin: cliBundleOptions?.origin ?? bundleConfig.origin,
|
|
76
80
|
composedFrom: group.map(([templateName]) => templateName),
|
|
77
|
-
composedOut: path.resolve(
|
|
81
|
+
composedOut: path.resolve(outDirAbsolute, relativePath),
|
|
78
82
|
composedOnly: true,
|
|
79
83
|
},
|
|
80
84
|
});
|
package/dist/dev/index.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { DevOptions } from '../types.mjs';
|
|
2
2
|
export declare class VovkDev {
|
|
3
3
|
#private;
|
|
4
|
-
constructor({ schemaOut, devHttps }: Pick<DevOptions, 'schemaOut' | 'devHttps'>);
|
|
4
|
+
constructor({ schemaOut, devHttps, logLevel }: Pick<DevOptions, 'schemaOut' | 'devHttps' | 'logLevel'>);
|
|
5
5
|
start({ exit }: {
|
|
6
6
|
exit: boolean;
|
|
7
7
|
}): Promise<void>;
|
package/dist/dev/index.mjs
CHANGED
|
@@ -38,9 +38,11 @@ export class VovkDev {
|
|
|
38
38
|
#onFirstTimeGenerate = null;
|
|
39
39
|
#schemaOut = null;
|
|
40
40
|
#devHttps;
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
this.#
|
|
41
|
+
#logLevel;
|
|
42
|
+
constructor({ schemaOut, devHttps, logLevel }) {
|
|
43
|
+
this.#schemaOut = schemaOut || null;
|
|
44
|
+
this.#devHttps = devHttps || false;
|
|
45
|
+
this.#logLevel = logLevel || 'info';
|
|
44
46
|
}
|
|
45
47
|
#watchSegments = (callback) => {
|
|
46
48
|
const segmentReg = /\/?\[\[\.\.\.[a-zA-Z-_]+\]\]\/route.ts$/;
|
|
@@ -165,7 +167,7 @@ export class VovkDev {
|
|
|
165
167
|
let isInitial = true;
|
|
166
168
|
let isReady = false;
|
|
167
169
|
const handle = debounce(async () => {
|
|
168
|
-
this.#projectInfo = await getProjectInfo();
|
|
170
|
+
this.#projectInfo = await getProjectInfo({ logLevel: this.#logLevel });
|
|
169
171
|
const { config, apiDirAbsolutePath } = this.#projectInfo;
|
|
170
172
|
this.#segments = await locateSegments({ dir: apiDirAbsolutePath, config, log });
|
|
171
173
|
await this.#modulesWatcher?.close();
|
|
@@ -323,7 +325,7 @@ export class VovkDev {
|
|
|
323
325
|
}
|
|
324
326
|
async start({ exit }) {
|
|
325
327
|
const now = Date.now();
|
|
326
|
-
this.#projectInfo = await getProjectInfo();
|
|
328
|
+
this.#projectInfo = await getProjectInfo({ logLevel: this.#logLevel });
|
|
327
329
|
const { log, config, cwd, apiDirAbsolutePath } = this.#projectInfo;
|
|
328
330
|
this.#segments = await locateSegments({ dir: apiDirAbsolutePath, config, log });
|
|
329
331
|
log.info('Starting...');
|
|
@@ -392,6 +394,7 @@ if (env.__VOVK_START_WATCHER_IN_STANDALONE_MODE__ === 'true') {
|
|
|
392
394
|
void new VovkDev({
|
|
393
395
|
schemaOut: env.__VOVK_SCHEMA_OUT_FLAG__ || undefined,
|
|
394
396
|
devHttps: env.__VOVK_DEV_HTTPS_FLAG__ === 'true',
|
|
397
|
+
logLevel: env.__VOVK_LOG_LEVEL__,
|
|
395
398
|
}).start({
|
|
396
399
|
exit: env.__VOVK_EXIT__ === 'true',
|
|
397
400
|
});
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { VovkSchemaIdEnum, type VovkStrictConfig } from 'vovk';
|
|
2
|
-
|
|
2
|
+
import type { LogLevelNames } from 'loglevel';
|
|
3
|
+
export default function getConfig({ configPath, cwd, logLevel, }: {
|
|
3
4
|
configPath?: string;
|
|
4
5
|
cwd: string;
|
|
6
|
+
logLevel?: LogLevelNames;
|
|
5
7
|
}): Promise<{
|
|
6
8
|
config: VovkStrictConfig;
|
|
7
9
|
srcRoot: string | null;
|
|
@@ -71,7 +73,7 @@ export default function getConfig({ configPath, cwd }: {
|
|
|
71
73
|
excludeSegments?: string[];
|
|
72
74
|
includeSegments?: never;
|
|
73
75
|
});
|
|
74
|
-
clientTemplateDefs?: Record<string, import("vovk/
|
|
76
|
+
clientTemplateDefs?: Record<string, import("vovk/types").ClientTemplateDef>;
|
|
75
77
|
imports?: {
|
|
76
78
|
fetcher?: string | [string, string] | [string];
|
|
77
79
|
validateOnClient?: string | [string, string] | [string];
|
|
@@ -106,8 +108,8 @@ export default function getConfig({ configPath, cwd }: {
|
|
|
106
108
|
banner?: string;
|
|
107
109
|
};
|
|
108
110
|
apiRoot?: string;
|
|
109
|
-
getModuleName?: "nestjs-operation-id" | (string & {}) | "api" | import("vovk/
|
|
110
|
-
getMethodName?: "nestjs-operation-id" | "camel-case-operation-id" | "auto" | import("vovk/
|
|
111
|
+
getModuleName?: "nestjs-operation-id" | (string & {}) | "api" | import("vovk/types").GetOpenAPINameFn;
|
|
112
|
+
getMethodName?: "nestjs-operation-id" | "camel-case-operation-id" | "auto" | import("vovk/types").GetOpenAPINameFn;
|
|
111
113
|
errorMessageKey?: string;
|
|
112
114
|
};
|
|
113
115
|
};
|
|
@@ -6,7 +6,7 @@ import getRelativeSrcRoot from './getRelativeSrcRoot.mjs';
|
|
|
6
6
|
import getTemplateDefs, { BuiltInTemplateName } from './getTemplateDefs.mjs';
|
|
7
7
|
import { normalizeOpenAPIMixins } from '../../utils/normalizeOpenAPIMixins.mjs';
|
|
8
8
|
import chalkHighlightThing from '../../utils/chalkHighlightThing.mjs';
|
|
9
|
-
export default async function getConfig({ configPath, cwd }) {
|
|
9
|
+
export default async function getConfig({ configPath, cwd, logLevel, }) {
|
|
10
10
|
const { configAbsolutePaths, error, userConfig } = await getUserConfig({
|
|
11
11
|
configPath,
|
|
12
12
|
cwd,
|
|
@@ -65,7 +65,7 @@ export default async function getConfig({ configPath, cwd }) {
|
|
|
65
65
|
origin: (env.VOVK_ORIGIN ?? conf.origin ?? '').replace(/\/$/, ''), // Remove trailing slash
|
|
66
66
|
rootEntry: env.VOVK_ROOT_ENTRY ?? conf.rootEntry ?? 'api',
|
|
67
67
|
rootSegmentModulesDirName: conf.rootSegmentModulesDirName ?? '',
|
|
68
|
-
logLevel:
|
|
68
|
+
logLevel: conf.logLevel ?? 'info',
|
|
69
69
|
devHttps: conf.devHttps ?? false,
|
|
70
70
|
moduleTemplates: {
|
|
71
71
|
service: 'vovk-cli/module-templates/service.ts.ejs',
|
|
@@ -85,7 +85,7 @@ export default async function getConfig({ configPath, cwd }) {
|
|
|
85
85
|
else if (Array.isArray(conf.emitConfig)) {
|
|
86
86
|
config.emitConfig = conf.emitConfig;
|
|
87
87
|
} // else it's false and emitConfig already is []
|
|
88
|
-
const log = getLogger(config.logLevel);
|
|
88
|
+
const log = getLogger(logLevel ?? config.logLevel);
|
|
89
89
|
config.openApiMixins = await normalizeOpenAPIMixins({
|
|
90
90
|
mixinModules: conf.openApiMixins ?? {},
|
|
91
91
|
cwd,
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import { LogLevelNames } from 'loglevel';
|
|
1
2
|
export type ProjectInfo = Awaited<ReturnType<typeof getProjectInfo>>;
|
|
2
|
-
export default function getProjectInfo({ port: givenPort, cwd, configPath, srcRootRequired, }?: {
|
|
3
|
+
export default function getProjectInfo({ port: givenPort, cwd, configPath, srcRootRequired, logLevel, }?: {
|
|
3
4
|
port?: number;
|
|
4
5
|
cwd?: string;
|
|
5
6
|
configPath?: string;
|
|
6
7
|
srcRootRequired?: boolean;
|
|
8
|
+
logLevel?: LogLevelNames;
|
|
7
9
|
}): Promise<{
|
|
8
10
|
cwd: string;
|
|
9
11
|
port: string;
|
|
@@ -13,7 +15,7 @@ export default function getProjectInfo({ port: givenPort, cwd, configPath, srcRo
|
|
|
13
15
|
vovkCliPackage: {
|
|
14
16
|
version: string;
|
|
15
17
|
};
|
|
16
|
-
config: import("vovk").VovkStrictConfig;
|
|
18
|
+
config: import("vovk/types").VovkStrictConfig;
|
|
17
19
|
packageJson: import("type-fest").PackageJson;
|
|
18
20
|
isNextInstalled: boolean;
|
|
19
21
|
log: {
|
|
@@ -2,13 +2,16 @@ import path from 'node:path';
|
|
|
2
2
|
import getConfig from './getConfig/index.mjs';
|
|
3
3
|
import { getPackageJson } from '../utils/getPackageJson.mjs';
|
|
4
4
|
import { readFile } from 'node:fs/promises';
|
|
5
|
-
export default async function getProjectInfo({ port: givenPort, cwd = process.cwd(), configPath, srcRootRequired = true, } = {
|
|
5
|
+
export default async function getProjectInfo({ port: givenPort, cwd = process.cwd(), configPath, srcRootRequired = true, logLevel, } = {
|
|
6
|
+
logLevel: 'info',
|
|
7
|
+
}) {
|
|
6
8
|
const port = givenPort?.toString() ?? process.env.PORT ?? '3000';
|
|
7
9
|
// Make PORT available to the config file at getConfig
|
|
8
10
|
process.env.PORT = port;
|
|
9
11
|
const { config, srcRoot, configAbsolutePaths, log } = await getConfig({
|
|
10
12
|
configPath,
|
|
11
13
|
cwd,
|
|
14
|
+
logLevel,
|
|
12
15
|
});
|
|
13
16
|
const packageJson = await getPackageJson(cwd, log);
|
|
14
17
|
const isNextInstalled = !!packageJson?.dependencies?.next || !!packageJson?.devDependencies?.next;
|
package/dist/index.mjs
CHANGED
|
@@ -25,8 +25,9 @@ program
|
|
|
25
25
|
.option('--exit', 'kill the processes when schema and client is generated')
|
|
26
26
|
.option('--schema-out <path>', 'path to schema output directory (default: .vovk-schema)')
|
|
27
27
|
.option('--https, --dev-https', 'use HTTPS for the dev server (default: false)')
|
|
28
|
+
.option('--log-level <level>', 'set the log level')
|
|
28
29
|
.action(async (nextArgs, options) => {
|
|
29
|
-
const { nextDev, exit = false, schemaOut, devHttps } = options;
|
|
30
|
+
const { nextDev, exit = false, schemaOut, devHttps, logLevel } = options;
|
|
30
31
|
const portAttempts = 30;
|
|
31
32
|
const PORT = !nextDev
|
|
32
33
|
? process.env.PORT
|
|
@@ -52,9 +53,11 @@ program
|
|
|
52
53
|
env: {
|
|
53
54
|
PORT,
|
|
54
55
|
__VOVK_START_WATCHER_IN_STANDALONE_MODE__: 'true',
|
|
56
|
+
// TODO: Pass these as flags
|
|
55
57
|
__VOVK_SCHEMA_OUT_FLAG__: schemaOut ?? '',
|
|
56
58
|
__VOVK_DEV_HTTPS_FLAG__: devHttps ? 'true' : 'false',
|
|
57
59
|
__VOVK_EXIT__: exit ? 'true' : 'false',
|
|
60
|
+
__VOVK_LOG_LEVEL__: logLevel ?? undefined,
|
|
58
61
|
},
|
|
59
62
|
},
|
|
60
63
|
], {
|
|
@@ -70,7 +73,7 @@ program
|
|
|
70
73
|
}
|
|
71
74
|
}
|
|
72
75
|
else {
|
|
73
|
-
void new VovkDev({ schemaOut, devHttps }).start({ exit });
|
|
76
|
+
void new VovkDev({ schemaOut, devHttps, logLevel }).start({ exit });
|
|
74
77
|
}
|
|
75
78
|
});
|
|
76
79
|
program
|
|
@@ -98,8 +101,13 @@ program
|
|
|
98
101
|
.option('--openapi-root-url <urls...>', 'root URLs corresponding to the index of --openapi option')
|
|
99
102
|
.option('--openapi-mixin-name <names...>', 'mixin names corresponding to the index of --openapi option')
|
|
100
103
|
.option('--openapi-fallback <paths...>', 'save OpenAPI spec and use it as a fallback if URL is not available')
|
|
104
|
+
.option('--log-level <level>', 'set the log level')
|
|
101
105
|
.action(async (cliGenerateOptions) => {
|
|
102
|
-
const projectInfo = await getProjectInfo({
|
|
106
|
+
const projectInfo = await getProjectInfo({
|
|
107
|
+
configPath: cliGenerateOptions.configPath,
|
|
108
|
+
srcRootRequired: false,
|
|
109
|
+
logLevel: cliGenerateOptions.logLevel,
|
|
110
|
+
});
|
|
103
111
|
await new VovkGenerate({
|
|
104
112
|
projectInfo,
|
|
105
113
|
forceNothingWrittenLog: true,
|
|
@@ -118,12 +126,18 @@ program
|
|
|
118
126
|
.option('--config <config>', 'path to config file')
|
|
119
127
|
.option('--schema <path>', 'path to schema folder (default: .vovk-schema)')
|
|
120
128
|
.option('--origin <url>', 'set the origin URL for the generated client')
|
|
129
|
+
.option('--tsconfig <path>', 'path to tsconfig.json for bundling by tsdown')
|
|
121
130
|
.option('--openapi, --openapi-spec <openapi_path_or_urls...>', 'use OpenAPI schema instead of Vovk schema')
|
|
122
131
|
.option('--openapi-get-module-name <names...>', 'module names corresponding to the index of --openapi option')
|
|
123
132
|
.option('--openapi-get-method-name <names...>', 'method names corresponding to the index of --openapi option')
|
|
124
133
|
.option('--openapi-root-url <urls...>', 'root URLs corresponding to the index of --openapi option')
|
|
134
|
+
.option('--log-level <level>', 'set the log level')
|
|
125
135
|
.action(async (cliBundleOptions) => {
|
|
126
|
-
const projectInfo = await getProjectInfo({
|
|
136
|
+
const projectInfo = await getProjectInfo({
|
|
137
|
+
configPath: cliBundleOptions.config,
|
|
138
|
+
srcRootRequired: false,
|
|
139
|
+
logLevel: cliBundleOptions.logLevel,
|
|
140
|
+
});
|
|
127
141
|
const { cwd, config, log, isNextInstalled } = projectInfo;
|
|
128
142
|
const fullSchema = await getProjectFullSchema({
|
|
129
143
|
schemaOutAbsolutePath: path.resolve(cwd, cliBundleOptions?.schema ?? config.schemaOutDir),
|
|
@@ -147,7 +161,10 @@ program
|
|
|
147
161
|
.option('--no-segment-update', 'do not update segment files when creating a new module')
|
|
148
162
|
.option('--dry-run', 'do not write files to disk')
|
|
149
163
|
.option('--static', 'if the segment is static')
|
|
150
|
-
.
|
|
164
|
+
.option('--log-level <level>', 'set the log level')
|
|
165
|
+
.action(async (components, newOptions) => newComponents(components, await getProjectInfo({
|
|
166
|
+
logLevel: newOptions.logLevel,
|
|
167
|
+
}), newOptions));
|
|
151
168
|
program
|
|
152
169
|
.command('help')
|
|
153
170
|
.description('Show help message')
|
|
@@ -11,14 +11,36 @@ export default async function createConfig({ root, log, options: { validationLib
|
|
|
11
11
|
.readFile(path.join(root, 'package.json'), 'utf-8')
|
|
12
12
|
.then((content) => JSON.parse(content).type === 'module');
|
|
13
13
|
const configAbsolutePath = path.join(dir, isModule ? 'vovk.config.mjs' : 'vovk.config.js');
|
|
14
|
+
const typeTemplates = {
|
|
15
|
+
controller: 'vovk-cli/module-templates/type/controller.ts.ejs',
|
|
16
|
+
service: 'vovk-cli/module-templates/type/service.ts.ejs',
|
|
17
|
+
};
|
|
14
18
|
const moduleTemplates = {
|
|
15
|
-
|
|
16
|
-
|
|
19
|
+
...typeTemplates,
|
|
20
|
+
...{
|
|
21
|
+
type: typeTemplates,
|
|
22
|
+
zod: {
|
|
23
|
+
controller: 'vovk-zod/module-templates/controller.ts.ejs',
|
|
24
|
+
},
|
|
25
|
+
yup: {
|
|
26
|
+
controller: 'vovk-yup/module-templates/controller.ts.ejs',
|
|
27
|
+
},
|
|
28
|
+
'class-validator': {
|
|
29
|
+
controller: 'vovk-dto/module-templates/controller.ts.ejs',
|
|
30
|
+
},
|
|
31
|
+
valibot: {
|
|
32
|
+
controller: 'vovk-cli/module-templates/valibot/controller.ts.ejs',
|
|
33
|
+
},
|
|
34
|
+
arktype: {
|
|
35
|
+
controller: 'vovk-cli/module-templates/arktype/controller.ts.ejs',
|
|
36
|
+
},
|
|
37
|
+
}[validationLibrary ?? 'type'],
|
|
17
38
|
};
|
|
18
39
|
config.imports ??= {};
|
|
19
|
-
config.imports.validateOnClient = validationLibrary === '
|
|
20
|
-
if (validationLibrary) {
|
|
40
|
+
config.imports.validateOnClient = validationLibrary === 'class-validator' ? 'vovk-dto/validateOnClient' : 'vovk-ajv';
|
|
41
|
+
if (validationLibrary && !moduleTemplates) {
|
|
21
42
|
try {
|
|
43
|
+
// TODO: Legacy, is it useful to keep it?
|
|
22
44
|
const validationTemplates = await getTemplateFilesFromPackage(validationLibrary, channel);
|
|
23
45
|
Object.assign(moduleTemplates, validationTemplates);
|
|
24
46
|
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import fs from 'fs/promises';
|
|
2
|
+
import getRelativeSrcRoot from '../getProjectInfo/getConfig/getRelativeSrcRoot.mjs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
function getCode(validationLibrary) {
|
|
5
|
+
if (validationLibrary === 'valibot') {
|
|
6
|
+
return `
|
|
7
|
+
import { createStandardValidation, KnownAny } from 'vovk';
|
|
8
|
+
import { toJsonSchema } from '@valibot/to-json-schema';
|
|
9
|
+
import * as v from 'valibot';
|
|
10
|
+
|
|
11
|
+
const withValibot = createStandardValidation({
|
|
12
|
+
toJSONSchema: (model: v.BaseSchema<KnownAny, KnownAny, KnownAny>) => toJsonSchema(model),
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
export default withValibot;
|
|
16
|
+
`.trimStart();
|
|
17
|
+
}
|
|
18
|
+
if (validationLibrary === 'arktype') {
|
|
19
|
+
return `
|
|
20
|
+
import { createStandardValidation } from 'vovk';
|
|
21
|
+
import { type } from 'arktype';
|
|
22
|
+
|
|
23
|
+
const withArk = createStandardValidation({
|
|
24
|
+
toJSONSchema: (model: type) => model.toJsonSchema(),
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
export default withArk;
|
|
28
|
+
`.trimStart();
|
|
29
|
+
}
|
|
30
|
+
throw new Error(`Unknown validation library: ${validationLibrary}`);
|
|
31
|
+
}
|
|
32
|
+
export async function createStandardSchemaValidatorFile({ cwd, validationLibrary, }) {
|
|
33
|
+
const code = getCode(validationLibrary);
|
|
34
|
+
const srcRoot = (await getRelativeSrcRoot({ cwd })) ?? '.';
|
|
35
|
+
const libDir = path.join(cwd, srcRoot, 'lib');
|
|
36
|
+
await fs.mkdir(libDir, { recursive: true });
|
|
37
|
+
await fs.writeFile(path.join(libDir, `${validationLibrary === 'arktype' ? 'withArk' : 'withValibot'}.ts`), code);
|
|
38
|
+
}
|
package/dist/init/index.mjs
CHANGED
|
@@ -8,18 +8,28 @@ import getFileSystemEntryType from '../utils/getFileSystemEntryType.mjs';
|
|
|
8
8
|
import installDependencies, { getPackageManager } from './installDependencies.mjs';
|
|
9
9
|
import getLogger from '../utils/getLogger.mjs';
|
|
10
10
|
import createConfig from './createConfig.mjs';
|
|
11
|
-
import updateNPMScripts, {
|
|
11
|
+
import updateNPMScripts, { getDevScript } from './updateNPMScripts.mjs';
|
|
12
12
|
import checkTSConfigForExperimentalDecorators from './checkTSConfigForExperimentalDecorators.mjs';
|
|
13
13
|
import updateTypeScriptConfig from './updateTypeScriptConfig.mjs';
|
|
14
14
|
import updateDependenciesWithoutInstalling from './updateDependenciesWithoutInstalling.mjs';
|
|
15
15
|
import logUpdateDependenciesError from './logUpdateDependenciesError.mjs';
|
|
16
16
|
import chalkHighlightThing from '../utils/chalkHighlightThing.mjs';
|
|
17
|
+
import { createStandardSchemaValidatorFile } from './createStandardSchemaValidatorFile.mjs';
|
|
17
18
|
export class Init {
|
|
18
19
|
root;
|
|
19
20
|
log;
|
|
20
|
-
async #init({ configPaths, pkgJson, }, { useNpm, useYarn, usePnpm, useBun, skipInstall, updateTsConfig, updateScripts, validationLibrary, lang, dryRun, channel, }) {
|
|
21
|
+
async #init({ configPaths, pkgJson, cwd = process.cwd(), }, { useNpm, useYarn, usePnpm, useBun, skipInstall, updateTsConfig, updateScripts, validationLibrary, lang, dryRun, channel, }) {
|
|
21
22
|
const { log, root } = this;
|
|
22
|
-
const dependencies = [
|
|
23
|
+
const dependencies = [
|
|
24
|
+
'vovk',
|
|
25
|
+
'vovk-client',
|
|
26
|
+
'openapi3-ts',
|
|
27
|
+
'vovk-ajv',
|
|
28
|
+
'ajv',
|
|
29
|
+
'ajv-errors',
|
|
30
|
+
'ajv-formats',
|
|
31
|
+
'ajv-i18n',
|
|
32
|
+
];
|
|
23
33
|
const devDependencies = ['vovk-cli'];
|
|
24
34
|
if (lang?.includes('py')) {
|
|
25
35
|
devDependencies.push('vovk-python');
|
|
@@ -33,9 +43,18 @@ export class Init {
|
|
|
33
43
|
log.debug(`Deleted existing config file${configPaths.length > 1 ? 's' : ''} at ${configPaths.join(', ')}`);
|
|
34
44
|
}
|
|
35
45
|
if (validationLibrary) {
|
|
36
|
-
dependencies.push(
|
|
37
|
-
|
|
38
|
-
'
|
|
46
|
+
dependencies.push(...({
|
|
47
|
+
zod: ['zod', 'vovk-zod'],
|
|
48
|
+
'class-validator': [
|
|
49
|
+
'class-validator',
|
|
50
|
+
'class-transformer',
|
|
51
|
+
'dto-mapped-types',
|
|
52
|
+
'reflect-metadata',
|
|
53
|
+
'vovk-dto',
|
|
54
|
+
],
|
|
55
|
+
yup: ['yup', 'vovk-yup'],
|
|
56
|
+
valibot: ['valibot', '@valibot/to-json-schema'],
|
|
57
|
+
arktype: ['arktype'],
|
|
39
58
|
}[validationLibrary] ?? []));
|
|
40
59
|
}
|
|
41
60
|
if (updateScripts) {
|
|
@@ -56,7 +75,7 @@ export class Init {
|
|
|
56
75
|
const compilerOptions = {
|
|
57
76
|
experimentalDecorators: true,
|
|
58
77
|
};
|
|
59
|
-
if (validationLibrary === '
|
|
78
|
+
if (validationLibrary === 'class-validator') {
|
|
60
79
|
compilerOptions.emitDecoratorMetadata = true;
|
|
61
80
|
}
|
|
62
81
|
if (!dryRun)
|
|
@@ -120,6 +139,12 @@ export class Init {
|
|
|
120
139
|
}
|
|
121
140
|
}
|
|
122
141
|
}
|
|
142
|
+
if (validationLibrary === 'valibot' || validationLibrary === 'arktype') {
|
|
143
|
+
createStandardSchemaValidatorFile({
|
|
144
|
+
cwd,
|
|
145
|
+
validationLibrary,
|
|
146
|
+
});
|
|
147
|
+
}
|
|
123
148
|
try {
|
|
124
149
|
const { configAbsolutePath } = await createConfig({
|
|
125
150
|
root,
|
|
@@ -135,13 +160,13 @@ export class Init {
|
|
|
135
160
|
async main({ prefix, yes, logLevel, useNpm, useYarn, usePnpm, useBun, skipInstall, updateTsConfig, updateScripts, validationLibrary, lang, dryRun, channel, }) {
|
|
136
161
|
const cwd = process.cwd();
|
|
137
162
|
const root = path.resolve(cwd, prefix ?? '.');
|
|
138
|
-
const log = getLogger(logLevel);
|
|
163
|
+
const log = getLogger(logLevel ?? 'info');
|
|
139
164
|
const pkgJson = await NPMCliPackageJson.load(root);
|
|
140
165
|
this.root = root;
|
|
141
166
|
this.log = log;
|
|
142
167
|
const configPaths = await getConfigPaths({ cwd, relativePath: prefix });
|
|
143
168
|
if (yes) {
|
|
144
|
-
return this.#init({ configPaths, pkgJson }, {
|
|
169
|
+
return this.#init({ configPaths, pkgJson, cwd }, {
|
|
145
170
|
prefix: prefix ?? '.',
|
|
146
171
|
useNpm: useNpm ?? (!useYarn && !usePnpm && !useBun),
|
|
147
172
|
useYarn: useYarn ?? false,
|
|
@@ -150,7 +175,7 @@ export class Init {
|
|
|
150
175
|
skipInstall: skipInstall ?? false,
|
|
151
176
|
updateTsConfig: updateTsConfig ?? true,
|
|
152
177
|
updateScripts: updateScripts ?? 'implicit',
|
|
153
|
-
validationLibrary: validationLibrary?.toLocaleLowerCase() === 'none' ? null : (validationLibrary ?? '
|
|
178
|
+
validationLibrary: validationLibrary?.toLocaleLowerCase() === 'none' ? null : (validationLibrary ?? 'zod'),
|
|
154
179
|
dryRun: dryRun ?? false,
|
|
155
180
|
channel: channel ?? 'latest',
|
|
156
181
|
lang: lang ?? [],
|
|
@@ -174,17 +199,27 @@ export class Init {
|
|
|
174
199
|
: (validationLibrary ??
|
|
175
200
|
(await select({
|
|
176
201
|
message: 'Choose validation library',
|
|
177
|
-
default: '
|
|
202
|
+
default: 'zod',
|
|
178
203
|
choices: [
|
|
179
204
|
{
|
|
180
|
-
name: '
|
|
181
|
-
value: '
|
|
205
|
+
name: 'Zod',
|
|
206
|
+
value: 'zod',
|
|
182
207
|
description: 'Use Zod for data validation',
|
|
183
208
|
},
|
|
184
209
|
{
|
|
185
|
-
name: '
|
|
186
|
-
value: '
|
|
187
|
-
description: 'Use class-validator for data validation
|
|
210
|
+
name: 'class-validator',
|
|
211
|
+
value: 'class-validator',
|
|
212
|
+
description: 'Use class-validator for data validation',
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
name: 'Valibot',
|
|
216
|
+
value: 'valibot',
|
|
217
|
+
description: 'Use valibot for data validation.',
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
name: 'ArkType',
|
|
221
|
+
value: 'arktype',
|
|
222
|
+
description: 'Use arktype for data validation.',
|
|
188
223
|
},
|
|
189
224
|
{ name: 'None', value: null, description: 'Install validation library later' },
|
|
190
225
|
],
|
|
@@ -196,12 +231,12 @@ export class Init {
|
|
|
196
231
|
{
|
|
197
232
|
name: 'Yes, use "concurrently" implicitly',
|
|
198
233
|
value: 'implicit',
|
|
199
|
-
description: `The "dev" script will use "concurrently" API to run "next dev" and "vovk dev" commands together and automatically find an available port ${chalk.whiteBright.bold(`"${getDevScript(pkgJson, 'implicit')}"`)} and the "
|
|
234
|
+
description: `The "dev" script will use "concurrently" API to run "next dev" and "vovk dev" commands together and automatically find an available port ${chalk.whiteBright.bold(`"${getDevScript(pkgJson, 'implicit')}"`)} and the "prebuild" script will run "vovk generate"`,
|
|
200
235
|
},
|
|
201
236
|
{
|
|
202
237
|
name: 'Yes, use "concurrently" explicitly',
|
|
203
238
|
value: 'explicit',
|
|
204
|
-
description: `The "dev" script will use pre-defined PORT variable and run "next dev" and "vovk dev" as "concurrently" CLI arguments ${chalk.whiteBright.bold(`"${getDevScript(pkgJson, 'explicit')}"`)} and the "
|
|
239
|
+
description: `The "dev" script will use pre-defined PORT variable and run "next dev" and "vovk dev" as "concurrently" CLI arguments ${chalk.whiteBright.bold(`"${getDevScript(pkgJson, 'explicit')}"`)} and the "prebuild" script will run "vovk generate"`,
|
|
205
240
|
},
|
|
206
241
|
{
|
|
207
242
|
name: 'No',
|
|
@@ -220,7 +255,7 @@ export class Init {
|
|
|
220
255
|
}
|
|
221
256
|
if (shouldAsk) {
|
|
222
257
|
const keys = ['experimentalDecorators'];
|
|
223
|
-
if (validationLibrary === '
|
|
258
|
+
if (validationLibrary === 'class-validator') {
|
|
224
259
|
keys.push('emitDecoratorMetadata');
|
|
225
260
|
}
|
|
226
261
|
updateTsConfig = await confirm({
|
|
@@ -229,13 +264,13 @@ export class Init {
|
|
|
229
264
|
}
|
|
230
265
|
}
|
|
231
266
|
lang ??= await checkbox({
|
|
232
|
-
message: 'Do you want to generate RPC client for other languages besides TypeScript (
|
|
267
|
+
message: 'Do you want to generate RPC client for other languages besides TypeScript (experimental)?',
|
|
233
268
|
choices: [
|
|
234
269
|
{ name: 'Python', value: 'py' },
|
|
235
270
|
{ name: 'Rust', value: 'rs' },
|
|
236
271
|
],
|
|
237
272
|
});
|
|
238
|
-
await this.#init({ configPaths, pkgJson }, {
|
|
273
|
+
await this.#init({ configPaths, pkgJson, cwd }, {
|
|
239
274
|
useNpm: useNpm ?? (!useYarn && !usePnpm && !useBun),
|
|
240
275
|
useYarn: useYarn ?? false,
|
|
241
276
|
usePnpm: usePnpm ?? false,
|
|
@@ -1,4 +1,3 @@
|
|
|
1
1
|
import NPMCliPackageJson from '@npmcli/package-json';
|
|
2
2
|
export declare function getDevScript(pkgJson: NPMCliPackageJson, updateScriptsMode: 'implicit' | 'explicit'): string;
|
|
3
|
-
export declare function getBuildScript(pkgJson: NPMCliPackageJson): string;
|
|
4
3
|
export default function updateNPMScripts(pkgJson: NPMCliPackageJson, root: string, updateScriptsMode: 'implicit' | 'explicit'): Promise<void>;
|
|
@@ -5,16 +5,12 @@ export function getDevScript(pkgJson, updateScriptsMode) {
|
|
|
5
5
|
? `PORT=3000 concurrently '${nextDev}' 'vovk dev' --kill-others`
|
|
6
6
|
: `vovk dev --next-dev${nextDevFlags ? ` -- ${nextDevFlags}` : ''}`;
|
|
7
7
|
}
|
|
8
|
-
export function getBuildScript(pkgJson) {
|
|
9
|
-
const nextBuild = pkgJson.content.scripts?.build ?? 'next build';
|
|
10
|
-
return `vovk generate && ${nextBuild}`;
|
|
11
|
-
}
|
|
12
8
|
export default async function updateNPMScripts(pkgJson, root, updateScriptsMode) {
|
|
13
9
|
pkgJson.update({
|
|
14
10
|
scripts: {
|
|
15
11
|
...pkgJson.content.scripts,
|
|
16
12
|
dev: getDevScript(pkgJson, updateScriptsMode),
|
|
17
|
-
|
|
13
|
+
prebuild: 'vovk generate',
|
|
18
14
|
},
|
|
19
15
|
});
|
|
20
16
|
await pkgJson.save();
|
package/dist/initProgram.mjs
CHANGED
|
@@ -14,7 +14,7 @@ export function initProgram(program) {
|
|
|
14
14
|
.option('--update-ts-config', 'update tsconfig.json')
|
|
15
15
|
.option('--update-scripts <mode>', 'update package.json scripts ("implicit" or "explicit")')
|
|
16
16
|
.option('--lang <languages...>', 'generate client for other programming languages by default ("py" for Python and "rs" for Rust are supported)')
|
|
17
|
-
.option('--validation-library <library>', 'validation library to use ("
|
|
17
|
+
.option('--validation-library <library>', 'validation library to use ("zod", "class-validator", "valibot", "arktype" or another); set to "none" to skip')
|
|
18
18
|
.option('--channel <channel>', 'channel to use for fetching packages', 'latest')
|
|
19
19
|
.option('--dry-run', 'do not write files to disk')
|
|
20
20
|
.action((options) => new Init().main(options));
|
package/dist/new/index.d.mts
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
import type { NewOptions } from '../types.mjs';
|
|
2
|
-
|
|
2
|
+
import type { ProjectInfo } from '../getProjectInfo/index.mts';
|
|
3
|
+
export declare function newComponents(components: string[], projectInfo: ProjectInfo, { dryRun, dir, templates, overwrite, noSegmentUpdate, empty, static: isStaticSegment }: NewOptions): Promise<void>;
|
package/dist/new/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import newModule from './newModule.mjs';
|
|
2
2
|
import newSegment from './newSegment.mjs';
|
|
3
|
-
export async function newComponents(components, { dryRun, dir, templates, overwrite, noSegmentUpdate, empty, static: isStaticSegment }) {
|
|
3
|
+
export async function newComponents(components, projectInfo, { dryRun, dir, templates, overwrite, noSegmentUpdate, empty, static: isStaticSegment }) {
|
|
4
4
|
if (components[0] === 'segment' || components[0] === 'segments') {
|
|
5
5
|
// vovk new segment [segmentName]
|
|
6
6
|
let segmentNames = components
|
|
@@ -10,7 +10,7 @@ export async function newComponents(components, { dryRun, dir, templates, overwr
|
|
|
10
10
|
segmentNames = [''];
|
|
11
11
|
}
|
|
12
12
|
for (const segmentName of segmentNames) {
|
|
13
|
-
await newSegment({ segmentName, isStaticSegment, overwrite, dryRun });
|
|
13
|
+
await newSegment({ projectInfo, segmentName, isStaticSegment, overwrite, dryRun });
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
16
|
else {
|
|
@@ -24,6 +24,7 @@ export async function newComponents(components, { dryRun, dir, templates, overwr
|
|
|
24
24
|
throw new Error('A module name with an optional segment cannot be empty');
|
|
25
25
|
}
|
|
26
26
|
await newModule({
|
|
27
|
+
projectInfo,
|
|
27
28
|
what,
|
|
28
29
|
moduleNameWithOptionalSegment,
|
|
29
30
|
dir,
|
package/dist/new/newModule.d.mts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
import type { ProjectInfo } from '../getProjectInfo/index.mjs';
|
|
2
|
+
export default function newModule({ projectInfo, what, moduleNameWithOptionalSegment, dryRun, dir: dirFlag, templates: templatesFlag, noSegmentUpdate, overwrite, empty, }: {
|
|
3
|
+
projectInfo: ProjectInfo;
|
|
2
4
|
what: string[];
|
|
3
5
|
moduleNameWithOptionalSegment: string;
|
|
4
6
|
dryRun?: boolean;
|
package/dist/new/newModule.mjs
CHANGED
|
@@ -3,7 +3,6 @@ import fs from 'node:fs/promises';
|
|
|
3
3
|
import { getTsconfig } from 'get-tsconfig';
|
|
4
4
|
import render from './render.mjs';
|
|
5
5
|
import addClassToSegmentCode from './addClassToSegmentCode.mjs';
|
|
6
|
-
import getProjectInfo from '../getProjectInfo/index.mjs';
|
|
7
6
|
import chalkHighlightThing from '../utils/chalkHighlightThing.mjs';
|
|
8
7
|
import formatLoggedSegmentName from '../utils/formatLoggedSegmentName.mjs';
|
|
9
8
|
import getFileSystemEntryType from '../utils/getFileSystemEntryType.mjs';
|
|
@@ -20,8 +19,8 @@ function splitByLast(str, delimiter = '/') {
|
|
|
20
19
|
const after = str.substring(index + delimiter.length);
|
|
21
20
|
return [before, after];
|
|
22
21
|
}
|
|
23
|
-
export default async function newModule({ what, moduleNameWithOptionalSegment, dryRun, dir: dirFlag, templates: templatesFlag, noSegmentUpdate, overwrite, empty, }) {
|
|
24
|
-
const { config, log, cwd, apiDirAbsolutePath } =
|
|
22
|
+
export default async function newModule({ projectInfo, what, moduleNameWithOptionalSegment, dryRun, dir: dirFlag, templates: templatesFlag, noSegmentUpdate, overwrite, empty, }) {
|
|
23
|
+
const { config, log, cwd, apiDirAbsolutePath } = projectInfo;
|
|
25
24
|
const segments = await locateSegments({ dir: apiDirAbsolutePath, config, log });
|
|
26
25
|
const isNodeNextResolution = ['node16', 'nodenext'].includes((await getTsconfig(cwd)?.config?.compilerOptions?.moduleResolution?.toLowerCase()) ?? '');
|
|
27
26
|
let templates = config.moduleTemplates;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
import type { ProjectInfo } from '../getProjectInfo/index.mjs';
|
|
2
|
+
export default function newSegment({ projectInfo, segmentName, isStaticSegment, overwrite, dryRun, }: {
|
|
3
|
+
projectInfo: ProjectInfo;
|
|
2
4
|
segmentName: string;
|
|
3
5
|
isStaticSegment?: boolean;
|
|
4
6
|
overwrite?: boolean;
|
package/dist/new/newSegment.mjs
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import fs from 'node:fs/promises';
|
|
3
|
-
import getProjectInfo from '../getProjectInfo/index.mjs';
|
|
4
3
|
import getFileSystemEntryType from '../utils/getFileSystemEntryType.mjs';
|
|
5
4
|
import chalkHighlightThing from '../utils/chalkHighlightThing.mjs';
|
|
6
5
|
import formatLoggedSegmentName from '../utils/formatLoggedSegmentName.mjs';
|
|
7
6
|
import prettify from '../utils/prettify.mjs';
|
|
8
7
|
import chalk from 'chalk';
|
|
9
|
-
export default async function newSegment({ segmentName, isStaticSegment, overwrite, dryRun, }) {
|
|
10
|
-
const { apiDirAbsolutePath, log, config } =
|
|
8
|
+
export default async function newSegment({ projectInfo, segmentName, isStaticSegment, overwrite, dryRun, }) {
|
|
9
|
+
const { apiDirAbsolutePath, log, config } = projectInfo;
|
|
11
10
|
if (!apiDirAbsolutePath) {
|
|
12
11
|
throw new Error('No API directory found. Please ensure you are in a Nest.js project.');
|
|
13
12
|
}
|
package/dist/types.d.mts
CHANGED
|
@@ -12,6 +12,7 @@ export interface DevOptions {
|
|
|
12
12
|
nextDev?: boolean;
|
|
13
13
|
exit?: boolean;
|
|
14
14
|
devHttps?: boolean;
|
|
15
|
+
logLevel?: LogLevelNames;
|
|
15
16
|
}
|
|
16
17
|
export interface GenerateOptions {
|
|
17
18
|
prettify?: boolean;
|
|
@@ -35,22 +36,24 @@ export interface GenerateOptions {
|
|
|
35
36
|
segmentedOnly?: boolean;
|
|
36
37
|
segmentedIncludeSegments?: string[];
|
|
37
38
|
segmentedExcludeSegments?: string[];
|
|
39
|
+
logLevel?: LogLevelNames;
|
|
38
40
|
}
|
|
39
41
|
export interface BundleOptions extends Partial<Pick<VovkStrictConfig['bundle'], 'prebundleOutDir' | 'keepPrebundleDir' | 'includeSegments' | 'excludeSegments'>> {
|
|
40
42
|
config?: string;
|
|
41
43
|
schema?: string;
|
|
42
44
|
outDir?: string;
|
|
43
45
|
origin?: string;
|
|
46
|
+
tsconfig?: string;
|
|
44
47
|
openapiSpec?: string[];
|
|
45
48
|
openapiGetModuleName?: string[];
|
|
46
49
|
openapiGetMethodName?: string[];
|
|
47
50
|
openapiRootUrl?: string[];
|
|
48
51
|
openapiMixinName?: string[];
|
|
52
|
+
logLevel?: LogLevelNames;
|
|
49
53
|
}
|
|
50
54
|
export interface InitOptions {
|
|
51
55
|
prefix?: string;
|
|
52
56
|
yes?: boolean;
|
|
53
|
-
logLevel: LogLevelNames;
|
|
54
57
|
useNpm?: boolean;
|
|
55
58
|
useYarn?: boolean;
|
|
56
59
|
usePnpm?: boolean;
|
|
@@ -58,10 +61,11 @@ export interface InitOptions {
|
|
|
58
61
|
skipInstall?: boolean;
|
|
59
62
|
updateTsConfig?: boolean;
|
|
60
63
|
updateScripts?: 'implicit' | 'explicit';
|
|
61
|
-
validationLibrary?:
|
|
64
|
+
validationLibrary?: 'zod' | 'yup' | 'class-validator' | 'valibot' | 'arktype' | null;
|
|
62
65
|
dryRun?: boolean;
|
|
63
66
|
lang?: string[];
|
|
64
67
|
channel?: 'latest' | 'beta' | 'draft';
|
|
68
|
+
logLevel?: LogLevelNames;
|
|
65
69
|
}
|
|
66
70
|
export interface NewOptions {
|
|
67
71
|
dryRun?: boolean;
|
|
@@ -71,6 +75,7 @@ export interface NewOptions {
|
|
|
71
75
|
noSegmentUpdate?: boolean;
|
|
72
76
|
empty?: boolean;
|
|
73
77
|
static?: boolean;
|
|
78
|
+
logLevel?: LogLevelNames;
|
|
74
79
|
}
|
|
75
80
|
export type VovkEnv = {
|
|
76
81
|
PORT?: string;
|
|
@@ -78,9 +83,9 @@ export type VovkEnv = {
|
|
|
78
83
|
VOVK_ORIGIN?: string;
|
|
79
84
|
VOVK_ROOT_ENTRY?: string;
|
|
80
85
|
VOVK_API_ENTRY_POINT?: string;
|
|
81
|
-
VOVK_LOG_LEVEL?: LogLevelNames;
|
|
82
86
|
__VOVK_START_WATCHER_IN_STANDALONE_MODE__?: 'true';
|
|
83
87
|
__VOVK_SCHEMA_OUT_FLAG__?: string;
|
|
84
88
|
__VOVK_DEV_HTTPS_FLAG__?: 'true' | 'false';
|
|
85
89
|
__VOVK_EXIT__?: 'true' | 'false';
|
|
90
|
+
__VOVK_LOG_LEVEL__?: LogLevelNames;
|
|
86
91
|
};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
<% const vars = {
|
|
2
|
+
ModuleName: t.TheThing + 'Controller',
|
|
3
|
+
ServiceName: t.TheThing + 'Service',
|
|
4
|
+
}; %>
|
|
5
|
+
---
|
|
6
|
+
dir: <%= t.defaultDir %>
|
|
7
|
+
fileName: <%= vars.ModuleName + '.ts' %>
|
|
8
|
+
sourceName: <%= vars.ModuleName %>
|
|
9
|
+
compiledName: <%= t.TheThing + 'RPC' %>
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
import { prefix, get, put, post, del, openapi } from 'vovk';
|
|
13
|
+
import { type } from 'arktype';
|
|
14
|
+
import withArk from '@/lib/withArk<%= t.nodeNextResolutionExt.ts %>';
|
|
15
|
+
<% if(t.withService) { %>
|
|
16
|
+
import <%= vars.ServiceName %> from './<%= vars.ServiceName %><%= t.nodeNextResolutionExt.ts %>';
|
|
17
|
+
<% } %>
|
|
18
|
+
|
|
19
|
+
@prefix('<%= t['the-things'] %>')
|
|
20
|
+
export default class <%= vars.ModuleName %> {
|
|
21
|
+
@openapi({
|
|
22
|
+
summary: 'Get <%= t.TheThings %>',
|
|
23
|
+
})
|
|
24
|
+
@get()
|
|
25
|
+
static get<%= t.TheThings %> = withArk({
|
|
26
|
+
query: type({ search: type('string') }),
|
|
27
|
+
handle(req) {
|
|
28
|
+
const search = req.nextUrl.searchParams.get('search');
|
|
29
|
+
<% if(t.withService) { %>
|
|
30
|
+
return <%= vars.ServiceName %>.get<%= t.TheThings %>(search);
|
|
31
|
+
<% } else { %>
|
|
32
|
+
return { results: [], search };
|
|
33
|
+
<% } %>
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
@openapi({
|
|
38
|
+
summary: 'Update <%= t.TheThing %>',
|
|
39
|
+
})
|
|
40
|
+
@put('{id}')
|
|
41
|
+
static update<%= t.TheThing %> = withArk({
|
|
42
|
+
body: type({
|
|
43
|
+
foo: type('"bar" | "baz"'),
|
|
44
|
+
}),
|
|
45
|
+
query: type({ q: type('string') }),
|
|
46
|
+
params: type({ id: type('string') }),
|
|
47
|
+
async handle(req, params) {
|
|
48
|
+
const { id } = params;
|
|
49
|
+
const body = await req.json();
|
|
50
|
+
const q = req.nextUrl.searchParams.get('q');
|
|
51
|
+
<% if(t.withService) { %>
|
|
52
|
+
return <%= vars.ServiceName %>.update<%= t.TheThing %>(id, q, body);
|
|
53
|
+
<% } else { %>
|
|
54
|
+
return { id, body, q };
|
|
55
|
+
<% } %>
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
@post()
|
|
60
|
+
static create<%= t.TheThing %> = () => {
|
|
61
|
+
// ...
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
@del(':id')
|
|
65
|
+
static delete<%= t.TheThing %> = () => {
|
|
66
|
+
// ...
|
|
67
|
+
};
|
|
68
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
<% const vars = {
|
|
2
|
+
ModuleName: t.TheThing + 'Controller',
|
|
3
|
+
ServiceName: t.TheThing + 'Service',
|
|
4
|
+
}; %>
|
|
5
|
+
---
|
|
6
|
+
dir: <%= t.defaultDir %>
|
|
7
|
+
fileName: <%= vars.ModuleName + '.ts' %>
|
|
8
|
+
sourceName: <%= vars.ModuleName %>
|
|
9
|
+
compiledName: <%= t.TheThing + 'RPC' %>
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
import { prefix, get, put, post, del, openapi } from 'vovk';
|
|
13
|
+
import * as v from 'valibot';
|
|
14
|
+
import withValibot from '@/lib/withValibot<%= t.nodeNextResolutionExt.ts %>';
|
|
15
|
+
<% if(t.withService) { %>
|
|
16
|
+
import <%= vars.ServiceName %> from './<%= vars.ServiceName %><%= t.nodeNextResolutionExt.ts %>';
|
|
17
|
+
<% } %>
|
|
18
|
+
|
|
19
|
+
@prefix('<%= t['the-things'] %>')
|
|
20
|
+
export default class <%= vars.ModuleName %> {
|
|
21
|
+
@openapi({
|
|
22
|
+
summary: 'Get <%= t.TheThings %>',
|
|
23
|
+
})
|
|
24
|
+
@get()
|
|
25
|
+
static get<%= t.TheThings %> = withValibot({
|
|
26
|
+
query: v.object({ search: v.string() }),
|
|
27
|
+
handle(req) {
|
|
28
|
+
const search = req.nextUrl.searchParams.get('search');
|
|
29
|
+
<% if(t.withService) { %>
|
|
30
|
+
return <%= vars.ServiceName %>.get<%= t.TheThings %>(search);
|
|
31
|
+
<% } else { %>
|
|
32
|
+
return { results: [], search };
|
|
33
|
+
<% } %>
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
@openapi({
|
|
38
|
+
summary: 'Update <%= t.TheThing %>',
|
|
39
|
+
})
|
|
40
|
+
@put('{id}')
|
|
41
|
+
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() }),
|
|
46
|
+
params: v.object({ id: v.string() }),
|
|
47
|
+
async handle(req, params) {
|
|
48
|
+
const { id } = params;
|
|
49
|
+
const body = await req.json();
|
|
50
|
+
const q = req.nextUrl.searchParams.get('q');
|
|
51
|
+
<% if(t.withService) { %>
|
|
52
|
+
return <%= vars.ServiceName %>.update<%= t.TheThing %>(id, q, body);
|
|
53
|
+
<% } else { %>
|
|
54
|
+
return { id, body, q };
|
|
55
|
+
<% } %>
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
@post()
|
|
60
|
+
static create<%= t.TheThing %> = () => {
|
|
61
|
+
// ...
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
@del(':id')
|
|
65
|
+
static delete<%= t.TheThing %> = () => {
|
|
66
|
+
// ...
|
|
67
|
+
};
|
|
68
|
+
}
|
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.334",
|
|
4
4
|
"bin": {
|
|
5
5
|
"vovk": "./dist/index.mjs"
|
|
6
6
|
},
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
},
|
|
36
36
|
"homepage": "https://vovk.dev",
|
|
37
37
|
"peerDependencies": {
|
|
38
|
-
"vovk": "^3.0.0-draft.
|
|
38
|
+
"vovk": "^3.0.0-draft.396"
|
|
39
39
|
},
|
|
40
40
|
"optionalDependencies": {
|
|
41
41
|
"@rolldown/binding-linux-x64-gnu": "1.0.0-beta.31"
|
|
File without changes
|
|
File without changes
|