vovk-cli 0.0.1-draft.36 → 0.0.1-draft.361

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 (142) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +29 -1
  3. package/client-templates/cjs/index.cjs.ejs +19 -0
  4. package/client-templates/cjs/index.d.cts.ejs +22 -0
  5. package/client-templates/mixins/mixins.d.ts.ejs +64 -0
  6. package/client-templates/mixins/mixins.json.ejs +1 -0
  7. package/client-templates/mjs/index.d.mts.ejs +22 -0
  8. package/client-templates/mjs/index.mjs.ejs +18 -0
  9. package/client-templates/openapiCjs/openapi.cjs.ejs +4 -0
  10. package/client-templates/openapiCjs/openapi.d.cts.ejs +4 -0
  11. package/client-templates/openapiJson/openapi.json.ejs +1 -0
  12. package/client-templates/openapiTs/openapi.ts.ejs +4 -0
  13. package/client-templates/packageJson/package.json.ejs +1 -0
  14. package/client-templates/readme/README.md.ejs +39 -0
  15. package/client-templates/schemaCjs/schema.cjs.ejs +24 -0
  16. package/client-templates/schemaCjs/schema.d.cts.ejs +10 -0
  17. package/client-templates/schemaJson/schema.json.ejs +1 -0
  18. package/client-templates/schemaTs/schema.ts.ejs +28 -0
  19. package/client-templates/ts/index.ts.ejs +27 -0
  20. package/dist/bundle/index.d.mts +8 -0
  21. package/dist/bundle/index.mjs +103 -0
  22. package/dist/dev/diffSegmentSchema.d.mts +36 -0
  23. package/dist/dev/{diffSchema.mjs → diffSegmentSchema.mjs} +3 -11
  24. package/dist/dev/ensureSchemaFiles.d.mts +4 -1
  25. package/dist/dev/ensureSchemaFiles.mjs +15 -31
  26. package/dist/dev/index.d.mts +5 -1
  27. package/dist/dev/index.mjs +191 -80
  28. package/dist/dev/logDiffResult.d.mts +1 -1
  29. package/dist/dev/logDiffResult.mjs +6 -43
  30. package/dist/dev/writeMetaJson.d.mts +2 -0
  31. package/dist/dev/writeMetaJson.mjs +20 -0
  32. package/dist/dev/writeOneSegmentSchemaFile.d.mts +12 -0
  33. package/dist/dev/{writeOneSchemaFile.mjs → writeOneSegmentSchemaFile.mjs} +10 -6
  34. package/dist/generate/ensureClient.d.mts +3 -0
  35. package/dist/generate/ensureClient.mjs +28 -0
  36. package/dist/generate/generate.d.mts +13 -0
  37. package/dist/generate/generate.mjs +306 -0
  38. package/dist/generate/getClientTemplateFiles.d.mts +20 -0
  39. package/dist/generate/getClientTemplateFiles.mjs +85 -0
  40. package/dist/generate/getProjectFullSchema.d.mts +8 -0
  41. package/dist/generate/getProjectFullSchema.mjs +66 -0
  42. package/dist/generate/getTemplateClientImports.d.mts +19 -0
  43. package/dist/generate/getTemplateClientImports.mjs +49 -0
  44. package/dist/generate/index.d.mts +33 -0
  45. package/dist/generate/index.mjs +186 -0
  46. package/dist/generate/writeOneClientFile.d.mts +42 -0
  47. package/dist/generate/writeOneClientFile.mjs +139 -0
  48. package/dist/getProjectInfo/getConfig/getConfigAbsolutePaths.d.mts +5 -0
  49. package/dist/getProjectInfo/{getConfigAbsolutePaths.mjs → getConfig/getConfigAbsolutePaths.mjs} +4 -1
  50. package/dist/getProjectInfo/{getRelativeSrcRoot.d.mts → getConfig/getRelativeSrcRoot.d.mts} +1 -1
  51. package/dist/getProjectInfo/{getRelativeSrcRoot.mjs → getConfig/getRelativeSrcRoot.mjs} +2 -2
  52. package/dist/getProjectInfo/getConfig/getTemplateDefs.d.mts +24 -0
  53. package/dist/getProjectInfo/getConfig/getTemplateDefs.mjs +165 -0
  54. package/dist/getProjectInfo/{getUserConfig.d.mts → getConfig/getUserConfig.d.mts} +3 -2
  55. package/dist/getProjectInfo/{getUserConfig.mjs → getConfig/getUserConfig.mjs} +3 -3
  56. package/dist/getProjectInfo/{importUncachedModule.mjs → getConfig/importUncachedModule.mjs} +1 -4
  57. package/dist/getProjectInfo/getConfig/index.d.mts +78 -0
  58. package/dist/getProjectInfo/getConfig/index.mjs +91 -0
  59. package/dist/getProjectInfo/getMetaSchema.d.mts +8 -0
  60. package/dist/getProjectInfo/getMetaSchema.mjs +14 -0
  61. package/dist/getProjectInfo/index.d.mts +14 -9
  62. package/dist/getProjectInfo/index.mjs +24 -22
  63. package/dist/index.d.mts +2 -2
  64. package/dist/index.mjs +118 -36
  65. package/dist/init/createConfig.d.mts +2 -2
  66. package/dist/init/createConfig.mjs +40 -13
  67. package/dist/init/createStandardSchemaValidatorFile.d.mts +4 -0
  68. package/dist/init/createStandardSchemaValidatorFile.mjs +39 -0
  69. package/dist/init/getTemplateFilesFromPackage.mjs +10 -5
  70. package/dist/init/index.d.mts +2 -2
  71. package/dist/init/index.mjs +122 -72
  72. package/dist/init/installDependencies.mjs +4 -2
  73. package/dist/init/logUpdateDependenciesError.d.mts +3 -1
  74. package/dist/init/logUpdateDependenciesError.mjs +7 -1
  75. package/dist/init/updateDependenciesWithoutInstalling.mjs +39 -9
  76. package/dist/init/updateNPMScripts.d.mts +3 -1
  77. package/dist/init/updateNPMScripts.mjs +10 -7
  78. package/dist/init/updateTypeScriptConfig.d.mts +4 -1
  79. package/dist/init/updateTypeScriptConfig.mjs +11 -7
  80. package/dist/initProgram.d.mts +1 -1
  81. package/dist/initProgram.mjs +17 -17
  82. package/dist/locateSegments.d.mts +8 -1
  83. package/dist/locateSegments.mjs +13 -3
  84. package/dist/new/addClassToSegmentCode.d.mts +1 -2
  85. package/dist/new/addClassToSegmentCode.mjs +3 -3
  86. package/dist/new/index.d.mts +2 -1
  87. package/dist/new/index.mjs +4 -2
  88. package/dist/new/newModule.d.mts +4 -1
  89. package/dist/new/newModule.mjs +18 -17
  90. package/dist/new/newSegment.d.mts +4 -1
  91. package/dist/new/newSegment.mjs +19 -11
  92. package/dist/new/render.d.mts +7 -3
  93. package/dist/new/render.mjs +29 -8
  94. package/dist/types.d.mts +64 -42
  95. package/dist/utils/compileJSONSchemaToTypeScriptType.d.mts +5 -0
  96. package/dist/utils/compileJSONSchemaToTypeScriptType.mjs +9 -0
  97. package/dist/utils/compileTs.d.mts +12 -0
  98. package/dist/utils/compileTs.mjs +261 -0
  99. package/dist/utils/debounceWithArgs.d.mts +2 -2
  100. package/dist/utils/debounceWithArgs.mjs +24 -6
  101. package/dist/utils/deepExtend.d.mts +54 -0
  102. package/dist/utils/deepExtend.mjs +129 -0
  103. package/dist/utils/formatLoggedSegmentName.d.mts +3 -1
  104. package/dist/utils/formatLoggedSegmentName.mjs +3 -2
  105. package/dist/utils/generateFnName.d.mts +23 -0
  106. package/dist/utils/generateFnName.mjs +76 -0
  107. package/dist/utils/getPackageJson.d.mts +3 -0
  108. package/dist/utils/getPackageJson.mjs +22 -0
  109. package/dist/utils/getPublicModuleNameFromPath.d.mts +4 -0
  110. package/dist/utils/getPublicModuleNameFromPath.mjs +9 -0
  111. package/dist/utils/normalizeOpenAPIMixin.d.mts +14 -0
  112. package/dist/utils/normalizeOpenAPIMixin.mjs +114 -0
  113. package/dist/utils/pickSegmentFullSchema.d.mts +3 -0
  114. package/dist/utils/pickSegmentFullSchema.mjs +15 -0
  115. package/dist/utils/removeUnlistedDirectories.d.mts +10 -0
  116. package/dist/utils/removeUnlistedDirectories.mjs +61 -0
  117. package/dist/utils/resolveAbsoluteModulePath.d.mts +2 -0
  118. package/dist/utils/resolveAbsoluteModulePath.mjs +32 -0
  119. package/module-templates/arktype/controller.ts.ejs +68 -0
  120. package/module-templates/type/controller.ts.ejs +56 -0
  121. package/module-templates/type/service.ts.ejs +28 -0
  122. package/module-templates/valibot/controller.ts.ejs +68 -0
  123. package/package.json +40 -22
  124. package/dist/dev/diffSchema.d.mts +0 -43
  125. package/dist/dev/ensureClient.d.mts +0 -5
  126. package/dist/dev/ensureClient.mjs +0 -31
  127. package/dist/dev/isMetadataEmpty.d.mts +0 -2
  128. package/dist/dev/isMetadataEmpty.mjs +0 -4
  129. package/dist/dev/writeOneSchemaFile.d.mts +0 -11
  130. package/dist/generateClient.d.mts +0 -7
  131. package/dist/generateClient.mjs +0 -97
  132. package/dist/getProjectInfo/getConfig.d.mts +0 -11
  133. package/dist/getProjectInfo/getConfig.mjs +0 -29
  134. package/dist/getProjectInfo/getConfigAbsolutePaths.d.mts +0 -4
  135. package/dist/postinstall.d.mts +0 -1
  136. package/dist/postinstall.mjs +0 -24
  137. package/templates/controller.ejs +0 -52
  138. package/templates/service.ejs +0 -27
  139. package/templates/worker.ejs +0 -24
  140. /package/dist/getProjectInfo/{importUncachedModule.d.mts → getConfig/importUncachedModule.d.mts} +0 -0
  141. /package/dist/getProjectInfo/{importUncachedModuleWorker.d.mts → getConfig/importUncachedModuleWorker.d.mts} +0 -0
  142. /package/dist/getProjectInfo/{importUncachedModuleWorker.mjs → getConfig/importUncachedModuleWorker.mjs} +0 -0
