vovk-cli 0.0.1-draft.165 → 0.0.1-draft.166
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/cjs/index.cjs.ejs +4 -4
- package/client-templates/cjs/index.d.cts.ejs +3 -3
- package/client-templates/mjs/index.d.mts.ejs +3 -3
- package/client-templates/mjs/index.mjs.ejs +4 -4
- package/client-templates/readme/README.md.ejs +1 -1
- package/client-templates/{fullSchemaCjs/fullSchema.cjs.ejs → schemaCjs/schema.cjs.ejs} +4 -4
- package/client-templates/schemaCjs/schema.d.cts.ejs +10 -0
- package/client-templates/schemaJson/schema.json.ejs +1 -0
- package/client-templates/{fullSchemaTs/fullSchema.ts.ejs → schemaTs/schema.ts.ejs} +4 -4
- package/client-templates/ts/index.ts.ejs +5 -5
- package/dist/bundle/index.d.mts +5 -3
- package/dist/bundle/index.mjs +28 -16
- package/dist/dev/ensureSchemaFiles.mjs +2 -2
- package/dist/dev/index.mjs +32 -27
- package/dist/generate/ensureClient.d.mts +2 -1
- package/dist/generate/ensureClient.mjs +8 -7
- package/dist/generate/getClientTemplateFiles.d.mts +1 -1
- package/dist/generate/getClientTemplateFiles.mjs +13 -16
- package/dist/generate/getFullSchemaFromJSON.d.mts +2 -2
- package/dist/generate/getFullSchemaFromJSON.mjs +3 -4
- package/dist/generate/getTemplateClientImports.d.mts +4 -5
- package/dist/generate/getTemplateClientImports.mjs +3 -3
- package/dist/generate/index.d.mts +5 -3
- package/dist/generate/index.mjs +41 -40
- package/dist/generate/mergePackages.mjs +4 -4
- package/dist/generate/writeOneClientFile.d.mts +5 -3
- package/dist/generate/writeOneClientFile.mjs +12 -8
- package/dist/getProjectInfo/{getRelativeSrcRoot.d.mts → getConfig/getRelativeSrcRoot.d.mts} +1 -1
- package/dist/getProjectInfo/{getRelativeSrcRoot.mjs → getConfig/getRelativeSrcRoot.mjs} +2 -2
- package/dist/getProjectInfo/getConfig/getTemplateDefs.d.mts +3 -3
- package/dist/getProjectInfo/getConfig/getTemplateDefs.mjs +17 -19
- package/dist/getProjectInfo/{getUserConfig.mjs → getConfig/getUserConfig.mjs} +1 -1
- package/dist/getProjectInfo/getConfig/index.d.mts +4 -7
- package/dist/getProjectInfo/getConfig/index.mjs +28 -65
- package/dist/getProjectInfo/index.d.mts +4 -6
- package/dist/getProjectInfo/index.mjs +7 -12
- package/dist/index.mjs +20 -13
- package/dist/init/index.mjs +1 -1
- package/dist/new/newModule.mjs +3 -1
- package/dist/new/newSegment.mjs +7 -5
- package/dist/types.d.mts +7 -8
- package/dist/utils/formatLoggedSegmentName.d.mts +2 -1
- package/dist/utils/formatLoggedSegmentName.mjs +2 -2
- package/dist/utils/getPublicModuleNameFromPath.d.mts +4 -0
- package/dist/utils/getPublicModuleNameFromPath.mjs +9 -0
- package/dist/utils/pickSegmentFullSchema.d.mts +3 -3
- package/dist/utils/pickSegmentFullSchema.mjs +9 -11
- package/dist/utils/resolveAbsoluteModulePath.d.mts +1 -0
- package/dist/utils/resolveAbsoluteModulePath.mjs +17 -5
- package/package.json +1 -1
- package/client-templates/fullSchemaCjs/fullSchema.d.cts.ejs +0 -10
- package/client-templates/fullSchemaJson/full-schema.json.ejs +0 -1
- package/dist/dev/isSegmentSchemaEmpty.d.mts +0 -2
- package/dist/dev/isSegmentSchemaEmpty.mjs +0 -4
- package/dist/enums.d.mts +0 -5
- package/dist/enums.mjs +0 -6
- /package/dist/getProjectInfo/{getConfigAbsolutePaths.d.mts → getConfig/getConfigAbsolutePaths.d.mts} +0 -0
- /package/dist/getProjectInfo/{getConfigAbsolutePaths.mjs → getConfig/getConfigAbsolutePaths.mjs} +0 -0
- /package/dist/getProjectInfo/{getUserConfig.d.mts → getConfig/getUserConfig.d.mts} +0 -0
- /package/dist/getProjectInfo/{importUncachedModule.d.mts → getConfig/importUncachedModule.d.mts} +0 -0
- /package/dist/getProjectInfo/{importUncachedModule.mjs → getConfig/importUncachedModule.mjs} +0 -0
- /package/dist/getProjectInfo/{importUncachedModuleWorker.d.mts → getConfig/importUncachedModuleWorker.d.mts} +0 -0
- /package/dist/getProjectInfo/{importUncachedModuleWorker.mjs → getConfig/importUncachedModuleWorker.mjs} +0 -0
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
<%- `// auto-generated ${new Date().toISOString()}\n/* eslint-disable */` %>
|
|
2
2
|
const { fetcher } = require('<%= t.imports.fetcher %>');
|
|
3
3
|
const { createRPC } = require('<%= t.imports.createRPC %>');
|
|
4
|
-
const {
|
|
4
|
+
const { schema } = require('./schema.cjs');
|
|
5
5
|
const { validateOnClient = null } = <%- t.imports.validateOnClient ? `require('${t.imports.validateOnClient}')` : '{}'%>;
|
|
6
|
-
<% Object.values(t.
|
|
6
|
+
<% Object.values(t.schema.segments).filter((segment) => segment.emitSchema).forEach((segment) => {
|
|
7
7
|
Object.keys(segment.controllers).forEach((rpcModuleName) => { %>
|
|
8
8
|
exports.<%= rpcModuleName %> = createRPC(
|
|
9
|
-
|
|
9
|
+
schema, '<%= segment.segmentName %>', '<%= rpcModuleName %>',
|
|
10
10
|
{ fetcher, validateOnClient, defaultOptions: { apiRoot: '<%= segment.segmentApiRoot ?? t.apiRoot %>' } }
|
|
11
11
|
);
|
|
12
12
|
<% })
|
|
13
13
|
}) %>
|
|
14
|
-
exports.
|
|
14
|
+
exports.schema = schema;
|
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
import type { VovkClientFetcher } from 'vovk';
|
|
4
4
|
import type { fetcher } from '<%= t.imports.module.fetcher %>';
|
|
5
5
|
import type { createRPC } from '<%= t.imports.module.createRPC %>';
|
|
6
|
-
<% Object.values(t.
|
|
6
|
+
<% Object.values(t.schema.segments).filter((segment) => segment.emitSchema).forEach((segment, i) => { %>
|
|
7
7
|
import type { Controllers as Controllers<%= i %> } from "<%= t.segmentMeta[segment.segmentName].segmentImportPath %>";
|
|
8
8
|
<% }) %>
|
|
9
9
|
type Options = typeof fetcher extends VovkClientFetcher<infer U> ? U : never;
|
|
10
|
-
<% Object.values(t.
|
|
10
|
+
<% Object.values(t.schema.segments).filter((segment) => segment.emitSchema).forEach((segment, i) => {
|
|
11
11
|
Object.keys(segment.controllers).forEach((rpcModuleName) => { %>
|
|
12
12
|
export const <%= rpcModuleName %>: ReturnType<typeof createRPC<Controllers<%= i %>["<%= rpcModuleName %>"], Options>>;
|
|
13
13
|
<% })
|
|
14
14
|
}) %>
|
|
15
|
-
export {
|
|
15
|
+
export { schema } from './schema.cjs';
|
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
import type { VovkClientFetcher } from 'vovk';
|
|
4
4
|
import type { fetcher } from '<%= t.imports.module.fetcher %>';
|
|
5
5
|
import type { createRPC } from '<%= t.imports.module.createRPC %>';
|
|
6
|
-
<% Object.values(t.
|
|
6
|
+
<% Object.values(t.schema.segments).filter((segment) => segment.emitSchema).forEach((segment, i) => { %>
|
|
7
7
|
import type { Controllers as Controllers<%= i %> } from "<%= t.segmentMeta[segment.segmentName].segmentImportPath %>";
|
|
8
8
|
<% }) %>
|
|
9
9
|
type Options = typeof fetcher extends VovkClientFetcher<infer U> ? U : never;
|
|
10
|
-
<% Object.values(t.
|
|
10
|
+
<% Object.values(t.schema.segments).filter((segment) => segment.emitSchema).forEach((segment, i) => {
|
|
11
11
|
Object.keys(segment.controllers).forEach((rpcModuleName) => { %>
|
|
12
12
|
export const <%= rpcModuleName %>: ReturnType<typeof createRPC<Controllers<%= i %>["<%= rpcModuleName %>"], Options>>;
|
|
13
13
|
<% })
|
|
14
14
|
}) %>
|
|
15
|
-
export {
|
|
15
|
+
export { schema } from './schema.cjs';
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
<%- `// auto-generated ${new Date().toISOString()}\n/* eslint-disable */` %>
|
|
2
2
|
import { fetcher } from '<%= t.imports.module.fetcher %>';
|
|
3
3
|
import { createRPC } from '<%= t.imports.module.createRPC %>';
|
|
4
|
-
import {
|
|
4
|
+
import { schema } from './schema.cjs';
|
|
5
5
|
<% if (t.imports.module.validateOnClient) { %>
|
|
6
6
|
import { validateOnClient } from '<%= t.imports.module.validateOnClient %>';
|
|
7
7
|
<% } else { %>
|
|
8
8
|
const validateOnClient = undefined;
|
|
9
9
|
<% } %>
|
|
10
|
-
<% Object.values(t.
|
|
10
|
+
<% Object.values(t.schema.segments).filter((segment) => segment.emitSchema).forEach((segment, i) => {
|
|
11
11
|
Object.keys(segment.controllers).forEach((rpcModuleName) => { %>
|
|
12
12
|
export const <%= rpcModuleName %> = createRPC(
|
|
13
|
-
|
|
13
|
+
schema, '<%= segment.segmentName %>', '<%= rpcModuleName %>',
|
|
14
14
|
{ fetcher, validateOnClient, defaultOptions: { apiRoot: '<%= segment.segmentApiRoot ?? t.apiRoot %>' } }
|
|
15
15
|
);
|
|
16
16
|
<%
|
|
17
17
|
});
|
|
18
18
|
});
|
|
19
19
|
%>
|
|
20
|
-
export {
|
|
20
|
+
export { schema };
|
|
@@ -16,7 +16,7 @@ imports: ['vovk-openapi']
|
|
|
16
16
|
npm install <%= t.package.name.replace(/-/g, '_') %>
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
-
<% Object.entries(t.
|
|
19
|
+
<% Object.entries(t.schema.segments).forEach(([segmentName, segment]) => {
|
|
20
20
|
Object.values(segment.controllers).forEach((controllerSchema) => { %>
|
|
21
21
|
|
|
22
22
|
## <%= controllerSchema.rpcModuleName %>
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
<%- `// auto-generated ${new Date().toISOString()}\n/* eslint-disable */` %>
|
|
2
2
|
const config = require('./<%= t.schemaOutDir %>/config.json');
|
|
3
|
-
const segments = {<% Object.values(t.
|
|
3
|
+
const segments = {<% Object.values(t.schema.segments).filter((segment) => segment.emitSchema).forEach((segment) => { %>
|
|
4
4
|
'<%= segment.segmentName %>': require('./<%= t.schemaOutDir %>/<%= t.SEGMENTS_SCHEMA_DIR_NAME %>/<%= segment.segmentName || t.ROOT_SEGMENT_SCHEMA_NAME %>.json'),<% }) %>
|
|
5
5
|
};
|
|
6
|
-
const
|
|
7
|
-
$schema: '<%- t.
|
|
6
|
+
const schema = {
|
|
7
|
+
$schema: '<%- t.VovkSchemaIdEnum.FULL %>',
|
|
8
8
|
config,
|
|
9
9
|
segments,
|
|
10
10
|
};
|
|
11
11
|
|
|
12
|
-
module.exports.
|
|
12
|
+
module.exports.schema = schema;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<%- `// auto-generated ${new Date().toISOString()}\n/* eslint-disable */` %>
|
|
2
|
+
import type { VovkStrictConfig, VovkSegmentSchema, VovkSchemaIdEnum } from 'vovk';
|
|
3
|
+
|
|
4
|
+
export const schema: {
|
|
5
|
+
$schema: '<%- t.VovkSchemaIdEnum.FULL %>';
|
|
6
|
+
config: Partial<VovkStrictConfig>;
|
|
7
|
+
segments: {<% Object.values(t.schema.segments).filter((segment) => segment.emitSchema).forEach((segment) => { %>
|
|
8
|
+
'<%= segment.segmentName %>': VovkSegmentSchema;<% }) %>
|
|
9
|
+
};
|
|
10
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<%- JSON.stringify(t.schema, null, 2) %>
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
<%- `// auto-generated ${new Date().toISOString()}\n/* eslint-disable */` %>
|
|
2
2
|
import config from './<%= t.schemaOutDir %>/config.json' with { type: "json" };
|
|
3
|
-
<% Object.values(t.
|
|
3
|
+
<% Object.values(t.schema.segments).filter((segment) => segment.emitSchema).forEach((segment, i) => { %>
|
|
4
4
|
import segment<%= i %> from './<%= t.schemaOutDir %>/<%= t.SEGMENTS_SCHEMA_DIR_NAME %>/<%= segment.segmentName || t.ROOT_SEGMENT_SCHEMA_NAME %>.json' with { type: "json" };
|
|
5
5
|
<% }) %>
|
|
6
|
-
const segments = {<% Object.values(t.
|
|
6
|
+
const segments = {<% Object.values(t.schema.segments).filter((segment) => segment.emitSchema).forEach((segment, i) => { %>
|
|
7
7
|
'<%= segment.segmentName %>': segment<%= i %>,<% }) %>
|
|
8
8
|
};
|
|
9
9
|
|
|
10
|
-
export const
|
|
11
|
-
$schema: '<%- t.
|
|
10
|
+
export const schema = {
|
|
11
|
+
$schema: '<%- t.VovkSchemaIdEnum.FULL %>',
|
|
12
12
|
config,
|
|
13
13
|
segments,
|
|
14
14
|
};
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
import type { VovkClientFetcher } from 'vovk';
|
|
3
3
|
import { fetcher } from '<%= t.imports.fetcher %>';
|
|
4
4
|
import { createRPC } from '<%= t.imports.createRPC %>';
|
|
5
|
-
import {
|
|
6
|
-
<% Object.values(t.
|
|
5
|
+
import { schema } from './schema.ts';
|
|
6
|
+
<% Object.values(t.schema.segments).filter((segment) => segment.emitSchema).forEach((segment, i) => { %>
|
|
7
7
|
import type { Controllers as Controllers<%= i %> } from "<%= t.segmentMeta[segment.segmentName].segmentImportPath %>";
|
|
8
8
|
<% }) %>
|
|
9
9
|
<% if (t.imports.validateOnClient) { %>
|
|
@@ -12,12 +12,12 @@ import { validateOnClient } from '<%= t.imports.validateOnClient %>';
|
|
|
12
12
|
const validateOnClient = undefined;
|
|
13
13
|
<% } %>
|
|
14
14
|
type Options = typeof fetcher extends VovkClientFetcher<infer U> ? U : never;
|
|
15
|
-
<% Object.values(t.
|
|
15
|
+
<% Object.values(t.schema.segments).filter((segment) => segment.emitSchema).forEach((segment, i) => { %>
|
|
16
16
|
<% Object.keys(segment.controllers).forEach((rpcModuleName) => { %>
|
|
17
17
|
export const <%= rpcModuleName %> = createRPC<Controllers<%= i %>["<%= rpcModuleName %>"], Options>(
|
|
18
|
-
|
|
18
|
+
schema, '<%= segment.segmentName %>', '<%= rpcModuleName %>',
|
|
19
19
|
{ fetcher, validateOnClient, defaultOptions: { apiRoot: '<%= segment.segmentApiRoot ?? t.apiRoot %>' } }
|
|
20
20
|
);
|
|
21
21
|
<% }) %>
|
|
22
22
|
<% }) %>
|
|
23
|
-
export {
|
|
23
|
+
export { schema };
|
package/dist/bundle/index.d.mts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { VovkSchema } from 'vovk';
|
|
2
2
|
import type { ProjectInfo } from '../getProjectInfo/index.mjs';
|
|
3
|
-
|
|
3
|
+
import type { BundleOptions } from '../types.mjs';
|
|
4
|
+
export default function bundle({ projectInfo, fullSchema, cliBundleOptions, }: {
|
|
4
5
|
projectInfo: ProjectInfo;
|
|
5
|
-
fullSchema:
|
|
6
|
+
fullSchema: VovkSchema;
|
|
7
|
+
cliBundleOptions: BundleOptions;
|
|
6
8
|
}): Promise<void>;
|
package/dist/bundle/index.mjs
CHANGED
|
@@ -5,25 +5,36 @@ import groupBy from 'lodash/groupBy.js';
|
|
|
5
5
|
import generate from '../generate/index.mjs';
|
|
6
6
|
import { BuiltInTemplateName } from '../getProjectInfo/getConfig/getTemplateDefs.mjs';
|
|
7
7
|
import chalkHighlightThing from '../utils/chalkHighlightThing.mjs';
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
import locateSegments from '../locateSegments.mjs';
|
|
9
|
+
export default async function bundle({ projectInfo, fullSchema, cliBundleOptions, }) {
|
|
10
|
+
const { config, log, cwd, apiDir } = projectInfo;
|
|
11
|
+
const locatedSegments = await locateSegments({ dir: path.join(cwd, apiDir), config, log });
|
|
10
12
|
const { bundle: bundleConfig } = config;
|
|
11
|
-
const cwd = process.cwd();
|
|
12
13
|
const tsFullClientOutAbsoluteDirInput = path.join(cwd, bundleConfig.tsClientOutDir);
|
|
14
|
+
const tsClientOutDir = cliBundleOptions?.tsClientOutDir ?? bundleConfig.tsClientOutDir;
|
|
15
|
+
const dontDeleteTsClientOutDirAfter = cliBundleOptions?.dontDeleteTsClientOutDirAfter ?? bundleConfig?.dontDeleteTsClientOutDirAfter ?? false;
|
|
16
|
+
const sourcemap = cliBundleOptions?.sourcemap ?? bundleConfig?.sourcemap;
|
|
17
|
+
if (!tsClientOutDir) {
|
|
18
|
+
throw new Error('No output directory specified for composed client');
|
|
19
|
+
}
|
|
20
|
+
const outDir = cliBundleOptions?.outDir ?? bundleConfig.outDir;
|
|
21
|
+
if (!outDir) {
|
|
22
|
+
throw new Error('No output directory specified for bundling');
|
|
23
|
+
}
|
|
13
24
|
await generate({
|
|
14
25
|
isEnsuringClient: false,
|
|
15
26
|
projectInfo,
|
|
16
27
|
forceNothingWrittenLog: true,
|
|
17
28
|
fullSchema,
|
|
29
|
+
locatedSegments,
|
|
18
30
|
cliGenerateOptions: {
|
|
19
|
-
|
|
20
|
-
|
|
31
|
+
composedFrom: [BuiltInTemplateName.ts],
|
|
32
|
+
composedOut: tsClientOutDir,
|
|
33
|
+
composedOnly: true,
|
|
34
|
+
composedIncludeSegments: cliBundleOptions.includeSegments ?? bundleConfig.includeSegments,
|
|
35
|
+
composedExcludeSegments: cliBundleOptions.excludeSegments ?? bundleConfig.excludeSegments,
|
|
21
36
|
},
|
|
22
37
|
});
|
|
23
|
-
const outDir = bundleConfig.outDir;
|
|
24
|
-
if (!outDir) {
|
|
25
|
-
throw new Error('No output directory specified for bundling');
|
|
26
|
-
}
|
|
27
38
|
await build({
|
|
28
39
|
entry: path.join(tsFullClientOutAbsoluteDirInput, './index.ts'),
|
|
29
40
|
dts: true,
|
|
@@ -35,29 +46,30 @@ export default async function bundle({ projectInfo, fullSchema, }) {
|
|
|
35
46
|
const outDirAbsolute = path.resolve(cwd, outDir);
|
|
36
47
|
log.info(`Bundled index.ts to ${chalkHighlightThing(outDirAbsolute)}`);
|
|
37
48
|
await build({
|
|
38
|
-
entry: path.join(tsFullClientOutAbsoluteDirInput, './
|
|
49
|
+
entry: path.join(tsFullClientOutAbsoluteDirInput, './schema.ts'),
|
|
39
50
|
dts: true,
|
|
40
51
|
format: ['cjs'],
|
|
41
52
|
fixedExtension: true,
|
|
42
53
|
outDir,
|
|
43
54
|
clean: false,
|
|
44
|
-
sourcemap
|
|
55
|
+
sourcemap,
|
|
45
56
|
});
|
|
46
|
-
log.info(`Bundled
|
|
47
|
-
const requiresGroup = groupBy(Object.entries(bundleConfig.requires), ([,
|
|
57
|
+
log.info(`Bundled schema.ts to ${chalkHighlightThing(outDirAbsolute)}`);
|
|
58
|
+
const requiresGroup = groupBy(Object.entries(bundleConfig.requires), ([, relativePath]) => relativePath);
|
|
48
59
|
for (const [relativePath, group] of Object.entries(requiresGroup)) {
|
|
49
60
|
await generate({
|
|
50
61
|
isEnsuringClient: false,
|
|
51
62
|
projectInfo,
|
|
52
63
|
forceNothingWrittenLog: true,
|
|
53
64
|
fullSchema,
|
|
65
|
+
locatedSegments,
|
|
54
66
|
cliGenerateOptions: {
|
|
55
|
-
|
|
56
|
-
|
|
67
|
+
composedFrom: group.map(([templateName]) => templateName),
|
|
68
|
+
composedOut: path.resolve(outDir, relativePath),
|
|
57
69
|
},
|
|
58
70
|
});
|
|
59
71
|
}
|
|
60
|
-
if (!
|
|
72
|
+
if (!dontDeleteTsClientOutDirAfter) {
|
|
61
73
|
await fs.rm(tsFullClientOutAbsoluteDirInput, { recursive: true, force: true });
|
|
62
74
|
log.debug(`Deleted temporary TypeScript client output directory: ${chalkHighlightThing(tsFullClientOutAbsoluteDirInput)}`);
|
|
63
75
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
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 { VovkSchemaIdEnum } from 'vovk';
|
|
4
5
|
import writeOneSchemaFile, { SEGMENTS_SCHEMA_DIR_NAME, ROOT_SEGMENT_SCHEMA_NAME, } from './writeOneSegmentSchemaFile.mjs';
|
|
5
6
|
import formatLoggedSegmentName from '../utils/formatLoggedSegmentName.mjs';
|
|
6
7
|
import writeConfigJson from './writeConfigJson.mjs';
|
|
7
|
-
import { SchemaIdEnum } from '../enums.mjs';
|
|
8
8
|
/**
|
|
9
9
|
* Ensure that the schema files are created to avoid any import errors.
|
|
10
10
|
*/
|
|
@@ -19,7 +19,7 @@ export default async function ensureSchemaFiles(projectInfo, schemaOutAbsolutePa
|
|
|
19
19
|
const { isCreated } = await writeOneSchemaFile({
|
|
20
20
|
schemaOutAbsolutePath,
|
|
21
21
|
segmentSchema: {
|
|
22
|
-
$schema:
|
|
22
|
+
$schema: VovkSchemaIdEnum.SEGMENT,
|
|
23
23
|
emitSchema: false,
|
|
24
24
|
segmentName,
|
|
25
25
|
controllers: {},
|
package/dist/dev/index.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import fs from 'node:fs/promises';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
+
import { VovkSchemaIdEnum } from 'vovk';
|
|
3
4
|
import * as chokidar from 'chokidar';
|
|
4
5
|
import { Agent, setGlobalDispatcher } from 'undici';
|
|
5
6
|
import keyBy from 'lodash/keyBy.js';
|
|
@@ -15,13 +16,13 @@ import generate from '../generate/index.mjs';
|
|
|
15
16
|
import locateSegments from '../locateSegments.mjs';
|
|
16
17
|
import debounceWithArgs from '../utils/debounceWithArgs.mjs';
|
|
17
18
|
import formatLoggedSegmentName from '../utils/formatLoggedSegmentName.mjs';
|
|
18
|
-
import isSegmentSchemaEmpty from './isSegmentSchemaEmpty.mjs';
|
|
19
19
|
import writeConfigJson from './writeConfigJson.mjs';
|
|
20
|
-
import {
|
|
20
|
+
import { isEmpty } from 'lodash';
|
|
21
21
|
export class VovkDev {
|
|
22
22
|
#projectInfo;
|
|
23
|
+
#segments = [];
|
|
23
24
|
#fullSchema = {
|
|
24
|
-
$schema:
|
|
25
|
+
$schema: VovkSchemaIdEnum.SCHEMA,
|
|
25
26
|
segments: {},
|
|
26
27
|
config: {},
|
|
27
28
|
};
|
|
@@ -45,18 +46,18 @@ export class VovkDev {
|
|
|
45
46
|
log.debug(`File ${filePath} has been added to segments folder`);
|
|
46
47
|
if (segmentReg.test(filePath)) {
|
|
47
48
|
const segmentName = getSegmentName(filePath);
|
|
48
|
-
this.#
|
|
49
|
-
? this.#
|
|
49
|
+
this.#segments = this.#segments.find((s) => s.segmentName === segmentName)
|
|
50
|
+
? this.#segments
|
|
50
51
|
: [
|
|
51
|
-
...this.#
|
|
52
|
+
...this.#segments,
|
|
52
53
|
{
|
|
53
54
|
routeFilePath: filePath,
|
|
54
55
|
segmentName,
|
|
55
56
|
},
|
|
56
57
|
];
|
|
57
58
|
log.info(`${capitalize(formatLoggedSegmentName(segmentName))} has been added`);
|
|
58
|
-
log.debug(`Full list of segments: ${this.#
|
|
59
|
-
void debouncedEnsureSchemaFiles(this.#projectInfo, schemaOutAbsolutePath, this.#
|
|
59
|
+
log.debug(`Full list of segments: ${this.#segments.map((s) => s.segmentName).join(', ')}`);
|
|
60
|
+
void debouncedEnsureSchemaFiles(this.#projectInfo, schemaOutAbsolutePath, this.#segments.map((s) => s.segmentName));
|
|
60
61
|
}
|
|
61
62
|
})
|
|
62
63
|
.on('change', (filePath) => {
|
|
@@ -67,23 +68,23 @@ export class VovkDev {
|
|
|
67
68
|
})
|
|
68
69
|
.on('addDir', async (dirPath) => {
|
|
69
70
|
log.debug(`Directory ${dirPath} has been added to segments folder`);
|
|
70
|
-
this.#
|
|
71
|
+
this.#segments = await locateSegments({
|
|
71
72
|
dir: apiDirAbsolutePath,
|
|
72
73
|
config,
|
|
73
74
|
log: this.#projectInfo.log,
|
|
74
75
|
});
|
|
75
|
-
for (const { segmentName } of this.#
|
|
76
|
+
for (const { segmentName } of this.#segments) {
|
|
76
77
|
void this.#requestSchema(segmentName);
|
|
77
78
|
}
|
|
78
79
|
})
|
|
79
80
|
.on('unlinkDir', async (dirPath) => {
|
|
80
81
|
log.debug(`Directory ${dirPath} has been removed from segments folder`);
|
|
81
|
-
this.#
|
|
82
|
+
this.#segments = await locateSegments({
|
|
82
83
|
dir: apiDirAbsolutePath,
|
|
83
84
|
config,
|
|
84
85
|
log: this.#projectInfo.log,
|
|
85
86
|
});
|
|
86
|
-
for (const { segmentName } of this.#
|
|
87
|
+
for (const { segmentName } of this.#segments) {
|
|
87
88
|
void this.#requestSchema(segmentName);
|
|
88
89
|
}
|
|
89
90
|
})
|
|
@@ -91,10 +92,10 @@ export class VovkDev {
|
|
|
91
92
|
log.debug(`File ${filePath} has been removed from segments folder`);
|
|
92
93
|
if (segmentReg.test(filePath)) {
|
|
93
94
|
const segmentName = getSegmentName(filePath);
|
|
94
|
-
this.#
|
|
95
|
+
this.#segments = this.#segments.filter((s) => s.segmentName !== segmentName);
|
|
95
96
|
log.info(`${formatLoggedSegmentName(segmentName, { upperFirst: true })} has been removed`);
|
|
96
|
-
log.debug(`Full list of segments: ${this.#
|
|
97
|
-
void debouncedEnsureSchemaFiles(this.#projectInfo, schemaOutAbsolutePath, this.#
|
|
97
|
+
log.debug(`Full list of segments: ${this.#segments.map((s) => s.segmentName).join(', ')}`);
|
|
98
|
+
void debouncedEnsureSchemaFiles(this.#projectInfo, schemaOutAbsolutePath, this.#segments.map((s) => s.segmentName));
|
|
98
99
|
}
|
|
99
100
|
})
|
|
100
101
|
.on('ready', () => {
|
|
@@ -127,12 +128,12 @@ export class VovkDev {
|
|
|
127
128
|
log.debug(`File ${filePath} has been removed from modules folder`);
|
|
128
129
|
})
|
|
129
130
|
.on('addDir', () => {
|
|
130
|
-
for (const { segmentName } of this.#
|
|
131
|
+
for (const { segmentName } of this.#segments) {
|
|
131
132
|
void this.#requestSchema(segmentName);
|
|
132
133
|
}
|
|
133
134
|
})
|
|
134
135
|
.on('unlinkDir', () => {
|
|
135
|
-
for (const { segmentName } of this.#
|
|
136
|
+
for (const { segmentName } of this.#segments) {
|
|
136
137
|
void this.#requestSchema(segmentName);
|
|
137
138
|
}
|
|
138
139
|
})
|
|
@@ -151,6 +152,8 @@ export class VovkDev {
|
|
|
151
152
|
let isReady = false;
|
|
152
153
|
const handle = debounce(async () => {
|
|
153
154
|
this.#projectInfo = await getProjectInfo();
|
|
155
|
+
const { config, apiDir } = this.#projectInfo;
|
|
156
|
+
this.#segments = await locateSegments({ dir: path.join(cwd, apiDir), config, log });
|
|
154
157
|
await this.#modulesWatcher?.close();
|
|
155
158
|
await this.#segmentWatcher?.close();
|
|
156
159
|
await Promise.all([
|
|
@@ -200,7 +203,7 @@ export class VovkDev {
|
|
|
200
203
|
if (this.#isWatching)
|
|
201
204
|
throw new Error('Already watching');
|
|
202
205
|
const { log } = this.#projectInfo;
|
|
203
|
-
log.debug(`Starting segments and modules watcher. Detected initial segments: ${JSON.stringify(this.#
|
|
206
|
+
log.debug(`Starting segments and modules watcher. Detected initial segments: ${JSON.stringify(this.#segments.map((s) => s.segmentName))}.`);
|
|
204
207
|
// automatically watches segments and modules
|
|
205
208
|
this.#watchConfig(callback);
|
|
206
209
|
}
|
|
@@ -215,7 +218,7 @@ export class VovkDev {
|
|
|
215
218
|
const namesOfClasses = [...code.matchAll(nameOfClasReg)].map((match) => match[1]);
|
|
216
219
|
const importRegex = /import\s*{[^}]*\b(get|post|put|del|head|options)\b[^}]*}\s*from\s*['"]vovk['"]/;
|
|
217
220
|
if (importRegex.test(code) && namesOfClasses.length) {
|
|
218
|
-
const affectedSegments = this.#
|
|
221
|
+
const affectedSegments = this.#segments.filter((s) => {
|
|
219
222
|
const segmentSchema = this.#fullSchema.segments[s.segmentName];
|
|
220
223
|
if (!segmentSchema)
|
|
221
224
|
return false;
|
|
@@ -265,7 +268,7 @@ export class VovkDev {
|
|
|
265
268
|
}
|
|
266
269
|
return { isError: false };
|
|
267
270
|
}, 500);
|
|
268
|
-
#generate = debounce(() => generate({ projectInfo: this.#projectInfo, fullSchema: this.#fullSchema }).then(this.#onFirstTimeGenerate), 1000);
|
|
271
|
+
#generate = debounce(() => generate({ projectInfo: this.#projectInfo, fullSchema: this.#fullSchema, locatedSegments: this.#segments }).then(this.#onFirstTimeGenerate), 1000);
|
|
269
272
|
async #handleSegmentSchema(segmentName, segmentSchema) {
|
|
270
273
|
const { log, config, cwd } = this.#projectInfo;
|
|
271
274
|
if (!segmentSchema) {
|
|
@@ -274,7 +277,7 @@ export class VovkDev {
|
|
|
274
277
|
}
|
|
275
278
|
log.debug(`Handling received schema from ${formatLoggedSegmentName(segmentName)}`);
|
|
276
279
|
const schemaOutAbsolutePath = path.join(cwd, config.schemaOutDir);
|
|
277
|
-
const segment = this.#
|
|
280
|
+
const segment = this.#segments.find((s) => s.segmentName === segmentName);
|
|
278
281
|
if (!segment) {
|
|
279
282
|
log.warn(`${formatLoggedSegmentName(segmentName)} not found`);
|
|
280
283
|
return;
|
|
@@ -293,10 +296,10 @@ export class VovkDev {
|
|
|
293
296
|
log.info(`Schema for ${formatLoggedSegmentName(segment.segmentName)} has been updated in ${timeTook}ms`);
|
|
294
297
|
}
|
|
295
298
|
}
|
|
296
|
-
else if (segmentSchema && !
|
|
299
|
+
else if (segmentSchema && !isEmpty(segmentSchema.controllers)) {
|
|
297
300
|
log.error(`Non-empty schema provided for ${formatLoggedSegmentName(segment.segmentName)} but "emitSchema" is false`);
|
|
298
301
|
}
|
|
299
|
-
if (this.#
|
|
302
|
+
if (this.#segments.every((s) => this.#fullSchema.segments[s.segmentName])) {
|
|
300
303
|
log.debug(`All segments with "emitSchema" have schema.`);
|
|
301
304
|
this.#generate();
|
|
302
305
|
}
|
|
@@ -304,7 +307,8 @@ export class VovkDev {
|
|
|
304
307
|
async start({ exit }) {
|
|
305
308
|
const now = Date.now();
|
|
306
309
|
this.#projectInfo = await getProjectInfo();
|
|
307
|
-
const { log, config, cwd } = this.#projectInfo;
|
|
310
|
+
const { log, config, cwd, apiDir } = this.#projectInfo;
|
|
311
|
+
this.#segments = await locateSegments({ dir: path.join(cwd, apiDir), config, log });
|
|
308
312
|
log.info('Starting...');
|
|
309
313
|
if (exit) {
|
|
310
314
|
this.#onFirstTimeGenerate = once(() => {
|
|
@@ -326,13 +330,14 @@ export class VovkDev {
|
|
|
326
330
|
log.error(`Unhandled Rejection: ${String(reason)}`);
|
|
327
331
|
});
|
|
328
332
|
const schemaOutAbsolutePath = path.join(cwd, config.schemaOutDir);
|
|
329
|
-
|
|
330
|
-
await
|
|
333
|
+
const segmentNames = this.#segments.map((s) => s.segmentName);
|
|
334
|
+
await ensureSchemaFiles(this.#projectInfo, schemaOutAbsolutePath, segmentNames);
|
|
335
|
+
await ensureClient(this.#projectInfo, this.#segments);
|
|
331
336
|
const MAX_ATTEMPTS = 5;
|
|
332
337
|
const DELAY = 5000;
|
|
333
338
|
// Request schema every segment in 5 seconds in order to update schema on start
|
|
334
339
|
setTimeout(() => {
|
|
335
|
-
for (const { segmentName } of this.#
|
|
340
|
+
for (const { segmentName } of this.#segments) {
|
|
336
341
|
let attempts = 0;
|
|
337
342
|
void this.#requestSchema(segmentName).then(({ isError }) => {
|
|
338
343
|
if (isError) {
|
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
import type { ProjectInfo } from '../getProjectInfo/index.mjs';
|
|
2
|
-
|
|
2
|
+
import type { Segment } from '../locateSegments.mjs';
|
|
3
|
+
export default function ensureClient(projectInfo: ProjectInfo, locatedSegments: Segment[]): Promise<void>;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { VovkSchemaIdEnum } from 'vovk';
|
|
2
2
|
import generate from './index.mjs';
|
|
3
|
-
const getEmptySegmentRecordSchema = (
|
|
3
|
+
const getEmptySegmentRecordSchema = (segmentNames) => {
|
|
4
4
|
const result = {};
|
|
5
|
-
for (const
|
|
5
|
+
for (const segmentName of segmentNames) {
|
|
6
6
|
result[segmentName] = {
|
|
7
|
-
$schema:
|
|
7
|
+
$schema: VovkSchemaIdEnum.SEGMENT,
|
|
8
8
|
segmentName,
|
|
9
9
|
emitSchema: false,
|
|
10
10
|
controllers: {},
|
|
@@ -12,14 +12,15 @@ const getEmptySegmentRecordSchema = (segments) => {
|
|
|
12
12
|
}
|
|
13
13
|
return result;
|
|
14
14
|
};
|
|
15
|
-
export default async function ensureClient(projectInfo) {
|
|
15
|
+
export default async function ensureClient(projectInfo, locatedSegments) {
|
|
16
16
|
return generate({
|
|
17
17
|
isEnsuringClient: true,
|
|
18
18
|
projectInfo,
|
|
19
19
|
fullSchema: {
|
|
20
|
-
$schema:
|
|
20
|
+
$schema: VovkSchemaIdEnum.SCHEMA,
|
|
21
21
|
config: {},
|
|
22
|
-
segments: getEmptySegmentRecordSchema(
|
|
22
|
+
segments: getEmptySegmentRecordSchema(locatedSegments.map(({ segmentName }) => segmentName)),
|
|
23
23
|
},
|
|
24
|
+
locatedSegments,
|
|
24
25
|
});
|
|
25
26
|
}
|
|
@@ -12,7 +12,7 @@ export default function getClientTemplateFiles({ config, cwd, log, configKey, cl
|
|
|
12
12
|
config: VovkStrictConfig;
|
|
13
13
|
cwd: string;
|
|
14
14
|
log: ProjectInfo['log'];
|
|
15
|
-
configKey: '
|
|
15
|
+
configKey: 'composedClient' | 'segmentedClient';
|
|
16
16
|
cliGenerateOptions?: GenerateOptions;
|
|
17
17
|
}): Promise<{
|
|
18
18
|
fromTemplates: string[];
|
|
@@ -2,18 +2,18 @@ import path from 'node:path';
|
|
|
2
2
|
import { glob } from 'glob';
|
|
3
3
|
import resolveAbsoluteModulePath from '../utils/resolveAbsoluteModulePath.mjs';
|
|
4
4
|
import getFileSystemEntryType, { FileSystemEntryType } from '../utils/getFileSystemEntryType.mjs';
|
|
5
|
+
import getPublicModuleNameFromPath from '../utils/getPublicModuleNameFromPath.mjs';
|
|
5
6
|
export default async function getClientTemplateFiles({ config, cwd, log, configKey, cliGenerateOptions, }) {
|
|
6
7
|
const usedTemplateDefs = {};
|
|
7
|
-
const fromTemplates = configKey === '
|
|
8
|
-
? cliGenerateOptions?.
|
|
9
|
-
? (cliGenerateOptions?.
|
|
10
|
-
: config.
|
|
11
|
-
: cliGenerateOptions?.
|
|
8
|
+
const fromTemplates = configKey === 'composedClient'
|
|
9
|
+
? cliGenerateOptions?.composedFrom || cliGenerateOptions?.segmentedFrom
|
|
10
|
+
? (cliGenerateOptions?.composedFrom ?? [])
|
|
11
|
+
: config.composedClient.fromTemplates
|
|
12
|
+
: cliGenerateOptions?.composedFrom || cliGenerateOptions?.segmentedFrom
|
|
12
13
|
? (cliGenerateOptions?.segmentedFrom ?? [])
|
|
13
14
|
: config.segmentedClient.fromTemplates;
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
: (cliGenerateOptions?.segmentedOut ?? config.segmentedClient.outDir);
|
|
15
|
+
const cliOutDir = configKey === 'composedClient' ? cliGenerateOptions?.composedOut : cliGenerateOptions?.segmentedOut;
|
|
16
|
+
const configOutDir = configKey === 'composedClient' ? config.composedClient.outDir : config.segmentedClient.outDir;
|
|
17
17
|
for (const templateName of fromTemplates) {
|
|
18
18
|
if (!(templateName in config.clientTemplateDefs)) {
|
|
19
19
|
throw new Error(`Unknown template name: ${templateName}`);
|
|
@@ -29,16 +29,13 @@ export default async function getClientTemplateFiles({ config, cwd, log, configK
|
|
|
29
29
|
: null;
|
|
30
30
|
const entryType = templateAbsolutePath ? await getFileSystemEntryType(templateAbsolutePath) : null;
|
|
31
31
|
if (templateAbsolutePath && !entryType) {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
const pathParts = templateDef.templatePath.split('/');
|
|
36
|
-
const npmModuleName = pathParts[0].startsWith('@') ? `${pathParts[0]}/${pathParts[1]}` : pathParts[0];
|
|
37
|
-
throw new Error(`Unable to locate template path "${templateDef.templatePath}" resolved as "${templateAbsolutePath}". You may need to install the package "${npmModuleName}" first.`);
|
|
32
|
+
const { moduleName } = templateDef.templatePath ? getPublicModuleNameFromPath(templateDef.templatePath) : {};
|
|
33
|
+
if (moduleName) {
|
|
34
|
+
throw new Error(`Unable to locate template path "${templateDef.templatePath}" resolved as "${templateAbsolutePath}". You may need to install the package "${moduleName}" first.`);
|
|
38
35
|
}
|
|
39
36
|
throw new Error(`Unable to locate template path "${templateDef.templatePath}" resolved as "${templateAbsolutePath}"`);
|
|
40
37
|
}
|
|
41
|
-
const defOutDir = configKey === '
|
|
38
|
+
const defOutDir = configKey === 'composedClient' ? templateDef.composedClient?.outDir : templateDef.segmentedClient?.outDir;
|
|
42
39
|
let files = [];
|
|
43
40
|
if (templateAbsolutePath) {
|
|
44
41
|
if (entryType === FileSystemEntryType.FILE) {
|
|
@@ -55,7 +52,7 @@ export default async function getClientTemplateFiles({ config, cwd, log, configK
|
|
|
55
52
|
log.error(`Template "${templateAbsolutePath}" not found`);
|
|
56
53
|
continue;
|
|
57
54
|
}
|
|
58
|
-
const outCwdRelativeDir = forceOutCwdRelativeDir ?? defOutDir ??
|
|
55
|
+
const outCwdRelativeDir = forceOutCwdRelativeDir ?? cliOutDir ?? defOutDir ?? configOutDir;
|
|
59
56
|
for (const { filePath, isSingleFileTemplate } of files) {
|
|
60
57
|
templateFiles.push({
|
|
61
58
|
templateName,
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type VovkSchema } from 'vovk';
|
|
2
2
|
import type { ProjectInfo } from '../getProjectInfo/index.mjs';
|
|
3
|
-
export declare function getFullSchemaFromJSON(schemaOutAbsolutePath: string,
|
|
3
|
+
export declare function getFullSchemaFromJSON(schemaOutAbsolutePath: string, log: ProjectInfo['log']): Promise<VovkSchema>;
|
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
import { readFile, access } from 'node:fs/promises';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { glob } from 'glob';
|
|
4
|
+
import { VovkSchemaIdEnum } from 'vovk';
|
|
4
5
|
import { ROOT_SEGMENT_SCHEMA_NAME } from '../dev/writeOneSegmentSchemaFile.mjs';
|
|
5
|
-
|
|
6
|
-
export async function getFullSchemaFromJSON(schemaOutAbsolutePath, projectInfo) {
|
|
6
|
+
export async function getFullSchemaFromJSON(schemaOutAbsolutePath, log) {
|
|
7
7
|
const result = {
|
|
8
|
-
$schema:
|
|
8
|
+
$schema: VovkSchemaIdEnum.SCHEMA,
|
|
9
9
|
config: {},
|
|
10
10
|
segments: {},
|
|
11
11
|
};
|
|
12
|
-
const { log } = projectInfo;
|
|
13
12
|
// Handle config.json
|
|
14
13
|
const configPath = path.join(schemaOutAbsolutePath, 'config.json');
|
|
15
14
|
try {
|