vovk-cli 0.1.3 → 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/{schemaTs → schema-ts}/schema.ts.ejs +1 -1
- package/client-templates/{tsBase → ts-base}/index.ts.ejs +1 -1
- package/dist/bundle/index.d.mts +1 -1
- package/dist/bundle/index.mjs +67 -45
- package/dist/dev/{diffSegmentSchema.d.mts → diff-segment-schema.d.mts} +0 -17
- package/dist/dev/{diffSegmentSchema.mjs → diff-segment-schema.mjs} +1 -17
- package/dist/dev/{ensureSchemaFiles.d.mts → ensure-schema-files.d.mts} +1 -1
- package/dist/dev/{ensureSchemaFiles.mjs → ensure-schema-files.mjs} +30 -12
- package/dist/dev/index.mjs +23 -17
- package/dist/dev/log-diff-result.d.mts +3 -0
- package/dist/dev/{logDiffResult.mjs → log-diff-result.mjs} +2 -2
- package/dist/dev/{writeMetaJson.d.mts → write-meta-json.d.mts} +1 -1
- package/dist/dev/{writeMetaJson.mjs → write-meta-json.mjs} +3 -3
- package/dist/dev/{writeOneSegmentSchemaFile.d.mts → write-one-segment-schema-file.d.mts} +1 -1
- package/dist/dev/{writeOneSegmentSchemaFile.mjs → write-one-segment-schema-file.mjs} +8 -3
- package/dist/generate/ensure-client.d.mts +3 -0
- package/dist/generate/{ensureClient.mjs → ensure-client.mjs} +1 -1
- package/dist/generate/generate.d.mts +2 -2
- package/dist/generate/generate.mjs +41 -28
- package/dist/generate/{getClientTemplateFiles.d.mts → get-client-template-files.d.mts} +1 -1
- package/dist/generate/{getClientTemplateFiles.mjs → get-client-template-files.mjs} +8 -4
- package/dist/generate/{getProjectFullSchema.d.mts → get-project-full-schema.d.mts} +1 -1
- package/dist/generate/{getProjectFullSchema.mjs → get-project-full-schema.mjs} +3 -3
- package/dist/generate/{getTemplateClientImports.mjs → get-template-client-imports.mjs} +2 -2
- package/dist/generate/index.d.mts +2 -2
- package/dist/generate/index.mjs +46 -34
- package/dist/generate/{writeOneClientFile.d.mts → write-one-client-file.d.mts} +5 -5
- package/dist/generate/{writeOneClientFile.mjs → write-one-client-file.mjs} +10 -8
- package/dist/{getProjectInfo/getConfig/getRelativeSrcRoot.mjs → get-project-info/get-config/get-relative-src-root.mjs} +1 -1
- package/dist/get-project-info/get-config/get-template-defs.d.mts +22 -0
- package/dist/{getProjectInfo/getConfig/getTemplateDefs.mjs → get-project-info/get-config/get-template-defs.mjs} +35 -61
- package/dist/{getProjectInfo/getConfig/getUserConfig.mjs → get-project-info/get-config/get-user-config.mjs} +2 -2
- package/dist/{getProjectInfo/getConfig → get-project-info/get-config}/index.d.mts +2 -2
- package/dist/{getProjectInfo/getConfig → get-project-info/get-config}/index.mjs +17 -12
- package/dist/{getProjectInfo/getMetaSchema.d.mts → get-project-info/get-meta-schema.d.mts} +1 -1
- package/dist/{getProjectInfo → get-project-info}/index.mjs +3 -3
- package/dist/index.mjs +25 -16
- package/dist/init/{createConfig.d.mts → create-config.d.mts} +1 -1
- package/dist/init/{createConfig.mjs → create-config.mjs} +6 -6
- package/dist/init/index.d.mts +1 -1
- package/dist/init/index.mjs +54 -22
- package/dist/init/{installDependencies.d.mts → install-dependencies.d.mts} +2 -1
- package/dist/init/{installDependencies.mjs → install-dependencies.mjs} +11 -3
- package/dist/init/{logUpdateDependenciesError.d.mts → log-update-dependencies-error.d.mts} +2 -2
- package/dist/init/{logUpdateDependenciesError.mjs → log-update-dependencies-error.mjs} +1 -1
- package/dist/init/{updateDependenciesWithoutInstalling.d.mts → update-dependencies-without-installing.d.mts} +1 -1
- package/dist/init/{updateDependenciesWithoutInstalling.mjs → update-dependencies-without-installing.mjs} +1 -2
- package/dist/init/update-gitignore.d.mts +2 -0
- package/dist/init/update-gitignore.mjs +20 -0
- package/dist/new/index.d.mts +1 -1
- package/dist/new/index.mjs +2 -2
- package/dist/new/{newModule.d.mts → new-module.d.mts} +1 -1
- package/dist/new/{newModule.mjs → new-module.mjs} +15 -9
- package/dist/new/{newSegment.d.mts → new-segment.d.mts} +1 -1
- package/dist/new/{newSegment.mjs → new-segment.mjs} +11 -6
- package/dist/new/render.mjs +3 -3
- package/dist/types.d.mts +1 -1
- package/dist/utils/{compileJSONSchemaToTypeScriptType.mjs → compile-json-schema-to-typescript-type.mjs} +1 -1
- package/dist/utils/{formatLoggedSegmentName.mjs → format-logged-segment-name.mjs} +1 -1
- package/dist/utils/{generateFnName.d.mts → generate-fn-name.d.mts} +0 -9
- package/dist/utils/{generateFnName.mjs → 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 +1 -0
- package/dist/utils/{getAvailablePort.mjs → get-available-port.mjs} +2 -14
- package/dist/utils/get-file-system-entry-type.d.mts +6 -0
- package/dist/utils/{getFileSystemEntryType.mjs → get-file-system-entry-type.mjs} +5 -5
- package/dist/utils/{getPackageJson.d.mts → get-package-json.d.mts} +1 -1
- package/dist/utils/{getPackageJson.mjs → get-package-json.mjs} +1 -1
- package/dist/utils/{locateSegments.d.mts → locate-segments.d.mts} +1 -1
- package/dist/utils/{locateSegments.mjs → locate-segments.mjs} +1 -1
- package/dist/utils/{normalizeOpenAPIMixin.d.mts → normalize-openapi-mixin.d.mts} +2 -2
- package/dist/utils/{normalizeOpenAPIMixin.mjs → normalize-openapi-mixin.mjs} +20 -5
- package/dist/utils/prettify.d.mts +4 -0
- package/dist/utils/prettify.mjs +39 -3
- package/dist/utils/remove-unlisted-directories.d.mts +1 -0
- package/dist/utils/remove-unlisted-directories.mjs +99 -0
- package/dist/utils/{resolveAbsoluteModulePath.mjs → resolve-absolute-module-path.mjs} +2 -3
- package/dist/utils/{updateConfigProperty.mjs → update-config-property.mjs} +1 -1
- package/module-templates/arktype/controller.ts.ejs +2 -2
- package/module-templates/type/controller.ts.ejs +2 -2
- package/module-templates/type/service.ts.ejs +2 -2
- package/module-templates/valibot/controller.ts.ejs +2 -2
- package/module-templates/zod/controller.ts.ejs +2 -2
- package/package.json +23 -30
- package/client-templates/jsBase/index.d.ts.ejs +0 -21
- package/client-templates/jsBase/index.js.ejs +0 -18
- package/client-templates/openapiJs/openapi.d.ts.ejs +0 -4
- package/client-templates/openapiJs/openapi.js.ejs +0 -4
- package/client-templates/schemaJs/schema.d.ts.ejs +0 -10
- package/client-templates/schemaJs/schema.js.ejs +0 -29
- package/dist/dev/logDiffResult.d.mts +0 -3
- package/dist/generate/ensureClient.d.mts +0 -3
- package/dist/getProjectInfo/getConfig/getTemplateDefs.d.mts +0 -25
- package/dist/utils/getAvailablePort.d.mts +0 -9
- package/dist/utils/getFileSystemEntryType.d.mts +0 -5
- package/dist/utils/removeUnlistedDirectories.d.mts +0 -9
- package/dist/utils/removeUnlistedDirectories.mjs +0 -60
- package/client-templates/{openapiJson → openapi-json}/openapi.json.ejs +0 -0
- package/client-templates/{openapiTs → openapi-ts}/openapi.ts.ejs +0 -0
- package/client-templates/{packageJson → package-json}/package.json.ejs +0 -0
- package/client-templates/{schemaJson → schema-json}/schema.json.ejs +0 -0
- package/dist/generate/{getTemplateClientImports.d.mts → get-template-client-imports.d.mts} +0 -0
- package/dist/{getProjectInfo/getConfig/getConfigAbsolutePaths.d.mts → get-project-info/get-config/get-config-absolute-paths.d.mts} +0 -0
- package/dist/{getProjectInfo/getConfig/getConfigAbsolutePaths.mjs → get-project-info/get-config/get-config-absolute-paths.mjs} +0 -0
- package/dist/{getProjectInfo/getConfig/getRelativeSrcRoot.d.mts → get-project-info/get-config/get-relative-src-root.d.mts} +0 -0
- package/dist/{getProjectInfo/getConfig/getUserConfig.d.mts → get-project-info/get-config/get-user-config.d.mts} +0 -0
- package/dist/{getProjectInfo/getMetaSchema.mjs → get-project-info/get-meta-schema.mjs} +1 -1
- package/dist/{getProjectInfo → get-project-info}/index.d.mts +0 -0
- package/dist/init/{checkTSConfigForExperimentalDecorators.d.mts → check-tsconfig-for-experimental-decorators.d.mts} +0 -0
- package/dist/init/{checkTSConfigForExperimentalDecorators.mjs → check-tsconfig-for-experimental-decorators.mjs} +1 -1
- package/dist/init/{updateNPMScripts.d.mts → update-npm-scripts.d.mts} +0 -0
- package/dist/init/{updateNPMScripts.mjs → update-npm-scripts.mjs} +0 -0
- package/dist/init/{updateTypeScriptConfig.d.mts → update-typescript-config.d.mts} +0 -0
- package/dist/init/{updateTypeScriptConfig.mjs → update-typescript-config.mjs} +1 -1
- package/dist/new/{addClassToSegmentCode.d.mts → add-class-to-segment-code.d.mts} +0 -0
- package/dist/new/{addClassToSegmentCode.mjs → add-class-to-segment-code.mjs} +0 -0
- package/dist/new/{addCommonTerms.d.mts → add-common-terms.d.mts} +0 -0
- package/dist/new/{addCommonTerms.mjs → add-common-terms.mjs} +0 -0
- package/dist/utils/{chalkHighlightThing.d.mts → chalk-highlight-thing.d.mts} +0 -0
- package/dist/utils/{chalkHighlightThing.mjs → chalk-highlight-thing.mjs} +0 -0
- package/dist/utils/{compileJSONSchemaToTypeScriptType.d.mts → compile-json-schema-to-typescript-type.d.mts} +1 -1
- package/dist/utils/{compileTs.d.mts → compile-ts.d.mts} +0 -0
- package/dist/utils/{compileTs.mjs → compile-ts.mjs} +1 -1
- /package/dist/utils/{debounceWithArgs.d.mts → debounce-with-args.d.mts} +0 -0
- /package/dist/utils/{debounceWithArgs.mjs → debounce-with-args.mjs} +0 -0
- /package/dist/utils/{formatLoggedSegmentName.d.mts → format-logged-segment-name.d.mts} +0 -0
- /package/dist/utils/{getLogger.d.mts → get-logger.d.mts} +0 -0
- /package/dist/utils/{getLogger.mjs → get-logger.mjs} +0 -0
- /package/dist/utils/{getNPMPackageMetadata.d.mts → get-npm-package-metadata.d.mts} +0 -0
- /package/dist/utils/{getNPMPackageMetadata.mjs → get-npm-package-metadata.mjs} +0 -0
- /package/dist/utils/{getPublicModuleNameFromPath.d.mts → get-public-module-name-from-path.d.mts} +0 -0
- /package/dist/utils/{getPublicModuleNameFromPath.mjs → get-public-module-name-from-path.mjs} +0 -0
- /package/dist/utils/{pickSegmentFullSchema.d.mts → pick-segment-full-schema.d.mts} +0 -0
- /package/dist/utils/{pickSegmentFullSchema.mjs → pick-segment-full-schema.mjs} +0 -0
- /package/dist/utils/{resolveAbsoluteModulePath.d.mts → resolve-absolute-module-path.d.mts} +0 -0
- /package/dist/utils/{updateConfigProperty.d.mts → update-config-property.d.mts} +0 -0
|
@@ -1,10 +1,5 @@
|
|
|
1
1
|
import net from 'node:net';
|
|
2
|
-
//
|
|
3
|
-
/**
|
|
4
|
-
* Checks if a port is available.
|
|
5
|
-
* @param {number} port - The port to check.
|
|
6
|
-
* @param {(isAvailable: boolean) => void} callback - The callback function.
|
|
7
|
-
*/
|
|
2
|
+
// checks if a port is free
|
|
8
3
|
function checkPort(port, callback) {
|
|
9
4
|
const server = net.createServer();
|
|
10
5
|
server.listen(port, () => {
|
|
@@ -16,14 +11,7 @@ function checkPort(port, callback) {
|
|
|
16
11
|
callback(false);
|
|
17
12
|
});
|
|
18
13
|
}
|
|
19
|
-
|
|
20
|
-
* Finds an available port starting from a given port.
|
|
21
|
-
* @param {number} startPort - The port to start checking from.
|
|
22
|
-
* @param {number} maxAttempts - The maximum number of attempts to find an available port.
|
|
23
|
-
* @param {number} attempt - The current attempt number.
|
|
24
|
-
* @param {(failedPort: number, tryingPort: number) => void} onWarning - The callback function for warnings.
|
|
25
|
-
* @returns {Promise<string>}
|
|
26
|
-
*/
|
|
14
|
+
// finds a free port starting from startPort, up to maxAttempts
|
|
27
15
|
export function getAvailablePort(startPort, maxAttempts, attempt, onWarning) {
|
|
28
16
|
return new Promise((resolve, reject) => {
|
|
29
17
|
checkPort(startPort, (isAvailable) => {
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare const FileSystemEntryType: {
|
|
2
|
+
readonly FILE: "FILE";
|
|
3
|
+
readonly DIRECTORY: "DIRECTORY";
|
|
4
|
+
};
|
|
5
|
+
export type FileSystemEntryType = (typeof FileSystemEntryType)[keyof typeof FileSystemEntryType];
|
|
6
|
+
export declare function getFileSystemEntryType(filePath: string): Promise<FileSystemEntryType | null>;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import fs from 'node:fs/promises';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
}
|
|
2
|
+
// const object instead of enum, node 26 runs ts with erasable syntax only
|
|
3
|
+
export const FileSystemEntryType = {
|
|
4
|
+
FILE: 'FILE',
|
|
5
|
+
DIRECTORY: 'DIRECTORY',
|
|
6
|
+
};
|
|
7
7
|
export async function getFileSystemEntryType(filePath) {
|
|
8
8
|
try {
|
|
9
9
|
const stats = await fs.stat(filePath);
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { PackageJson } from 'type-fest';
|
|
2
|
-
import type { ProjectInfo } from '../
|
|
2
|
+
import type { ProjectInfo } from '../get-project-info/index.mjs';
|
|
3
3
|
export declare function getPackageJson(cwd: string, log: ProjectInfo['log']): Promise<PackageJson>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import fs from 'node:fs/promises';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
-
import { chalkHighlightThing } from './
|
|
3
|
+
import { chalkHighlightThing } from './chalk-highlight-thing.mjs';
|
|
4
4
|
let cachedPromise;
|
|
5
5
|
export function getPackageJson(cwd, log) {
|
|
6
6
|
const pkgPath = path.join(cwd, 'package.json');
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import fs from 'node:fs/promises';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
-
import { getFileSystemEntryType } from './
|
|
3
|
+
import { getFileSystemEntryType } from './get-file-system-entry-type.mjs';
|
|
4
4
|
export async function locateSegments({ dir, rootDir, config, log, }) {
|
|
5
5
|
let results = [];
|
|
6
6
|
if (!dir)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import type { OpenAPIObject } from 'openapi3-ts/oas31';
|
|
1
2
|
import type { HttpMethod, VovkConfig } from 'vovk';
|
|
2
3
|
import type { VovkOperationObject, VovkStrictConfig } from 'vovk/internal';
|
|
3
|
-
import type {
|
|
4
|
-
import type { ProjectInfo } from '../getProjectInfo/index.mjs';
|
|
4
|
+
import type { ProjectInfo } from '../get-project-info/index.mjs';
|
|
5
5
|
export type GetOpenAPINameFn = (config: {
|
|
6
6
|
operationObject: VovkOperationObject;
|
|
7
7
|
method: HttpMethod;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import fs from 'node:fs/promises';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
-
import * as YAML from 'yaml';
|
|
4
|
-
import { chalkHighlightThing } from './chalkHighlightThing.mjs';
|
|
5
3
|
import camelCase from 'lodash/camelCase.js';
|
|
6
|
-
import
|
|
4
|
+
import * as YAML from 'yaml';
|
|
5
|
+
import { chalkHighlightThing } from './chalk-highlight-thing.mjs';
|
|
6
|
+
import { generateFnName } from './generate-fn-name.mjs';
|
|
7
7
|
const normalizeGetModuleName = (getModuleName) => {
|
|
8
|
+
getModuleName = getModuleName ?? 'api';
|
|
8
9
|
if (typeof getModuleName === 'string') {
|
|
9
10
|
const moduleName = getModuleName;
|
|
10
11
|
getModuleName = () => moduleName;
|
|
@@ -15,6 +16,7 @@ const normalizeGetModuleName = (getModuleName) => {
|
|
|
15
16
|
return getModuleName;
|
|
16
17
|
};
|
|
17
18
|
const normalizeGetMethodName = (getMethodName) => {
|
|
19
|
+
getMethodName = getMethodName ?? 'auto';
|
|
18
20
|
if (getMethodName === 'camel-case-operation-id') {
|
|
19
21
|
getMethodName = ({ operationObject }) => {
|
|
20
22
|
const operationId = operationObject.operationId;
|
|
@@ -47,8 +49,21 @@ async function getOpenApiSpecLocal(openApiSpecFilePath, cwd) {
|
|
|
47
49
|
return (fileName.endsWith('.json') ? JSON.parse(openApiSpecContent) : YAML.parse(openApiSpecContent));
|
|
48
50
|
}
|
|
49
51
|
async function getOpenApiSpecRemote({ cwd, url, fallback, log, }) {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
+
let resp;
|
|
53
|
+
let text;
|
|
54
|
+
try {
|
|
55
|
+
resp = await fetch(url);
|
|
56
|
+
text = await resp.text();
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
// network failures (DNS, offline, timeouts) should use the fallback too
|
|
60
|
+
const message = `Failed to fetch OpenAPI spec from ${chalkHighlightThing(url)}: ${error.message}`;
|
|
61
|
+
if (fallback) {
|
|
62
|
+
log.warn(`${message}. Falling back to ${chalkHighlightThing(fallback)}`);
|
|
63
|
+
return getOpenApiSpecLocal(fallback, cwd);
|
|
64
|
+
}
|
|
65
|
+
throw new Error(message);
|
|
66
|
+
}
|
|
52
67
|
if (!resp.ok) {
|
|
53
68
|
if (fallback) {
|
|
54
69
|
log.warn(`Failed to fetch OpenAPI spec from ${chalkHighlightThing(url)}: ${resp.status} ${resp.statusText}. Falling back to ${chalkHighlightThing(fallback)}`);
|
|
@@ -1 +1,5 @@
|
|
|
1
|
+
import type { getLogger } from './get-logger.mjs';
|
|
2
|
+
/** Formats with the project-installed prettier; returns the code unchanged when it's not installed. */
|
|
1
3
|
export declare function prettify(code: string, absoluteFilePath: string): Promise<string>;
|
|
4
|
+
/** Warns once per run when prettifyClient is enabled but prettier is not installed. */
|
|
5
|
+
export declare function warnIfPrettierMissing(log: ReturnType<typeof getLogger>): Promise<void>;
|
package/dist/utils/prettify.mjs
CHANGED
|
@@ -1,10 +1,46 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { createRequire } from 'node:module';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { pathToFileURL } from 'node:url';
|
|
4
|
+
let prettierPromise;
|
|
5
|
+
let warned = false;
|
|
6
|
+
/** Prettier is not a CLI dependency; it's resolved from the user's project if installed. */
|
|
7
|
+
function getPrettier() {
|
|
8
|
+
prettierPromise ??= (async () => {
|
|
9
|
+
try {
|
|
10
|
+
const require = createRequire(path.join(process.cwd(), 'noop.js'));
|
|
11
|
+
const mod = (await import(pathToFileURL(require.resolve('prettier')).href));
|
|
12
|
+
return mod.default ?? mod;
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
})();
|
|
18
|
+
return prettierPromise;
|
|
19
|
+
}
|
|
20
|
+
/** Formats with the project-installed prettier; returns the code unchanged when it's not installed. */
|
|
2
21
|
export async function prettify(code, absoluteFilePath) {
|
|
22
|
+
const prettier = await getPrettier();
|
|
23
|
+
if (!prettier)
|
|
24
|
+
return code;
|
|
3
25
|
const options = await prettier.resolveConfig(absoluteFilePath);
|
|
4
26
|
const finalOptions = {
|
|
5
27
|
...options,
|
|
6
28
|
filepath: absoluteFilePath, // for selecting the correct parser
|
|
7
29
|
};
|
|
8
|
-
|
|
9
|
-
|
|
30
|
+
try {
|
|
31
|
+
return await prettier.format(code, finalOptions);
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
// no parser for this file type (.rs, .toml, .py etc)
|
|
35
|
+
if (error.name === 'UndefinedParserError')
|
|
36
|
+
return code;
|
|
37
|
+
throw error;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/** Warns once per run when prettifyClient is enabled but prettier is not installed. */
|
|
41
|
+
export async function warnIfPrettierMissing(log) {
|
|
42
|
+
if (warned || (await getPrettier()))
|
|
43
|
+
return;
|
|
44
|
+
warned = true;
|
|
45
|
+
log.warn('prettifyClient is enabled but prettier is not installed. Either install it or set prettifyClient to false to suppress this warning.');
|
|
10
46
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function removeUnlistedDirectories(folderPath: string, allowedDirs: string[], generatedRelPaths?: string[]): Promise<string[]>;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { GENERATED_BANNER_PREFIX } from './generated-banner.mjs';
|
|
4
|
+
import { FileSystemEntryType, getFileSystemEntryType } from './get-file-system-entry-type.mjs';
|
|
5
|
+
// removes all dirs in folderPath that aren't in allowedDirs, supports nested paths like 'foo/bar/baz'
|
|
6
|
+
// generatedRelPaths guards user files: a dir holding anything the generator wouldn't write is kept,
|
|
7
|
+
// returns the dirs that were kept for that reason
|
|
8
|
+
export async function removeUnlistedDirectories(folderPath, allowedDirs, generatedRelPaths) {
|
|
9
|
+
// Normalize all allowed paths to use the system-specific separator
|
|
10
|
+
const normalizedAllowedDirs = allowedDirs.map((dir) => dir.split('/').join(path.sep));
|
|
11
|
+
const skipped = [];
|
|
12
|
+
// Process the directory tree recursively
|
|
13
|
+
await processDirectory(folderPath, '', normalizedAllowedDirs, generatedRelPaths, skipped);
|
|
14
|
+
return skipped;
|
|
15
|
+
}
|
|
16
|
+
// "[package_name]" is substituted at write time, so treat it as a wildcard segment
|
|
17
|
+
function matchesGeneratedPath(relPath, generatedRelPaths) {
|
|
18
|
+
const segments = relPath.split(path.sep);
|
|
19
|
+
return generatedRelPaths.some((generated) => {
|
|
20
|
+
const generatedSegments = generated.split(path.sep);
|
|
21
|
+
if (generatedSegments.length > segments.length)
|
|
22
|
+
return false;
|
|
23
|
+
// a nested segment such as bar/baz adds leading directories, so match the tail
|
|
24
|
+
const offset = segments.length - generatedSegments.length;
|
|
25
|
+
return generatedSegments.every((segment, i) => segment === '[package_name]' || segment === segments[offset + i]);
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
// a matching name is not enough, a user file may be named like ours, so require our banner too.
|
|
29
|
+
// json holds no comment and therefore no banner, so there the name stays the only signal
|
|
30
|
+
async function isGeneratedFile(absolutePath, relPath, generatedRelPaths) {
|
|
31
|
+
if (!matchesGeneratedPath(relPath, generatedRelPaths))
|
|
32
|
+
return false;
|
|
33
|
+
if (path.extname(absolutePath) === '.json')
|
|
34
|
+
return true;
|
|
35
|
+
try {
|
|
36
|
+
const content = await fs.readFile(absolutePath, 'utf-8');
|
|
37
|
+
return content.slice(0, content.indexOf('\n') + 1 || undefined).includes(GENERATED_BANNER_PREFIX);
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
// true when every file below dirPath is something the generator wrote
|
|
44
|
+
async function containsOnlyGenerated(dirPath, generatedRelPaths, relativePath = '') {
|
|
45
|
+
const entries = await fs.readdir(path.join(dirPath, relativePath), { withFileTypes: true });
|
|
46
|
+
for (const entry of entries) {
|
|
47
|
+
const entryRelPath = relativePath ? path.join(relativePath, entry.name) : entry.name;
|
|
48
|
+
if (entry.isDirectory()) {
|
|
49
|
+
if (!(await containsOnlyGenerated(dirPath, generatedRelPaths, entryRelPath)))
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
else if (!(await isGeneratedFile(path.join(dirPath, entryRelPath), entryRelPath, generatedRelPaths))) {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
// recursively decides which dirs to keep or remove
|
|
59
|
+
async function processDirectory(basePath, relativePath, allowedDirs, generatedRelPaths, skipped) {
|
|
60
|
+
const currentDirPath = path.join(basePath, relativePath);
|
|
61
|
+
// check if the current path is a directory
|
|
62
|
+
const type = await getFileSystemEntryType(currentDirPath);
|
|
63
|
+
if (type !== FileSystemEntryType.DIRECTORY) {
|
|
64
|
+
// If it's not a directory, return early
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
// Read all entries in the current directory
|
|
68
|
+
const entries = await fs.readdir(currentDirPath, { withFileTypes: true });
|
|
69
|
+
// Process only directories
|
|
70
|
+
const dirEntries = entries.filter((entry) => entry.isDirectory());
|
|
71
|
+
// Check each directory
|
|
72
|
+
for (const dir of dirEntries) {
|
|
73
|
+
// Calculate the new relative path
|
|
74
|
+
const newRelativePath = relativePath ? path.join(relativePath, dir.name) : dir.name;
|
|
75
|
+
// Check if this directory or any of its subdirectories should be kept
|
|
76
|
+
const shouldKeep = allowedDirs.some((allowedDir) => {
|
|
77
|
+
// Direct match
|
|
78
|
+
if (allowedDir === newRelativePath)
|
|
79
|
+
return true;
|
|
80
|
+
// Check if it's a parent path of an allowed directory
|
|
81
|
+
// e.g. "foo" is a parent of "foo/bar/baz"
|
|
82
|
+
return allowedDir.startsWith(newRelativePath + path.sep);
|
|
83
|
+
});
|
|
84
|
+
if (shouldKeep) {
|
|
85
|
+
// Recursively process this directory's contents
|
|
86
|
+
await processDirectory(basePath, newRelativePath, allowedDirs, generatedRelPaths, skipped);
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
const fullPath = path.join(basePath, newRelativePath);
|
|
90
|
+
// never delete a directory that holds files we did not generate
|
|
91
|
+
if (generatedRelPaths && !(await containsOnlyGenerated(fullPath, generatedRelPaths))) {
|
|
92
|
+
skipped.push(fullPath);
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
// Remove this directory since it's not in the allowed list
|
|
96
|
+
await fs.rm(fullPath, { recursive: true, force: true });
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import path from 'node:path';
|
|
2
1
|
import { createRequire } from 'node:module';
|
|
3
|
-
import
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { getPublicModuleNameFromPath } from './get-public-module-name-from-path.mjs';
|
|
4
4
|
// Returns the path up to and including the last occurrence of the given module name
|
|
5
5
|
export function getPathUpToModule(moduleName, fullPath) {
|
|
6
6
|
const idx = fullPath.lastIndexOf(moduleName);
|
|
@@ -24,7 +24,6 @@ export function resolveAbsoluteModulePath(modulePath, cwd) {
|
|
|
24
24
|
return path.resolve(getPathUpToModule(moduleName, path.dirname(resolved)), restPath);
|
|
25
25
|
}
|
|
26
26
|
catch (e) {
|
|
27
|
-
// eslint-disable-next-line no-console
|
|
28
27
|
console.error(`Error resolving module path: ${modulePath}`, e);
|
|
29
28
|
// If resolution fails, fall back to the original behavior
|
|
30
29
|
return path.resolve(cwd, './node_modules', modulePath);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { IndentationText, NewLineKind, Node, Project, QuoteKind, SyntaxKind, } from 'ts-morph';
|
|
2
2
|
export function updateConfigProperty(sourceCode, pathToProperty, newValue) {
|
|
3
3
|
const project = createProject();
|
|
4
4
|
const sourceFile = project.createSourceFile('config-temp.mts', sourceCode, { overwrite: true });
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
}; %>
|
|
5
5
|
---
|
|
6
6
|
outDir: <%= t.defaultOutDir %>
|
|
7
|
-
fileName: <%=
|
|
7
|
+
fileName: <%= t['the-thing'] + '-controller.ts' %>
|
|
8
8
|
sourceName: <%= vars.ModuleName %>
|
|
9
9
|
compiledName: <%= t.TheThing + 'RPC' %>
|
|
10
10
|
---
|
|
@@ -12,7 +12,7 @@ compiledName: <%= t.TheThing + 'RPC' %>
|
|
|
12
12
|
import { procedure, prefix, get, put, post, del, operation } from 'vovk';
|
|
13
13
|
import { type } from 'arktype';
|
|
14
14
|
<% if(t.withService) { %>
|
|
15
|
-
import <%= vars.ServiceName %> from './<%=
|
|
15
|
+
import <%= vars.ServiceName %> from './<%= t['the-thing'] %>-service<%= t.nodeNextResolutionExt.ts %>';
|
|
16
16
|
<% } %>
|
|
17
17
|
|
|
18
18
|
@prefix('<%= t['the-things'] %>')
|
|
@@ -4,14 +4,14 @@
|
|
|
4
4
|
}; %>
|
|
5
5
|
---
|
|
6
6
|
outDir: <%= t.defaultOutDir %>
|
|
7
|
-
fileName: <%=
|
|
7
|
+
fileName: <%= t['the-thing'] + '-controller.ts' %>
|
|
8
8
|
sourceName: <%= vars.ControllerName %>
|
|
9
9
|
compiledName: <%= t.TheThing + 'RPC' %>
|
|
10
10
|
---
|
|
11
11
|
|
|
12
12
|
import { prefix, get, put, post, del, operation, type VovkRequest } from 'vovk';
|
|
13
13
|
<% if(t.withService) { %>
|
|
14
|
-
import <%= vars.ServiceName %> from './<%=
|
|
14
|
+
import <%= vars.ServiceName %> from './<%= t['the-thing'] %>-service<%= t.nodeNextResolutionExt.ts %>';
|
|
15
15
|
<% } %>
|
|
16
16
|
|
|
17
17
|
@prefix('<%= t['the-things'] %>')
|
|
@@ -4,12 +4,12 @@
|
|
|
4
4
|
}; %>
|
|
5
5
|
---
|
|
6
6
|
outDir: <%= t.defaultOutDir %>
|
|
7
|
-
fileName: <%=
|
|
7
|
+
fileName: <%= t['the-thing'] + '-service.ts' %>
|
|
8
8
|
sourceName: <%= vars.ServiceName %>
|
|
9
9
|
---
|
|
10
10
|
|
|
11
11
|
import type { VovkBody, VovkParams } from 'vovk';
|
|
12
|
-
import type <%= vars.ControllerName %> from './<%=
|
|
12
|
+
import type <%= vars.ControllerName %> from './<%= t['the-thing'] %>-controller<%= t.nodeNextResolutionExt.ts %>';
|
|
13
13
|
|
|
14
14
|
export default class <%= vars.ServiceName %> {
|
|
15
15
|
static get<%= t.TheThings %> = () => {
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
}; %>
|
|
5
5
|
---
|
|
6
6
|
outDir: <%= t.defaultOutDir %>
|
|
7
|
-
fileName: <%=
|
|
7
|
+
fileName: <%= t['the-thing'] + '-controller.ts' %>
|
|
8
8
|
sourceName: <%= vars.ModuleName %>
|
|
9
9
|
compiledName: <%= t.TheThing + 'RPC' %>
|
|
10
10
|
---
|
|
@@ -13,7 +13,7 @@ import { procedure, prefix, get, put, post, del, operation } from 'vovk';
|
|
|
13
13
|
import * as v from 'valibot';
|
|
14
14
|
import { toStandardJsonSchema } from '@valibot/to-json-schema';
|
|
15
15
|
<% if(t.withService) { %>
|
|
16
|
-
import <%= vars.ServiceName %> from './<%=
|
|
16
|
+
import <%= vars.ServiceName %> from './<%= t['the-thing'] %>-service<%= t.nodeNextResolutionExt.ts %>';
|
|
17
17
|
<% } %>
|
|
18
18
|
|
|
19
19
|
@prefix('<%= t['the-things'] %>')
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
}; %>
|
|
5
5
|
---
|
|
6
6
|
outDir: <%= t.defaultOutDir %>
|
|
7
|
-
fileName: <%=
|
|
7
|
+
fileName: <%= t['the-thing'] + '-controller.ts' %>
|
|
8
8
|
sourceName: <%= vars.ModuleName %>
|
|
9
9
|
compiledName: <%= t.TheThing + 'RPC' %>
|
|
10
10
|
---
|
|
@@ -12,7 +12,7 @@ compiledName: <%= t.TheThing + 'RPC' %>
|
|
|
12
12
|
import { procedure, prefix, get, put, post, del, operation } from 'vovk';
|
|
13
13
|
import { z } from 'zod';
|
|
14
14
|
<% if(t.withService) { %>
|
|
15
|
-
import <%= vars.ServiceName %> from './<%=
|
|
15
|
+
import <%= vars.ServiceName %> from './<%= t['the-thing'] %>-service<%= t.nodeNextResolutionExt.ts %>';
|
|
16
16
|
<% } %>
|
|
17
17
|
|
|
18
18
|
@prefix('<%= t['the-things'] %>')
|
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vovk-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0-beta.0",
|
|
4
4
|
"description": "CLI tool for managing Vovk.ts projects",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
7
7
|
"client-templates",
|
|
8
|
-
"module-templates"
|
|
8
|
+
"module-templates",
|
|
9
|
+
"CHANGELOG.md"
|
|
9
10
|
],
|
|
10
11
|
"bin": {
|
|
11
12
|
"vovk": "./dist/index.mjs"
|
|
@@ -18,10 +19,10 @@
|
|
|
18
19
|
"build": "rm -rf dist tsconfig.build.tsbuildinfo && tsc -P tsconfig.build.json",
|
|
19
20
|
"postbuild": "chmod +x ./dist/index.mjs",
|
|
20
21
|
"pre-test": "npm run build && npm run clear-test-cache",
|
|
21
|
-
"test-only": "npm run pre-test && NODE_ENV=test node --experimental-
|
|
22
|
-
"test": "npm run pre-test && NODE_ENV=test node --experimental-
|
|
22
|
+
"test-only": "npm run pre-test && NODE_ENV=test node --experimental-strip-types --experimental-vm-modules --test --test-only test/spec/**/*.mts",
|
|
23
|
+
"test": "npm run pre-test && NODE_ENV=test node --experimental-strip-types --experimental-vm-modules --test --test-concurrency=1 test/spec/**/*.mts",
|
|
23
24
|
"tsc": "tsc --noEmit",
|
|
24
|
-
"ncu": "npm-check-updates -u -x commander,
|
|
25
|
+
"ncu": "npm-check-updates -u -x commander,tsdown",
|
|
25
26
|
"npm-publish": "npm publish",
|
|
26
27
|
"clear-test-cache": "rm -rf ./tmp_*"
|
|
27
28
|
},
|
|
@@ -44,36 +45,29 @@
|
|
|
44
45
|
"peerDependencies": {
|
|
45
46
|
"vovk": ">=3.0.0"
|
|
46
47
|
},
|
|
47
|
-
"optionalDependencies": {
|
|
48
|
-
"@rolldown/binding-linux-x64-gnu": "1.0.0-rc.13"
|
|
49
|
-
},
|
|
50
48
|
"dependencies": {
|
|
51
49
|
"@iarna/toml": "^2.2.5",
|
|
52
|
-
"@inquirer/prompts": "^8.
|
|
53
|
-
"@npmcli/package-json": "^
|
|
50
|
+
"@inquirer/prompts": "^8.5.2",
|
|
51
|
+
"@npmcli/package-json": "^8.0.0",
|
|
54
52
|
"@types/json-schema": "^7.0.15",
|
|
55
|
-
"@types/lodash": "^4.17.
|
|
56
|
-
"chalk": "^
|
|
53
|
+
"@types/lodash": "^4.17.25",
|
|
54
|
+
"chalk": "^6.0.0",
|
|
57
55
|
"chokidar": "^5.0.0",
|
|
58
|
-
"clone-deep": "^4.0.1",
|
|
59
56
|
"commander": "^13.1.0",
|
|
60
|
-
"concurrently": "^
|
|
61
|
-
"dotenv": "^17.4.
|
|
62
|
-
"ejs": "^
|
|
63
|
-
"get-tsconfig": "^4.
|
|
57
|
+
"concurrently": "^10.0.4",
|
|
58
|
+
"dotenv": "^17.4.2",
|
|
59
|
+
"ejs": "^6.0.1",
|
|
60
|
+
"get-tsconfig": "^4.14.1",
|
|
64
61
|
"glob": "^13.0.6",
|
|
65
62
|
"gray-matter": "^4.0.3",
|
|
66
|
-
"inflection": "^3.0.2",
|
|
67
63
|
"jsonc-parser": "^3.3.1",
|
|
68
64
|
"lodash": "^4.18.1",
|
|
69
65
|
"loglevel": "^1.9.2",
|
|
70
66
|
"pluralize": "^8.0.0",
|
|
71
|
-
"
|
|
72
|
-
"
|
|
73
|
-
"
|
|
74
|
-
"
|
|
75
|
-
"undici": "^8.0.2",
|
|
76
|
-
"yaml": "^2.8.3"
|
|
67
|
+
"ts-morph": "^28.0.0",
|
|
68
|
+
"type-fest": "^5.8.0",
|
|
69
|
+
"undici": "^8.9.0",
|
|
70
|
+
"yaml": "^2.9.0"
|
|
77
71
|
},
|
|
78
72
|
"devDependencies": {
|
|
79
73
|
"@types/concat-stream": "^2.0.3",
|
|
@@ -81,13 +75,12 @@
|
|
|
81
75
|
"@types/js-yaml": "^4.0.9",
|
|
82
76
|
"@types/npmcli__package-json": "^4.0.4",
|
|
83
77
|
"@types/pluralize": "^0.0.33",
|
|
84
|
-
"@types/tar-stream": "^3.1.4",
|
|
85
78
|
"concat-stream": "^2.0.0",
|
|
86
|
-
"create-next-app": "^16.2.
|
|
79
|
+
"create-next-app": "^16.2.12",
|
|
87
80
|
"http-server": "^14.1.1",
|
|
88
|
-
"node-pty": "
|
|
89
|
-
"openapi3-ts": "^4.
|
|
90
|
-
"tsdown": "
|
|
91
|
-
"zod": "^4.3
|
|
81
|
+
"node-pty": "1.1.0",
|
|
82
|
+
"openapi3-ts": "^4.6.1",
|
|
83
|
+
"tsdown": "0.22.14",
|
|
84
|
+
"zod": "^4.4.3"
|
|
92
85
|
}
|
|
93
86
|
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
<%- t.getFirstLineBanner() %>
|
|
2
|
-
import type { VovkFetcher } from 'vovk/fetcher';
|
|
3
|
-
import type { createRPC } from '<%= t.commonImports.createRPC %>';
|
|
4
|
-
<% Object.values(t.schema.segments).filter((segment) => segment.emitSchema).forEach((segment, i) => { if(segment.segmentType !== 'mixin') { %>
|
|
5
|
-
import type { Controllers as Controllers<%= i %> } from "<%= t.segmentMeta[segment.segmentName].segmentImportPath %>";
|
|
6
|
-
<% }}) %>
|
|
7
|
-
<% if (t.hasMixins) { %>
|
|
8
|
-
import type { Controllers as MixinControllers, Mixins } from "./mixins";
|
|
9
|
-
<% } %>
|
|
10
|
-
<% Object.entries(t.reExports).forEach(([reExportWhat, reExportFrom]) => { %>
|
|
11
|
-
export { <%= reExportWhat %> } from '<%= reExportFrom %>';
|
|
12
|
-
<% }) %>
|
|
13
|
-
<% Object.values(t.schema.segments).filter((segment) => segment.emitSchema).forEach((segment, i) => { %>
|
|
14
|
-
<% Object.keys(segment.controllers).forEach((rpcModuleName) => { %>
|
|
15
|
-
export const <%= rpcModuleName %>: ReturnType<typeof createRPC<<%= segment.segmentType === 'mixin' ? `MixinControllers` : `Controllers${i}` %>["<%= rpcModuleName %>"], typeof import('<%- t.segmentImports[segment.segmentName].fetcher %>').fetcher extends VovkFetcher<infer U> ? U : never>>;
|
|
16
|
-
<% })
|
|
17
|
-
}) %>
|
|
18
|
-
export { schema } from './schema.js';
|
|
19
|
-
<% if (t.hasMixins) { %>
|
|
20
|
-
export { Mixins };
|
|
21
|
-
<% } %>
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
<%- t.getFirstLineBanner() %>
|
|
2
|
-
import { createRPC } from '<%= t.commonImports.createRPC %>';
|
|
3
|
-
import { schema } from './schema.js';
|
|
4
|
-
<% Object.entries(t.reExports).forEach(([reExportWhat, reExportFrom]) => { %>
|
|
5
|
-
export { <%= reExportWhat %> } from '<%= reExportFrom %>';
|
|
6
|
-
<% }) %>
|
|
7
|
-
<% Object.values(t.schema.segments).filter((segment) => segment.emitSchema).forEach((segment, i) => { %>
|
|
8
|
-
<% Object.keys(segment.controllers).forEach((rpcModuleName) => {
|
|
9
|
-
const apiRoot = t.segmentMeta[segment.segmentName].forceApiRoot ?? t.apiRoot; %>
|
|
10
|
-
export const <%= rpcModuleName %> = createRPC(
|
|
11
|
-
schema, '<%= segment.segmentName %>', '<%= rpcModuleName %>', import('<%- t.segmentImports[segment.segmentName].fetcher %>'),
|
|
12
|
-
{ validateOnClient: <%- t.segmentImports[segment.segmentName].validateOnClient ? `import('${t.segmentImports[segment.segmentName].validateOnClient}')` : 'undefined' %>, <%- typeof t.segmentMeta[segment.segmentName].segmentNameOverride === 'string' ? `segmentNameOverride: '${t.segmentMeta[segment.segmentName].segmentNameOverride}', ` : '' %><%- segment.segmentType === 'mixin' ? '' : apiRoot ? `apiRoot: '${apiRoot}'` : '' %> }
|
|
13
|
-
);
|
|
14
|
-
<%
|
|
15
|
-
});
|
|
16
|
-
});
|
|
17
|
-
%>
|
|
18
|
-
export { schema };
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
<%- t.getFirstLineBanner() %>
|
|
2
|
-
import type { VovkMetaSchema, VovkSegmentSchema } from 'vovk';
|
|
3
|
-
|
|
4
|
-
export const schema: {
|
|
5
|
-
$schema: '<%- t.VovkSchemaIdEnum.SCHEMA %>';
|
|
6
|
-
meta: VovkMetaSchema;
|
|
7
|
-
segments: {<% Object.values(t.schema.segments).filter((segment) => segment.emitSchema).forEach((segment) => { %>
|
|
8
|
-
'<%= segment.segmentName %>': VovkSegmentSchema;<% }) %>
|
|
9
|
-
};
|
|
10
|
-
};
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
<%- t.getFirstLineBanner() %>
|
|
2
|
-
<% if(t.isVovkProject) { %>
|
|
3
|
-
import meta from './<%= t.schemaOutDir %>/_meta.json' with { type: 'json' };
|
|
4
|
-
<% } else { %>
|
|
5
|
-
const meta = <%- JSON.stringify(t.schema.meta, null, 2) %>;
|
|
6
|
-
<% } %>
|
|
7
|
-
|
|
8
|
-
<% if(t.hasMixins) { %>
|
|
9
|
-
import mixins from './mixins.json' with { type: 'json' };
|
|
10
|
-
<% } %>
|
|
11
|
-
<% Object.values(t.schema.segments).filter((segment) => segment.emitSchema && segment.segmentType !== 'mixin').forEach((segment, i) => { %>
|
|
12
|
-
import schema<%= i %> from './<%= t.schemaOutDir %>/<%= segment.segmentName || t.ROOT_SEGMENT_FILE_NAME %>.json' with { type: 'json' };
|
|
13
|
-
<% }) %>
|
|
14
|
-
|
|
15
|
-
const segments = {<% Object.values(t.schema.segments).filter((segment) => segment.emitSchema && segment.segmentType !== 'mixin').forEach((segment, i) => { %>
|
|
16
|
-
'<%= segment.segmentName %>': schema<%= i %>,
|
|
17
|
-
<% }) %>
|
|
18
|
-
<% if(t.hasMixins) { %>
|
|
19
|
-
...mixins,
|
|
20
|
-
<% } %>
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
const schema = {
|
|
24
|
-
$schema: '<%- t.VovkSchemaIdEnum.SCHEMA %>',
|
|
25
|
-
segments,
|
|
26
|
-
meta,
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
export { schema };
|