vovk-cli 0.0.1-draft.147 → 0.0.1-draft.149

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 (38) hide show
  1. package/client-templates/{main/main.cjs.ejs → cjs/index.cjs.ejs} +4 -4
  2. package/client-templates/{module/module.d.mts.ejs → dts/index.d.ts.ejs} +5 -5
  3. package/client-templates/fullSchemaCjs/fullSchema.cjs.ejs +2 -4
  4. package/client-templates/fullSchemaCjs/fullSchema.d.cts.ejs +2 -4
  5. package/client-templates/fullSchemaTs/fullSchema.ts.ejs +5 -10
  6. package/client-templates/{module/module.mjs.ejs → mjs/index.mjs.ejs} +4 -4
  7. package/client-templates/readme/README.md.ejs +41 -0
  8. package/client-templates/ts/index.ts.ejs +6 -6
  9. package/dist/bundle/index.d.mts +8 -0
  10. package/dist/bundle/index.mjs +27 -0
  11. package/dist/bundle/rollupBundle.d.mts +5 -0
  12. package/dist/bundle/rollupBundle.mjs +55 -0
  13. package/dist/generate/getClientTemplateFiles.d.mts +7 -4
  14. package/dist/generate/getClientTemplateFiles.mjs +45 -37
  15. package/dist/generate/index.d.mts +2 -2
  16. package/dist/generate/index.mjs +9 -7
  17. package/dist/getProjectInfo/getConfig/getTemplateDefs.d.mts +5 -3
  18. package/dist/getProjectInfo/getConfig/getTemplateDefs.mjs +21 -10
  19. package/dist/getProjectInfo/getConfig/index.d.mts +4 -3
  20. package/dist/getProjectInfo/getConfig/index.mjs +16 -6
  21. package/dist/getProjectInfo/importUncachedModule.mjs +1 -4
  22. package/dist/getProjectInfo/index.d.mts +4 -3
  23. package/dist/getProjectInfo/index.mjs +3 -2
  24. package/dist/index.d.mts +2 -0
  25. package/dist/index.mjs +27 -4
  26. package/dist/init/createConfig.mjs +2 -5
  27. package/dist/init/getTemplateFilesFromPackage.mjs +0 -1
  28. package/dist/new/index.d.mts +1 -1
  29. package/dist/new/index.mjs +2 -2
  30. package/dist/new/newModule.mjs +3 -1
  31. package/dist/new/newSegment.d.mts +2 -1
  32. package/dist/new/newSegment.mjs +7 -3
  33. package/dist/types.d.mts +22 -0
  34. package/module-templates/controller.ts.ejs +4 -4
  35. package/module-templates/service.ts.ejs +5 -5
  36. package/package.json +11 -4
  37. package/client-templates/main/main.d.cts.ejs +0 -15
  38. /package/client-templates/{package → packageJson}/package.json.ejs +0 -0
@@ -3,10 +3,10 @@ const { fetcher } = require('<%= t.imports.fetcher %>');
3
3
  const { createRPC } = require('<%= t.imports.createRPC %>');
4
4
  const { fullSchema } = require('./fullSchema.cjs');
5
5
  const { validateOnClient = null } = <%- t.imports.validateOnClient ? `require('${t.imports.validateOnClient}')` : '{}'%>;
