vovk-cli 0.0.1 → 0.0.4

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.
@@ -1,4 +1,4 @@
1
- import { ProjectInfo } from '../getProjectInfo/index.mjs';
1
+ import type { ProjectInfo } from '../getProjectInfo/index.mjs';
2
2
  /**
3
3
  * Ensure that the schema files are created to avoid any import errors.
4
4
  */
@@ -171,6 +171,9 @@ export class VovkDev {
171
171
  const schemaOutAbsolutePath = path.join(cwd, this.#schemaOut ?? this.#projectInfo.config.schemaOutDir);
172
172
  if (isInitial) {
173
173
  callback();
174
+ if (!this.#segments.length) {
175
+ log.info(`Create a root segment with ${chalkHighlightThing('npx vovk new segment')} command`);
176
+ }
174
177
  }
175
178
  else {
176
179
  log.info('Config file has been updated');
@@ -254,7 +257,7 @@ export class VovkDev {
254
257
  }
255
258
  catch (error) {
256
259
  log.error(`Error parsing JSON from ${chalkHighlightThing(endpoint)} for ${formatLoggedSegmentName(segmentName)}: ${error?.message}`);
257
- log.error(`Response text: ${text.length > 2000 ? text.slice(0, 2000) + '...' : text}`);
260
+ log.error(`Response text: ${text.length > 2000 ? `${text.slice(0, 2000)}...` : text}`);
258
261
  return { isError: true };
259
262
  }
260
263
  if (resp.status !== 200) {
@@ -4,7 +4,7 @@ import { META_FILE_NAME } from './writeOneSegmentSchemaFile.mjs';
4
4
  import { chalkHighlightThing } from '../utils/chalkHighlightThing.mjs';
5
5
  import { getMetaSchema } from '../getProjectInfo/getMetaSchema.mjs';
6
6
  export async function writeMetaJson(schemaOutAbsolutePath, projectInfo) {
7
- const metaJsonPath = path.join(schemaOutAbsolutePath, META_FILE_NAME + '.json');
7
+ const metaJsonPath = path.join(schemaOutAbsolutePath, `${META_FILE_NAME}.json`);
8
8
  const metaStr = JSON.stringify(getMetaSchema({
9
9
  config: projectInfo.config,
10
10
  }), null, 2);
@@ -72,7 +72,7 @@ const cliOptionsToOpenAPIMixins = ({ openapiGetMethodName, openapiGetModuleName,
72
72
  apiRoot: openapiRootUrl?.[i] ?? '',
73
73
  getModuleName: openapiGetModuleName?.[i] ?? 'api',
74
74
  getMethodName: openapiGetMethodName?.[i] ?? 'auto',
75
- mixinName: openapiMixinName?.[i] ?? 'mixin' + (i > 0 ? i + 1 : ''),
75
+ mixinName: openapiMixinName?.[i] ?? `mixin${i > 0 ? i + 1 : ''}`,
76
76
  };
77
77
  }) || []).map(({ source, apiRoot, getModuleName, getMethodName, mixinName }) => [
78
78
  mixinName,
@@ -100,6 +100,7 @@ export async function generate({ isEnsuringClient = false, isBundle = false, pro
100
100
  .forEach(([segmentName, segmentConfig]) => {
101
101
  fullSchema.segments = {
102
102
  ...fullSchema.segments,
103
+ // biome-ignore lint/style/noNonNullAssertion: TODO
103
104
  [segmentName]: openAPIToVovkSchema({ ...segmentConfig.openAPIMixin, segmentName }).segments[segmentName],
104
105
  };
105
106
  });
@@ -59,7 +59,7 @@ export async function getClientTemplateFiles({ config, cwd, log, configKey, cliG
59
59
  templateFiles.push({
60
60
  templateName,
61
61
  templateFilePath: filePath,
62
- relativeDir: path.relative(isSingleFileTemplate ? path.dirname(templateAbsolutePath) : templateAbsolutePath, path.dirname(filePath) + '/'),
62
+ relativeDir: path.relative(isSingleFileTemplate ? path.dirname(templateAbsolutePath) : templateAbsolutePath, `${path.dirname(filePath)}/`),
63
63
  outCwdRelativeDir,
64
64
  templateDef,
65
65
  });
@@ -1,4 +1,4 @@
1
- import { type VovkSchema } from 'vovk';
1
+ import type { VovkSchema } from 'vovk';
2
2
  import type { ProjectInfo } from '../getProjectInfo/index.mjs';
3
3
  import { type VovkStrictConfig } from 'vovk/internal';
4
4
  export declare function getProjectFullSchema({ schemaOutAbsolutePath, isNextInstalled, log, config, }: {
@@ -1,4 +1,4 @@
1
- import { type VovkSchema } from 'vovk';
1
+ import type { VovkSchema } from 'vovk';
2
2
  import type { GenerateOptions } from '../types.mjs';
3
3
  import type { ProjectInfo } from '../getProjectInfo/index.mjs';
4
4
  export declare class VovkGenerate {
@@ -76,7 +76,7 @@ templateContent, matterResult: { data, content }, openAPIObject, package: packag
76
76
  outCwdRelativeDir,
77
77
  segmentName,
78
78
  outputConfigs: [templateDef.outputConfig ?? {}],
79
- })['composedClient'],
79
+ }).composedClient,
80
80
  segmentImports: Object.fromEntries(Object.values(fullSchema.segments).map(({ segmentName: sName }) => {
81
81
  const clientImports = getTemplateClientImports({
82
82
  config: projectConfig,
@@ -86,7 +86,7 @@ templateContent, matterResult: { data, content }, openAPIObject, package: packag
86
86
  outCwdRelativeDir,
87
87
  outputConfigs: [projectConfig[configKey].outputConfig ?? {}, templateDef.outputConfig ?? {}],
88
88
  });
89
- const imports = configKey === 'composedClient' ? clientImports['composedClient'] : clientImports['segmentedClient'][sName];
89
+ const imports = configKey === 'composedClient' ? clientImports.composedClient : clientImports.segmentedClient[sName];
90
90
  return [sName, imports];
91
91
  })),
92
92
  segmentMeta: Object.fromEntries(Object.values(fullSchema.segments).map(({ segmentName: sName, forceApiRoot }) => {
@@ -113,7 +113,7 @@ templateContent, matterResult: { data, content }, openAPIObject, package: packag
113
113
  ];
114
114
  })),
115
115
  };
116
- if (data.imports instanceof Array) {
116
+ if (Array.isArray(data.imports)) {
117
117
  for (const imp of data.imports) {
118
118
  t.imports = {
119
119
  [imp]: await import(imp),
@@ -132,7 +132,7 @@ templateContent, matterResult: { data, content }, openAPIObject, package: packag
132
132
  rendered = await prettify(rendered, outPath);
133
133
  }
134
134
  if (isEnsuringClient) {
135
- rendered = rendered + `\n\n${placeholder}`;
135
+ rendered = `${rendered}\n\n${placeholder}`;
136
136
  }
137
137
  // Read existing file content to compare
138
138
  const existingContent = await fs.readFile(outPath, 'utf-8').catch(() => null);
@@ -40,7 +40,6 @@ async function getLoadersForExtension(configPath) {
40
40
  return canUseVM
41
41
  ? [() => importWithVMCommonJS(configPath, code), () => importWithCacheBuster(configPath)]
42
42
  : [() => importWithCacheBuster(configPath)];
43
- case '.js':
44
43
  default:
45
44
  return canUseVM
46
45
  ? [
@@ -86,7 +86,7 @@ export async function getConfig({ configPath, cwd, logLevel, }) {
86
86
  config.exposeConfigKeys = conf.exposeConfigKeys;
87
87
  } // else it's false and exposeConfigKeys already is []
88
88
  if (!userConfig) {
89
- log.warn(`Unable to load config at ${chalkHighlightThing(cwd + '/')}. Using default values. ${error ?? ''}`);
89
+ log.warn(`Unable to load config at ${chalkHighlightThing(`${cwd}/`)}. Using default values. ${error ?? ''}`);
90
90
  }
91
91
  return { config, srcRoot, configAbsolutePaths, userConfig, log };
92
92
  }
@@ -1,4 +1,4 @@
1
- import { LogLevelNames } from 'loglevel';
1
+ import type { LogLevelNames } from 'loglevel';
2
2
  export type ProjectInfo = Awaited<ReturnType<typeof getProjectInfo>>;
3
3
  export declare function getProjectInfo({ port: givenPort, cwd, configPath, srcRootRequired, logLevel, }?: {
4
4
  port?: number;
@@ -30,7 +30,7 @@ export async function createConfig({ root, options: { validationLibrary, bundle,
30
30
  const config = {};
31
31
  const dotConfigPath = path.join(root, '.config');
32
32
  const dir = (await getFileSystemEntryType(dotConfigPath)) === FileSystemEntryType.DIRECTORY ? dotConfigPath : root;
33
- const configAbsolutePath = path.join(dir, 'vovk.config.js');
33
+ const configAbsolutePath = path.join(dir, 'vovk.config.mjs');
34
34
  const typeTemplates = {
35
35
  controller: 'vovk-cli/module-templates/type/controller.ts.ejs',
36
36
  service: 'vovk-cli/module-templates/type/service.ts.ejs',
@@ -97,7 +97,7 @@ export class Init {
97
97
  }
98
98
  if (depsUpdated) {
99
99
  if (skipInstall) {
100
- log.info(`Installation skipped. Please, install them manually with ${chalkHighlightThing(packageManager + ' install')}`);
100
+ log.info(`Installation skipped. Please, install them manually with ${chalkHighlightThing(`${packageManager} install`)}`);
101
101
  }
102
102
  else {
103
103
  try {
@@ -109,7 +109,7 @@ export class Init {
109
109
  log.info('Dependencies installed successfully');
110
110
  }
111
111
  catch (error) {
112
- log.warn(`Failed to install dependencies. ${error.message}. Please, install them manually with ${chalkHighlightThing(packageManager + ' install')}`);
112
+ log.warn(`Failed to install dependencies. ${error.message}. Please, install them manually with ${chalkHighlightThing(`${packageManager} install`)}`);
113
113
  }
114
114
  }
115
115
  }
@@ -120,7 +120,7 @@ export class Init {
120
120
  log,
121
121
  options: { validationLibrary, channel, bundle, lang, dryRun },
122
122
  });
123
- log.info('Config created successfully at ' + chalkHighlightThing(configAbsolutePath));
123
+ log.info(`Config created successfully at ${chalkHighlightThing(configAbsolutePath)}`);
124
124
  log.info(`You can now create a root segment with ${chalkHighlightThing('npx vovk new segment')} command`);
125
125
  }
126
126
  catch (error) {
@@ -1,5 +1,5 @@
1
- import NPMCliPackageJson from '@npmcli/package-json';
2
- import { getLogger } from '../utils/getLogger.mjs';
1
+ import type NPMCliPackageJson from '@npmcli/package-json';
2
+ import type { getLogger } from '../utils/getLogger.mjs';
3
3
  import type { InitOptions } from '../types.mjs';
4
4
  export type PackageManager = 'npm' | 'yarn' | 'pnpm' | 'bun';
5
5
  export declare function getPackageManager(options: Pick<InitOptions, 'useNpm' | 'useYarn' | 'usePnpm' | 'useBun'> & {
@@ -9,7 +9,7 @@ export function getPackageManager(options) {
9
9
  return 'pnpm';
10
10
  if (options.useBun)
11
11
  return 'bun';
12
- const packageManager = options.pkgJson.content?.['packageManager'];
12
+ const packageManager = options.pkgJson.content?.packageManager;
13
13
  return packageManager ? packageManager.split('@')[0] : 'npm'; // Default to npm if no options are true
14
14
  }
15
15
  export async function installDependencies({ log, cwd, packageManager, }) {
@@ -1,5 +1,5 @@
1
1
  import type { getLogger } from '../utils/getLogger.mjs';
2
- import { InitOptions } from '../types.mjs';
2
+ import type { InitOptions } from '../types.mjs';
3
3
  export declare function updateDependenciesWithoutInstalling({ log, dir, dependencyNames, devDependencyNames, channel, }: {
4
4
  log: ReturnType<typeof getLogger>;
5
5
  dir: string;
@@ -1,4 +1,4 @@
1
- import NPMCliPackageJson from '@npmcli/package-json';
1
+ import type NPMCliPackageJson from '@npmcli/package-json';
2
2
  export declare function getDevScript(pkgJson: NPMCliPackageJson, updateScriptsMode: 'implicit' | 'explicit'): string;
3
3
  export declare function updateNPMScripts({ pkgJson, bundle, updateScriptsMode, }: {
4
4
  pkgJson: NPMCliPackageJson;
@@ -41,8 +41,7 @@ export async function newModule({ projectInfo, what, moduleNameWithOptionalSegme
41
41
  if (templatesFlag.length > what.length) {
42
42
  throw new Error('Too many templates provided');
43
43
  }
44
- templates = templatesFlag.reduce((acc, templatePath, index) => ({
45
- ...acc,
44
+ templates = templatesFlag.reduce((acc, templatePath, index) => Object.assign(acc, {
46
45
  [what[index]]: templatePath,
47
46
  }), templates);
48
47
  }
@@ -58,6 +57,8 @@ export async function newModule({ projectInfo, what, moduleNameWithOptionalSegme
58
57
  }
59
58
  for (const type of what) {
60
59
  const templatePath = templates[type];
60
+ if (!templatePath)
61
+ continue; // suppresses TypeScript error, but it shouldn't happen
61
62
  const templateAbsolutePath = resolveAbsoluteModulePath(templatePath, cwd);
62
63
  const templateCode = await fs.readFile(templateAbsolutePath, 'utf-8');
63
64
  const { outDir: renderedOutDir, fileName, sourceName, compiledName, code, } = await render(templateCode, {
@@ -101,7 +102,7 @@ export async function newModule({ projectInfo, what, moduleNameWithOptionalSegme
101
102
  }
102
103
  const { routeFilePath } = segment;
103
104
  const segmentSourceCode = await fs.readFile(routeFilePath, 'utf-8');
104
- let importPath = path.relative(path.dirname(routeFilePath) + '/', absoluteModulePath).replace(/\.(ts|tsx)$/, '');
105
+ let importPath = path.relative(`${path.dirname(routeFilePath)}/`, absoluteModulePath).replace(/\.(ts|tsx)$/, '');
105
106
  importPath += isNodeNextResolution ? '.ts' : '';
106
107
  if (!noSegmentUpdate) {
107
108
  const newSegmentCode = await prettify(addClassToSegmentCode(segmentSourceCode, {
@@ -1,5 +1,5 @@
1
- import { JSONSchema7 } from 'json-schema';
2
- import { OpenAPIObject } from 'openapi3-ts/oas31';
1
+ import type { JSONSchema7 } from 'json-schema';
2
+ import type { OpenAPIObject } from 'openapi3-ts/oas31';
3
3
  interface CompileOptions {
4
4
  name: string;
5
5
  schema: JSONSchema7 & {
@@ -68,7 +68,9 @@ function collectDefinitions(schema, refs) {
68
68
  schemasToProcess.push(...schema.anyOf.filter(isSchema));
69
69
  if (schema.oneOf)
70
70
  schemasToProcess.push(...schema.oneOf.filter(isSchema));
71
- schemasToProcess.forEach((s) => collectDefinitions(s, refs));
71
+ schemasToProcess.forEach((s) => {
72
+ collectDefinitions(s, refs);
73
+ });
72
74
  }
73
75
  function isSchema(value) {
74
76
  return typeof value === 'object' && !Array.isArray(value);
@@ -1 +1,3 @@
1
- export declare function debounceWithArgs<Callback extends (...args: any[]) => any>(callback: Callback, wait: number): (...args: Parameters<Callback>) => Promise<Awaited<ReturnType<Callback>>>;
1
+ type KnownAny = any;
2
+ export declare function debounceWithArgs<Callback extends (...args: KnownAny[]) => KnownAny>(callback: Callback, wait: number): (...args: Parameters<Callback>) => Promise<Awaited<ReturnType<Callback>>>;
3
+ export {};
@@ -1,4 +1,3 @@
1
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
2
1
  export function debounceWithArgs(callback, wait) {
3
2
  // Stores timeouts keyed by the stringified arguments
4
3
  const timeouts = new Map();
@@ -1,4 +1,4 @@
1
- import { HttpMethod } from 'vovk';
1
+ import type { HttpMethod } from 'vovk';
2
2
  export interface VerbMapEntry {
3
3
  noParams?: string;
4
4
  withParams?: string;
@@ -50,15 +50,17 @@ export function generateFnName(method, rawPath, opts = {}) {
50
50
  // 3. Pick base verb from VERB_MAP
51
51
  let baseVerb;
52
52
  if (method === 'GET') {
53
+ // biome-ignore lint/style/noNonNullAssertion: TODO
53
54
  baseVerb = params.length ? VERB_MAP.GET.withParams : VERB_MAP.GET.noParams;
54
55
  }
55
56
  else {
57
+ // biome-ignore lint/style/noNonNullAssertion: TODO
56
58
  baseVerb = VERB_MAP[method].default;
57
59
  }
58
60
  // 4. Build the “resource” part
59
61
  const resourcePart = resources.map(capitalize).join('');
60
62
  // 5. Build the “ByParam” suffix
61
- const byParams = params.length ? 'By' + params.map(capitalize).join('') : '';
63
+ const byParams = params.length ? `By${params.map(capitalize).join('')}` : '';
62
64
  // 6. Combine and ensure camelCase
63
65
  const rawName = `${baseVerb}${resourcePart}${byParams}`;
64
66
  return rawName[0].toLowerCase() + rawName.slice(1);
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Interface representing the structure of NPM package metadata.
3
3
  */
4
- interface NpmPackageMetadata {
4
+ export interface NpmPackageMetadata {
5
5
  'dist-tags': {
6
6
  [tag: string]: string;
7
7
  };
@@ -14,4 +14,3 @@ interface NpmPackageMetadata {
14
14
  };
15
15
  }
16
16
  export declare function getNPMPackageMetadata(packageName: string): Promise<NpmPackageMetadata>;
17
- export {};
@@ -1,3 +1,3 @@
1
- import { PackageJson } from 'type-fest';
1
+ import type { PackageJson } from 'type-fest';
2
2
  import type { ProjectInfo } from '../getProjectInfo/index.mjs';
3
3
  export declare function getPackageJson(cwd: string, log: ProjectInfo['log']): Promise<PackageJson>;
@@ -1,6 +1,6 @@
1
- import { HttpMethod, type VovkConfig } from 'vovk';
2
- import { VovkOperationObject, VovkStrictConfig } from 'vovk/internal';
3
- import { OpenAPIObject } from 'openapi3-ts/oas31';
1
+ import type { HttpMethod, VovkConfig } from 'vovk';
2
+ import type { VovkOperationObject, VovkStrictConfig } from 'vovk/internal';
3
+ import type { OpenAPIObject } from 'openapi3-ts/oas31';
4
4
  import type { ProjectInfo } from '../getProjectInfo/index.mjs';
5
5
  export type GetOpenAPINameFn = (config: {
6
6
  operationObject: VovkOperationObject;
@@ -1,3 +1,3 @@
1
- import { type VovkSchema } from 'vovk';
1
+ import type { VovkSchema } from 'vovk';
2
2
  export declare function pickSegmentFullSchema(schema: VovkSchema, segmentNames: string[]): VovkSchema;
3
3
  export declare function omitSegmentFullSchema(schema: VovkSchema, segmentNames: string[]): VovkSchema;
@@ -1,5 +1,5 @@
1
- import fs from 'fs/promises';
2
- import path from 'path';
1
+ import fs from 'node:fs/promises';
2
+ import path from 'node:path';
3
3
  import { getFileSystemEntryType, FileSystemEntryType } from './getFileSystemEntryType.mjs';
4
4
  /**
5
5
  * Removes all directories in a folder that aren't in the provided allowlist
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vovk-cli",
3
- "version": "0.0.1",
3
+ "version": "0.0.4",
4
4
  "description": "CLI tool for managing Vovk.ts projects",
5
5
  "files": [
6
6
  "dist",