vovk-cli 0.1.3 → 0.3.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (138) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/client-templates/{schemaTs → schema-ts}/schema.ts.ejs +1 -1
  3. package/client-templates/{tsBase → ts-base}/index.ts.ejs +1 -1
  4. package/dist/bundle/index.d.mts +1 -1
  5. package/dist/bundle/index.mjs +67 -45
  6. package/dist/dev/{diffSegmentSchema.d.mts → diff-segment-schema.d.mts} +0 -17
  7. package/dist/dev/{diffSegmentSchema.mjs → diff-segment-schema.mjs} +1 -17
  8. package/dist/dev/{ensureSchemaFiles.d.mts → ensure-schema-files.d.mts} +1 -1
  9. package/dist/dev/{ensureSchemaFiles.mjs → ensure-schema-files.mjs} +30 -12
  10. package/dist/dev/index.mjs +23 -17
  11. package/dist/dev/log-diff-result.d.mts +3 -0
  12. package/dist/dev/{logDiffResult.mjs → log-diff-result.mjs} +2 -2
  13. package/dist/dev/{writeMetaJson.d.mts → write-meta-json.d.mts} +1 -1
  14. package/dist/dev/{writeMetaJson.mjs → write-meta-json.mjs} +3 -3
  15. package/dist/dev/{writeOneSegmentSchemaFile.d.mts → write-one-segment-schema-file.d.mts} +1 -1
  16. package/dist/dev/{writeOneSegmentSchemaFile.mjs → write-one-segment-schema-file.mjs} +8 -3
  17. package/dist/generate/ensure-client.d.mts +3 -0
  18. package/dist/generate/{ensureClient.mjs → ensure-client.mjs} +1 -1
  19. package/dist/generate/generate.d.mts +2 -2
  20. package/dist/generate/generate.mjs +41 -28
  21. package/dist/generate/{getClientTemplateFiles.d.mts → get-client-template-files.d.mts} +1 -1
  22. package/dist/generate/{getClientTemplateFiles.mjs → get-client-template-files.mjs} +8 -4
  23. package/dist/generate/{getProjectFullSchema.d.mts → get-project-full-schema.d.mts} +1 -1
  24. package/dist/generate/{getProjectFullSchema.mjs → get-project-full-schema.mjs} +3 -3
  25. package/dist/generate/{getTemplateClientImports.mjs → get-template-client-imports.mjs} +2 -2
  26. package/dist/generate/index.d.mts +2 -2
  27. package/dist/generate/index.mjs +46 -34
  28. package/dist/generate/{writeOneClientFile.d.mts → write-one-client-file.d.mts} +5 -5
  29. package/dist/generate/{writeOneClientFile.mjs → write-one-client-file.mjs} +10 -8
  30. package/dist/{getProjectInfo/getConfig/getRelativeSrcRoot.mjs → get-project-info/get-config/get-relative-src-root.mjs} +1 -1
  31. package/dist/get-project-info/get-config/get-template-defs.d.mts +22 -0
  32. package/dist/{getProjectInfo/getConfig/getTemplateDefs.mjs → get-project-info/get-config/get-template-defs.mjs} +35 -61
  33. package/dist/{getProjectInfo/getConfig/getUserConfig.mjs → get-project-info/get-config/get-user-config.mjs} +2 -2
  34. package/dist/{getProjectInfo/getConfig → get-project-info/get-config}/index.d.mts +2 -2
  35. package/dist/{getProjectInfo/getConfig → get-project-info/get-config}/index.mjs +17 -12
  36. package/dist/{getProjectInfo/getMetaSchema.d.mts → get-project-info/get-meta-schema.d.mts} +1 -1
  37. package/dist/{getProjectInfo → get-project-info}/index.mjs +3 -3
  38. package/dist/index.mjs +25 -16
  39. package/dist/init/{createConfig.d.mts → create-config.d.mts} +1 -1
  40. package/dist/init/{createConfig.mjs → create-config.mjs} +6 -6
  41. package/dist/init/index.d.mts +1 -1
  42. package/dist/init/index.mjs +54 -22
  43. package/dist/init/{installDependencies.d.mts → install-dependencies.d.mts} +2 -1
  44. package/dist/init/{installDependencies.mjs → install-dependencies.mjs} +11 -3
  45. package/dist/init/{logUpdateDependenciesError.d.mts → log-update-dependencies-error.d.mts} +2 -2
  46. package/dist/init/{logUpdateDependenciesError.mjs → log-update-dependencies-error.mjs} +1 -1
  47. package/dist/init/{updateDependenciesWithoutInstalling.d.mts → update-dependencies-without-installing.d.mts} +1 -1
  48. package/dist/init/{updateDependenciesWithoutInstalling.mjs → update-dependencies-without-installing.mjs} +1 -2
  49. package/dist/init/update-gitignore.d.mts +2 -0
  50. package/dist/init/update-gitignore.mjs +20 -0
  51. package/dist/new/index.d.mts +1 -1
  52. package/dist/new/index.mjs +2 -2
  53. package/dist/new/{newModule.d.mts → new-module.d.mts} +1 -1
  54. package/dist/new/{newModule.mjs → new-module.mjs} +15 -9
  55. package/dist/new/{newSegment.d.mts → new-segment.d.mts} +1 -1
  56. package/dist/new/{newSegment.mjs → new-segment.mjs} +11 -6
  57. package/dist/new/render.mjs +3 -3
  58. package/dist/types.d.mts +1 -1
  59. package/dist/utils/{compileJSONSchemaToTypeScriptType.mjs → compile-json-schema-to-typescript-type.mjs} +1 -1
  60. package/dist/utils/{formatLoggedSegmentName.mjs → format-logged-segment-name.mjs} +1 -1
  61. package/dist/utils/{generateFnName.d.mts → generate-fn-name.d.mts} +0 -9
  62. package/dist/utils/{generateFnName.mjs → generate-fn-name.mjs} +2 -9
  63. package/dist/utils/generated-banner.d.mts +1 -0
  64. package/dist/utils/generated-banner.mjs +3 -0
  65. package/dist/utils/get-available-port.d.mts +1 -0
  66. package/dist/utils/{getAvailablePort.mjs → get-available-port.mjs} +2 -14
  67. package/dist/utils/get-file-system-entry-type.d.mts +6 -0
  68. package/dist/utils/{getFileSystemEntryType.mjs → get-file-system-entry-type.mjs} +5 -5
  69. package/dist/utils/{getPackageJson.d.mts → get-package-json.d.mts} +1 -1
  70. package/dist/utils/{getPackageJson.mjs → get-package-json.mjs} +1 -1
  71. package/dist/utils/{locateSegments.d.mts → locate-segments.d.mts} +1 -1
  72. package/dist/utils/{locateSegments.mjs → locate-segments.mjs} +1 -1
  73. package/dist/utils/{normalizeOpenAPIMixin.d.mts → normalize-openapi-mixin.d.mts} +2 -2
  74. package/dist/utils/{normalizeOpenAPIMixin.mjs → normalize-openapi-mixin.mjs} +20 -5
  75. package/dist/utils/prettify.d.mts +4 -0
  76. package/dist/utils/prettify.mjs +39 -3
  77. package/dist/utils/remove-unlisted-directories.d.mts +1 -0
  78. package/dist/utils/remove-unlisted-directories.mjs +99 -0
  79. package/dist/utils/{resolveAbsoluteModulePath.mjs → resolve-absolute-module-path.mjs} +2 -3
  80. package/dist/utils/{updateConfigProperty.mjs → update-config-property.mjs} +1 -1
  81. package/module-templates/arktype/controller.ts.ejs +2 -2
  82. package/module-templates/type/controller.ts.ejs +2 -2
  83. package/module-templates/type/service.ts.ejs +2 -2
  84. package/module-templates/valibot/controller.ts.ejs +2 -2
  85. package/module-templates/zod/controller.ts.ejs +2 -2
  86. package/package.json +23 -30
  87. package/client-templates/jsBase/index.d.ts.ejs +0 -21
  88. package/client-templates/jsBase/index.js.ejs +0 -18
  89. package/client-templates/openapiJs/openapi.d.ts.ejs +0 -4
  90. package/client-templates/openapiJs/openapi.js.ejs +0 -4
  91. package/client-templates/schemaJs/schema.d.ts.ejs +0 -10
  92. package/client-templates/schemaJs/schema.js.ejs +0 -29
  93. package/dist/dev/logDiffResult.d.mts +0 -3
  94. package/dist/generate/ensureClient.d.mts +0 -3
  95. package/dist/getProjectInfo/getConfig/getTemplateDefs.d.mts +0 -25
  96. package/dist/utils/getAvailablePort.d.mts +0 -9
  97. package/dist/utils/getFileSystemEntryType.d.mts +0 -5
  98. package/dist/utils/removeUnlistedDirectories.d.mts +0 -9
  99. package/dist/utils/removeUnlistedDirectories.mjs +0 -60
  100. package/client-templates/{openapiJson → openapi-json}/openapi.json.ejs +0 -0
  101. package/client-templates/{openapiTs → openapi-ts}/openapi.ts.ejs +0 -0
  102. package/client-templates/{packageJson → package-json}/package.json.ejs +0 -0
  103. package/client-templates/{schemaJson → schema-json}/schema.json.ejs +0 -0
  104. package/dist/generate/{getTemplateClientImports.d.mts → get-template-client-imports.d.mts} +0 -0
  105. package/dist/{getProjectInfo/getConfig/getConfigAbsolutePaths.d.mts → get-project-info/get-config/get-config-absolute-paths.d.mts} +0 -0
  106. package/dist/{getProjectInfo/getConfig/getConfigAbsolutePaths.mjs → get-project-info/get-config/get-config-absolute-paths.mjs} +0 -0
  107. package/dist/{getProjectInfo/getConfig/getRelativeSrcRoot.d.mts → get-project-info/get-config/get-relative-src-root.d.mts} +0 -0
  108. package/dist/{getProjectInfo/getConfig/getUserConfig.d.mts → get-project-info/get-config/get-user-config.d.mts} +0 -0
  109. package/dist/{getProjectInfo/getMetaSchema.mjs → get-project-info/get-meta-schema.mjs} +1 -1
  110. package/dist/{getProjectInfo → get-project-info}/index.d.mts +0 -0
  111. package/dist/init/{checkTSConfigForExperimentalDecorators.d.mts → check-tsconfig-for-experimental-decorators.d.mts} +0 -0
  112. package/dist/init/{checkTSConfigForExperimentalDecorators.mjs → check-tsconfig-for-experimental-decorators.mjs} +1 -1
  113. package/dist/init/{updateNPMScripts.d.mts → update-npm-scripts.d.mts} +0 -0
  114. package/dist/init/{updateNPMScripts.mjs → update-npm-scripts.mjs} +0 -0
  115. package/dist/init/{updateTypeScriptConfig.d.mts → update-typescript-config.d.mts} +0 -0
  116. package/dist/init/{updateTypeScriptConfig.mjs → update-typescript-config.mjs} +1 -1
  117. package/dist/new/{addClassToSegmentCode.d.mts → add-class-to-segment-code.d.mts} +0 -0
  118. package/dist/new/{addClassToSegmentCode.mjs → add-class-to-segment-code.mjs} +0 -0
  119. package/dist/new/{addCommonTerms.d.mts → add-common-terms.d.mts} +0 -0
  120. package/dist/new/{addCommonTerms.mjs → add-common-terms.mjs} +0 -0
  121. package/dist/utils/{chalkHighlightThing.d.mts → chalk-highlight-thing.d.mts} +0 -0
  122. package/dist/utils/{chalkHighlightThing.mjs → chalk-highlight-thing.mjs} +0 -0
  123. package/dist/utils/{compileJSONSchemaToTypeScriptType.d.mts → compile-json-schema-to-typescript-type.d.mts} +1 -1
  124. package/dist/utils/{compileTs.d.mts → compile-ts.d.mts} +0 -0
  125. package/dist/utils/{compileTs.mjs → compile-ts.mjs} +1 -1
  126. /package/dist/utils/{debounceWithArgs.d.mts → debounce-with-args.d.mts} +0 -0
  127. /package/dist/utils/{debounceWithArgs.mjs → debounce-with-args.mjs} +0 -0
  128. /package/dist/utils/{formatLoggedSegmentName.d.mts → format-logged-segment-name.d.mts} +0 -0
  129. /package/dist/utils/{getLogger.d.mts → get-logger.d.mts} +0 -0
  130. /package/dist/utils/{getLogger.mjs → get-logger.mjs} +0 -0
  131. /package/dist/utils/{getNPMPackageMetadata.d.mts → get-npm-package-metadata.d.mts} +0 -0
  132. /package/dist/utils/{getNPMPackageMetadata.mjs → get-npm-package-metadata.mjs} +0 -0
  133. /package/dist/utils/{getPublicModuleNameFromPath.d.mts → get-public-module-name-from-path.d.mts} +0 -0
  134. /package/dist/utils/{getPublicModuleNameFromPath.mjs → get-public-module-name-from-path.mjs} +0 -0
  135. /package/dist/utils/{pickSegmentFullSchema.d.mts → pick-segment-full-schema.d.mts} +0 -0
  136. /package/dist/utils/{pickSegmentFullSchema.mjs → pick-segment-full-schema.mjs} +0 -0
  137. /package/dist/utils/{resolveAbsoluteModulePath.d.mts → resolve-absolute-module-path.d.mts} +0 -0
  138. /package/dist/utils/{updateConfigProperty.d.mts → update-config-property.d.mts} +0 -0
