vovk-cli 0.0.1-draft.96 → 0.0.1-draft.98
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/dist/dev/ensureSchemaFiles.mjs +6 -5
- package/dist/dev/index.mjs +3 -3
- package/dist/dev/writeOneSchemaFile.d.mts +3 -2
- package/dist/dev/writeOneSchemaFile.mjs +3 -2
- package/dist/generate/ensureClient.mjs +3 -3
- package/dist/generate/getClientTemplates.d.mts +5 -4
- package/dist/generate/getClientTemplates.mjs +19 -7
- package/dist/generate/index.mjs +18 -7
- package/dist/getProjectInfo/getConfig.mjs +4 -1
- package/dist/types.d.mts +10 -2
- package/package.json +2 -2
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import fs from 'node:fs/promises';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import debounce from 'lodash/debounce.js';
|
|
4
|
-
import writeOneSchemaFile, { ROOT_SEGMENT_SCHEMA_NAME } from './writeOneSchemaFile.mjs';
|
|
4
|
+
import writeOneSchemaFile, { JSON_DIR_NAME, ROOT_SEGMENT_SCHEMA_NAME } from './writeOneSchemaFile.mjs';
|
|
5
5
|
import formatLoggedSegmentName from '../utils/formatLoggedSegmentName.mjs';
|
|
6
6
|
/**
|
|
7
7
|
* Ensure that the schema files are created to avoid any import errors.
|
|
@@ -9,10 +9,11 @@ import formatLoggedSegmentName from '../utils/formatLoggedSegmentName.mjs';
|
|
|
9
9
|
export default async function ensureSchemaFiles(projectInfo, schemaOutAbsolutePath, segmentNames) {
|
|
10
10
|
const now = Date.now();
|
|
11
11
|
let hasChanged = false;
|
|
12
|
+
const schemaJsonOutAbsolutePath = path.join(schemaOutAbsolutePath, JSON_DIR_NAME);
|
|
12
13
|
const jsContent = `// auto-generated ${new Date().toISOString()}
|
|
13
14
|
${segmentNames
|
|
14
15
|
.map((segmentName) => {
|
|
15
|
-
return `module.exports['${segmentName}'] = require('./${segmentName || ROOT_SEGMENT_SCHEMA_NAME}.json');`;
|
|
16
|
+
return `module.exports['${segmentName}'] = require('./${JSON_DIR_NAME}/${segmentName || ROOT_SEGMENT_SCHEMA_NAME}.json');`;
|
|
16
17
|
})
|
|
17
18
|
.join('\n')}`;
|
|
18
19
|
const dTsContent = `// auto-generated ${new Date().toISOString()}
|
|
@@ -23,7 +24,7 @@ ${segmentNames.map((segmentName) => ` '${segmentName}': VovkSchema;`).join('\n'
|
|
|
23
24
|
export default fullSchema;`;
|
|
24
25
|
const tsContent = `// auto-generated ${new Date().toISOString()}
|
|
25
26
|
import type { VovkSchema } from 'vovk';
|
|
26
|
-
${segmentNames.map((segmentName, i) => `import segment${i} from './${segmentName || ROOT_SEGMENT_SCHEMA_NAME}.json';`).join('\n')}
|
|
27
|
+
${segmentNames.map((segmentName, i) => `import segment${i} from './${JSON_DIR_NAME}/${segmentName || ROOT_SEGMENT_SCHEMA_NAME}.json';`).join('\n')}
|
|
27
28
|
const fullSchema = {
|
|
28
29
|
${segmentNames.map((segmentName, i) => ` '${segmentName}': segment${i} as VovkSchema,`).join('\n')}
|
|
29
30
|
};
|
|
@@ -48,7 +49,7 @@ export default fullSchema;`;
|
|
|
48
49
|
// Create JSON files (if not exist) with name [segmentName].json (where segmentName can include /, which means the folder structure can be nested)
|
|
49
50
|
await Promise.all(segmentNames.map(async (segmentName) => {
|
|
50
51
|
const { isCreated } = await writeOneSchemaFile({
|
|
51
|
-
|
|
52
|
+
schemaJsonOutAbsolutePath,
|
|
52
53
|
schema: {
|
|
53
54
|
emitSchema: false,
|
|
54
55
|
segmentName,
|
|
@@ -90,7 +91,7 @@ export default fullSchema;`;
|
|
|
90
91
|
}));
|
|
91
92
|
}
|
|
92
93
|
// Start the recursive deletion from the root directory
|
|
93
|
-
await deleteUnnecessaryJsonFiles(
|
|
94
|
+
await deleteUnnecessaryJsonFiles(schemaJsonOutAbsolutePath);
|
|
94
95
|
if (hasChanged)
|
|
95
96
|
projectInfo?.log.info(`Created empty schema files in ${Date.now() - now}ms`);
|
|
96
97
|
}
|
package/dist/dev/index.mjs
CHANGED
|
@@ -7,7 +7,7 @@ import capitalize from 'lodash/capitalize.js';
|
|
|
7
7
|
import debounce from 'lodash/debounce.js';
|
|
8
8
|
import once from 'lodash/once.js';
|
|
9
9
|
import { debouncedEnsureSchemaFiles } from './ensureSchemaFiles.mjs';
|
|
10
|
-
import writeOneSchemaFile from './writeOneSchemaFile.mjs';
|
|
10
|
+
import writeOneSchemaFile, { JSON_DIR_NAME } from './writeOneSchemaFile.mjs';
|
|
11
11
|
import logDiffResult from './logDiffResult.mjs';
|
|
12
12
|
import ensureClient from '../generate/ensureClient.mjs';
|
|
13
13
|
import getProjectInfo from '../getProjectInfo/index.mjs';
|
|
@@ -260,7 +260,7 @@ export class VovkDev {
|
|
|
260
260
|
return;
|
|
261
261
|
}
|
|
262
262
|
log.debug(`Handling received schema from ${formatLoggedSegmentName(schema.segmentName)}`);
|
|
263
|
-
const
|
|
263
|
+
const schemaJsonOutAbsolutePath = path.join(cwd, config.schemaOutDir, JSON_DIR_NAME);
|
|
264
264
|
const segment = this.#segments.find((s) => s.segmentName === schema.segmentName);
|
|
265
265
|
if (!segment) {
|
|
266
266
|
log.warn(`Segment "${schema.segmentName}" not found`);
|
|
@@ -270,7 +270,7 @@ export class VovkDev {
|
|
|
270
270
|
if (schema.emitSchema) {
|
|
271
271
|
const now = Date.now();
|
|
272
272
|
const { diffResult } = await writeOneSchemaFile({
|
|
273
|
-
|
|
273
|
+
schemaJsonOutAbsolutePath,
|
|
274
274
|
schema,
|
|
275
275
|
skipIfExists: false,
|
|
276
276
|
});
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type { VovkSchema } from 'vovk';
|
|
2
2
|
import { type DiffResult } from './diffSchema.mjs';
|
|
3
3
|
export declare const ROOT_SEGMENT_SCHEMA_NAME = "_root";
|
|
4
|
-
export
|
|
5
|
-
|
|
4
|
+
export declare const JSON_DIR_NAME = "json";
|
|
5
|
+
export default function writeOneSchemaFile({ schemaJsonOutAbsolutePath, schema, skipIfExists, }: {
|
|
6
|
+
schemaJsonOutAbsolutePath: string;
|
|
6
7
|
schema: VovkSchema;
|
|
7
8
|
skipIfExists?: boolean;
|
|
8
9
|
}): Promise<{
|
|
@@ -3,8 +3,9 @@ import fs from 'node:fs/promises';
|
|
|
3
3
|
import diffSchema from './diffSchema.mjs';
|
|
4
4
|
import getFileSystemEntryType from '../utils/getFileSystemEntryType.mjs';
|
|
5
5
|
export const ROOT_SEGMENT_SCHEMA_NAME = '_root';
|
|
6
|
-
export
|
|
7
|
-
|
|
6
|
+
export const JSON_DIR_NAME = 'json';
|
|
7
|
+
export default async function writeOneSchemaFile({ schemaJsonOutAbsolutePath, schema, skipIfExists = false, }) {
|
|
8
|
+
const segmentPath = path.join(schemaJsonOutAbsolutePath, `${schema.segmentName || ROOT_SEGMENT_SCHEMA_NAME}.json`);
|
|
8
9
|
if (skipIfExists && (await getFileSystemEntryType(segmentPath))) {
|
|
9
10
|
try {
|
|
10
11
|
await fs.stat(segmentPath);
|
|
@@ -7,18 +7,18 @@ export default async function ensureClient({ config, cwd, log }) {
|
|
|
7
7
|
const { clientOutDirAbsolutePath, templateFiles } = getClientTemplates({
|
|
8
8
|
config,
|
|
9
9
|
cwd,
|
|
10
|
-
|
|
10
|
+
generateFrom: config.generateFrom,
|
|
11
11
|
});
|
|
12
12
|
let usedTemplateNames = [];
|
|
13
13
|
const text = `// auto-generated ${new Date().toISOString()}
|
|
14
|
-
// This is a temporary placeholder to avoid errors if client is imported before it's generated.
|
|
14
|
+
// This is a temporary placeholder to avoid compilation errors if client is imported before it's generated.
|
|
15
15
|
// If you still see this text, the client is not generated yet because of an unknown problem.
|
|
16
16
|
// Feel free to report an issue at https://github.com/finom/vovk/issues`;
|
|
17
17
|
for (const { outPath, templateName } of templateFiles) {
|
|
18
18
|
const existing = await fs.readFile(outPath, 'utf-8').catch(() => null);
|
|
19
19
|
if (!existing) {
|
|
20
20
|
await fs.mkdir(clientOutDirAbsolutePath, { recursive: true });
|
|
21
|
-
await fs.writeFile(outPath, text);
|
|
21
|
+
await fs.writeFile(outPath, outPath.endsWith('.py') ? text.replace(/\/\//g, '#') : text);
|
|
22
22
|
usedTemplateNames.push(templateName);
|
|
23
23
|
}
|
|
24
24
|
}
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { VovkStrictConfig } from '../types.mjs';
|
|
2
2
|
interface ClientTemplate {
|
|
3
3
|
templateName: string;
|
|
4
4
|
templatePath: string;
|
|
5
5
|
outPath: string;
|
|
6
|
+
fullSchema?: string | boolean;
|
|
6
7
|
}
|
|
7
|
-
export default function getClientTemplates({ config, cwd,
|
|
8
|
-
config:
|
|
8
|
+
export default function getClientTemplates({ config, cwd, generateFrom, }: {
|
|
9
|
+
config: VovkStrictConfig;
|
|
9
10
|
cwd: string;
|
|
10
|
-
|
|
11
|
+
generateFrom?: VovkStrictConfig['generateFrom'];
|
|
11
12
|
}): {
|
|
12
13
|
clientOutDirAbsolutePath: string;
|
|
13
14
|
templateFiles: ClientTemplate[];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
|
-
export default function getClientTemplates({ config, cwd,
|
|
2
|
+
export default function getClientTemplates({ config, cwd, generateFrom = [], }) {
|
|
3
3
|
const templatesDir = path.join(import.meta.dirname, '../..', 'client-templates');
|
|
4
4
|
const clientOutDirAbsolutePath = path.resolve(cwd, config.clientOutDir);
|
|
5
5
|
const mapper = (dir) => (name) => ({
|
|
@@ -13,16 +13,28 @@ export default function getClientTemplates({ config, cwd, templateNames = [], })
|
|
|
13
13
|
module: ['module.mjs.ejs', 'module.d.mts.ejs'].map(mapper('module')),
|
|
14
14
|
python: ['__init__.py'].map(mapper('python')),
|
|
15
15
|
};
|
|
16
|
-
const templateFiles = (
|
|
17
|
-
if (template
|
|
18
|
-
|
|
16
|
+
const templateFiles = (generateFrom ?? config.generateFrom).reduce((acc, template) => {
|
|
17
|
+
if (typeof template === 'string') {
|
|
18
|
+
if (template in builtInTemplatesMap) {
|
|
19
|
+
return [...acc, ...builtInTemplatesMap[template]];
|
|
20
|
+
}
|
|
21
|
+
return [
|
|
22
|
+
...acc,
|
|
23
|
+
{
|
|
24
|
+
templateName: template,
|
|
25
|
+
templatePath: path.resolve(cwd, template),
|
|
26
|
+
outPath: path.join(clientOutDirAbsolutePath, path.basename(template).replace('.ejs', '')),
|
|
27
|
+
},
|
|
28
|
+
];
|
|
19
29
|
}
|
|
30
|
+
const outDirAbsolutePath = template.outDir ? path.resolve(cwd, template.outDir) : clientOutDirAbsolutePath;
|
|
20
31
|
return [
|
|
21
32
|
...acc,
|
|
22
33
|
{
|
|
23
|
-
templateName: template,
|
|
24
|
-
templatePath: path.resolve(cwd, template),
|
|
25
|
-
outPath: path.join(
|
|
34
|
+
templateName: template.templateName ?? template.templatePath,
|
|
35
|
+
templatePath: path.resolve(cwd, template.templatePath),
|
|
36
|
+
outPath: path.join(outDirAbsolutePath, path.basename(template.templatePath).replace('.ejs', '')),
|
|
37
|
+
fullSchema: template.fullSchema,
|
|
26
38
|
},
|
|
27
39
|
];
|
|
28
40
|
}, []);
|
package/dist/generate/index.mjs
CHANGED
|
@@ -7,10 +7,10 @@ import getClientTemplates from './getClientTemplates.mjs';
|
|
|
7
7
|
import chalkHighlightThing from '../utils/chalkHighlightThing.mjs';
|
|
8
8
|
import uniq from 'lodash/uniq.js';
|
|
9
9
|
export default async function generate({ projectInfo, segments, segmentsSchema, forceNothingWrittenLog, templates, prettify: prettifyClient, fullSchema, }) {
|
|
10
|
-
|
|
10
|
+
const generateFrom = templates ?? projectInfo.config.generateFrom;
|
|
11
11
|
const noClient = templates?.[0] === 'none';
|
|
12
12
|
const { config, cwd, log, clientImports, apiRoot } = projectInfo;
|
|
13
|
-
const { clientOutDirAbsolutePath, templateFiles } = getClientTemplates({ config, cwd,
|
|
13
|
+
const { clientOutDirAbsolutePath, templateFiles } = getClientTemplates({ config, cwd, generateFrom });
|
|
14
14
|
// Ensure that each segment has a matching schema if it needs to be emitted:
|
|
15
15
|
for (let i = 0; i < segments.length; i++) {
|
|
16
16
|
const { segmentName } = segments[i];
|
|
@@ -57,14 +57,25 @@ export default async function generate({ projectInfo, segments, segmentsSchema,
|
|
|
57
57
|
};
|
|
58
58
|
}));
|
|
59
59
|
const usedTemplateNames = uniq(processedTemplates.filter(({ needsWriting }) => needsWriting).map(({ templateName }) => templateName));
|
|
60
|
-
|
|
60
|
+
let fullSchemaNames = [];
|
|
61
|
+
const DEFAULT_NAME = 'full-schema.json';
|
|
62
|
+
if (fullSchema) {
|
|
63
|
+
fullSchemaNames.push(typeof fullSchema === 'string' ? fullSchema : DEFAULT_NAME);
|
|
64
|
+
fullSchemaNames.push(...templateFiles
|
|
65
|
+
.filter(({ fullSchema }) => fullSchema)
|
|
66
|
+
.map(({ fullSchema }) => (typeof fullSchema === 'string' ? fullSchema : DEFAULT_NAME)));
|
|
67
|
+
}
|
|
68
|
+
fullSchemaNames = uniq(fullSchemaNames);
|
|
69
|
+
if (fullSchemaNames.length || usedTemplateNames.length > 0) {
|
|
61
70
|
// Make sure the output directory exists
|
|
62
71
|
await fs.mkdir(clientOutDirAbsolutePath, { recursive: true });
|
|
63
72
|
}
|
|
64
|
-
if (
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
73
|
+
if (fullSchemaNames.length) {
|
|
74
|
+
await Promise.all(fullSchemaNames.map(async (name) => {
|
|
75
|
+
const fullSchemaOutAbsolutePath = path.resolve(clientOutDirAbsolutePath, name);
|
|
76
|
+
await fs.writeFile(fullSchemaOutAbsolutePath, JSON.stringify(segmentsSchema, null, 2));
|
|
77
|
+
log.info(`Full schema has ben written to ${fullSchemaOutAbsolutePath}`);
|
|
78
|
+
}));
|
|
68
79
|
}
|
|
69
80
|
if (usedTemplateNames.length === 0) {
|
|
70
81
|
const logOrDebug = forceNothingWrittenLog ? log.info : log.debug;
|
|
@@ -8,6 +8,7 @@ export default async function getConfig({ clientOutDir, cwd }) {
|
|
|
8
8
|
const validateOnClientImport = env.VOVK_VALIDATE_ON_CLIENT_PATH ?? conf.validateOnClientImport ?? null;
|
|
9
9
|
const fetcherImport = env.VOVK_FETCHER_PATH ?? conf.fetcherImport ?? 'vovk/dist/client/defaultFetcher.js';
|
|
10
10
|
const createRPCImport = env.VOVK_CREATE_RPC_PATH ?? conf.createRPCImport ?? 'vovk/dist/client/createRPC.js';
|
|
11
|
+
const defaultClientTemplates = ['ts', 'module', 'main'];
|
|
11
12
|
const config = {
|
|
12
13
|
modulesDir: env.VOVK_MODULES_DIR ?? conf.modulesDir ?? './' + [srcRoot, 'modules'].filter(Boolean).join('/'),
|
|
13
14
|
validateOnClientImport: typeof validateOnClientImport === 'string' ? [validateOnClientImport] : validateOnClientImport,
|
|
@@ -21,7 +22,9 @@ export default async function getConfig({ clientOutDir, cwd }) {
|
|
|
21
22
|
logLevel: env.VOVK_LOG_LEVEL ?? conf.logLevel ?? 'info',
|
|
22
23
|
prettifyClient: (env.VOVK_PRETTIFY_CLIENT ? !!env.VOVK_PRETTIFY_CLIENT : null) ?? conf.prettifyClient ?? false,
|
|
23
24
|
devHttps: (env.VOVK_DEV_HTTPS ? !!env.VOVK_DEV_HTTPS : null) ?? conf.devHttps ?? false,
|
|
24
|
-
|
|
25
|
+
generateFrom: typeof conf.generateFrom === 'function'
|
|
26
|
+
? conf.generateFrom(defaultClientTemplates)
|
|
27
|
+
: (conf.generateFrom ?? ['ts', 'module', 'main']),
|
|
25
28
|
templates: {
|
|
26
29
|
service: 'vovk-cli/templates/service.ejs',
|
|
27
30
|
controller: 'vovk-cli/templates/controller.ejs',
|
package/dist/types.d.mts
CHANGED
|
@@ -18,6 +18,12 @@ export type VovkEnv = {
|
|
|
18
18
|
__VOVK_START_WATCHER_IN_STANDALONE_MODE__?: 'true';
|
|
19
19
|
__VOVK_EXIT__?: 'true' | 'false';
|
|
20
20
|
};
|
|
21
|
+
type GenerateFrom = (string | {
|
|
22
|
+
templatePath: string;
|
|
23
|
+
outDir?: string;
|
|
24
|
+
templateName?: string;
|
|
25
|
+
fullSchema?: string | boolean;
|
|
26
|
+
})[];
|
|
21
27
|
export type VovkConfig = {
|
|
22
28
|
clientOutDir?: string;
|
|
23
29
|
schemaOutDir?: string;
|
|
@@ -31,17 +37,18 @@ export type VovkConfig = {
|
|
|
31
37
|
logLevel?: LogLevelNames;
|
|
32
38
|
prettifyClient?: boolean;
|
|
33
39
|
devHttps?: boolean;
|
|
34
|
-
|
|
40
|
+
generateFrom?: GenerateFrom | ((value: GenerateFrom) => GenerateFrom);
|
|
35
41
|
templates?: {
|
|
36
42
|
service?: string;
|
|
37
43
|
controller?: string;
|
|
38
44
|
[key: string]: string | undefined;
|
|
39
45
|
};
|
|
40
46
|
};
|
|
41
|
-
export type VovkStrictConfig = Required<Omit<VovkConfig, 'validateOnClientImport' | 'fetcherImport' | 'createRPCImport'>> & {
|
|
47
|
+
export type VovkStrictConfig = Required<Omit<VovkConfig, 'validateOnClientImport' | 'fetcherImport' | 'createRPCImport' | 'generateFrom'>> & {
|
|
42
48
|
validateOnClientImport: string[] | null;
|
|
43
49
|
fetcherImport: string[];
|
|
44
50
|
createRPCImport: string[];
|
|
51
|
+
generateFrom: GenerateFrom;
|
|
45
52
|
};
|
|
46
53
|
export type VovkModuleRenderResult = {
|
|
47
54
|
fileName: string;
|
|
@@ -84,3 +91,4 @@ export interface NewOptions {
|
|
|
84
91
|
noSegmentUpdate?: boolean;
|
|
85
92
|
empty?: boolean;
|
|
86
93
|
}
|
|
94
|
+
export {};
|
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.98",
|
|
4
4
|
"bin": {
|
|
5
5
|
"vovk": "./dist/index.mjs"
|
|
6
6
|
},
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
},
|
|
37
37
|
"homepage": "https://vovk.dev",
|
|
38
38
|
"peerDependencies": {
|
|
39
|
-
"vovk": "^3.0.0-draft.
|
|
39
|
+
"vovk": "^3.0.0-draft.87"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
42
|
"@inquirer/prompts": "^7.3.1",
|