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
package/dist/index.mjs CHANGED
@@ -1,30 +1,32 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env -S node --experimental-vm-modules --disable-warning=ExperimentalWarning
2
2
  import path from 'node:path';
3
3
  import { readFileSync } from 'node:fs';
4
- import { pathToFileURL } from 'node:url';
5
4
  import 'dotenv/config';
6
5
  import { Command } from 'commander';
7
6
  import concurrently from 'concurrently';
8
- import getAvailablePort from './utils/getAvailablePort.mjs';
9
- import getProjectInfo from './getProjectInfo/index.mjs';
10
- import generate from './generate/index.mjs';
11
- import locateSegments from './locateSegments.mjs';
7
+ import { getAvailablePort } from './utils/getAvailablePort.mjs';
8
+ import { getProjectInfo } from './getProjectInfo/index.mjs';
9
+ import { VovkGenerate } from './generate/index.mjs';
10
+ import { bundle } from './bundle/index.mjs';
12
11
  import { VovkDev } from './dev/index.mjs';
13
- import newComponents from './new/index.mjs';
14
- import initProgram from './initProgram.mjs';
12
+ import { newComponents } from './new/index.mjs';
13
+ import { getProjectFullSchema } from './generate/getProjectFullSchema.mjs';
14
+ import { Init } from './init/index.mjs';
15
15
  const program = new Command();
16
- const packageJSON = JSON.parse(readFileSync(path.join(import.meta.dirname, '../package.json'), 'utf-8'));
17
- program.name('vovk').description('Vovk CLI').version(packageJSON.version);
18
- initProgram(program.command('init'));
16
+ const vovkCliPackage = JSON.parse(readFileSync(path.join(import.meta.dirname, '../package.json'), 'utf-8'));
17
+ program.name('vovk').description('Vovk CLI').version(vovkCliPackage.version);
19
18
  program
20
19
  .command('dev')
21
20
  .alias('d')
22
- .description('start schema watcher (optional flag --next-dev to start it with Next.js)')
23
- .argument('[nextArgs...]', 'extra arguments for the dev command')
21
+ .description('Start schema watcher (optional flag --next-dev to start it with Next.js)')
22
+ .argument('[nextArgs...]', 'extra arguments for the implicit next dev command call')
24
23
  .option('--next-dev', 'start schema watcher and Next.js with automatic port allocation')
25
- .option('--exit', 'kill the processe when schema and client is generated')
24
+ .option('--exit', 'kill the processes when schema and client is generated')
25
+ .option('--schema-out <path>', 'path to schema output directory (default: .vovk-schema)')
26
+ .option('--https, --dev-https', 'use HTTPS for the dev server (default: false)')
27
+ .option('--log-level <level>', 'set the log level')
26
28
  .action(async (nextArgs, options) => {
27
- const { nextDev, exit = false } = options;
29
+ const { nextDev, exit = false, schemaOut, devHttps, logLevel } = options;
28
30
  const portAttempts = 30;
29
31
  const PORT = !nextDev
30
32
  ? process.env.PORT
@@ -50,11 +52,15 @@ program
50
52
  env: {
51
53
  PORT,
52
54
  __VOVK_START_WATCHER_IN_STANDALONE_MODE__: 'true',
55
+ // TODO: Pass these as flags
56
+ __VOVK_SCHEMA_OUT_FLAG__: schemaOut ?? '',
57
+ __VOVK_DEV_HTTPS_FLAG__: devHttps ? 'true' : 'false',
53
58
  __VOVK_EXIT__: exit ? 'true' : 'false',
59
+ __VOVK_LOG_LEVEL__: logLevel ?? undefined,
54
60
  },
55
61
  },
56
62
  ], {
57
- killOthers: ['failure', 'success'],
63
+ killOthersOn: ['failure', 'success'],
58
64
  prefix: 'none',
59
65
  successCondition: 'first',
60
66
  });
@@ -66,46 +72,119 @@ program
66
72
  }
67
73
  }
68
74
  else {
69
- void new VovkDev().start({ exit });
75
+ void new VovkDev({ schemaOut, devHttps, logLevel }).start({ exit });
70
76
  }
71
77
  });
72
78
  program
73
79
  .command('generate')
74
80
  .alias('g')
75
81
  .description('Generate RPC client from schema')