@@ -1,10 +1,10 @@
1
1
  import path from 'node:path';
2
2
  import { glob } from 'glob';
3
- import { resolveAbsoluteModulePath } from '../utils/resolveAbsoluteModulePath.mjs';
4
- import { getFileSystemEntryType, FileSystemEntryType } from '../utils/getFileSystemEntryType.mjs';
5
- import { getPublicModuleNameFromPath } from '../utils/getPublicModuleNameFromPath.mjs';
6
- import omit from 'lodash/omit.js';
7
3
  import merge from 'lodash/merge.js';
4
+ import omit from 'lodash/omit.js';
5
+ import { FileSystemEntryType, getFileSystemEntryType } from '../utils/get-file-system-entry-type.mjs';
6
+ import { getPublicModuleNameFromPath } from '../utils/get-public-module-name-from-path.mjs';
7
+ import { resolveAbsoluteModulePath } from '../utils/resolve-absolute-module-path.mjs';
8
8
  export async function getClientTemplateFiles({ config, cwd, log, configKey, cliGenerateOptions, }) {
9
9
  const usedTemplateDefs = {};
10
10
  const fromTemplates = configKey === 'composedClient'
@@ -18,6 +18,10 @@ export async function getClientTemplateFiles({ config, cwd, log, configKey, cliG
18
18
  const configOutDir = config[configKey].outDir;
19
19
  for (const templateName of fromTemplates) {
20
20
  if (!(templateName in config.clientTemplateDefs)) {
21
+ // js family removed in v4
22
+ if (['js', 'jsBase', 'schemaJs', 'openapiJs'].includes(templateName)) {
23
+ throw new Error(`The "${templateName}" template was removed in v4. Use "ts" instead.`);
24
+ }
21
25
  throw new Error(`Unknown template name: ${templateName}`);
22
26
  }
23
27
  usedTemplateDefs[templateName] = config.clientTemplateDefs[templateName];
@@ -1,6 +1,6 @@
1
1
  import type { VovkSchema } from 'vovk';
2
- import type { ProjectInfo } from '../getProjectInfo/index.mjs';
3
2
  import { type VovkStrictConfig } from 'vovk/internal';
3
+ import type { ProjectInfo } from '../get-project-info/index.mjs';
4
4
  export declare function getProjectFullSchema({ schemaOutAbsolutePath, isNextInstalled, log, config, }: {
5
5
  schemaOutAbsolutePath: string;
6
6
  isNextInstalled: boolean;
@@ -1,9 +1,9 @@
1
- import { readFile, access } from 'node:fs/promises';
1
+ import { access, readFile } from 'node:fs/promises';
2
2
  import path from 'node:path';
3
3
  import { glob } from 'glob';
4
- import { META_FILE_NAME, ROOT_SEGMENT_FILE_NAME } from '../dev/writeOneSegmentSchemaFile.mjs';
5
- import { getMetaSchema } from '../getProjectInfo/getMetaSchema.mjs';
6
4
  import { deepExtend, VovkSchemaIdEnum } from 'vovk/internal';
5
+ import { META_FILE_NAME, ROOT_SEGMENT_FILE_NAME } from '../dev/write-one-segment-schema-file.mjs';
6
+ import { getMetaSchema } from '../get-project-info/get-meta-schema.mjs';
7
7
  export async function getProjectFullSchema({ schemaOutAbsolutePath, isNextInstalled, log, config, }) {
8
8
  const result = {
9
9
  $schema: VovkSchemaIdEnum.SCHEMA,
@@ -1,6 +1,6 @@
1
1
  import path from 'node:path';
2
2
  import { resolveGeneratorConfigValues } from 'vovk/internal';
3
- import { ROOT_SEGMENT_FILE_NAME } from '../dev/writeOneSegmentSchemaFile.mjs';
3
+ import { ROOT_SEGMENT_FILE_NAME } from '../dev/write-one-segment-schema-file.mjs';
4
4
  export function getTemplateClientImports({ config, fullSchema, outCwdRelativeDir, segmentName, isBundle, outputConfigs, }) {
5
5
  const { imports: configImports } = resolveGeneratorConfigValues({
6
6
  config,
@@ -12,7 +12,7 @@ export function getTemplateClientImports({ config, fullSchema, outCwdRelativeDir
12
12
  const imports = {
13
13
  fetcher: configImports?.fetcher ?? 'vovk/fetcher',
14
14
  validateOnClient: configImports?.validateOnClient ?? null,
15
- createRPC: configImports?.createRPC ?? 'vovk/createRPC',
15
+ createRPC: configImports?.createRPC ?? 'vovk/create-rpc',
16
16
  };
17
17
  const getImportPath = (p, s = '') => p.startsWith('.') ? path.relative(path.join(outCwdRelativeDir, s), p) : p;
18
18
  const clientImports = {
@@ -1,6 +1,6 @@
1
1
  import type { VovkSchema } from 'vovk';
2
+ import type { ProjectInfo } from '../get-project-info/index.mjs';
2
3
  import type { GenerateOptions } from '../types.mjs';
3
- import type { ProjectInfo } from '../getProjectInfo/index.mjs';
4
4
  export declare class VovkGenerate {
5
5
  #private;
6
6
  constructor({ cliGenerateOptions, projectInfo, forceNothingWrittenLog, }: {
@@ -8,7 +8,7 @@ export declare class VovkGenerate {
8
8
  projectInfo: ProjectInfo;
9
9
  forceNothingWrittenLog?: boolean;
10
10
  });
11
- start(): void;
11
+ start(): Promise<void> | undefined;
12
12
  generate(): Promise<void>;
13
13
  getFullSchema(): Promise<VovkSchema>;
14
14
  watch({ throttleDelay }: {
@@ -1,9 +1,9 @@
1
1
  import path from 'node:path';
2
2
  import * as chokidar from 'chokidar';
3
- import { getProjectFullSchema } from './getProjectFullSchema.mjs';
3
+ import { chalkHighlightThing } from '../utils/chalk-highlight-thing.mjs';
4
+ import { locateSegments } from '../utils/locate-segments.mjs';
4
5
  import { generate } from './generate.mjs';
5
- import { locateSegments } from '../utils/locateSegments.mjs';
6
- import { chalkHighlightThing } from '../utils/chalkHighlightThing.mjs';
6
+ import { getProjectFullSchema } from './get-project-full-schema.mjs';
7
7
  const THROTTLE_DELAY = 5000;
8
8
  export class VovkGenerate {
9
9
  #cliGenerateOptions;
@@ -19,10 +19,10 @@ export class VovkGenerate {
19
19
  if (watch) {
20
20
  const throttleDelay = typeof watch === 'boolean' ? THROTTLE_DELAY : parseFloat(watch) * 1e3 || THROTTLE_DELAY;
21
21
  this.watch({ throttleDelay });
22
+ return;
22
23
  }
23
- else {
24
- this.generate();
25
- }
24
+ // return the promise so one-shot generate errors reach the CLI error handler
25
+ return this.generate();
26
26
  }
27
27
  async generate() {
28
28
  const fullSchema = await this.getFullSchema();
@@ -63,6 +63,17 @@ export class VovkGenerate {
63
63
  watchSchema({ schemaPath, throttleDelay }) {
64
64
  const { log } = this.#projectInfo;
65
65
  let lastGenerationTime = 0;
66
+ let pendingTimer = null;
67
+ const generateCode = async () => {
68
+ try {
69
+ lastGenerationTime = Date.now();
70
+ await this.generate();
71
+ log.debug(`Regenerated from schema changes`);
72
+ }
73
+ catch (error) {
74
+ log.error(`Failed to regenerate from schema: ${error instanceof Error ? error.message : String(error)}`);
75
+ }
76
+ };
66
77
  chokidar
67
78
  .watch(schemaPath, {
68
79
  persistent: true,
@@ -72,20 +83,15 @@ export class VovkGenerate {
72
83
  if (event === 'change' || event === 'add' || event === 'ready' || event === 'unlink') {
73
84
  log.debug(`Schema file ${event}: ${path}`);
74
85
  const now = Date.now();
75
- const shouldGenerateImmediately = now - lastGenerationTime > throttleDelay;
76
- const generateCode = async () => {
77
- try {
78
- lastGenerationTime = Date.now();
79
- await this.generate();
80
- log.debug(`Regenerated from schema changes`);
81
- }
82
- catch (error) {
83
- log.error(`Failed to regenerate from schema: ${error instanceof Error ? error.message : String(error)}`);
84
- }
85
- };
86
- // Generate immediately if it's been a while since the last generation
87
- if (shouldGenerateImmediately) {
88
- generateCode();
86
+ // generate immediately outside the throttle window, otherwise defer to the end of it
87
+ if (now - lastGenerationTime > throttleDelay) {
88
+ void generateCode();
89
+ }
90
+ else if (!pendingTimer) {
91
+ pendingTimer = setTimeout(() => {
92
+ pendingTimer = null;
93
+ void generateCode();
94
+ }, throttleDelay - (now - lastGenerationTime));
89
95
  }
90
96
  }
91
97
  });
@@ -111,6 +117,17 @@ export class VovkGenerate {
111
117
  watchOpenApiSpecLocal({ openApiSpecPaths, throttleDelay }) {
112
118
  const { log, cwd } = this.#projectInfo;
113
119
  let lastGenerationTime = 0;
120
+ let pendingTimer = null;
121
+ const generateCode = async () => {
122
+ try {
123
+ lastGenerationTime = Date.now();
124
+ await this.generate();
125
+ log.debug(`Regenerated from OpenAPI spec changes`);
126
+ }
127
+ catch (error) {
128
+ log.error(`Failed to regenerate from OpenAPI spec: ${error instanceof Error ? error.message : String(error)}`);
129
+ }
130
+ };
114
131
  chokidar
115
132
  .watch(openApiSpecPaths, {
116
133
  cwd,
@@ -121,20 +138,15 @@ export class VovkGenerate {
121
138
  if (event === 'change' || event === 'add' || event === 'ready' || event === 'unlink') {
122
139
  log.debug(`OpenAPI spec file changed: ${path}`);
123
140
  const now = Date.now();
124
- const shouldGenerateImmediately = now - lastGenerationTime > throttleDelay;
125
- const generateCode = async () => {
126
- try {
127
- lastGenerationTime = Date.now();
128
- await this.generate();
129
- log.debug(`Regenerated from OpenAPI spec changes`);
130
- }
131
- catch (error) {
132
- log.error(`Failed to regenerate from OpenAPI spec: ${error instanceof Error ? error.message : String(error)}`);
133
- }
134
- };
135
- // Generate immediately if it's been a while since the last generation
136
- if (shouldGenerateImmediately) {
137
- generateCode();
141
+ // generate immediately outside the throttle window, otherwise defer to the end of it
142
+ if (now - lastGenerationTime > throttleDelay) {
143
+ void generateCode();
144
+ }
145
+ else if (!pendingTimer) {
146
+ pendingTimer = setTimeout(() => {
147
+ pendingTimer = null;
148
+ void generateCode();
149
+ }, throttleDelay - (now - lastGenerationTime));
138
150
  }
139
151
  }
140
152
  });
@@ -1,10 +1,10 @@
1
+ import type { OpenAPIObject } from 'openapi3-ts/oas31';
2
+ import type { PackageJson } from 'type-fest';
1
3
  import type { VovkSchema } from 'vovk';
2
4
  import { type VovkReadmeConfig, type VovkSamplesConfig, type VovkStrictConfig } from 'vovk/internal';
3
- import type { PackageJson } from 'type-fest';
4
- import type { OpenAPIObject } from 'openapi3-ts/oas31';
5
- import type { ProjectInfo } from '../getProjectInfo/index.mjs';
6
- import type { ClientTemplateFile } from './getClientTemplateFiles.mjs';
7
- import type { Segment } from '../utils/locateSegments.mjs';
5
+ import type { ProjectInfo } from '../get-project-info/index.mjs';
6
+ import type { Segment } from '../utils/locate-segments.mjs';
7
+ import type { ClientTemplateFile } from './get-client-template-files.mjs';
8
8
  export declare function normalizeOutTemplatePath(out: string, packageJson: PackageJson): string;
9
9
  export declare function writeOneClientFile({ cwd, projectInfo, clientTemplateFile, fullSchema, prettifyClient, segmentName, templateContent, matterResult: { data, content }, openAPIObject, package: packageJson, readme, samples, reExports, isEnsuringClient, outCwdRelativeDir, templateDef, locatedSegments, isNodeNextResolution, hasMixins, isVovkProject, vovkCliPackage, isBundle, origin, configKey, cliSchemaPath, projectConfig, }: {
10
10
  cwd: string;
@@ -1,15 +1,16 @@
1
1
  import fs from 'node:fs/promises';
2
2
  import path from 'node:path';
3
+ import TOML from '@iarna/toml';
3
4
  import ejs from 'ejs';
4
5
  import _ from 'lodash';
5
- import * as YAML from 'yaml';
6
- import TOML from '@iarna/toml';
7
6
  import { createCodeSamples, reattachMixinDefs, VovkSchemaIdEnum, } from 'vovk/internal';
8
- import { compileJSONSchemaToTypeScriptType } from '../utils/compileJSONSchemaToTypeScriptType.mjs';
9
- import { getTemplateClientImports } from './getTemplateClientImports.mjs';
10
- import { chalkHighlightThing } from '../utils/chalkHighlightThing.mjs';
11
- import { ROOT_SEGMENT_FILE_NAME } from '../dev/writeOneSegmentSchemaFile.mjs';
12
- import { prettify } from '../utils/prettify.mjs';
7
+ import * as YAML from 'yaml';
8
+ import { ROOT_SEGMENT_FILE_NAME } from '../dev/write-one-segment-schema-file.mjs';
9
+ import { chalkHighlightThing } from '../utils/chalk-highlight-thing.mjs';
10
+ import { compileJSONSchemaToTypeScriptType } from '../utils/compile-json-schema-to-typescript-type.mjs';
11
+ import { GENERATED_BANNER_PREFIX } from '../utils/generated-banner.mjs';
12
+ import { prettify, warnIfPrettierMissing } from '../utils/prettify.mjs';
13
+ import { getTemplateClientImports } from './get-template-client-imports.mjs';
13
14
  export function normalizeOutTemplatePath(out, packageJson) {
14
15
  return out.replace('[package_name]', packageJson.name?.replace(/-/g, '_') ?? 'my_package_name');
15
16
  }
@@ -27,7 +28,7 @@ templateContent, matterResult: { data, content }, openAPIObject, package: packag
27
28
  // Feel free to report an issue at https://github.com/finom/vovk/issues`;
28
29
  placeholder = outPath.endsWith('.py') ? placeholder.replace(/\/\//g, '#') : placeholder;
29
30
  const getFirstLineBanner = (type = 'c') => {
30
- const text = `Generated by vovk-cli v${vovkCliPackage.version} at ${new Date().toISOString()}`;
31
+ const text = `${GENERATED_BANNER_PREFIX} v${vovkCliPackage.version} at ${new Date().toISOString()}`;
31
32
  switch (type) {
32
33
  case 'html':
33
34
  return `<!-- ${text} -->`;
@@ -130,6 +131,7 @@ templateContent, matterResult: { data, content }, openAPIObject, package: packag
130
131
  : templateContent;
131
132
  // Optionally prettify
132
133
  if (prettifyClient) {
134
+ await warnIfPrettierMissing(log);
133
135
  rendered = await prettify(rendered, outPath);
134
136
  }
135
137
  if (isEnsuringClient) {
@@ -1,5 +1,5 @@
1
1
  import path from 'node:path';
2
- import { getFileSystemEntryType, FileSystemEntryType } from '../../utils/getFileSystemEntryType.mjs';
2
+ import { FileSystemEntryType, getFileSystemEntryType } from '../../utils/get-file-system-entry-type.mjs';
3
3
  export async function getRelativeSrcRoot({ cwd }) {
4
4
  // Next.js Docs: src/app or src/pages will be ignored if app or pages are present in the root directory.
5
5
  if ((await getFileSystemEntryType(path.join(cwd, 'app'))) === FileSystemEntryType.DIRECTORY) {
@@ -0,0 +1,22 @@
1
+ import type { VovkStrictConfig } from 'vovk/internal';
2
+ export declare const BuiltInTemplateName: {
3
+ readonly tsBase: "tsBase";
4
+ readonly ts: "ts";
5
+ readonly schemaTs: "schemaTs";
6
+ readonly schemaJson: "schemaJson";
7
+ readonly openapiTs: "openapiTs";
8
+ readonly openapiJson: "openapiJson";
9
+ readonly readme: "readme";
10
+ readonly packageJson: "packageJson";
11
+ readonly mixins: "mixins";
12
+ readonly rsSrc: "rsSrc";
13
+ readonly rsPkg: "rsPkg";
14
+ readonly rsReadme: "rsReadme";
15
+ readonly rs: "rs";
16
+ readonly pySrc: "pySrc";
17
+ readonly pyPkg: "pyPkg";
18
+ readonly pyReadme: "pyReadme";
19
+ readonly py: "py";
20
+ };
21
+ export type BuiltInTemplateName = (typeof BuiltInTemplateName)[keyof typeof BuiltInTemplateName];
22
+ export declare function getTemplateDefs(userTemplateDefs?: VovkStrictConfig['clientTemplateDefs']): VovkStrictConfig['clientTemplateDefs'];
@@ -1,105 +1,79 @@
1
- export var BuiltInTemplateName;
2
- (function (BuiltInTemplateName) {
3
- // ts/js
4
- BuiltInTemplateName["tsBase"] = "tsBase";
5
- BuiltInTemplateName["jsBase"] = "jsBase";
6
- BuiltInTemplateName["ts"] = "ts";
7
- BuiltInTemplateName["js"] = "js";
1
+ // const object instead of enum, node 26 runs ts with erasable syntax only
2
+ export const BuiltInTemplateName = {
3
+ // ts
4
+ tsBase: 'tsBase',
5
+ ts: 'ts',
8
6
  // schema
9
- BuiltInTemplateName["schemaTs"] = "schemaTs";
10
- BuiltInTemplateName["schemaJs"] = "schemaJs";
11
- BuiltInTemplateName["schemaJson"] = "schemaJson";
7
+ schemaTs: 'schemaTs',
8
+ schemaJson: 'schemaJson',
12
9
  // openapi
13
- BuiltInTemplateName["openapiTs"] = "openapiTs";
14
- BuiltInTemplateName["openapiJs"] = "openapiJs";
15
- BuiltInTemplateName["openapiJson"] = "openapiJson";
10
+ openapiTs: 'openapiTs',
11
+ openapiJson: 'openapiJson',
16
12
  // misc
17
- BuiltInTemplateName["readme"] = "readme";
18
- BuiltInTemplateName["packageJson"] = "packageJson";
19
- BuiltInTemplateName["mixins"] = "mixins";
13
+ readme: 'readme',
14
+ packageJson: 'packageJson',
15
+ mixins: 'mixins',
20
16
  // other languages (packages installed separately)
21
- BuiltInTemplateName["rsSrc"] = "rsSrc";
22
- BuiltInTemplateName["rsPkg"] = "rsPkg";
23
- BuiltInTemplateName["rsReadme"] = "rsReadme";
24
- BuiltInTemplateName["rs"] = "rs";
25
- BuiltInTemplateName["pySrc"] = "pySrc";
26
- BuiltInTemplateName["pyPkg"] = "pyPkg";
27
- BuiltInTemplateName["pyReadme"] = "pyReadme";
28
- BuiltInTemplateName["py"] = "py";
29
- })(BuiltInTemplateName || (BuiltInTemplateName = {}));
17
+ rsSrc: 'rsSrc',
18
+ rsPkg: 'rsPkg',
19
+ rsReadme: 'rsReadme',
20
+ rs: 'rs',
21
+ pySrc: 'pySrc',
22
+ pyPkg: 'pyPkg',
23
+ pyReadme: 'pyReadme',
24
+ py: 'py',
25
+ };
30
26
  export function getTemplateDefs(userTemplateDefs = {}) {
31
27
  const defs = {};
32
28
  const builtInDefs = {
33
29
  [BuiltInTemplateName.openapiTs]: {
34
- templatePath: `vovk-cli/client-templates/${BuiltInTemplateName.openapiTs}/`,
35
- requires: {
36
- [BuiltInTemplateName.openapiJson]: './',
37
- },
38
- },
39
- [BuiltInTemplateName.openapiJs]: {
40
- templatePath: `vovk-cli/client-templates/${BuiltInTemplateName.openapiJs}/`,
30
+ templatePath: 'vovk-cli/client-templates/openapi-ts/',
41
31
  requires: {
42
32
  [BuiltInTemplateName.openapiJson]: './',
43
33
  },
44
34
  },
45
35
  [BuiltInTemplateName.openapiJson]: {
46
- templatePath: `vovk-cli/client-templates/${BuiltInTemplateName.openapiJson}/`,
36
+ templatePath: 'vovk-cli/client-templates/openapi-json/',
47
37
  },
48
38
  [BuiltInTemplateName.tsBase]: {
49
- templatePath: `vovk-cli/client-templates/${BuiltInTemplateName.tsBase}/`,
39
+ templatePath: 'vovk-cli/client-templates/ts-base/',
50
40
  requires: {
51
41
  [BuiltInTemplateName.schemaTs]: './',
52
42
  [BuiltInTemplateName.mixins]: './', // used conditionally if OpenAPI mixins are used
53
43
  },
54
44
  },
55
- [BuiltInTemplateName.jsBase]: {
56
- templatePath: `vovk-cli/client-templates/${BuiltInTemplateName.jsBase}/`,
57
- requires: {
58
- [BuiltInTemplateName.schemaJs]: './',
59
- [BuiltInTemplateName.mixins]: './', // used conditionally if OpenAPI mixins are used
60
- },
61
- },
62
45
  [BuiltInTemplateName.ts]: {
63
46
  requires: {
64
47
  [BuiltInTemplateName.tsBase]: './',
65
48
  [BuiltInTemplateName.openapiTs]: './',
66
49
  },
67
50
  },
68
- [BuiltInTemplateName.js]: {
69
- requires: {
70
- [BuiltInTemplateName.jsBase]: './',
71
- [BuiltInTemplateName.openapiJs]: './',
72
- },
73
- },
74
51
  [BuiltInTemplateName.schemaTs]: {
75
- templatePath: `vovk-cli/client-templates/${BuiltInTemplateName.schemaTs}/`,
76
- },
77
- [BuiltInTemplateName.schemaJs]: {
78
- templatePath: `vovk-cli/client-templates/${BuiltInTemplateName.schemaJs}/`,
52
+ templatePath: 'vovk-cli/client-templates/schema-ts/',
79
53
  },
80
54
  [BuiltInTemplateName.schemaJson]: {
81
- templatePath: `vovk-cli/client-templates/${BuiltInTemplateName.schemaJson}/`,
55
+ templatePath: 'vovk-cli/client-templates/schema-json/',
82
56
  },
83
57
  [BuiltInTemplateName.readme]: {
84
- templatePath: `vovk-cli/client-templates/${BuiltInTemplateName.readme}/`,
58
+ templatePath: 'vovk-cli/client-templates/readme/',
85
59
  },
86
60
  [BuiltInTemplateName.packageJson]: {
87
- templatePath: `vovk-cli/client-templates/${BuiltInTemplateName.packageJson}/`,
61
+ templatePath: 'vovk-cli/client-templates/package-json/',
88
62
  },
89
63
  [BuiltInTemplateName.mixins]: {
90
- templatePath: `vovk-cli/client-templates/${BuiltInTemplateName.mixins}/`,
64
+ templatePath: 'vovk-cli/client-templates/mixins/',
91
65
  },
92
66
  [BuiltInTemplateName.rsSrc]: {
93
- templatePath: `vovk-rust/client-templates/${BuiltInTemplateName.rsSrc}/`,
67
+ templatePath: 'vovk-rust/client-templates/rs-src/',
94
68
  requires: {
95
69
  [BuiltInTemplateName.schemaJson]: './',
96
70
  },
97
71
  },
98
72
  [BuiltInTemplateName.rsPkg]: {
99
- templatePath: `vovk-rust/client-templates/${BuiltInTemplateName.rsPkg}/`,
73
+ templatePath: 'vovk-rust/client-templates/rs-pkg/',
100
74
  },
101
75
  [BuiltInTemplateName.rsReadme]: {
102
- templatePath: `vovk-rust/client-templates/${BuiltInTemplateName.rsReadme}/`,
76
+ templatePath: 'vovk-rust/client-templates/rs-readme/',
103
77
  },
104
78
  [BuiltInTemplateName.rs]: {
105
79
  composedClient: {
@@ -112,16 +86,16 @@ export function getTemplateDefs(userTemplateDefs = {}) {
112
86
  },
113
87
  },
114
88
  [BuiltInTemplateName.pySrc]: {
115
- templatePath: `vovk-python/client-templates/${BuiltInTemplateName.pySrc}/`,
89
+ templatePath: 'vovk-python/client-templates/py-src/',
116
90
  requires: {
117
91
  [BuiltInTemplateName.schemaJson]: './',
118
92
  },
119
93
  },
120
94
  [BuiltInTemplateName.pyPkg]: {
121
- templatePath: `vovk-python/client-templates/${BuiltInTemplateName.pyPkg}/`,
95
+ templatePath: 'vovk-python/client-templates/py-pkg/',
122
96
  },
123
97
  [BuiltInTemplateName.pyReadme]: {
124
- templatePath: `vovk-python/client-templates/${BuiltInTemplateName.pyReadme}/`,
98
+ templatePath: 'vovk-python/client-templates/py-readme/',
125
99
  },
126
100
  [BuiltInTemplateName.py]: {
127
101
  composedClient: {
@@ -1,9 +1,9 @@
1
- import { pathToFileURL } from 'node:url';
2
1
  import { readFile } from 'node:fs/promises';
3
2
  import { createRequire } from 'node:module';
4
3
  import { dirname, extname } from 'node:path';
4
+ import { pathToFileURL } from 'node:url';
5
5
  import vm from 'node:vm';
6
- import { getConfigAbsolutePaths } from './getConfigAbsolutePaths.mjs';
6
+ import { getConfigAbsolutePaths } from './get-config-absolute-paths.mjs';
7
7
  const isVMModulesEnabled = typeof vm.SourceTextModule !== 'undefined';
8
8
  export async function getUserConfig({ configPath: givenConfigPath, cwd, }) {
9
9
  const configAbsolutePaths = await getConfigAbsolutePaths({ configPath: givenConfigPath, cwd });
@@ -1,7 +1,7 @@
1
+ import type { LogLevelNames } from 'loglevel';
1
2
  import type { VovkConfig } from 'vovk';
2
3
  import { type VovkStrictConfig } from 'vovk/internal';
3
- import type { LogLevelNames } from 'loglevel';
4
- import { getLogger } from '../../utils/getLogger.mjs';
4
+ import { getLogger } from '../../utils/get-logger.mjs';
5
5
  export declare function getConfig({ configPath, cwd, logLevel, }: {
6
6
  configPath?: string;
7
7
  cwd: string;
@@ -1,16 +1,20 @@
1
1
  import path from 'node:path';
2
2
  import { VovkSchemaIdEnum } from 'vovk/internal';
3
- import { getLogger } from '../../utils/getLogger.mjs';
4
- import { getUserConfig } from './getUserConfig.mjs';
5
- import { getRelativeSrcRoot } from './getRelativeSrcRoot.mjs';
6
- import { getTemplateDefs, BuiltInTemplateName } from './getTemplateDefs.mjs';
7
- import { normalizeOpenAPIMixin } from '../../utils/normalizeOpenAPIMixin.mjs';
8
- import { chalkHighlightThing } from '../../utils/chalkHighlightThing.mjs';
3
+ import { chalkHighlightThing } from '../../utils/chalk-highlight-thing.mjs';
4
+ import { getLogger } from '../../utils/get-logger.mjs';
5
+ import { normalizeOpenAPIMixin } from '../../utils/normalize-openapi-mixin.mjs';
6
+ import { getRelativeSrcRoot } from './get-relative-src-root.mjs';
7
+ import { BuiltInTemplateName, getTemplateDefs } from './get-template-defs.mjs';
8
+ import { getUserConfig } from './get-user-config.mjs';
9
9
  export async function getConfig({ configPath, cwd, logLevel, }) {
10
10
  const { configAbsolutePaths, error, userConfig } = await getUserConfig({
11
11
  configPath,
12
12
  cwd,
13
13
  });
14
+ // a config that exists but fails to load must not be silently replaced by defaults
15
+ if (!userConfig && configAbsolutePaths.length) {
16
+ throw new Error(`Failed to load config file at ${chalkHighlightThing(configAbsolutePaths[0])}. ${error?.message ?? 'Unknown error'}`);
17
+ }
14
18
  const conf = userConfig ?? {};
15
19
  logLevel = logLevel ?? conf.logLevel ?? 'info';
16
20
  const log = getLogger(logLevel);
@@ -24,9 +28,9 @@ export async function getConfig({ configPath, cwd, logLevel, }) {
24
28
  composedClient: {
25
29
  ...conf.composedClient,
26
30
  enabled: conf.composedClient?.enabled ?? true,
27
- fromTemplates: conf.composedClient?.fromTemplates ?? [BuiltInTemplateName.js],
28
- outDir: conf.composedClient?.outDir ?? './node_modules/.vovk-client',
29
- prettifyClient: conf.composedClient?.prettifyClient ?? false,
31
+ fromTemplates: conf.composedClient?.fromTemplates ?? [BuiltInTemplateName.ts],
32
+ outDir: conf.composedClient?.outDir ?? path.join(srcRoot ?? '.', 'client'),
33
+ prettifyClient: conf.composedClient?.prettifyClient ?? true,
30
34
  },
31
35
  segmentedClient: {
32
36
  ...conf.segmentedClient,
@@ -45,9 +49,10 @@ export async function getConfig({ configPath, cwd, logLevel, }) {
45
49
  },
46
50
  outputConfig: {},
47
51
  build: conf.bundle?.build ??
48
- (() => {
52
+ // isMissingBuild lets the bundle command fail fast before doing any work
53
+ Object.assign(() => {
49
54
  throw new Error('No bundle.build function specified');
50
- }),
55
+ }, { isMissingBuild: true }),
51
56
  ...conf.bundle,
52
57
  },
53
58
  modulesDir: conf.modulesDir ?? path.join(srcRoot ?? '.', 'modules'),
@@ -86,7 +91,7 @@ export async function getConfig({ configPath, cwd, logLevel, }) {
86
91
  config.exposeConfigKeys = conf.exposeConfigKeys;
87
92
  } // else it's false and exposeConfigKeys already is []
88
93
  if (!userConfig) {
89
- log.warn(`Unable to load config at ${chalkHighlightThing(`${cwd}/`)}. Using default values. ${error ?? ''}`);
94
+ log.warn(`No config file found at ${chalkHighlightThing(`${cwd}/`)}. Using default values.`);
90
95
  }
91
96
  return { config, srcRoot, configAbsolutePaths, userConfig, log };
92
97
  }
@@ -1,4 +1,4 @@
1
- import { type VovkStrictConfig, type VovkMetaSchema } from 'vovk/internal';
1
+ import { type VovkMetaSchema, type VovkStrictConfig } from 'vovk/internal';
2
2
  export declare function getMetaSchema({ config }: {
3
3
  config: VovkStrictConfig;
4
4
  }): VovkMetaSchema;
@@ -1,7 +1,7 @@
1
- import path from 'node:path';
2
- import { getConfig } from './getConfig/index.mjs';
3
- import { getPackageJson } from '../utils/getPackageJson.mjs';
4
1
  import { readFile } from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { getPackageJson } from '../utils/get-package-json.mjs';
4
+ import { getConfig } from './get-config/index.mjs';
5
5
  export async function getProjectInfo({ port: givenPort, cwd = process.cwd(), configPath, srcRootRequired = true, logLevel, } = {
6
6
  logLevel: 'info',
7
7
  }) {