vovk-cli 0.2.0 → 0.3.0-beta.0
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/CHANGELOG.md +38 -0
- package/client-templates/schema-ts/schema.ts.ejs +1 -1
- package/client-templates/ts-base/index.ts.ejs +1 -1
- package/dist/bundle/index.mjs +64 -42
- package/dist/dev/diff-segment-schema.d.mts +0 -17
- package/dist/dev/diff-segment-schema.mjs +1 -17
- package/dist/dev/ensure-schema-files.mjs +28 -10
- package/dist/dev/index.mjs +19 -13
- package/dist/dev/log-diff-result.d.mts +1 -1
- package/dist/dev/log-diff-result.mjs +1 -1
- package/dist/dev/write-meta-json.mjs +2 -2
- package/dist/dev/write-one-segment-schema-file.mjs +7 -2
- package/dist/generate/ensure-client.mjs +1 -1
- package/dist/generate/generate.mjs +38 -25
- package/dist/generate/get-client-template-files.mjs +8 -4
- package/dist/generate/get-project-full-schema.d.mts +1 -1
- package/dist/generate/get-project-full-schema.mjs +2 -2
- package/dist/generate/index.d.mts +2 -2
- package/dist/generate/index.mjs +46 -34
- package/dist/generate/write-one-client-file.d.mts +3 -3
- package/dist/generate/write-one-client-file.mjs +8 -6
- package/dist/get-project-info/get-config/get-relative-src-root.mjs +1 -1
- package/dist/get-project-info/get-config/get-template-defs.d.mts +20 -23
- package/dist/get-project-info/get-config/get-template-defs.mjs +21 -47
- package/dist/get-project-info/get-config/get-user-config.mjs +1 -1
- package/dist/get-project-info/get-config/index.d.mts +1 -1
- package/dist/get-project-info/get-config/index.mjs +15 -10
- package/dist/get-project-info/get-meta-schema.d.mts +1 -1
- package/dist/get-project-info/get-meta-schema.mjs +1 -1
- package/dist/get-project-info/index.mjs +2 -2
- package/dist/index.mjs +25 -16
- package/dist/init/check-tsconfig-for-experimental-decorators.mjs +1 -1
- package/dist/init/create-config.d.mts +1 -1
- package/dist/init/create-config.mjs +5 -5
- package/dist/init/index.d.mts +1 -1
- package/dist/init/index.mjs +49 -17
- package/dist/init/install-dependencies.d.mts +2 -1
- package/dist/init/install-dependencies.mjs +10 -2
- package/dist/init/update-dependencies-without-installing.d.mts +1 -1
- package/dist/init/update-dependencies-without-installing.mjs +0 -1
- package/dist/init/update-gitignore.d.mts +2 -0
- package/dist/init/update-gitignore.mjs +20 -0
- package/dist/init/update-typescript-config.mjs +1 -1
- package/dist/new/index.d.mts +1 -1
- package/dist/new/new-module.mjs +11 -16
- package/dist/new/new-segment.mjs +9 -4
- package/dist/new/render.mjs +1 -1
- package/dist/types.d.mts +1 -1
- package/dist/utils/compile-json-schema-to-typescript-type.d.mts +1 -1
- package/dist/utils/compile-ts.mjs +1 -1
- package/dist/utils/generate-fn-name.d.mts +0 -9
- package/dist/utils/generate-fn-name.mjs +2 -9
- package/dist/utils/generated-banner.d.mts +1 -0
- package/dist/utils/generated-banner.mjs +3 -0
- package/dist/utils/get-available-port.d.mts +0 -8
- package/dist/utils/get-available-port.mjs +2 -14
- package/dist/utils/get-file-system-entry-type.d.mts +5 -4
- package/dist/utils/get-file-system-entry-type.mjs +5 -5
- package/dist/utils/normalize-openapi-mixin.d.mts +1 -1
- package/dist/utils/normalize-openapi-mixin.mjs +18 -3
- package/dist/utils/prettify.d.mts +4 -0
- package/dist/utils/prettify.mjs +39 -3
- package/dist/utils/remove-unlisted-directories.d.mts +1 -9
- package/dist/utils/remove-unlisted-directories.mjs +60 -21
- package/dist/utils/resolve-absolute-module-path.mjs +1 -2
- package/dist/utils/update-config-property.mjs +1 -1
- package/package.json +23 -30
- package/client-templates/js-base/index.d.ts.ejs +0 -21
- package/client-templates/js-base/index.js.ejs +0 -18
- package/client-templates/openapi-js/openapi.d.ts.ejs +0 -4
- package/client-templates/openapi-js/openapi.js.ejs +0 -4
- package/client-templates/schema-js/schema.d.ts.ejs +0 -10
- package/client-templates/schema-js/schema.js.ejs +0 -29
package/dist/generate/index.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import * as chokidar from 'chokidar';
|
|
3
|
-
import { getProjectFullSchema } from './get-project-full-schema.mjs';
|
|
4
|
-
import { generate } from './generate.mjs';
|
|
5
|
-
import { locateSegments } from '../utils/locate-segments.mjs';
|
|
6
3
|
import { chalkHighlightThing } from '../utils/chalk-highlight-thing.mjs';
|
|
4
|
+
import { locateSegments } from '../utils/locate-segments.mjs';
|
|
5
|
+
import { generate } from './generate.mjs';
|
|
6
|
+
import { getProjectFullSchema } from './get-project-full-schema.mjs';
|
|
7
7
|
const THROTTLE_DELAY = 5000;
|
|
8
8
|
export class VovkGenerate {
|
|
9
9
|
#cliGenerateOptions;
|
|
@@ -19,10 +19,10 @@ export class VovkGenerate {
|
|
|
19
19
|
if (watch) {
|
|
20
20
|
const throttleDelay = typeof watch === 'boolean' ? THROTTLE_DELAY : parseFloat(watch) * 1e3 || THROTTLE_DELAY;
|
|
21
21
|
this.watch({ throttleDelay });
|
|
22
|
+
return;
|
|
22
23
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
24
|
+
// return the promise so one-shot generate errors reach the CLI error handler
|
|
25
|
+
return this.generate();
|
|
26
26
|
}
|
|
27
27
|
async generate() {
|
|
28
28
|
const fullSchema = await this.getFullSchema();
|
|
@@ -63,6 +63,17 @@ export class VovkGenerate {
|
|
|
63
63
|
watchSchema({ schemaPath, throttleDelay }) {
|
|
64
64
|
const { log } = this.#projectInfo;
|
|
65
65
|
let lastGenerationTime = 0;
|
|
66
|
+
let pendingTimer = null;
|
|
67
|
+
const generateCode = async () => {
|
|
68
|
+
try {
|
|
69
|
+
lastGenerationTime = Date.now();
|
|
70
|
+
await this.generate();
|
|
71
|
+
log.debug(`Regenerated from schema changes`);
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
log.error(`Failed to regenerate from schema: ${error instanceof Error ? error.message : String(error)}`);
|
|
75
|
+
}
|
|
76
|
+
};
|
|
66
77
|
chokidar
|
|
67
78
|
.watch(schemaPath, {
|
|
68
79
|
persistent: true,
|
|
@@ -72,20 +83,15 @@ export class VovkGenerate {
|
|
|
72
83
|
if (event === 'change' || event === 'add' || event === 'ready' || event === 'unlink') {
|
|
73
84
|
log.debug(`Schema file ${event}: ${path}`);
|
|
74
85
|
const now = Date.now();
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
85
|
-
};
|
|
86
|
-
// Generate immediately if it's been a while since the last generation
|
|
87
|
-
if (shouldGenerateImmediately) {
|
|
88
|
-
generateCode();
|
|
86
|
+
// generate immediately outside the throttle window, otherwise defer to the end of it
|
|
87
|
+
if (now - lastGenerationTime > throttleDelay) {
|
|
88
|
+
void generateCode();
|
|
89
|
+
}
|
|
90
|
+
else if (!pendingTimer) {
|
|
91
|
+
pendingTimer = setTimeout(() => {
|
|
92
|
+
pendingTimer = null;
|
|
93
|
+
void generateCode();
|
|
94
|
+
}, throttleDelay - (now - lastGenerationTime));
|
|
89
95
|
}
|
|
90
96
|
}
|
|
91
97
|
});
|
|
@@ -111,6 +117,17 @@ export class VovkGenerate {
|
|
|
111
117
|
watchOpenApiSpecLocal({ openApiSpecPaths, throttleDelay }) {
|
|
112
118
|
const { log, cwd } = this.#projectInfo;
|
|
113
119
|
let lastGenerationTime = 0;
|
|
120
|
+
let pendingTimer = null;
|
|
121
|
+
const generateCode = async () => {
|
|
122
|
+
try {
|
|
123
|
+
lastGenerationTime = Date.now();
|
|
124
|
+
await this.generate();
|
|
125
|
+
log.debug(`Regenerated from OpenAPI spec changes`);
|
|
126
|
+
}
|
|
127
|
+
catch (error) {
|
|
128
|
+
log.error(`Failed to regenerate from OpenAPI spec: ${error instanceof Error ? error.message : String(error)}`);
|
|
129
|
+
}
|
|
130
|
+
};
|
|
114
131
|
chokidar
|
|
115
132
|
.watch(openApiSpecPaths, {
|
|
116
133
|
cwd,
|
|
@@ -121,20 +138,15 @@ export class VovkGenerate {
|
|
|
121
138
|
if (event === 'change' || event === 'add' || event === 'ready' || event === 'unlink') {
|
|
122
139
|
log.debug(`OpenAPI spec file changed: ${path}`);
|
|
123
140
|
const now = Date.now();
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
}
|
|
134
|
-
};
|
|
135
|
-
// Generate immediately if it's been a while since the last generation
|
|
136
|
-
if (shouldGenerateImmediately) {
|
|
137
|
-
generateCode();
|
|
141
|
+
// generate immediately outside the throttle window, otherwise defer to the end of it
|
|
142
|
+
if (now - lastGenerationTime > throttleDelay) {
|
|
143
|
+
void generateCode();
|
|
144
|
+
}
|
|
145
|
+
else if (!pendingTimer) {
|
|
146
|
+
pendingTimer = setTimeout(() => {
|
|
147
|
+
pendingTimer = null;
|
|
148
|
+
void generateCode();
|
|
149
|
+
}, throttleDelay - (now - lastGenerationTime));
|
|
138
150
|
}
|
|
139
151
|
}
|
|
140
152
|
});
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
+
import type { OpenAPIObject } from 'openapi3-ts/oas31';
|
|
2
|
+
import type { PackageJson } from 'type-fest';
|
|
1
3
|
import type { VovkSchema } from 'vovk';
|
|
2
4
|
import { type VovkReadmeConfig, type VovkSamplesConfig, type VovkStrictConfig } from 'vovk/internal';
|
|
3
|
-
import type { PackageJson } from 'type-fest';
|
|
4
|
-
import type { OpenAPIObject } from 'openapi3-ts/oas31';
|
|
5
5
|
import type { ProjectInfo } from '../get-project-info/index.mjs';
|
|
6
|
-
import type { ClientTemplateFile } from './get-client-template-files.mjs';
|
|
7
6
|
import type { Segment } from '../utils/locate-segments.mjs';
|
|
7
|
+
import type { ClientTemplateFile } from './get-client-template-files.mjs';
|
|
8
8
|
export declare function normalizeOutTemplatePath(out: string, packageJson: PackageJson): string;
|
|
9
9
|
export declare function writeOneClientFile({ cwd, projectInfo, clientTemplateFile, fullSchema, prettifyClient, segmentName, templateContent, matterResult: { data, content }, openAPIObject, package: packageJson, readme, samples, reExports, isEnsuringClient, outCwdRelativeDir, templateDef, locatedSegments, isNodeNextResolution, hasMixins, isVovkProject, vovkCliPackage, isBundle, origin, configKey, cliSchemaPath, projectConfig, }: {
|
|
10
10
|
cwd: string;
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import fs from 'node:fs/promises';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
+
import TOML from '@iarna/toml';
|
|
3
4
|
import ejs from 'ejs';
|
|
4
5
|
import _ from 'lodash';
|
|
5
|
-
import * as YAML from 'yaml';
|
|
6
|
-
import TOML from '@iarna/toml';
|
|
7
6
|
import { createCodeSamples, reattachMixinDefs, VovkSchemaIdEnum, } from 'vovk/internal';
|
|
7
|
+
import * as YAML from 'yaml';
|
|
8
|
+
import { ROOT_SEGMENT_FILE_NAME } from '../dev/write-one-segment-schema-file.mjs';
|
|
9
|
+
import { chalkHighlightThing } from '../utils/chalk-highlight-thing.mjs';
|
|
8
10
|
import { compileJSONSchemaToTypeScriptType } from '../utils/compile-json-schema-to-typescript-type.mjs';
|
|
11
|
+
import { GENERATED_BANNER_PREFIX } from '../utils/generated-banner.mjs';
|
|
12
|
+
import { prettify, warnIfPrettierMissing } from '../utils/prettify.mjs';
|
|
9
13
|
import { getTemplateClientImports } from './get-template-client-imports.mjs';
|
|
10
|
-
import { chalkHighlightThing } from '../utils/chalk-highlight-thing.mjs';
|
|
11
|
-
import { ROOT_SEGMENT_FILE_NAME } from '../dev/write-one-segment-schema-file.mjs';
|
|
12
|
-
import { prettify } from '../utils/prettify.mjs';
|
|
13
14
|
export function normalizeOutTemplatePath(out, packageJson) {
|
|
14
15
|
return out.replace('[package_name]', packageJson.name?.replace(/-/g, '_') ?? 'my_package_name');
|
|
15
16
|
}
|
|
@@ -27,7 +28,7 @@ templateContent, matterResult: { data, content }, openAPIObject, package: packag
|
|
|
27
28
|
// Feel free to report an issue at https://github.com/finom/vovk/issues`;
|
|
28
29
|
placeholder = outPath.endsWith('.py') ? placeholder.replace(/\/\//g, '#') : placeholder;
|
|
29
30
|
const getFirstLineBanner = (type = 'c') => {
|
|
30
|
-
const text =
|
|
31
|
+
const text = `${GENERATED_BANNER_PREFIX} v${vovkCliPackage.version} at ${new Date().toISOString()}`;
|
|
31
32
|
switch (type) {
|
|
32
33
|
case 'html':
|
|
33
34
|
return `<!-- ${text} -->`;
|
|
@@ -130,6 +131,7 @@ templateContent, matterResult: { data, content }, openAPIObject, package: packag
|
|
|
130
131
|
: templateContent;
|
|
131
132
|
// Optionally prettify
|
|
132
133
|
if (prettifyClient) {
|
|
134
|
+
await warnIfPrettierMissing(log);
|
|
133
135
|
rendered = await prettify(rendered, outPath);
|
|
134
136
|
}
|
|
135
137
|
if (isEnsuringClient) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
|
-
import {
|
|
2
|
+
import { FileSystemEntryType, getFileSystemEntryType } from '../../utils/get-file-system-entry-type.mjs';
|
|
3
3
|
export async function getRelativeSrcRoot({ cwd }) {
|
|
4
4
|
// Next.js Docs: src/app or src/pages will be ignored if app or pages are present in the root directory.
|
|
5
5
|
if ((await getFileSystemEntryType(path.join(cwd, 'app'))) === FileSystemEntryType.DIRECTORY) {
|
|
@@ -1,25 +1,22 @@
|
|
|
1
1
|
import type { VovkStrictConfig } from 'vovk/internal';
|
|
2
|
-
export declare
|
|
3
|
-
tsBase
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
pyReadme = "pyReadme",
|
|
23
|
-
py = "py"
|
|
24
|
-
}
|
|
2
|
+
export declare const BuiltInTemplateName: {
|
|
3
|
+
readonly tsBase: "tsBase";
|
|
4
|
+
readonly ts: "ts";
|
|
5
|
+
readonly schemaTs: "schemaTs";
|
|
6
|
+
readonly schemaJson: "schemaJson";
|
|
7
|
+
readonly openapiTs: "openapiTs";
|
|
8
|
+
readonly openapiJson: "openapiJson";
|
|
9
|
+
readonly readme: "readme";
|
|
10
|
+
readonly packageJson: "packageJson";
|
|
11
|
+
readonly mixins: "mixins";
|
|
12
|
+
readonly rsSrc: "rsSrc";
|
|
13
|
+
readonly rsPkg: "rsPkg";
|
|
14
|
+
readonly rsReadme: "rsReadme";
|
|
15
|
+
readonly rs: "rs";
|
|
16
|
+
readonly pySrc: "pySrc";
|
|
17
|
+
readonly pyPkg: "pyPkg";
|
|
18
|
+
readonly pyReadme: "pyReadme";
|
|
19
|
+
readonly py: "py";
|
|
20
|
+
};
|
|
21
|
+
export type BuiltInTemplateName = (typeof BuiltInTemplateName)[keyof typeof BuiltInTemplateName];
|
|
25
22
|
export declare function getTemplateDefs(userTemplateDefs?: VovkStrictConfig['clientTemplateDefs']): VovkStrictConfig['clientTemplateDefs'];
|
|
@@ -1,32 +1,28 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
// ts
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
BuiltInTemplateName["ts"] = "ts";
|
|
7
|
-
BuiltInTemplateName["js"] = "js";
|
|
1
|
+
// const object instead of enum, node 26 runs ts with erasable syntax only
|
|
2
|
+
export const BuiltInTemplateName = {
|
|
3
|
+
// ts
|
|
4
|
+
tsBase: 'tsBase',
|
|
5
|
+
ts: 'ts',
|
|
8
6
|
// schema
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
BuiltInTemplateName["schemaJson"] = "schemaJson";
|
|
7
|
+
schemaTs: 'schemaTs',
|
|
8
|
+
schemaJson: 'schemaJson',
|
|
12
9
|
// openapi
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
BuiltInTemplateName["openapiJson"] = "openapiJson";
|
|
10
|
+
openapiTs: 'openapiTs',
|
|
11
|
+
openapiJson: 'openapiJson',
|
|
16
12
|
// misc
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
13
|
+
readme: 'readme',
|
|
14
|
+
packageJson: 'packageJson',
|
|
15
|
+
mixins: 'mixins',
|
|
20
16
|
// other languages (packages installed separately)
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
17
|
+
rsSrc: 'rsSrc',
|
|
18
|
+
rsPkg: 'rsPkg',
|
|
19
|
+
rsReadme: 'rsReadme',
|
|
20
|
+
rs: 'rs',
|
|
21
|
+
pySrc: 'pySrc',
|
|
22
|
+
pyPkg: 'pyPkg',
|
|
23
|
+
pyReadme: 'pyReadme',
|
|
24
|
+
py: 'py',
|
|
25
|
+
};
|
|
30
26
|
export function getTemplateDefs(userTemplateDefs = {}) {
|
|
31
27
|
const defs = {};
|
|
32
28
|
const builtInDefs = {
|
|
@@ -36,12 +32,6 @@ export function getTemplateDefs(userTemplateDefs = {}) {
|
|
|
36
32
|
[BuiltInTemplateName.openapiJson]: './',
|
|
37
33
|
},
|
|
38
34
|
},
|
|
39
|
-
[BuiltInTemplateName.openapiJs]: {
|
|
40
|
-
templatePath: 'vovk-cli/client-templates/openapi-js/',
|
|
41
|
-
requires: {
|
|
42
|
-
[BuiltInTemplateName.openapiJson]: './',
|
|
43
|
-
},
|
|
44
|
-
},
|
|
45
35
|
[BuiltInTemplateName.openapiJson]: {
|
|
46
36
|
templatePath: 'vovk-cli/client-templates/openapi-json/',
|
|
47
37
|
},
|
|
@@ -52,31 +42,15 @@ export function getTemplateDefs(userTemplateDefs = {}) {
|
|
|
52
42
|
[BuiltInTemplateName.mixins]: './', // used conditionally if OpenAPI mixins are used
|
|
53
43
|
},
|
|
54
44
|
},
|
|
55
|
-
[BuiltInTemplateName.jsBase]: {
|
|
56
|
-
templatePath: 'vovk-cli/client-templates/js-base/',
|
|
57
|
-
requires: {
|
|
58
|
-
[BuiltInTemplateName.schemaJs]: './',
|
|
59
|
-
[BuiltInTemplateName.mixins]: './', // used conditionally if OpenAPI mixins are used
|
|
60
|
-
},
|
|
61
|
-
},
|
|
62
45
|
[BuiltInTemplateName.ts]: {
|
|
63
46
|
requires: {
|
|
64
47
|
[BuiltInTemplateName.tsBase]: './',
|
|
65
48
|
[BuiltInTemplateName.openapiTs]: './',
|
|
66
49
|
},
|
|
67
50
|
},
|
|
68
|
-
[BuiltInTemplateName.js]: {
|
|
69
|
-
requires: {
|
|
70
|
-
[BuiltInTemplateName.jsBase]: './',
|
|
71
|
-
[BuiltInTemplateName.openapiJs]: './',
|
|
72
|
-
},
|
|
73
|
-
},
|
|
74
51
|
[BuiltInTemplateName.schemaTs]: {
|
|
75
52
|
templatePath: 'vovk-cli/client-templates/schema-ts/',
|
|
76
53
|
},
|
|
77
|
-
[BuiltInTemplateName.schemaJs]: {
|
|
78
|
-
templatePath: 'vovk-cli/client-templates/schema-js/',
|
|
79
|
-
},
|
|
80
54
|
[BuiltInTemplateName.schemaJson]: {
|
|
81
55
|
templatePath: 'vovk-cli/client-templates/schema-json/',
|
|
82
56
|
},
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { pathToFileURL } from 'node:url';
|
|
2
1
|
import { readFile } from 'node:fs/promises';
|
|
3
2
|
import { createRequire } from 'node:module';
|
|
4
3
|
import { dirname, extname } from 'node:path';
|
|
4
|
+
import { pathToFileURL } from 'node:url';
|
|
5
5
|
import vm from 'node:vm';
|
|
6
6
|
import { getConfigAbsolutePaths } from './get-config-absolute-paths.mjs';
|
|
7
7
|
const isVMModulesEnabled = typeof vm.SourceTextModule !== 'undefined';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import type { LogLevelNames } from 'loglevel';
|
|
1
2
|
import type { VovkConfig } from 'vovk';
|
|
2
3
|
import { type VovkStrictConfig } from 'vovk/internal';
|
|
3
|
-
import type { LogLevelNames } from 'loglevel';
|
|
4
4
|
import { getLogger } from '../../utils/get-logger.mjs';
|
|
5
5
|
export declare function getConfig({ configPath, cwd, logLevel, }: {
|
|
6
6
|
configPath?: string;
|
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import { VovkSchemaIdEnum } from 'vovk/internal';
|
|
3
|
+
import { chalkHighlightThing } from '../../utils/chalk-highlight-thing.mjs';
|
|
3
4
|
import { getLogger } from '../../utils/get-logger.mjs';
|
|
4
|
-
import { getUserConfig } from './get-user-config.mjs';
|
|
5
|
-
import { getRelativeSrcRoot } from './get-relative-src-root.mjs';
|
|
6
|
-
import { getTemplateDefs, BuiltInTemplateName } from './get-template-defs.mjs';
|
|
7
5
|
import { normalizeOpenAPIMixin } from '../../utils/normalize-openapi-mixin.mjs';
|
|
8
|
-
import {
|
|
6
|
+
import { getRelativeSrcRoot } from './get-relative-src-root.mjs';
|
|
7
|
+
import { BuiltInTemplateName, getTemplateDefs } from './get-template-defs.mjs';
|
|
8
|
+
import { getUserConfig } from './get-user-config.mjs';
|
|
9
9
|
export async function getConfig({ configPath, cwd, logLevel, }) {
|
|
10
10
|
const { configAbsolutePaths, error, userConfig } = await getUserConfig({
|
|
11
11
|
configPath,
|
|
12
12
|
cwd,
|
|
13
13
|
});
|
|
14
|
+
// a config that exists but fails to load must not be silently replaced by defaults
|
|
15
|
+
if (!userConfig && configAbsolutePaths.length) {
|
|
16
|
+
throw new Error(`Failed to load config file at ${chalkHighlightThing(configAbsolutePaths[0])}. ${error?.message ?? 'Unknown error'}`);
|
|
17
|
+
}
|
|
14
18
|
const conf = userConfig ?? {};
|
|
15
19
|
logLevel = logLevel ?? conf.logLevel ?? 'info';
|
|
16
20
|
const log = getLogger(logLevel);
|
|
@@ -24,9 +28,9 @@ export async function getConfig({ configPath, cwd, logLevel, }) {
|
|
|
24
28
|
composedClient: {
|
|
25
29
|
...conf.composedClient,
|
|
26
30
|
enabled: conf.composedClient?.enabled ?? true,
|
|
27
|
-
fromTemplates: conf.composedClient?.fromTemplates ?? [BuiltInTemplateName.
|
|
28
|
-
outDir: conf.composedClient?.outDir ?? '
|
|
29
|
-
prettifyClient: conf.composedClient?.prettifyClient ??
|
|
31
|
+
fromTemplates: conf.composedClient?.fromTemplates ?? [BuiltInTemplateName.ts],
|
|
32
|
+
outDir: conf.composedClient?.outDir ?? path.join(srcRoot ?? '.', 'client'),
|
|
33
|
+
prettifyClient: conf.composedClient?.prettifyClient ?? true,
|
|
30
34
|
},
|
|
31
35
|
segmentedClient: {
|
|
32
36
|
...conf.segmentedClient,
|
|
@@ -45,9 +49,10 @@ export async function getConfig({ configPath, cwd, logLevel, }) {
|
|
|
45
49
|
},
|
|
46
50
|
outputConfig: {},
|
|
47
51
|
build: conf.bundle?.build ??
|
|
48
|
-
|
|
52
|
+
// isMissingBuild lets the bundle command fail fast before doing any work
|
|
53
|
+
Object.assign(() => {
|
|
49
54
|
throw new Error('No bundle.build function specified');
|
|
50
|
-
}),
|
|
55
|
+
}, { isMissingBuild: true }),
|
|
51
56
|
...conf.bundle,
|
|
52
57
|
},
|
|
53
58
|
modulesDir: conf.modulesDir ?? path.join(srcRoot ?? '.', 'modules'),
|
|
@@ -86,7 +91,7 @@ export async function getConfig({ configPath, cwd, logLevel, }) {
|
|
|
86
91
|
config.exposeConfigKeys = conf.exposeConfigKeys;
|
|
87
92
|
} // else it's false and exposeConfigKeys already is []
|
|
88
93
|
if (!userConfig) {
|
|
89
|
-
log.warn(`
|
|
94
|
+
log.warn(`No config file found at ${chalkHighlightThing(`${cwd}/`)}. Using default values.`);
|
|
90
95
|
}
|
|
91
96
|
return { config, srcRoot, configAbsolutePaths, userConfig, log };
|
|
92
97
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
1
2
|
import path from 'node:path';
|
|
2
|
-
import { getConfig } from './get-config/index.mjs';
|
|
3
3
|
import { getPackageJson } from '../utils/get-package-json.mjs';
|
|
4
|
-
import {
|
|
4
|
+
import { getConfig } from './get-config/index.mjs';
|
|
5
5
|
export async function getProjectInfo({ port: givenPort, cwd = process.cwd(), configPath, srcRootRequired = true, logLevel, } = {
|
|
6
6
|
logLevel: 'info',
|
|
7
7
|
}) {
|
package/dist/index.mjs
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env -S node --experimental-vm-modules --disable-warning=ExperimentalWarning
|
|
2
|
-
import path from 'node:path';
|
|
3
2
|
import { readFileSync } from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
4
|
import 'dotenv/config';
|
|
5
5
|
import { Command } from 'commander';
|
|
6
6
|
import concurrently from 'concurrently';
|
|
7
|
-
import { getAvailablePort } from './utils/get-available-port.mjs';
|
|
8
|
-
import { getProjectInfo } from './get-project-info/index.mjs';
|
|
9
|
-
import { VovkGenerate } from './generate/index.mjs';
|
|
10
7
|
import { bundle } from './bundle/index.mjs';
|
|
11
8
|
import { VovkDev } from './dev/index.mjs';
|
|
12
|
-
import { newComponents } from './new/index.mjs';
|
|
13
9
|
import { getProjectFullSchema } from './generate/get-project-full-schema.mjs';
|
|
10
|
+
import { VovkGenerate } from './generate/index.mjs';
|
|
11
|
+
import { getProjectInfo } from './get-project-info/index.mjs';
|
|
12
|
+
import { newComponents } from './new/index.mjs';
|
|
13
|
+
import { getAvailablePort } from './utils/get-available-port.mjs';
|
|
14
14
|
import { Init } from './init/index.mjs';
|
|
15
15
|
const program = new Command();
|
|
16
16
|
const vovkCliPackage = JSON.parse(readFileSync(path.join(import.meta.dirname, '../package.json'), 'utf-8'));
|
|
@@ -31,13 +31,11 @@ program
|
|
|
31
31
|
const PORT = !nextDev
|
|
32
32
|
? process.env.PORT
|
|
33
33
|
: process.env.PORT ||
|
|
34
|
-
(await getAvailablePort(3000, portAttempts, 0, (failedPort, tryingPort) =>
|
|
35
|
-
|
|
36
|
-
console.warn(`🐺 Port ${failedPort} is in use, trying ${tryingPort} instead.`)).catch(() => {
|
|
37
|
-
throw new Error(`🐺 ❌ Failed to find an available port after ${portAttempts} attempts`);
|
|
34
|
+
(await getAvailablePort(3000, portAttempts, 0, (failedPort, tryingPort) => console.warn(`🐺 Port ${failedPort} is in use, trying ${tryingPort} instead.`)).catch(() => {
|
|
35
|
+
throw new Error(`Failed to find an available port after ${portAttempts} attempts`);
|
|
38
36
|
}));
|
|
39
37
|
if (!PORT) {
|
|
40
|
-
throw new Error('
|
|
38
|
+
throw new Error('PORT env variable is required');
|
|
41
39
|
}
|
|
42
40
|
if (nextDev) {
|
|
43
41
|
const { result } = concurrently([
|
|
@@ -54,7 +52,7 @@ program
|
|
|
54
52
|
__VOVK_START_WATCHER_IN_STANDALONE_MODE__: 'true',
|
|
55
53
|
// TODO: Pass these as flags
|
|
56
54
|
__VOVK_SCHEMA_OUT_FLAG__: schemaOut ?? '',
|
|
57
|
-
__VOVK_DEV_HTTPS_FLAG__: devHttps ? 'true' : '
|
|
55
|
+
__VOVK_DEV_HTTPS_FLAG__: devHttps ? 'true' : '',
|
|
58
56
|
__VOVK_EXIT__: exit ? 'true' : 'false',
|
|
59
57
|
__VOVK_LOG_LEVEL__: logLevel ?? undefined,
|
|
60
58
|
},
|
|
@@ -67,12 +65,16 @@ program
|
|
|
67
65
|
try {
|
|
68
66
|
await result;
|
|
69
67
|
}
|
|
70
|
-
|
|
71
|
-
//
|
|
68
|
+
catch (closeEvents) {
|
|
69
|
+
// concurrently rejects with child close events on shutdown; children already logged the reason
|
|
70
|
+
const hasFailure = Array.isArray(closeEvents) &&
|
|
71
|
+
closeEvents.some((event) => typeof event?.exitCode === 'number' && event.exitCode !== 0);
|
|
72
|
+
if (hasFailure)
|
|
73
|
+
process.exit(1);
|
|
72
74
|
}
|
|
73
75
|
}
|
|
74
76
|
else {
|
|
75
|
-
|
|
77
|
+
await new VovkDev({ schemaOut, devHttps, logLevel }).start({ exit });
|
|
76
78
|
}
|
|
77
79
|
});
|
|
78
80
|
program
|
|
@@ -120,7 +122,8 @@ program
|
|
|
120
122
|
.option('--out, --out-dir <path>', 'path to output directory for bundle')
|
|
121
123
|
.option('--include, --include-segments <segments...>', 'include segments')
|
|
122
124
|
.option('--exclude, --exclude-segments <segments...>', 'exclude segments')
|
|
123
|
-
|
|
125
|
+
// the last long flag names the option, it has to stay prebundleOutDir
|
|
126
|
+
.option('--prebundle-out, --prebundle-out-dir <path>', 'path to output directory for prebundle')
|
|
124
127
|
.option('--keep-prebundle-dir', 'do not delete prebundle directory after bundling')
|
|
125
128
|
.option('--schema, --schema-path <path>', 'path to schema folder (default: .vovk-schema)')
|
|
126
129
|
.option('--config, --config-path <config>', 'path to config file')
|
|
@@ -189,7 +192,13 @@ program
|
|
|
189
192
|
.command('help')
|
|
190
193
|
.description('Show help message')
|
|
191
194
|
.action(() => program.help());
|
|
192
|
-
program.
|
|
195
|
+
program.parseAsync(process.argv).catch((error) => {
|
|
196
|
+
const logLevelFlagIndex = process.argv.indexOf('--log-level');
|
|
197
|
+
const isDebug = ['debug', 'trace'].includes(process.argv[logLevelFlagIndex + 1] ?? '');
|
|
198
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
199
|
+
console.error(`🐺 ❌ ${isDebug ? (err.stack ?? err.message) : err.message}`);
|
|
200
|
+
process.exit(1);
|
|
201
|
+
});
|
|
193
202
|
if (!process.argv.slice(2).length) {
|
|
194
203
|
program.outputHelp();
|
|
195
204
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import path from 'node:path';
|
|
2
1
|
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
3
|
import * as jsonc from 'jsonc-parser';
|
|
4
4
|
export async function checkTSConfigForExperimentalDecorators(root) {
|
|
5
5
|
const tsconfigPath = path.resolve(root, 'tsconfig.json');
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { VovkStrictConfig } from 'vovk/internal';
|
|
2
|
-
import type { getLogger } from '../utils/get-logger.mjs';
|
|
3
2
|
import type { InitOptions } from '../types.mjs';
|
|
3
|
+
import type { getLogger } from '../utils/get-logger.mjs';
|
|
4
4
|
export declare const BUNDLE_BUILD_TSDOWN: ({ entry, outDir }: Parameters<VovkStrictConfig["bundle"]["build"]>[0]) => Promise<void>;
|
|
5
5
|
export declare function createConfig({ root, options: { validationLibrary, bundle, lang, dryRun }, }: {
|
|
6
6
|
root: string;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import path from 'node:path';
|
|
2
1
|
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { FileSystemEntryType, getFileSystemEntryType } from '../utils/get-file-system-entry-type.mjs';
|
|
3
4
|
import { prettify } from '../utils/prettify.mjs';
|
|
4
|
-
import { getFileSystemEntryType, FileSystemEntryType } from '../utils/get-file-system-entry-type.mjs';
|
|
5
5
|
import { updateConfigProperty } from '../utils/update-config-property.mjs';
|
|
6
6
|
export const BUNDLE_BUILD_TSDOWN = async ({ entry, outDir }) => {
|
|
7
7
|
const { build } = await import('tsdown');
|
|
@@ -16,14 +16,14 @@ export const BUNDLE_BUILD_TSDOWN = async ({ entry, outDir }) => {
|
|
|
16
16
|
platform: 'neutral',
|
|
17
17
|
outExtensions: () => ({ js: '.js', dts: '.d.ts' }),
|
|
18
18
|
outputOptions: {
|
|
19
|
-
|
|
19
|
+
codeSplitting: false,
|
|
20
20
|
},
|
|
21
21
|
inputOptions: {
|
|
22
22
|
resolve: {
|
|
23
23
|
mainFields: ['module', 'main'],
|
|
24
24
|
},
|
|
25
25
|
},
|
|
26
|
-
|
|
26
|
+
deps: { alwaysBundle: ['!next/**'] },
|
|
27
27
|
});
|
|
28
28
|
};
|
|
29
29
|
export async function createConfig({ root, options: { validationLibrary, bundle, lang, dryRun }, }) {
|
|
@@ -55,7 +55,7 @@ export async function createConfig({ root, options: { validationLibrary, bundle,
|
|
|
55
55
|
config.outputConfig.imports.validateOnClient = 'vovk-ajv';
|
|
56
56
|
if (lang?.length) {
|
|
57
57
|
config.composedClient ??= {};
|
|
58
|
-
config.composedClient.fromTemplates = ['
|
|
58
|
+
config.composedClient.fromTemplates = ['ts', ...lang];
|
|
59
59
|
}
|
|
60
60
|
config.moduleTemplates = moduleTemplates;
|
|
61
61
|
if (bundle) {
|