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
@@ -0,0 +1,168 @@
1
+ export var BuiltInTemplateName;
2
+ (function (BuiltInTemplateName) {
3
+ // ts/js
4
+ BuiltInTemplateName["tsBase"] = "tsBase";
5
+ BuiltInTemplateName["jsBase"] = "jsBase";
6
+ BuiltInTemplateName["ts"] = "ts";
7
+ BuiltInTemplateName["js"] = "js";
8
+ // schema
9
+ BuiltInTemplateName["schemaTs"] = "schemaTs";
10
+ BuiltInTemplateName["schemaJs"] = "schemaJs";
11
+ BuiltInTemplateName["schemaJson"] = "schemaJson";
12
+ // openapi
13
+ BuiltInTemplateName["openapiTs"] = "openapiTs";
14
+ BuiltInTemplateName["openapiJs"] = "openapiJs";
15
+ BuiltInTemplateName["openapiJson"] = "openapiJson";
16
+ // misc
17
+ BuiltInTemplateName["readme"] = "readme";
18
+ BuiltInTemplateName["packageJson"] = "packageJson";
19
+ BuiltInTemplateName["mixins"] = "mixins";
20
+ // other languages (packages installed separately)
21
+ BuiltInTemplateName["rsSrc"] = "rsSrc";
22
+ BuiltInTemplateName["rsPkg"] = "rsPkg";
23
+ BuiltInTemplateName["rsReadme"] = "rsReadme";
24
+ BuiltInTemplateName["rs"] = "rs";
25
+ BuiltInTemplateName["pySrc"] = "pySrc";
26
+ BuiltInTemplateName["pyPkg"] = "pyPkg";
27
+ BuiltInTemplateName["pyReadme"] = "pyReadme";
28
+ BuiltInTemplateName["py"] = "py";
29
+ })(BuiltInTemplateName || (BuiltInTemplateName = {}));
30
+ export function getTemplateDefs(userTemplateDefs = {}) {
31
+ const defs = {};
32
+ const builtInDefs = {
33
+ [BuiltInTemplateName.openapiTs]: {
34
+ templatePath: `vovk-cli/client-templates/${BuiltInTemplateName.openapiTs}/`,
35
+ requires: {
36
+ [BuiltInTemplateName.openapiJson]: './',
37
+ },
38
+ },
39
+ [BuiltInTemplateName.openapiJs]: {
40
+ templatePath: `vovk-cli/client-templates/${BuiltInTemplateName.openapiJs}/`,
41
+ requires: {
42
+ [BuiltInTemplateName.openapiJson]: './',
43
+ },
44
+ },
45
+ [BuiltInTemplateName.openapiJson]: {
46
+ templatePath: `vovk-cli/client-templates/${BuiltInTemplateName.openapiJson}/`,
47
+ },
48
+ [BuiltInTemplateName.tsBase]: {
49
+ templatePath: `vovk-cli/client-templates/${BuiltInTemplateName.tsBase}/`,
50
+ requires: {
51
+ [BuiltInTemplateName.schemaTs]: './',
52
+ [BuiltInTemplateName.mixins]: './', // used conditionally if OpenAPI mixins are used
53
+ },
54
+ },
55
+ [BuiltInTemplateName.jsBase]: {
56
+ templatePath: `vovk-cli/client-templates/${BuiltInTemplateName.jsBase}/`,
57
+ requires: {
58
+ [BuiltInTemplateName.schemaJs]: './',
59
+ [BuiltInTemplateName.mixins]: './', // used conditionally if OpenAPI mixins are used
60
+ },
61
+ },
62
+ [BuiltInTemplateName.ts]: {
63
+ requires: {
64
+ [BuiltInTemplateName.tsBase]: './',
65
+ [BuiltInTemplateName.openapiTs]: './',
66
+ },
67
+ },
68
+ [BuiltInTemplateName.js]: {
69
+ requires: {
70
+ [BuiltInTemplateName.jsBase]: './',
71
+ [BuiltInTemplateName.openapiJs]: './',
72
+ },
73
+ },
74
+ [BuiltInTemplateName.schemaTs]: {
75
+ templatePath: `vovk-cli/client-templates/${BuiltInTemplateName.schemaTs}/`,
76
+ },
77
+ [BuiltInTemplateName.schemaJs]: {
78
+ templatePath: `vovk-cli/client-templates/${BuiltInTemplateName.schemaJs}/`,
79
+ },
80
+ [BuiltInTemplateName.schemaJson]: {
81
+ templatePath: `vovk-cli/client-templates/${BuiltInTemplateName.schemaJson}/`,
82
+ },
83
+ [BuiltInTemplateName.readme]: {
84
+ templatePath: `vovk-cli/client-templates/${BuiltInTemplateName.readme}/`,
85
+ },
86
+ [BuiltInTemplateName.packageJson]: {
87
+ templatePath: `vovk-cli/client-templates/${BuiltInTemplateName.packageJson}/`,
88
+ },
89
+ [BuiltInTemplateName.mixins]: {
90
+ templatePath: `vovk-cli/client-templates/${BuiltInTemplateName.mixins}/`,
91
+ },
92
+ [BuiltInTemplateName.rsSrc]: {
93
+ templatePath: `vovk-rust/client-templates/${BuiltInTemplateName.rsSrc}/`,
94
+ requires: {
95
+ [BuiltInTemplateName.schemaJson]: './',
96
+ },
97
+ },
98
+ [BuiltInTemplateName.rsPkg]: {
99
+ templatePath: `vovk-rust/client-templates/${BuiltInTemplateName.rsPkg}/`,
100
+ },
101
+ [BuiltInTemplateName.rsReadme]: {
102
+ templatePath: `vovk-rust/client-templates/${BuiltInTemplateName.rsReadme}/`,
103
+ },
104
+ [BuiltInTemplateName.rs]: {
105
+ composedClient: {
106
+ outDir: 'dist_rust',
107
+ },
108
+ requires: {
109
+ [BuiltInTemplateName.rsSrc]: './src/',
110
+ [BuiltInTemplateName.rsPkg]: './',
111
+ [BuiltInTemplateName.rsReadme]: './',
112
+ },
113
+ },
114
+ [BuiltInTemplateName.pySrc]: {
115
+ templatePath: `vovk-python/client-templates/${BuiltInTemplateName.pySrc}/`,
116
+ requires: {
117
+ [BuiltInTemplateName.schemaJson]: './',
118
+ },
119
+ },
120
+ [BuiltInTemplateName.pyPkg]: {
121
+ templatePath: `vovk-python/client-templates/${BuiltInTemplateName.pyPkg}/`,
122
+ },
123
+ [BuiltInTemplateName.pyReadme]: {
124
+ templatePath: `vovk-python/client-templates/${BuiltInTemplateName.pyReadme}/`,
125
+ },
126
+ [BuiltInTemplateName.py]: {
127
+ composedClient: {
128
+ outDir: 'dist_python',
129
+ },
130
+ requires: {
131
+ [BuiltInTemplateName.pySrc]: './src/[package_name]/',
132
+ [BuiltInTemplateName.pyPkg]: './',
133
+ [BuiltInTemplateName.pyReadme]: './',
134
+ },
135
+ },
136
+ };
137
+ for (const [name, templateDef] of Object.entries(userTemplateDefs)) {
138
+ if ('extends' in templateDef) {
139
+ if (templateDef.extends) {
140
+ const builtIn = builtInDefs[templateDef.extends];
141
+ if (!builtIn) {
142
+ throw new Error(`Unknown template extends: ${templateDef.extends}`);
143
+ }
144
+ defs[name] = {
145
+ ...builtIn,
146
+ ...templateDef,
147
+ composedClient: {
148
+ ...builtIn.composedClient,
149
+ ...templateDef.composedClient,
150
+ },
151
+ segmentedClient: {
152
+ ...builtIn.segmentedClient,
153
+ ...templateDef.segmentedClient,
154
+ },
155
+ outputConfig: {
156
+ ...builtIn.outputConfig,
157
+ ...templateDef.outputConfig,
158
+ },
159
+ // 'requires' and other props will be overridden
160
+ };
161
+ }
162
+ }
163
+ else {
164
+ defs[name] = templateDef;
165
+ }
166
+ }
167
+ return { ...builtInDefs, ...defs };
168
+ }
@@ -0,0 +1,9 @@
1
+ import type { VovkConfig } from 'vovk';
2
+ export declare function getUserConfig({ configPath: givenConfigPath, cwd, }: {
3
+ configPath?: string;
4
+ cwd: string;
5
+ }): Promise<{
6
+ userConfig: VovkConfig | null;
7
+ configAbsolutePaths: string[];
8
+ error?: Error;
9
+ }>;
@@ -0,0 +1,142 @@
1
+ import { pathToFileURL } from 'node:url';
2
+ import { readFile } from 'node:fs/promises';
3
+ import { createRequire } from 'node:module';
4
+ import { dirname, extname } from 'node:path';
5
+ import vm from 'node:vm';
6
+ import { getConfigAbsolutePaths } from './getConfigAbsolutePaths.mjs';
7
+ const isVMModulesEnabled = typeof vm.SourceTextModule !== 'undefined';
8
+ export async function getUserConfig({ configPath: givenConfigPath, cwd, }) {
9
+ const configAbsolutePaths = await getConfigAbsolutePaths({ configPath: givenConfigPath, cwd });
10
+ if (!configAbsolutePaths.length) {
11
+ return { userConfig: null, configAbsolutePaths };
12
+ }
13
+ const configPath = configAbsolutePaths[0];
14
+ let userConfig;
15
+ let lastError;
16
+ const loaders = await getLoadersForExtension(configPath);
17
+ for (const loader of loaders) {
18
+ try {
19
+ userConfig = await loader();
20
+ return { userConfig, configAbsolutePaths };
21
+ }
22
+ catch (e) {
23
+ lastError = e;
24
+ }
25
+ }
26
+ return { userConfig: null, configAbsolutePaths, error: lastError };
27
+ }
28
+ async function getLoadersForExtension(configPath) {
29
+ const ext = extname(configPath).toLowerCase();
30
+ const code = await readFile(configPath, 'utf-8');
31
+ const hasDynamicImport = /\bimport\s*\(/.test(code);
32
+ // If config has dynamic imports and flag is not enabled, skip VM loaders entirely
33
+ const canUseVM = isVMModulesEnabled || !hasDynamicImport;
34
+ switch (ext) {
35
+ case '.mjs':
36
+ return canUseVM
37
+ ? [() => importWithVMModule(configPath, code), () => importWithCacheBuster(configPath)]
38
+ : [() => importWithCacheBuster(configPath)];
39
+ case '.cjs':
40
+ return canUseVM
41
+ ? [() => importWithVMCommonJS(configPath, code), () => importWithCacheBuster(configPath)]
42
+ : [() => importWithCacheBuster(configPath)];
43
+ default:
44
+ return canUseVM
45
+ ? [
46
+ () => importWithVMCommonJS(configPath, code),
47
+ () => importWithVMModule(configPath, code),
48
+ () => importWithCacheBuster(configPath),
49
+ ]
50
+ : [() => importWithCacheBuster(configPath)];
51
+ }
52
+ }
53
+ function createDynamicImportHandler(context) {
54
+ return async (specifier) => {
55
+ const imported = await import(specifier);
56
+ const exportNames = Object.keys(imported);
57
+ const syntheticModule = new vm.SyntheticModule(exportNames, function () {
58
+ for (const name of exportNames) {
59
+ this.setExport(name, imported[name]);
60
+ }
61
+ }, { context, identifier: specifier });
62
+ await syntheticModule.link(() => {
63
+ throw new Error('Nested linking not supported');
64
+ });
65
+ await syntheticModule.evaluate();
66
+ return syntheticModule;
67
+ };
68
+ }
69
+ async function importWithVMCommonJS(configPath, code) {
70
+ const require = createRequire(configPath);
71
+ const moduleObj = { exports: {} };
72
+ const contextObject = {
73
+ module: moduleObj,
74
+ exports: moduleObj.exports,
75
+ require,
76
+ __filename: configPath,
77
+ __dirname: dirname(configPath),
78
+ console,
79
+ process,
80
+ Buffer,
81
+ URL,
82
+ URLSearchParams,
83
+ setTimeout,
84
+ setInterval,
85
+ setImmediate,
86
+ clearTimeout,
87
+ clearInterval,
88
+ clearImmediate,
89
+ };
90
+ const context = vm.createContext(contextObject);
91
+ const script = new vm.Script(code, {
92
+ filename: configPath,
93
+ importModuleDynamically: createDynamicImportHandler(context),
94
+ });
95
+ script.runInContext(context);
96
+ return moduleObj.exports;
97
+ }
98
+ async function importWithVMModule(configPath, code) {
99
+ if (!isVMModulesEnabled) {
100
+ throw new Error('vm.SourceTextModule not available');
101
+ }
102
+ const configUrl = pathToFileURL(configPath).href;
103
+ const context = vm.createContext({
104
+ console,
105
+ process,
106
+ Buffer,
107
+ URL,
108
+ URLSearchParams,
109
+ setTimeout,
110
+ setInterval,
111
+ setImmediate,
112
+ clearTimeout,
113
+ clearInterval,
114
+ clearImmediate,
115
+ });
116
+ const module = new vm.SourceTextModule(code, {
117
+ context,
118
+ identifier: configUrl,
119
+ initializeImportMeta(meta) {
120
+ meta.url = configUrl;
121
+ },
122
+ importModuleDynamically: createDynamicImportHandler(context),
123
+ });
124
+ await module.link(async (specifier) => {
125
+ const imported = await import(specifier);
126
+ const exportNames = Object.keys(imported);
127
+ const syntheticModule = new vm.SyntheticModule(exportNames, function () {
128
+ for (const name of exportNames) {
129
+ this.setExport(name, imported[name]);
130
+ }
131
+ }, { context, identifier: specifier });
132
+ return syntheticModule;
133
+ });
134
+ await module.evaluate();
135
+ return module.namespace.default;
136
+ }
137
+ async function importWithCacheBuster(configPath) {
138
+ const cacheBuster = Date.now();
139
+ const configPathUrl = pathToFileURL(configPath).href;
140
+ const { default: userConfig } = (await import(`${configPathUrl}?cache=${cacheBuster}`));
141
+ return userConfig;
142
+ }
@@ -0,0 +1,15 @@
1
+ import type { VovkConfig } from 'vovk';
2
+ import { type VovkStrictConfig } from 'vovk/internal';
3
+ import type { LogLevelNames } from 'loglevel';
4
+ import { getLogger } from '../../utils/getLogger.mjs';
5
+ export declare function getConfig({ configPath, cwd, logLevel, }: {
6
+ configPath?: string;
7
+ cwd: string;
8
+ logLevel?: LogLevelNames;
9
+ }): Promise<{
10
+ config: VovkStrictConfig;
11
+ srcRoot: string | null;
12
+ configAbsolutePaths: string[];
13
+ userConfig: VovkConfig | null;
14
+ log: ReturnType<typeof getLogger>;
15
+ }>;
@@ -0,0 +1,92 @@
1
+ import path from 'node:path';
2
+ import { VovkSchemaIdEnum } from 'vovk/internal';
3
+ import { getLogger } from '../../utils/getLogger.mjs';
4
+ import { getUserConfig } from './getUserConfig.mjs';
5
+ import { getRelativeSrcRoot } from './getRelativeSrcRoot.mjs';
6
+ import { getTemplateDefs, BuiltInTemplateName } from './getTemplateDefs.mjs';
7
+ import { normalizeOpenAPIMixin } from '../../utils/normalizeOpenAPIMixin.mjs';
8
+ import { chalkHighlightThing } from '../../utils/chalkHighlightThing.mjs';
9
+ export async function getConfig({ configPath, cwd, logLevel, }) {
10
+ const { configAbsolutePaths, error, userConfig } = await getUserConfig({
11
+ configPath,
12
+ cwd,
13
+ });
14
+ const conf = userConfig ?? {};
15
+ logLevel = logLevel ?? conf.logLevel ?? 'info';
16
+ const log = getLogger(logLevel);
17
+ const env = process.env;
18
+ const clientTemplateDefs = getTemplateDefs(conf.clientTemplateDefs);
19
+ const srcRoot = await getRelativeSrcRoot({ cwd });
20
+ const config = {
21
+ $schema: VovkSchemaIdEnum.CONFIG,
22
+ clientTemplateDefs,
23
+ exposeConfigKeys: [],
24
+ composedClient: {
25
+ ...conf.composedClient,
26
+ enabled: conf.composedClient?.enabled ?? true,
27
+ fromTemplates: conf.composedClient?.fromTemplates ?? [BuiltInTemplateName.js],
28
+ outDir: conf.composedClient?.outDir ?? './node_modules/.vovk-client',
29
+ prettifyClient: conf.composedClient?.prettifyClient ?? false,
30
+ },
31
+ segmentedClient: {
32
+ ...conf.segmentedClient,
33
+ enabled: conf.segmentedClient?.enabled ?? false,
34
+ fromTemplates: conf.segmentedClient?.fromTemplates ?? ['ts'],
35
+ outDir: conf.segmentedClient?.outDir ?? path.join(srcRoot ?? '.', 'client'),
36
+ prettifyClient: conf.segmentedClient?.prettifyClient ?? true,
37
+ },
38
+ bundle: {
39
+ prebundleOutDir: conf.bundle?.prebundleOutDir ?? 'tmp_prebundle',
40
+ keepPrebundleDir: conf.bundle?.keepPrebundleDir ?? false,
41
+ outDir: conf.bundle?.outDir ?? 'dist',
42
+ requires: {
43
+ [BuiltInTemplateName.readme]: '.',
44
+ [BuiltInTemplateName.packageJson]: '.',
45
+ },
46
+ outputConfig: {},
47
+ build: conf.bundle?.build ??
48
+ (() => {
49
+ throw new Error('No bundle.build function specified');
50
+ }),
51
+ ...conf.bundle,
52
+ },
53
+ modulesDir: conf.modulesDir ?? path.join(srcRoot ?? '.', 'modules'),
54
+ schemaOutDir: env.VOVK_SCHEMA_OUT_DIR ?? conf.schemaOutDir ?? './.vovk-schema',
55
+ rootEntry: env.VOVK_ROOT_ENTRY ?? conf.rootEntry ?? 'api',
56
+ rootSegmentModulesDirName: conf.rootSegmentModulesDirName ?? '',
57
+ logLevel,
58
+ devHttps: conf.devHttps ?? false,
59
+ moduleTemplates: {
60
+ service: 'vovk-cli/module-templates/type/service.ts.ejs',
61
+ controller: 'vovk-cli/module-templates/type/controller.ts.ejs',
62
+ ...conf.moduleTemplates,
63
+ },
64
+ libs: conf.libs ?? {},
65
+ outputConfig: {
66
+ ...conf.outputConfig,
67
+ origin: (env.VOVK_ORIGIN ?? conf?.outputConfig?.origin ?? '').replace(/\/$/, ''), // Remove trailing slash
68
+ segments: Object.fromEntries(await Promise.all(Object.entries(conf.outputConfig?.segments ?? {}).map(async ([key, value]) => [
69
+ key,
70
+ {
71
+ ...value,
72
+ openAPIMixin: value.openAPIMixin
73
+ ? await normalizeOpenAPIMixin({ mixinModule: value.openAPIMixin, log, cwd })
74
+ : undefined,
75
+ },
76
+ ]))),
77
+ },
78
+ };
79
+ if (typeof conf.exposeConfigKeys === 'undefined') {
80
+ config.exposeConfigKeys = ['libs', 'rootEntry'];
81
+ }
82
+ else if (conf.exposeConfigKeys === true) {
83
+ config.exposeConfigKeys = Object.keys(config);
84
+ }
85
+ else if (Array.isArray(conf.exposeConfigKeys)) {
86
+ config.exposeConfigKeys = conf.exposeConfigKeys;
87
+ } // else it's false and exposeConfigKeys already is []
88
+ if (!userConfig) {
89
+ log.warn(`Unable to load config at ${chalkHighlightThing(`${cwd}/`)}. Using default values. ${error ?? ''}`);
90
+ }
91
+ return { config, srcRoot, configAbsolutePaths, userConfig, log };
92
+ }
@@ -0,0 +1,4 @@
1
+ import { type VovkStrictConfig, type VovkMetaSchema } from 'vovk/internal';
2
+ export declare function getMetaSchema({ config }: {
3
+ config: VovkStrictConfig;
4
+ }): VovkMetaSchema;
@@ -0,0 +1,12 @@
1
+ import { VovkSchemaIdEnum } from 'vovk/internal';
2
+ import pick from 'lodash/pick.js';
3
+ export function getMetaSchema({ config }) {
4
+ return {
5
+ $schema: VovkSchemaIdEnum.META,
6
+ config: config
7
+ ? pick(config, [...config.exposeConfigKeys, '$schema'])
8
+ : {
9
+ $schema: VovkSchemaIdEnum.CONFIG,
10
+ },
11
+ };
12
+ }
@@ -1,27 +1,23 @@
1
+ import type { LogLevelNames } from 'loglevel';
1
2
  export type ProjectInfo = Awaited<ReturnType<typeof getProjectInfo>>;
2
- export default function getProjectInfo({ port: givenPort, clientOutDir, cwd, }?: {
3
+ export declare function getProjectInfo({ port: givenPort, cwd, configPath, srcRootRequired, logLevel, }?: {
3
4
  port?: number;
4
- clientOutDir?: string;
5
5
  cwd?: string;
6
+ configPath?: string;
7
+ srcRootRequired?: boolean;
8
+ logLevel?: LogLevelNames;
6
9
  }): Promise<{
7
10
  cwd: string;
8
11
  port: string;
9
12
  apiRoot: string;
10
- apiDir: string;
11
- srcRoot: string;
12
- config: import("../types.mjs").VovkStrictConfig;
13
- clientImports: {
14
- schema: string;
15
- fetcher: string;
16
- createRPC: string;
17
- validateOnClient: string | null;
18
- module: {
19
- schema: string;
20
- fetcher: string;
21
- createRPC: string;
22
- validateOnClient: string | null;
23
- };
13
+ apiDirAbsolutePath: string | null;
14
+ srcRoot: string | null;
15
+ vovkCliPackage: {
16
+ version: string;
24
17
  };
18
+ config: import("vovk/internal").VovkStrictConfig;
19
+ packageJson: import("type-fest").PackageJson;
20
+ isNextInstalled: boolean;
25
21
  log: {
26
22
  info: (msg: string) => void;
27
23
  warn: (msg: string) => void;
@@ -1,45 +1,39 @@
1
1
  import path from 'node:path';
2
- import getConfig from './getConfig.mjs';
3
- import getLogger from '../utils/getLogger.mjs';
4
- export default async function getProjectInfo({ port: givenPort, clientOutDir, cwd = process.cwd(), } = {}) {
2
+ import { getConfig } from './getConfig/index.mjs';
3
+ import { getPackageJson } from '../utils/getPackageJson.mjs';
4
+ import { readFile } from 'node:fs/promises';
5
+ export async function getProjectInfo({ port: givenPort, cwd = process.cwd(), configPath, srcRootRequired = true, logLevel, } = {
6
+ logLevel: 'info',
7
+ }) {
5
8
  const port = givenPort?.toString() ?? process.env.PORT ?? '3000';
6
9
  // Make PORT available to the config file at getConfig
7
10
  process.env.PORT = port;
8
- const { config, srcRoot, configAbsolutePaths, userConfig, error } = await getConfig({ clientOutDir, cwd });
9
- const apiRoot = `${config.origin ?? ''}/${config.rootEntry}`;
10
- const apiDir = path.join(srcRoot, 'app', config.rootEntry);
11
- const schemaOutImportPath = path.relative(config.clientOutDir, config.schemaOutDir).replace(/\\/g, '/') + // windows fix
12
- '/main.cjs';
13
- const log = getLogger(config.logLevel);
11
+ const { config, srcRoot, configAbsolutePaths, log } = await getConfig({
12
+ configPath,
13
+ cwd,
14
+ logLevel,
15
+ });
16
+ const packageJson = await getPackageJson(cwd, log);
17
+ const isNextInstalled = !!packageJson?.dependencies?.next || !!packageJson?.devDependencies?.next;
18
+ if (srcRootRequired && !srcRoot) {
19
+ throw new Error(`Could not find app router directory at ${cwd}. Check Next.js docs for more info.`);
20
+ }
21
+ const apiRoot = `${config.outputConfig.origin ?? ''}/${config.rootEntry}`;
22
+ const apiDirAbsolutePath = srcRoot ? path.resolve(cwd, srcRoot, 'app', config.rootEntry) : null;
14
23
  if (configAbsolutePaths.length > 1) {
15
24
  log.warn(`Multiple config files found. Using the first one: ${configAbsolutePaths[0]}`);
16
25
  }
17
- if (!userConfig && configAbsolutePaths.length > 0) {
18
- log.error(`Error reading config file at ${configAbsolutePaths[0]}: ${error?.message ?? 'Unknown Error'}`);
19
- }
20
- const getImportPath = (p) => (p.startsWith('.') ? path.relative(config.clientOutDir, p) : p);
21
- const clientImports = {
22
- schema: schemaOutImportPath,
23
- fetcher: getImportPath(config.fetcherImport[0]),
24
- createRPC: getImportPath(config.createRPCImport[0]),
25
- validateOnClient: config.validateOnClientImport ? getImportPath(config.validateOnClientImport[0]) : null,
26
- module: {
27
- schema: schemaOutImportPath,
28
- fetcher: getImportPath(config.fetcherImport[1] ?? config.fetcherImport[0]),
29
- createRPC: getImportPath(config.createRPCImport[1] ?? config.createRPCImport[0]),
30
- validateOnClient: config.validateOnClientImport
31
- ? getImportPath(config.validateOnClientImport[1] ?? config.validateOnClientImport[0])
32
- : null,
33
- },
34
- };
26
+ const vovkCliPackage = JSON.parse(await readFile(path.join(import.meta.dirname, '../../package.json'), 'utf-8'));
35
27
  return {
36
28
  cwd,
37
29
  port,
38
30
  apiRoot,
39
- apiDir,
31
+ apiDirAbsolutePath,
40
32
  srcRoot,
33
+ vovkCliPackage,
41
34
  config,
42
- clientImports,
35
+ packageJson,
36
+ isNextInstalled,
43
37
  log,
44
38
  };
45
39
  }
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env -S node --experimental-vm-modules --disable-warning=ExperimentalWarning
2
2
  import 'dotenv/config';
3
- import type { VovkConfig, VovkEnv } from './types.mjs';
4
- export type { VovkConfig, VovkEnv };
3
+ import type { VovkEnv } from './types.mjs';
4
+ export type { VovkEnv };