vovk-cli 0.0.1-draft.352 → 0.0.1-draft.355

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.
@@ -2,7 +2,6 @@
2
2
  const { createRPC } = require('<%= t.commonImports.createRPC %>');
3
3
  const { schema } = require('./schema.cjs');
4
4
  const { openapi } = require('./openapi.cjs');
5
- const { validateOnClient = null } = <%- t.imports.validateOnClient ? `require('${t.imports.validateOnClient}')` : '{}'%>;
6
5
  <% Object.entries(t.reExports).forEach(([reExportWhatCommaDivisible, reExportFrom]) => {
7
6
  reExportWhatCommaDivisible.split(/\s*,\s*/).forEach((reExportWhat) => { %>
8
7
  exports['<%= reExportWhat.split(/\s+as\s+/)[1] ?? reExportWhat %>'] = require('<%= reExportFrom %>')['<%= reExportWhat.split(/\s+as\s+/)[0] %>'];
@@ -5,10 +5,10 @@ import type { VovkRequest, VovkStreamAsyncIterable, KnownAny } from 'vovk';
5
5
 
6
6
  export namespace Mixins {
7
7
  <% for (const segment of mixins) { %>
8
- <% if(segment.meta?.components?.schemas) { %>
8
+ <% if(segment.meta?.openAPIObject?.components?.schemas) { %>
9
9
  export namespace <%= t._.upperFirst(t._.camelCase(segment.segmentName)) %> {
10
- <% for (const [componentName, componentSchema] of Object.entries(segment.meta.components.schemas)) { %>
11
- <%- t.compileJSONSchemaToTypeScriptType(componentSchema, componentName, segment.meta.components, { dontCreateRefTypes: true }) %>
10
+ <% for (const [componentName, componentSchema] of Object.entries(segment.meta.openAPIObject.components.schemas)) { %>
11
+ <%- t.compileJSONSchemaToTypeScriptType(componentSchema, componentName, segment.meta.openAPIObject.components, { dontCreateRefTypes: true }) %>
12
12
  <% } %>
13
13
  }
14
14
  <% } %>
@@ -56,7 +56,7 @@ export type Controllers = {
56
56
  <%- getType(segment, controllerSchema, handlerName, 'body') %>,
57
57
  <%- getType(segment, controllerSchema, handlerName, 'query') %>,
58
58
  <%- getType(segment, controllerSchema, handlerName, 'params') %>
59
- >) => <%- handlerSchema.validation?.output ? `Promise<${getType(segment, controllerSchema, handlerName, 'output')}>` : handlerSchema.validation?.iteration ? `Promise<VovkStreamAsyncIterable<${getType(segment, controllerSchema, handlerName, 'iteration')}>` : 'Promise<KnownAny>' %>,
59
+ >) => <%- handlerSchema.validation?.output ? `Promise<${getType(segment, controllerSchema, handlerName, 'output')}>` : handlerSchema.validation?.iteration ? `Promise<VovkStreamAsyncIterable<${getType(segment, controllerSchema, handlerName, 'iteration')}>>` : 'Promise<KnownAny>' %>,
60
60
  <% } %>
61
61
  };
62
62
  <% } %>
@@ -26,12 +26,12 @@
26
26
  `<%= handlerSchema.httpMethod %> <%= [...(forceApiRoot ? [forceApiRoot] : [t.apiRoot, segmentName]), controllerSchema.prefix, handlerSchema.path].map((part, i) => i > 0 ? t._.trim(part, '/') : part).filter(Boolean).join('/') %>`
27
27
 
28
28
  ```ts
29
- <%- t.createCodeExamples({
29
+ <%- t.createCodeSamples({
30
30
  handlerSchema,
31
31
  handlerName,
32
32
  controllerSchema,
33
33
  package: t.package,
34
- config: t.snippets,
34
+ config: t.samples,
35
35
  }).ts %>
36
36
  ```
37
37
  <% }) %>
@@ -1,13 +1,16 @@
1
1
  <%- t.getFirstLineBanner() %>
2
2
  <% if(t.isVovkProject) { %>
3
3
  const meta = require('./<%= t.schemaOutDir %>/_meta.json');
4
+ <% } else { %>
5
+ const meta = <%- JSON.stringify(t.publicMeta, null, 2) %>;
4
6
  <% } %>
7
+
5
8
  <% if(t.hasMixins) { %>
6
9
  const mixins = require('./mixins.json');
7
10
  <% } %>
8
- const segments = {<% Object.values(t.schema.segments).filter((segment) => segment.emitSchema).forEach((segment) => { if(segment.segmentType !== 'mixin') { %>
11
+ const segments = {<% Object.values(t.schema.segments).filter((segment) => segment.emitSchema && segment.segmentType !== 'mixin').forEach((segment) => { %>
9
12
  '<%= segment.segmentName %>': require('./<%= t.schemaOutDir %>/<%= segment.segmentName || t.ROOT_SEGMENT_FILE_NAME %>.json'),
10
- <% }}) %>
13
+ <% }) %>
11
14
  <% if(t.hasMixins) { %>
12
15
  ...mixins,
13
16
  <% } %>
@@ -15,9 +18,7 @@ const segments = {<% Object.values(t.schema.segments).filter((segment) => segmen
15
18
  const schema = {
16
19
  $schema: '<%- t.VovkSchemaIdEnum.SCHEMA %>',
17
20
  segments,
18
- meta: {
19
- <% if(t.isVovkProject) { %>...meta<% } %>
20
- }
21
+ meta,
21
22
  };
22
23
 
23
24
  module.exports.schema = schema;
@@ -1,17 +1,17 @@
1
1
  <%- t.getFirstLineBanner() %>
2
- <% if(t.isVovkProject) { %>
3
- import meta from './<%= t.schemaOutDir %>/_meta.json' with { type: "json" };
4
- <% } %>
5
2
  <% if(t.hasMixins) { %>
6
3
  import mixins from './mixins.json' with { type: "json" };
7
4
  import type { Mixins } from './mixins.d.ts';
8
5
  <% } %>
9
- <% Object.values(t.schema.segments).filter((segment) => segment.emitSchema).forEach((segment, i) => { if(segment.segmentType !== 'mixin') { %>
6
+ <% Object.values(t.schema.segments).filter((segment) => segment.emitSchema && segment.segmentType !== 'mixin').forEach((segment, i) => { %>
10
7
  import segment<%= i %> from './<%= t.schemaOutDir %>/<%= segment.segmentName || t.ROOT_SEGMENT_FILE_NAME %>.json' with { type: "json" };
8
+ <% }); %>
9
+ <% if(t.isVovkProject) { %>
10
+ import meta from './<%= t.schemaOutDir %>/_meta.json' with { type: "json" };
11
11
  <% } else { %>
12
- import segment<%= i %> from './<%= segment.segmentName %>.json' with { type: "json" };
13
- <% }}) %>
14
- const segments = {<% Object.values(t.schema.segments).filter((segment) => segment.emitSchema).forEach((segment, i) => { %>
12
+ const meta = <%- JSON.stringify(t.publicMeta, null, 2) %>;
13
+ <% } %>
14
+ const segments = {<% Object.values(t.schema.segments).filter((segment) => segment.emitSchema && segment.segmentType !== 'mixin').forEach((segment, i) => { %>
15
15
  '<%= segment.segmentName %>': segment<%= i %>,<% }) %>
16
16
  <% if(t.hasMixins) { %>
17
17
  ...mixins,
@@ -21,11 +21,8 @@ const segments = {<% Object.values(t.schema.segments).filter((segment) => segmen
21
21
  export const schema = {
22
22
  $schema: '<%- t.VovkSchemaIdEnum.SCHEMA %>',
23
23
  segments,
24
- meta: {
25
- <% if(t.isVovkProject) { %>...meta,<% } %>
26
- }
24
+ meta,
27
25
  };
28
-
29
26
  <% if (t.hasMixins) { %>
30
27
  export { Mixins };
31
28
  <% } %>
@@ -47,6 +47,7 @@ export async function bundle({ projectInfo, fullSchema, cliBundleOptions, }) {
47
47
  entry: path.join(tsFullClientOutAbsoluteDirInput, './index.ts'),
48
48
  dts: true,
49
49
  format: ['cjs', 'esm'],
50
+ hash: false,
50
51
  fixedExtension: true,
51
52
  clean: true,
52
53
  ...bundleConfig.tsdownBuildOptions,
@@ -2,7 +2,7 @@ import path from 'node:path';
2
2
  import fs from 'node:fs/promises';
3
3
  import matter from 'gray-matter';
4
4
  import _ from 'lodash';
5
- import { getGeneratorConfig, openAPIToVovkSchema, vovkSchemaToOpenAPI, } from 'vovk';
5
+ import { resolveGeneratorConfigValues, openAPIToVovkSchema, vovkSchemaToOpenAPI, } from 'vovk';
6
6
  import getClientTemplateFiles from './getClientTemplateFiles.mjs';
7
7
  import chalkHighlightThing from '../utils/chalkHighlightThing.mjs';
8
8
  import pickSegmentFullSchema from '../utils/pickSegmentFullSchema.mjs';
@@ -68,10 +68,10 @@ const cliOptionsToOpenAPIMixins = ({ openapiGetMethodName, openapiGetModuleName,
68
68
  source: spec.startsWith('http://') || spec.startsWith('https://')
69
69
  ? { url: spec, fallback: openapiFallback?.[i] }
70
70
  : { file: spec },
71
- apiRoot: openapiRootUrl?.[i] ?? '/',
72
- getModuleName: openapiGetModuleName?.[i] ?? undefined,
71
+ apiRoot: openapiRootUrl?.[i] ?? '',
72
+ getModuleName: openapiGetModuleName?.[i] ?? 'api',
73
73
  getMethodName: openapiGetMethodName?.[i] ?? 'auto',
74
- mixinName: openapiMixinName?.[i],
74
+ mixinName: openapiMixinName?.[i] ?? 'mixin' + (i > 0 ? i + 1 : ''),
75
75
  };
76
76
  }) || []).map(({ source, apiRoot, getModuleName, getMethodName, mixinName }) => [
77
77
  mixinName,
@@ -103,13 +103,20 @@ export async function generate({ isEnsuringClient = false, isBundle = false, pro
103
103
  };
104
104
  });
105
105
  const cliMixins = cliOptionsToOpenAPIMixins(cliGenerateOptions ?? {});
106
- await Promise.all(Object.entries(cliMixins).map(async ([mixinName, mixinModule]) => {
107
- fullSchema.segments = {
108
- ...fullSchema.segments,
109
- [mixinName]: openAPIToVovkSchema(await normalizeOpenAPIMixin({ mixinModule, log })).segments[mixinName],
110
- };
111
- }));
112
- const isNodeNextResolution = ['node16', 'nodenext'].includes((await getTsconfig(cwd)?.config?.compilerOptions?.moduleResolution?.toLowerCase()) ?? '');
106
+ fullSchema.segments = {
107
+ ...fullSchema.segments,
108
+ ...Object.fromEntries(await Promise.all(Object.entries(cliMixins).map(async ([mixinName, mixinModule]) => {
109
+ return [
110
+ mixinName,
111
+ openAPIToVovkSchema({
112
+ segmentName: mixinName,
113
+ ...(await normalizeOpenAPIMixin({ mixinModule, log })),
114
+ }).segments[mixinName],
115
+ ];
116
+ }))),
117
+ };
118
+ const moduleResolution = await getTsconfig(cwd)?.config?.compilerOptions?.moduleResolution?.toLowerCase();
119
+ const isNodeNextResolution = !moduleResolution || ['node16', 'nodenext'].includes(moduleResolution ?? '');
113
120
  const isVovkProject = !!srcRoot;
114
121
  const isComposedEnabled = cliGenerateOptions?.composedOnly ||
115
122
  !!cliGenerateOptions?.composedFrom ||
@@ -135,13 +142,14 @@ export async function generate({ isEnsuringClient = false, isBundle = false, pro
135
142
  const matterResult = templateFilePath.endsWith('.ejs')
136
143
  ? matter(templateContent)
137
144
  : { data: { imports: [] }, content: templateContent };
138
- const { package: packageJson, readme, origin, snippets, reExports, } = getGeneratorConfig({
145
+ const { package: packageJson, readme, origin, samples, reExports, } = resolveGeneratorConfigValues({
139
146
  schema: fullSchema,
140
147
  configs: [templateDef.generatorConfig ?? {}],
141
148
  projectPackageJson,
142
149
  isBundle,
143
150
  segmentName: null,
144
151
  });
152
+ // console.log('reExports', fullSchema.meta)
145
153
  const openapi = vovkSchemaToOpenAPI({
146
154
  schema: fullSchema,
147
155
  rootEntry: config.rootEntry,
@@ -156,14 +164,14 @@ export async function generate({ isEnsuringClient = false, isBundle = false, pro
156
164
  projectInfo,
157
165
  clientTemplateFile,
158
166
  fullSchema: composedFullSchema,
159
- prettifyClient: config.composedClient.prettifyClient,
167
+ prettifyClient: cliGenerateOptions?.prettify ?? config.composedClient.prettifyClient,
160
168
  segmentName: null,
161
169
  templateContent,
162
170
  matterResult,
163
171
  openapi,
164
172
  package: packageJson,
165
173
  readme,
166
- snippets,
174
+ samples,
167
175
  reExports,
168
176
  isEnsuringClient,
169
177
  outCwdRelativeDir,
@@ -177,6 +185,7 @@ export async function generate({ isEnsuringClient = false, isBundle = false, pro
177
185
  origin: cliGenerateOptions?.origin ?? origin,
178
186
  configKey: 'composedClient',
179
187
  cliSchemaPath: cliGenerateOptions?.schemaPath ?? null,
188
+ projectConfig: config,
180
189
  });
181
190
  const outAbsoluteDir = path.resolve(cwd, outCwdRelativeDir);
182
191
  return {
@@ -218,7 +227,7 @@ export async function generate({ isEnsuringClient = false, isBundle = false, pro
218
227
  ? matter(templateContent)
219
228
  : { data: { imports: [] }, content: templateContent };
220
229
  const results = await Promise.all(segmentNames.map(async (segmentName) => {
221
- const { package: packageJson, readme, origin, snippets, reExports, } = getGeneratorConfig({
230
+ const { package: packageJson, readme, origin, samples, reExports, } = resolveGeneratorConfigValues({
222
231
  schema: fullSchema,
223
232
  configs: [templateDef.generatorConfig ?? {}],
224
233
  projectPackageJson,
@@ -240,14 +249,14 @@ export async function generate({ isEnsuringClient = false, isBundle = false, pro
240
249
  projectInfo,
241
250
  clientTemplateFile,
242
251
  fullSchema: segmentedFullSchema,
243
- prettifyClient: config.segmentedClient.prettifyClient,
252
+ prettifyClient: cliGenerateOptions?.prettify ?? config.segmentedClient.prettifyClient,
244
253
  segmentName,
245
254
  templateContent,
246
255
  matterResult,
247
256
  openapi,
248
257
  package: packageJson,
249
258
  readme,
250
- snippets,
259
+ samples,
251
260
  reExports,
252
261
  isEnsuringClient,
253
262
  outCwdRelativeDir,
@@ -261,6 +270,7 @@ export async function generate({ isEnsuringClient = false, isBundle = false, pro
261
270
  origin: cliGenerateOptions?.origin ?? origin,
262
271
  configKey: 'segmentedClient',
263
272
  cliSchemaPath: cliGenerateOptions?.schemaPath ?? null,
273
+ projectConfig: config,
264
274
  });
265
275
  return {
266
276
  written,
@@ -4,6 +4,7 @@ import { glob } from 'glob';
4
4
  import { VovkSchemaIdEnum } from 'vovk';
5
5
  import { META_FILE_NAME, ROOT_SEGMENT_FILE_NAME } from '../dev/writeOneSegmentSchemaFile.mjs';
6
6
  import getMetaSchema from '../getProjectInfo/getMetaSchema.mjs';
7
+ import deepExtend from '../utils/deepExtend.mjs';
7
8
  export async function getProjectFullSchema({ schemaOutAbsolutePath, isNextInstalled, log, config, }) {
8
9
  const result = {
9
10
  $schema: VovkSchemaIdEnum.SCHEMA,
@@ -19,14 +20,7 @@ export async function getProjectFullSchema({ schemaOutAbsolutePath, isNextInstal
19
20
  try {
20
21
  const metaContent = await readFile(metaPath, 'utf-8');
21
22
  const fromFileMeta = JSON.parse(metaContent);
22
- result.meta = {
23
- ...result.meta,
24
- ...fromFileMeta,
25
- config: {
26
- ...result.meta?.config,
27
- ...fromFileMeta?.config,
28
- },
29
- };
23
+ result.meta = deepExtend({}, result.meta, fromFileMeta);
30
24
  }
31
25
  catch {
32
26
  isEmptyLogOrWarn(`${META_FILE_NAME}.json not found at ${metaPath}. Using empty meta as fallback.`);
@@ -1,8 +1,8 @@
1
1
  import path from 'node:path';
2
- import { getGeneratorConfig } from 'vovk';
2
+ import { resolveGeneratorConfigValues } from 'vovk';
3
3
  import { ROOT_SEGMENT_FILE_NAME } from '../dev/writeOneSegmentSchemaFile.mjs';
4
4
  export default function getTemplateClientImports({ fullSchema, outCwdRelativeDir, segmentName, isBundle, }) {
5
- const { imports: configImports } = getGeneratorConfig({ schema: fullSchema, segmentName, isBundle });
5
+ const { imports: configImports } = resolveGeneratorConfigValues({ schema: fullSchema, segmentName, isBundle });
6
6
  const validateOnClientImport = configImports?.validateOnClient ?? null;
7
7
  const fetcherImport = configImports?.fetcher ?? 'vovk';
8
8
  const createRPCImport = configImports?.createRPC ?? 'vovk';
@@ -115,7 +115,7 @@ export class VovkGenerate {
115
115
  .watch(openApiSpecPaths, {
116
116
  cwd,
117
117
  persistent: true,
118
- ignoreInitial: true,
118
+ ignoreInitial: false,
119
119
  })
120
120
  .on('all', (event, path) => {
121
121
  if (event === 'change' || event === 'add' || event === 'ready' || event === 'unlink') {
@@ -159,10 +159,6 @@ export class VovkGenerate {
159
159
  return;
160
160
  }
161
161
  const content = await response.text();
162
- if (lastContent === null) {
163
- lastContent = content;
164
- return;
165
- }
166
162
  if (content !== lastContent) {
167
163
  log.info(`Remote OpenAPI spec changed at ${chalkHighlightThing(openApiSpecUrl)}`);
168
164
  lastContent = content;
@@ -1,11 +1,11 @@
1
- import { VovkReadmeConfig, VovkSnippetsConfig, type VovkSchema, type VovkStrictConfig } from 'vovk';
1
+ import { VovkReadmeConfig, VovkSamplesConfig, type VovkSchema, type VovkStrictConfig } from 'vovk';
2
2
  import type { PackageJson } from 'type-fest';
3
3
  import type { ProjectInfo } from '../getProjectInfo/index.mjs';
4
4
  import type { ClientTemplateFile } from './getClientTemplateFiles.mjs';
5
5
  import type { Segment } from '../locateSegments.mjs';
6
6
  import { OpenAPIObject } from 'openapi3-ts/oas31';
7
7
  export declare function normalizeOutTemplatePath(out: string, packageJson: PackageJson): string;
8
- export default function writeOneClientFile({ cwd, projectInfo, clientTemplateFile, fullSchema, prettifyClient, segmentName, templateContent, matterResult: { data, content }, openapi, package: packageJson, readme, snippets, reExports, isEnsuringClient, outCwdRelativeDir, locatedSegments, isNodeNextResolution, hasMixins, isVovkProject, vovkCliPackage, isBundle, origin, configKey, cliSchemaPath, }: {
8
+ export default function writeOneClientFile({ cwd, projectInfo, clientTemplateFile, fullSchema, prettifyClient, segmentName, templateContent, matterResult: { data, content }, openapi, package: packageJson, readme, samples, reExports, isEnsuringClient, outCwdRelativeDir, locatedSegments, isNodeNextResolution, hasMixins, isVovkProject, vovkCliPackage, isBundle, origin, configKey, cliSchemaPath, projectConfig, }: {
9
9
  cwd: string;
10
10
  projectInfo: ProjectInfo;
11
11
  clientTemplateFile: ClientTemplateFile;
@@ -22,7 +22,7 @@ export default function writeOneClientFile({ cwd, projectInfo, clientTemplateFil
22
22
  openapi: OpenAPIObject;
23
23
  package: PackageJson;
24
24
  readme: VovkReadmeConfig;
25
- snippets: VovkSnippetsConfig;
25
+ samples: VovkSamplesConfig;
26
26
  reExports: VovkStrictConfig['generatorConfig']['reExports'];
27
27
  isEnsuringClient: boolean;
28
28
  outCwdRelativeDir: string;
@@ -36,6 +36,7 @@ export default function writeOneClientFile({ cwd, projectInfo, clientTemplateFil
36
36
  origin: string | null;
37
37
  configKey: 'composedClient' | 'segmentedClient';
38
38
  cliSchemaPath: string | null;
39
+ projectConfig: VovkStrictConfig;
39
40
  }): Promise<{
40
41
  written: boolean;
41
42
  }>;
@@ -2,21 +2,22 @@ import fs from 'fs/promises';
2
2
  import path from 'node:path';
3
3
  import ejs from 'ejs';
4
4
  import _ from 'lodash';
5
- import { createCodeExamples, VovkSchemaIdEnum, } from 'vovk';
5
+ import { createCodeSamples, VovkSchemaIdEnum, } from 'vovk';
6
6
  import * as YAML from 'yaml';
7
7
  import TOML from '@iarna/toml';
8
8
  import prettify from '../utils/prettify.mjs';
9
9
  import { ROOT_SEGMENT_FILE_NAME } from '../dev/writeOneSegmentSchemaFile.mjs';
10
10
  import { compileJSONSchemaToTypeScriptType } from '../utils/compileJSONSchemaToTypeScriptType.mjs';
11
11
  import getTemplateClientImports from './getTemplateClientImports.mjs';
12
+ import getMetaSchema from '../getProjectInfo/getMetaSchema.mjs';
12
13
  export function normalizeOutTemplatePath(out, packageJson) {
13
14
  return out.replace('[package_name]', packageJson.name?.replace(/-/g, '_') ?? 'my_package_name');
14
15
  }
15
16
  export default async function writeOneClientFile({ cwd, projectInfo, clientTemplateFile, fullSchema, prettifyClient, segmentName,
16
17
  // imports,
17
- templateContent, matterResult: { data, content }, openapi, package: packageJson, readme, snippets, reExports, isEnsuringClient, outCwdRelativeDir,
18
+ templateContent, matterResult: { data, content }, openapi, package: packageJson, readme, samples, reExports, isEnsuringClient, outCwdRelativeDir,
18
19
  // templateDef,
19
- locatedSegments, isNodeNextResolution, hasMixins, isVovkProject, vovkCliPackage, isBundle, origin, configKey, cliSchemaPath, }) {
20
+ locatedSegments, isNodeNextResolution, hasMixins, isVovkProject, vovkCliPackage, isBundle, origin, configKey, cliSchemaPath, projectConfig, }) {
20
21
  const { config, apiRoot } = projectInfo;
21
22
  const { templateFilePath, relativeDir } = clientTemplateFile;
22
23
  const locatedSegmentsByName = _.keyBy(locatedSegments, 'segmentName');
@@ -48,19 +49,21 @@ locatedSegments, isNodeNextResolution, hasMixins, isVovkProject, vovkCliPackage,
48
49
  isVovkProject,
49
50
  package: packageJson,
50
51
  readme,
51
- snippets,
52
+ samples,
52
53
  reExports,
53
54
  openapi,
54
55
  ROOT_SEGMENT_FILE_NAME,
55
56
  apiRoot: origin ? `${origin}/${config.rootEntry}` : apiRoot,
56
57
  imports: {},
57
58
  schema: fullSchema,
59
+ config: projectConfig,
58
60
  VovkSchemaIdEnum,
59
- createCodeExamples,
61
+ createCodeSamples,
60
62
  compileJSONSchemaToTypeScriptType,
61
63
  YAML,
62
64
  TOML,
63
65
  getFirstLineBanner,
66
+ publicMeta: getMetaSchema({ config: projectConfig, useEmitConfig: true }),
64
67
  nodeNextResolutionExt: {
65
68
  ts: isNodeNextResolution ? '.ts' : '',
66
69
  js: isNodeNextResolution ? '.js' : '',
@@ -48,8 +48,8 @@ export default function getConfig({ configPath, cwd, logLevel, }: {
48
48
  requires?: Record<string, string>;
49
49
  prebundleOutDir?: string;
50
50
  keepPrebundleDir?: boolean;
51
- tsdownBuildOptions?: Parameters<typeof import("tsdown/config-9hj-APNF.mjs").build>[0];
52
- generatorConfig?: import("vovk").VovkGeneratorConfigCommon;
51
+ tsdownBuildOptions?: Parameters<typeof import("tsdown/index.mjs").build>[0];
52
+ generatorConfig?: import("vovk").VovkGeneratorConfig;
53
53
  } & ({
54
54
  excludeSegments?: never;
55
55
  includeSegments?: string[];
@@ -64,7 +64,9 @@ export default function getConfig({ configPath, cwd, logLevel, }: {
64
64
  controller?: string;
65
65
  [key: string]: string | undefined;
66
66
  };
67
- generatorConfig?: import("vovk").VovkGeneratorConfig;
67
+ generatorConfig?: import("vovk").VovkGeneratorConfig & {
68
+ segments?: Record<string, import("vovk/types").VovkSegmentConfig>;
69
+ };
68
70
  } | null;
69
71
  log: {
70
72
  info: (msg: string) => void;
package/dist/index.mjs CHANGED
@@ -94,10 +94,10 @@ program
94
94
  .option('--schema, --schema-path <path>', 'path to schema folder (default: ./.vovk-schema)')
95
95
  .option('--config, --config-path <config>', 'path to config file')
96
96
  .option('--origin <url>', 'set the origin URL for the generated client')
97
- .option('--watch <s>', 'watch for changes in schema or openapi spec and regenerate client; accepts a number in seconds to throttle the watcher or make an HTTP request to the OpenAPI spec URL')
97
+ .option('--watch <s>', 'watch for changes in schema or openapi spec and regenerate client; accepts a number in seconds to throttle the watcher or make an HTTP request to the OpenAPI spec URL', false)
98
98
  .option('--openapi, --openapi-spec <openapi_path_or_urls...>', 'use OpenAPI schema for client generation')
99
- .option('--openapi-get-module-name <names...>', 'module names corresponding to the index of --openapi option')
100
- .option('--openapi-get-method-name <names...>', 'method names corresponding to the index of --openapi option')
99
+ .option('--openapi-module-name, --openapi-get-module-name <names...>', 'module names corresponding to the index of --openapi option')
100
+ .option('--openapi-method-name, --openapi-get-method-name <names...>', 'method names corresponding to the index of --openapi option')
101
101
  .option('--openapi-root-url <urls...>', 'root URLs corresponding to the index of --openapi option')
102
102
  .option('--openapi-mixin-name <names...>', 'mixin names corresponding to the index of --openapi option')
103
103
  .option('--openapi-fallback <paths...>', 'save OpenAPI spec and use it as a fallback if URL is not available')
@@ -0,0 +1,54 @@
1
+ /*!
2
+ * @description Recursive object extending
3
+ * @author Viacheslav Lotsmanov <lotsmanov89@gmail.com>
4
+ * @license MIT
5
+ *
6
+ * The MIT License (MIT)
7
+ *
8
+ * Copyright (c) 2013-2018 Viacheslav Lotsmanov
9
+ *
10
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
11
+ * this software and associated documentation files (the "Software"), to deal in
12
+ * the Software without restriction, including without limitation the rights to
13
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
14
+ * the Software, and to permit persons to whom the Software is furnished to do so,
15
+ * subject to the following conditions:
16
+ *
17
+ * The above copyright notice and this permission notice shall be included in all
18
+ * copies or substantial portions of the Software.
19
+ *
20
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
22
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
23
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
24
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
25
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26
+ */
27
+ type DeepPartial<T> = {
28
+ [P in keyof T]?: T[P] extends (infer U)[] ? DeepPartial<U>[] : T[P] extends object ? DeepPartial<T[P]> : T[P];
29
+ };
30
+ type SpecificValue = Buffer | Date | RegExp;
31
+ declare function isSpecificValue(val: any): val is SpecificValue;
32
+ declare function cloneSpecificValue(val: SpecificValue): SpecificValue;
33
+ /**
34
+ * Recursive cloning array.
35
+ */
36
+ declare function deepCloneArray<T = any>(arr: T[]): T[];
37
+ declare function safeGetProperty<T extends object>(object: T, property: PropertyKey): any;
38
+ /**
39
+ * Extending object that entered in first argument.
40
+ *
41
+ * Returns extended object or false if have no target object or incorrect type.
42
+ *
43
+ * If you wish to clone source object (without modify it), just use empty new
44
+ * object as first argument, like this:
45
+ * deepExtend({}, yourObj_1, [yourObj_N]);
46
+ */
47
+ declare function deepExtend<T extends object>(...args: [T, ...Partial<T>[]]): T;
48
+ declare function deepExtend<T extends object, U extends object>(target: T, source: U): T & U;
49
+ declare function deepExtend<T extends object, U extends object, V extends object>(target: T, source1: U, source2: V): T & U & V;
50
+ declare function deepExtend<T extends object, U extends object, V extends object, W extends object>(target: T, source1: U, source2: V, source3: W): T & U & V & W;
51
+ declare function deepExtend<T extends object>(target: T, ...sources: any[]): T;
52
+ export default deepExtend;
53
+ export { deepExtend, deepCloneArray, isSpecificValue, cloneSpecificValue, safeGetProperty };
54
+ export type { DeepPartial, SpecificValue };
@@ -0,0 +1,129 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ /*!
3
+ * @description Recursive object extending
4
+ * @author Viacheslav Lotsmanov <lotsmanov89@gmail.com>
5
+ * @license MIT
6
+ *
7
+ * The MIT License (MIT)
8
+ *
9
+ * Copyright (c) 2013-2018 Viacheslav Lotsmanov
10
+ *
11
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
12
+ * this software and associated documentation files (the "Software"), to deal in
13
+ * the Software without restriction, including without limitation the rights to
14
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
15
+ * the Software, and to permit persons to whom the Software is furnished to do so,
16
+ * subject to the following conditions:
17
+ *
18
+ * The above copyright notice and this permission notice shall be included in all
19
+ * copies or substantial portions of the Software.
20
+ *
21
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
23
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
24
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
25
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
26
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
+ */
28
+ 'use strict';
29
+ function isSpecificValue(val) {
30
+ return val instanceof Buffer || val instanceof Date || val instanceof RegExp;
31
+ }
32
+ function cloneSpecificValue(val) {
33
+ if (val instanceof Buffer) {
34
+ const x = Buffer.alloc ? Buffer.alloc(val.length) : Buffer.from(val);
35
+ val.copy(x);
36
+ return x;
37
+ }
38
+ else if (val instanceof Date) {
39
+ return new Date(val.getTime());
40
+ }
41
+ else if (val instanceof RegExp) {
42
+ return new RegExp(val);
43
+ }
44
+ else {
45
+ throw new Error('Unexpected situation');
46
+ }
47
+ }
48
+ /**
49
+ * Recursive cloning array.
50
+ */
51
+ function deepCloneArray(arr) {
52
+ const clone = [];
53
+ arr.forEach((item, index) => {
54
+ if (typeof item === 'object' && item !== null) {
55
+ if (Array.isArray(item)) {
56
+ clone[index] = deepCloneArray(item);
57
+ }
58
+ else if (isSpecificValue(item)) {
59
+ clone[index] = cloneSpecificValue(item);
60
+ }
61
+ else {
62
+ clone[index] = deepExtend({}, item);
63
+ }
64
+ }
65
+ else {
66
+ clone[index] = item;
67
+ }
68
+ });
69
+ return clone;
70
+ }
71
+ function safeGetProperty(object, property) {
72
+ return property === '__proto__' ? undefined : object[property];
73
+ }
74
+ function deepExtend(...args) {
75
+ if (args.length < 1 || typeof args[0] !== 'object') {
76
+ return false;
77
+ }
78
+ if (args.length < 2) {
79
+ return args[0];
80
+ }
81
+ const target = args[0];
82
+ // convert arguments to array and cut off target object
83
+ const sources = args.slice(1);
84
+ sources.forEach((obj) => {
85
+ // skip argument if isn't an object, is null, or is an array
86
+ if (typeof obj !== 'object' || obj === null || Array.isArray(obj)) {
87
+ return;
88
+ }
89
+ Object.keys(obj).forEach((key) => {
90
+ const src = safeGetProperty(target, key); // source value
91
+ const val = safeGetProperty(obj, key); // new value
92
+ // recursion prevention
93
+ if (val === target) {
94
+ return;
95
+ }
96
+ else if (typeof val !== 'object' || val === null) {
97
+ /**
98
+ * if new value isn't object then just overwrite by new value
99
+ * instead of extending.
100
+ */
101
+ target[key] = val;
102
+ return;
103
+ }
104
+ // just clone arrays (and recursive clone objects inside)
105
+ else if (Array.isArray(val)) {
106
+ target[key] = deepCloneArray(val);
107
+ return;
108
+ }
109
+ // custom cloning and overwrite for specific objects
110
+ else if (isSpecificValue(val)) {
111
+ target[key] = cloneSpecificValue(val);
112
+ return;
113
+ }
114
+ // overwrite by new value if source isn't object or array
115
+ else if (typeof src !== 'object' || src === null || Array.isArray(src)) {
116
+ target[key] = deepExtend({}, val);
117
+ return;
118
+ }
119
+ // source value and new value is objects both, extending...
120
+ else {
121
+ target[key] = deepExtend(src, val);
122
+ return;
123
+ }
124
+ });
125
+ });
126
+ return target;
127
+ }
128
+ export default deepExtend;
129
+ export { deepExtend, deepCloneArray, isSpecificValue, cloneSpecificValue, safeGetProperty };
@@ -11,4 +11,4 @@ export declare function normalizeOpenAPIMixin({ mixinModule, log, cwd, }: {
11
11
  mixinModule: NonNullable<NonNullable<NonNullable<NonNullable<VovkConfig['generatorConfig']>['segments']>[string]>['openAPIMixin']>;
12
12
  log: ProjectInfo['log'];
13
13
  cwd?: string;
14
- }): Promise<NonNullable<NonNullable<NonNullable<VovkStrictConfig['generatorConfig']>['segments']>[string]>['openAPIMixin']>;
14
+ }): Promise<NonNullable<NonNullable<NonNullable<NonNullable<VovkStrictConfig['generatorConfig']>['segments']>[string]>['openAPIMixin']>>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vovk-cli",
3
- "version": "0.0.1-draft.352",
3
+ "version": "0.0.1-draft.355",
4
4
  "bin": {
5
5
  "vovk": "./dist/index.mjs"
6
6
  },
@@ -35,22 +35,22 @@
35
35
  },
36
36
  "homepage": "https://vovk.dev",
37
37
  "peerDependencies": {
38
- "vovk": "^3.0.0-draft.413"
38
+ "vovk": "^3.0.0-draft.415"
39
39
  },
40
40
  "optionalDependencies": {
41
- "@rolldown/binding-linux-x64-gnu": "1.0.0-beta.31"
41
+ "@rolldown/binding-linux-x64-gnu": "1.0.0-beta.36"
42
42
  },
43
43
  "dependencies": {
44
44
  "@iarna/toml": "^2.2.5",
45
- "@inquirer/prompts": "^7.7.1",
46
- "@npmcli/package-json": "^6.2.0",
45
+ "@inquirer/prompts": "^7.8.4",
46
+ "@npmcli/package-json": "^7.0.0",
47
47
  "@types/json-schema": "^7.0.15",
48
- "chalk": "^5.4.1",
48
+ "chalk": "^5.6.2",
49
49
  "chokidar": "^4.0.3",
50
50
  "clone-deep": "^4.0.1",
51
51
  "commander": "^13.1.0",
52
- "concurrently": "^9.2.0",
53
- "dotenv": "^17.2.1",
52
+ "concurrently": "^9.2.1",
53
+ "dotenv": "^17.2.2",
54
54
  "ejs": "^3.1.10",
55
55
  "get-tsconfig": "^4.10.1",
56
56
  "glob": "^11.0.3",
@@ -63,12 +63,12 @@
63
63
  "pluralize": "^8.0.0",
64
64
  "prettier": "^3.6.2",
65
65
  "tar-stream": "^3.1.7",
66
- "ts-morph": "^26.0.0",
67
- "tsdown": "^0.13.0",
66
+ "ts-morph": "^27.0.0",
67
+ "tsdown": "^0.15.0",
68
68
  "type-fest": "^4.41.0",
69
- "undici": "^7.12.0",
69
+ "undici": "^7.15.0",
70
70
  "vovk-openapi": "^0.0.1-draft.112",
71
- "yaml": "^2.8.0"
71
+ "yaml": "^2.8.1"
72
72
  },
73
73
  "devDependencies": {
74
74
  "@types/concat-stream": "^2.0.3",
@@ -78,8 +78,9 @@
78
78
  "@types/pluralize": "^0.0.33",
79
79
  "@types/tar-stream": "^3.1.4",
80
80
  "concat-stream": "^2.0.0",
81
- "create-next-app": "^15.4.4",
81
+ "create-next-app": "^15.5.2",
82
+ "http-server": "^14.1.1",
82
83
  "node-pty": "^1.0.0",
83
- "zod": "^4.0.10"
84
+ "zod": "^4.1.5"
84
85
  }
85
86
  }