@@ -1,10 +1,20 @@
1
1
  import fs from 'node:fs/promises';
2
2
  import path from 'node:path';
3
3
  import getFileSystemEntryType from './utils/getFileSystemEntryType.mjs';
4
- export default async function locateSegments(dir, rootDir = dir) {
4
+ export async function locateSegments({ dir, rootDir, config, log, }) {
5
5
  let results = [];
6
+ if (!dir)
7
+ return results; // If dir is null, return empty results because this isn't a Next.js app
8
+ rootDir = rootDir ?? dir;
9
+ let list = [];
6
10
  // Read the contents of the directory
7
- const list = await fs.readdir(dir);
11
+ try {
12
+ list = (await fs.readdir(dir)).toSorted();
13
+ }
14
+ catch {
15
+ // do nothing
16
+ return results;
17
+ }
8
18
  // Iterate through each item in the directory
9
19
  for (const file of list) {
10
20
  const filePath = path.join(dir, file);
@@ -21,7 +31,7 @@ export default async function locateSegments(dir, rootDir = dir) {
21
31
  }
22
32
  }
23
33
  // Recursively search inside subdirectories
24
- const subDirResults = await locateSegments(filePath, rootDir);
34
+ const subDirResults = await locateSegments({ dir: filePath, rootDir, config, log });
25
35
  results = results.concat(subDirResults);
26
36
  }
27
37
  }
