vovk 3.0.0-draft.413 → 3.0.0-draft.415

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/cjs/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { createVovkApp } from './createVovkApp';
2
- import { HttpStatus, HttpMethod, VovkSchemaIdEnum, type KnownAny, type VovkErrorResponse, type VovkRequest, type VovkBody, type VovkQuery, type VovkParams, type VovkReturnType, type VovkYieldType, type VovkOutput, type VovkIteration, type VovkMetaSchema, type VovkSegmentSchema, type VovkControllerSchema, type VovkHandlerSchema, type VovkSchema, type VovkConfig, type VovkGeneratorConfig, type VovkGeneratorConfigCommon, type VovkReadmeConfig, type VovkSnippetsConfig, type VovkOpenAPIMixin, type VovkOpenAPIMixinNormalized, type VovkStrictConfig, type VovkValidationType, type VovkLLMTool, type VovkTypedMethod, type VovkBasicJSONSchema, type VovkOperationObject } from './types';
2
+ import { HttpStatus, HttpMethod, VovkSchemaIdEnum, type KnownAny, type VovkErrorResponse, type VovkRequest, type VovkBody, type VovkQuery, type VovkParams, type VovkReturnType, type VovkYieldType, type VovkOutput, type VovkIteration, type VovkMetaSchema, type VovkSegmentSchema, type VovkControllerSchema, type VovkHandlerSchema, type VovkSchema, type VovkConfig, type VovkGeneratorConfig, type VovkGeneratorConfigCommon, type VovkReadmeConfig, type VovkSamplesConfig, type VovkOpenAPIMixin, type VovkOpenAPIMixinNormalized, type VovkStrictConfig, type VovkValidationType, type VovkLLMTool, type VovkTypedMethod, type VovkBasicJSONSchema, type VovkOperationObject } from './types';
3
3
  import { type VovkClient, type VovkClientFetcher, type VovkDefaultFetcherOptions, type VovkValidateOnClient, type VovkStreamAsyncIterable, createRPC, fetcher, createFetcher, progressive } from './client';
4
4
  import { operation, openAPIToVovkSchema, vovkSchemaToOpenAPI } from './openapi';
5
5
  import { HttpException } from './HttpException';
@@ -10,10 +10,10 @@ import { withValidationLibrary } from './utils/withValidationLibrary';
10
10
  import { createStandardValidation } from './utils/createStandardValidation';
11
11
  import { multitenant } from './utils/multitenant';
12
12
  import { createLLMTools } from './utils/createLLMTools';
13
- import { createCodeExamples } from './utils/createCodeExamples';
13
+ import { createCodeSamples } from './utils/createCodeSamples';
14
14
  import { createValidateOnClient } from './utils/createValidateOnClient';