76
- .option('--out, --client-out-dir <path>', 'path to output directory')
77
- .option('--template, --templates <templates...>', 'client code templates ("ts", "compiled", "python", "none", a custom path)')
78
- .option('--full-schema [fileName]', 'generate client with full schema')
82
+ .option('--composed-only', 'generate only composed client even if segmented client is enabled')
83
+ .option('--out, --composed-out <path>', 'path to output directory for composed client')
84
+ .option('--from, --composed-from <templates...>', 'client template names for composed client')
85
+ .option('--include, --composed-include-segments <segments...>', 'include segments in composed client')
86
+ .option('--exclude, --composed-exclude-segments <segments...>', 'exclude segments in composed client')
87
+ .option('--segmented-only', 'generate only segmented client even if composed client is enabled')
88
+ .option('--segmented-out <path>', 'path to output directory for segmented client')
89
+ .option('--segmented-from <templates...>', 'client template names for segmented client')
90
+ .option('--segmented-include-segments <segments...>', 'include segments in segmented client')
91
+ .option('--segmented-exclude-segments <segments...>', 'exclude segments in segmented client')
79
92
  .option('--prettify', 'prettify output files')
80
- .action(async (options) => {
81
- const { clientOutDir, templates, prettify, fullSchema } = options;
82
- const projectInfo = await getProjectInfo({ clientOutDir });
83
- const { cwd, config, apiDir } = projectInfo;
84
- const segments = await locateSegments({ dir: apiDir, config });
85
- const schemaOutAbsolutePath = path.join(cwd, config.schemaOutDir);
86
- const schemaImportUrl = pathToFileURL(path.join(schemaOutAbsolutePath, 'main.cjs')).href;
87
- const { default: segmentsSchema } = (await import(schemaImportUrl));
88
- await generate({
93
+ .option('--schema, --schema-path <path>', 'path to schema folder (default: ./.vovk-schema)')
94
+ .option('--config, --config-path <config>', 'path to config file')
95
+ .option('--origin <url>', 'set the origin URL for the generated client')
96
+ .option('--watch [s]', 'watch for changes in schema or openapi spec and regenerate client; accepts a number in seconds to throttle the watcher or make an HTTP request to the OpenAPI spec URLs')
97
+ .option('--openapi, --openapi-spec <openapi_path_or_urls...>', 'use OpenAPI mixins for client generation')
98
+ .option('--openapi-module-name, --openapi-get-module-name <names...>', 'module name strategies corresponding to the index of --openapi option')
99
+ .option('--openapi-method-name, --openapi-get-method-name <names...>', 'method name strategies corresponding to the index of --openapi option')
100
+ .option('--openapi-root-url <urls...>', 'root URLs corresponding to the index of --openapi option')
101
+ .option('--openapi-mixin-name <names...>', 'mixin names corresponding to the index of --openapi option')
102
+ .option('--openapi-fallback <paths...>', 'save OpenAPI spec corresponding to the index of --openapi option to a local file and use it as a fallback if URL is not available')
103
+ .option('--log-level <level>', 'set the log level')
104
+ .action(async (cliGenerateOptions) => {
105
+ const projectInfo = await getProjectInfo({
106
+ configPath: cliGenerateOptions.configPath,
107
+ srcRootRequired: false,
108
+ logLevel: cliGenerateOptions.logLevel,
109
+ });
110
+ await new VovkGenerate({
89
111
  projectInfo,
90
- segments,
91
- segmentsSchema,
92
- templates,
93
- prettify,
94
- fullSchema,
95
112
  forceNothingWrittenLog: true,
113
+ cliGenerateOptions,
114
+ }).start();
115
+ });
116
+ program
117
+ .command('bundle')
118
+ .alias('b')
119
+ .description('Generate TypeScript RPC and bundle it')
120
+ .option('--out, --out-dir <path>', 'path to output directory for bundle')
121
+ .option('--include, --include-segments <segments...>', 'include segments')
122
+ .option('--exclude, --exclude-segments <segments...>', 'exclude segments')
123
+ .option('--prebundle-out-dir, --prebundle-out <path>', 'path to output directory for prebundle')
124
+ .option('--keep-prebundle-dir', 'do not delete prebundle directory after bundling')
125
+ .option('--schema, --schema-path <path>', 'path to schema folder (default: .vovk-schema)')
126
+ .option('--config, --config-path <config>', 'path to config file')
127
+ .option('--origin <url>', 'set the origin URL for the generated client')
128
+ .option('--openapi, --openapi-spec <openapi_path_or_urls...>', 'use OpenAPI mixins for client generation')
129
+ .option('--openapi-module-name, --openapi-get-module-name <names...>', 'module name strategies corresponding to the index of --openapi option')
130
+ .option('--openapi-method-name, --openapi-get-method-name <names...>', 'method name strategies corresponding to the index of --openapi option')
131
+ .option('--openapi-root-url <urls...>', 'root URLs corresponding to the index of --openapi option')
132
+ .option('--openapi-mixin-name <names...>', 'mixin names corresponding to the index of --openapi option')
133
+ .option('--openapi-fallback <paths...>', 'save OpenAPI spec corresponding to the index of --openapi option to a local file and use it as a fallback if URL is not available')
134
+ .option('--log-level <level>', 'set the log level')
135
+ .action(async (cliBundleOptions) => {
136
+ const projectInfo = await getProjectInfo({
137
+ configPath: cliBundleOptions.configPath,
138
+ srcRootRequired: false,
139
+ logLevel: cliBundleOptions.logLevel,
140
+ });
141
+ const { cwd, config, log, isNextInstalled } = projectInfo;
142
+ const fullSchema = await getProjectFullSchema({
143
+ schemaOutAbsolutePath: path.resolve(cwd, cliBundleOptions?.schemaPath ?? config.schemaOutDir),
144
+ log,
145
+ isNextInstalled,
146
+ config,
147
+ });
148
+ await bundle({
149
+ projectInfo,
150
+ fullSchema,
151
+ cliBundleOptions,
96
152
  });
97
153
  });
98
154
  program
99
155
  .command('new [components...]')
100
156
  .alias('n')
101
- .description('create new components. "vovk new [...components] [segmentName/]moduleName" to create a new module or "vovk new segment [segmentName]" to create a new segment')
157
+ .description('Create new components. "vovk new [...components] [segmentName/]moduleName" to create a new module or "vovk new segment [segmentName]" to create a new segment')
102
158
  .option('-o, --overwrite', 'overwrite existing files')
103
- .option('--template, --templates <templates...>', 'override config template; accepts an array of strings that correspond the order of the components')
104
- .option('--dir <dirname>', 'override dirName in template file; relative to the root of the project')
105
- .option('--empty', 'create an empty module')
106
- .option('--no-segment-update', 'do not update segment files when creating a new module')
159
+ .option('--static', '(new segment only) if the segment is static')
160
+ .option('--template, --templates <templates...>', '(new module only) override config template; accepts an array of strings that correspond the order of the components')
161
+ .option('--out, --out-dir <dirname>', '(new module only) override outDir in template file; relative to the root of the project')
162
+ .option('--no-segment-update', '(new module only) do not update segment files when creating a new module')
163
+ .option('--empty', '(new module only) create an empty module')
164
+ .option('--dry-run', 'do not write files to disk')
165
+ .option('--log-level <level>', 'set the log level')
166
+ .action(async (components, newOptions) => newComponents(components, await getProjectInfo({
167
+ logLevel: newOptions.logLevel,
168
+ }), newOptions));
169
+ program
170
+ .command('init')
171
+ .description('Initialize Vovk.ts at existing Next.js project')
172
+ .option('--prefix <prefix>', 'directory to initialize project in')
173
+ .option('-y, --yes', 'skip all prompts and use default values')
174
+ .option('--log-level <level>', 'set log level', 'info')
175
+ .option('--use-npm', 'use npm as package manager')
176
+ .option('--use-yarn', 'use yarn as package manager')
177
+ .option('--use-pnpm', 'use pnpm as package manager')
178
+ .option('--use-bun', 'use bun as package manager')
179
+ .option('--skip-install', 'skip installing dependencies')
180
+ .option('--update-ts-config', 'update tsconfig.json')
181
+ .option('--update-scripts <mode>', 'update package.json scripts ("implicit" or "explicit")')
182
+ .option('--bundle', 'set up "tsdown" bundler')
183
+ .option('--lang <languages...>', 'generate client for other programming languages by default ("py" for Python and "rs" for Rust are supported)')
184
+ .option('--validation-library <library>', 'validation library to use ("zod", "valibot" or "arktype"); set to "none" to skip')
185
+ .option('--channel <channel>', 'channel to use for fetching packages', 'latest')
107
186
  .option('--dry-run', 'do not write files to disk')
108
- .action((components, options) => newComponents(components, options));
187
+ .action((options) => new Init().main(options));
109
188
  program
110
189
  .command('help')
111
190
  .description('Show help message')
@@ -1 +1 @@
1
- export default function checkTSConfigForExperimentalDecorators(root: string): Promise<boolean>;
1
+ export declare function checkTSConfigForExperimentalDecorators(root: string): Promise<boolean>;
@@ -1,14 +1,14 @@
1
1
  import path from 'node:path';
2
2
  import fs from 'node:fs/promises';
3
3
  import * as jsonc from 'jsonc-parser';
4
- export default async function checkTSConfigForExperimentalDecorators(root) {
4
+ export async function checkTSConfigForExperimentalDecorators(root) {
5
5
  const tsconfigPath = path.resolve(root, 'tsconfig.json');
6
6
  let tsconfigContent;
7
7
  try {
8
8
  tsconfigContent = await fs.readFile(tsconfigPath, 'utf8');
9
9
  }
10
10
  catch (error) {
11
- throw new Error(`Failed to read tsconfig.json at ${tsconfigPath}. You can run "npx tsc --init" to create it. ${String(error)}`);
11
+ throw new Error(`Failed to read tsconfig.json at ${tsconfigPath}. You can run "npx tsc --init" to create it. ${String(error)}`, { cause: error });
12
12
  }
13
13
  const tsconfig = jsonc.parse(tsconfigContent);
14
14
  return !!tsconfig?.compilerOptions?.experimentalDecorators;
@@ -1,9 +1,11 @@
1
- import type getLogger from '../utils/getLogger.mjs';
1
+ import type { VovkStrictConfig } from 'vovk/internal';
2
+ import type { getLogger } from '../utils/getLogger.mjs';
2
3
  import type { InitOptions } from '../types.mjs';
3
- export default function createConfig({ root, log, options: { validationLibrary, validateOnClient, reactQuery, channel, dryRun }, }: {
4
+ export declare const BUNDLE_BUILD_TSDOWN: ({ entry, outDir }: Parameters<VovkStrictConfig["bundle"]["build"]>[0]) => Promise<void>;
5
+ export declare function createConfig({ root, options: { validationLibrary, bundle, lang, dryRun }, }: {
4
6
  root: string;
5
7
  log: ReturnType<typeof getLogger>;
6
- options: Pick<InitOptions, 'validationLibrary' | 'validateOnClient' | 'reactQuery' | 'channel' | 'dryRun'>;
8
+ options: Pick<InitOptions, 'validationLibrary' | 'bundle' | 'lang' | 'channel' | 'dryRun'>;
7
9
  }): Promise<{
8
10
  configAbsolutePath: string;
9
11
  }>;
@@ -1,39 +1,89 @@
1
1
  import path from 'node:path';
2
2
  import fs from 'node:fs/promises';
3
- import getTemplateFilesFromPackage from './getTemplateFilesFromPackage.mjs';
4
- import prettify from '../utils/prettify.mjs';
5
- import getFileSystemEntryType, { FileSystemEntryType } from '../utils/getFileSystemEntryType.mjs';
6
- export default async function createConfig({ root, log, options: { validationLibrary, validateOnClient, reactQuery, channel, dryRun }, }) {
3
+ import { prettify } from '../utils/prettify.mjs';
4
+ import { getFileSystemEntryType, FileSystemEntryType } from '../utils/getFileSystemEntryType.mjs';
5
+ import { updateConfigProperty } from '../utils/updateConfigProperty.mjs';
6
+ export const BUNDLE_BUILD_TSDOWN = async ({ entry, outDir }) => {
7
+ const { build } = await import('tsdown');
8
+ await build({
9
+ entry,
10
+ dts: true,
11
+ format: 'esm',
12
+ hash: false,
13
+ fixedExtension: true,
14
+ clean: true,
15
+ outDir,
16
+ platform: 'neutral',
17
+ outExtensions: () => ({ js: '.js', dts: '.d.ts' }),
18
+ outputOptions: {
19
+ inlineDynamicImports: true,
20
+ },
21
+ inputOptions: {
22
+ resolve: {
23
+ mainFields: ['module', 'main'],
24
+ },
25
+ },
26
+ noExternal: ['!next/**'],
27
+ });
28
+ };
29
+ export async function createConfig({ root, options: { validationLibrary, bundle, lang, dryRun }, }) {
7
30
  const config = {};
8
31
  const dotConfigPath = path.join(root, '.config');
9
32
  const dir = (await getFileSystemEntryType(dotConfigPath)) === FileSystemEntryType.DIRECTORY ? dotConfigPath : root;
10
- const isModule = await fs
11
- .readFile(path.join(root, 'package.json'), 'utf-8')
12
- .then((content) => JSON.parse(content).type === 'module');
13
- const configAbsolutePath = path.join(dir, isModule ? 'vovk.config.mjs' : 'vovk.config.js');
14
- const templates = {
15
- controller: 'vovk-cli/templates/controller.ejs',
16
- service: 'vovk-cli/templates/service.ejs',
33
+ const configAbsolutePath = path.join(dir, 'vovk.config.mjs');
34
+ const typeTemplates = {
35
+ controller: 'vovk-cli/module-templates/type/controller.ts.ejs',
36
+ service: 'vovk-cli/module-templates/type/service.ts.ejs',
17
37
  };
18
- if (validationLibrary) {
19
- if (validateOnClient) {
20
- config.validateOnClientImport = `${validationLibrary}/validateOnClient.js`;
21
- }
22
- try {
23
- const validationTemplates = await getTemplateFilesFromPackage(validationLibrary, channel);
24
- Object.assign(templates, validationTemplates);
25
- }
26
- catch (error) {
27
- log.warn(`Failed to fetch validation library templates: ${error.message}`);
28
- }
38
+ const moduleTemplates = {
39
+ ...typeTemplates,
40
+ ...{
41
+ type: typeTemplates,
42
+ zod: {
43
+ controller: 'vovk-cli/module-templates/zod/controller.ts.ejs',
44
+ },
45
+ valibot: {
46
+ controller: 'vovk-cli/module-templates/valibot/controller.ts.ejs',
47
+ },
48
+ arktype: {
49
+ controller: 'vovk-cli/module-templates/arktype/controller.ts.ejs',
50
+ },
51
+ }[validationLibrary ?? 'type'],
52
+ };
53
+ config.outputConfig ??= {};
54
+ config.outputConfig.imports ??= {};
55
+ config.outputConfig.imports.validateOnClient = 'vovk-ajv';
56
+ if (lang?.length) {
57
+ config.composedClient ??= {};
58
+ config.composedClient.fromTemplates = ['js', ...lang];
29
59
  }
30
- if (reactQuery) {
31
- config.createRPCImport = 'vovk-react-query';
60
+ config.moduleTemplates = moduleTemplates;
61
+ if (bundle) {
62
+ config.bundle ??= {};
63
+ config.bundle.outputConfig ??= {
64
+ imports: { validateOnClient: null },
65
+ package: {
66
+ type: 'module',
67
+ main: './index.js',
68
+ types: './index.d.ts',
69
+ exports: {
70
+ '.': {
71
+ default: './index.js',
72
+ types: './index.d.ts',
73
+ },
74
+ },
75
+ },
76
+ };
32
77
  }
33
- config.templates = templates;
34
- const configStr = await prettify(`/** @type {import('vovk-cli').VovkConfig} */
78
+ let configStr = `// @ts-check
79
+ /** @type {import('vovk').VovkConfig} */
35
80
  const config = ${JSON.stringify(config, null, 2)};
36
- ${isModule ? '\nexport default config;' : 'module.exports = config;'}`, configAbsolutePath);
81
+
82
+ export default config;`;
83
+ if (bundle) {
84
+ configStr = await updateConfigProperty(configStr, ['bundle', 'build'], BUNDLE_BUILD_TSDOWN);
85
+ }
86
+ configStr = await prettify(configStr, configAbsolutePath);
37
87
  if (!dryRun)
38
88
  await fs.writeFile(configAbsolutePath, configStr, 'utf-8');
39
89
  return { configAbsolutePath };
@@ -1,8 +1,8 @@
1
+ import { getLogger } from '../utils/getLogger.mjs';
1
2
  import type { InitOptions } from '../types.mjs';
2
- import getLogger from '../utils/getLogger.mjs';
3
3
  export declare class Init {
4
4
  #private;
5
5
  root: string;
6
6
  log: ReturnType<typeof getLogger>;
7
- main(prefix: string, { yes, logLevel, useNpm, useYarn, usePnpm, useBun, skipInstall, updateTsConfig, updateScripts, validationLibrary, validateOnClient, reactQuery, dryRun, channel, }: InitOptions): Promise<void>;
7
+ main({ prefix, yes, logLevel, useNpm, useYarn, usePnpm, useBun, skipInstall, updateTsConfig, updateScripts, validationLibrary, bundle, lang, dryRun, channel, }: InitOptions): Promise<void>;
8
8
  }