6
- <% Object.values(t.fullSchema.segments).forEach((segment) => {
7
- Object.keys(segment.controllers).forEach((controllerName) => { %>
8
- exports.<%= controllerName %> = createRPC(
9
- fullSchema, '<%= segment.segmentName %>', '<%= controllerName %>',
6
+ <% Object.values(t.fullSchema.segments).filter((segment) => segment.emitSchema).forEach((segment) => {
7
+ Object.keys(segment.controllers).forEach((rpcModuleName) => { %>
8
+ exports.<%= rpcModuleName %> = createRPC(
9
+ fullSchema, '<%= segment.segmentName %>', '<%= rpcModuleName %>',
10
10
  { fetcher, validateOnClient, defaultOptions: { apiRoot: '<%= segment.segmentApiRoot ?? t.apiRoot %>' } }
11
11
  );
12
12
  <% })
@@ -3,13 +3,13 @@
3
3
  import type { VovkClientFetcher } from 'vovk';
4
4
  import type { fetcher } from '<%= t.imports.module.fetcher %>';
5
5
  import type { createRPC } from '<%= t.imports.module.createRPC %>';
6
- <% Object.values(t.fullSchema.segments).forEach((segment, i) => { if(Object.keys(segment.controllers).length) { %>
6
+ <% Object.values(t.fullSchema.segments).filter((segment) => segment.emitSchema).forEach((segment, i) => { %>
7
7
  import type { Controllers as Controllers<%= i %> } from "<%= t.segmentMeta[segment.segmentName].segmentImportPath %>";
8
- <% }}) %>
8
+ <% }) %>
9
9
  type Options = typeof fetcher extends VovkClientFetcher<infer U> ? U : never;
10
- <% Object.values(t.fullSchema.segments).forEach((segment, i) => {
11
- Object.keys(segment.controllers).forEach((controllerName) => { %>
12
- export const <%= controllerName %>: ReturnType<typeof createRPC<Controllers<%= i %>["<%= controllerName %>"], Options>>;
10
+ <% Object.values(t.fullSchema.segments).filter((segment) => segment.emitSchema).forEach((segment, i) => {
11
+ Object.keys(segment.controllers).forEach((rpcModuleName) => { %>
12
+ export const <%= rpcModuleName %>: ReturnType<typeof createRPC<Controllers<%= i %>["<%= rpcModuleName %>"], Options>>;
13
13
  <% })
14
14
  }) %>
15
15
  export { fullSchema } from './fullSchema.cjs';
@@ -1,9 +1,7 @@
1
1
  <%- `// auto-generated ${new Date().toISOString()}\n/* eslint-disable */` %>
2
2
  const config = require('./<%= t.schemaOutDir %>/config.json');
3
- const segments = {
4
- <% Object.values(t.fullSchema.segments).forEach((segment) => { %>
5
- '<%= segment.segmentName %>': require('./<%= t.schemaOutDir %>/<%= t.SEGMENTS_SCHEMA_DIR_NAME %>/<%= segment.segmentName || t.ROOT_SEGMENT_SCHEMA_NAME %>.json'),
6
- <% }) %>
3
+ const segments = {<% Object.values(t.fullSchema.segments).filter((segment) => segment.emitSchema).forEach((segment) => { %>
4
+ '<%= segment.segmentName %>': require('./<%= t.schemaOutDir %>/<%= t.SEGMENTS_SCHEMA_DIR_NAME %>/<%= segment.segmentName || t.ROOT_SEGMENT_SCHEMA_NAME %>.json'),<% }) %>
7
5
  };
8
6
  const fullSchema = {
9
7
  config,
@@ -3,9 +3,7 @@ import type { VovkStrictConfig, VovkSegmentSchema } from 'vovk';
3
3
 
4
4
  export const fullSchema: {
5
5
  config: Partial<VovkStrictConfig>;
6
- segments: {
7
- <% Object.values(t.fullSchema.segments).forEach((segment) => { %>
8
- '<%= segment.segmentName %>': VovkSegmentSchema;
9
- <% }) %>
6
+ segments: {<% Object.values(t.fullSchema.segments).filter((segment) => segment.emitSchema).forEach((segment) => { %>
7
+ '<%= segment.segmentName %>': VovkSegmentSchema;<% }) %>
10
8
  };
11
9
  };
@@ -1,15 +1,10 @@
1
1
  <%- `// auto-generated ${new Date().toISOString()}\n/* eslint-disable */` %>
2
- import type { VovkStrictConfig, VovkSegmentSchema } from 'vovk';
3
2
  import config from './<%= t.schemaOutDir %>/config.json' with { type: "json" };
4
-
5
- <% Object.values(t.fullSchema.segments).forEach((segment, i) => { if(Object.keys(segment.controllers).length) { %>
6
- import segment<%= i %> from './<%= t.schemaOutDir %>/<%= t.SEGMENTS_SCHEMA_DIR_NAME %>/<%= segment.segmentName || t.ROOT_SEGMENT_SCHEMA_NAME %>.json' with { type: "json" };
7
- <% }}) %>
8
-
9
- const segments = {
10
- <% Object.values(t.fullSchema.segments).forEach((segment, i) => { %>
11
- '<%= segment.segmentName %>': segment<%= i %>,
12
- <% }) %>
3
+ <% Object.values(t.fullSchema.segments).filter((segment) => segment.emitSchema).forEach((segment, i) => { %>
4
+ import segment<%= i %> from './<%= t.schemaOutDir %>/<%= t.SEGMENTS_SCHEMA_DIR_NAME %>/<%= segment.segmentName || t.ROOT_SEGMENT_SCHEMA_NAME %>.json' with { type: "json" };
5
+ <% }) %>
6
+ const segments = {<% Object.values(t.fullSchema.segments).filter((segment) => segment.emitSchema).forEach((segment, i) => { %>
7
+ '<%= segment.segmentName %>': segment<%= i %>,<% }) %>
13
8
  };
14
9
 
15
10
  export const fullSchema = {
@@ -7,10 +7,10 @@ import { validateOnClient } from '<%= t.imports.module.validateOnClient %>';
7
7
  <% } else { %>
8
8
  const validateOnClient = undefined;
9
9
  <% } %>
10
- <% Object.values(t.fullSchema.segments).forEach((segment, i) => {
11
- Object.keys(segment.controllers).forEach((controllerName) => { %>
12
- export const <%= controllerName %> = createRPC(
13
- fullSchema, '<%= segment.segmentName %>', '<%= controllerName %>',
10
+ <% Object.values(t.fullSchema.segments).filter((segment) => segment.emitSchema).forEach((segment, i) => {
11
+ Object.keys(segment.controllers).forEach((rpcModuleName) => { %>
12
+ export const <%= rpcModuleName %> = createRPC(
13
+ fullSchema, '<%= segment.segmentName %>', '<%= rpcModuleName %>',
14
14
  { fetcher, validateOnClient, defaultOptions: { apiRoot: '<%= segment.segmentApiRoot ?? t.apiRoot %>' } }
15
15
  );
16
16
  <%
@@ -0,0 +1,41 @@
1
+ ---
2
+ imports: ['vovk-openapi']
3
+ ---
4
+ <% const vars = {
5
+ createCodeExamples: t.imports['vovk-openapi'].createCodeExamples,
6
+ }; %>
7
+
8
+ # <%= t.package.name %> v<%= t.package.version %>
9
+
10
+ <%- t.package.description ? `> ${t.package.description}` : '' %>
11
+
12
+ <%- t.package.license ? `License: **${t.package.license}**` : '' %>
13
+
14
+ ```bash
15
+ # Install the package
16
+ npm install <%= t.package.name.replace(/-/g, '_') %>
17
+ ```
18
+
19
+ <% Object.entries(t.fullSchema.segments).forEach(([segmentName, segment]) => {
20
+ Object.values(segment.controllers).forEach((controllerSchema) => { %>
21
+
22
+ ## <%= controllerSchema.rpcModuleName %>
23
+ <% Object.entries(controllerSchema.handlers).forEach(([handlerName, handlerSchema]) => { %>
24
+ ### <%= controllerSchema.rpcModuleName %>.<%= handlerName %>
25
+ <%- handlerSchema.openapi?.summary ? `> ${handlerSchema.openapi.summary}` : '' %>
26
+
27
+ <%- handlerSchema.openapi?.description ? `${handlerSchema.openapi.description}` : '' %>
28
+
29
+ Endpoint: <%= t.apiRoot %>/<%= segmentName %>/<%= controllerSchema.prefix %>/<%= handlerSchema.path %>
30
+
31
+ ```ts
32
+ <%- vars.createCodeExamples({
33
+ handlerSchema,
34
+ handlerName,
35
+ controllerSchema,
36
+ package: t.package,
37
+ }).ts %>
38
+ ```
39
+ <% }) %>
40
+ <% }) %>
41
+ <% }) %>
@@ -3,19 +3,19 @@ import type { VovkClientFetcher } from 'vovk';
3
3
  import { fetcher } from '<%= t.imports.fetcher %>';
4
4
  import { createRPC } from '<%= t.imports.createRPC %>';
5
5
  import { fullSchema } from './fullSchema.ts';
6
- <% Object.values(t.fullSchema.segments).forEach((segment, i) => { if(Object.keys(segment.controllers).length) { %>
6
+ <% Object.values(t.fullSchema.segments).filter((segment) => segment.emitSchema).forEach((segment, i) => { %>
7
7
  import type { Controllers as Controllers<%= i %> } from "<%= t.segmentMeta[segment.segmentName].segmentImportPath %>";
8
- <% }}) %>
8
+ <% }) %>
9
9
  <% if (t.imports.validateOnClient) { %>
10
10
  import { validateOnClient } from '<%= t.imports.validateOnClient %>';
11
11
  <% } else { %>
12
12
  const validateOnClient = undefined;
13
13
  <% } %>
14
14
  type Options = typeof fetcher extends VovkClientFetcher<infer U> ? U : never;
15
- <% Object.values(t.fullSchema.segments).forEach((segment, i) => { %>
16
- <% Object.keys(segment.controllers).forEach((controllerName) => { %>
17
- export const <%= controllerName %> = createRPC<Controllers<%= i %>["<%= controllerName %>"], Options>(
18
- fullSchema, '<%= segment.segmentName %>', '<%= controllerName %>',
15
+ <% Object.values(t.fullSchema.segments).filter((segment) => segment.emitSchema).forEach((segment, i) => { %>
16
+ <% Object.keys(segment.controllers).forEach((rpcModuleName) => { %>
17
+ export const <%= rpcModuleName %> = createRPC<Controllers<%= i %>["<%= rpcModuleName %>"], Options>(
18
+ fullSchema, '<%= segment.segmentName %>', '<%= rpcModuleName %>',
19
19
  { fetcher, validateOnClient, defaultOptions: { apiRoot: '<%= segment.segmentApiRoot ?? t.apiRoot %>' } }
20
20
  );
21
21
  <% }) %>
@@ -0,0 +1,8 @@
1
+ import type { VovkFullSchema } from 'vovk';
2
+ import type { ProjectInfo } from '../getProjectInfo/index.mjs';
3
+ import type { BundleOptions } from '../types.mjs';
4
+ export default function bundle({ projectInfo, fullSchema, cliBundleOptions, }: {
5
+ projectInfo: ProjectInfo;
6
+ fullSchema: VovkFullSchema;
7
+ cliBundleOptions?: BundleOptions;
8
+ }): Promise<void>;
@@ -0,0 +1,27 @@
1
+ import path from 'node:path';
2
+ import generate from '../generate/index.mjs';
3
+ import { BuiltInTemplateName } from '../getProjectInfo/getConfig/getTemplateDefs.mjs';
4
+ import { rollupBundle } from './rollupBundle.mjs';
5
+ export default async function bundle({ projectInfo, fullSchema, cliBundleOptions, }) {
6
+ const cwd = process.cwd();
7
+ const tsFullClientOutAbsoluteDirInput = path.join(cwd, projectInfo.config.bundle.tsClientOutDir);
8
+ await generate({
9
+ isEnsuringClient: false,
10
+ projectInfo,
11
+ forceNothingWrittenLog: true,
12
+ fullSchema,
13
+ cliGenerateOptions: {
14
+ fullClientFrom: [BuiltInTemplateName.ts],
15
+ fullClientOut: projectInfo.config.bundle.tsClientOutDir,
16
+ },
17
+ });
18
+ const outDir = cliBundleOptions?.outDir ?? projectInfo.config.bundle.outDir;
19
+ if (!outDir) {
20
+ throw new Error('No output directory specified for bundling');
21
+ }
22
+ await rollupBundle({
23
+ tsFullClientOutAbsoluteDirInput,
24
+ outDir,
25
+ cwd,
26
+ });
27
+ }
@@ -0,0 +1,5 @@
1
+ export declare function rollupBundle({ tsFullClientOutAbsoluteDirInput, outDir, cwd, }: {
2
+ tsFullClientOutAbsoluteDirInput: string;
3
+ outDir: string;
4
+ cwd: string;
5
+ }): Promise<void>;
@@ -0,0 +1,55 @@
1
+ import path from 'node:path';
2
+ import { rollup } from 'rollup';
3
+ import resolve from '@rollup/plugin-node-resolve';
4
+ import commonjs from '@rollup/plugin-commonjs';
5
+ import typescript from '@rollup/plugin-typescript';
6
+ import json from '@rollup/plugin-json';
7
+ function getRollupConfig({ tsFullClientOutAbsoluteDirInput, outDir, cwd, }) {
8
+ const out = path.join(cwd, outDir);
9
+ const config = {
10
+ input: path.join(tsFullClientOutAbsoluteDirInput, './index.ts'),
11
+ output: [
12
+ {
13
+ file: path.join(out, './index.cjs'),
14
+ format: 'cjs',
15
+ sourcemap: true,
16
+ },
17
+ {
18
+ file: path.join(out, './index.mjs'),
19
+ format: 'esm',
20
+ sourcemap: true,
21
+ },
22
+ ],
23
+ plugins: [
24
+ resolve(),
25
+ commonjs(),
26
+ json(),
27
+ typescript({
28
+ declaration: true,
29
+ declarationDir: out,
30
+ outDir: cwd,
31
+ rootDir: tsFullClientOutAbsoluteDirInput,
32
+ module: 'ESNext',
33
+ target: 'ESNext',
34
+ experimentalDecorators: true,
35
+ emitDecoratorMetadata: true,
36
+ allowImportingTsExtensions: true,
37
+ noForceEmit: false,
38
+ }),
39
+ ],
40
+ };
41
+ return config;
42
+ }
43
+ export async function rollupBundle({ tsFullClientOutAbsoluteDirInput, outDir, cwd, }) {
44
+ const { output, ...input } = getRollupConfig({
45
+ tsFullClientOutAbsoluteDirInput,
46
+ outDir,
47
+ cwd,
48
+ });
49
+ console.log({ input });
50
+ const bundle = await rollup(input);
51
+ for (const outputOption of output) {
52
+ await bundle.write(outputOption);
53
+ }
54
+ await bundle.close();
55
+ }
@@ -1,6 +1,6 @@
1
1
  import type { VovkStrictConfig } from 'vovk';
2
2
  import type { ProjectInfo } from '../getProjectInfo/index.mjs';
3
- import { type GenerateOptions } from '../types.mjs';
3
+ import type { GenerateOptions } from '../types.mjs';
4
4
  export interface ClientTemplateFile {
5
5
  templateName: string;
6
6
  templateFilePath: string;
@@ -8,10 +8,13 @@ export interface ClientTemplateFile {
8
8
  outCwdRelativeDir: string;
9
9
  templateDef: VovkStrictConfig['clientTemplateDefs'][string];
10
10
  }
11
- export default function getClientTemplateFiles({ config, cwd, log, configKey, cliOptions, }: {
11
+ export default function getClientTemplateFiles({ config, cwd, log, configKey, cliGenerateOptions, }: {
12
12
  config: VovkStrictConfig;
13
13
  cwd: string;
14
14
  log: ProjectInfo['log'];
15
15
  configKey: 'fullClient' | 'segmentedClient';
16
- cliOptions?: GenerateOptions;
17
- }): Promise<ClientTemplateFile[]>;
16
+ cliGenerateOptions?: GenerateOptions;
17
+ }): Promise<{
18
+ fromTemplates: string[];
19
+ templateFiles: ClientTemplateFile[];
20
+ }>;
@@ -2,14 +2,18 @@ import path from 'node:path';
2
2
  import { glob } from 'glob';
3
3
  import resolveAbsoluteModulePath from '../utils/resolveAbsoluteModulePath.mjs';
4
4
  import getFileSystemEntryType, { FileSystemEntryType } from '../utils/getFileSystemEntryType.mjs';
5
- export default async function getClientTemplateFiles({ config, cwd, log, configKey, cliOptions, }) {
5
+ export default async function getClientTemplateFiles({ config, cwd, log, configKey, cliGenerateOptions, }) {
6
6
  const usedTemplateDefs = {};
7
7
  const fromTemplates = configKey === 'fullClient'
8
- ? (cliOptions?.fullClientFrom ?? config.fullClient.fromTemplates)
9
- : (cliOptions?.segmentedClientFrom ?? config.segmentedClient.fromTemplates);
8
+ ? cliGenerateOptions?.fullClientFrom || cliGenerateOptions?.segmentedClientFrom
9
+ ? (cliGenerateOptions?.fullClientFrom ?? [])
10
+ : config.fullClient.fromTemplates
11
+ : cliGenerateOptions?.fullClientFrom || cliGenerateOptions?.segmentedClientFrom
12
+ ? (cliGenerateOptions?.segmentedClientFrom ?? [])
13
+ : config.segmentedClient.fromTemplates;
10
14
  const outDir = configKey === 'fullClient'
11
- ? (cliOptions?.fullClientOut ?? config.fullClient.outDir)
12
- : (cliOptions?.segmentedClientOut ?? config.segmentedClient.outDir);
15
+ ? (cliGenerateOptions?.fullClientOut ?? config.fullClient.outDir)
16
+ : (cliGenerateOptions?.segmentedClientOut ?? config.segmentedClient.outDir);
13
17
  for (const templateName of fromTemplates) {
14
18
  if (!(templateName in config.clientTemplateDefs)) {
15
19
  throw new Error(`Unknown template name: ${templateName}`);
@@ -20,42 +24,46 @@ export default async function getClientTemplateFiles({ config, cwd, log, configK
20
24
  const entries = Object.entries(usedTemplateDefs);
21
25
  for (let i = 0; i < entries.length; i++) {
22
26
  const [templateName, templateDef, forceOutCwdRelativeDir] = entries[i];
23
- const templateAbsolutePath = resolveAbsoluteModulePath(templateDef.templatePath, cwd);
24
- const entryType = await getFileSystemEntryType(templateDef.templatePath);
25
- if (!entryType)
27
+ const templateAbsolutePath = templateDef.templatePath
28
+ ? resolveAbsoluteModulePath(templateDef.templatePath, cwd)
29
+ : null;
30
+ const entryType = templateDef.templatePath ? await getFileSystemEntryType(templateDef.templatePath) : null;
31
+ if (templateAbsolutePath && !entryType)
26
32
  throw new Error(`Unable to locate template path ${templateDef.templatePath}`);
27
33
  const defOutDir = configKey === 'fullClient' ? templateDef.fullClient?.outDir : templateDef.segmentedClient?.outDir;
28
- let files;
29
- if (entryType === FileSystemEntryType.FILE) {
30
- files = [templateAbsolutePath];
31
- }
32
- else {
33
- const globPath = path.join(templateAbsolutePath, '**/*.*');
34
- files = await glob(globPath);
35
- }
36
- if (files.length === 0) {
37
- log.error(`Template "${templateAbsolutePath}" not found`);
38
- continue;
39
- }
40
- const outCwdRelativeDir = forceOutCwdRelativeDir ?? defOutDir ?? outDir;
41
- for (const filePath of files) {
42
- templateFiles.push({
43
- templateName,
44
- templateFilePath: filePath,
45
- relativeDir: path.relative(templateAbsolutePath, path.dirname(filePath)),
46
- outCwdRelativeDir,
47
- templateDef,
48
- });
49
- }
50
- if (templateDef.requires) {
51
- for (const [tName, reqRelativeDir] of Object.entries(templateDef.requires)) {
52
- const def = config.clientTemplateDefs[tName];
53
- if (!def) {
54
- throw new Error(`Template "${tName}" required by "${templateName}" not found`);
34
+ let files = [];
35
+ if (templateAbsolutePath) {
36
+ if (entryType === FileSystemEntryType.FILE) {
37
+ files = [templateAbsolutePath];
38
+ }
39
+ else {
40
+ const globPath = path.join(templateAbsolutePath, '**/*.*');
41
+ files = await glob(globPath);
42
+ }
43
+ if (files.length === 0) {
44
+ log.error(`Template "${templateAbsolutePath}" not found`);
45
+ continue;
46
+ }
47
+ const outCwdRelativeDir = forceOutCwdRelativeDir ?? defOutDir ?? outDir;
48
+ for (const filePath of files) {
49
+ templateFiles.push({
50
+ templateName,
51
+ templateFilePath: filePath,
52
+ relativeDir: path.relative(templateAbsolutePath, path.dirname(filePath) + '/'),
53
+ outCwdRelativeDir,
54
+ templateDef,
55
+ });
56
+ }
57
+ if (templateDef.requires) {
58
+ for (const [tName, reqRelativeDir] of Object.entries(templateDef.requires)) {
59
+ const def = config.clientTemplateDefs[tName];
60
+ if (!def) {
61
+ throw new Error(`Template "${tName}" required by "${templateName}" not found`);
62
+ }
63
+ entries.push([tName, def, path.join(outCwdRelativeDir, reqRelativeDir)]);
55
64
  }
56
- entries.push([tName, def, path.join(outCwdRelativeDir, reqRelativeDir)]);
57
65
  }
58
66
  }
59
67
  }
60
- return templateFiles;
68
+ return { fromTemplates, templateFiles };
61
69
  }
@@ -1,10 +1,10 @@
1
1
  import type { VovkFullSchema } from 'vovk';
2
2
  import type { ProjectInfo } from '../getProjectInfo/index.mjs';
3
3
  import type { GenerateOptions } from '../types.mjs';
4
- export default function generate({ isEnsuringClient, projectInfo, forceNothingWrittenLog, fullSchema, cliOptions, }: {
4
+ export default function generate({ isEnsuringClient, projectInfo, forceNothingWrittenLog, fullSchema, cliGenerateOptions, }: {
5
5
  isEnsuringClient?: boolean;
6
6
  projectInfo: ProjectInfo;
7
7
  forceNothingWrittenLog?: boolean;
8
8
  fullSchema: VovkFullSchema;
9
- cliOptions?: GenerateOptions;
9
+ cliGenerateOptions?: GenerateOptions;
10
10
  }): Promise<void>;
@@ -32,7 +32,7 @@ const getIncludedSegmentNames = (config, segments, configKey) => {
32
32
  : segments.map(({ segmentName }) => segmentName);
33
33
  return includedSegmentNames;
34
34
  };
35
- function logClientGenerationResults({ results, log, isEnsuringClient = false, forceNothingWrittenLog = false, clientType = 'Full', startTime, }) {
35
+ function logClientGenerationResults({ results, log, isEnsuringClient = false, forceNothingWrittenLog = false, clientType = 'Full', startTime, fromTemplates, }) {
36
36
  const writtenResults = results.filter(({ written }) => written);
37
37
  const duration = Date.now() - startTime;
38
38
  if (writtenResults.length) {
@@ -42,12 +42,12 @@ function logClientGenerationResults({ results, log, isEnsuringClient = false, fo
42
42
  log.info(`${clientType} client${isEnsuringClient ? ' placeholder' : ''} is generated to ${chalkHighlightThing(outAbsoluteDir)} from template${templateNames.length !== 1 ? 's' : ''} ${chalkHighlightThing(templateNames.map((s) => `"${s}"`).join(', '))} in ${duration}ms`);
43
43
  }
44
44
  }
45
- else if (!isEnsuringClient) {
45
+ else if (!isEnsuringClient && fromTemplates.length) {
46
46
  const logOrDebug = forceNothingWrittenLog ? log.info : log.debug;
47
47
  logOrDebug(`${clientType} client is up to date and doesn't need to be regenerated (${duration}ms)`);
48
48
  }
49
49
  }
50
- export default async function generate({ isEnsuringClient = false, projectInfo, forceNothingWrittenLog, fullSchema, cliOptions, }) {
50
+ export default async function generate({ isEnsuringClient = false, projectInfo, forceNothingWrittenLog, fullSchema, cliGenerateOptions, }) {
51
51
  const { config, cwd, log, segments } = projectInfo;
52
52
  // Ensure that each segment has a matching schema if it needs to be emitted:
53
53
  for (let i = 0; i < segments.length; i++) {
@@ -62,11 +62,11 @@ export default async function generate({ isEnsuringClient = false, projectInfo,
62
62
  if (config.fullClient.enabled) {
63
63
  const now = Date.now();
64
64
  const segmentNames = getIncludedSegmentNames(config, segments, 'fullClient');
65
- const fullClientTemplateFiles = await getClientTemplateFiles({
65
+ const { templateFiles: fullClientTemplateFiles, fromTemplates } = await getClientTemplateFiles({
66
66
  config,
67
67
  cwd,
68
68
  log,
69
- cliOptions,
69
+ cliGenerateOptions,
70
70
  configKey: 'fullClient',
71
71
  });
72
72
  const fullClientResults = await Promise.all(fullClientTemplateFiles.map(async (clientTemplateFile) => {
@@ -115,16 +115,17 @@ export default async function generate({ isEnsuringClient = false, projectInfo,
115
115
  forceNothingWrittenLog,
116
116
  clientType: 'Full',
117
117
  startTime: now,
118
+ fromTemplates,
118
119
  });
119
120
  }
120
121
  if (config.segmentedClient.enabled) {
121
122
  const now = Date.now();
122
123
  const segmentNames = getIncludedSegmentNames(config, segments, 'segmentedClient');
123
- const segmentedClientTemplateFiles = await getClientTemplateFiles({
124
+ const { templateFiles: segmentedClientTemplateFiles, fromTemplates } = await getClientTemplateFiles({
124
125
  config,
125
126
  cwd,
126
127
  log,
127
- cliOptions,
128
+ cliGenerateOptions,
128
129
  configKey: 'segmentedClient',
129
130
  });
130
131
  const segmentedClientResults = await Promise.all(segmentedClientTemplateFiles.map(async (clientTemplateFile) => {
@@ -184,6 +185,7 @@ export default async function generate({ isEnsuringClient = false, projectInfo,
184
185
  forceNothingWrittenLog,
185
186
  clientType: 'Segmented',
186
187
  startTime: now,
188
+ fromTemplates,
187
189
  });
188
190
  }
189
191
  }
@@ -1,9 +1,11 @@
1
1
  import type { VovkStrictConfig } from 'vovk';
2
2
  export declare enum BuiltInTemplateName {
3
3
  ts = "ts",
4
- main = "main",
5
- module = "module",
6
- package = "package",
4
+ cjs = "cjs",
5
+ mjs = "mjs",
6
+ dts = "dts",
7
+ readme = "readme",
8
+ packageJson = "packageJson",
7
9
  fullSchemaTs = "fullSchemaTs",
8
10
  fullSchemaCjs = "fullSchemaCjs",
9
11
  fullSchemaJson = "fullSchemaJson"
@@ -2,9 +2,11 @@ import path from 'node:path';
2
2
  export var BuiltInTemplateName;
3
3
  (function (BuiltInTemplateName) {
4
4
  BuiltInTemplateName["ts"] = "ts";
5
- BuiltInTemplateName["main"] = "main";
6
- BuiltInTemplateName["module"] = "module";
7
- BuiltInTemplateName["package"] = "package";
5
+ BuiltInTemplateName["cjs"] = "cjs";
6
+ BuiltInTemplateName["mjs"] = "mjs";
7
+ BuiltInTemplateName["dts"] = "dts";
8
+ BuiltInTemplateName["readme"] = "readme";
9
+ BuiltInTemplateName["packageJson"] = "packageJson";
8
10
  BuiltInTemplateName["fullSchemaTs"] = "fullSchemaTs";
9
11
  BuiltInTemplateName["fullSchemaCjs"] = "fullSchemaCjs";
10
12
  BuiltInTemplateName["fullSchemaJson"] = "fullSchemaJson";
@@ -18,18 +20,27 @@ export default function getTemplateDefs(userTemplateDefs = {}) {
18
20
  origin: null,
19
21
  requires: { [BuiltInTemplateName.fullSchemaTs]: '.' },
20
22
  },
21
- [BuiltInTemplateName.main]: {
22
- templatePath: path.resolve(templatesDir, 'main/'),
23
+ [BuiltInTemplateName.cjs]: {
24
+ templatePath: path.resolve(templatesDir, 'cjs/'),
23
25
  origin: null,
24
- requires: { [BuiltInTemplateName.fullSchemaCjs]: '.' },
26
+ requires: { [BuiltInTemplateName.fullSchemaCjs]: '.', [BuiltInTemplateName.dts]: '.' },
27
+ },
28
+ [BuiltInTemplateName.mjs]: {
29
+ templatePath: path.resolve(templatesDir, 'mjs/'),
30
+ origin: null,
31
+ requires: { [BuiltInTemplateName.fullSchemaCjs]: '.', [BuiltInTemplateName.dts]: '.' },
25
32
  },
26
- [BuiltInTemplateName.module]: {
27
- templatePath: path.resolve(templatesDir, 'module/'),
33
+ [BuiltInTemplateName.dts]: {
34
+ templatePath: path.resolve(templatesDir, 'mjs/'),
28
35
  origin: null,
29
36
  requires: { [BuiltInTemplateName.fullSchemaCjs]: '.' },
30
37
  },
31
- [BuiltInTemplateName.package]: {
32
- templatePath: path.resolve(templatesDir, 'package/'),
38
+ [BuiltInTemplateName.readme]: {
39
+ templatePath: path.resolve(templatesDir, 'readme/'),
40
+ origin: null,
41
+ },
42
+ [BuiltInTemplateName.packageJson]: {
43
+ templatePath: path.resolve(templatesDir, 'packageJson/'),
33
44
  origin: null,
34
45
  },
35
46
  [BuiltInTemplateName.fullSchemaTs]: {
@@ -1,7 +1,8 @@
1
1
  import type { VovkStrictConfig } from 'vovk';
2
- import type { GenerateOptions } from '../../types.mjs';
3
- export default function getConfig({ cliOptions, cwd }: {
4
- cliOptions?: GenerateOptions;
2
+ import type { BundleOptions, GenerateOptions } from '../../types.mjs';
3
+ export default function getConfig({ cliGenerateOptions, cliBundleOptions, cwd, }: {
4
+ cliGenerateOptions?: GenerateOptions;
5
+ cliBundleOptions?: BundleOptions;
5
6
  cwd: string;
6
7
  }): Promise<{
7
8
  config: VovkStrictConfig;
@@ -2,8 +2,11 @@ import path from 'node:path';
2
2
  import getUserConfig from '../getUserConfig.mjs';
3
3
  import getRelativeSrcRoot from '../getRelativeSrcRoot.mjs';
4
4
  import getTemplateDefs from './getTemplateDefs.mjs';
5
- export default async function getConfig({ cliOptions, cwd }) {
6
- const { configAbsolutePaths, error, userConfig } = await getUserConfig({ configPath: cliOptions?.config, cwd });
5
+ export default async function getConfig({ cliGenerateOptions, cliBundleOptions, cwd, }) {
6
+ const { configAbsolutePaths, error, userConfig } = await getUserConfig({
7
+ configPath: cliGenerateOptions?.config,
8
+ cwd,
9
+ });
7
10
  const conf = userConfig ?? {};
8
11
  const env = process.env;
9
12
  const clientTemplateDefs = getTemplateDefs(conf.clientTemplateDefs);
@@ -25,14 +28,21 @@ export default async function getConfig({ cliOptions, cwd }) {
25
28
  fullClient: {
26
29
  enabled: true,
27
30
  ...conf.fullClient,
28
- fromTemplates: cliOptions?.fullClientFrom ?? conf.fullClient?.fromTemplates ?? ['module', 'main'],
29
- outDir: cliOptions?.fullClientOut ?? conf.fullClient?.outDir ?? './node_modules/.vovk-client',
31
+ fromTemplates: cliGenerateOptions?.fullClientFrom ?? conf.fullClient?.fromTemplates ?? ['mjs', 'cjs'],
32
+ outDir: cliGenerateOptions?.fullClientOut ?? conf.fullClient?.outDir ?? './node_modules/.vovk-client',
30
33
  },
31
34
  segmentedClient: {
32
35
  enabled: false,
33
36
  ...conf.segmentedClient,
34
- fromTemplates: cliOptions?.segmentedClientFrom ?? conf.segmentedClient?.fromTemplates ?? ['ts'],
35
- outDir: cliOptions?.segmentedClientOut ?? conf.segmentedClient?.outDir ?? path.join(srcRoot, 'client'),
37
+ fromTemplates: cliGenerateOptions?.segmentedClientFrom ?? conf.segmentedClient?.fromTemplates ?? ['ts'],
38
+ outDir: cliGenerateOptions?.segmentedClientOut ?? conf.segmentedClient?.outDir ?? path.join(srcRoot, 'client'),
39
+ },
40
+ bundle: {
41
+ outDir: cliBundleOptions?.outDir ?? conf.bundle?.outDir ?? path.join(srcRoot, 'dist'),
42
+ tsClientOutDir: cliBundleOptions?.tsClientOutDir ?? conf.bundle?.tsClientOutDir ?? '.tmp-ts-rpc',
43
+ dontDeleteTsClientOutDirAfter: cliBundleOptions?.dontDeleteTsClientOutDirAfter ?? conf.bundle?.dontDeleteTsClientOutDirAfter ?? true,
44
+ noReadme: cliBundleOptions?.noReadme ?? conf.bundle?.noReadme ?? false,
45
+ noPackage: cliBundleOptions?.noPackage ?? conf.bundle?.noPackage ?? false,
36
46
  },
37
47
  modulesDir: env.VOVK_MODULES_DIR ?? conf.modulesDir ?? './' + [srcRoot, 'modules'].filter(Boolean).join('/'),
38
48
  schemaOutDir: env.VOVK_SCHEMA_OUT_DIR ?? conf.schemaOutDir ?? './.vovk-schema',
@@ -1,14 +1,11 @@
1
1
  // importUncachedModule.js
2
2
  import { Worker } from 'node:worker_threads';
3
3
  import path from 'node:path';
4
- import { fileURLToPath } from 'node:url';
5
4
  import './importUncachedModuleWorker.mjs'; // required for TS compilation
6
5
  function importUncachedModule(modulePath) {
7
6
  return new Promise((resolve, reject) => {
8
- const __filename = fileURLToPath(import.meta.url);
9
- const __dirname = path.dirname(__filename);
10
7
  // Resolve the path to the worker script
11
- const workerPath = path.resolve(__dirname, 'importUncachedModuleWorker.mjs');
8
+ const workerPath = path.resolve(import.meta.dirname, 'importUncachedModuleWorker.mjs');
12
9
  // Initialize the worker thread
13
10
  const worker = new Worker(workerPath, {
14
11
  workerData: { modulePath },
@@ -1,9 +1,10 @@
1
- import type { GenerateOptions } from '../types.mjs';
1
+ import type { BundleOptions, GenerateOptions } from '../types.mjs';
2
2
  export type ProjectInfo = Awaited<ReturnType<typeof getProjectInfo>>;
3
- export default function getProjectInfo({ port: givenPort, cwd, cliOptions, }?: {
3
+ export default function getProjectInfo({ port: givenPort, cwd, cliGenerateOptions, cliBundleOptions, }?: {
4
4
  port?: number;
5
5
  cwd?: string;
6
- cliOptions?: GenerateOptions;
6
+ cliGenerateOptions?: GenerateOptions;
7
+ cliBundleOptions?: BundleOptions;
7
8
  }): Promise<{
8
9
  cwd: string;
9
10
  port: string;
@@ -2,12 +2,13 @@ import path from 'node:path';
2
2
  import getConfig from './getConfig/index.mjs';
3
3
  import getLogger from '../utils/getLogger.mjs';
4
4
  import locateSegments from '../locateSegments.mjs';
5
- export default async function getProjectInfo({ port: givenPort, cwd = process.cwd(), cliOptions, } = {}) {
5
+ export default async function getProjectInfo({ port: givenPort, cwd = process.cwd(), cliGenerateOptions, cliBundleOptions, } = {}) {
6
6
  const port = givenPort?.toString() ?? process.env.PORT ?? '3000';
7
7
  // Make PORT available to the config file at getConfig
8
8
  process.env.PORT = port;
9
9
  const { config, srcRoot, configAbsolutePaths, userConfig, error } = await getConfig({
10
- cliOptions,
10
+ cliGenerateOptions,
11
+ cliBundleOptions,
11
12
  cwd,
12
13
  });
13
14
  const apiRoot = `${config.origin ?? ''}/${config.rootEntry}`;
package/dist/index.d.mts CHANGED
@@ -1,2 +1,4 @@
1
1
  #!/usr/bin/env node
2
2
  import 'dotenv/config';
3
+ import type { VovkEnv } from './types.mjs';
4
+ export type { VovkEnv };
package/dist/index.mjs CHANGED
@@ -7,6 +7,7 @@ import concurrently from 'concurrently';
7
7
  import getAvailablePort from './utils/getAvailablePort.mjs';
8
8
  import getProjectInfo from './getProjectInfo/index.mjs';
9
9
  import generate from './generate/index.mjs';
10
+ import bundle from './bundle/index.mjs';
10
11
  import { VovkDev } from './dev/index.mjs';
11
12
  import newComponents from './new/index.mjs';
12
13
  import initProgram from './initProgram.mjs';
@@ -78,8 +79,8 @@ program
78
79
  .option('--segment-client-from <templates...>', 'client template names for segment client')
79
80
  .option('--prettify', 'prettify output files')
80
81
  .option('--config <config>', 'path to config file')
81
- .action(async (cliOptions) => {
82
- const projectInfo = await getProjectInfo({ cliOptions });
82
+ .action(async (cliGenerateOptions) => {
83
+ const projectInfo = await getProjectInfo({ cliGenerateOptions });
83
84
  const { cwd, config } = projectInfo;
84
85
  const schemaOutAbsolutePath = path.join(cwd, config.schemaOutDir);
85
86
  const fullSchema = await getFullSchemaFromJSON(schemaOutAbsolutePath, projectInfo);
@@ -87,7 +88,28 @@ program
87
88
  projectInfo,
88
89
  fullSchema,
89
90
  forceNothingWrittenLog: true,
90
- cliOptions,
91
+ cliGenerateOptions,
92
+ });
93
+ });
94
+ program
95
+ .command('bundle')
96
+ .alias('b')
97
+ .description('Generate TypeScrtipt RPC and bundle it')
98
+ .option('--out, --out-dir <path>', 'path to output directory for bundle')
99
+ .option('--ts-client-out-dir <path>', 'path to output directory for TypeScript client')
100
+ .option('--no-readme', 'do not generate README file')
101
+ .option('--no-package', 'do not generate package.json file')
102
+ .option('--dont-delete-ts-client-out-dir-after', 'do not delete TypeScript client output directory after bundling')
103
+ .option('--config <config>', 'path to config file')
104
+ .action(async (cliBundleOptions) => {
105
+ const projectInfo = await getProjectInfo({ cliBundleOptions });
106
+ const { cwd, config } = projectInfo;
107
+ const schemaOutAbsolutePath = path.join(cwd, config.schemaOutDir);
108
+ const fullSchema = await getFullSchemaFromJSON(schemaOutAbsolutePath, projectInfo);
109
+ await bundle({
110
+ projectInfo,
111
+ fullSchema,
112
+ cliBundleOptions,
91
113
  });
92
114
  });
93
115
  program
@@ -100,7 +122,8 @@ program
100
122
  .option('--empty', 'create an empty module')
101
123
  .option('--no-segment-update', 'do not update segment files when creating a new module')
102
124
  .option('--dry-run', 'do not write files to disk')
103
- .action((components, options) => newComponents(components, options));
125
+ .option('--static', 'if the segment is static')
126
+ .action((components, newOptions) => newComponents(components, newOptions));
104
127
  program
105
128
  .command('help')
106
129
  .description('Show help message')
@@ -17,10 +17,7 @@ export default async function createConfig({ root, log, options: { validationLib
17
17
  };
18
18
  if (validationLibrary) {
19
19
  config.imports ??= {};
20
- config.imports.validateOnClient =
21
- {
22
- 'vovk-dto': `vovk-dto/validateOnClient.js`,
23
- }[validationLibrary] ?? 'vovk-ajv';
20
+ config.imports.validateOnClient = 'vovk-ajv';
24
21
  try {
25
22
  const validationTemplates = await getTemplateFilesFromPackage(validationLibrary, channel);
26
23
  Object.assign(moduleTemplates, validationTemplates);
@@ -35,7 +32,7 @@ export default async function createConfig({ root, log, options: { validationLib
35
32
  }
36
33
  config.moduleTemplates = moduleTemplates;
37
34
  const configStr = await prettify(`// @ts-check
38
- /** @type {import('vovk-cli').VovkConfig} */
35
+ /** @type {import('vovk').VovkConfig} */
39
36
  const config = ${JSON.stringify(config, null, 2)};
40
37
  ${isModule ? '\nexport default config;' : 'module.exports = config;'}`, configAbsolutePath);
41
38
  if (!dryRun)
@@ -2,7 +2,6 @@ import { Readable } from 'node:stream';
2
2
  import { createGunzip } from 'node:zlib';
3
3
  import tar from 'tar-stream';
4
4
  import getNPMPackageMetadata from '../utils/getNPMPackageMetadata.mjs';
5
- // Crereated with AI
6
5
  /**
7
6
  * Retrieves a list of files in the 'templates' folder of an NPM package.
8
7
  * @param packageName - The name of the NPM package.
@@ -1,2 +1,2 @@
1
1
  import type { NewOptions } from '../types.mjs';
2
- export default function newComponents(components: string[], { dryRun, dir, templates, overwrite, noSegmentUpdate, empty }: NewOptions): Promise<void>;
2
+ export default function newComponents(components: string[], { 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, empty }) {
3
+ export default async function newComponents(components, { 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({ segmentName, isStaticSegment, overwrite, dryRun });
14
14
  }
15
15
  }
16
16
  else {
@@ -93,7 +93,9 @@ export default async function newModule({ what, moduleNameWithOptionalSegment, d
93
93
  }
94
94
  const { routeFilePath } = segment;
95
95
  const segmentSourceCode = await fs.readFile(routeFilePath, 'utf-8');
96
- const importPath = path.relative(path.dirname(routeFilePath), absoluteModulePath).replace(/\.(ts|tsx)$/, '');
96
+ const importPath = path
97
+ .relative(path.dirname(routeFilePath) + '/', absoluteModulePath)
98
+ .replace(/\.(ts|tsx)$/, '');
97
99
  if (!noSegmentUpdate) {
98
100
  const newSegmentCode = await prettify(addClassToSegmentCode(segmentSourceCode, {
99
101
  sourceName,
@@ -1,5 +1,6 @@
1
- export default function newSegment({ segmentName, overwrite, dryRun, }: {
1
+ export default function newSegment({ segmentName, isStaticSegment, overwrite, dryRun, }: {
2
2
  segmentName: string;
3
+ isStaticSegment?: boolean;
3
4
  overwrite?: boolean;
4
5
  dryRun?: boolean;
5
6
  }): Promise<void>;
@@ -6,20 +6,24 @@ import chalkHighlightThing from '../utils/chalkHighlightThing.mjs';
6
6
  import formatLoggedSegmentName from '../utils/formatLoggedSegmentName.mjs';
7
7
  import prettify from '../utils/prettify.mjs';
8
8
  import chalk from 'chalk';
9
- export default async function newSegment({ segmentName, overwrite, dryRun, }) {
9
+ export default async function newSegment({ segmentName, isStaticSegment, overwrite, dryRun, }) {
10
10
  const { apiDir, cwd, log } = await getProjectInfo();
11
11
  const absoluteSegmentRoutePath = path.join(cwd, apiDir, segmentName, '[[...vovk]]/route.ts');
12
12
  if (!overwrite && (await getFileSystemEntryType(absoluteSegmentRoutePath))) {
13
13
  throw new Error(`Unable to create new segment. ${formatLoggedSegmentName(segmentName, { upperFirst: true })} already exists.`);
14
14
  }
15
- const code = await prettify(`import { initVovk } from 'vovk';
15
+ const code = await prettify(`import { initVovk${isStaticSegment ? ', generateStaticAPI' : ''} } from 'vovk';
16
16
 
17
17
  export const runtime = 'edge';
18
18
 
19
19
  const controllers = {};
20
20
 
21
21
  export type Controllers = typeof controllers;
22
-
22
+ ${isStaticSegment
23
+ ? `export function generateStaticParams() {
24
+ return generateStaticAPI(controllers);
25
+ }`
26
+ : ''}
23
27
  export const { GET, POST, PATCH, PUT, HEAD, OPTIONS, DELETE } = initVovk({
24
28
  ${segmentName ? ` segmentName: '${segmentName}',\n` : ''} emitSchema: true,
25
29
  controllers,
package/dist/types.d.mts CHANGED
@@ -1,4 +1,5 @@
1
1
  import type { LogLevelNames } from 'loglevel';
2
+ import type { VovkStrictConfig } from 'vovk';
2
3
  export type VovkModuleRenderResult = {
3
4
  fileName: string;
4
5
  dir: string;
@@ -18,6 +19,9 @@ export interface GenerateOptions {
18
19
  segmentedClientFrom?: string[];
19
20
  segmentedClientOut?: string;
20
21
  }
22
+ export interface BundleOptions extends Partial<VovkStrictConfig['bundle']> {
23
+ config?: string;
24
+ }
21
25
  export interface InitOptions {
22
26
  yes?: boolean;
23
27
  logLevel: LogLevelNames;
@@ -40,4 +44,22 @@ export interface NewOptions {
40
44
  overwrite?: boolean;
41
45
  noSegmentUpdate?: boolean;
42
46
  empty?: boolean;
47
+ static?: boolean;
43
48
  }
49
+ export type VovkEnv = {
50
+ PORT?: string;
51
+ VOVK_SCHEMA_OUT_DIR?: string;
52
+ VOVK_IMPORTS_FETCHER?: string;
53
+ VOVK_IMPORTS_VALIDATE_ON_CLIENT?: string;
54
+ VOVK_IMPORTS_CREATE_RPC?: string;
55
+ VOVK_MODULES_DIR?: string;
56
+ VOVK_ORIGIN?: string;
57
+ VOVK_ROOT_ENTRY?: string;
58
+ VOVK_API_ENTRY_POINT?: string;
59
+ VOVK_ROOT_SEGMENT_MODULES_DIR_NAME?: string;
60
+ VOVK_LOG_LEVEL?: LogLevelNames;
61
+ VOVK_PRETTIFY_CLIENT?: string;
62
+ VOVK_DEV_HTTPS?: string;
63
+ __VOVK_START_WATCHER_IN_STANDALONE_MODE__?: 'true';
64
+ __VOVK_EXIT__?: 'true' | 'false';
65
+ };
@@ -1,11 +1,11 @@
1
1
  <% const vars = {
2
- ControllerName: t.TheThing + 'Controller',
2
+ rpcModuleName: t.TheThing + 'Controller',
3
3
  ServiceName: t.TheThing + 'Service',
4
4
  }; %>
5
5
  ---
6
6
  dir: <%= t.defaultDir %>
7
- fileName: <%= vars.ControllerName + '.ts' %>
8
- sourceName: <%= vars.ControllerName %>
7
+ fileName: <%= vars.rpcModuleName + '.ts' %>
8
+ sourceName: <%= vars.rpcModuleName %>
9
9
  compiledName: <%= t.TheThing + 'RPC' %>
10
10
  ---
11
11
 
@@ -15,7 +15,7 @@ import <%= vars.ServiceName %> from './<%= vars.ServiceName %>';
15
15
  <% } %>
16
16
 
17
17
  @prefix('<%= t['the-things'] %>')
18
- export default class <%= vars.ControllerName %> {
18
+ export default class <%= vars.rpcModuleName %> {
19
19
  @get()
20
20
  static get<%= t.TheThings %> = async (req: VovkRequest<null, { search: string }>) => {
21
21
  const search = req.nextUrl.searchParams.get('search');
@@ -1,5 +1,5 @@
1
1
  <% const vars = {
2
- ControllerName: t.TheThing + 'Controller',
2
+ rpcModuleName: t.TheThing + 'Controller',
3
3
  ServiceName: t.TheThing + 'Service',
4
4
  }; %>
5
5
  ---
@@ -9,17 +9,17 @@ sourceName: <%= vars.ServiceName %>
9
9
  ---
10
10
 
11
11
  import type { VovkControllerBody, VovkControllerQuery } from 'vovk';
12
- import type <%= vars.ControllerName %> from './<%= vars.ControllerName %>';
12
+ import type <%= vars.rpcModuleName %> from './<%= vars.rpcModuleName %>';
13
13
 
14
14
  export default class <%= vars.ServiceName %> {
15
- static get<%= t.TheThings %> = (search: VovkControllerQuery<typeof <%= vars.ControllerName %>.get<%= t.TheThings %>>['search']) => {
15
+ static get<%= t.TheThings %> = (search: VovkControllerQuery<typeof <%= vars.rpcModuleName %>.get<%= t.TheThings %>>['search']) => {
16
16
  return { results: [], search };
17
17
  };
18
18
 
19
19
  static update<%= t.TheThing %> = (
20
20
  id: string,
21
- q: VovkControllerQuery<typeof <%= vars.ControllerName %>.update<%= t.TheThing %>>['q'],
22
- body: VovkControllerBody<typeof <%= vars.ControllerName %>.update<%= t.TheThing %>>
21
+ q: VovkControllerQuery<typeof <%= vars.rpcModuleName %>.update<%= t.TheThing %>>['q'],
22
+ body: VovkControllerBody<typeof <%= vars.rpcModuleName %>.update<%= t.TheThing %>>
23
23
  ) => {
24
24
  return { id, q, body };
25
25
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vovk-cli",
3
- "version": "0.0.1-draft.147",
3
+ "version": "0.0.1-draft.149",
4
4
  "bin": {
5
5
  "vovk": "./dist/index.mjs"
6
6
  },
@@ -35,7 +35,7 @@
35
35
  },
36
36
  "homepage": "https://vovk.dev",
37
37
  "peerDependencies": {
38
- "vovk": "^3.0.0-draft.119"
38
+ "vovk": "^3.0.0-draft.120"
39
39
  },
40
40
  "optionalDependencies": {
41
41
  "vovk-python-client": "^0.0.1-draft.15"
@@ -43,6 +43,10 @@
43
43
  "dependencies": {
44
44
  "@inquirer/prompts": "^7.5.0",
45
45
  "@npmcli/package-json": "^6.1.1",
46
+ "@rollup/plugin-commonjs": "^28.0.3",
47
+ "@rollup/plugin-json": "^6.1.0",
48
+ "@rollup/plugin-node-resolve": "^16.0.1",
49
+ "@rollup/plugin-typescript": "^12.1.2",
46
50
  "chalk": "^5.4.1",
47
51
  "chokidar": "^4.0.3",
48
52
  "commander": "^13.1.0",
@@ -57,10 +61,13 @@
57
61
  "loglevel": "^1.9.2",
58
62
  "pluralize": "^8.0.0",
59
63
  "prettier": "^3.5.3",
64
+ "rollup": "^4.40.2",
60
65
  "tar-stream": "^3.1.7",
61
66
  "ts-morph": "^25.0.1",
67
+ "tsdown": "^0.11.5",
68
+ "type-fest": "^4.41.0",
62
69
  "undici": "^7.8.0",
63
- "type-fest": "^4.40.1"
70
+ "vovk-openapi": "*"
64
71
  },
65
72
  "devDependencies": {
66
73
  "@types/concat-stream": "^2.0.3",
@@ -69,7 +76,7 @@
69
76
  "@types/pluralize": "^0.0.33",
70
77
  "@types/tar-stream": "^3.1.3",
71
78
  "concat-stream": "^2.0.0",
72
- "create-next-app": "^15.3.1",
79
+ "create-next-app": "^15.3.2",
73
80
  "node-pty": "^1.0.0"
74
81
  }
75
82
  }
@@ -1,15 +0,0 @@
1
-
2
- <%- `// auto-generated ${new Date().toISOString()}\n/* eslint-disable */` %>
3
- import type { VovkClientFetcher } from 'vovk';
4
- import type { fetcher } from '<%= t.imports.fetcher %>';
5
- import type { createRPC } from '<%= t.imports.createRPC %>';
6
- <% Object.values(t.fullSchema.segments).forEach((segment, i) => { if(Object.keys(segment.controllers).length) { %>
7
- import type { Controllers as Controllers<%= i %> } from "<%= t.segmentMeta[segment.segmentName].segmentImportPath %>";
8
- <% }}) %>
9
- type Options = typeof fetcher extends VovkClientFetcher<infer U> ? U : never;
10
- <% Object.values(t.fullSchema.segments).forEach((segment, i) => {
11
- Object.keys(segment.controllers).forEach((controllerName) => { %>
12
- export const <%= controllerName %>: ReturnType<typeof createRPC<Controllers<%= i %>["<%= controllerName %>"], Options>>;
13
- <% })
14
- }) %>
15
- export { fullSchema } from './fullSchema.cjs';