vovk-cli 0.0.1-draft.99 → 0.0.3

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 (164) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +24 -16
  3. package/client-templates/jsBase/index.d.ts.ejs +21 -0
  4. package/client-templates/jsBase/index.js.ejs +18 -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/openapiJs/openapi.d.ts.ejs +4 -0
  8. package/client-templates/openapiJs/openapi.js.ejs +4 -0
  9. package/client-templates/openapiJson/openapi.json.ejs +1 -0
  10. package/client-templates/openapiTs/openapi.ts.ejs +4 -0
  11. package/client-templates/packageJson/package.json.ejs +1 -0
  12. package/client-templates/readme/README.md.ejs +39 -0
  13. package/client-templates/schemaJs/schema.d.ts.ejs +10 -0
  14. package/client-templates/schemaJs/schema.js.ejs +29 -0
  15. package/client-templates/schemaJson/schema.json.ejs +1 -0
  16. package/client-templates/schemaTs/schema.ts.ejs +28 -0
  17. package/client-templates/tsBase/index.ts.ejs +27 -0
  18. package/dist/bundle/index.d.mts +8 -0
  19. package/dist/bundle/index.mjs +76 -0
  20. package/dist/dev/{diffSchema.d.mts → diffSegmentSchema.d.mts} +3 -3
  21. package/dist/dev/{diffSchema.mjs → diffSegmentSchema.mjs} +1 -1
  22. package/dist/dev/ensureSchemaFiles.d.mts +2 -2
  23. package/dist/dev/ensureSchemaFiles.mjs +16 -47
  24. package/dist/dev/index.d.mts +2 -0
  25. package/dist/dev/index.mjs +113 -64
  26. package/dist/dev/logDiffResult.d.mts +2 -2
  27. package/dist/dev/logDiffResult.mjs +6 -6
  28. package/dist/dev/writeMetaJson.d.mts +2 -0
  29. package/dist/dev/writeMetaJson.mjs +19 -0
  30. package/dist/dev/writeOneSegmentSchemaFile.d.mts +12 -0
  31. package/dist/dev/{writeOneSchemaFile.mjs → writeOneSegmentSchemaFile.mjs} +11 -8
  32. package/dist/generate/ensureClient.d.mts +2 -4
  33. package/dist/generate/ensureClient.mjs +26 -28
  34. package/dist/generate/generate.d.mts +13 -0
  35. package/dist/generate/generate.mjs +307 -0
  36. package/dist/generate/getClientTemplateFiles.d.mts +20 -0
  37. package/dist/generate/getClientTemplateFiles.mjs +85 -0
  38. package/dist/generate/getProjectFullSchema.d.mts +9 -0
  39. package/dist/generate/getProjectFullSchema.mjs +64 -0
  40. package/dist/generate/getTemplateClientImports.d.mts +18 -0
  41. package/dist/generate/getTemplateClientImports.mjs +36 -0
  42. package/dist/generate/index.d.mts +31 -11
  43. package/dist/generate/index.mjs +177 -85
  44. package/dist/generate/writeOneClientFile.d.mts +43 -0
  45. package/dist/generate/writeOneClientFile.mjs +150 -0
  46. package/dist/getProjectInfo/getConfig/getConfigAbsolutePaths.d.mts +5 -0
  47. package/dist/getProjectInfo/{getConfigAbsolutePaths.mjs → getConfig/getConfigAbsolutePaths.mjs} +4 -1
  48. package/dist/getProjectInfo/getConfig/getRelativeSrcRoot.d.mts +3 -0
  49. package/dist/getProjectInfo/{getRelativeSrcRoot.mjs → getConfig/getRelativeSrcRoot.mjs} +3 -3
  50. package/dist/getProjectInfo/getConfig/getTemplateDefs.d.mts +25 -0
  51. package/dist/getProjectInfo/getConfig/getTemplateDefs.mjs +168 -0
  52. package/dist/getProjectInfo/getConfig/getUserConfig.d.mts +9 -0
  53. package/dist/getProjectInfo/getConfig/getUserConfig.mjs +142 -0
  54. package/dist/getProjectInfo/getConfig/index.d.mts +15 -0
  55. package/dist/getProjectInfo/getConfig/index.mjs +92 -0
  56. package/dist/getProjectInfo/getMetaSchema.d.mts +4 -0
  57. package/dist/getProjectInfo/getMetaSchema.mjs +12 -0
  58. package/dist/getProjectInfo/index.d.mts +12 -16
  59. package/dist/getProjectInfo/index.mjs +23 -29
  60. package/dist/index.d.mts +3 -3
  61. package/dist/index.mjs +119 -40
  62. package/dist/init/checkTSConfigForExperimentalDecorators.d.mts +1 -1
  63. package/dist/init/checkTSConfigForExperimentalDecorators.mjs +2 -2
  64. package/dist/init/createConfig.d.mts +5 -3
  65. package/dist/init/createConfig.mjs +77 -27
  66. package/dist/init/index.d.mts +2 -2
  67. package/dist/init/index.mjs +118 -103
  68. package/dist/init/installDependencies.d.mts +8 -6
  69. package/dist/init/installDependencies.mjs +7 -5
  70. package/dist/init/logUpdateDependenciesError.d.mts +6 -6
  71. package/dist/init/logUpdateDependenciesError.mjs +8 -4
  72. package/dist/init/updateDependenciesWithoutInstalling.d.mts +3 -3
  73. package/dist/init/updateDependenciesWithoutInstalling.mjs +41 -11
  74. package/dist/init/updateNPMScripts.d.mts +7 -2
  75. package/dist/init/updateNPMScripts.mjs +9 -5
  76. package/dist/init/updateTypeScriptConfig.d.mts +4 -1
  77. package/dist/init/updateTypeScriptConfig.mjs +12 -8
  78. package/dist/new/addClassToSegmentCode.d.mts +1 -1
  79. package/dist/new/addClassToSegmentCode.mjs +3 -3
  80. package/dist/new/addCommonTerms.d.mts +1 -1
  81. package/dist/new/addCommonTerms.mjs +1 -1
  82. package/dist/new/index.d.mts +2 -1
  83. package/dist/new/index.mjs +6 -5
  84. package/dist/new/newModule.d.mts +5 -3
  85. package/dist/new/newModule.mjs +34 -27
  86. package/dist/new/newSegment.d.mts +5 -2
  87. package/dist/new/newSegment.mjs +23 -16
  88. package/dist/new/render.d.mts +6 -3
  89. package/dist/new/render.mjs +15 -14
  90. package/dist/types.d.mts +64 -61
  91. package/dist/utils/chalkHighlightThing.d.mts +1 -1
  92. package/dist/utils/chalkHighlightThing.mjs +1 -1
  93. package/dist/utils/compileJSONSchemaToTypeScriptType.d.mts +5 -0
  94. package/dist/utils/compileJSONSchemaToTypeScriptType.mjs +9 -0
  95. package/dist/utils/compileTs.d.mts +12 -0
  96. package/dist/utils/compileTs.mjs +263 -0
  97. package/dist/utils/debounceWithArgs.d.mts +3 -2
  98. package/dist/utils/debounceWithArgs.mjs +1 -1
  99. package/dist/utils/formatLoggedSegmentName.d.mts +3 -1
  100. package/dist/utils/formatLoggedSegmentName.mjs +4 -3
  101. package/dist/utils/generateFnName.d.mts +23 -0
  102. package/dist/utils/generateFnName.mjs +78 -0
  103. package/dist/utils/getAvailablePort.d.mts +1 -2
  104. package/dist/utils/getAvailablePort.mjs +1 -2
  105. package/dist/utils/getFileSystemEntryType.d.mts +1 -1
  106. package/dist/utils/getFileSystemEntryType.mjs +1 -1
  107. package/dist/utils/getLogger.d.mts +1 -1
  108. package/dist/utils/getLogger.mjs +1 -1
  109. package/dist/utils/getNPMPackageMetadata.d.mts +2 -3
  110. package/dist/utils/getNPMPackageMetadata.mjs +1 -1
  111. package/dist/utils/getPackageJson.d.mts +3 -0
  112. package/dist/utils/getPackageJson.mjs +23 -0
  113. package/dist/utils/getPublicModuleNameFromPath.d.mts +4 -0
  114. package/dist/utils/getPublicModuleNameFromPath.mjs +9 -0
  115. package/dist/utils/locateSegments.d.mts +12 -0
  116. package/dist/{locateSegments.mjs → utils/locateSegments.mjs} +14 -7
  117. package/dist/utils/normalizeOpenAPIMixin.d.mts +15 -0
  118. package/dist/utils/normalizeOpenAPIMixin.mjs +96 -0
  119. package/dist/utils/pickSegmentFullSchema.d.mts +3 -0
  120. package/dist/utils/pickSegmentFullSchema.mjs +15 -0
  121. package/dist/utils/prettify.d.mts +1 -1
  122. package/dist/utils/prettify.mjs +1 -1
  123. package/dist/utils/removeUnlistedDirectories.d.mts +9 -0
  124. package/dist/utils/removeUnlistedDirectories.mjs +60 -0
  125. package/dist/utils/resolveAbsoluteModulePath.d.mts +2 -0
  126. package/dist/utils/resolveAbsoluteModulePath.mjs +32 -0
  127. package/dist/utils/updateConfigProperty.d.mts +2 -0
  128. package/dist/utils/updateConfigProperty.mjs +132 -0
  129. package/module-templates/arktype/controller.ts.ejs +90 -0
  130. package/module-templates/type/controller.ts.ejs +80 -0
  131. package/module-templates/type/service.ts.ejs +43 -0
  132. package/module-templates/valibot/controller.ts.ejs +91 -0
  133. package/module-templates/zod/controller.ts.ejs +98 -0
  134. package/package.json +50 -25
  135. package/client-templates/main/main.cjs.ejs +0 -15
  136. package/client-templates/main/main.d.cts.ejs +0 -14
  137. package/client-templates/module/module.d.mts.ejs +0 -14
  138. package/client-templates/module/module.mjs.ejs +0 -24
  139. package/client-templates/python/__init__.py +0 -276
  140. package/client-templates/ts/index.ts.ejs +0 -25
  141. package/dist/dev/isSchemaEmpty.d.mts +0 -2
  142. package/dist/dev/isSchemaEmpty.mjs +0 -4
  143. package/dist/dev/writeOneSchemaFile.d.mts +0 -12
  144. package/dist/generate/getClientTemplates.d.mts +0 -16
  145. package/dist/generate/getClientTemplates.mjs +0 -42
  146. package/dist/getProjectInfo/getConfig.d.mts +0 -11
  147. package/dist/getProjectInfo/getConfig.mjs +0 -35
  148. package/dist/getProjectInfo/getConfigAbsolutePaths.d.mts +0 -4
  149. package/dist/getProjectInfo/getRelativeSrcRoot.d.mts +0 -3
  150. package/dist/getProjectInfo/getUserConfig.d.mts +0 -9
  151. package/dist/getProjectInfo/getUserConfig.mjs +0 -27
  152. package/dist/getProjectInfo/importUncachedModule.d.mts +0 -3
  153. package/dist/getProjectInfo/importUncachedModule.mjs +0 -40
  154. package/dist/getProjectInfo/importUncachedModuleWorker.d.mts +0 -1
  155. package/dist/getProjectInfo/importUncachedModuleWorker.mjs +0 -25
  156. package/dist/init/getTemplateFilesFromPackage.d.mts +0 -7
  157. package/dist/init/getTemplateFilesFromPackage.mjs +0 -59
  158. package/dist/initProgram.d.mts +0 -2
  159. package/dist/initProgram.mjs +0 -22
  160. package/dist/locateSegments.d.mts +0 -11
  161. package/dist/postinstall.d.mts +0 -1
  162. package/dist/postinstall.mjs +0 -21
  163. package/templates/controller.ejs +0 -50
  164. package/templates/service.ejs +0 -27