@@ -1,6 +1,5 @@
1
- export default function addClassToSegmentCode(segmentSourceCode: string, { sourceName, compiledName, type, importPath, }: {
1
+ export default function addClassToSegmentCode(segmentSourceCode: string, { sourceName, compiledName, importPath, }: {
2
2
  sourceName: string;
3
3
  compiledName: string;
4
- type: 'worker' | 'controller';
5
4
  importPath: string;
6
5
  }): string;
@@ -1,5 +1,5 @@
1
1
  import { Project, QuoteKind, SyntaxKind } from 'ts-morph';
2
- export default function addClassToSegmentCode(segmentSourceCode, { sourceName, compiledName, type, importPath, }) {
2
+ export default function addClassToSegmentCode(segmentSourceCode, { sourceName, compiledName, importPath, }) {
3
3
  const project = new Project({
4
4
  manipulationSettings: {
5
5
  quoteKind: QuoteKind.Single,
@@ -16,8 +16,8 @@ export default function addClassToSegmentCode(segmentSourceCode, { sourceName, c
16
16
  moduleSpecifier: importPath,
17
17
  });
18
18
  }
19
- // Get the variable declaration for controllers or workers
20
- const variableDeclaration = sourceFile.getVariableDeclaration(`${type}s`);
19
+ // Get the variable declaration for controllers
20
+ const variableDeclaration = sourceFile.getVariableDeclaration('controllers');
21
21
  if (variableDeclaration) {
22
22
  const initializer = variableDeclaration.getInitializer();
23
23
  if (initializer && initializer.getKind() === SyntaxKind.ObjectLiteralExpression) {
@@ -1,2 +1,3 @@
1
1
  import type { NewOptions } from '../types.mjs';
2
- export default function newComponents(components: string[], { dryRun, dir, templates, overwrite, noSegmentUpdate }: NewOptions): Promise<void>;
2
+ import type { ProjectInfo } from '../getProjectInfo/index.mts';
3
+ export declare function newComponents(components: string[], projectInfo: ProjectInfo, { dryRun, dir, templates, overwrite, noSegmentUpdate, empty, static: isStaticSegment }: NewOptions): Promise<void>;
@@ -1,6 +1,6 @@
1
1
  import newModule from './newModule.mjs';
2
2
  import newSegment from './newSegment.mjs';
3
- export default async function newComponents(components, { dryRun, dir, templates, overwrite, noSegmentUpdate }) {
3
+ export async function newComponents(components, projectInfo, { dryRun, dir, templates, overwrite, noSegmentUpdate, empty, static: isStaticSegment }) {
4
4
  if (components[0] === 'segment' || components[0] === 'segments') {
5
5
  // vovk new segment [segmentName]
6
6
  let segmentNames = components
@@ -10,7 +10,7 @@ export default async function newComponents(components, { dryRun, dir, templates
10
10
  segmentNames = [''];
11
11
  }
12
12
  for (const segmentName of segmentNames) {
13
- await newSegment({ segmentName, overwrite, dryRun });
13
+ await newSegment({ projectInfo, segmentName, isStaticSegment, overwrite, dryRun });
14
14
  }
15
15
  }
16
16
  else {
@@ -24,6 +24,7 @@ export default async function newComponents(components, { dryRun, dir, templates
24
24
  throw new Error('A module name with an optional segment cannot be empty');
25
25
  }
26
26
  await newModule({
27
+ projectInfo,
27
28
  what,
28
29
  moduleNameWithOptionalSegment,
29
30
  dir,
@@ -31,6 +32,7 @@ export default async function newComponents(components, { dryRun, dir, templates
31
32
  overwrite,
32
33
  noSegmentUpdate,
33
34
  dryRun,
35
+ empty,
34
36
  });
35
37
  }
36
38
  }
@@ -1,4 +1,6 @@
1
- export default function newModule({ what, moduleNameWithOptionalSegment, dryRun, dir: dirFlag, templates: templatesFlag, noSegmentUpdate, overwrite, }: {
1
+ import type { ProjectInfo } from '../getProjectInfo/index.mjs';
2
+ export default function newModule({ projectInfo, what, moduleNameWithOptionalSegment, dryRun, dir: dirFlag, templates: templatesFlag, noSegmentUpdate, overwrite, empty, }: {
3
+ projectInfo: ProjectInfo;
2
4
  what: string[];
3
5
  moduleNameWithOptionalSegment: string;
4
6
  dryRun?: boolean;
@@ -6,4 +8,5 @@ export default function newModule({ what, moduleNameWithOptionalSegment, dryRun,
6
8
  templates?: string[];
7
9
  noSegmentUpdate?: boolean;
8
10
  overwrite?: boolean;
11
+ empty?: boolean;
9
12
  }): Promise<void>;
@@ -1,13 +1,14 @@
1
1
  import path from 'node:path';
2
2
  import fs from 'node:fs/promises';
3
+ import { getTsconfig } from 'get-tsconfig';
3
4
  import render from './render.mjs';
4
5
  import addClassToSegmentCode from './addClassToSegmentCode.mjs';
5
- import getProjectInfo from '../getProjectInfo/index.mjs';
6
- import locateSegments from '../locateSegments.mjs';
7
6
  import chalkHighlightThing from '../utils/chalkHighlightThing.mjs';
8
7
  import formatLoggedSegmentName from '../utils/formatLoggedSegmentName.mjs';
9
8
  import getFileSystemEntryType from '../utils/getFileSystemEntryType.mjs';
10
9
  import prettify from '../utils/prettify.mjs';
10
+ import resolveAbsoluteModulePath from '../utils/resolveAbsoluteModulePath.mjs';
11
+ import { locateSegments } from '../locateSegments.mjs';
11
12
  function splitByLast(str, delimiter = '/') {
12
13
  const index = str.lastIndexOf(delimiter);
13
14
  if (index === -1) {
@@ -18,19 +19,19 @@ function splitByLast(str, delimiter = '/') {
18
19
  const after = str.substring(index + delimiter.length);
19
20
  return [before, after];
20
21
  }
21
- export default async function newModule({ what, moduleNameWithOptionalSegment, dryRun, dir: dirFlag, templates: templatesFlag, noSegmentUpdate, overwrite, }) {
22
- const { config, log, apiDir, cwd } = await getProjectInfo();
23
- let templates = config.templates;
22
+ export default async function newModule({ projectInfo, what, moduleNameWithOptionalSegment, dryRun, dir: dirFlag, templates: templatesFlag, noSegmentUpdate, overwrite, empty, }) {
23
+ const { config, log, cwd, apiDirAbsolutePath } = projectInfo;
24
+ const segments = await locateSegments({ dir: apiDirAbsolutePath, config, log });
25
+ const isNodeNextResolution = ['node16', 'nodenext'].includes((await getTsconfig(cwd)?.config?.compilerOptions?.moduleResolution?.toLowerCase()) ?? '');
26
+ let templates = config.moduleTemplates;
24
27
  const [segmentName, moduleName] = splitByLast(moduleNameWithOptionalSegment);
25
- // replace c by controller, s by service, w by worker, everything else keeps the same
28
+ // replace c by controller, s by service, everything else keeps the same
26
29
  what = what.map((s) => {
27
30
  switch (s) {
28
31
  case 'c':
29
32
  return 'controller';
30
33
  case 's':
31
34
  return 'service';
32
- case 'w':
33
- return 'worker';
34
35
  default:
35
36
  return s;
36
37
  }
@@ -49,16 +50,13 @@ export default async function newModule({ what, moduleNameWithOptionalSegment, d
49
50
  throw new Error(`Template for "${type}" not found`);
50
51
  }
51
52
  }
52
- const segments = await locateSegments(apiDir);
53
53
  const segment = segments.find((s) => s.segmentName === segmentName);
54
54
  if (!segment) {
55
55
  throw new Error(`Unable to create module. Segment "${segmentName}" not found. Run "vovk new segment ${segmentName}" to create it`);
56
56
  }
57
57
  for (const type of what) {
58
58
  const templatePath = templates[type];
59
- const templateAbsolutePath = templatePath.startsWith('/') || templatePath.startsWith('.')
60
- ? path.resolve(cwd, templatePath)
61
- : path.resolve(cwd, './node_modules', templatePath);
59
+ const templateAbsolutePath = resolveAbsoluteModulePath(templatePath, cwd);
62
60
  const templateCode = await fs.readFile(templateAbsolutePath, 'utf-8');
63
61
  const { dir: renderedDir, fileName, sourceName, compiledName, code, } = await render(templateCode, {
64
62
  cwd,
@@ -66,6 +64,9 @@ export default async function newModule({ what, moduleNameWithOptionalSegment, d
66
64
  withService: what.includes('service'),
67
65
  segmentName,
68
66
  moduleName,
67
+ empty,
68
+ templateFileName: templateAbsolutePath,
69
+ isNodeNextResolution,
69
70
  });
70
71
  const dir = dirFlag || renderedDir;
71
72
  if (!dir) {
@@ -84,24 +85,24 @@ export default async function newModule({ what, moduleNameWithOptionalSegment, d
84
85
  else {
85
86
  await fs.mkdir(absoluteModuleDir, { recursive: true });
86
87
  await fs.writeFile(absoluteModulePath, prettiedCode);
87
- log.info(`Created ${chalkHighlightThing(fileName)} using ${chalkHighlightThing(`"${type}"`)} template for ${formatLoggedSegmentName(segmentName)}`);
88
+ log.info(`Created${empty ? ' empty' : ''} ${chalkHighlightThing(absoluteModulePath)} using ${chalkHighlightThing(`"${type}"`)} template for ${formatLoggedSegmentName(segmentName)}`);
88
89
  }
89
90
  }
90
- if (type === 'controller' || type === 'worker') {
91
+ if (type === 'controller') {
91
92
  if (!sourceName) {
92
93
  throw new Error(`The template for "${type}" does not provide a sourceName`);
93
94
  }
94
95
  if (!compiledName) {
95
- throw new Error('The template for "${type}" does not provide a compiledName');
96
+ throw new Error(`The template for "${type}" does not provide a compiledName`);
96
97
  }
97
98
  const { routeFilePath } = segment;
98
99
  const segmentSourceCode = await fs.readFile(routeFilePath, 'utf-8');
99
- const importPath = path.relative(path.dirname(routeFilePath), absoluteModulePath).replace(/\.(ts|tsx)$/, '');
100
+ let importPath = path.relative(path.dirname(routeFilePath) + '/', absoluteModulePath).replace(/\.(ts|tsx)$/, '');
101
+ importPath += isNodeNextResolution ? '.ts' : '';
100
102
  if (!noSegmentUpdate) {
101
103
  const newSegmentCode = await prettify(addClassToSegmentCode(segmentSourceCode, {
102
104
  sourceName,
103
105
  compiledName,
104
- type,
105
106
  importPath,
106
107
  }), routeFilePath);
107
108
  if (!dryRun) {
@@ -1,5 +1,8 @@
1
- export default function newSegment({ segmentName, overwrite, dryRun, }: {
1
+ import type { ProjectInfo } from '../getProjectInfo/index.mjs';
2
+ export default function newSegment({ projectInfo, segmentName, isStaticSegment, overwrite, dryRun, }: {
3
+ projectInfo: ProjectInfo;
2
4
  segmentName: string;
5
+ isStaticSegment?: boolean;
3
6
  overwrite?: boolean;
4
7
  dryRun?: boolean;
5
8
  }): Promise<void>;
@@ -1,27 +1,33 @@
1
1
  import path from 'node:path';
2
2
  import fs from 'node:fs/promises';
3
- import getProjectInfo from '../getProjectInfo/index.mjs';
4
3
  import getFileSystemEntryType from '../utils/getFileSystemEntryType.mjs';
5
4
  import chalkHighlightThing from '../utils/chalkHighlightThing.mjs';
6
5
  import formatLoggedSegmentName from '../utils/formatLoggedSegmentName.mjs';
7
6
  import prettify from '../utils/prettify.mjs';
8
- export default async function newSegment({ segmentName, overwrite, dryRun, }) {
9
- const { apiDir, cwd, log } = await getProjectInfo();
10
- const absoluteSegmentRoutePath = path.join(cwd, apiDir, segmentName, '[[...vovk]]/route.ts');
7
+ import chalk from 'chalk';
8
+ export default async function newSegment({ projectInfo, segmentName, isStaticSegment, overwrite, dryRun, }) {
9
+ const { apiDirAbsolutePath, log, config } = projectInfo;
10
+ if (!apiDirAbsolutePath) {
11
+ throw new Error('No API directory found. Please ensure you are in a Nest.js project.');
12
+ }
13
+ const absoluteSegmentRoutePath = path.join(apiDirAbsolutePath, segmentName, '[[...vovk]]/route.ts');
11
14
  if (!overwrite && (await getFileSystemEntryType(absoluteSegmentRoutePath))) {
12
15
  throw new Error(`Unable to create new segment. ${formatLoggedSegmentName(segmentName, { upperFirst: true })} already exists.`);
13
16
  }
14
- const code = await prettify(`import { initVovk } from 'vovk';
17
+ const code = await prettify(`import { initSegment${isStaticSegment ? ', generateStaticAPI' : ''} } from 'vovk';
15
18
 
16
19
  const controllers = {};
17
- const workers = {};
18
20
 
19
21
  export type Controllers = typeof controllers;
20
- export type Workers = typeof workers;
21
-
22
- export const { GET, POST, PATCH, PUT, HEAD, OPTIONS, DELETE } = initVovk({
22
+ ${isStaticSegment
23
+ ? `
24
+ export function generateStaticParams() {
25
+ return generateStaticAPI(controllers);
26
+ }
27
+ `
28
+ : ''}
29
+ export const { GET${isStaticSegment ? '' : ', POST, PATCH, PUT, HEAD, OPTIONS, DELETE'} } = initSegment({
23
30
  ${segmentName ? ` segmentName: '${segmentName}',\n` : ''} emitSchema: true,
24
- workers,
25
31
  controllers,
26
32
  });
27
33
  `, absoluteSegmentRoutePath);
@@ -29,5 +35,7 @@ ${segmentName ? ` segmentName: '${segmentName}',\n` : ''} emitSchema: true,
29
35
  await fs.mkdir(path.dirname(absoluteSegmentRoutePath), { recursive: true });
30
36
  await fs.writeFile(absoluteSegmentRoutePath, code);
31
37
  }
32
- log.info(`${formatLoggedSegmentName(segmentName, { upperFirst: true })} created at ${absoluteSegmentRoutePath}. Run ${chalkHighlightThing(`vovk new controller ${[segmentName, 'someName'].filter(Boolean).join('/')}`)} to create a new controller`);
38
+ log.info(`${formatLoggedSegmentName(segmentName, { upperFirst: true, isStatic: isStaticSegment })} created at ${absoluteSegmentRoutePath}.`);
39
+ const dir = chalk.cyanBright([segmentName, 'thing'].filter(Boolean).join('/'));
40
+ log.info(`Run ${chalkHighlightThing(`npx vovk new service controller ${dir}`)} to create a new controller with a service at ${path.join(config.modulesDir, dir)} folder for this segment`);
33
41
  }
@@ -1,8 +1,12 @@
1
- import type { VovkConfig, VovkModuleRenderResult } from '../types.mjs';
2
- export default function render(codeTemplate: string, { config, withService, segmentName, moduleName, }: {
1
+ import type { VovkStrictConfig } from 'vovk';
2
+ import type { VovkModuleRenderResult } from '../types.mjs';
3
+ export default function render(codeTemplate: string, { config, withService, segmentName, moduleName, empty, templateFileName, isNodeNextResolution, }: {
3
4
  cwd: string;
4
- config: VovkConfig;
5
+ config: VovkStrictConfig;
5
6
  withService: boolean;
6
7
  segmentName: string;
7
8
  moduleName: string;
9
+ empty?: boolean;
10
+ templateFileName: string;
11
+ isNodeNextResolution: boolean;
8
12
  }): Promise<VovkModuleRenderResult>;
@@ -4,25 +4,46 @@ import _ from 'lodash';
4
4
  import pluralize from 'pluralize';
5
5
  import addCommonTerms from './addCommonTerms.mjs';
6
6
  addCommonTerms();
7
- export default async function render(codeTemplate, { config, withService, segmentName, moduleName, }) {
7
+ export default async function render(codeTemplate, { config, withService, segmentName, moduleName, empty, templateFileName, isNodeNextResolution, }) {
8
8
  const getModuleDirName = (givenSegmentName, givenModuleName) => [config.modulesDir, givenSegmentName || config.rootSegmentModulesDirName, _.camelCase(givenModuleName)]
9
9
  .filter(Boolean)
10
10
  .join('/');
11
- const templateVars = {
12
- // input
11
+ const theThing = _.camelCase(moduleName);
12
+ const TheThing = _.upperFirst(theThing);
13
+ const the_thing = _.snakeCase(moduleName);
14
+ const THE_THING = _.toUpper(the_thing);
15
+ const the__thing = _.kebabCase(moduleName);
16
+ const t = {
17
+ // module name variations
18
+ moduleName,
19
+ theThing,
20
+ theThings: pluralize(theThing),
21
+ TheThing,
22
+ TheThings: pluralize(TheThing),
23
+ the_thing,
24
+ the_things: pluralize(the_thing),
25
+ THE_THING,
26
+ THE_THINGS: pluralize(THE_THING),
27
+ 'the-thing': the__thing,
28
+ 'the-things': pluralize(the__thing),
29
+ // data
13
30
  config,
14
31
  withService,
15
32
  segmentName,
16
- moduleName,
17
- // utils
18
- getModuleDirName,
33
+ nodeNextResolutionExt: {
34
+ ts: isNodeNextResolution ? '.ts' : '',
35
+ js: isNodeNextResolution ? '.js' : '',
36
+ cjs: isNodeNextResolution ? '.cjs' : '',
37
+ mjs: isNodeNextResolution ? '.mjs' : '',
38
+ },
39
+ defaultDir: getModuleDirName(segmentName, theThing),
19
40
  // libraries
20
41
  _, // lodash
21
42
  pluralize,
22
43
  };
23
- const parsed = matter((await ejs.render(codeTemplate, templateVars, { async: true })).trim());
44
+ const parsed = matter((await ejs.render(codeTemplate, { t }, { async: true, filename: templateFileName })).trim());
24
45
  const { dir, fileName, sourceName, compiledName } = parsed.data;
25
- const code = parsed.content;
46
+ const code = empty ? (sourceName ? `export default class ${sourceName} {}` : '') : parsed.content;
26
47
  return {
27
48
  dir,
28
49
  fileName,
package/dist/types.d.mts CHANGED
@@ -1,42 +1,6 @@
1
1
  import type { LogLevelNames } from 'loglevel';
2
- export type KnownAny = any;
3
- export type VovkDevEnv = {
4
- PORT?: string;
5
- VOVK_CLIENT_OUT_DIR?: string;
6
- VOVK_SCHEMA_OUT_DIR?: string;
7
- VOVK_FETCHER?: string;
8
- VOVK_VALIDATE_ON_CLIENT?: string;
9
- VOVK_MODULES_DIR?: string;
10
- VOVK_VALIDATION_LIBRARY?: string;
11
- VOVK_ORIGIN?: string;
12
- VOVK_ROOT_ENTRY?: string;
13
- VOVK_API_ENTRY_POINT?: string;
14
- VOVK_ROOT_SEGMENT_MODULES_DIR_NAME?: string;
15
- VOVK_LOG_LEVEL?: LogLevelNames;
16
- VOVK_PRETTIFY_CLIENT?: string;
17
- VOVK_DEV_HTTPS?: string;
18
- __VOVK_START_WATCHER_IN_STANDALONE_MODE__?: 'true';
19
- };
20
- export type VovkConfig = {
21
- clientOutDir?: string;
22
- schemaOutDir?: string;
23
- fetcher?: string;
24
- validateOnClient?: string | null;
25
- modulesDir?: string;
26
- validationLibrary?: string | null;
27
- rootEntry?: string;
28
- origin?: string;
29
- rootSegmentModulesDirName?: string;
30
- logLevel?: LogLevelNames;
31
- prettifyClient?: boolean;
32
- devHttps?: boolean;
33
- templates?: {
34
- service?: string;
35
- controller?: string;
36
- worker?: string;
37
- [key: string]: string | undefined;
38
- };
39
- };
2
+ import type { build } from 'tsdown';
3
+ import type { VovkStrictConfig } from 'vovk';
40
4
  export type VovkModuleRenderResult = {
41
5
  fileName: string;
42
6
  dir: string;
@@ -45,14 +9,53 @@ export type VovkModuleRenderResult = {
45
9
  code: string;
46
10
  };
47
11
  export interface DevOptions {
12
+ schemaOut?: string;
48
13
  nextDev?: boolean;
14
+ exit?: boolean;
15
+ devHttps?: boolean;
16
+ logLevel?: LogLevelNames;
49
17
  }
50
18
  export interface GenerateOptions {
51
- clientOut?: string;
19
+ prettify?: boolean;
20
+ configPath?: string;
21
+ schemaPath?: string;
22
+ origin?: string;
23
+ openapiSpec?: string[];
24
+ openapiGetModuleName?: string[];
25
+ openapiGetMethodName?: string[];
26
+ openapiRootUrl?: string[];
27
+ openapiMixinName?: string[];
28
+ openapiFallback?: string[];
29
+ watch?: boolean | string;
30
+ composedFrom?: string[];
31
+ composedOut?: string;
32
+ composedOnly?: boolean;
33
+ composedIncludeSegments?: string[];
34
+ composedExcludeSegments?: string[];
35
+ segmentedFrom?: string[];
36
+ segmentedOut?: string;
37
+ segmentedOnly?: boolean;
38
+ segmentedIncludeSegments?: string[];
39
+ segmentedExcludeSegments?: string[];
40
+ logLevel?: LogLevelNames;
41
+ }
42
+ export interface BundleOptions extends Partial<Pick<VovkStrictConfig['bundle'], 'prebundleOutDir' | 'keepPrebundleDir' | 'includeSegments' | 'excludeSegments'>> {
43
+ configPath?: string;
44
+ schemaPath?: string;
45
+ schema?: string;
46
+ outDir?: string;
47
+ origin?: string;
48
+ tsconfig?: string;
49
+ openapiSpec?: string[];
50
+ openapiGetModuleName?: string[];
51
+ openapiGetMethodName?: string[];
52
+ openapiRootUrl?: string[];
53
+ openapiMixinName?: string[];
54
+ logLevel?: LogLevelNames;
52
55
  }
53
56
  export interface InitOptions {
57
+ prefix?: string;
54
58
  yes?: boolean;
55
- logLevel: LogLevelNames;
56
59
  useNpm?: boolean;
57
60
  useYarn?: boolean;
58
61
  usePnpm?: boolean;
@@ -60,10 +63,11 @@ export interface InitOptions {
60
63
  skipInstall?: boolean;
61
64
  updateTsConfig?: boolean;
62
65
  updateScripts?: 'implicit' | 'explicit';
63
- validationLibrary?: string | null;
64
- validateOnClient?: boolean;
66
+ validationLibrary?: 'zod' | 'yup' | 'class-validator' | 'valibot' | 'arktype' | null;
65
67
  dryRun?: boolean;
68
+ lang?: string[];
66
69
  channel?: 'latest' | 'beta' | 'draft';
70
+ logLevel?: LogLevelNames;
67
71
  }
68
72
  export interface NewOptions {
69
73
  dryRun?: boolean;
@@ -71,4 +75,22 @@ export interface NewOptions {
71
75
  dir?: string;
72
76
  overwrite?: boolean;
73
77
  noSegmentUpdate?: boolean;
78
+ empty?: boolean;
79
+ static?: boolean;
80
+ logLevel?: LogLevelNames;
81
+ }
82
+ export type VovkEnv = {
83
+ PORT?: string;
84
+ VOVK_SCHEMA_OUT_DIR?: string;
85
+ VOVK_ORIGIN?: string;
86
+ VOVK_ROOT_ENTRY?: string;
87
+ VOVK_API_ENTRY_POINT?: string;
88
+ __VOVK_START_WATCHER_IN_STANDALONE_MODE__?: 'true';
89
+ __VOVK_SCHEMA_OUT_FLAG__?: string;
90
+ __VOVK_DEV_HTTPS_FLAG__?: 'true' | 'false';
91
+ __VOVK_EXIT__?: 'true' | 'false';
92
+ __VOVK_LOG_LEVEL__?: LogLevelNames;
93
+ };
94
+ declare global {
95
+ var TSdownBuildOptions: Parameters<typeof build>[0];
74
96
  }
@@ -0,0 +1,5 @@
1
+ import type { OpenAPIObject } from 'openapi3-ts/oas31';
2
+ import type { JSONSchema7 } from 'json-schema';
3
+ export declare function compileJSONSchemaToTypeScriptType(schema: JSONSchema7, typeName: string, components?: NonNullable<OpenAPIObject['components']>, options?: {
4
+ dontCreateRefTypes?: boolean;
5
+ }): string;
@@ -0,0 +1,9 @@
1
+ import { compileTs } from './compileTs.mjs';
2
+ export function compileJSONSchemaToTypeScriptType(schema, typeName, components = {}, options = {}) {
3
+ if (!schema)
4
+ return '';
5
+ if ('tsType' in schema && typeof schema.tsType === 'string')
6
+ return `export type ${typeName} = ${schema.tsType};\n`;
7
+ const tsType = compileTs({ schema: { ...schema, components }, name: typeName, ...options });
8
+ return tsType;
9
+ }
@@ -0,0 +1,12 @@
1
+ import { JSONSchema7 } from 'json-schema';
2
+ import { OpenAPIObject } from 'openapi3-ts/oas31';
3
+ interface CompileOptions {
4
+ name: string;
5
+ schema: JSONSchema7 & {
6
+ components?: OpenAPIObject['components'];
7
+ };
8
+ refs?: Map<string, JSONSchema7>;
9
+ dontCreateRefTypes?: boolean;
10
+ }
11
+ export declare function compileTs(options: CompileOptions): string;
12
+ export {};