15
- import { getGeneratorConfig } from './utils/getGeneratorConfig';
16
- export { type KnownAny, type VovkClient, type VovkClientFetcher, type VovkDefaultFetcherOptions, type VovkStreamAsyncIterable, type VovkValidateOnClient, type VovkSegmentSchema, type VovkErrorResponse, type VovkRequest, type VovkOutput, type VovkIteration, type VovkBody, type VovkQuery, type VovkParams, type VovkYieldType, type VovkReturnType, type VovkMetaSchema, type VovkControllerSchema, type VovkHandlerSchema, type VovkSchema, type VovkConfig, type VovkStrictConfig, type VovkGeneratorConfig, type VovkGeneratorConfigCommon, type VovkReadmeConfig, type VovkSnippetsConfig, type VovkOpenAPIMixin, type VovkOpenAPIMixinNormalized, type VovkValidationType, type VovkLLMTool, type VovkTypedMethod, type VovkBasicJSONSchema, type VovkOperationObject, VovkSchemaIdEnum, JSONLinesResponse, HttpException, HttpStatus, HttpMethod, createVovkApp, createDecorator, createRPC, fetcher, createFetcher, generateStaticAPI, withValidationLibrary, createStandardValidation, multitenant, createLLMTools, createCodeExamples, createValidateOnClient, progressive, operation, openAPIToVovkSchema, vovkSchemaToOpenAPI, getGeneratorConfig, };
15
+ import { resolveGeneratorConfigValues } from './utils/resolveGeneratorConfigValues';
16
+ export { type KnownAny, type VovkClient, type VovkClientFetcher, type VovkDefaultFetcherOptions, type VovkStreamAsyncIterable, type VovkValidateOnClient, type VovkSegmentSchema, type VovkErrorResponse, type VovkRequest, type VovkOutput, type VovkIteration, type VovkBody, type VovkQuery, type VovkParams, type VovkYieldType, type VovkReturnType, type VovkMetaSchema, type VovkControllerSchema, type VovkHandlerSchema, type VovkSchema, type VovkConfig, type VovkStrictConfig, type VovkGeneratorConfig, type VovkGeneratorConfigCommon, type VovkReadmeConfig, type VovkSamplesConfig, type VovkOpenAPIMixin, type VovkOpenAPIMixinNormalized, type VovkValidationType, type VovkLLMTool, type VovkTypedMethod, type VovkBasicJSONSchema, type VovkOperationObject, VovkSchemaIdEnum, JSONLinesResponse, HttpException, HttpStatus, HttpMethod, createVovkApp, createDecorator, createRPC, fetcher, createFetcher, generateStaticAPI, withValidationLibrary, createStandardValidation, multitenant, createLLMTools, createCodeSamples, createValidateOnClient, progressive, operation, openAPIToVovkSchema, vovkSchemaToOpenAPI, resolveGeneratorConfigValues, };
17
17
  export declare const get: {
18
18
  (givenPath?: string | undefined, options?: import("./types").DecoratorOptions | undefined): (givenTarget: KnownAny, propertyKey: string) => void;
19
19
  auto: (options?: import("./types").DecoratorOptions) => (givenTarget: KnownAny, propertyKey: string) => void;
package/cjs/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  var _a;
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.initSegment = exports.prefix = exports.options = exports.head = exports.del = exports.patch = exports.put = exports.post = exports.get = exports.getGeneratorConfig = exports.vovkSchemaToOpenAPI = exports.openAPIToVovkSchema = exports.operation = exports.progressive = exports.createValidateOnClient = exports.createCodeExamples = exports.createLLMTools = exports.multitenant = exports.createStandardValidation = exports.withValidationLibrary = exports.generateStaticAPI = exports.createFetcher = exports.fetcher = exports.createRPC = exports.createDecorator = exports.createVovkApp = exports.HttpMethod = exports.HttpStatus = exports.HttpException = exports.JSONLinesResponse = exports.VovkSchemaIdEnum = void 0;
4
+ exports.initSegment = exports.prefix = exports.options = exports.head = exports.del = exports.patch = exports.put = exports.post = exports.get = exports.resolveGeneratorConfigValues = exports.vovkSchemaToOpenAPI = exports.openAPIToVovkSchema = exports.operation = exports.progressive = exports.createValidateOnClient = exports.createCodeSamples = exports.createLLMTools = exports.multitenant = exports.createStandardValidation = exports.withValidationLibrary = exports.generateStaticAPI = exports.createFetcher = exports.fetcher = exports.createRPC = exports.createDecorator = exports.createVovkApp = exports.HttpMethod = exports.HttpStatus = exports.HttpException = exports.JSONLinesResponse = exports.VovkSchemaIdEnum = void 0;
5
5
  const createVovkApp_1 = require("./createVovkApp");
6
6
  Object.defineProperty(exports, "createVovkApp", { enumerable: true, get: function () { return createVovkApp_1.createVovkApp; } });
7
7
  const types_1 = require("./types");
@@ -33,10 +33,10 @@ const multitenant_1 = require("./utils/multitenant");
33
33
  Object.defineProperty(exports, "multitenant", { enumerable: true, get: function () { return multitenant_1.multitenant; } });
34
34
  const createLLMTools_1 = require("./utils/createLLMTools");
35
35
  Object.defineProperty(exports, "createLLMTools", { enumerable: true, get: function () { return createLLMTools_1.createLLMTools; } });
36
- const createCodeExamples_1 = require("./utils/createCodeExamples");
37
- Object.defineProperty(exports, "createCodeExamples", { enumerable: true, get: function () { return createCodeExamples_1.createCodeExamples; } });
36
+ const createCodeSamples_1 = require("./utils/createCodeSamples");
37
+ Object.defineProperty(exports, "createCodeSamples", { enumerable: true, get: function () { return createCodeSamples_1.createCodeSamples; } });
38
38
  const createValidateOnClient_1 = require("./utils/createValidateOnClient");
39
39
  Object.defineProperty(exports, "createValidateOnClient", { enumerable: true, get: function () { return createValidateOnClient_1.createValidateOnClient; } });
40
- const getGeneratorConfig_1 = require("./utils/getGeneratorConfig");
41
- Object.defineProperty(exports, "getGeneratorConfig", { enumerable: true, get: function () { return getGeneratorConfig_1.getGeneratorConfig; } });
40
+ const resolveGeneratorConfigValues_1 = require("./utils/resolveGeneratorConfigValues");
41
+ Object.defineProperty(exports, "resolveGeneratorConfigValues", { enumerable: true, get: function () { return resolveGeneratorConfigValues_1.resolveGeneratorConfigValues; } });
42
42
  _a = (0, createVovkApp_1.createVovkApp)(), exports.get = _a.get, exports.post = _a.post, exports.put = _a.put, exports.patch = _a.patch, exports.del = _a.del, exports.head = _a.head, exports.options = _a.options, exports.prefix = _a.prefix, exports.initSegment = _a.initSegment;
@@ -6,11 +6,11 @@ const applyComponentsSchemas_1 = require("./applyComponentsSchemas");
6
6
  const inlineRefs_1 = require("./inlineRefs");
7
7
  function openAPIToVovkSchema({ apiRoot, source: { object: openAPIObject }, getModuleName, getMethodName, errorMessageKey, segmentName, }) {
8
8
  segmentName = segmentName ?? '';
9
- const forceApiRoot = apiRoot ??
10
- openAPIObject.servers?.[0]?.url ??
11
- ('host' in openAPIObject
12
- ? `https://${openAPIObject.host}${'basePath' in openAPIObject ? openAPIObject.basePath : ''}`
13
- : null);
9
+ const forceApiRoot = apiRoot ||
10
+ (openAPIObject.servers?.[0]?.url ??
11
+ ('host' in openAPIObject
12
+ ? `https://${openAPIObject.host}${'basePath' in openAPIObject ? openAPIObject.basePath : ''}`
13
+ : null));
14
14
  if (!forceApiRoot) {
15
15
  throw new Error('API root URL is required in OpenAPI configuration');
16
16
  }
@@ -24,6 +24,7 @@ function openAPIToVovkSchema({ apiRoot, source: { object: openAPIObject }, getMo
24
24
  segmentName,
25
25
  segmentType: 'mixin',
26
26
  controllers: {},
27
+ forceApiRoot,
27
28
  meta: {
28
29
  openAPIObject: noPathsOpenAPIObject,
29
30
  },
@@ -48,7 +49,6 @@ function openAPIToVovkSchema({ apiRoot, source: { object: openAPIObject }, getMo
48
49
  operationObject: operation,
49
50
  });
50
51
  segment.controllers[rpcModuleName] ??= {
51
- forceApiRoot,
52
52
  rpcModuleName,
53
53
  handlers: {},
54
54
  };
@@ -114,6 +114,9 @@ function openAPIToVovkSchema({ apiRoot, source: { object: openAPIObject }, getMo
114
114
  httpMethod: method.toUpperCase(),
115
115
  path,
116
116
  operationObject: operation,
117
+ misc: {
118
+ originalPath: path,
119
+ },
117
120
  validation: {
118
121
  ...(query && {
119
122
  query: (0, applyComponentsSchemas_1.applyComponentsSchemas)(query, componentsSchemas, segmentName),
@@ -1,10 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.vovkSchemaToOpenAPI = vovkSchemaToOpenAPI;
4
- const createCodeExamples_1 = require("../utils/createCodeExamples");
4
+ const createCodeSamples_1 = require("../utils/createCodeSamples");
5
5
  const types_1 = require("../types");
6
6
  const getJSONSchemaSample_1 = require("../utils/getJSONSchemaSample");
7
- const getGeneratorConfig_1 = require("../utils/getGeneratorConfig");
7
+ const resolveGeneratorConfigValues_1 = require("../utils/resolveGeneratorConfigValues");
8
8
  function extractComponents(schema) {
9
9
  if (!schema)
10
10
  return [undefined, {}];
@@ -47,7 +47,7 @@ function extractComponents(schema) {
47
47
  function vovkSchemaToOpenAPI({ rootEntry = 'api', schema: fullSchema, configs, segmentName: givenSegmentName, }) {
48
48
  const paths = {};
49
49
  const components = {};
50
- const { openAPIObject, snippets: snippetsConfig, package: packageJson, } = (0, getGeneratorConfig_1.getGeneratorConfig)({
50
+ const { openAPIObject, samples: samplesConfig, package: packageJson, } = (0, resolveGeneratorConfigValues_1.resolveGeneratorConfigValues)({
51
51
  schema: fullSchema,
52
52
  configs,
53
53
  segmentName: givenSegmentName ?? null,
@@ -65,12 +65,12 @@ function vovkSchemaToOpenAPI({ rootEntry = 'api', schema: fullSchema, configs, s
65
65
  const [iterationValidation, iterationComponents] = extractComponents(h?.validation?.iteration);
66
66
  // TODO: Handle name conflicts?
67
67
  Object.assign(components, queryComponents, bodyComponents, paramsComponents, outputComponents, iterationComponents);
68
- const { ts, rs, py } = (0, createCodeExamples_1.createCodeExamples)({
68
+ const { ts, rs, py } = (0, createCodeSamples_1.createCodeSamples)({
69
69
  package: packageJson,
70
70
  handlerName,
71
71
  handlerSchema: h,
72
72
  controllerSchema: c,
73
- config: snippetsConfig,
73
+ config: samplesConfig,
74
74
  });
75
75
  const queryParameters = queryValidation && 'type' in queryValidation && 'properties' in queryValidation
76
76
  ? Object.entries(queryValidation.properties ?? {}).map(([propName, propSchema]) => ({
@@ -88,7 +88,8 @@ function vovkSchemaToOpenAPI({ rootEntry = 'api', schema: fullSchema, configs, s
88
88
  schema: propSchema,
89
89
  }))
90
90
  : null;
91
- const path = '/' + [rootEntry.replace(/^\/+|\/+$/g, ''), segmentName, c.prefix, h.path].filter(Boolean).join('/');
91
+ const path = h.misc?.originalPath ??
92
+ '/' + [rootEntry.replace(/^\/+|\/+$/g, ''), segmentName, c.prefix, h.path].filter(Boolean).join('/');
92
93
  paths[path] = paths[path] ?? {};
93
94
  const httpMethod = h.httpMethod.toLowerCase();
94
95
  paths[path][httpMethod] ??= {};
@@ -194,8 +195,8 @@ function vovkSchemaToOpenAPI({ rootEntry = 'api', schema: fullSchema, configs, s
194
195
  }
195
196
  return {
196
197
  ...openAPIObject,
197
- openapi: '3.1.0',
198
198
  components: {
199
+ ...openAPIObject?.components,
199
200
  schemas: {
200
201
  ...(openAPIObject?.components?.schemas ?? components),
201
202
  HttpStatus: {
package/cjs/types.d.ts CHANGED
@@ -256,6 +256,8 @@ export type VovkBasicJSONSchema = {
256
256
  $ref?: string;
257
257
  items?: VovkBasicJSONSchema;
258
258
  enum?: KnownAny[];
259
+ minimum?: number;
260
+ maximum?: number;
259
261
  title?: string;
260
262
  description?: string;
261
263
  properties?: {
@@ -299,7 +301,7 @@ export type VovkReadmeConfig = {
299
301
  installCommand?: string;
300
302
  description?: string;
301
303
  };
302
- export type VovkSnippetsConfig = {
304
+ export type VovkSamplesConfig = {
303
305
  apiRoot?: string;
304
306
  headers?: Record<string, string>;
305
307
  };
@@ -334,7 +336,7 @@ export interface VovkGeneratorConfigCommon {
334
336
  origin?: string | null;
335
337
  package?: VovkPackageJson;
336
338
  readme?: VovkReadmeConfig;
337
- snippets?: VovkSnippetsConfig;
339
+ samples?: VovkSamplesConfig;
338
340
  openAPIObject?: Partial<OpenAPIObject>;
339
341
  reExports?: Record<string, string>;
340
342
  imports?: {
@@ -370,6 +372,7 @@ export interface VovkOpenAPIMixin {
370
372
  getModuleName?: 'nestjs-operation-id' | (string & {}) | 'api' | GetOpenAPINameFn;
371
373
  getMethodName?: 'nestjs-operation-id' | 'camel-case-operation-id' | 'auto' | GetOpenAPINameFn;
372
374
  errorMessageKey?: string;
375
+ mixinName?: string;
373
376
  }
374
377
  export interface VovkOpenAPIMixinNormalized extends Omit<VovkOpenAPIMixin, 'source' | 'getMethodName' | 'getModuleName'> {
375
378
  source: Exclude<NonNullable<VovkOpenAPIMixin['source']>, {
@@ -388,10 +391,9 @@ export interface VovkSegmentConfig extends VovkGeneratorConfigCommon {
388
391
  export interface VovkGeneratorConfig extends VovkGeneratorConfigCommon {
389
392
  segments?: Record<string, VovkSegmentConfig>;
390
393
  }
391
- export interface VovkGeneratorConfigStrict extends Omit<VovkGeneratorConfig, 'origin' | 'segments'> {
392
- origin: string;
394
+ export interface VovkGeneratorConfigStrict extends Omit<VovkGeneratorConfig, 'segments'> {
393
395
  segments?: Record<string, Omit<VovkSegmentConfig, 'openAPIMixin'> & {
394
- openAPIMixin: VovkOpenAPIMixinNormalized;
396
+ openAPIMixin?: VovkOpenAPIMixinNormalized;
395
397
  }>;
396
398
  }
397
399
  type VovkUserConfig = {
@@ -1,4 +1,4 @@
1
- import type { KnownAny, VovkControllerSchema, VovkHandlerSchema, VovkSnippetsConfig } from '../types';
1
+ import type { KnownAny, VovkControllerSchema, VovkHandlerSchema, VovkSamplesConfig } from '../types';
2
2
  export type CodeSamplePackageJson = {
3
3
  name?: string;
4
4
  version?: string;
@@ -7,12 +7,12 @@ export type CodeSamplePackageJson = {
7
7
  py_name?: string;
8
8
  [key: string]: KnownAny;
9
9
  };
10
- export declare function createCodeExamples({ handlerName, handlerSchema, controllerSchema, package: packageJson, config, }: {
10
+ export declare function createCodeSamples({ handlerName, handlerSchema, controllerSchema, package: packageJson, config, }: {
11
11
  handlerName: string;
12
12
  handlerSchema: VovkHandlerSchema;
13
13
  controllerSchema: VovkControllerSchema;
14
14
  package?: CodeSamplePackageJson;
15
- config: VovkSnippetsConfig;
15
+ config: VovkSamplesConfig;
16
16
  }): {
17
17
  ts: string;
18
18
  py: string;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createCodeExamples = createCodeExamples;
3
+ exports.createCodeSamples = createCodeSamples;
4
4
  const getJSONSchemaExample_1 = require("./getJSONSchemaExample");
5
5
  const getSampleFromObject_1 = require("./getSampleFromObject");
6
6
  const toSnakeCase = (str) => str
@@ -71,7 +71,7 @@ ${[
71
71
  config?.apiRoot ? ` apiRoot: '${config.apiRoot}',` : null,
72
72
  config?.headers
73
73
  ? ` init: {
74
- headers: ${(0, getSampleFromObject_1.getSampleFromObject)(config.headers, { stripQuotes: true, indent: 6 })}
74
+ headers: ${(0, getSampleFromObject_1.getSampleFromObject)(config.headers, { stripQuotes: true, indent: 6, nestingIndent: 4 })}
75
75
  },`
76
76
  : null,
77
77
  ]
@@ -159,35 +159,6 @@ ${outputValidation ? `print(response)\n${getPySample(outputValidation, 0)}` : ''
159
159
  function generateRustCode({ handlerName, rpcName, packageName, queryValidation, bodyValidation, paramsValidation, outputValidation, iterationValidation, config, }) {
160
160
  const getRsJSONSample = (schema, indent) => (0, getJSONSchemaExample_1.getJSONSchemaExample)(schema, { stripQuotes: false, indent: indent ?? 4 });
161
161
  const getRsOutputSample = (schema, indent) => (0, getJSONSchemaExample_1.getJSONSchemaExample)(schema, { stripQuotes: true, indent: indent ?? 4 });
162
- /* const getRsFormSample = (schema: VovkBasicJSONSchema, indent?: number, nesting = 0) => {
163
- let formSample = 'let form = multipart::Form::new()';
164
- for (const [key, prop] of Object.entries(schema.properties || {})) {
165
- const target = prop.oneOf?.[0] || prop.anyOf?.[0] || prop.allOf?.[0] || prop;
166
- let sampleValue; // = value.type === 'object' ? 'object_unknown' : getSampleValue(value);
167
- if (target.type === 'string' && target.format === 'binary') {
168
- sampleValue = isTextFormat(target.contentMediaType)
169
- ? 'multipart::Part::text("text_content")'
170
- : 'multipart::Part::bytes(binary_data)';
171
-
172
- if (target.contentMediaType) {
173
- sampleValue += `.mime_str("${target.contentMediaType}").unwrap()`;
174
- }
175
- } else if (prop.type === 'array') {
176
- if (nesting === 0 && prop.items) {
177
- sampleValue =
178
- getRsFormSample(prop.items, indent, nesting + 1) + getRsFormSample(prop.items, indent, nesting + 1);
179
- } else {
180
- sampleValue = '"array_unknown"';
181
- }
182
- } else if (target.type === 'object') {
183
- sampleValue = '"object_unknown"';
184
- } else {
185
- sampleValue = `"${getSampleValue(target)}"`;
186
- }
187
- formSample += `\n${getIndentSpaces(4)}.part("${key}", ${sampleValue});`;
188
- }
189
- return formSample;
190
- }; */
191
162
  const getRsFormSample = (schema) => {
192
163
  let formSample = 'let form = multipart::Form::new()';
193
164
  for (const [key, prop] of Object.entries(schema.properties || {})) {
@@ -244,8 +215,7 @@ use serde_json::{
244
215
  from_value,
245
216
  json
246
217
  };
247
- ${bodyValidation?.['x-isForm'] ? `use multipart;` : ''}
248
-
218
+ ${bodyValidation?.['x-isForm'] ? `use multipart;\n` : ''}
249
219
  pub fn main() {${bodyValidation?.['x-isForm'] ? '\n ' + getRsFormSample(bodyValidation) + '\n' : ''}
250
220
  let response = ${rpcNameSnake}::${handlerNameSnake}(
251
221
  ${bodyValidation ? getBody(bodyValidation) : '()'}, /* body */
@@ -278,7 +248,7 @@ pub fn main() {${bodyValidation?.['x-isForm'] ? '\n ' + getRsFormSample(bodyVal
278
248
  }`;
279
249
  return RS_CODE.trim();
280
250
  }
281
- function createCodeExamples({ handlerName, handlerSchema, controllerSchema, package: packageJson, config, }) {
251
+ function createCodeSamples({ handlerName, handlerSchema, controllerSchema, package: packageJson, config, }) {
282
252
  const queryValidation = handlerSchema?.validation?.query;
283
253
  const bodyValidation = handlerSchema?.validation?.body;
284
254
  const paramsValidation = handlerSchema?.validation?.params;
@@ -114,9 +114,8 @@ ignoreBinary) {
114
114
  if (entries.length === 0)
115
115
  return '{}';
116
116
  const formattedEntries = [];
117
- const isTopLevel = indent === 0;
118
117
  // Add top-level description for objects
119
- if (isTopLevel && schema.type === 'object' && schema.description) {
118
+ if (schema.type === 'object' && schema.description) {
120
119
  const descLines = schema.description.split('\n');
121
120
  formattedEntries.push(`${indentStr}${nestIndentStr}${comment} -----`);
122
121
  descLines.forEach((line) => {
@@ -1,7 +1,7 @@
1
1
  import type { PackageJson } from 'type-fest';
2
- import type { VovkGeneratorConfigCommon, VovkReadmeConfig, VovkSnippetsConfig, VovkSchema, VovkGeneratorConfigStrict } from '../types';
2
+ import type { VovkGeneratorConfigCommon, VovkReadmeConfig, VovkSamplesConfig, VovkSchema, VovkGeneratorConfigStrict } from '../types';
3
3
  import type { OpenAPIObject } from 'openapi3-ts/oas31';
4
- export declare function getGeneratorConfig({ schema, configs, segmentName, isBundle, projectPackageJson, }: {
4
+ export declare function resolveGeneratorConfigValues({ schema, configs, segmentName, isBundle, projectPackageJson, }: {
5
5
  schema: VovkSchema;
6
6
  configs?: VovkGeneratorConfigCommon[];
7
7
  segmentName: string | null;
@@ -10,7 +10,7 @@ export declare function getGeneratorConfig({ schema, configs, segmentName, isBun
10
10
  }): {
11
11
  readme: VovkReadmeConfig;
12
12
  openAPIObject: OpenAPIObject;
13
- snippets: VovkSnippetsConfig;
13
+ samples: VovkSamplesConfig;
14
14
  origin: string;
15
15
  package: PackageJson;
16
16
  imports: VovkGeneratorConfigStrict['imports'];
@@ -3,9 +3,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.getGeneratorConfig = getGeneratorConfig;
6
+ exports.resolveGeneratorConfigValues = resolveGeneratorConfigValues;
7
7
  const deepExtend_1 = __importDefault(require("./deepExtend"));
8
- function getGeneratorConfig({ schema, configs, segmentName, isBundle, projectPackageJson, }) {
8
+ function resolveGeneratorConfigValues({ schema, configs, segmentName, isBundle, projectPackageJson, }) {
9
9
  const packageJson = (0, deepExtend_1.default)({}, {
10
10
  main: './index.cjs',
11
11
  module: './index.mjs',
@@ -27,21 +27,32 @@ function getGeneratorConfig({ schema, configs, segmentName, isBundle, projectPac
27
27
  types: './openapi.d.cts',
28
28
  },
29
29
  },
30
- }, projectPackageJson, schema.meta?.config?.generatorConfig?.package, isBundle ? schema.meta?.config?.bundle?.generatorConfig?.package : undefined, segmentName ? schema.segments?.[segmentName]?.meta?.package : undefined, segmentName ? schema.meta?.config?.generatorConfig?.segments?.[segmentName]?.package : undefined, configs?.reduce((acc, config) => (0, deepExtend_1.default)(acc, config.package), {}));
30
+ }, projectPackageJson, schema.meta?.config?.generatorConfig?.package, isBundle ? schema.meta?.config?.bundle?.generatorConfig?.package : undefined, typeof segmentName === 'string' ? schema.segments?.[segmentName]?.meta?.package : undefined, typeof segmentName === 'string'
31
+ ? schema.meta?.config?.generatorConfig?.segments?.[segmentName]?.package
32
+ : undefined, configs?.reduce((acc, config) => (0, deepExtend_1.default)(acc, config.package), {}));
31
33
  return {
32
34
  package: Object.fromEntries(Object.entries(packageJson).filter(([key]) => ['name', 'version', 'description', 'license', 'authors', 'repository', 'homepage', 'bugs', 'keywords'].includes(key))),
33
35
  openAPIObject: (0, deepExtend_1.default)({}, {
36
+ openapi: '3.1.0',
34
37
  info: {
35
38
  title: packageJson.name,
36
39
  version: packageJson.version,
37
40
  description: packageJson.description,
38
41
  },
39
- }, schema.meta?.config?.generatorConfig?.openAPIObject, isBundle ? schema.meta?.config?.bundle?.generatorConfig?.openAPIObject : undefined, segmentName ? schema?.segments?.[segmentName]?.meta?.openAPIObject : undefined, segmentName ? schema.meta?.config?.generatorConfig?.segments?.[segmentName]?.openAPIObject : undefined, configs?.reduce((acc, config) => (0, deepExtend_1.default)(acc, config.openAPIObject), {})),
40
- snippets: (0, deepExtend_1.default)({}, schema.meta?.config?.generatorConfig?.snippets, isBundle ? schema.meta?.config?.bundle?.generatorConfig?.snippets : undefined, segmentName ? schema.meta?.config?.generatorConfig?.segments?.[segmentName]?.snippets : undefined, configs?.reduce((acc, config) => (0, deepExtend_1.default)(acc, config.snippets), {})),
41
- readme: (0, deepExtend_1.default)({}, schema.meta?.config?.generatorConfig?.readme, isBundle ? schema.meta?.config?.bundle?.generatorConfig?.readme : undefined, segmentName ? schema.meta?.config?.generatorConfig?.segments?.[segmentName]?.readme : undefined, configs?.reduce((acc, config) => (0, deepExtend_1.default)(acc, config.readme), {})),
42
+ }, schema.meta?.config?.generatorConfig?.openAPIObject, isBundle ? schema.meta?.config?.bundle?.generatorConfig?.openAPIObject : undefined, typeof segmentName === 'string' ? schema?.segments?.[segmentName]?.meta?.openAPIObject : undefined, typeof segmentName === 'string'
43
+ ? schema.meta?.config?.generatorConfig?.segments?.[segmentName]?.openAPIObject
44
+ : undefined, configs?.reduce((acc, config) => (0, deepExtend_1.default)(acc, config.openAPIObject), {})),
45
+ samples: (0, deepExtend_1.default)({}, schema.meta?.config?.generatorConfig?.samples, isBundle ? schema.meta?.config?.bundle?.generatorConfig?.samples : undefined, typeof segmentName === 'string'
46
+ ? schema.meta?.config?.generatorConfig?.segments?.[segmentName]?.samples
47
+ : undefined, configs?.reduce((acc, config) => (0, deepExtend_1.default)(acc, config.samples), {})),
48
+ readme: (0, deepExtend_1.default)({}, schema.meta?.config?.generatorConfig?.readme, isBundle ? schema.meta?.config?.bundle?.generatorConfig?.readme : undefined, typeof segmentName === 'string'
49
+ ? schema.meta?.config?.generatorConfig?.segments?.[segmentName]?.readme
50
+ : undefined, configs?.reduce((acc, config) => (0, deepExtend_1.default)(acc, config.readme), {})),
42
51
  origin: [
43
52
  isBundle ? schema.meta?.config?.bundle?.generatorConfig?.origin : undefined,
44
- segmentName ? schema.meta?.config?.generatorConfig?.segments?.[segmentName]?.origin : undefined,
53
+ typeof segmentName === 'string'
54
+ ? schema.meta?.config?.generatorConfig?.segments?.[segmentName]?.origin
55
+ : undefined,
45
56
  schema.meta?.config?.generatorConfig?.origin,
46
57
  ...(configs?.map((config) => config.origin) ?? []),
47
58
  ]
@@ -51,10 +62,19 @@ function getGeneratorConfig({ schema, configs, segmentName, isBundle, projectPac
51
62
  fetcher: ['vovk'],
52
63
  validateOnClient: null,
53
64
  createRPC: ['vovk'],
54
- }, schema.meta?.config?.generatorConfig?.imports, isBundle ? schema.meta?.config?.bundle?.generatorConfig?.imports : undefined, segmentName ? schema.meta?.config?.generatorConfig?.segments?.[segmentName]?.imports : undefined, configs?.reduce((acc, config) => (0, deepExtend_1.default)(acc, config.imports), {})),
65
+ }, schema.meta?.config?.generatorConfig?.imports, isBundle ? schema.meta?.config?.bundle?.generatorConfig?.imports : undefined, typeof segmentName === 'string'
66
+ ? schema.meta?.config?.generatorConfig?.segments?.[segmentName]?.imports
67
+ : undefined, configs?.reduce((acc, config) => (0, deepExtend_1.default)(acc, config.imports), {})),
55
68
  reExports: (0, deepExtend_1.default)(
56
69
  // segmentName can be an empty string (for the root segment) and null (for composed clients)
57
70
  // therefore, !segmentName indicates that this either a composed client or a root segment of a segmented client
58
- {}, !segmentName && schema.meta?.config?.generatorConfig?.reExports, !segmentName && isBundle ? schema.meta?.config?.bundle?.generatorConfig?.reExports : undefined, segmentName ? schema.meta?.config?.generatorConfig?.segments?.[segmentName]?.reExports : undefined, configs?.reduce((acc, config) => (0, deepExtend_1.default)(acc, config.reExports), {})),
71
+ {}, !segmentName && schema.meta?.config?.generatorConfig?.reExports, !segmentName && isBundle ? schema.meta?.config?.bundle?.generatorConfig?.reExports : undefined,
72
+ // for segmented client, apply all reExports from all segments
73
+ typeof segmentName !== 'string' &&
74
+ Object.values(schema.meta?.config?.generatorConfig?.segments ?? {}).reduce((acc, segmentConfig) => (0, deepExtend_1.default)(acc, segmentConfig.reExports ?? {}), {}),
75
+ // for a specific segment, apply reExports from that segment
76
+ typeof segmentName === 'string'
77
+ ? schema.meta?.config?.generatorConfig?.segments?.[segmentName]?.reExports
78
+ : undefined, configs?.reduce((acc, config) => (0, deepExtend_1.default)(acc, config.reExports), {})),
59
79
  };
60
80
  }
package/mjs/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { createVovkApp } from './createVovkApp';
2
- import { HttpStatus, HttpMethod, VovkSchemaIdEnum, type KnownAny, type VovkErrorResponse, type VovkRequest, type VovkBody, type VovkQuery, type VovkParams, type VovkReturnType, type VovkYieldType, type VovkOutput, type VovkIteration, type VovkMetaSchema, type VovkSegmentSchema, type VovkControllerSchema, type VovkHandlerSchema, type VovkSchema, type VovkConfig, type VovkGeneratorConfig, type VovkGeneratorConfigCommon, type VovkReadmeConfig, type VovkSnippetsConfig, type VovkOpenAPIMixin, type VovkOpenAPIMixinNormalized, type VovkStrictConfig, type VovkValidationType, type VovkLLMTool, type VovkTypedMethod, type VovkBasicJSONSchema, type VovkOperationObject } from './types';
2
+ import { HttpStatus, HttpMethod, VovkSchemaIdEnum, type KnownAny, type VovkErrorResponse, type VovkRequest, type VovkBody, type VovkQuery, type VovkParams, type VovkReturnType, type VovkYieldType, type VovkOutput, type VovkIteration, type VovkMetaSchema, type VovkSegmentSchema, type VovkControllerSchema, type VovkHandlerSchema, type VovkSchema, type VovkConfig, type VovkGeneratorConfig, type VovkGeneratorConfigCommon, type VovkReadmeConfig, type VovkSamplesConfig, type VovkOpenAPIMixin, type VovkOpenAPIMixinNormalized, type VovkStrictConfig, type VovkValidationType, type VovkLLMTool, type VovkTypedMethod, type VovkBasicJSONSchema, type VovkOperationObject } from './types';
3
3
  import { type VovkClient, type VovkClientFetcher, type VovkDefaultFetcherOptions, type VovkValidateOnClient, type VovkStreamAsyncIterable, createRPC, fetcher, createFetcher, progressive } from './client';
4
4
  import { operation, openAPIToVovkSchema, vovkSchemaToOpenAPI } from './openapi';
5
5
  import { HttpException } from './HttpException';
@@ -10,10 +10,10 @@ import { withValidationLibrary } from './utils/withValidationLibrary';
10
10
  import { createStandardValidation } from './utils/createStandardValidation';
11
11
  import { multitenant } from './utils/multitenant';
12
12
  import { createLLMTools } from './utils/createLLMTools';
13
- import { createCodeExamples } from './utils/createCodeExamples';
13
+ import { createCodeSamples } from './utils/createCodeSamples';
14
14
  import { createValidateOnClient } from './utils/createValidateOnClient';
15
- import { getGeneratorConfig } from './utils/getGeneratorConfig';
16
- export { type KnownAny, type VovkClient, type VovkClientFetcher, type VovkDefaultFetcherOptions, type VovkStreamAsyncIterable, type VovkValidateOnClient, type VovkSegmentSchema, type VovkErrorResponse, type VovkRequest, type VovkOutput, type VovkIteration, type VovkBody, type VovkQuery, type VovkParams, type VovkYieldType, type VovkReturnType, type VovkMetaSchema, type VovkControllerSchema, type VovkHandlerSchema, type VovkSchema, type VovkConfig, type VovkStrictConfig, type VovkGeneratorConfig, type VovkGeneratorConfigCommon, type VovkReadmeConfig, type VovkSnippetsConfig, type VovkOpenAPIMixin, type VovkOpenAPIMixinNormalized, type VovkValidationType, type VovkLLMTool, type VovkTypedMethod, type VovkBasicJSONSchema, type VovkOperationObject, VovkSchemaIdEnum, JSONLinesResponse, HttpException, HttpStatus, HttpMethod, createVovkApp, createDecorator, createRPC, fetcher, createFetcher, generateStaticAPI, withValidationLibrary, createStandardValidation, multitenant, createLLMTools, createCodeExamples, createValidateOnClient, progressive, operation, openAPIToVovkSchema, vovkSchemaToOpenAPI, getGeneratorConfig, };
15
+ import { resolveGeneratorConfigValues } from './utils/resolveGeneratorConfigValues';
16
+ export { type KnownAny, type VovkClient, type VovkClientFetcher, type VovkDefaultFetcherOptions, type VovkStreamAsyncIterable, type VovkValidateOnClient, type VovkSegmentSchema, type VovkErrorResponse, type VovkRequest, type VovkOutput, type VovkIteration, type VovkBody, type VovkQuery, type VovkParams, type VovkYieldType, type VovkReturnType, type VovkMetaSchema, type VovkControllerSchema, type VovkHandlerSchema, type VovkSchema, type VovkConfig, type VovkStrictConfig, type VovkGeneratorConfig, type VovkGeneratorConfigCommon, type VovkReadmeConfig, type VovkSamplesConfig, type VovkOpenAPIMixin, type VovkOpenAPIMixinNormalized, type VovkValidationType, type VovkLLMTool, type VovkTypedMethod, type VovkBasicJSONSchema, type VovkOperationObject, VovkSchemaIdEnum, JSONLinesResponse, HttpException, HttpStatus, HttpMethod, createVovkApp, createDecorator, createRPC, fetcher, createFetcher, generateStaticAPI, withValidationLibrary, createStandardValidation, multitenant, createLLMTools, createCodeSamples, createValidateOnClient, progressive, operation, openAPIToVovkSchema, vovkSchemaToOpenAPI, resolveGeneratorConfigValues, };
17
17
  export declare const get: {
18
18
  (givenPath?: string | undefined, options?: import("./types").DecoratorOptions | undefined): (givenTarget: KnownAny, propertyKey: string) => void;
19
19
  auto: (options?: import("./types").DecoratorOptions) => (givenTarget: KnownAny, propertyKey: string) => void;
package/mjs/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  var _a;
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.initSegment = exports.prefix = exports.options = exports.head = exports.del = exports.patch = exports.put = exports.post = exports.get = exports.getGeneratorConfig = exports.vovkSchemaToOpenAPI = exports.openAPIToVovkSchema = exports.operation = exports.progressive = exports.createValidateOnClient = exports.createCodeExamples = exports.createLLMTools = exports.multitenant = exports.createStandardValidation = exports.withValidationLibrary = exports.generateStaticAPI = exports.createFetcher = exports.fetcher = exports.createRPC = exports.createDecorator = exports.createVovkApp = exports.HttpMethod = exports.HttpStatus = exports.HttpException = exports.JSONLinesResponse = exports.VovkSchemaIdEnum = void 0;
4
+ exports.initSegment = exports.prefix = exports.options = exports.head = exports.del = exports.patch = exports.put = exports.post = exports.get = exports.resolveGeneratorConfigValues = exports.vovkSchemaToOpenAPI = exports.openAPIToVovkSchema = exports.operation = exports.progressive = exports.createValidateOnClient = exports.createCodeSamples = exports.createLLMTools = exports.multitenant = exports.createStandardValidation = exports.withValidationLibrary = exports.generateStaticAPI = exports.createFetcher = exports.fetcher = exports.createRPC = exports.createDecorator = exports.createVovkApp = exports.HttpMethod = exports.HttpStatus = exports.HttpException = exports.JSONLinesResponse = exports.VovkSchemaIdEnum = void 0;
5
5
  const createVovkApp_1 = require("./createVovkApp");
6
6
  Object.defineProperty(exports, "createVovkApp", { enumerable: true, get: function () { return createVovkApp_1.createVovkApp; } });
7
7
  const types_1 = require("./types");
@@ -33,10 +33,10 @@ const multitenant_1 = require("./utils/multitenant");
33
33
  Object.defineProperty(exports, "multitenant", { enumerable: true, get: function () { return multitenant_1.multitenant; } });
34
34
  const createLLMTools_1 = require("./utils/createLLMTools");
35
35
  Object.defineProperty(exports, "createLLMTools", { enumerable: true, get: function () { return createLLMTools_1.createLLMTools; } });
36
- const createCodeExamples_1 = require("./utils/createCodeExamples");
37
- Object.defineProperty(exports, "createCodeExamples", { enumerable: true, get: function () { return createCodeExamples_1.createCodeExamples; } });
36
+ const createCodeSamples_1 = require("./utils/createCodeSamples");
37
+ Object.defineProperty(exports, "createCodeSamples", { enumerable: true, get: function () { return createCodeSamples_1.createCodeSamples; } });
38
38
  const createValidateOnClient_1 = require("./utils/createValidateOnClient");
39
39
  Object.defineProperty(exports, "createValidateOnClient", { enumerable: true, get: function () { return createValidateOnClient_1.createValidateOnClient; } });
40
- const getGeneratorConfig_1 = require("./utils/getGeneratorConfig");
41
- Object.defineProperty(exports, "getGeneratorConfig", { enumerable: true, get: function () { return getGeneratorConfig_1.getGeneratorConfig; } });
40
+ const resolveGeneratorConfigValues_1 = require("./utils/resolveGeneratorConfigValues");
41
+ Object.defineProperty(exports, "resolveGeneratorConfigValues", { enumerable: true, get: function () { return resolveGeneratorConfigValues_1.resolveGeneratorConfigValues; } });
42
42
  _a = (0, createVovkApp_1.createVovkApp)(), exports.get = _a.get, exports.post = _a.post, exports.put = _a.put, exports.patch = _a.patch, exports.del = _a.del, exports.head = _a.head, exports.options = _a.options, exports.prefix = _a.prefix, exports.initSegment = _a.initSegment;
@@ -6,11 +6,11 @@ const applyComponentsSchemas_1 = require("./applyComponentsSchemas");
6
6
  const inlineRefs_1 = require("./inlineRefs");
7
7
  function openAPIToVovkSchema({ apiRoot, source: { object: openAPIObject }, getModuleName, getMethodName, errorMessageKey, segmentName, }) {
8
8
  segmentName = segmentName ?? '';
9
- const forceApiRoot = apiRoot ??
10
- openAPIObject.servers?.[0]?.url ??
11
- ('host' in openAPIObject
12
- ? `https://${openAPIObject.host}${'basePath' in openAPIObject ? openAPIObject.basePath : ''}`
13
- : null);
9
+ const forceApiRoot = apiRoot ||
10
+ (openAPIObject.servers?.[0]?.url ??
11
+ ('host' in openAPIObject
12
+ ? `https://${openAPIObject.host}${'basePath' in openAPIObject ? openAPIObject.basePath : ''}`
13
+ : null));
14
14
  if (!forceApiRoot) {
15
15
  throw new Error('API root URL is required in OpenAPI configuration');
16
16
  }
@@ -24,6 +24,7 @@ function openAPIToVovkSchema({ apiRoot, source: { object: openAPIObject }, getMo
24
24
  segmentName,
25
25
  segmentType: 'mixin',
26
26
  controllers: {},
27
+ forceApiRoot,
27
28
  meta: {
28
29
  openAPIObject: noPathsOpenAPIObject,
29
30
  },
@@ -48,7 +49,6 @@ function openAPIToVovkSchema({ apiRoot, source: { object: openAPIObject }, getMo
48
49
  operationObject: operation,
49
50
  });
50
51
  segment.controllers[rpcModuleName] ??= {
51
- forceApiRoot,
52
52
  rpcModuleName,
53
53
  handlers: {},
54
54
  };
@@ -114,6 +114,9 @@ function openAPIToVovkSchema({ apiRoot, source: { object: openAPIObject }, getMo
114
114
  httpMethod: method.toUpperCase(),
115
115
  path,
116
116
  operationObject: operation,
117
+ misc: {
118
+ originalPath: path,
119
+ },
117
120
  validation: {
118
121
  ...(query && {
119
122
  query: (0, applyComponentsSchemas_1.applyComponentsSchemas)(query, componentsSchemas, segmentName),
@@ -1,10 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.vovkSchemaToOpenAPI = vovkSchemaToOpenAPI;
4
- const createCodeExamples_1 = require("../utils/createCodeExamples");
4
+ const createCodeSamples_1 = require("../utils/createCodeSamples");
5
5
  const types_1 = require("../types");
6
6
  const getJSONSchemaSample_1 = require("../utils/getJSONSchemaSample");
7
- const getGeneratorConfig_1 = require("../utils/getGeneratorConfig");
7
+ const resolveGeneratorConfigValues_1 = require("../utils/resolveGeneratorConfigValues");
8
8
  function extractComponents(schema) {
9
9
  if (!schema)
10
10
  return [undefined, {}];
@@ -47,7 +47,7 @@ function extractComponents(schema) {
47
47
  function vovkSchemaToOpenAPI({ rootEntry = 'api', schema: fullSchema, configs, segmentName: givenSegmentName, }) {
48
48
  const paths = {};
49
49
  const components = {};
50
- const { openAPIObject, snippets: snippetsConfig, package: packageJson, } = (0, getGeneratorConfig_1.getGeneratorConfig)({
50
+ const { openAPIObject, samples: samplesConfig, package: packageJson, } = (0, resolveGeneratorConfigValues_1.resolveGeneratorConfigValues)({
51
51
  schema: fullSchema,
52
52
  configs,
53
53
  segmentName: givenSegmentName ?? null,
@@ -65,12 +65,12 @@ function vovkSchemaToOpenAPI({ rootEntry = 'api', schema: fullSchema, configs, s
65
65
  const [iterationValidation, iterationComponents] = extractComponents(h?.validation?.iteration);
66
66
  // TODO: Handle name conflicts?
67
67
  Object.assign(components, queryComponents, bodyComponents, paramsComponents, outputComponents, iterationComponents);
68
- const { ts, rs, py } = (0, createCodeExamples_1.createCodeExamples)({
68
+ const { ts, rs, py } = (0, createCodeSamples_1.createCodeSamples)({
69
69
  package: packageJson,
70
70
  handlerName,
71
71
  handlerSchema: h,
72
72
  controllerSchema: c,
73
- config: snippetsConfig,
73
+ config: samplesConfig,
74
74
  });
75
75
  const queryParameters = queryValidation && 'type' in queryValidation && 'properties' in queryValidation
76
76
  ? Object.entries(queryValidation.properties ?? {}).map(([propName, propSchema]) => ({
@@ -88,7 +88,8 @@ function vovkSchemaToOpenAPI({ rootEntry = 'api', schema: fullSchema, configs, s
88
88
  schema: propSchema,
89
89
  }))
90
90
  : null;
91
- const path = '/' + [rootEntry.replace(/^\/+|\/+$/g, ''), segmentName, c.prefix, h.path].filter(Boolean).join('/');
91
+ const path = h.misc?.originalPath ??
92
+ '/' + [rootEntry.replace(/^\/+|\/+$/g, ''), segmentName, c.prefix, h.path].filter(Boolean).join('/');
92
93
  paths[path] = paths[path] ?? {};
93
94
  const httpMethod = h.httpMethod.toLowerCase();
94
95
  paths[path][httpMethod] ??= {};
@@ -194,8 +195,8 @@ function vovkSchemaToOpenAPI({ rootEntry = 'api', schema: fullSchema, configs, s
194
195
  }
195
196
  return {
196
197
  ...openAPIObject,
197
- openapi: '3.1.0',
198
198
  components: {
199
+ ...openAPIObject?.components,
199
200
  schemas: {
200
201
  ...(openAPIObject?.components?.schemas ?? components),
201
202
  HttpStatus: {
package/mjs/types.d.ts CHANGED
@@ -256,6 +256,8 @@ export type VovkBasicJSONSchema = {
256
256
  $ref?: string;
257
257
  items?: VovkBasicJSONSchema;
258
258
  enum?: KnownAny[];
259
+ minimum?: number;
260
+ maximum?: number;
259
261
  title?: string;
260
262
  description?: string;
261
263
  properties?: {
@@ -299,7 +301,7 @@ export type VovkReadmeConfig = {
299
301
  installCommand?: string;
300
302
  description?: string;
301
303
  };
302
- export type VovkSnippetsConfig = {
304
+ export type VovkSamplesConfig = {
303
305
  apiRoot?: string;
304
306
  headers?: Record<string, string>;
305
307
  };
@@ -334,7 +336,7 @@ export interface VovkGeneratorConfigCommon {
334
336
  origin?: string | null;
335
337
  package?: VovkPackageJson;
336
338
  readme?: VovkReadmeConfig;
337
- snippets?: VovkSnippetsConfig;
339
+ samples?: VovkSamplesConfig;
338
340
  openAPIObject?: Partial<OpenAPIObject>;
339
341
  reExports?: Record<string, string>;
340
342
  imports?: {
@@ -370,6 +372,7 @@ export interface VovkOpenAPIMixin {
370
372
  getModuleName?: 'nestjs-operation-id' | (string & {}) | 'api' | GetOpenAPINameFn;
371
373
  getMethodName?: 'nestjs-operation-id' | 'camel-case-operation-id' | 'auto' | GetOpenAPINameFn;
372
374
  errorMessageKey?: string;
375
+ mixinName?: string;
373
376
  }
374
377
  export interface VovkOpenAPIMixinNormalized extends Omit<VovkOpenAPIMixin, 'source' | 'getMethodName' | 'getModuleName'> {
375
378
  source: Exclude<NonNullable<VovkOpenAPIMixin['source']>, {
@@ -388,10 +391,9 @@ export interface VovkSegmentConfig extends VovkGeneratorConfigCommon {
388
391
  export interface VovkGeneratorConfig extends VovkGeneratorConfigCommon {
389
392
  segments?: Record<string, VovkSegmentConfig>;
390
393
  }
391
- export interface VovkGeneratorConfigStrict extends Omit<VovkGeneratorConfig, 'origin' | 'segments'> {
392
- origin: string;
394
+ export interface VovkGeneratorConfigStrict extends Omit<VovkGeneratorConfig, 'segments'> {
393
395
  segments?: Record<string, Omit<VovkSegmentConfig, 'openAPIMixin'> & {
394
- openAPIMixin: VovkOpenAPIMixinNormalized;
396
+ openAPIMixin?: VovkOpenAPIMixinNormalized;
395
397
  }>;
396
398
  }
397
399
  type VovkUserConfig = {
@@ -1,4 +1,4 @@
1
- import type { KnownAny, VovkControllerSchema, VovkHandlerSchema, VovkSnippetsConfig } from '../types';
1
+ import type { KnownAny, VovkControllerSchema, VovkHandlerSchema, VovkSamplesConfig } from '../types';
2
2
  export type CodeSamplePackageJson = {
3
3
  name?: string;
4
4
  version?: string;
@@ -7,12 +7,12 @@ export type CodeSamplePackageJson = {
7
7
  py_name?: string;
8
8
  [key: string]: KnownAny;
9
9
  };
10
- export declare function createCodeExamples({ handlerName, handlerSchema, controllerSchema, package: packageJson, config, }: {
10
+ export declare function createCodeSamples({ handlerName, handlerSchema, controllerSchema, package: packageJson, config, }: {
11
11
  handlerName: string;
12
12
  handlerSchema: VovkHandlerSchema;
13
13
  controllerSchema: VovkControllerSchema;
14
14
  package?: CodeSamplePackageJson;
15
- config: VovkSnippetsConfig;
15
+ config: VovkSamplesConfig;
16
16
  }): {
17
17
  ts: string;
18
18
  py: string;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createCodeExamples = createCodeExamples;
3
+ exports.createCodeSamples = createCodeSamples;
4
4
  const getJSONSchemaExample_1 = require("./getJSONSchemaExample");
5
5
  const getSampleFromObject_1 = require("./getSampleFromObject");
6
6
  const toSnakeCase = (str) => str
@@ -71,7 +71,7 @@ ${[
71
71
  config?.apiRoot ? ` apiRoot: '${config.apiRoot}',` : null,
72
72
  config?.headers
73
73
  ? ` init: {
74
- headers: ${(0, getSampleFromObject_1.getSampleFromObject)(config.headers, { stripQuotes: true, indent: 6 })}
74
+ headers: ${(0, getSampleFromObject_1.getSampleFromObject)(config.headers, { stripQuotes: true, indent: 6, nestingIndent: 4 })}
75
75
  },`
76
76
  : null,
77
77
  ]
@@ -159,35 +159,6 @@ ${outputValidation ? `print(response)\n${getPySample(outputValidation, 0)}` : ''
159
159
  function generateRustCode({ handlerName, rpcName, packageName, queryValidation, bodyValidation, paramsValidation, outputValidation, iterationValidation, config, }) {
160
160
  const getRsJSONSample = (schema, indent) => (0, getJSONSchemaExample_1.getJSONSchemaExample)(schema, { stripQuotes: false, indent: indent ?? 4 });
161
161
  const getRsOutputSample = (schema, indent) => (0, getJSONSchemaExample_1.getJSONSchemaExample)(schema, { stripQuotes: true, indent: indent ?? 4 });
162
- /* const getRsFormSample = (schema: VovkBasicJSONSchema, indent?: number, nesting = 0) => {
163
- let formSample = 'let form = multipart::Form::new()';
164
- for (const [key, prop] of Object.entries(schema.properties || {})) {
165
- const target = prop.oneOf?.[0] || prop.anyOf?.[0] || prop.allOf?.[0] || prop;
166
- let sampleValue; // = value.type === 'object' ? 'object_unknown' : getSampleValue(value);
167
- if (target.type === 'string' && target.format === 'binary') {
168
- sampleValue = isTextFormat(target.contentMediaType)
169
- ? 'multipart::Part::text("text_content")'
170
- : 'multipart::Part::bytes(binary_data)';
171
-
172
- if (target.contentMediaType) {
173
- sampleValue += `.mime_str("${target.contentMediaType}").unwrap()`;
174
- }
175
- } else if (prop.type === 'array') {
176
- if (nesting === 0 && prop.items) {
177
- sampleValue =
178
- getRsFormSample(prop.items, indent, nesting + 1) + getRsFormSample(prop.items, indent, nesting + 1);
179
- } else {
180
- sampleValue = '"array_unknown"';
181
- }
182
- } else if (target.type === 'object') {
183
- sampleValue = '"object_unknown"';
184
- } else {
185
- sampleValue = `"${getSampleValue(target)}"`;
186
- }
187
- formSample += `\n${getIndentSpaces(4)}.part("${key}", ${sampleValue});`;
188
- }
189
- return formSample;
190
- }; */
191
162
  const getRsFormSample = (schema) => {
192
163
  let formSample = 'let form = multipart::Form::new()';
193
164
  for (const [key, prop] of Object.entries(schema.properties || {})) {
@@ -244,8 +215,7 @@ use serde_json::{
244
215
  from_value,
245
216
  json
246
217
  };
247
- ${bodyValidation?.['x-isForm'] ? `use multipart;` : ''}
248
-
218
+ ${bodyValidation?.['x-isForm'] ? `use multipart;\n` : ''}
249
219
  pub fn main() {${bodyValidation?.['x-isForm'] ? '\n ' + getRsFormSample(bodyValidation) + '\n' : ''}
250
220
  let response = ${rpcNameSnake}::${handlerNameSnake}(
251
221
  ${bodyValidation ? getBody(bodyValidation) : '()'}, /* body */
@@ -278,7 +248,7 @@ pub fn main() {${bodyValidation?.['x-isForm'] ? '\n ' + getRsFormSample(bodyVal
278
248
  }`;
279
249
  return RS_CODE.trim();
280
250
  }
281
- function createCodeExamples({ handlerName, handlerSchema, controllerSchema, package: packageJson, config, }) {
251
+ function createCodeSamples({ handlerName, handlerSchema, controllerSchema, package: packageJson, config, }) {
282
252
  const queryValidation = handlerSchema?.validation?.query;
283
253
  const bodyValidation = handlerSchema?.validation?.body;
284
254
  const paramsValidation = handlerSchema?.validation?.params;
@@ -114,9 +114,8 @@ ignoreBinary) {
114
114
  if (entries.length === 0)
115
115
  return '{}';
116
116
  const formattedEntries = [];
117
- const isTopLevel = indent === 0;
118
117
  // Add top-level description for objects
119
- if (isTopLevel && schema.type === 'object' && schema.description) {
118
+ if (schema.type === 'object' && schema.description) {
120
119
  const descLines = schema.description.split('\n');
121
120
  formattedEntries.push(`${indentStr}${nestIndentStr}${comment} -----`);
122
121
  descLines.forEach((line) => {
@@ -1,7 +1,7 @@
1
1
  import type { PackageJson } from 'type-fest';
2
- import type { VovkGeneratorConfigCommon, VovkReadmeConfig, VovkSnippetsConfig, VovkSchema, VovkGeneratorConfigStrict } from '../types';
2
+ import type { VovkGeneratorConfigCommon, VovkReadmeConfig, VovkSamplesConfig, VovkSchema, VovkGeneratorConfigStrict } from '../types';
3
3
  import type { OpenAPIObject } from 'openapi3-ts/oas31';
4
- export declare function getGeneratorConfig({ schema, configs, segmentName, isBundle, projectPackageJson, }: {
4
+ export declare function resolveGeneratorConfigValues({ schema, configs, segmentName, isBundle, projectPackageJson, }: {
5
5
  schema: VovkSchema;
6
6
  configs?: VovkGeneratorConfigCommon[];
7
7
  segmentName: string | null;
@@ -10,7 +10,7 @@ export declare function getGeneratorConfig({ schema, configs, segmentName, isBun
10
10
  }): {
11
11
  readme: VovkReadmeConfig;
12
12
  openAPIObject: OpenAPIObject;
13
- snippets: VovkSnippetsConfig;
13
+ samples: VovkSamplesConfig;
14
14
  origin: string;
15
15
  package: PackageJson;
16
16
  imports: VovkGeneratorConfigStrict['imports'];
@@ -3,9 +3,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.getGeneratorConfig = getGeneratorConfig;
6
+ exports.resolveGeneratorConfigValues = resolveGeneratorConfigValues;
7
7
  const deepExtend_1 = __importDefault(require("./deepExtend"));
8
- function getGeneratorConfig({ schema, configs, segmentName, isBundle, projectPackageJson, }) {
8
+ function resolveGeneratorConfigValues({ schema, configs, segmentName, isBundle, projectPackageJson, }) {
9
9
  const packageJson = (0, deepExtend_1.default)({}, {
10
10
  main: './index.cjs',
11
11
  module: './index.mjs',
@@ -27,21 +27,32 @@ function getGeneratorConfig({ schema, configs, segmentName, isBundle, projectPac
27
27
  types: './openapi.d.cts',
28
28
  },
29
29
  },
30
- }, projectPackageJson, schema.meta?.config?.generatorConfig?.package, isBundle ? schema.meta?.config?.bundle?.generatorConfig?.package : undefined, segmentName ? schema.segments?.[segmentName]?.meta?.package : undefined, segmentName ? schema.meta?.config?.generatorConfig?.segments?.[segmentName]?.package : undefined, configs?.reduce((acc, config) => (0, deepExtend_1.default)(acc, config.package), {}));
30
+ }, projectPackageJson, schema.meta?.config?.generatorConfig?.package, isBundle ? schema.meta?.config?.bundle?.generatorConfig?.package : undefined, typeof segmentName === 'string' ? schema.segments?.[segmentName]?.meta?.package : undefined, typeof segmentName === 'string'
31
+ ? schema.meta?.config?.generatorConfig?.segments?.[segmentName]?.package
32
+ : undefined, configs?.reduce((acc, config) => (0, deepExtend_1.default)(acc, config.package), {}));
31
33
  return {
32
34
  package: Object.fromEntries(Object.entries(packageJson).filter(([key]) => ['name', 'version', 'description', 'license', 'authors', 'repository', 'homepage', 'bugs', 'keywords'].includes(key))),
33
35
  openAPIObject: (0, deepExtend_1.default)({}, {
36
+ openapi: '3.1.0',
34
37
  info: {
35
38
  title: packageJson.name,
36
39
  version: packageJson.version,
37
40
  description: packageJson.description,
38
41
  },
39
- }, schema.meta?.config?.generatorConfig?.openAPIObject, isBundle ? schema.meta?.config?.bundle?.generatorConfig?.openAPIObject : undefined, segmentName ? schema?.segments?.[segmentName]?.meta?.openAPIObject : undefined, segmentName ? schema.meta?.config?.generatorConfig?.segments?.[segmentName]?.openAPIObject : undefined, configs?.reduce((acc, config) => (0, deepExtend_1.default)(acc, config.openAPIObject), {})),
40
- snippets: (0, deepExtend_1.default)({}, schema.meta?.config?.generatorConfig?.snippets, isBundle ? schema.meta?.config?.bundle?.generatorConfig?.snippets : undefined, segmentName ? schema.meta?.config?.generatorConfig?.segments?.[segmentName]?.snippets : undefined, configs?.reduce((acc, config) => (0, deepExtend_1.default)(acc, config.snippets), {})),
41
- readme: (0, deepExtend_1.default)({}, schema.meta?.config?.generatorConfig?.readme, isBundle ? schema.meta?.config?.bundle?.generatorConfig?.readme : undefined, segmentName ? schema.meta?.config?.generatorConfig?.segments?.[segmentName]?.readme : undefined, configs?.reduce((acc, config) => (0, deepExtend_1.default)(acc, config.readme), {})),
42
+ }, schema.meta?.config?.generatorConfig?.openAPIObject, isBundle ? schema.meta?.config?.bundle?.generatorConfig?.openAPIObject : undefined, typeof segmentName === 'string' ? schema?.segments?.[segmentName]?.meta?.openAPIObject : undefined, typeof segmentName === 'string'
43
+ ? schema.meta?.config?.generatorConfig?.segments?.[segmentName]?.openAPIObject
44
+ : undefined, configs?.reduce((acc, config) => (0, deepExtend_1.default)(acc, config.openAPIObject), {})),
45
+ samples: (0, deepExtend_1.default)({}, schema.meta?.config?.generatorConfig?.samples, isBundle ? schema.meta?.config?.bundle?.generatorConfig?.samples : undefined, typeof segmentName === 'string'
46
+ ? schema.meta?.config?.generatorConfig?.segments?.[segmentName]?.samples
47
+ : undefined, configs?.reduce((acc, config) => (0, deepExtend_1.default)(acc, config.samples), {})),
48
+ readme: (0, deepExtend_1.default)({}, schema.meta?.config?.generatorConfig?.readme, isBundle ? schema.meta?.config?.bundle?.generatorConfig?.readme : undefined, typeof segmentName === 'string'
49
+ ? schema.meta?.config?.generatorConfig?.segments?.[segmentName]?.readme
50
+ : undefined, configs?.reduce((acc, config) => (0, deepExtend_1.default)(acc, config.readme), {})),
42
51
  origin: [
43
52
  isBundle ? schema.meta?.config?.bundle?.generatorConfig?.origin : undefined,
44
- segmentName ? schema.meta?.config?.generatorConfig?.segments?.[segmentName]?.origin : undefined,
53
+ typeof segmentName === 'string'
54
+ ? schema.meta?.config?.generatorConfig?.segments?.[segmentName]?.origin
55
+ : undefined,
45
56
  schema.meta?.config?.generatorConfig?.origin,
46
57
  ...(configs?.map((config) => config.origin) ?? []),
47
58
  ]
@@ -51,10 +62,19 @@ function getGeneratorConfig({ schema, configs, segmentName, isBundle, projectPac
51
62
  fetcher: ['vovk'],
52
63
  validateOnClient: null,
53
64
  createRPC: ['vovk'],
54
- }, schema.meta?.config?.generatorConfig?.imports, isBundle ? schema.meta?.config?.bundle?.generatorConfig?.imports : undefined, segmentName ? schema.meta?.config?.generatorConfig?.segments?.[segmentName]?.imports : undefined, configs?.reduce((acc, config) => (0, deepExtend_1.default)(acc, config.imports), {})),
65
+ }, schema.meta?.config?.generatorConfig?.imports, isBundle ? schema.meta?.config?.bundle?.generatorConfig?.imports : undefined, typeof segmentName === 'string'
66
+ ? schema.meta?.config?.generatorConfig?.segments?.[segmentName]?.imports
67
+ : undefined, configs?.reduce((acc, config) => (0, deepExtend_1.default)(acc, config.imports), {})),
55
68
  reExports: (0, deepExtend_1.default)(
56
69
  // segmentName can be an empty string (for the root segment) and null (for composed clients)
57
70
  // therefore, !segmentName indicates that this either a composed client or a root segment of a segmented client
58
- {}, !segmentName && schema.meta?.config?.generatorConfig?.reExports, !segmentName && isBundle ? schema.meta?.config?.bundle?.generatorConfig?.reExports : undefined, segmentName ? schema.meta?.config?.generatorConfig?.segments?.[segmentName]?.reExports : undefined, configs?.reduce((acc, config) => (0, deepExtend_1.default)(acc, config.reExports), {})),
71
+ {}, !segmentName && schema.meta?.config?.generatorConfig?.reExports, !segmentName && isBundle ? schema.meta?.config?.bundle?.generatorConfig?.reExports : undefined,
72
+ // for segmented client, apply all reExports from all segments
73
+ typeof segmentName !== 'string' &&
74
+ Object.values(schema.meta?.config?.generatorConfig?.segments ?? {}).reduce((acc, segmentConfig) => (0, deepExtend_1.default)(acc, segmentConfig.reExports ?? {}), {}),
75
+ // for a specific segment, apply reExports from that segment
76
+ typeof segmentName === 'string'
77
+ ? schema.meta?.config?.generatorConfig?.segments?.[segmentName]?.reExports
78
+ : undefined, configs?.reduce((acc, config) => (0, deepExtend_1.default)(acc, config.reExports), {})),
59
79
  };
60
80
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vovk",
3
- "version": "3.0.0-draft.413",
3
+ "version": "3.0.0-draft.415",
4
4
  "main": "./cjs/index.js",
5
5
  "module": "./mjs/index.js",
6
6
  "types": "./mjs/index.d.ts",