@@ -1,6 +1,6 @@
1
- import newModule from './newModule.mjs';
2
- import newSegment from './newSegment.mjs';
3
- export default async function newComponents(components, { dryRun, dir, templates, overwrite, noSegmentUpdate, empty }) {
1
+ import { newModule } from './newModule.mjs';
2
+ import { newSegment } from './newSegment.mjs';
3
+ export async function newComponents(components, projectInfo, { dryRun, outDir, 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,9 +24,10 @@ 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
- dir,
30
+ outDir,
30
31
  templates,
31
32
  overwrite,
32
33
  noSegmentUpdate,
@@ -1,10 +1,12 @@
1
- export default function newModule({ what, moduleNameWithOptionalSegment, dryRun, dir: dirFlag, templates: templatesFlag, noSegmentUpdate, overwrite, empty, }: {
1
+ import type { ProjectInfo } from '../getProjectInfo/index.mjs';
2
+ export declare function newModule({ projectInfo, what, moduleNameWithOptionalSegment, dryRun, outDir: outDirFlag, templates: templatesFlag, noSegmentUpdate, overwrite, empty, }: {
3
+ projectInfo: ProjectInfo;
2
4
  what: string[];
3
5
  moduleNameWithOptionalSegment: string;
4
6
  dryRun?: boolean;
5
- dir?: string;
7
+ outDir?: string;
6
8
  templates?: string[];
7
9
  noSegmentUpdate?: boolean;
8
10
  overwrite?: boolean;
9
11
  empty?: boolean;
10
- }): Promise<void>;
12
+ }): Promise<undefined>;
@@ -1,13 +1,15 @@
1
1
  import path from 'node:path';
2
2
  import fs from 'node:fs/promises';
3
- import render from './render.mjs';
4
- import addClassToSegmentCode from './addClassToSegmentCode.mjs';
5
- import getProjectInfo from '../getProjectInfo/index.mjs';
6
- import locateSegments from '../locateSegments.mjs';
7
- import chalkHighlightThing from '../utils/chalkHighlightThing.mjs';
8
- import formatLoggedSegmentName from '../utils/formatLoggedSegmentName.mjs';
9
- import getFileSystemEntryType from '../utils/getFileSystemEntryType.mjs';
10
- import prettify from '../utils/prettify.mjs';
3
+ import chalk from 'chalk';
4
+ import { getTsconfig } from 'get-tsconfig';
5
+ import { render } from './render.mjs';
6
+ import { addClassToSegmentCode } from './addClassToSegmentCode.mjs';
7
+ import { chalkHighlightThing } from '../utils/chalkHighlightThing.mjs';
8
+ import { formatLoggedSegmentName } from '../utils/formatLoggedSegmentName.mjs';
9
+ import { getFileSystemEntryType } from '../utils/getFileSystemEntryType.mjs';
10
+ import { prettify } from '../utils/prettify.mjs';
11
+ import { resolveAbsoluteModulePath } from '../utils/resolveAbsoluteModulePath.mjs';
12
+ import { locateSegments } from '../utils/locateSegments.mjs';
11
13
  function splitByLast(str, delimiter = '/') {
12
14
  const index = str.lastIndexOf(delimiter);
13
15
  if (index === -1) {
@@ -18,9 +20,11 @@ function splitByLast(str, delimiter = '/') {
18
20
  const after = str.substring(index + delimiter.length);
19
21
  return [before, after];
20
22
  }
21
- export default async function newModule({ what, moduleNameWithOptionalSegment, dryRun, dir: dirFlag, templates: templatesFlag, noSegmentUpdate, overwrite, empty, }) {
22
- const { config, log, apiDir, cwd } = await getProjectInfo();
23
- let templates = config.templates;
23
+ export async function newModule({ projectInfo, what, moduleNameWithOptionalSegment, dryRun, outDir: outDirFlag, templates: templatesFlag, noSegmentUpdate, overwrite, empty, }) {
24
+ const { config, log, cwd, apiDirAbsolutePath, srcRoot } = projectInfo;
25
+ const segments = await locateSegments({ dir: apiDirAbsolutePath, config, log });
26
+ const isNodeNextResolution = ['node16', 'nodenext'].includes((await getTsconfig(cwd)?.config?.compilerOptions?.moduleResolution?.toLowerCase()) ?? '');
27
+ let templates = config.moduleTemplates;
24
28
  const [segmentName, moduleName] = splitByLast(moduleNameWithOptionalSegment);
25
29
  // replace c by controller, s by service, everything else keeps the same
26
30
  what = what.map((s) => {
@@ -37,8 +41,7 @@ export default async function newModule({ what, moduleNameWithOptionalSegment, d
37
41
  if (templatesFlag.length > what.length) {
38
42
  throw new Error('Too many templates provided');
39
43
  }
40
- templates = templatesFlag.reduce((acc, templatePath, index) => ({
41
- ...acc,
44
+ templates = templatesFlag.reduce((acc, templatePath, index) => Object.assign(acc, {
42
45
  [what[index]]: templatePath,
43
46
  }), templates);
44
47
  }
@@ -47,44 +50,47 @@ export default async function newModule({ what, moduleNameWithOptionalSegment, d
47
50
  throw new Error(`Template for "${type}" not found`);
48
51
  }
49
52
  }
50
- const segments = await locateSegments({ dir: apiDir, config });
51
53
  const segment = segments.find((s) => s.segmentName === segmentName);
52
54
  if (!segment) {
53
- throw new Error(`Unable to create module. Segment "${segmentName}" not found. Run "vovk new segment ${segmentName}" to create it`);
55
+ log.error(`Unable to create module: ${formatLoggedSegmentName(segmentName)} not found. Run ${chalkHighlightThing(`npx vovk new segment${segmentName ? ` ${segmentName}` : ''}`)} to create it`);
56
+ return process.exit(1);
54
57
  }
55
58
  for (const type of what) {
56
59
  const templatePath = templates[type];
57
- const templateAbsolutePath = templatePath.startsWith('/') || templatePath.startsWith('.')
58
- ? path.resolve(cwd, templatePath)
59
- : path.resolve(cwd, './node_modules', templatePath);
60
+ if (!templatePath)
61
+ continue; // suppresses TypeScript error, but it shouldn't happen
62
+ const templateAbsolutePath = resolveAbsoluteModulePath(templatePath, cwd);
60
63
  const templateCode = await fs.readFile(templateAbsolutePath, 'utf-8');
61
- const { dir: renderedDir, fileName, sourceName, compiledName, code, } = await render(templateCode, {
64
+ const { outDir: renderedOutDir, fileName, sourceName, compiledName, code, } = await render(templateCode, {
62
65
  cwd,
66
+ srcRoot,
63
67
  config,
64
68
  withService: what.includes('service'),
65
69
  segmentName,
66
70
  moduleName,
67
71
  empty,
68
72
  templateFileName: templateAbsolutePath,
73
+ isNodeNextResolution,
69
74
  });
70
- const dir = dirFlag || renderedDir;
71
- if (!dir) {
72
- throw new Error(`The template for "${type}" does not provide a dir`);
75
+ const outDir = outDirFlag ?? renderedOutDir;
76
+ if (!outDir) {
77
+ throw new Error(`The template for "${type}" does not provide a outDir`);
73
78
  }
74
79
  if (!fileName) {
75
80
  throw new Error(`The template for "${type}" does not provide a fileName`);
76
81
  }
77
- const absoluteModuleDir = path.join(cwd, dir);
82
+ const absoluteModuleDir = path.join(cwd, outDir);
78
83
  const absoluteModulePath = path.join(absoluteModuleDir, fileName);
79
84
  const prettiedCode = await prettify(code, absoluteModulePath);
80
85
  if (!dryRun) {
81
86
  if (!overwrite && (await getFileSystemEntryType(absoluteModulePath))) {
82
- log.warn(`File ${chalkHighlightThing(absoluteModulePath)} already exists, skipping this "${type}"`);
87
+ log.error(`File ${chalkHighlightThing(absoluteModulePath)} already exists, skipping this "${chalkHighlightThing(type)}". You can use --overwrite flag to overwrite it.`);
88
+ return process.exit(1);
83
89
  }
84
90
  else {
85
91
  await fs.mkdir(absoluteModuleDir, { recursive: true });
86
92
  await fs.writeFile(absoluteModulePath, prettiedCode);
87
- log.info(`Created ${chalkHighlightThing(fileName)} using ${chalkHighlightThing(`"${type}"`)} template for ${formatLoggedSegmentName(segmentName)}`);
93
+ log.info(`${chalk.green('Created')}${empty ? ' empty' : ''} ${chalkHighlightThing(absoluteModulePath)} using ${chalkHighlightThing(`"${type}"`)} template for ${formatLoggedSegmentName(segmentName)}`);
88
94
  }
89
95
  }
90
96
  if (type === 'controller') {
@@ -96,7 +102,8 @@ export default async function newModule({ what, moduleNameWithOptionalSegment, d
96
102
  }
97
103
  const { routeFilePath } = segment;
98
104
  const segmentSourceCode = await fs.readFile(routeFilePath, 'utf-8');
99
- const importPath = path.relative(path.dirname(routeFilePath), absoluteModulePath).replace(/\.(ts|tsx)$/, '');
105
+ let importPath = path.relative(`${path.dirname(routeFilePath)}/`, absoluteModulePath).replace(/\.(ts|tsx)$/, '');
106
+ importPath += isNodeNextResolution ? '.ts' : '';
100
107
  if (!noSegmentUpdate) {
101
108
  const newSegmentCode = await prettify(addClassToSegmentCode(segmentSourceCode, {
102
109
  sourceName,
@@ -107,7 +114,7 @@ export default async function newModule({ what, moduleNameWithOptionalSegment, d
107
114
  await fs.writeFile(routeFilePath, newSegmentCode);
108
115
  }
109
116
  }
110
- log.info(`Added ${chalkHighlightThing(sourceName)} ${type} as ${chalkHighlightThing(compiledName)} to ${formatLoggedSegmentName(segmentName)}`);
117
+ log.info(`${chalk.green('Added')} ${chalkHighlightThing(sourceName)} ${type} as ${chalkHighlightThing(compiledName)} to ${formatLoggedSegmentName(segmentName)}`);
111
118
  }
112
119
  }
113
120
  }
@@ -1,5 +1,8 @@
1
- export default function newSegment({ segmentName, overwrite, dryRun, }: {
1
+ import type { ProjectInfo } from '../getProjectInfo/index.mjs';
2
+ export declare 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
- }): Promise<void>;
8
+ }): Promise<undefined>;
@@ -1,26 +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
- import getFileSystemEntryType from '../utils/getFileSystemEntryType.mjs';
5
- import chalkHighlightThing from '../utils/chalkHighlightThing.mjs';
6
- import formatLoggedSegmentName from '../utils/formatLoggedSegmentName.mjs';
7
- import prettify from '../utils/prettify.mjs';
3
+ import { getFileSystemEntryType } from '../utils/getFileSystemEntryType.mjs';
4
+ import { chalkHighlightThing } from '../utils/chalkHighlightThing.mjs';
5
+ import { formatLoggedSegmentName } from '../utils/formatLoggedSegmentName.mjs';
6
+ import { prettify } from '../utils/prettify.mjs';
8
7
  import chalk from 'chalk';
9
- export default async function newSegment({ segmentName, overwrite, dryRun, }) {
10
- const { apiDir, cwd, log } = await getProjectInfo();
11
- const absoluteSegmentRoutePath = path.join(cwd, apiDir, segmentName, '[[...vovk]]/route.ts');
8
+ export 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 Next.js project.');
12
+ }
13
+ const absoluteSegmentRoutePath = path.join(apiDirAbsolutePath, segmentName, '[[...vovk]]/route.ts');
12
14
  if (!overwrite && (await getFileSystemEntryType(absoluteSegmentRoutePath))) {
13
- throw new Error(`Unable to create new segment. ${formatLoggedSegmentName(segmentName, { upperFirst: true })} already exists.`);
15
+ log.error(`Unable to create new segment. ${formatLoggedSegmentName(segmentName, { upperFirst: true })} already exists. You can use --overwrite flag to overwrite it.`);
16
+ return process.exit(1);
14
17
  }
15
- const code = await prettify(`import { initVovk } from 'vovk';
16
-
17
- export const runtime = 'edge';
18
+ const code = await prettify(`import { initSegment${isStaticSegment ? ', controllersToStaticParams' : ''} } from 'vovk';
18
19
 
19
20
  const controllers = {};
20
21
 
21
22
  export type Controllers = typeof controllers;
22
-
23
- export const { GET, POST, PATCH, PUT, HEAD, OPTIONS, DELETE } = initVovk({
23
+ ${isStaticSegment
24
+ ? `
25
+ export function generateStaticParams() {
26
+ return controllersToStaticParams(controllers);
27
+ }
28
+ `
29
+ : ''}
30
+ export const { GET${isStaticSegment ? '' : ', POST, PATCH, PUT, HEAD, OPTIONS, DELETE'} } = initSegment({
24
31
  ${segmentName ? ` segmentName: '${segmentName}',\n` : ''} emitSchema: true,
25
32
  controllers,
26
33
  });
@@ -29,7 +36,7 @@ ${segmentName ? ` segmentName: '${segmentName}',\n` : ''} emitSchema: true,
29
36
  await fs.mkdir(path.dirname(absoluteSegmentRoutePath), { recursive: true });
30
37
  await fs.writeFile(absoluteSegmentRoutePath, code);
31
38
  }
32
- log.info(`${formatLoggedSegmentName(segmentName, { upperFirst: true })} created at ${absoluteSegmentRoutePath}.`);
39
+ log.info(`${chalk.green('Created')} ${formatLoggedSegmentName(segmentName, { isStatic: isStaticSegment })} at ${absoluteSegmentRoutePath}.`);
33
40
  const dir = chalk.cyanBright([segmentName, 'thing'].filter(Boolean).join('/'));
34
- log.info(`Run ${chalkHighlightThing(`npx vovk new service controller ${dir}`)} to create a new controller with a service at modules/${dir} folder for this segment`);
41
+ log.info(`Run ${chalkHighlightThing(`npx vovk new service controller ${dir}`)} to create a new controller with a service at ./${path.join(config.modulesDir, dir)}/ directory for this segment`);
35
42
  }
@@ -1,10 +1,13 @@
1
- import type { VovkConfig, VovkModuleRenderResult } from '../types.mjs';
2
- export default function render(codeTemplate: string, { config, withService, segmentName, moduleName, empty, templateFileName, }: {
1
+ import type { VovkStrictConfig } from 'vovk/internal';
2
+ import type { VovkModuleRenderResult } from '../types.mjs';
3
+ export declare function render(codeTemplate: string, { cwd, config, withService, segmentName, moduleName, empty, templateFileName, isNodeNextResolution, srcRoot, }: {
3
4
  cwd: string;
4
- config: VovkConfig;
5
+ config: VovkStrictConfig;
5
6
  withService: boolean;
6
7
  segmentName: string;
7
8
  moduleName: string;
8
9
  empty?: boolean;
9
10
  templateFileName: string;
11
+ isNodeNextResolution: boolean;
12
+ srcRoot: string | null;
10
13
  }): Promise<VovkModuleRenderResult>;
@@ -2,20 +2,14 @@ import ejs from 'ejs';
2
2
  import matter from 'gray-matter';
3
3
  import _ from 'lodash';
4
4
  import pluralize from 'pluralize';
5
- import addCommonTerms from './addCommonTerms.mjs';
5
+ import { addCommonTerms } from './addCommonTerms.mjs';
6
+ import path from 'node:path';
6
7
  addCommonTerms();
7
- export default async function render(codeTemplate, { config, withService, segmentName, moduleName, empty, templateFileName, }) {
8
- const getModuleDirName = (givenSegmentName, givenModuleName) => [config.modulesDir, givenSegmentName || config.rootSegmentModulesDirName, _.camelCase(givenModuleName)]
8
+ export async function render(codeTemplate, { cwd, config, withService, segmentName, moduleName, empty, templateFileName, isNodeNextResolution, srcRoot, }) {
9
+ const defaultOutDir = [config.modulesDir, segmentName || config.rootSegmentModulesDirName, _.camelCase(moduleName)]
9
10
  .filter(Boolean)
10
11
  .join('/');
11
- /*
12
- <% var modulePascalName = _.upperFirst(_.camelCase(moduleName)); %>
13
- <% var modulePascalNamePlural = pluralize(modulePascalName); %>
14
- <% var controllerName = modulePascalName + 'Controller'; %>
15
- <% var compiledName = modulePascalName + 'RPC'; %>
16
- <% var serviceName = modulePascalName + 'Service'; %>
17
- <% var prefix = pluralize(_.kebabCase(moduleName).toLowerCase()); %>
18
- */
12
+ const relativePathToSourceRoot = path.relative(path.resolve(cwd, defaultOutDir), path.join(cwd, srcRoot ?? '.')) || '.';
19
13
  const theThing = _.camelCase(moduleName);
20
14
  const TheThing = _.upperFirst(theThing);
21
15
  const the_thing = _.snakeCase(moduleName);
@@ -38,16 +32,23 @@ export default async function render(codeTemplate, { config, withService, segmen
38
32
  config,
39
33
  withService,
40
34
  segmentName,
41
- defaultDir: getModuleDirName(segmentName, theThing),
35
+ nodeNextResolutionExt: {
36
+ ts: isNodeNextResolution ? '.ts' : '',
37
+ js: isNodeNextResolution ? '.js' : '',
38
+ cjs: isNodeNextResolution ? '.cjs' : '',
39
+ mjs: isNodeNextResolution ? '.mjs' : '',
40
+ },
41
+ defaultOutDir,
42
+ relativePathToSourceRoot,
42
43
  // libraries
43
44
  _, // lodash
44
45
  pluralize,
45
46
  };
46
47
  const parsed = matter((await ejs.render(codeTemplate, { t }, { async: true, filename: templateFileName })).trim());
47
- const { dir, fileName, sourceName, compiledName } = parsed.data;
48
+ const { outDir, fileName, sourceName, compiledName } = parsed.data;
48
49
  const code = empty ? (sourceName ? `export default class ${sourceName} {}` : '') : parsed.content;
49
50
  return {
50
- dir,
51
+ outDir,
51
52
  fileName,
52
53
  sourceName,
53
54
  compiledName,
package/dist/types.d.mts CHANGED
@@ -1,75 +1,61 @@
1
1
  import type { LogLevelNames } from 'loglevel';
2
- export type KnownAny = any;
3
- export type VovkEnv = {
4
- PORT?: string;
5
- VOVK_CLIENT_OUT_DIR?: string;
6
- VOVK_SCHEMA_OUT_DIR?: string;
7
- VOVK_FETCHER_PATH?: string;
8
- VOVK_VALIDATE_ON_CLIENT_PATH?: string;
9
- VOVK_CREATE_RPC_PATH?: string;
10
- VOVK_MODULES_DIR?: 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
- __VOVK_EXIT__?: 'true' | 'false';
20
- };
21
- type GenerateFrom = (string | {
22
- templatePath: string;
23
- outDir?: string;
24
- templateName?: string;
25
- fullSchema?: string | boolean;
26
- })[];
27
- export type VovkConfig = {
28
- clientOutDir?: string;
29
- schemaOutDir?: string;
30
- fetcherImport?: string | string[];
31
- validateOnClientImport?: string | string[] | null;
32
- createRPCImport?: string | string[];
33
- modulesDir?: string;
34
- rootEntry?: string;
35
- origin?: string;
36
- rootSegmentModulesDirName?: string;
37
- logLevel?: LogLevelNames;
38
- prettifyClient?: boolean;
39
- devHttps?: boolean;
40
- generateFrom?: GenerateFrom | ((value: GenerateFrom) => GenerateFrom);
41
- templates?: {
42
- service?: string;
43
- controller?: string;
44
- [key: string]: string | undefined;
45
- };
46
- };
47
- export type VovkStrictConfig = Required<Omit<VovkConfig, 'validateOnClientImport' | 'fetcherImport' | 'createRPCImport' | 'generateFrom'>> & {
48
- validateOnClientImport: string[] | null;
49
- fetcherImport: string[];
50
- createRPCImport: string[];
51
- generateFrom: GenerateFrom;
52
- };
2
+ import type { build } from 'tsdown';
3
+ import type { VovkStrictConfig } from 'vovk/internal';
53
4
  export type VovkModuleRenderResult = {
54
5
  fileName: string;
55
- dir: string;
6
+ outDir: string;
56
7
  sourceName?: string;
57
8
  compiledName?: string;
58
9
  code: string;
59
10
  };
60
11
  export interface DevOptions {
12
+ schemaOut?: string;
61
13
  nextDev?: boolean;
62
14
  exit?: boolean;
15
+ devHttps?: boolean;
16
+ logLevel?: LogLevelNames;
63
17
  }
64
18
  export interface GenerateOptions {
65
- clientOutDir?: string;
66
- templates?: string[];
67
19
  prettify?: boolean;
68
- fullSchema?: string | 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
+ bundler?: 'tsdown' | 'ncc';
44
+ configPath?: string;
45
+ schemaPath?: string;
46
+ outDir?: string;
47
+ origin?: string;
48
+ openapiSpec?: string[];
49
+ openapiGetModuleName?: string[];
50
+ openapiGetMethodName?: string[];
51
+ openapiRootUrl?: string[];
52
+ openapiMixinName?: string[];
53
+ openapiFallback?: string[];
54
+ logLevel?: LogLevelNames;
69
55
  }
70
56
  export interface InitOptions {
57
+ prefix?: string;
71
58
  yes?: boolean;
72
- logLevel: LogLevelNames;
73
59
  useNpm?: boolean;
74
60
  useYarn?: boolean;
75
61
  usePnpm?: boolean;
@@ -77,18 +63,35 @@ export interface InitOptions {
77
63
  skipInstall?: boolean;
78
64
  updateTsConfig?: boolean;
79
65
  updateScripts?: 'implicit' | 'explicit';
80
- validationLibrary?: string | null;
81
- reactQuery?: boolean;
82
- validateOnClient?: boolean;
66
+ bundle?: boolean;
67
+ validationLibrary?: 'zod' | 'valibot' | 'arktype' | null;
83
68
  dryRun?: boolean;
69
+ lang?: string[];
84
70
  channel?: 'latest' | 'beta' | 'draft';
71
+ logLevel?: LogLevelNames;
85
72
  }
86
73
  export interface NewOptions {
87
74
  dryRun?: boolean;
88
75
  templates?: string[];
89
- dir?: string;
76
+ outDir?: string;
90
77
  overwrite?: boolean;
91
78
  noSegmentUpdate?: boolean;
92
79
  empty?: boolean;
80
+ static?: boolean;
81
+ logLevel?: LogLevelNames;
82
+ }
83
+ export type VovkEnv = {
84
+ PORT?: string;
85
+ VOVK_SCHEMA_OUT_DIR?: string;
86
+ VOVK_ORIGIN?: string;
87
+ VOVK_ROOT_ENTRY?: string;
88
+ VOVK_API_ENTRY_POINT?: string;
89
+ __VOVK_START_WATCHER_IN_STANDALONE_MODE__?: 'true';
90
+ __VOVK_SCHEMA_OUT_FLAG__?: string;
91
+ __VOVK_DEV_HTTPS_FLAG__?: 'true' | 'false';
92
+ __VOVK_EXIT__?: 'true' | 'false';
93
+ __VOVK_LOG_LEVEL__?: LogLevelNames;
94
+ };
95
+ declare global {
96
+ var TSdownBuildOptions: Parameters<typeof build>[0];
93
97
  }
94
- export {};
@@ -1 +1 @@
1
- export default function chalkHighlightThing(str: string): string;
1
+ export declare function chalkHighlightThing(str: string): string;
@@ -1,4 +1,4 @@
1
1
  import chalk from 'chalk';
2
- export default function chalkHighlightThing(str) {
2
+ export function chalkHighlightThing(str) {
3
3
  return chalk.whiteBright.bold(str);
4
4
  }
@@ -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 type { JSONSchema7 } from 'json-schema';
2
+ import type { 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 {};